Ejemplo n.º 1
0
			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));
			}
Ejemplo n.º 2
0
			void CShader::SetPixelStage(SharedPointer<IPixelStage> PixelShader)
			{
				if (PixelShader)
				{
					CheckedGLCall(glAttachShader(Handle, std::dynamic_pointer_cast<CPixelStage>(PixelShader)->Handle));
				}
			}
Ejemplo n.º 3
0
			void CShader::SetGeometryStage(SharedPointer<IGeometryStage> GeometryShader)
			{
				if (GeometryShader)
				{
					CheckedGLCall(glAttachShader(Handle, std::dynamic_pointer_cast<CGeometryStage>(GeometryShader)->Handle));
				}
			}
Ejemplo n.º 4
0
			void CShader::SetVertexStage(SharedPointer<IVertexStage> VertexShader)
			{
				if (VertexShader)
				{
					CheckedGLCall(glAttachShader(Handle, std::dynamic_pointer_cast<CVertexStage>(VertexShader)->Handle));
				}
			}
Ejemplo n.º 5
0
			void CShader::Link()
			{
				CheckedGLCall(glBindFragDataLocation(Handle, 0, "outColor"));
				CheckedGLCall(glLinkProgram(Handle));

				int LinkStatus;
				CheckedGLCall(glGetProgramiv(Handle, GL_LINK_STATUS, & LinkStatus));

				if (LinkStatus)
				{
					Linked = true;

					// Load active uniforms
					int ActiveUniforms = 0;
					int ActiveUniformMaxLength = 0;
					CheckedGLCall(glGetProgramiv(Handle, GL_ACTIVE_UNIFORMS, & ActiveUniforms));
					CheckedGLCall(glGetProgramiv(Handle, GL_ACTIVE_UNIFORM_MAX_LENGTH, & ActiveUniformMaxLength));
					for (int i = 0; i < ActiveUniforms; ++ i)
					{
						int Length = -1, Size = -1;
						uint DataType;
						char * Name = new char[ActiveUniformMaxLength + 1]();

						CheckedGLCall(glGetActiveUniform(Handle, i, ActiveUniformMaxLength, & Length, & Size, & DataType, Name));
						Uniforms[Name] = glGetUniformLocation(Handle, Name);
						delete[] Name;
					}

					// Load active attributes
					int ActiveAttributes = 0;
					int ActiveAttributeMaxLength = 0;
					CheckedGLCall(glGetProgramiv(Handle, GL_ACTIVE_ATTRIBUTES, & ActiveAttributes));
					CheckedGLCall(glGetProgramiv(Handle, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, & ActiveAttributeMaxLength));
					for (GLint i = 0; i < ActiveAttributes; ++ i)
					{
						int Length = -1, Size = -1;
						uint DataType;
						char * Name = new char[ActiveAttributeMaxLength + 1];

						CheckedGLCall(glGetActiveAttrib(Handle, i, ActiveAttributeMaxLength, & Length, & Size, & DataType, Name));
						Attributes[Name] = std::make_pair(glGetAttribLocation(Handle, Name), DataType);
						delete[] Name;
					}
				}
				else
				{
					Log::Error("Failed to link shader program.");
					PrintProgramInfoLog(Handle);
				}

			}
Ejemplo n.º 6
0
			void CGraphicsContext::DrawInstanced(SharedPointer<IPipelineState> State, uint const InstanceCount)
			{
				Window->MakeContextCurrent();
				InternalDrawSetup(State);
				SharedPointer<GL::CPipelineState> PipelineState = std::dynamic_pointer_cast<GL::CPipelineState>(State);
				CheckedGLCall(glDrawElementsInstanced(GL_TRIANGLES, (int) PipelineState->IndexBuffer->Size, GL_UNSIGNED_INT, 0, InstanceCount));
				InternalDrawTeardown(State);
			}
