Пример #1
0
		void CSimpleSceneObject::Draw(CRenderPass * RenderPass)
		{
			SharedPointer<Graphics::IPipelineState> PipelineState;
			if (TryMapAccess(PipelineStates, RenderPass, PipelineState))
			{
				RenderPass->SubmitPipelineStateForRendering(PipelineState, this, InstanceCount, RenderCategory);
			}
		}
Пример #2
0
		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;
		}
Пример #3
0
			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;
			}