Jump to content

  • Log In with Google      Sign In   
  • Create Account

Interested in a FREE copy of HTML5 game maker Construct 2?

We'll be giving away three Personal Edition licences in next Tuesday's GDNet Direct email newsletter!

Sign up from the right-hand sidebar on our homepage and read Tuesday's newsletter for details!


We're also offering banner ads on our site from just $5! 1. Details HERE. 2. GDNet+ Subscriptions HERE. 3. Ad upload HERE.


Texture Loading "Per Triangle" versus all of the Triangles Called with glDrawElements


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
12 replies to this topic

#1 tmason   Members   -  Reputation: 285

Like
0Likes
Like

Posted 16 June 2014 - 02:49 AM

Hello,

 

I have this weird problem that I assume is really simple to fix but I can't figure it out. Basically my textures are being loaded per "triangle" when I use them in OpenGL.

 

Thank you in advance for any assistance you can provide.

 

Here is how I am loading them into OpenGL: 

glGenTextures(1, &TextureObject_ID);   // section being edited by CKoeber to pull in material files
		glActiveTexture(GL_TEXTURE0 + 1);
		glBindTexture(GL_TEXTURE_2D, TextureObject_ID);
		GLsizei iFormat = BytesPerPixel == 24 ? GL_BGR : BytesPerPixel == 8 ? GL_LUMINANCE : 0;
		GLsizei iInternalFormat = BytesPerPixel == 24 ? GL_RGB : GL_DEPTH_COMPONENT;
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
		             WidthOfTexture, HeightOfTexture, 0, iFormat,
		             GL_UNSIGNED_BYTE, bytesDataPointer);
		glGenerateMipmap(GL_TEXTURE_2D);
		FreeImage_Unload(loadedImage);
		glGenSamplers(1, &TextureSamplerObject_ID);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
		setFiltering(TEXTURE_FILTER_MAG_BILINEAR, TEXTURE_FILTER_MIN_BILINEAR_MIPMAP);
		HasMipsBeenGenerated = true;
		glActiveTexture(GL_TEXTURE0 + 0);
		glBindTexture(GL_TEXTURE_2D, NULL);

I am sending my UV coordinates to OpenGL like so:

		glBufferSubData(GL_ARRAY_BUFFER, UVOffset, UVBufferSize, UVs);
		glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, 0);
		glEnableVertexAttribArray(2);

I am buffering my vertices and normals in similar fashion as I am drawing fine.

 

Also,

 

Here is the relevant section in the graphics card:

/*

In Fragment Shader...

*/

uniform sampler2D MainTextureSampler; 
in vec2 TextureCoordinates;
out vec4 finalColor;

void Main() {

    vec4 MaterialTextureColor = texture2D(MainTextureSampler, TextureCoordinates);
    finalColor = MaterialTextureColor;

}

Below is an example image:

 

Texture_Per_Triangle.png



Sponsor:

#2 Wh0p   Members   -  Reputation: 340

Like
0Likes
Like

Posted 16 June 2014 - 07:13 AM

This looks pretty much like broken tex coordinates for this triangle.

 

Do you generate the texture coordinates yourself or are you loading them from a model?

If you generate them your self, check that corresponding vertices in each triangle have the same texture coordinates assigned.

 

If the vertexbuffer of this quad looks like this  [V1/V2/V3/V1/V3/V4]

make sure the buffer for the texture coordinates is layouted the same way [T1/T2/T3/T1/T3/T4]

 

 



#3 tmason   Members   -  Reputation: 285

Like
0Likes
Like

Posted 16 June 2014 - 08:13 AM

This looks pretty much like broken tex coordinates for this triangle.

 

Do you generate the texture coordinates yourself or are you loading them from a model?

If you generate them your self, check that corresponding vertices in each triangle have the same texture coordinates assigned.

 

If the vertexbuffer of this quad looks like this  [V1/V2/V3/V1/V3/V4]

make sure the buffer for the texture coordinates is layouted the same way [T1/T2/T3/T1/T3/T4]

 

Thanks,

 

I am loading the UVs from a file. I was wondering how to generate them myself but I want to use them from the file if I can.

 

If I have to, how would I generate them?

 

Thank you for your time.



#4 Wh0p   Members   -  Reputation: 340

Like
0Likes
Like

Posted 16 June 2014 - 11:13 AM

Then maybe it would help to post the code where you are loading the file (what format?) and you draw call to open gl.

 

It's just a hunch, but if you have back face culling disabled and use the wrong winding order of faces, it might just generate this effect.

