Sign in to follow this  
Pasanova

OpenGL Struggling with textures in openGL

Recommended Posts

Hi,

I am trying to define my own texture but struggling to get even a simple test to work. I have been hitting my head against the wall all day unable to move past this issue (I am sure you remember the feeling) so any help would be gratefully appreciated.

-> I am just seeing a black box where the texture colour should be (in this simple test I am just expecting a white box in the middle of the screen)

->There is no error from glGetError() and the shader compiles and links without giving an error.

->In the fragment shader if I comment out the texture line and instead just return a vec4  then it will display a solid colour with no problem

I have posted the essential elements of the code below. Can anyone spot what I am missing?
 

//Position vertices and texture coordinates for a box
GLfloat screen2DVertices[] = 
{ //x, y, z                    //u, v
-0.8f, -0.8f, 0.0f,        0.0f, 0.0f, // bottom left corner
-0.8f,  0.8f, 0.0f,        0.0f, 1.0f, // top left corner
0.8f,  0.8f, 0.0f,         1.0f, 1.0f, // top right corner
0.8f, -0.8f, 0.0f,         1.0f, 0.0f, // bottom right corner
};

GLushort screen2DIndices[] = 
{ 
0,1,2, // first triangle (bottom left - top left - top right)
0,2,3  // second triangle (bottom left - top right - bottom right)
};

//Texture width in pixels
const int TEXTURE_WIDTH = 32;
const int TEXTURE_HEIGHT = 32;

//3 RGB values per pixel
float texturePixels[TEXTURE_WIDTH * TEXTURE_HEIGHT * 3];

//Test with all white r = g = b = 1.0f
for (int i = 0; i < TEXTURE_WIDTH * TEXTURE_HEIGHT * 3; i++)
{
texturePixels[i] = 1.0f;
}

GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);


// Load texture
GLuint tex;
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0, GL_RGB, GL_FLOAT, texturePixels);

GLuint vbo;
glGenBuffers(1, &vbo);

// Create an element array
GLuint ebo;
glGenBuffers(1, &ebo);

glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(screen2DVertices), screen2DVertices, GL_STATIC_DRAW);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(screen2DIndices), screen2DIndices, GL_STATIC_DRAW);


// Specify the layout of the vertex data
GLint posAttrib = glGetAttribLocation(screenShader.Program, "position");
glEnableVertexAttribArray(posAttrib);
glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void*)0);

GLint texAttrib = glGetAttribLocation(screenShader.Program, "texcoord");
glEnableVertexAttribArray(texAttrib);
glVertexAttribPointer(texAttrib, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void*)(3 * sizeof(GLfloat)));

while (!glfwWindowShouldClose(window))
{
glfwPollEvents();

glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);

screenShader.Use();
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)0);

glfwSwapBuffers(window);
}

Shaders:


//---------------------------Vertex Shader------------------------------------------
#version 330 core

in vec3 position;
in vec2 texcoord;

out vec2 Texcoord;

void main()
{
Texcoord = texcoord;
gl_Position = vec4(position, 1.0);
}

//---------------------------Fragment Shader------------------------------------------
#version 330 core

in vec2 Texcoord;
out vec4 outColour;
uniform sampler2D tex;

void main()
{
outColour = texture(tex, Texcoord) * vec4(1.0f);
}
Edited by Promit

Share this post


Link to post
Share on other sites

How does this work at all with (void*)0?

glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (void*)0);

The program is expecting a 24 bit image so check that.

Share this post


Link to post
Share on other sites

The glDrawElements calls are in no way related to texture as one can draw untextured primitives. However, I am not seeing in the code you posted, how you are notifying the fragment shader as to which texture unit, the sampler's texture is in. Hate to be sarcastic here, but it does not magically appear in the shader because you created one and bind it. Usually, you use glUniform1i, specify the attribute location ( of the sampler ) retrieved from the compile program or specified in the shader  along with the texture/sampler unit the texture was bound to.

Share this post


Link to post
Share on other sites

Few hints:

 

If the rendering is all black, that generally means that the texture has not been correctly created or used (does glIsTexture gives the right result ?)

If the rendering has some color which looks like a color from the image (some kind of red if the image is redish for example), then the issue is most certainly related to texture coordinates.

 

Also try to change the underlying type the texture uses. Use GL_UNSIGNED_BYTE for start. Try also to use a different internal format. GL_RGB8 would do the thing.

Share this post


Link to post
Share on other sites

Also a very common gotcha for this is mipmaps. If you upload the texture but don't create mipmaps, and it samples from the blank mipmaps you just get black.

Share this post


Link to post
Share on other sites

Thank you all so much for the suggestions, it is REALLY appreciated! lawnjelly you are my saviour, I added mipmaps and immediately got a white square (they were not part of the tutorial that I was using as a reference so I didn't realise they were so important). cgrant I thought that you had found the problem but strangely it works even without sending the uniform location, not sure why.

Thanks again to everyone!

Share this post


Link to post
Share on other sites

You want to make sure the first time you bind a texture at creation that you setup the glTexParameter  calls that describe your sampling types for minification and magnification such as anisotropic filtering or simple point sampling.

Share this post


Link to post
Share on other sites

Also changing the value of glClearColor to anything but black lets you know if there is any rendering direction ahead of you at least.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this