OpengGl 4.2 Texture Mapping not displaying
Asked Answered
L

1

0

I'm using cross-platform libraries (glfw, glew, glm) to make a simple texture mapping OpenGl Sample Program. It just takes an image from my computer, which is a 512 x 512 PNG, and is supposed to map it to a square I have displaying. The Program without the texture mapping works great and the square is visible. With the texture mapping Nothing is Visible, could you help me find where the mistake is?

Edit: Perhaps I'm missing a binding or something within my "do" drawing-to-the-frame loop?

Main Program (LoadShaders and stbi_Image are externally defined correctly)

if( !glfwInit() )
{
    fprintf( stderr, "Failed to initialize GLFW\n" );
    return -1;
}

glfwWindowHint(GLFW_SAMPLES, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_COMPAT_PROFILE);

// Open a window and create its OpenGL context
GLFWwindow* window = glfwCreateWindow (640, 480, "Hello Triangle", NULL, NULL);
if(!window)
{
    fprintf( stderr, "Failed to open GLFW window. If you have an Intel GPU, they are
              not 3.3 compatible. Try the 2.1 version of the tutorials.\n" );
    glfwTerminate();
    return -1;
}

glfwMakeContextCurrent(window);

// Initialize GLEW
glewExperimental = GL_TRUE; // Needed for core profile
GLenum err = glewInit();
if (err != GLEW_OK) {
  fprintf(stderr, "Failed to initialize GLEW\n");
  fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
  return -1;
}


const GLubyte* renderer = glGetString (GL_RENDERER); // get renderer string
const GLubyte* version = glGetString (GL_VERSION); // version as a string
printf ("Renderer: %s\n", renderer);
printf ("OpenGL version supported %s\n", version);

// tell GL to only draw onto a pixel if the shape is closer to the viewer
glEnable (GL_DEPTH_TEST); // enable depth-testing
glDepthFunc (GL_LESS); // depth-testing interprets a smaller value as "closer"


 // Ensure we can capture the escape key being pressed below
glfwSetInputMode(window,GLFW_STICKY_KEYS,GL_TRUE );

// Create and compile our GLSL program from the shaders
GLuint programID = LoadShaders( "SimpleVertexShader.vertexshader", 
"SimpleFragmentShader.fragmentshader" );

GLuint MatrixID = glGetUniformLocation(programID, "MVP");

    // Projection matrix : 45° Field of View, 4:3 ratio, display range : 0.1 unit <-> 
    // 100 units
glm::mat4 Projection = glm::perspective(45.0f, 4.0f / 3.0f, 0.1f, 100.0f);
// Camera matrix
glm::mat4 View       = glm::lookAt(
                            glm::vec3(4,3,3), // Camera is at (4,3,3), in World Space
                            glm::vec3(0,0,0), // and looks at the origin
                            glm::vec3(0,1,0)  // Head is up
                       );
// Model matrix : an identity matrix (model will be at the origin)
glm::mat4 Model      = glm::mat4(1.0f);
// Our ModelViewProjection : multiplication of our 3 matrices
glm::mat4 MVP        = Projection * View * Model; 


unsigned char* image_data;
int x, y, n;
char* file_name;
file_name = "/home/syk435/Pictures/texture_sample.png";
int force_channels = 4;
image_data = stbi_load(file_name, &x, &y, &n, force_channels); 

if (!image_data)
{
       fprintf (stderr, "ERROR: could not load %s\n", file_name);
}

//check if not normal dims
if (x & (x - 1) != 0 || y & (y - 1) != 0)
{
        fprintf (stderr, "WARNING: texture %s is not power-of-2 dimensions\n",
file_name);
}
//invert to norm
int width_in_bytes = x * 4;
unsigned char *top = NULL;
unsigned char *bottom = NULL;
unsigned char temp = 0;
int half_height = y / 2;

for (int row = 0; row < half_height; row++) {
top = image_data + row * width_in_bytes;
bottom = image_data + (y - row - 1) * width_in_bytes;
        for (int col = 0; col < width_in_bytes; col++)
        {
               temp = *top;
               *top = *bottom;
               *bottom = temp;
               top++;
               bottom++;
        }
}


static const GLfloat g_vertex_buffer_data[] = {
    -0.75f,-0.75f,0.0f,
    -0.75f, 0.75f,0.0f,
     0.75f,-0.75f,0.0f,
     0.75f, 0.75f,0.0f,
    -0.75f, 0.75f,0.0f,
     0.75f,-0.75f,0.0f,
   };

GLuint vertexbuffer;
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data,   
GL_STATIC_DRAW);

// Dark blue background
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

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

//texture stuff
unsigned int tex = 0;
glGenTextures (1, &tex);
glActiveTexture (GL_TEXTURE0);
glBindTexture (GL_TEXTURE_2D, tex);
GLuint TextureID  = glGetUniformLocation(programID, "basic_texture");
glTexImage2D (
  GL_TEXTURE_2D,
  0,
  GL_RGBA,
  x,
  y,
  0,
  GL_RGBA,
  GL_UNSIGNED_BYTE,
  image_data
);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

float texcoords[] = {
  0.0f, 0.0f,
  0.0f, 1.0f,
  1.0, 0.0,
  1.0, 1.0,
  0.0, 1.0,
  1.0, 0.0
};

unsigned int vt_vbo;
glGenBuffers (1, &vt_vbo);
glBindBuffer (GL_ARRAY_BUFFER, vt_vbo);
int dimensions = 2; // 2d data for texture coords
int length = 6; // 6 vertices