maybe playing a little around with glFrontFace() and glCullFace() will help.

 

 

If I have to, how would I generate them?

 

Don't even think about that then biggrin.png



#5 tmason   Members   -  Reputation: 285

Like
0Likes
Like

Posted 16 June 2014 - 07:54 PM

Then maybe it would help to post the code where you are loading the file (what format?) and you draw call to open gl.


Here is the way I am loading the texture (using FreeImage and JPEG files):

FIBITMAP *loadedImage = NULL;
		FREE_IMAGE_FORMAT CurrentFormat = FIF_UNKNOWN;
		CurrentFormat = FreeImage_GetFileType(MaterialFile.c_str(), 0);

		if (CurrentFormat == FIF_UNKNOWN) {
			FREE_IMAGE_FORMAT CurrentFormat = FreeImage_GetFIFFromFilename(MaterialFile.c_str());
		}

		if (CurrentFormat == FIF_UNKNOWN) {
			return false;
		}

		if (FreeImage_FIFSupportsReading(CurrentFormat)) {
			loadedImage = FreeImage_Load(CurrentFormat, MaterialFile.c_str());
		}

		if (!loadedImage) {
			return false;
		}

		BYTE* bytesDataPointer = FreeImage_GetBits(loadedImage);
		WidthOfTexture = FreeImage_GetWidth(loadedImage);
		HeightOfTexture = FreeImage_GetHeight(loadedImage);
		BytesPerPixel = FreeImage_GetBPP(loadedImage);

		if (WidthOfTexture == 0 || HeightOfTexture == 0 || BytesPerPixel == 0) {
			return false;
		}

		glGenTextures(1, &TextureObject_ID);   // section being edited by CKoeber to pull in material files
		glActiveTexture(GL_TEXTURE0 + 1);
		glBindTexture(GL_TEXTURE_2D, TextureObject_ID);
		GLsizei iFormat = BytesPerPixel == 24 ? GL_BGR : BytesPerPixel == 8 ? GL_LUMINANCE : 0;
		GLsizei iInternalFormat = BytesPerPixel == 24 ? GL_RGB : GL_DEPTH_COMPONENT;
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
		             WidthOfTexture, HeightOfTexture, 0, iFormat,
		             GL_UNSIGNED_BYTE, bytesDataPointer);
		glGenerateMipmap(GL_TEXTURE_2D);
		FreeImage_Unload(loadedImage);
		glGenSamplers(1, &TextureSamplerObject_ID);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
		setFiltering(TEXTURE_FILTER_MAG_BILINEAR, TEXTURE_FILTER_MIN_BILINEAR_MIPMAP);
		HasMipsBeenGenerated = true;
		glActiveTexture(GL_TEXTURE0 + 0);
		glBindTexture(GL_TEXTURE_2D, NULL);
And here is the way I am drawing the OpenGL quad with materials:

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
		
glUseProgram(g_StandardShaderProgram_ID);

glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

glEnable(GL_TEXTURE_2D);
glUniform1i(GetEnableWireframeID(), 0);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

