private bool FilterTeapotObjectsFunction(RenderablePrimitiveBase renderablePrimitiveBase) { var renderablePrimitive = renderablePrimitiveBase as RenderablePrimitive; if (renderablePrimitive != null) { return(renderablePrimitive.OriginalObject == _teapotSceneNode); } return(false); }
private static bool FilterShadowReceivingObjectsFunction(RenderablePrimitiveBase renderablePrimitiveBase) { return(renderablePrimitiveBase.IsReceivingShadow); }
/// <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; } }