Textures, some work and some doesn't???

Started by
24 comments, last by babaliaris 5 years, 5 months ago

Hello again :) 

Recently I was trying to apply 6 different textures in a cube and I noticed that some textures would not apply correctly, but if i change the texture image with another it works just fine. I can't really understand what's going on. I will also attach the image files. So does this might have to do anything with coding or its just the image fault???

This is a high quality texture 2048x2048 brick1.jpg, which does the following:

yyAqqpT.png

 

And this is another texture 512x512 container.jpg which is getting applied correctly with the exact same texture coordinates as the prev one:

3YwvDhp.png

 

Vertex Shader


#version 330 core

layout(location = 0) in vec3 aPos;
layout(location = 1) in vec3 aNormal;
layout(location = 2) in vec2 aTexCoord;

uniform mat4 model;
uniform mat4 view;
uniform mat4 proj;


out vec2 TexCoord;

void main()
{
	gl_Position = proj * view * model * vec4(aPos, 1.0);

	TexCoord = aTexCoord;
}

 

Fragment Shader


#version 330 core

out vec4 Color;
in vec2 TexCoord;

uniform sampler2D diffuse;

void main()
{
	Color = texture(diffuse, TexCoord);
}

 

Texture Loader


Texture::Texture(std::string path, bool trans, int unit)
{

	//Reverse the pixels.
	stbi_set_flip_vertically_on_load(1);

	//Try to load the image.
	unsigned char *data = stbi_load(path.c_str(), &m_width, &m_height, &m_channels, 0);

	//Image loaded successfully.
	if (data)
	{

		//Generate the texture and bind it.
		GLCall(glGenTextures(1, &m_id));
		GLCall(glActiveTexture(GL_TEXTURE0 + unit));
		GLCall(glBindTexture(GL_TEXTURE_2D, m_id));

		//Not Transparent texture.
		if (!trans)
		{
			GLCall(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, m_width, m_height, 0, GL_RGB, GL_UNSIGNED_BYTE, data));
		}

		//Transparent texture.
		else
		{
			GLCall(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data));
		}

		//Generate mipmaps.
		GLCall(glGenerateMipmap(GL_TEXTURE_2D));

		//Texture Filters.
		GLCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT));
		GLCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT));
		GLCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
		GLCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
	}


	//Loading Failed.
	else
		throw EngineError("The was an error loading image: " + path);


	//Free the image data.
	stbi_image_free(data);
}


Texture::~Texture()
{
}

void Texture::Bind(int unit)
{
	GLCall(glActiveTexture(GL_TEXTURE0 + unit));
	GLCall(glBindTexture(GL_TEXTURE_2D, m_id));
}

Rendering Code:


Renderer::Renderer()
{
	float vertices[] = {
		// positions          // normals           // texture coords
		-0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  0.0f, 0.0f,
		 0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  1.0f, 0.0f,
		 0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  1.0f, 1.0f,
		 0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  1.0f, 1.0f,
		-0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  0.0f, 1.0f,
		-0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  0.0f, 0.0f,

		-0.5f, -0.5f,  0.5f,  0.0f,  0.0f, 1.0f,   0.0f, 0.0f,
		 0.5f, -0.5f,  0.5f,  0.0f,  0.0f, 1.0f,   1.0f, 0.0f,
		 0.5f,  0.5f,  0.5f,  0.0f,  0.0f, 1.0f,   1.0f, 1.0f,
		 0.5f,  0.5f,  0.5f,  0.0f,  0.0f, 1.0f,   1.0f, 1.0f,
		-0.5f,  0.5f,  0.5f,  0.0f,  0.0f, 1.0f,   0.0f, 1.0f,
		-0.5f, -0.5f,  0.5f,  0.0f,  0.0f, 1.0f,   0.0f, 0.0f,

		-0.5f,  0.5f,  0.5f, -1.0f,  0.0f,  0.0f,  1.0f, 0.0f,
		-0.5f,  0.5f, -0.5f, -1.0f,  0.0f,  0.0f,  1.0f, 1.0f,
		-0.5f, -0.5f, -0.5f, -1.0f,  0.0f,  0.0f,  0.0f, 1.0f,
		-0.5f, -0.5f, -0.5f, -1.0f,  0.0f,  0.0f,  0.0f, 1.0f,
		-0.5f, -0.5f,  0.5f, -1.0f,  0.0f,  0.0f,  0.0f, 0.0f,
		-0.5f,  0.5f,  0.5f, -1.0f,  0.0f,  0.0f,  1.0f, 0.0f,

		 0.5f,  0.5f,  0.5f,  1.0f,  0.0f,  0.0f,  1.0f, 0.0f,
		 0.5f,  0.5f, -0.5f,  1.0f,  0.0f,  0.0f,  1.0f, 1.0f,
		 0.5f, -0.5f, -0.5f,  1.0f,  0.0f,  0.0f,  0.0f, 1.0f,
		 0.5f, -0.5f, -0.5f,  1.0f,  0.0f,  0.0f,  0.0f, 1.0f,
		 0.5f, -0.5f,  0.5f,  1.0f,  0.0f,  0.0f,  0.0f, 0.0f,
		 0.5f,  0.5f,  0.5f,  1.0f,  0.0f,  0.0f,  1.0f, 0.0f,

		-0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,  0.0f, 1.0f,
		 0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,  1.0f, 1.0f,
		 0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,  1.0f, 0.0f,
		 0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,  1.0f, 0.0f,
		-0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,  0.0f, 0.0f,
		-0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,  0.0f, 1.0f,

		-0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f,  0.0f, 1.0f,
		 0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f,  1.0f, 1.0f,
		 0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,  1.0f, 0.0f,
		 0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,  1.0f, 0.0f,
		-0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,  0.0f, 0.0f,
		-0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f,  0.0f, 1.0f
	};

	//Create the Vertex Array.
	m_vao = new Vao();

	//Create the Vertex Buffer.
	m_vbo = new Vbo(vertices, sizeof(vertices));

	//Create the attributes.
	m_attributes = new VertexAttributes();
	m_attributes->Push(3);
	m_attributes->Push(3);
	m_attributes->Push(2);
	m_attributes->Commit(m_vbo);
}







