Esempio n. 1
0
        public void TestMacrosArray()
        {
            // test that macros are correctly used through an array
            var baseMixin = new ShaderMixinSource();

            baseMixin.AddMacro("SILICONSTUDIO_XENKO_GRAPHICS_API_DIRECT3D", 1);
            baseMixin.Macros.Add(new ShaderMacro("MACRO_TEST", "int"));
            baseMixin.Mixins.Add(new ShaderClassSource("TestMacrosArray"));

            var compositionArray = new ShaderArraySource();

            var macros0 = new ShaderMixinSource();

            macros0.Mixins.Add(new ShaderClassSource("MacroTest"));
            compositionArray.Add(macros0);

            var macros1 = new ShaderMixinSource();

            macros1.Mixins.Add(new ShaderClassSource("MacroTest"));
            macros1.Macros.Add(new ShaderMacro("MACRO_TEST", "float"));
            compositionArray.Add(macros1);

            var macros2 = new ShaderMixinSource();

            macros2.Mixins.Add(new ShaderClassSource("MacroTest"));
            macros2.Macros.Add(new ShaderMacro("MACRO_TEST", "float4"));
            compositionArray.Add(macros2);

            baseMixin.Compositions.Add("macrosArray", compositionArray);

            var parsingResult = shaderMixinParser.Parse(baseMixin, baseMixin.Macros.ToArray());

            Assert.IsFalse(parsingResult.HasErrors);
            var cBufferVar = parsingResult.Shader.Declarations.OfType <ConstantBuffer>().First(x => x.Name == "Globals").Members.OfType <Variable>().ToList();

            Assert.AreEqual(1, cBufferVar.Count(x => x.Type.Name.Text == "int"));
            Assert.AreEqual(1, cBufferVar.Count(x => x.Type.Name.Text == "float"));
            Assert.AreEqual(1, cBufferVar.Count(x => x.Type.Name.Text == "float4"));
        }
