//[-------------------------------------------------------] //[ 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); } } } } } } } }
/** * @brief * Recursive part of PerformQuery() */ bool SQPlaneSet::PerformQueryRec(SceneHierarchyNode &cHierarchyNode) { // Is this scene hierarchy node intersecting the plane set? if (!cHierarchyNode.CheckPlaneSet(m_cPlaneSet)) return true; // Continue the query // Touch this node cHierarchyNode.Touch(); // Get the scene context SceneContext *pSceneContext = GetSceneContext(); if (pSceneContext) { // Inform all listeners const SceneHierarchyNodeItem *pItem = cHierarchyNode.GetFirstItem(); while (pItem) { // Get the linked scene node SceneNode *pSceneNode = pItem->GetSceneNode(); // Was this scene node already processed? if (pSceneNode && !pSceneContext->IsNodeTouched(*pSceneNode)) { // Check scene node const AABoundingBox &cAABB = pSceneNode->GetContainerAABoundingBox(); if (Intersect::PlaneSetAABox(m_cPlaneSet, cAABB.vMin, cAABB.vMax)) { // Touch this node pSceneContext->TouchNode(*pSceneNode); // Emit signal SignalSceneNode(*this, *pSceneNode); if (m_nFlags & StopQuery) return false; // Stop the query right now // Continue recursive? if (m_nFlags & Recursive) { // Is this a container and is recursion allowed? if (pSceneNode->IsContainer() && !(pSceneNode->GetFlags() & SceneContainer::NoRecursion)) { // Backup current plane set const PlaneSet cPlaneSet = m_cPlaneSet; // Transform the plane set into container space m_cPlaneSet *= pSceneNode->GetTransform().GetInverseMatrix(); // Container recursion const bool bContinue = PerformQueryRec(static_cast<SceneContainer*>(pSceneNode)->GetHierarchyInstance()->GetRootNode()); // Restore plane set m_cPlaneSet = cPlaneSet; // Stop the query right now? if (!bContinue) return false; // Is this a cell-portal? } else if (pSceneNode->IsPortal() && pSceneNode->IsInstanceOf("PLScene::SNCellPortal") && !(pSceneNode->GetFlags() & SNCellPortal::NoPassThrough)) { // Get the target cell SNCellPortal &cCellPortal = static_cast<SNCellPortal&>(*pSceneNode); SceneContainer *pCell = reinterpret_cast<SceneContainer*>(cCellPortal.GetTargetCellInstance()); if (pCell && pCell != pSceneNode->GetContainer()) { // Backup current plane set const PlaneSet cPlaneSet = m_cPlaneSet; // Transform the plane set into container space m_cPlaneSet *= cCellPortal.GetWarpMatrix(); // Container recursion const bool bContinue = PerformQueryRec(pCell->GetHierarchyInstance()->GetRootNode()); // Restore plane set m_cPlaneSet = cPlaneSet; // Stop the query right now? if (!bContinue) return false; } } } } } // Next item, please pItem = pItem->GetNextItem(); } } // Check all sub-hierarchies for (uint32 i=0; i<cHierarchyNode.GetNumOfNodes(); i++) { if (!PerformQueryRec(*cHierarchyNode.GetNode(i))) return false; // Stop the query right now } // Done, continue the query return true; }