void CGraphicsContext::InternalDrawSetup(SharedPointer<IPipelineState> State) { SharedPointer<GL::CPipelineState> PipelineState = std::dynamic_pointer_cast<GL::CPipelineState>(State); if (! PipelineState->Loaded) { PipelineState->Load(); } if (! PipelineState->ShaderProgram) { Log::Error("Cannot draw pipeline state with no shader program."); return; } CheckedGLCall(glUseProgram(PipelineState->ShaderProgram->Handle)); CheckedGLCall(glBindVertexArray(PipelineState->VertexArrayHandle)); // Uniforms for (auto const & it : PipelineState->BoundUniforms) { switch (it.second->GetType()) { case EUniformType::Float: CheckedGLCall(glUniform1f(it.first, * static_cast<float const *>(it.second->GetData()))); break; case EUniformType::FloatArray: CheckedGLCall(glUniform1fv(it.first, (GLsizei) static_cast<vector<float> const *>(it.second->GetData())->size(), static_cast<vector<float> const *>(it.second->GetData())->data() )); break; case EUniformType::Float2: CheckedGLCall(glUniform2f(it.first, static_cast<SVectorBase<float, 2> const *>(it.second->GetData())->Values[0], static_cast<SVectorBase<float, 2> const *>(it.second->GetData())->Values[1])); break; case EUniformType::Float2Array: { vector<float> CompactedData; for (auto const & Vector : *static_cast<vector<vec2f> const *>(it.second->GetData())) { CompactedData.push_back(Vector.X); CompactedData.push_back(Vector.Y); } CheckedGLCall(glUniform2fv(it.first, (GLsizei) CompactedData.size() / 2, CompactedData.data() )); break; } case EUniformType::Float3: CheckedGLCall(glUniform3f(it.first, static_cast<SVectorBase<float, 3> const *>(it.second->GetData())->Values[0], static_cast<SVectorBase<float, 3> const *>(it.second->GetData())->Values[1], static_cast<SVectorBase<float, 3> const *>(it.second->GetData())->Values[2])); break; case EUniformType::Float3Array: { vector<float> CompactedData; for (auto const & Vector : *static_cast<vector<vec3f> const *>(it.second->GetData())) { CompactedData.push_back(Vector.X); CompactedData.push_back(Vector.Y); CompactedData.push_back(Vector.Z); } CheckedGLCall(glUniform3fv(it.first, (GLsizei) CompactedData.size() / 3, CompactedData.data() )); break; } case EUniformType::Float4: CheckedGLCall(glUniform4f(it.first, static_cast<SVectorBase<float, 4> const *>(it.second->GetData())->Values[0], static_cast<SVectorBase<float, 4> const *>(it.second->GetData())->Values[1], static_cast<SVectorBase<float, 4> const *>(it.second->GetData())->Values[2], static_cast<SVectorBase<float, 4> const *>(it.second->GetData())->Values[3])); break; case EUniformType::Matrix4x4: CheckedGLCall(glUniformMatrix4fv(it.first, 1, GL_FALSE, glm::value_ptr(* static_cast<glm::mat4 const *>(it.second->GetData())))); break; case EUniformType::Matrix4x4Array: { vector<float> CompactedData; for (auto const & Matrix : *static_cast<vector<glm::mat4> const *>(it.second->GetData())) { CompactedData.insert(CompactedData.end(), glm::value_ptr(Matrix), glm::value_ptr(Matrix) + 16); } CheckedGLCall(glUniformMatrix4fv(it.first, (GLsizei) CompactedData.size() / 16, GL_FALSE, CompactedData.data())); break; } case EUniformType::Int: CheckedGLCall(glUniform1i(it.first, * static_cast<uint const *>(it.second->GetData()))); break; case EUniformType::Int2: CheckedGLCall(glUniform2i(it.first, static_cast<SVectorBase<int, 2> const *>(it.second->GetData())->Values[0], static_cast<SVectorBase<int, 2> const *>(it.second->GetData())->Values[1])); break; case EUniformType::Int3: CheckedGLCall(glUniform3i(it.first, static_cast<SVectorBase<int, 3> const *>(it.second->GetData())->Values[0], static_cast<SVectorBase<int, 3> const *>(it.second->GetData())->Values[1], static_cast<SVectorBase<int, 3> const *>(it.second->GetData())->Values[2])); break; case EUniformType::Int4: CheckedGLCall(glUniform4i(it.first, static_cast<SVectorBase<int, 4> const *>(it.second->GetData())->Values[0], static_cast<SVectorBase<int, 4> const *>(it.second->GetData())->Values[1], static_cast<SVectorBase<int, 4> const *>(it.second->GetData())->Values[2], static_cast<SVectorBase<int, 4> const *>(it.second->GetData())->Values[3])); break; default: Log::Error("Unexpected uniform type during uniform binding: '%s'", GetUniformTypeString(it.second->GetType())); break; } } // Textures int TextureIndex = 0; for (auto const & it : PipelineState->BoundTextures) { CheckedGLCall(glUniform1i(it.first, TextureIndex)); CheckedGLCall(glActiveTexture(GL_TEXTURE0 + TextureIndex++)); SharedPointer<CTexture const> Texture = std::dynamic_pointer_cast<CTexture const>(it.second); CheckedGLCall(glBindTexture(Texture->GetGLBindTextureTarget(), Texture->Handle)); } // Draw Features if (PipelineState->DrawWireframe) { CheckedGLCall(glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)); } if (PipelineState->CullFront || PipelineState->CullBack) { glEnable(GL_CULL_FACE); if (! PipelineState->CullFront) CheckedGLCall(glCullFace(GL_BACK)); else if (! PipelineState->CullBack) CheckedGLCall(glCullFace(GL_FRONT)); else CheckedGLCall(glCullFace(GL_FRONT_AND_BACK)); } if (PipelineState->DisableDepthTest) { CheckedGLCall(glDisable(GL_DEPTH_TEST)); } if (PipelineState->DisableDepthWrite) { CheckedGLCall(glDepthMask(GL_FALSE)); } if (PipelineState->BlendMode != EBlendMode::None) { CheckedGLCall(glEnable(GL_BLEND)); if (PipelineState->BlendMode == EBlendMode::Alpha) { CheckedGLCall(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); } else if (PipelineState->BlendMode == EBlendMode::Additive) { CheckedGLCall(glBlendFunc(GL_SRC_ALPHA, GL_ONE)); } } }
void CRenderPass::PreparePipelineStateForRendering(SharedPointer<Graphics::IPipelineState> PipelineState, ISceneObject * SceneObject) { if (! PipelineState) { return; } set<string> const UnboundUniforms = PipelineState->GetUnboundUniforms(); std::for_each(UnboundUniforms.begin(), UnboundUniforms.end(), [&](string const & Name) { int Index = -1; string LHS, Remaining; if (Name == "uModelMatrix") { PipelineState->SetUniform(Name, uModelMatrix); } else if (Name == "uNormalMatrix") { PipelineState->SetUniform(Name, uNormalMatrix); } else if (Name == "uViewMatrix") { PipelineState->SetUniform(Name, uViewMatrix); } else if (Name == "uProjectionMatrix") { PipelineState->SetUniform(Name, uProjectionMatrix); } else if (Name == "uCameraMatrix") { PipelineState->SetUniform(Name, uCameraMatrix); } else if (Name == "uInvCameraMatrix") { PipelineState->SetUniform(Name, uInvCameraMatrix); } else if (Name == "uCameraPosition") { PipelineState->SetUniform(Name, uCameraPosition); } else if (IsUniformNameArrayElement(Name, Index, LHS, Remaining)) { if (Remaining.size() && Remaining[0] == '.') { auto const it = Lights.find(LHS); if (it != Lights.end()) { if (Index < it->second.size()) { ILight * const Light = it->second[Index]; PipelineState->SetUniform(Name, Light->GetAttributeByName(Remaining.substr(1))); } else { PipelineState->IgnoreUniform(Name); } } } } else { for (auto const & it : Lights) { string const CountName = it.first + "Count"; if (Name == CountName) { PipelineState->SetUniform(Name, SharedFromNew(new Graphics::CUniformValue<int>((int) it.second.size()))); } } for (auto const & it : Uniforms) { if (Name == it.first) { PipelineState->SetUniform(Name, it.second); } } for (auto const & it : Textures) { if (Name == it.first) { PipelineState->SetTexture(Name, it.second); } } } }); PipelineState->Load(); }