Ejemplo n.º 7
0
			void CTexture::ApplyParams()
			{
				static u32 const FilterMatrix[3][2] =
				{
					{GL_NEAREST, GL_LINEAR},
					{GL_NEAREST_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_NEAREST},
					{GL_NEAREST_MIPMAP_LINEAR, GL_LINEAR_MIPMAP_LINEAR},
				};

				static u32 const FilterLookup[2] =
				{
					GL_NEAREST, GL_LINEAR
				};

				static u32 const WrapLookup[3] =
				{
					GL_CLAMP_TO_EDGE, GL_MIRRORED_REPEAT, GL_REPEAT
				};

				int MipMapMode;
				if (MipMaps)
					MipMapMode = 1 + (int) MipMapFilter;
				else
					MipMapMode = 0;

				int PreviouslyBoundTexture;
				CheckedGLCall(glGetIntegerv(GetGLTextureBindingEnum(), & PreviouslyBoundTexture));
				CheckedGLCall(glBindTexture(GetGLBindTextureTarget(), Handle));
				CheckedGLCall(glTexParameteri(GetGLBindTextureTarget(), GL_TEXTURE_MIN_FILTER, FilterMatrix[MipMapMode][(int) MinFilter]));
				CheckedGLCall(glTexParameteri(GetGLBindTextureTarget(), GL_TEXTURE_MAG_FILTER, FilterLookup[(int) MagFilter]));

				CheckedGLCall(glTexParameteri(GetGLBindTextureTarget(), GL_TEXTURE_WRAP_S, WrapLookup[(int) WrapMode]));
				CheckedGLCall(glTexParameteri(GetGLBindTextureTarget(), GL_TEXTURE_WRAP_T, WrapLookup[(int) WrapMode]));
				CheckedGLCall(glTexParameteri(GetGLBindTextureTarget(), GL_TEXTURE_WRAP_R, WrapLookup[(int) WrapMode]));

				float LargestAnisotropy = 2.f;
				CheckedGLCall(glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, & LargestAnisotropy));
				if (Anisotropy < 0.f)
					Anisotropy = LargestAnisotropy;
				CheckedGLCall(glTexParameterf(GetGLBindTextureTarget(), GL_TEXTURE_MAX_ANISOTROPY_EXT, Clamp(Anisotropy, 0.f, LargestAnisotropy)));
				CheckedGLCall(glBindTexture(GetGLBindTextureTarget(), PreviouslyBoundTexture));
			}
Ejemplo n.º 8
0
			void CTextureCubeMap::UploadSubRegion(EFace const Face, void const * const Data, vec2u const & Offset, vec2u const & Size, EFormatComponents const Components, EScalarType const Type)
			{
				CheckedGLCall(glBindTexture(GL_TEXTURE_CUBE_MAP, Handle));
				CheckExistingErrors(Texture2D::SubImage);
				glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + (int) Face, 0, Offset.X, Offset.Y, Size.X, Size.Y, FormatMatrix[(int) Components], Util::ScalarTypeMatrix[(int) Type], Data);
				if (OpenGLError())
				{
					cerr << "Error occured during glTexSubImage2D for CTextureCubeMap: " << GetOpenGLError() << endl;
					cerr << "Handle is " << Handle << endl;
					cerr << "Offset is " << Offset << endl;
					cerr << "Size is " << Size << endl;
					cerr << "Format is " << FormatStringMatrix[(int) Components] << endl;
					cerr << "Type is " << Util::ScalarTypeStringMatrix[(int) Type] << endl;
					cerr << endl;
				}
				else
				{
					if (MipMaps)
						CheckedGLCall(glGenerateMipmap(GL_TEXTURE_CUBE_MAP));
					ApplyParams();
				}
				CheckedGLCall(glBindTexture(GL_TEXTURE_CUBE_MAP, 0));
			}
Ejemplo n.º 9
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;
			}
Ejemplo n.º 10
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));
					}
				}
			}