for (GLuint i = 0; i < CurrentMeshCache.size(); i++) {

/*

Inside my object that has my mesh/quad/material data...

/*

glBindVertexArray(Pointer_VAO);

for (int i = 0; i < ModelMatrixInstances.size(); i++) {
	glm::mat4 ModelViewMatrix = CurrentOpenGLController->GetViewMatrix() * ModelMatrixInstances[i];
	glm::mat3 NormalMatrix = glm::transpose(glm::inverse(glm::mat3(ModelViewMatrix)));
	glm::mat4 ModelViewProjectionMatrix = CurrentOpenGLController->GetProjectionViewMatrix() * ModelMatrixInstances[i];
	glBindBuffer(GL_ARRAY_BUFFER, MVP_VBO);
	glBufferSubData(GL_ARRAY_BUFFER, (i * (sizeof(glm::mat4))), sizeof(glm::mat4), glm::value_ptr(ModelViewProjectionMatrix));
	glBindBuffer(GL_ARRAY_BUFFER, NormalMatrix_VBO);
	glBufferSubData(GL_ARRAY_BUFFER, (i * (sizeof(glm::mat3))), sizeof(glm::mat3), glm::value_ptr(NormalMatrix));
}

glUniform4fv(CurrentOpenGLController->GetMaterialColorID(), 1, Materials[0].ObjectColor);
glUniform4fv(CurrentOpenGLController->GetAmbientMeshColorID(), 1, Materials[0].AmbientColor);
glUniform4fv(CurrentOpenGLController->GetEmmissiveMeshColorID(), 1, Materials[0].EmissiveColor);
glUniform4fv(CurrentOpenGLController->GetSpecularMeshColorID(), 1, Materials[0].SpecularColor);
glUniform4fv(CurrentOpenGLController->GetDiffuseMeshColorID(), 1, Materials[0].DiffuseColor);
glUniform1fv(CurrentOpenGLController->GetMeshShininessID(), 1, &Materials[0].Shininess);

if (Materials[0].HasMaterialFile == true) {
	GLfloat ObjectHasMaterial = 1.0f;
	glUniform1fv(CurrentOpenGLController->GetObjectHasMaterialFileID(), 1, &ObjectHasMaterial);
	glUniform1i(CurrentOpenGLController->GetMainTextureID(), 1);
	Materials[0].bindTexture(1);
}
else {
	GLfloat ObjectDoesNotHaveMaterial = 0.0f;
	glUniform1fv(CurrentOpenGLController->GetObjectHasMaterialFileID(), 1, &ObjectDoesNotHaveMaterial);
	glBindTexture(GL_TEXTURE_2D, NULL);
}

glDrawElementsInstanced(GL_TRIANGLES, TotalVertexCount,
	GL_UNSIGNED_INT, NULL, NumberOfChildItems + 1);

if (Materials[0].HasMaterialFile == true) {
	glActiveTexture(GL_TEXTURE0 + NULL);
	glBindTexture(GL_TEXTURE_2D, NULL);
}

/*

Now out of my object...

*/
}

glBindVertexArray(0);


#6 tmason   Members   -  Reputation: 285

Like
0Likes
Like

Posted 16 June 2014 - 08:04 PM

It's just a hunch, but if you have back face culling disabled and use the wrong winding order of faces, it might just generate this effect.
maybe playing a little around with glFrontFace() and glCullFace() will help.


Tried this; same results. Thank you for the suggestion though.

#7 tmason   Members   -  Reputation: 285

Like
0Likes
Like

Posted 16 June 2014 - 08:05 PM

If I have to, how would I generate them?

 
Don't even think about that then biggrin.png


Darn, it's OK, I can learn smile.png

#8 Wh0p   Members   -  Reputation: 340

Like
0Likes
Like

Posted 17 June 2014 - 03:02 AM

Darn, it's OK, I can learn

 

 

Naa, thats not what I mean. This would just be a hack and not a solution to your problem in the first place.

 

I am sorry, I think I was not clear enough, but with file I didn't mean the image but the geometry you are loading. I think you have to look for the error in how you set up your vertex/normal/texcoord/index buffers.

 

Have you ever tried to render a simpler scene (just one quad maybe?) to make it easier to narrow down the error?

 

 