Renderer::~Renderer()
{
	delete m_vao;
	delete m_vbo;
	delete m_attributes;
}






void Renderer::DrawArrays(Cube *cube)
{

	//Render the cube.
	cube->Render();

	unsigned int tex = 0;

	for (unsigned int i = 0; i < 36; i += 6)
	{

		if (tex < cube->m_textures.size())
			cube->m_textures[tex]->Bind();

		GLCall(glDrawArrays(GL_TRIANGLES, i, 6));

		tex++;
	}
}

 

brick1.jpg

container.jpg


void life()
{
  while (!succeed())
    try_again();

  die_happily();
}

 

Advertisement

Since no one's replied yet, I'll go ahead and reply (even though I don't have an answer for you).

I skimmed the code, but didn't see anything obvious (if there's an error, maybe someone else will spot it).

If you haven't solved it yet, here are some things you could try:

- Simplify things by only rendering a single quad without indices (e.g. glDrawArrays()). If that fixes it, that'll be a hint as to where the problem is.

- Try a 512x512 version of the brick texture to see if the problem is size-related.

- Try it with both images exported from the same image editing program to (possibly) eliminate any vagaries related to image format, etc.

I can't tell from the picture, but is there a quad on the side being successfully rendered with the brick texture? If so, that should be a hint.

