public override void GenerateShader(MaterialGeneratorContext context)
        {
            if (NormalMap != null)
            {
                // Inform the context that we are using matNormal (from the MaterialSurfaceNormalMap shader)
                context.UseStreamWithCustomBlend(MaterialShaderStage.Pixel, NormalStream.Stream, new ShaderClassSource("MaterialStreamNormalBlend"));
                context.Parameters.Set(MaterialKeys.HasNormalMap, true);
                context.Parameters.Set(MaterialKeys.SkipTangents, SkipTangents);

                var normalMap = NormalMap;
                // Workaround to make sure that normal map are setup
                var computeTextureColor = normalMap as ComputeTextureColor;
                if (computeTextureColor != null)
                {
                    if (computeTextureColor.FallbackValue.Value == Color.White)
                    {
                        computeTextureColor.FallbackValue.Value = DefaultNormalColor;
                    }
                }
                else
                {
                    var computeColor = normalMap as ComputeColor;
                    if (computeColor != null)
                    {
                        if (computeColor.Value == Color.Black || computeColor.Value == Color.White)
                        {
                            computeColor.Value = DefaultNormalColor;
                        }
                    }
                    else
                    {
                        var computeFloat4 = normalMap as ComputeFloat4;
                        if (computeFloat4 != null)
                        {
                            if (computeFloat4.Value == Vector4.Zero)
                            {
                                computeFloat4.Value = DefaultNormalColor.ToVector4();
                            }
                        }
                    }
                }

                var computeColorSource = NormalMap.GenerateShaderSource(context, new MaterialComputeColorKeys(MaterialKeys.NormalMap, MaterialKeys.NormalValue, DefaultNormalColor, false));
                var mixin = new ShaderMixinSource();
                mixin.Mixins.Add(new ShaderClassSource("MaterialSurfaceNormalMap", IsXYNormal, ScaleAndBias));
                mixin.AddComposition("normalMap", computeColorSource);
                context.AddShaderSource(MaterialShaderStage.Pixel, mixin);
            }
        }
        private void AddClearCoatNormalMap(MaterialGeneratorContext context)
        {
            var computeColorKeys   = new MaterialComputeColorKeys(MaterialKeys.NormalMap, MaterialKeys.NormalValue, MaterialNormalMapFeature.DefaultNormalColor, false);
            var computeColorSource = OrangePeelNormalMap.GenerateShaderSource(context, computeColorKeys);

            // Orange Peel Normal Map
            var mixinNormalMap = new ShaderMixinSource();

            // Inform the context that we are using matNormal (from the MaterialSurfaceNormalMap shader)
            context.UseStreamWithCustomBlend(MaterialShaderStage.Pixel, "matNormal", new ShaderClassSource("MaterialStreamNormalBlend"));
            context.Parameters.Set(MaterialKeys.HasNormalMap, true);

            mixinNormalMap.Mixins.Add(new ShaderClassSource("MaterialSurfaceNormalMap", OrangePeelIsXYNormal, OrangePeelScaleAndBias));

            mixinNormalMap.AddComposition("normalMap", computeColorSource);
            context.AddShaderSource(MaterialShaderStage.Pixel, mixinNormalMap);
        }
        public override void GenerateShader(MaterialGeneratorContext context)
        {
            if (DisplacementMap == null)
            {
                return;
            }

            var materialStage = (MaterialShaderStage)Stage;

            // reset the displacement streams at the beginning of the stage
            context.AddStreamInitializer(materialStage, "MaterialDisplacementStream");

            // set the blending mode of displacement map to additive (and not default linear blending)
            context.UseStreamWithCustomBlend(materialStage, DisplacementStream, new ShaderClassSource("MaterialStreamAdditiveBlend", DisplacementStream));

            // build the displacement computer
            var displacement = DisplacementMap;

            if (ScaleAndBias) // scale and bias should be done by layer
            {
                displacement = new ComputeBinaryScalar(displacement, new ComputeFloat(2f), BinaryOperator.Multiply);
                displacement = new ComputeBinaryScalar(displacement, new ComputeFloat(1f), BinaryOperator.Subtract);
            }
            displacement = new ComputeBinaryScalar(displacement, Intensity, BinaryOperator.Multiply);

            // Workaround to inform compute colors that sampling is occurring from a vertex shader
            context.IsNotPixelStage = materialStage != MaterialShaderStage.Pixel;
            context.SetStream(materialStage, DisplacementStream, displacement, MaterialKeys.DisplacementMap, MaterialKeys.DisplacementValue);
            context.IsNotPixelStage = false;

            var scaleNormal    = materialStage != MaterialShaderStage.Vertex;
            var positionMember = materialStage == MaterialShaderStage.Vertex ? "Position" : "PositionWS";
            var normalMember   = materialStage == MaterialShaderStage.Vertex ? "meshNormal" : "normalWS";

            context.SetStreamFinalModifier <MaterialDisplacementMapFeature>(materialStage, new ShaderClassSource("MaterialSurfaceDisplacement", positionMember, normalMember, scaleNormal));
        }