Do you really want to draw glDrawElementsInstanced ()???   this would mean that you would render the same geometry over and over again and you need an instance buffer with appropriate glVertexAttribDivisor() set (have a look at instanced rendering then: http://en.wikipedia.org/wiki/Geometry_instancing)

Second I noticed, that you call glDrawElements* with TotalVertexCount  I dont know what this variable contains but you should call this function with the number of indices not vertices.



#9 L. Spiro   Crossbones+   -  Reputation: 13953

Like
0Likes
Like

Posted 19 June 2014 - 08:43 PM

From what type of file are you loading the model data?
Some file formats are obnoxious and use 1-based indices or have other quirks when indexing into UV/normal/vertex pools.


L. Spiro
It is amazing how often people try to be unique, and yet they are always trying to make others be like them. - L. Spiro 2011
I spent most of my life learning the courage it takes to go out and get what I want. Now that I have it, I am not sure exactly what it is that I want. - L. Spiro 2013
I went to my local Subway once to find some guy yelling at the staff. When someone finally came to take my order and asked, “May I help you?”, I replied, “Yeah, I’ll have one asshole to go.”
L. Spiro Engine: http://lspiroengine.com
L. Spiro Engine Forums: http://lspiroengine.com/forums

#10 tmason   Members   -  Reputation: 285

Like
0Likes
Like

Posted 19 June 2014 - 08:45 PM

From what type of file are you loading the model data?
Some file formats are obnoxious and use 1-based indices or have other quirks when indexing into UV/normal/vertex pools.


L. Spiro


I am loading the data from an FBX file.

Specifically, I am using Autodesk's FBX SDK.

#11 L. Spiro   Crossbones+   -  Reputation: 13953

Like
0Likes
Like

Posted 20 June 2014 - 02:44 AM

So you are covering all 4 methods for creating indices into the pools, right?


L. Spiro
It is amazing how often people try to be unique, and yet they are always trying to make others be like them. - L. Spiro 2011
I spent most of my life learning the courage it takes to go out and get what I want. Now that I have it, I am not sure exactly what it is that I want. - L. Spiro 2013
I went to my local Subway once to find some guy yelling at the staff. When someone finally came to take my order and asked, “May I help you?”, I replied, “Yeah, I’ll have one asshole to go.”
L. Spiro Engine: http://lspiroengine.com
L. Spiro Engine Forums: http://lspiroengine.com/forums

#12 tmason   Members   -  Reputation: 285

Like
0Likes
Like

Posted 20 June 2014 - 11:03 AM

So you are covering all 4 methods for creating indices into the pools, right?


L. Spiro


Hello,

Perhaps I am an amateur but I don't get this. "Creating indices into the pools"?

I don't know what that means.

Thank you for your time.

Edited by tmason, 20 June 2014 - 11:03 AM.


#13 L. Spiro   Crossbones+   -  Reputation: 13953

Like
0Likes
Like

Posted 20 June 2014 - 02:02 PM

Look at any sample that runs over the faces of each mesh.
You have FbxGeometryElement::eByControlPoint or FbxGeometryElement::eByPolygonVertex.
In both cases you have either GetReferenceMode() == FbxLayerElement::eDirect or FbxLayerElement::eIndexToDirect.

This snippet gets the proper normal index (ffvThisVert.u32NormalIndex) under these considerations:
	// Go over each vertex in the face.
	for ( u32 I = 0UL; I < ui32PolyTotal; ++I ) {
		FC_FACE::FC_FACE_VERTEX ffvThisVert;
		u32 u32VertIndex = piFacePool[ui32PolyStart+I];
		ffvThisVert.u32VertexIndex = u32VertIndex;

		if ( m_u32Flags & FC_NORMALS ) {
			ffvThisVert.u32NormalIndex = 0UL;
			const FbxLayerElementNormal * plenNormals = m_pfmMesh->GetLayer( 0 )->GetNormals();
			switch ( plenNormals->GetMappingMode() ) {
				case FbxGeometryElement::eByControlPoint : {
					// The normal index is based on the vertex index.
					if ( plenNormals->GetReferenceMode() == FbxLayerElement::eDirect ) {
						// The normal index is the same as the vertex index.
						ffvThisVert.u32NormalIndex = u32VertIndex;
					}
					else if ( plenNormals->GetReferenceMode() == FbxLayerElement::eIndexToDirect ) {
						// The normal index is found by plugging the vertex index into an array of indices.
						ffvThisVert.u32NormalIndex = plenNormals->GetIndexArray().GetAt( u32VertIndex );
					}
					if ( ffvThisVert.u32NormalIndex >= static_cast<u32>(plenNormals->GetDirectArray().GetCount()) ) {
						std::cout << "Invalid normal index." << std::endl;
					}
					break;
				}
				case FbxGeometryElement::eByPolygonVertex : {
					// The normal index is based off _favAddVert.u32IndexCount, which is
					//	incremented once for each vertex over which we loop.
					if ( plenNormals->GetReferenceMode() == FbxLayerElement::eDirect ) {
						// It is just _favAddVert.u32IndexCount.
						ffvThisVert.u32NormalIndex = _favAddVert.u32IndexCount;
					}
					else if ( plenNormals->GetReferenceMode() == FbxLayerElement::eIndexToDirect ) {
						// The normal index is found by plugging _favAddVert.u32IndexCount into an array of indices.
						ffvThisVert.u32NormalIndex = plenNormals->GetIndexArray().GetAt( _favAddVert.u32IndexCount );
					}
					break;
				}
				default : {
					std::cout << "Unsupported normal mapping mode." << std::endl;
				}
			}
		}
Vertices, vertex, colors, and UV coordinates all work the same way, though you can go over more layers if you want more UV sets (or you can just ignore all but the base layer).


L. Spiro
It is amazing how often people try to be unique, and yet they are always trying to make others be like them. - L. Spiro 2011
I spent most of my life learning the courage it takes to go out and get what I want. Now that I have it, I am not sure exactly what it is that I want. - L. Spiro 2013
I went to my local Subway once to find some guy yelling at the staff. When someone finally came to take my order and asked, “May I help you?”, I replied, “Yeah, I’ll have one asshole to go.”
L. Spiro Engine: http://lspiroengine.com
L. Spiro Engine Forums: http://lspiroengine.com/forums




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS