Esempio n. 1
0
        /// <summary>
        /// Calculate the shader selector value based on the original shader ID, the render batch and general
        /// information from the model.
        /// </summary>
        /// <param name="baseShaderID">The original shader ID. Typically 0.</param>
        /// <param name="renderBatch">The render batch to which the ID belongs.</param>
        /// <param name="model">The model to which the batch belongs.</param>
        /// <returns>A new shader selector value.</returns>
        public static ushort GetRuntimeShaderID(ushort baseShaderID, MDXRenderBatch renderBatch, Warcraft.MDX.MDX model)
        {
            // The shader ID is already "modernized", so there's nothing to do.
            if ((baseShaderID & 0x8000) > 0)
            {
                return(baseShaderID);
            }

            var operationCount = renderBatch.TextureCount;
            var material       = model.Materials ![renderBatch.MaterialIndex];
Esempio n. 2
0
        /// <summary>
        /// Calculate the shader selector value based on the original shader ID, the render batch and general
        /// information from the model.
        /// </summary>
        /// <param name="baseShaderID">The original shader ID. Typically 0.</param>
        /// <param name="renderBatch">The render batch to which the ID belongs.</param>
        /// <param name="model">The model to which the batch belongs.</param>
        /// <returns>A new shader selector value.</returns>
        public static ushort GetRuntimeShaderID(ushort baseShaderID, MDXRenderBatch renderBatch, Warcraft.MDX.MDX model)
        {
            // The shader ID is already "modernized", so there's nothing to do.
            if ((baseShaderID & 0x8000) > 0)
            {
                return(baseShaderID);
            }

            var operationCount = renderBatch.TextureCount;
            var material       = model.Materials[renderBatch.MaterialIndex];

            ushort newShaderID = 0;

            if (!model.GlobalModelFlags.HasFlag(ModelObjectFlags.HasBlendModeOverrides))
            {
                var  textureMapping        = model.TextureMappingLookupTable[renderBatch.TextureMappingLookupTableIndex];
                bool isEnvMapped           = textureMapping == EMDXTextureMappingType.Environment;
                bool nonOpaqueBlendingMode = material.BlendMode != BlendingMode.Opaque;

                if (nonOpaqueBlendingMode)
                {
                    newShaderID = 1;
                    if (isEnvMapped)
                    {
                        newShaderID |= 8;
                    }
                }

                newShaderID *= 16;

                if (textureMapping == EMDXTextureMappingType.T2)
                {
                    newShaderID |= 0x4000;
                }

                return(newShaderID);
            }

            if (operationCount == 0)
            {
                return(baseShaderID);
            }

            var v19 = new short[] { 0, 0 };

            for (int opIndex = 0; opIndex < operationCount; ++opIndex)
            {
                int blendingOverrideIndex = baseShaderID + opIndex;
                var blendingOverride      = model.BlendMapOverrides[blendingOverrideIndex];

                if (opIndex == 0 && material.BlendMode == BlendingMode.Opaque)
                {
                    blendingOverride = BlendingMode.Opaque;
                }

                int textureMappingOverrideIndex            = renderBatch.TextureMappingLookupTableIndex + opIndex;
                EMDXTextureMappingType textureSlotOverride = model.TextureMappingLookupTable[textureMappingOverrideIndex];
                bool isEnvMapped = textureSlotOverride == EMDXTextureMappingType.Environment;

                if (isEnvMapped)
                {
                    v19[opIndex] = (short)((short)blendingOverride | 8);
                }
                else
                {
                    v19[opIndex] = (short)blendingOverride;
                }

                if (textureSlotOverride == EMDXTextureMappingType.Environment && (opIndex + 1) == operationCount)
                {
                    newShaderID |= 0x4000;
                }
            }

            newShaderID |= (ushort)(v19[1] | (v19[0] * 16));

            return(newShaderID);
        }
Esempio n. 3
0
 /// <summary>
 /// Reads an <see cref="MDXRenderBatch"/> from the data stream.
 /// </summary>
 /// <param name="binaryReader">The reader.</param>
 /// <returns>The value.</returns>
 public static MDXRenderBatch ReadMDXRenderBatch(this BinaryReader binaryReader)
 {
     return(new MDXRenderBatch(binaryReader.ReadBytes(MDXRenderBatch.GetSize())));
 }
Esempio n. 4
0
        /// <summary>
        /// Prepares the OpenGL state for rendering the specified batch.
        /// </summary>
        /// <param name="renderBatch">The batch to prepare for rendering.</param>
        /// <exception cref="ArgumentOutOfRangeException">Thrown if the batch has more than four textures.</exception>
        private void PrepareBatchForRender(MDXRenderBatch renderBatch)
        {
            var fragmentShader = MDXShaderHelper.GetFragmentShaderType(renderBatch.TextureCount, renderBatch.ShaderID);
            var vertexShader   = MDXShaderHelper.GetVertexShaderType(renderBatch.TextureCount, renderBatch.ShaderID);
            var batchMaterial  = this.Model.Materials[renderBatch.MaterialIndex];

            this.Shader.SetVertexShaderType(vertexShader);
            this.Shader.SetFragmentShaderType(fragmentShader);
            this.Shader.SetMaterial(batchMaterial);

            var baseColour = Color4.White;

            if (renderBatch.ColorIndex >= 0)
            {
                var colorAnimation = this.Model.ColourAnimations[renderBatch.ColorIndex];

                // TODO: Sample based on animated values
                RGB   rgb;
                float alpha;

                if (colorAnimation.ColourTrack.IsComposite)
                {
                    rgb   = colorAnimation.ColourTrack.CompositeTimelineValues.First();
                    alpha = colorAnimation.OpacityTrack.CompositeTimelineValues.First() / 0x7fff;
                }
                else
                {
                    rgb   = colorAnimation.ColourTrack.Values.First().First();
                    alpha = colorAnimation.OpacityTrack.Values.First().First() / 0x7fff;
                }

                baseColour = new Color4
                             (
                    MathHelper.Clamp(rgb.R, 0.0f, 1.0f),
                    MathHelper.Clamp(rgb.G, 0.0f, 1.0f),
                    MathHelper.Clamp(rgb.B, 0.0f, 1.0f),
                    MathHelper.Clamp(alpha, 0.0f, 1.0f)
                             );
            }

            if ((short)renderBatch.TransparencyLookupTableIndex >= 0)
            {
                var transparencyAnimationIndex = this.Model.TransparencyLookupTable[renderBatch.TransparencyLookupTableIndex];
                var transparencyAnimation      = this.Model.TransparencyAnimations[transparencyAnimationIndex];

                float alphaWeight;
                if (transparencyAnimation.Weight.IsComposite)
                {
                    alphaWeight = transparencyAnimation.Weight.CompositeTimelineValues.First() / 0x7fff;
                }
                else
                {
                    alphaWeight = transparencyAnimation.Weight.Values.First().First() / 0x7fff;
                }

                baseColour.A *= alphaWeight;
            }

            this.Shader.SetBaseInputColour(baseColour);

            var textureIndexes = this.Model.TextureLookupTable.Skip(renderBatch.TextureLookupTableIndex)
                                 .Take(renderBatch.TextureCount);
            var textures = this.Model.Textures.Where((t, i) => textureIndexes.Contains((short)i)).ToList();

            for (int i = 0; i < textures.Count; ++i)
            {
                var    texture = textures[i];
                string textureName;
                switch (texture.TextureType)
                {
                case MDXTextureType.Regular:
                {
                    textureName = texture.Filename;
                    break;
                }

                case MDXTextureType.MonsterSkin1:
                {
                    textureName = GetDisplayInfoTexturePath(this.CurrentDisplayInfo?.TextureVariation1.Value);
                    break;
                }

                case MDXTextureType.MonsterSkin2:
                {
                    textureName = GetDisplayInfoTexturePath(this.CurrentDisplayInfo?.TextureVariation2.Value);
                    break;
                }

                case MDXTextureType.MonsterSkin3:
                {
                    textureName = GetDisplayInfoTexturePath(this.CurrentDisplayInfo?.TextureVariation3.Value);
                    break;
                }

                default:
                {
                    // Use the fallback texture if we don't know how to load the texture type
                    textureName = string.Empty;
                    break;
                }
                }

                var textureObject = this.TextureLookup[textureName];
                switch (i)
                {
                case 0:
                {
                    this.Shader.BindTexture0(textureObject);
                    break;
                }

                case 1:
                {
                    this.Shader.BindTexture1(textureObject);
                    break;
                }

                case 2:
                {
                    this.Shader.BindTexture2(textureObject);
                    break;
                }

                case 3:
                {
                    this.Shader.BindTexture3(textureObject);
                    break;
                }

                default:
                {
                    throw new ArgumentOutOfRangeException();
                }
                }
            }
        }
Esempio n. 5
0
        /// <summary>
        /// Prepares the OpenGL state for rendering the specified batch.
        /// </summary>
        /// <param name="renderBatch">The batch to prepare for rendering.</param>
        /// <exception cref="ArgumentOutOfRangeException">Thrown if the batch has more than four textures.</exception>
        private void PrepareBatchForRender(MDXRenderBatch renderBatch)
        {
            var fragmentShader = MDXShaderHelper.GetFragmentShaderType(renderBatch.TextureCount, renderBatch.ShaderID);
            var vertexShader   = MDXShaderHelper.GetVertexShaderType(renderBatch.TextureCount, renderBatch.ShaderID);
            var batchMaterial  = this.Model.Materials[renderBatch.MaterialIndex];

            this.Shader.SetVertexShaderType(vertexShader);
            this.Shader.SetFragmentShaderType(fragmentShader);
            this.Shader.SetMaterial(batchMaterial);

            var textureIndexes = this.Model.TextureLookupTable.Skip(renderBatch.TextureLookupTableIndex)
                                 .Take(renderBatch.TextureCount);
            var textures = this.Model.Textures.Where((t, i) => textureIndexes.Contains((short)i)).ToList();

            for (int i = 0; i < textures.Count; ++i)
            {
                var    texture = textures[i];
                string textureName;
                switch (texture.TextureType)
                {
                case EMDXTextureType.Regular:
                {
                    textureName = texture.Filename;
                    break;
                }

                case EMDXTextureType.MonsterSkin1:
                {
                    textureName = GetDisplayInfoTexturePath(this.CurrentDisplayInfo?.TextureVariation1.Value);
                    break;
                }

                case EMDXTextureType.MonsterSkin2:
                {
                    textureName = GetDisplayInfoTexturePath(this.CurrentDisplayInfo?.TextureVariation2.Value);
                    break;
                }

                case EMDXTextureType.MonsterSkin3:
                {
                    textureName = GetDisplayInfoTexturePath(this.CurrentDisplayInfo?.TextureVariation3.Value);
                    break;
                }

                default:
                {
                    // Use the fallback texture if we don't know how to load the texture type
                    textureName = string.Empty;
                    break;
                }
                }

                var textureObject = this.TextureLookup[textureName];
                switch (i)
                {
                case 0:
                {
                    this.Shader.BindTexture0(textureObject);
                    break;
                }

                case 1:
                {
                    this.Shader.BindTexture1(textureObject);
                    break;
                }

                case 2:
                {
                    this.Shader.BindTexture2(textureObject);
                    break;
                }

                case 3:
                {
                    this.Shader.BindTexture3(textureObject);
                    break;
                }

                default:
                {
                    throw new ArgumentOutOfRangeException();
                }
                }
            }
        }