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));
					}
				}
			}
Esempio n. 2
0
		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();
		}