Jump to content
  • Advertisement
Sign in to follow this  
tmason

OpenGL Using Uniform Blocks for Materials ...

This topic is 1434 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello,

I am attemtping to use uniform blocks for materials and for some reason with my current implementation the uniform for one material ends up "overriding" the previous drawn information for previous draw calls, which ends up with a lot of flashing on screen.

The animated gif below does a better job of explaining what happens:

d4pfw.gif

Any ideas? Thank you!

Here are my draw calls and how I send data to the uniform buffer:

MVPMatrix = (*ProjectionMatrix) * (*ViewMatrix) * ModelMatrix;
	NormalMatrix = glm::transpose(glm::inverse(glm::mat3(MVPMatrix)));
	InverseViewMatrix = glm::inverse((*ViewMatrix));

	glBindVertexArray(VertextArrayObjectID);
	
	glUniformMatrix4fv((*AssociatedOpenGLProgram->GetModelMatrixID()), 1, GL_FALSE, glm::value_ptr(ModelMatrix));
	glUniformMatrix4fv((*AssociatedOpenGLProgram->GetMVPMatrixID()), 1, GL_FALSE, glm::value_ptr(MVPMatrix));
	glUniformMatrix4fv((*AssociatedOpenGLProgram->GetViewMatrixID()), 1, GL_FALSE, glm::value_ptr((*ViewMatrix)));
	glUniformMatrix4fv((*AssociatedOpenGLProgram->GetInverseViewMatrixID()), 1, GL_FALSE, glm::value_ptr(InverseViewMatrix));
	glUniformMatrix3fv((*AssociatedOpenGLProgram->GetNormalMatrixID()), 1, GL_FALSE, glm::value_ptr(NormalMatrix));

	glBindBuffer(GL_UNIFORM_BUFFER, (*AssociatedOpenGLProgram->GetMaterialUniformBufferID()));

	glBufferData(GL_UNIFORM_BUFFER, sizeof(GLfloat) * 18,
		AssociatedMaterial->GetMaterialUniformValues(), GL_DYNAMIC_DRAW);

	glBindBuffer(GL_UNIFORM_BUFFER, NULL);

	if (AssociatedMaterial->IsWireframeEnabled() != false && AssociatedOpenGLProgram->IsWireframeEnabled() == false) {

		GLfloat EnableWireframe = 1.0f;
		glUniform1fv((*AssociatedOpenGLProgram->GetEnableWireframeID()), 1, &EnableWireframe);
		glDisable(GL_BLEND);
		glDisable(GL_TEXTURE_2D);
		glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

	}
	else {

		if (AssociatedMaterial->HasAssociatedTexture()) {

			GLfloat ObjectHasMaterial = 1.0f;
			glUniform1fv((*AssociatedOpenGLProgram->GetObjectHasTextureID()), 1, &ObjectHasMaterial);
			glUniform1i((*AssociatedOpenGLProgram->GetTextureSamplerID()), 1);

			AssociatedMaterial->BindTexture(1);

		}
		else {

			glBindTexture(GL_TEXTURE_2D, NULL);

		}

	}

	glDrawElementsInstanced(GL_TRIANGLES, NumOfIndices, GL_UNSIGNED_INT, NULL, 1);

	if (AssociatedMaterial->IsWireframeEnabled() != false && AssociatedOpenGLProgram->IsWireframeEnabled() == false) {

		GLfloat EnableWireframe = 0.0f;
		glUniform1fv((*AssociatedOpenGLProgram->GetEnableWireframeID()), 1, &EnableWireframe);
		glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
		glEnable(GL_TEXTURE_2D);
		glEnable(GL_BLEND);
		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

	}
This is how I set up the material uniform in question:

MaterialUniformBlockID = glGetUniformBlockIndex(programID, "Material");
	glUniformBlockBinding(programID, MaterialUniformBlockID, MaterialUniformBlockBindingPoint);
	glGenBuffers(1, &MaterialUniformBufferID);
	glBindBuffer(GL_UNIFORM_BUFFER, MaterialUniformBufferID);
	glBindBufferBase(GL_UNIFORM_BUFFER, MaterialUniformBlockBindingPoint, MaterialUniformBufferID);
	glBindBuffer(GL_UNIFORM_BUFFER, NULL);
Here is my vertex shader:

#version 330 core

#extension GL_ARB_explicit_attrib_location : require

// Input vertex data, different for all executions of this shader.

layout(location = 0) in vec3 vPosition;
layout(location = 1) in vec3 Normals;
layout(location = 2) in vec2 vUV;

// Output data ; will be interpolated for each fragment.