Also, what exactly (if you know) is being rendered at the bottom of the front-facing quad with the brick texture? It looks like another texture, or perhaps the brick texture, scaled and with different coloring (I can't really tell). That seems like a clue as well.

Again, the problem may be evident from what you've posted so far, and if so, maybe someone else will spot it.

3 hours ago, Zakwayda said:

- Try a 512x512 version of the brick texture to see if the problem is size-related.

This worked. I resized the image with windows painter and it worked.

But what is causing that? Why a high resolution image would create such an effect? Also you are right about the bottom of the front quad, you can see other textures too which i actually use for the other faces, but that mix of them is just so weird, I literally can't tell why it causes this when i use a high resolution image. Also from what i learned so far, high resolution images are always better because they cover a big range of sizes, also i'm generating mipmaps.

I also tried the following and it worked:

I kept the original image 2048x2048 and I loaded only that image as a texture (in the previous examples i was loading up to 6 differently textures) and the cube was getting rendered just fine with the high resolution image. So probably the problem must be in the loading texture class. If anyone has any ideas, help me.

 

I attached the program (build in visual studio for windows 32). Can someone download and run it to see if it works? Just to see if there is a bug with my graphics card drivers, because amd recently was having huge bugs on radeon, especially for my graphics card series.

This is what i see when i run the program which i attached:

Capture.png

 

openGL.rar


void life()
{
  while (!succeed())
    try_again();

  die_happily();
}

 

I'm not set up for Windows development right now, else I'd give it a try.

Quote

Also from what i learned so far, high resolution images are always better because they cover a big range of sizes, also i'm generating mipmaps.

I don't know that high-resolution images are always better. There are various tradeoffs to consider, such as target platform, frame buffer resolution, texture memory usage, what sort of compressed formats are available and what effect they have on image quality, and so on.

Consider that if the frame buffer resolution and texture usage patterns are such that the top mipmap level is never touched, you're just wasting texture memory (or so it would seem to me). A texture management system could, for example, take this into account by selecting a texture size based on (e.g.) frame buffer resolution and expected usage. (And of course some platforms, like iOS and Android, have OS-level support for image resolution selection.)

Of course that's all tangential here, since the real question is why you're getting the behavior you're getting.

Couple other things to try would be checking glGetError() at some point, and (just to be sure) checking for program compile/link errors as well. If you have OpenGL-related diagnostic tools available (e.g. something similar to what's available with Xcode), you could try that as well.

It's also possible to check the maximum texture size that the OpenGL implementation supports, and (if I recall correctly) to check that a particular texture will be uploaded successfully using texture proxies. It seems unlikely that that's the issue here, but if this is Windows, there may be some vagaries with respect to OpenGL support (at least that's been the case in the past).

With any luck, someone who's set up for Windows will be able to try out your app.

I use glGetError in every gl function, it's the GLCall macro in my code. I'm not getting any errors or compilation errors. 


void life()
{
  while (!succeed())
    try_again();

  die_happily();
}

 

By calling:


GLint data;
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &data);

I'm getting: 16384

and with a google search I found out that this means my graphics card can manipulate up to 16384x16384 resolution textures. So the brick texture which is 2048x2048 should be fine.


void life()
{
  while (!succeed())
    try_again();

  die_happily();
}

 

Seems to be a problem with the texture loading.

In your texture source file change to the following code:


//Not Transparent texture.
if (!trans)
{
	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
	GLCall(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, m_width, m_height, 0, GL_RGB, GL_UNSIGNED_BYTE, data));
	glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
}

Another way is to force stbi to use 4 channels so that it aligns to four bytes


Texture::Texture(std::string path, bool trans, int unit)
{
// ...
	unsigned char *data = stbi_load(path.c_str(), &m_width, &m_height, &m_channels, 4);
// ...
	if (data)
	{
		//Not Transparent texture.
		if (!trans)
		{
			GLCall(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data));
		}
	// ...	
	}
//...
}

 

1 hour ago, stororokw said:

Seems to be a problem with the texture loading.

In your texture source file change to the following code:



//Not Transparent texture.
if (!trans)
{
	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
	GLCall(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, m_width, m_height, 0, GL_RGB, GL_UNSIGNED_BYTE, data));
	glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
}

Another way is to force stbi to use 4 channels so that it aligns to four bytes



Texture::Texture(std::string path, bool trans, int unit)
{
// ...
	unsigned char *data = stbi_load(path.c_str(), &m_width, &m_height, &m_channels, 4);
// ...
	if (data)
	{
		//Not Transparent texture.
		if (!trans)
		{
			GLCall(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data));
		}
	// ...	
	}
//...
}

 

This is what I get when I'm using 4 channels:

four_channels.png


//Not Transparent texture.
		if (!trans)
		{
			GLCall(glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
			GLCall(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, m_width, m_height, 0, GL_RGB, GL_UNSIGNED_BYTE, data));
			GLCall(glPixelStorei(GL_UNPACK_ALIGNMENT, 4));
		}

And when I use the above code I'm getting this:

Capture.png


void life()
{
  while (!succeed())
    try_again();

  die_happily();
}

 

I took a look at your code from github OpenGLTextureProblem and for me things appear to be working properly.

Do you have the version of the code you used to post that last screenshot?

ogl.jpg

31 minutes ago, stororokw said:

I took a look at your code from github OpenGLTextureProblem and for me things appear to be working properly.

Do you have the version of the code you used to post that last screenshot?

ogl.jpg

Can you change the input from the first texture in Main.cpp


	Texture *texture1 = new Texture("Resources/brick1.jpg", false);
	Texture *texture2 = new Texture("Resources/container.jpg", false);
	Texture *texture3 = new Texture("Resources/brick2.jpg", false);
	Texture *texture4 = new Texture("Resources/brick3.jpg", false);
	Texture *texture5 = new Texture("Resources/brick4.jpg", false);
	Texture *texture6 = new Texture("Resources/container2.png", true);

from brick1.jpg to a.jpg and show me again the result? brick1.jpg is a resized version of a.jpg and it works on my computer as well.

So change the *texture1 in Main.cpp with:


Texture *texture1 = new Texture("Resources/a.jpg", false);

 


void life()
{
  while (!succeed())
    try_again();

  die_happily();
}

 

This topic is closed to new replies.

Advertisement