void CSimpleSceneObject::Draw(CRenderPass * RenderPass) { SharedPointer<Graphics::IPipelineState> PipelineState; if (TryMapAccess(PipelineStates, RenderPass, PipelineState)) { RenderPass->SubmitPipelineStateForRendering(PipelineState, this, InstanceCount, RenderCategory); } }
void CSimpleSceneObject::Load(CRenderPass * RenderPass) { if (! IndexBuffer || ! VertexBuffers.size() || ! Shader) { return; } SharedPointer<Graphics::IPipelineState> PipelineState; if (! TryMapAccess(PipelineStates, RenderPass, PipelineState)) { PipelineStates[RenderPass] = PipelineState = RenderPass->GetGraphicsContext()->CreatePipelineState(); } PipelineState->SetIndexBuffer(IndexBuffer); for (uint i = 0; i < VertexBuffers.size(); ++ i) { PipelineState->SetVertexBuffer(i, VertexBuffers[i]); } Material.LoadTextures(); PipelineState->SetShader(Shader); std::for_each(Textures.begin(), Textures.end(), [this, PipelineState](pair<string, SharedPointer<Graphics::ITexture>> const & Iterator) { PipelineState->SetTexture(Iterator.first, Iterator.second); }); std::for_each(Uniforms.begin(), Uniforms.end(), [this, PipelineState](pair<string, SharedPointer<Graphics::IUniform>> const & Iterator) { PipelineState->SetUniform(Iterator.first, Iterator.second); }); Material.LoadTextures(); PipelineState->OfferUniform("uMaterial.AmbientColor", Material.Ambient); PipelineState->OfferUniform("uMaterial.DiffuseColor", Material.Diffuse); PipelineState->OfferUniform("uMaterial.SpecularColor", Material.Specular); PipelineState->OfferUniform("uMaterial.Shininess", Material.Shininess); if (Material.DiffuseTexture) { PipelineState->OfferTexture("uMaterial.DiffuseTexture", Material.DiffuseTexture); } for (auto Pair : DrawFeatures) { PipelineState->SetFeatureEnabled(Pair.first, Pair.second); } PipelineState->SetPolygonOffsetAmount(PolygonOffsetAmount); PipelineState->SetBlendMode(BlendMode); PipelineState->SetPrimitiveType(PrimitiveType); RenderPass->PreparePipelineStateForRendering(PipelineState, this); Loaded[RenderPass] = true; }
void CPipelineState::Load() { if (! ShaderProgram || VertexBuffers.empty() || ! IndexBuffer) { Log::Error("Attempting to load an invalid PipelineState"); return; } Window->MakeContextCurrent(); CheckedGLCall(glUseProgram(ShaderProgram->Handle)); CheckedGLCall(glBindVertexArray(VertexArrayHandle)); for (auto & VertexBuffer : VertexBuffers) { CheckedGLCall(glBindBuffer(GL_ARRAY_BUFFER, VertexBuffer->Handle)); ////////////////////////////// // Set up VBOs (attributes) // ////////////////////////////// // Calculate stride of VBO data size_t TotalStride = 0; for (auto & InputLayoutElement : VertexBuffer->InputLayout) { TotalStride += GetAttributeTypeSize(InputLayoutElement.Type) * InputLayoutElement.Components; } size_t CurrentOffset = 0; for (auto & InputLayoutElement : VertexBuffer->InputLayout) { pair<uint, uint> AttributeInfo; if (TryMapAccess(ShaderProgram->Attributes, InputLayoutElement.Name, AttributeInfo)) { uint const AttributeLocation = AttributeInfo.first; uint const AttributeType = AttributeInfo.second; // Validate Attribute Type (does the VBO layout match what the shader wants?) { bool IsAttributeTypeCorrect = false; string ShaderAttributeTypeString = "Unknown"; switch (AttributeType) { default: Log::Error("Unexpected type for attribute %s: %u", InputLayoutElement.Name, AttributeType); break; case GL_FLOAT: IsAttributeTypeCorrect = (InputLayoutElement.Type == EAttributeType::Float && InputLayoutElement.Components == 1); ShaderAttributeTypeString = "GL_FLOAT"; break; case GL_FLOAT_VEC2: IsAttributeTypeCorrect = (InputLayoutElement.Type == EAttributeType::Float && InputLayoutElement.Components == 2); ShaderAttributeTypeString = "GL_FLOAT_VEC2"; break; case GL_FLOAT_VEC3: IsAttributeTypeCorrect = (InputLayoutElement.Type == EAttributeType::Float && InputLayoutElement.Components == 3); ShaderAttributeTypeString = "GL_FLOAT_VEC3"; break; case GL_FLOAT_VEC4: IsAttributeTypeCorrect = (InputLayoutElement.Type == EAttributeType::Float && InputLayoutElement.Components == 4); ShaderAttributeTypeString = "GL_FLOAT_VEC4"; break; case GL_INT: IsAttributeTypeCorrect = (InputLayoutElement.Type == EAttributeType::Int && InputLayoutElement.Components == 1); ShaderAttributeTypeString = "GL_INT"; break; case GL_INT_VEC2: IsAttributeTypeCorrect = (InputLayoutElement.Type == EAttributeType::Int && InputLayoutElement.Components == 2); ShaderAttributeTypeString = "GL_INT_VEC2"; break; case GL_INT_VEC3: IsAttributeTypeCorrect = (InputLayoutElement.Type == EAttributeType::Int && InputLayoutElement.Components == 3); ShaderAttributeTypeString = "GL_INT_VEC3"; break; case GL_INT_VEC4: IsAttributeTypeCorrect = (InputLayoutElement.Type == EAttributeType::Int && InputLayoutElement.Components == 4); ShaderAttributeTypeString = "GL_INT_VEC4"; break; } if (! IsAttributeTypeCorrect) { Log::Error("Mistmatch for attribute type '%s': VBO supplied %d components of type %s but shader expected '%s'", InputLayoutElement.Name, InputLayoutElement.Components, GetAttributeTypeString(InputLayoutElement.Type), ShaderAttributeTypeString); } } CheckedGLCall(glEnableVertexAttribArray(AttributeLocation)); switch (AttributeType) { case GL_FLOAT: case GL_FLOAT_VEC2: case GL_FLOAT_VEC3: case GL_FLOAT_VEC4: CheckedGLCall(glVertexAttribPointer( AttributeLocation, InputLayoutElement.Components, GetAttributeTypeOpenGLEnum(InputLayoutElement.Type), GL_FALSE, (int) TotalStride, (void *) CurrentOffset)); break; case GL_INT: case GL_INT_VEC2: case GL_INT_VEC3: case GL_INT_VEC4: CheckedGLCall(glVertexAttribIPointer( AttributeLocation, InputLayoutElement.Components, GetAttributeTypeOpenGLEnum(InputLayoutElement.Type), (int) TotalStride, (void *) CurrentOffset)); break; } if (VertexBuffer->Instancing) { CheckedGLCall(glVertexAttribDivisor(AttributeLocation, 1)); } UnboundAttributes.erase(InputLayoutElement.Name); } CurrentOffset += GetAttributeTypeSize(InputLayoutElement.Type) * InputLayoutElement.Components; } CheckedGLCall(glBindBuffer(GL_ARRAY_BUFFER, 0)); // Remember, VBOs are not part of VAO state (that's why we never leave them set in the VAO) } std::for_each(UnboundAttributes.begin(), UnboundAttributes.end(), [](string const & Attribuite) { Log::Error("Attribute expected by shader but not provided by VBO: %s", Attribuite); }); CheckedGLCall(glBindVertexArray(0)); CheckedGLCall(glUseProgram(0)); ///////////////////// // Set up Uniforms // ///////////////////// BoundUniforms.clear(); for (auto const & it : Uniforms) { uint Handle = 0; if (TryMapAccess(ShaderProgram->Uniforms, it.first, Handle)) { BoundUniforms[Handle] = it.second; } } for (auto const & it : Textures) { uint Handle = 0; if (TryMapAccess(ShaderProgram->Uniforms, it.first, Handle)) { BoundTextures[Handle] = it.second; } } std::for_each(UnboundUniforms.begin(), UnboundUniforms.end(), [](string const & Uniform) { Log::Error("Uniform expected by shader but not provided by PSO: %s", Uniform); }); Loaded = true; }