out vec3 SurfaceNormal;
out vec4 vertexPosition;
out vec2 TextureCoordinates;

// Values that stay constant for the whole mesh.

uniform mat4 MVP;
uniform mat4 ModelMatrix;
uniform mat4 ViewMatrix;
uniform mat3 NormalMatrix;

void main(){	

	gl_Position = MVP * vec4(vPosition, 1.0);	
	vertexPosition = ModelMatrix * vec4(vPosition, 1.0);
	SurfaceNormal = normalize(NormalMatrix * Normals);
	TextureCoordinates = vUV;
	
}
And here is my fragment shader:

#version 330
#extension GL_ARB_explicit_attrib_location : require

//
// These values vary per Mesh
//

layout (std140) uniform Material
{
	
	vec4 	AmbientMeshColor;
	vec4 	EmissiveMeshColor;
	vec4 	DiffuseMeshColor;
	vec4 	SpecularMeshColor;
	float 	MeshShininess;
	float	ObjectHasTextureFile;

};

//
// Sunlight Settings.
//

layout (std140) uniform Sunlight
{
  
  vec4 SunlightPosition;
  vec4 SunlightDiffuse;
  vec4 SunlightSpecular;
  vec4 SunlightDirection;
  float constantAttenuation, linearAttenuation, quadraticAttenuation;
  float spotCutoff, spotExponent;
  float	EnableLighting;
  float	EnableSun;
  float ExtraValue;

};

uniform vec4		SceneAmbient = vec4(0.2, 0.2, 0.2, 1.0);

//
// Whether Materials are enabled at all.
//

uniform float		IfEnableTextures;

//
// If we are just simply drawing the skybox.
//

uniform float		DrawingSkyBox;

uniform float		EnableWireframe;

uniform vec4		WireframeColor;

uniform float		TextureCoordinateDebug;

uniform sampler2D MainTextureSampler; 

vec4 MaterialTextureColor;

out vec4 finalColor;

in vec4 vertexPosition;  // position of the vertex (and fragment) in world space
in vec3 SurfaceNormal;  // surface normal vector in world space
in vec2 TextureCoordinates; // Texture coordinates...

uniform mat4 ViewMatrix;
uniform mat4 InverseView;

void DrawSkyBox() {

	finalColor = texture(MainTextureSampler, TextureCoordinates);

}

void DrawWireFrame() {

	finalColor = WireframeColor;

}

void main()
{

	if (DrawingSkyBox != 1.0) {
	
		vec3 normalDirection = normalize(SurfaceNormal);
		vec3 viewDirection = normalize(vec3(InverseView * vec4(0.0, 0.0, 0.0, 1.0) - vertexPosition));
		vec3 lightDirection;
		float attenuation;

		if (0.0 == SunlightPosition.w) // directional light?
		{

			attenuation = 1.0; // no attenuation
			lightDirection = normalize(vec3(SunlightPosition));

		} 
		else // point light or spotlight (or other kind of light)
		{
			vec3 positionToLightSource = vec3(SunlightPosition - vertexPosition);
			float distance = length(positionToLightSource);
			lightDirection = normalize(positionToLightSource);
			attenuation = 1.0 / (constantAttenuation
				   + linearAttenuation * distance
				   + quadraticAttenuation * distance * distance);

			if (spotCutoff <= 90.0) // spotlight?
			{
				float clampedCosine = max(0.0, dot(-lightDirection, vec3(SunlightDirection)));
				if (clampedCosine < cos(radians(spotCutoff))) // outside of spotlight cone?
				{
					attenuation = 0.0;
				}
				else
				{
					attenuation = attenuation * pow(clampedCosine, spotExponent);   
				}
			}
		}

		vec3 ambientLighting = vec3(SceneAmbient) * vec3(AmbientMeshColor);

		vec3 diffuseReflection = attenuation 
		* vec3(SunlightDiffuse) * vec3(DiffuseMeshColor)
		* max(0.0, dot(normalDirection, lightDirection));

		vec3 specularReflection;
		if (dot(normalDirection, lightDirection) < 0.0) // light source on the wrong side?
		{
			specularReflection = vec3(0.0, 0.0, 0.0); // no specular reflection
		}
		else // light source on the right side
		{
			specularReflection = attenuation * vec3(SunlightSpecular) * vec3(SpecularMeshColor) 
				* pow(max(0.0, dot(reflect(-lightDirection, normalDirection), viewDirection)), MeshShininess);
		}

		finalColor = vec4(ambientLighting + diffuseReflection + specularReflection, DiffuseMeshColor.a);
	
	} else {
	
		DrawSkyBox();
	
	}
  
}

Share this post


Link to post
Share on other sites
Advertisement
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!