/** * @brief * Draws a mesh */ void SRPDebugWireframesFixedFunctions::DrawMesh(Renderer &cRenderer, const VisNode &cVisNode, const MeshHandler &cMeshHandler) const { // Check for draw distance limitation if ((MaxDrawDistance <= 0.0f || cVisNode.GetSquaredDistanceToCamera() <= MaxDrawDistance*MaxDrawDistance) && cMeshHandler.GetVertexBuffer()) { // Get the mesh const Mesh *pMesh = cMeshHandler.GetResource(); if (pMesh) { // Get buffers const MeshLODLevel *pLODLevel = pMesh->GetLODLevel(0); if (pLODLevel && pLODLevel->GetIndexBuffer()) { IndexBuffer *pIndexBuffer = pLODLevel->GetIndexBuffer(); const Array<Geometry> &lstGeometries = *pLODLevel->GetGeometries(); // Bind buffers cRenderer.SetIndexBuffer(pIndexBuffer); FixedFunctions *pFixedFunctions = cRenderer.GetFixedFunctions(); if (pFixedFunctions) pFixedFunctions->SetVertexBuffer(cMeshHandler.GetVertexBuffer()); // Draw geometries for (uint32 nGeo=0; nGeo<lstGeometries.GetNumOfElements(); nGeo++) { // Is this geometry active? const Geometry &cGeometry = lstGeometries[nGeo]; if (cGeometry.IsActive()) { // Draw geometry cRenderer.DrawIndexedPrimitives( cGeometry.GetPrimitiveType(), 0, cMeshHandler.GetVertexBuffer()->GetNumOfElements()-1, cGeometry.GetStartIndex(), cGeometry.GetIndexSize() ); } } } } } }
/** * @brief * Draws the scene */ void SPRTTShaders::DrawScene(Renderer &cRenderer) { // Clear the content of the current used render target by using gray (this way, in case on an graphics error we might still see at least something) cRenderer.Clear(Clear::Color | Clear::ZBuffer, Color4::Gray); // Make our program to the current one if (cRenderer.SetProgram(m_pSceneProgram)) { // Calculate the world matrix Matrix4x4 mWorld; { // Build a rotation matrix by using a given Euler angle around the y-axis mWorld.FromEulerAngleY(static_cast<float>(m_fRotation*Math::DegToRad)); } // Set program uniforms ProgramUniform *pProgramUniform = m_pSceneProgram->GetUniform("ObjectSpaceToClipSpaceMatrix"); if (pProgramUniform) { // Calculate the view matrix Matrix4x4 mView; { mView.SetTranslation(0.0f, -0.1f, -0.5f); } // Calculate the projection matrix Matrix4x4 mProjection; { const float fAspect = 1.0f; const float fAspectRadio = cRenderer.GetViewport().GetWidth()/(cRenderer.GetViewport().GetHeight()*fAspect); mProjection.PerspectiveFov(static_cast<float>(45.0f*Math::DegToRad), fAspectRadio, 0.001f, 1000.0f); } // Calculate the final composed world view projection matrix const Matrix4x4 mWorldViewProjection = mProjection*mView*mWorld; // Set object space to clip space matrix uniform pProgramUniform->Set(mWorldViewProjection); } // Set object space to world space matrix uniform pProgramUniform = m_pSceneProgram->GetUniform("ObjectSpaceToWorldSpaceMatrix"); if (pProgramUniform) pProgramUniform->Set(mWorld); // Set world space light direction pProgramUniform = m_pSceneProgram->GetUniform("LightDirection"); if (pProgramUniform) pProgramUniform->Set(Vector3::UnitZ); // Get the used mesh const Mesh *pMesh = m_pMeshHandler->GetMesh(); if (pMesh) { // Get the mesh LOD level to use const MeshLODLevel *pLODLevel = pMesh->GetLODLevel(0); if (pLODLevel && pLODLevel->GetIndexBuffer()) { // Get and use the index buffer of the mesh LOD level cRenderer.SetIndexBuffer(pLODLevel->GetIndexBuffer()); // Get the vertex buffer of the mesh handler VertexBuffer *pVertexBuffer = m_pMeshHandler->GetVertexBuffer(); if (pVertexBuffer) { // Set program vertex attributes, this creates a connection between "Vertex Buffer Attribute" and "Vertex Shader Attribute" ProgramAttribute *pProgramAttribute = m_pSceneProgram->GetAttribute("VertexPosition"); if (pProgramAttribute) pProgramAttribute->Set(pVertexBuffer, VertexBuffer::Position); pProgramAttribute = m_pSceneProgram->GetAttribute("VertexNormal"); if (pProgramAttribute) pProgramAttribute->Set(pVertexBuffer, VertexBuffer::Normal); // Loop through all geometries of the mesh const Array<Geometry> &lstGeometries = *pLODLevel->GetGeometries(); for (uint32 nGeo=0; nGeo<lstGeometries.GetNumOfElements(); nGeo++) { // Is this geometry active? const Geometry &cGeometry = lstGeometries[nGeo]; if (cGeometry.IsActive()) { // Draw the geometry cRenderer.DrawIndexedPrimitives( cGeometry.GetPrimitiveType(), 0, pVertexBuffer->GetNumOfElements()-1, cGeometry.GetStartIndex(), cGeometry.GetIndexSize() ); } } } } } } }
//[-------------------------------------------------------] //[ Private virtual SRPDirectionalLighting functions ] //[-------------------------------------------------------] void SRPDirectionalLightingShaders::DrawMesh(Renderer &cRenderer, const SQCull &cCullQuery, const VisNode &cVisNode, SceneNode &cSceneNode, const MeshHandler &cMeshHandler, const Mesh &cMesh, const MeshLODLevel &cMeshLODLevel, VertexBuffer &cVertexBuffer) { // Get scene container const VisContainer &cVisContainer = cCullQuery.GetVisContainer(); // Get buffers IndexBuffer *pIndexBuffer = cMeshLODLevel.GetIndexBuffer(); const Array<Geometry> &lstGeometries = *cMeshLODLevel.GetGeometries(); // Bind buffers cRenderer.SetIndexBuffer(pIndexBuffer); // Is lighting enabled for this scene node? const bool bLightingEnabled = !(cSceneNode.GetFlags() & SceneNode::NoLighting) && (m_cLightColor != Color3::Black); // Get available vertex buffer attributes // Binormal and tangent make only sense in this usage when there's also a normal, we need all three vectors! const bool bHasVertexTexCoord0 = (cVertexBuffer.GetVertexAttribute(VertexBuffer::TexCoord, 0) != nullptr); // e.g. for diffuse maps const bool bHasVertexTexCoord1 = (cVertexBuffer.GetVertexAttribute(VertexBuffer::TexCoord, 1) != nullptr); // e.g. for light maps const bool bHasVertexNormal = (cVertexBuffer.GetVertexAttribute(VertexBuffer::Normal) != nullptr); bool bHasVertexTangent = bHasVertexNormal && (cVertexBuffer.GetVertexAttribute(VertexBuffer::Tangent) != nullptr); const bool bHasVertexBinormal = bHasVertexTangent && (cVertexBuffer.GetVertexAttribute(VertexBuffer::Binormal) != nullptr); // For better readability, define whether or not normal mapping is possible with the given vertex data const bool bNormalMappingPossible = bHasVertexBinormal; // We don't need to check for all three vectors in here :D // [TODO] Cleanup uint32 nEnvironmentFlags = 0; if (bHasVertexNormal) nEnvironmentFlags |= SRPDirectionalLightingShadersMaterial::EnvironmentVertexNormal; if (bHasVertexTexCoord0) nEnvironmentFlags |= SRPDirectionalLightingShadersMaterial::EnvironmentVertexTexCoord0; if (bHasVertexTexCoord1) nEnvironmentFlags |= SRPDirectionalLightingShadersMaterial::EnvironmentVertexTexCoord1; if (bNormalMappingPossible) nEnvironmentFlags |= SRPDirectionalLightingShadersMaterial::EnvironmentNormalMappingPossible; if (bLightingEnabled) nEnvironmentFlags |= SRPDirectionalLightingShadersMaterial::EnvironmentLightingEnabled; if (m_bGlowEnabled) nEnvironmentFlags |= SRPDirectionalLightingShadersMaterial::EnvironmentGlowEnabled; if (m_fDOFBlurrinessCutoff) nEnvironmentFlags |= SRPDirectionalLightingShadersMaterial::EnvironmentDOFEnabled; // Draw mesh for (uint32 nMat=0; nMat<cMeshHandler.GetNumOfMaterials(); nMat++) { // Get mesh material Material *pMaterial = cMeshHandler.GetMaterial(nMat); if (pMaterial) { // Draw geometries for (uint32 nGeo=0; nGeo<lstGeometries.GetNumOfElements(); nGeo++) { // Is this geometry active and is it using the current used mesh material? const Geometry &cGeometry = lstGeometries[nGeo]; if (cGeometry.IsActive() && nMat == cGeometry.GetMaterial()) { // Transparent material? static const String sOpacity = "Opacity"; const Parameter *pParameter = pMaterial->GetParameter(sOpacity); if ((GetFlags() & TransparentPass) ? (pParameter && pParameter->GetValue1f() < 1.0f) : (!pParameter || pParameter->GetValue1f() >= 1.0f)) { // SRPDirectionalLightingShaders-material caching SRPDirectionalLightingShadersMaterial *pSRPDirectionalLightingShadersMaterial = m_lstMaterialCache.Get(reinterpret_cast<uint64>(pMaterial)); if (!pSRPDirectionalLightingShadersMaterial) { // The material is not yet cached pSRPDirectionalLightingShadersMaterial = new SRPDirectionalLightingShadersMaterial(*m_pRenderStates, *pMaterial, *m_pProgramGenerator); m_lstMaterialCache.Add(reinterpret_cast<uint64>(pMaterial), pSRPDirectionalLightingShadersMaterial); } // [TODO] Correct texture filter SRPDirectionalLightingShadersMaterial::GeneratedProgramUserData *pGeneratedProgramUserData = pSRPDirectionalLightingShadersMaterial->MakeMaterialCurrent(GetFlags(), nEnvironmentFlags, SRPDirectionalLightingShadersMaterial::Anisotropic2); if (pGeneratedProgramUserData) { // Ambient color if (pGeneratedProgramUserData->pAmbientColor) pGeneratedProgramUserData->pAmbientColor->Set(AmbientColor.Get()); // Set the "ViewSpaceToWorldSpace" fragment shader parameter if (pGeneratedProgramUserData->pViewSpaceToWorldSpace) { // [TODO] Add *SQCullQuery::GetInvViewMatrix()? Matrix3x3 mRot = cCullQuery.GetViewMatrix().GetInverted(); pGeneratedProgramUserData->pViewSpaceToWorldSpace->Set(mRot); } if (bLightingEnabled) { // Set view space light direction and light color if (pGeneratedProgramUserData->pLightDirection) pGeneratedProgramUserData->pLightDirection->Set(m_vLightDirection); if (pGeneratedProgramUserData->pLightColor) pGeneratedProgramUserData->pLightColor->Set(m_cLightColor); } // DOF if (pGeneratedProgramUserData->pDOFParams) pGeneratedProgramUserData->pDOFParams->Set(m_fDOFNearBlurDepth, m_fDOFFocalPlaneDepth, m_fDOFFarBlurDepth, m_fDOFBlurrinessCutoff); // Set object space to clip space matrix uniform if (pGeneratedProgramUserData->pObjectSpaceToClipSpaceMatrix) pGeneratedProgramUserData->pObjectSpaceToClipSpaceMatrix->Set(cVisNode.GetWorldViewProjectionMatrix()); // Set object space to view space matrix uniform if (pGeneratedProgramUserData->pObjectSpaceToViewSpaceMatrix) pGeneratedProgramUserData->pObjectSpaceToViewSpaceMatrix->Set(cVisNode.GetWorldViewMatrix()); // Parallax mapping - set object space eye position if (pGeneratedProgramUserData->pHeightMap && pGeneratedProgramUserData->pEyePos) pGeneratedProgramUserData->pEyePos->Set(cVisNode.GetInverseWorldMatrix()*(cVisContainer.GetWorldMatrix()*cCullQuery.GetCameraPosition())); // Set program vertex attributes, this creates a connection between "Vertex Buffer Attribute" and "Vertex Shader Attribute" if (pGeneratedProgramUserData->pVertexPosition) pGeneratedProgramUserData->pVertexPosition->Set(&cVertexBuffer, PLRenderer::VertexBuffer::Position); if (pGeneratedProgramUserData->pVertexTexCoord0) pGeneratedProgramUserData->pVertexTexCoord0->Set(&cVertexBuffer, PLRenderer::VertexBuffer::TexCoord, 0); if (pGeneratedProgramUserData->pVertexTexCoord1) pGeneratedProgramUserData->pVertexTexCoord1->Set(&cVertexBuffer, PLRenderer::VertexBuffer::TexCoord, 1); if (pGeneratedProgramUserData->pVertexNormal) pGeneratedProgramUserData->pVertexNormal->Set(&cVertexBuffer, PLRenderer::VertexBuffer::Normal); if (pGeneratedProgramUserData->pVertexTangent) pGeneratedProgramUserData->pVertexTangent->Set(&cVertexBuffer, PLRenderer::VertexBuffer::Tangent); if (pGeneratedProgramUserData->pVertexBinormal) pGeneratedProgramUserData->pVertexBinormal->Set(&cVertexBuffer, PLRenderer::VertexBuffer::Binormal); // Two sided lighting? if (pGeneratedProgramUserData->pNormalScale) pGeneratedProgramUserData->pNormalScale->Set(1.0f); // Draw the geometry cRenderer.DrawIndexedPrimitives( cGeometry.GetPrimitiveType(), 0, cVertexBuffer.GetNumOfElements()-1, cGeometry.GetStartIndex(), cGeometry.GetIndexSize() ); // If this is a two sided material, draw the primitives again - but with // flipped culling mode and vertex normals if (pGeneratedProgramUserData->pNormalScale) { // Flip normals pGeneratedProgramUserData->pNormalScale->Set(-1.0f); // Flip the backface culling const uint32 nCullModeBackup = cRenderer.GetRenderState(RenderState::CullMode); cRenderer.SetRenderState(RenderState::CullMode, Cull::CW); // Draw geometry - again cRenderer.DrawIndexedPrimitives( cGeometry.GetPrimitiveType(), 0, cVertexBuffer.GetNumOfElements()-1, cGeometry.GetStartIndex(), cGeometry.GetIndexSize() ); // Restore the previous cull mode cRenderer.SetRenderState(RenderState::CullMode, nCullModeBackup); } } } } } } } }
//[-------------------------------------------------------] //[ Private virtual SRPDirectionalLighting functions ] //[-------------------------------------------------------] void SRPDirectionalLightingFixedFunctions::DrawMesh(Renderer &cRenderer, const SQCull &cCullQuery, const VisNode &cVisNode, SceneNode &cSceneNode, const MeshHandler &cMeshHandler, const Mesh &cMesh, const MeshLODLevel &cMeshLODLevel, VertexBuffer &cVertexBuffer) { // Get the fixed functions interface (when we're in here, we know that it must exist!) FixedFunctions *pFixedFunctions = cRenderer.GetFixedFunctions(); // Set the current world matrix pFixedFunctions->SetTransformState(FixedFunctions::Transform::World, cVisNode.GetWorldMatrix()); // Get buffers IndexBuffer *pIndexBuffer = cMeshLODLevel.GetIndexBuffer(); const Array<Geometry> &lstGeometries = *cMeshLODLevel.GetGeometries(); // Bind buffers cRenderer.SetIndexBuffer(pIndexBuffer); pFixedFunctions->SetVertexBuffer(&cVertexBuffer); // Draw mesh for (uint32 nMat=0; nMat<cMeshHandler.GetNumOfMaterials(); nMat++) { // Get mesh material const Material *pMaterial = cMeshHandler.GetMaterial(nMat); if (pMaterial && !pMaterial->GetEffect()) { // Draw geometries for (uint32 nGeo=0; nGeo<lstGeometries.GetNumOfElements(); nGeo++) { // Is this geometry active and is it using the current used mesh material? const Geometry &cGeometry = lstGeometries[nGeo]; if (cGeometry.IsActive() && nMat == cGeometry.GetMaterial()) { // Transparent material? static const String sOpacity = "Opacity"; const Parameter *pParameter = pMaterial->GetParameter(sOpacity); if ((GetFlags() & TransparentPass) ? (pParameter && pParameter->GetValue1f() < 1.0f) : (!pParameter || pParameter->GetValue1f() >= 1.0f)) { // Material change? if (m_pCurrentMaterial != pMaterial) { // Update current material m_nMaterialChanges++; m_pCurrentMaterial = pMaterial; // Get opacity const float fOpacity = pParameter ? pParameter->GetValue1f() : 1.0f; if (fOpacity < 1) { // Get and set source blend function uint32 nValue = BlendFunc::SrcAlpha; static const String sSrcBlendFunc = "SrcBlendFunc"; pParameter = pMaterial->GetParameter(sSrcBlendFunc); if (pParameter) { m_pRenderStates->SetAttribute("SrcBlendFunc", pParameter->GetParameterString()); nValue = m_pRenderStates->Get(RenderState::SrcBlendFunc); } cRenderer.SetRenderState(RenderState::SrcBlendFunc, nValue); // Get and set destination blend function nValue = BlendFunc::InvSrcAlpha; static const String sDstBlendFunc = "DstBlendFunc"; pParameter = pMaterial->GetParameter(sDstBlendFunc); if (pParameter) { m_pRenderStates->SetAttribute("DstBlendFunc", pParameter->GetParameterString()); nValue = m_pRenderStates->Get(RenderState::DstBlendFunc); } cRenderer.SetRenderState(RenderState::DstBlendFunc, nValue); } // Setup cull mode static const String sTwoSided = "TwoSided"; pParameter = pMaterial->GetParameter(sTwoSided); cRenderer.SetRenderState(RenderState::CullMode, (pParameter && pParameter->GetValue1f()) == 1.0f ? Cull::None : Cull::CCW); // Setup transparency and diffuse color static const String sDiffuseColor = "DiffuseColor"; pParameter = pMaterial->GetParameter(sDiffuseColor); if (pParameter) { float fDiffuseColor[3] = { 1.0f, 1.0f, 1.0f }; pParameter->GetValue3f(fDiffuseColor[0], fDiffuseColor[1], fDiffuseColor[2]); pFixedFunctions->SetColor(Color4(fDiffuseColor[0], fDiffuseColor[1], fDiffuseColor[2], fOpacity)); } else { pFixedFunctions->SetColor(Color4(1.0f, 1.0f, 1.0f, fOpacity)); } // Specular highlight if (GetFlags() & NoSpecular) { pFixedFunctions->SetMaterialState(FixedFunctions::MaterialState::Specular, Color4::Black.ToUInt32()); pFixedFunctions->SetMaterialState(FixedFunctions::MaterialState::Shininess, 0); } else { static const String sSpecularColor = "SpecularColor"; static const String sSpecularExponent = "SpecularExponent"; float fSpecularExponent = 45.0f; Color4 cSpecularColor = Color4::White; // First, get specular color - if it's 0, we don't have any specular at all pParameter = pMaterial->GetParameter(sSpecularColor); if (pParameter) cSpecularColor = pParameter->GetValue3fv(); if (cSpecularColor != 0.0f) { // Get specular exponent pParameter = pMaterial->GetParameter(sSpecularExponent); if (pParameter) pParameter->GetValue1f(fSpecularExponent); } // Set material states pFixedFunctions->SetMaterialState(FixedFunctions::MaterialState::Specular, cSpecularColor.ToUInt32()); pFixedFunctions->SetMaterialState(FixedFunctions::MaterialState::Shininess, Tools::FloatToUInt32(fSpecularExponent)); } // Bind textures // Diffuse map (stage 0) const Texture *pTexture = nullptr; if (GetFlags() & NoDiffuseMap) cRenderer.SetTextureBuffer(0, nullptr); else { pParameter = pMaterial->GetParameter(Material::DiffuseMap); if (pParameter) pTexture = pParameter->GetValueTexture(); if (pTexture && pTexture->GetTextureBuffer()) { pTexture->Bind(0); SetupTextureFiltering(cRenderer, 0); // Enable/disable alpha test - but only if this material is not transparent, else the result may look odd if (pTexture->GetTextureBuffer()->GetComponentsPerPixel() == 4 && fOpacity >= 1) { // Get alpha reference static const String sAlphaReference = "AlphaReference"; pParameter = pMaterial->GetParameter(sAlphaReference); float fAlphaReference = pParameter ? pParameter->GetValue1f() : 0.5f; // Set alpha render states if (fAlphaReference) { pFixedFunctions->SetRenderState(FixedFunctions::RenderState::AlphaTestEnable, true); pFixedFunctions->SetRenderState(FixedFunctions::RenderState::AlphaTestReference, Tools::FloatToUInt32(fAlphaReference)); } else { pFixedFunctions->SetRenderState(FixedFunctions::RenderState::AlphaTestEnable, false); } } else { pFixedFunctions->SetRenderState(FixedFunctions::RenderState::AlphaTestEnable, false); } } else { cRenderer.SetTextureBuffer(0, nullptr); // Disable alpha test pFixedFunctions->SetRenderState(FixedFunctions::RenderState::AlphaTestEnable, false); } } // Light map (stage 1) bool bLightMapUsed = false; if (GetFlags() & NoLightMap) cRenderer.SetTextureBuffer(1, nullptr); else { pTexture = nullptr; pParameter = pMaterial->GetParameter(Material::LightMap); if (pParameter) pTexture = pParameter->GetValueTexture(); if (pTexture) { pTexture->Bind(1); SetupTextureFiltering(cRenderer, 1); bLightMapUsed = true; } else { cRenderer.SetTextureBuffer(1, nullptr); } } // Ambient occlusion map (stage 1) if (!bLightMapUsed) { if (GetFlags() & NoAmbientOcclusionMap) cRenderer.SetTextureBuffer(1, nullptr); else { pTexture = nullptr; pParameter = pMaterial->GetParameter(Material::AmbientOcclusionMap); if (pParameter) pTexture = pParameter->GetValueTexture(); if (pTexture) { pTexture->Bind(1); SetupTextureFiltering(cRenderer, 1); } else { cRenderer.SetTextureBuffer(1, nullptr); } } } // Reflection map (stage 2) if (GetFlags() & NoReflectionMap) cRenderer.SetTextureBuffer(2, nullptr); else { pTexture = nullptr; pParameter = pMaterial->GetParameter(Material::ReflectionMap); if (pParameter) pTexture = pParameter->GetValueTexture(); if (pTexture) { pTexture->Bind(2); SetupTextureFiltering(cRenderer, 2); // 2D or cube ? const TextureBuffer *pTextureBuffer = pTexture->GetTextureBuffer(); if (pTextureBuffer) { if (pTextureBuffer->GetType() == TextureBuffer::TypeTextureBufferCube) { pFixedFunctions->SetTextureStageState(2, FixedFunctions::TextureStage::TexGen, FixedFunctions::TexCoordGen::ReflectionMap); cRenderer.SetSamplerState(2, Sampler::AddressU, TextureAddressing::Clamp); cRenderer.SetSamplerState(2, Sampler::AddressV, TextureAddressing::Clamp); cRenderer.SetSamplerState(2, Sampler::AddressW, TextureAddressing::Clamp); } else if (pTextureBuffer->GetType() == TextureBuffer::TypeTextureBuffer2D) { pFixedFunctions->SetTextureStageState(2, FixedFunctions::TextureStage::TexGen, FixedFunctions::TexCoordGen::SphereMap); cRenderer.SetSamplerState(2, Sampler::AddressU, TextureAddressing::Wrap); cRenderer.SetSamplerState(2, Sampler::AddressV, TextureAddressing::Wrap); cRenderer.SetSamplerState(2, Sampler::AddressW, TextureAddressing::Wrap); } } } else { cRenderer.SetTextureBuffer(2, nullptr); } } } // Draw geometry cRenderer.DrawIndexedPrimitives( cGeometry.GetPrimitiveType(), 0, cVertexBuffer.GetNumOfElements()-1, cGeometry.GetStartIndex(), cGeometry.GetIndexSize() ); } } } } } }