예제 #1
0
        private bool FilterTeapotObjectsFunction(RenderablePrimitiveBase renderablePrimitiveBase)
        {
            var renderablePrimitive = renderablePrimitiveBase as RenderablePrimitive;

            if (renderablePrimitive != null)
            {
                return(renderablePrimitive.OriginalObject == _teapotSceneNode);
            }

            return(false);
        }
예제 #2
0
 private static bool FilterShadowReceivingObjectsFunction(RenderablePrimitiveBase renderablePrimitiveBase)
 {
     return(renderablePrimitiveBase.IsReceivingShadow);
 }
예제 #3
0
        /// <summary>
        /// Applies the material and object's world matrix to this effect.
        /// </summary>
        /// <remarks>
        /// <para>
        /// <b>ApplyMaterial</b> applies the material and object's world matrix to this effect.
        /// </para>
        /// <para>
        /// Usually effects define two constant buffers:<br/>
        /// - one that is can be changed only once per frame and contains data about lights,<br/>
        /// - one that is different for each material and object.
        /// </para>
        /// <para>
        /// The first constant buffer is set by calling <see cref="OnApplyPerFrameSettings(ICamera, IList{ILight}, RenderingContext)"/> method.
        /// </para>
        /// <para>
        /// The second constant buffer can be set by calling <see cref="ApplyMaterial(Material, RenderablePrimitiveBase)"/> method.
        /// This sets properties defined in Material.
        /// It also sets projection matrixes like world_view_projection and others.
        /// The device states (blend state, rasterizer state, etc.) are also set there.
        /// </para>
        /// </remarks>
        /// <param name="material">Material</param>
        /// <param name="renderablePrimitive">object that the material is applied for (usually RenderablePrimitive).</param>
        public override void ApplyMaterial(Material material, RenderablePrimitiveBase renderablePrimitive)
        {
            bool hasAlphaBlend = false;

            _isConstantBufferDirty = false;

            if (_renderingContext == null)
            {
                throw new DXEngineException("ApplyMaterial called without calling ApplyPerFrameSettings. This is usually caused by not registering the effect to EffectsManager.");
            }

            DeviceContext deviceContext = _renderingContext.DeviceContext;

            // Material data:
            var    diffuseMaterial = material as IDiffuseMaterial;
            Color4 newDiffuseColor;

            if (diffuseMaterial != null)
            {
                newDiffuseColor = new Color4(diffuseMaterial.DiffuseColor.Red, diffuseMaterial.DiffuseColor.Green,
                                             diffuseMaterial.DiffuseColor.Blue, diffuseMaterial.Alpha);

                if (diffuseMaterial.HasTransparency)
                {
                    hasAlphaBlend = true;
                }
            }
            else
            {
                newDiffuseColor = Color.Black;
            }

            if (_perObjectConstantsBufferData.DiffuseColor != newDiffuseColor)
            {
                _isConstantBufferDirty = true;
                _perObjectConstantsBufferData.DiffuseColor = newDiffuseColor;
            }

            // Working with matrixes is very slow - especially in .Net because we do not have hi perf SIMD instructions and
            // Here we optimize the code for cases when the world matrix is identity
            if (renderablePrimitive.IsWorldMatrixIdentity)
            {
                if (!_isLastWorldMatrixIdentity)
                {
                    _perObjectConstantsBufferData.World = Matrix.Identity;
                    _perObjectConstantsBufferData.WorldInverseTranspose = Matrix.Identity;

                    _isLastWorldMatrixIdentity = true;
                    _isConstantBufferDirty     = true;
                }
                // else - this object has identity as world matrix and also last object had identity => no need to change anything
            }
            else
            {
                // Normal un-optimized code (world matrix is not identity)

                Matrix world = renderablePrimitive.WorldMatrix;

                if (_perObjectConstantsBufferData.World != world || _isLastWorldMatrixIdentity)
                {
                    _perObjectConstantsBufferData.World = world;

                    Matrix invertedWorldMatrix;
                    Matrix.Invert(ref world, out invertedWorldMatrix);
                    invertedWorldMatrix = Matrix.Transpose(invertedWorldMatrix);

                    _perObjectConstantsBufferData.WorldInverseTranspose = invertedWorldMatrix;

                    _isConstantBufferDirty = true;
                }

                _isLastWorldMatrixIdentity = false;
            }



            if (hasAlphaBlend)
            {
                _contextStatesManager.BlendState = _renderingContext.CommonStates.PremultipliedAlphaBlend;
            }
            else
            {
                _contextStatesManager.BlendState = _renderingContext.CommonStates.Opaque;
            }


            if (_isConstantBufferDirty)
            {
                deviceContext.UpdateSubresource(ref _perObjectConstantsBufferData, _perObjectConstantsBuffer);
            }


            // Set RasterizerState
            // The most important setting in RasterizerState is IsFrontCounterClockwise
            // Here is a place where we have all the info to set it.
            // On one side we can get the orientation of triangles in mesh (object's IsFrontCounterClockwise) and on the other the IBackFaceMaterial.IsBackFaceMaterial
            // Set RasterizerState based on object's IsFrontCounterClockwise (tells orientation of the triangles in the mesh) and IBackFaceMaterial.IsBackFaceMaterial
            bool isFrontCounterClockwise = renderablePrimitive.IsFrontCounterClockwise;

            // If IsBackFaceMaterial than flip the IsFrontCounterClockwise setting from the object
            if (renderablePrimitive.IsBackFaceMaterial)
            {
                isFrontCounterClockwise = !isFrontCounterClockwise;
            }

            var rasterizerState = isFrontCounterClockwise ? parentDXDevice.CommonStates.CullClockwise : parentDXDevice.CommonStates.CullCounterClockwise;

            _contextStatesManager.SetRasterizerState(rasterizerState, isFrontCounterClockwise);


            if (_vertexShader == null || _pixelShader == null || _inputLayout == null)
            {
                throw new Exception("Shaders not initialized.");
            }


            _contextStatesManager.InputLayout    = _inputLayout;
            _contextStatesManager.GeometryShader = null;

            bool isVertexShaderChanged = _contextStatesManager.SetVertexShader(_vertexShader);
            bool isPixelShaderChanged  = _contextStatesManager.SetPixelShader(_pixelShader);

            // Apply constant buffer only if vertex / pixel shader is changed or if constant buffer was changed
            // To see which constant buffers are bound to which slots see the debug file created by fxc:

            // For vertex shader:
            //
            // Resource Bindings:
            //
            // Name                                 Type  Format         Dim      HLSL Bind  Count
            // ------------------------------ ---------- ------- ----------- -------------- ------
            // cbPerFrameCamera                  cbuffer      NA          NA            cb0      1
            // cbPerObject                       cbuffer      NA          NA            cb1      1
            if (isVertexShaderChanged)
            {
                _contextStatesManager.SetVertexShaderConstantBuffer(_perFrameCameraConstantsBuffer, 0, forceOverrideExistingBuffer: false);
            }

            if (isVertexShaderChanged || _isConstantBufferDirty)
            {
                _contextStatesManager.SetVertexShaderConstantBuffer(_perObjectConstantsBuffer, 2);
            }


            // For pixel shader:
            // Resource Bindings:
            //
            // Name                                 Type  Format         Dim      HLSL Bind  Count
            // ------------------------------ ---------- ------- ----------- -------------- ------
            // cbPerFrameCamera                  cbuffer      NA          NA            cb0      1
            // cbPerFrameLights                  cbuffer      NA          NA            cb1      1
            // cbPerObject                       cbuffer      NA          NA            cb2      1
            if (isPixelShaderChanged)
            {
                _contextStatesManager.SetPixelShaderConstantBuffer(_perFrameCameraConstantsBuffer, 0, forceOverrideExistingBuffer: false);
                _contextStatesManager.SetPixelShaderConstantBuffer(_perFrameLightsConstantsBuffer, 1, forceOverrideExistingBuffer: false);
            }

            if (isPixelShaderChanged || _isConstantBufferDirty)
            {
                _contextStatesManager.SetPixelShaderConstantBuffer(_perObjectConstantsBuffer, 2);
            }
        }
        public override void ApplyMaterial(Material material, RenderablePrimitiveBase renderableGeometry)
        {
            if (_renderingContext == null)
            {
                throw new DXEngineException("ApplyMaterial called without calling ApplyPerFrameSettings. This is usually caused by not registering the effect to EffectsManager.");
            }


            _vertexShaderConstantBufferData.DiffuseColor       = this.DiffuseColor;
            _vertexShaderConstantBufferData.SpecularColorPower = new Vector4(this.SpecularColor.Red, this.SpecularColor.Green, this.SpecularColor.Blue, this.SpecularPower);

            if (renderableGeometry.IsWorldMatrixIdentity)
            {
                _vertexShaderConstantBufferData.World = Matrix.Identity;
                _vertexShaderConstantBufferData.WorldInverseTranspose = Matrix.Identity;
                _vertexShaderConstantBufferData.WorldViewProjection   = _frameViewProjection; // Note: we use row_major declaration for matrix in HLSL
            }
            else
            {
                // Note: we use row_major declaration for matrix in HLSL so we do not need to transpose the matrix here
                _vertexShaderConstantBufferData.World = renderableGeometry.WorldMatrix;
                _vertexShaderConstantBufferData.WorldInverseTranspose = renderableGeometry.WorldInverseTransposeMatrix;
                _vertexShaderConstantBufferData.WorldViewProjection   = renderableGeometry.WorldMatrix * _frameViewProjection;
            }

            _renderingContext.DeviceContext.UpdateSubresource(ref _vertexShaderConstantBufferData, _vertexShaderConstantBuffer);


            var statesManager = _renderingContext.ContextStatesManager;


            var renderablePrimitive = renderableGeometry as RenderablePrimitive;

            if (renderablePrimitive != null && (renderablePrimitive.InputLayoutType & (InputLayoutType.Color3 | InputLayoutType.Color4)) != 0)
            {
                // Per point color
                EnsureShaders(_renderingContext.DXDevice, usePerPointColor: true);

                statesManager.InputLayout = _inputLayoutPerPointColorSharedResource.Resource;
                statesManager.SetVertexShader(_vertexShaderPerPointColorSharedResource.Resource);
            }
            else
            {
                EnsureShaders(_renderingContext.DXDevice, usePerPointColor: false);

                statesManager.InputLayout = _inputLayoutSharedResource.Resource;
                statesManager.SetVertexShader(_vertexShaderSharedResource.Resource);
            }

            statesManager.SetVertexShaderConstantBuffer(_vertexShaderConstantBuffer, 2); // Set third slot - see Resource Bindings in PointCloud.vs.txt

            statesManager.SetGeometryShader(_geometryShaderSharedResource.Resource);
            statesManager.SetGeometryShaderConstantBuffer(_geometryShaderConstantBuffer, 0);

            statesManager.SetPixelShader(_pixelShaderSharedResource.Resource);

            // We can use No culling because the rendered quads are always oriented towards the camera
            // Theoretically this should be faster then Culling, because GPU does not need to check the orientation of the triangle, but in practice the perf. is the same.
            statesManager.SetRasterizerState(parentDXDevice.CommonStates.CullNone, statesManager.IsFrontCounterClockwise);

            statesManager.PrimitiveTopology = PrimitiveTopology.PointList;

            if (this.DiffuseColor.Alpha < 1.0f)
            {
                statesManager.BlendState = _dxDevice.CommonStates.NonPremultipliedAlphaBlend;
            }
            else
            {
                statesManager.BlendState = _dxDevice.CommonStates.Opaque;
            }
        }