Esempio n. 2
0
        public void TestMacrosArray()
        {
            // test that macros are correctly used through an array
            var baseMixin = new ShaderMixinSource();
            baseMixin.AddMacro("SILICONSTUDIO_XENKO_GRAPHICS_API_DIRECT3D", 1);
            baseMixin.Macros.Add(new ShaderMacro("MACRO_TEST", "int"));
            baseMixin.Mixins.Add(new ShaderClassSource("TestMacrosArray"));

            var compositionArray = new ShaderArraySource();

            var macros0 = new ShaderMixinSource();
            macros0.Mixins.Add(new ShaderClassSource("MacroTest"));
            compositionArray.Add(macros0);

            var macros1 = new ShaderMixinSource();
            macros1.Mixins.Add(new ShaderClassSource("MacroTest"));
            macros1.Macros.Add(new ShaderMacro("MACRO_TEST", "float"));
            compositionArray.Add(macros1);

            var macros2 = new ShaderMixinSource();
            macros2.Mixins.Add(new ShaderClassSource("MacroTest"));
            macros2.Macros.Add(new ShaderMacro("MACRO_TEST", "float4"));
            compositionArray.Add(macros2);
            
            baseMixin.Compositions.Add("macrosArray", compositionArray);

            var parsingResult = shaderMixinParser.Parse(baseMixin, baseMixin.Macros.ToArray());

            Assert.IsFalse(parsingResult.HasErrors);
            var cBufferVar = parsingResult.Shader.Declarations.OfType<ConstantBuffer>().First(x => x.Name == "Globals").Members.OfType<Variable>().ToList();
            Assert.AreEqual(1, cBufferVar.Count(x => x.Type.Name.Text == "int"));
            Assert.AreEqual(1, cBufferVar.Count(x => x.Type.Name.Text == "float"));
            Assert.AreEqual(1, cBufferVar.Count(x => x.Type.Name.Text == "float4"));
        }
        public void SetupShadersPermutationReceiver(EffectShaderPass effectPass, object permutationKey)
        {
            var currentShadowMapsPermutation = (ShadowMapPermutationArray)permutationKey;

            if (currentShadowMapsPermutation.ShadowMaps.Count == 0)
            {
                return;
            }

            var shadowsArray = new ShaderArraySource();

            effectPass.Shader.Mixins.Add("ShadowMapReceiver");
            effectPass.Shader.Compositions.Add("shadows", shadowsArray);

            // Group by shadow map types (one group can be processed in the same loop).
            // Currently based on filtering type and number of cascades (but some more parameters might affect this later as new type of shadow maps are introduced).
            var shadowMapTypes = currentShadowMapsPermutation.ShadowMaps.GroupBy(x => Tuple.Create(x.ShadowMap.Filter.GetType(), x.ShadowMap.LevelCount, x.ShadowMap.Texture));

            int shadowMapTypeIndex = 0;

            foreach (var shadowMapType in shadowMapTypes)
            {
                var shadowMapTypeCopy = shadowMapType.ToArray();
                var shadowMixin       = new ShaderMixinSource();

                // Currently use shadow map count, but we should probably use next power of two to limit number of permutations.
                var maxShadowMapCount = shadowMapTypeCopy.Length;

                // Setup shadow mapping
                shadowMixin.Mixins.Add(new ShaderClassSource("ShadowMapCascadeBase", shadowMapType.Key.Item2, 0, maxShadowMapCount, 1));
                //shadowMixin.Mixins.Add(new ShaderClassSource("LightDirectionalShading", shadowMapPermutation.Index));

                // Setup the filter
                // TODO: Use static based on type of filter? (should use Key instead of First()).
                shadowMixin.Mixins.Add(shadowMapType.First().ShadowMap.Filter.GenerateShaderSource(maxShadowMapCount));

                shadowsArray.Add(shadowMixin);

                // Register keys for this shadow map type
                var shadowSubKey = string.Format(".shadows[{0}]", shadowMapTypeIndex++);

                effectPass.Parameters.Set(ShadowMapKeys.Texture.AppendKey(shadowSubKey), shadowMapType.Key.Item3);

                effectPass.Parameters.Set(LightingPlugin.ShadowMapLightCount.AppendKey(shadowSubKey), shadowMapTypeCopy.Length);

                effectPass.Parameters.AddDynamic(LightingPlugin.ReceiverInfo.AppendKey(shadowSubKey), ParameterDynamicValue.New(ShadowMapPermutationArray.Key, TransformationKeys.World, TransformationKeys.ViewProjection, (ref ShadowMapPermutationArray shadowMapPermutations, ref Matrix world, ref Matrix viewProj, ref ShadowMapReceiverInfo[] output) =>
                {
                    unsafe
                    {
                        for (int i = 0; i < shadowMapTypeCopy.Length; ++i)
                        {
                            var permutationParameters = shadowMapTypeCopy[i].ShadowMap.Parameters;

                            // TODO: Optimize dictionary access this using SetKeyMapping
                            var shadowMapData  = permutationParameters.Get(LightingPlugin.ViewProjectionArray);
                            var textureCoords  = permutationParameters.Get(LightingPlugin.CascadeTextureCoordsBorder);
                            var distanceMax    = permutationParameters.Get(ShadowMapKeys.DistanceMax);
                            var lightDirection = permutationParameters.Get(LightKeys.LightDirection);

                            Matrix *vpPtr         = &shadowMapData.ViewProjReceiver0;
                            fixed(Matrix * wvpPtr = &output[i].WorldViewProjReceiver0)
                            {
                                for (int j = 0; j < 4; ++j)
                                {
                                    Matrix.Multiply(ref world, ref vpPtr[j], ref wvpPtr[j]);
                                }
                            }

                            output[i].Offset0 = shadowMapData.Offset0;
                            output[i].Offset1 = shadowMapData.Offset1;
                            output[i].Offset2 = shadowMapData.Offset2;
                            output[i].Offset3 = shadowMapData.Offset3;

                            fixed(Vector4 * targetPtr = &output[i].CascadeTextureCoordsBorder0)
                            fixed(Vector4 * sourcePtr = &textureCoords[0])
                            {
                                for (int j = 0; j < 4; ++j)
                                {
                                    targetPtr[j] = sourcePtr[j];
                                }
                            }

                            output[i].ShadowLightDirection = lightDirection;
                            LightKeys.LightDirectionVSUpdate(ref output[i].ShadowLightDirection, ref viewProj, ref output[i].ShadowLightDirectionVS);
                            output[i].ShadowMapDistance = distanceMax;
                            output[i].ShadowLightColor  = shadowMapData.LightColor;
                        }
                    }
                }, autoCheckDependencies: false));     // Always update (permutation won't get updated, only its content)!

                // Register VSM filter if necessary
                if (shadowMapType.Key.Item1 == typeof(ShadowMapFilterVsm))
                {
                    effectPass.Parameters.AddDynamic(LightingPlugin.ReceiverVsmInfo.AppendKey(shadowSubKey), ParameterDynamicValue.New(ShadowMapPermutationArray.Key, (ref ShadowMapPermutationArray shadowMapPermutations, ref ShadowMapReceiverVsmInfo[] output) =>
                    {
                        for (int i = 0; i < shadowMapTypeCopy.Length; ++i)
                        {
                            var permutationParameters = shadowMapTypeCopy[i].ShadowMap.Parameters;
                            output[i].BleedingFactor  = permutationParameters.Get(ShadowMapFilterVsm.VsmBleedingFactor);
                            output[i].MinVariance     = permutationParameters.Get(ShadowMapFilterVsm.VsmMinVariance);
                        }
                    }, autoCheckDependencies: false));
                }
            }
        }