void CGraphicsContext::InternalDrawTeardown(SharedPointer<IPipelineState> State) { SharedPointer<GL::CPipelineState> PipelineState = std::dynamic_pointer_cast<GL::CPipelineState>(State); if (PipelineState->DrawWireframe) { CheckedGLCall(glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)); } if (PipelineState->CullFront || PipelineState->CullBack) { CheckedGLCall(glDisable(GL_CULL_FACE)); CheckedGLCall(glCullFace(GL_BACK)); // Default value } if (PipelineState->DisableDepthTest) { CheckedGLCall(glEnable(GL_DEPTH_TEST)); } if (PipelineState->DisableDepthWrite) { CheckedGLCall(glDepthMask(GL_TRUE)); } if (PipelineState->BlendMode != EBlendMode::None) { CheckedGLCall(glDisable(GL_BLEND)); } int TextureIndex = 0; for (auto const & it : PipelineState->BoundTextures) { CheckedGLCall(glActiveTexture(GL_TEXTURE0 + TextureIndex++)); SharedPointer<CTexture const> Texture = std::dynamic_pointer_cast<CTexture const>(it.second); CheckedGLCall(glBindTexture(Texture->GetGLBindTextureTarget(), 0)); } CheckedGLCall(glBindVertexArray(0)); }
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)); } } }