glBufferData (
  GL_ARRAY_BUFFER,
  dimensions * length * sizeof (float),
  texcoords,
  GL_STATIC_DRAW
);

   do{

    // Clear the screen
    glClear( GL_COLOR_BUFFER_BIT );

    // Use our shader
    glUseProgram(programID);
    glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, tex);
    // Set our "myTextureSampler" sampler to user Texture Unit 0
    glUniform1i(TextureID, 0);

    // 1rst attribute buffer : vertices
    glEnableVertexAttribArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);

    glVertexAttribPointer(
        0,                  // attribute 0
        3,                  // size
        GL_FLOAT,           // type
        GL_FALSE,           // normalized?
        0,                  // stride
        (void*)0            // array buffer offset
    );


    // note: this is your existing VAO
    glEnableVertexAttribArray(1);
    glBindBuffer (GL_ARRAY_BUFFER, vt_vbo);
    // note: I assume that vertex positions are location 0
    dimensions = 2; // 2d data for texture coords
    glVertexAttribPointer (1, dimensions, GL_FLOAT, GL_FALSE, 0, NULL);

    // Draw the triangle !
    glDrawArrays(GL_TRIANGLES, 0, 6); // 3 indices starting at 0 -> 1 triangle

    glDisableVertexAttribArray(0);
    glDisableVertexAttribArray(1);

    // Swap buffers
    glfwSwapBuffers(window);

} // Check if the ESC key was pressed or the window was closed
while( glfwGetKey( window, GLFW_KEY_ESCAPE ) != GLFW_PRESS && window!=NULL );

// Close OpenGL window and terminate GLFW
glfwTerminate();

// Cleanup VBO
glDeleteBuffers(1, &vertexbuffer);
glDeleteBuffers(1, &vt_vbo);
glDeleteProgram(programID);
glDeleteTextures(1, &TextureID);
glDeleteVertexArrays(1, &vao);

return 0;

VertexShader:

#version 420

// Input vertex data, different for all executions of this shader.
layout (location = 0) in vec3 vertexPosition_modelspace;

layout (location = 1) in vec2 vt; // per-vertex texture co-ords

out vec2 texture_coordinates;

uniform mat4 MVP;

void main(){

   gl_Position = MVP * vec4(vertexPosition_modelspace,1);

   texture_coordinates =  vt;
}

FragmentShader:

#version 420

// Ouput data
//texture stuff
in vec2 texture_coordinates;

uniform sampler2D basic_texture;

out vec3 frag_colour;

void main()
{

frag_colour = texture2D(basic_texture, texture_coordinates).rgb;

}
Lombroso answered 31/12, 2013 at 11:57 Comment(10)
If you are drawing to the default framebuffer, the texture has a signature of RGBA. Im not quite sure if this is an issue, but have you tried a vec4 as your fragment shader output?Hoopen
Thank you for your reply, but yeah I tried that to no avail.Lombroso
Have you considered using glGetError in your setup code to at least determine that your texture is correctly loaded? Why is frag_colour a vec3 and not a vec4?Verity
working with setting up glGetError right now actually, thanks for the suggestion-will report back with results if i can't figure it out! frag_colour was set to vec3 just while I was playing around with it, since vec4 had no output either.Lombroso
No error flags were thrown, so I'm still at a loss for what my error is. On a sidenote, I found a really nice setup for glgeterror on this site blog.nobel-joergensen.com/2013/01/29/…Lombroso
Do not use texture2D (...) in a GLSL 4.20 shader, that is plain wrong. Beginning with GLSL 1.30, things like texture1D, texture2D, textureCube, etc. were all replaced with overloads of more fundamental texture lookup functions. So what was left was texture (...), textureProj (...), textureLod (...), textureOffset (...), etc. GLSL knows the dimensionality of the texture simply by the type of sampler and the coordinates you pass it.Urias
You are also using VAOs completely wrong in this situation. You do not have to enable / disable arrays and setup your vertex attrib pointers every time you draw - you have a VAO for this. Just do that when you create your VAO, bind the VAO before you draw and you're golden.Urias
I implemented those changes exactly as you said and have the VAO being bound every time before drawing, but still nothing shows. Do you perchance see any other glaringly obvious mistake? I think it's something else, like not enabling some key settingLombroso
@salamisalem: Well, you are also enabling depth testing and I do not see any code where you ask for a pixel format that actually has a depth buffer, much less clear the buffer. I have never used GLFW, so I do not know the exact steps you need to do to request a depth buffer, but my best guess is that it is a window hint.Urias
You are exactly correct, I was not enabling depth testing correctly.My code renders now, Thank you very much!Lombroso
M
0

For those who don't want to search the comments...

Either remove these 2 lines (i.e. do not enable depth test).

glEnable (GL_DEPTH_TEST); // enable depth-testing
glDepthFunc (GL_LESS); // depth-testing interprets a smaller value as "closer"

Or with depth buffer enabled, clear the depth buffer at the start of the do while loop

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

(The answer is in the comment below the question from Andon Coleman. As I'm reading Anton's OpenGL 4 Tutorials I thought I'll practice a bit and see if I could get the code working. Doing either of the above displayed the texture.)

Melonie answered 1/1, 2014 at 13:58 Comment(2)
I'm pretty sure you also need glClearDepth(1.0f); in the do loop to clear the depth buffer.Lombroso
Yes, or e.g. glClearBufferfv(GL_COLOR, 0, red);Melonie

© 2022 - 2024 — McMap. All rights reserved.