1

I'm learning texture mapping using this tutorial. I tried to modify some of the code to see if it is still working.

I wanted to remove the EBO part and to use purely VBO with VAO. In order to test texture mapping only, I also deleted the color indices.

So the code now looks like this:

const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;

int main()
{
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
    if (window == NULL)
    {
        std::cout << "Failed to create GLFW window" << std::endl;
        glfwTerminate();
        return -1;
    }
    glfwMakeContextCurrent(window);

    glewInit();

    // build and compile our shader zprogram
    // ------------------------------------
    int vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
    glCompileShader(vertexShader);
    // check for shader compile errors
    int success;
    char infoLog[512];
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
    if (!success)
    {
        glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
        std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
    }
    // fragment shader
    int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
    glCompileShader(fragmentShader);
    // check for shader compile errors
    glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
    if (!success)
    {
        glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
        std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
    }
    // link shaders
    int shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vertexShader);
    glAttachShader(shaderProgram, fragmentShader);
    glLinkProgram(shaderProgram);
    glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
    if (!success) {
        glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
        std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
    }
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);

    // set up vertex data (and buffer(s)) and configure vertex attributes
    // ------------------------------------------------------------------
    float vertices[] = {
        // positions        // texture coords
        0.5f, -0.5f, 0.0f, 1.0f, 0.0f, // bottom right
        0.5f,  0.5f, 0.0f, 1.0f, 1.0f, // top right
        -0.5f,  0.5f, 0.0f, 0.0f, 1.0f  // top left 
    };

    unsigned int VBO, VAO;
    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);

    glBindVertexArray(VAO);

    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    // position attribute
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);
    // texture coord attribute
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
    glEnableVertexAttribArray(1);

    // load and create a texture 
    // -------------------------
    unsigned int texture1;
    // texture 1
    // ---------
    glGenTextures(1, &texture1);
    glBindTexture(GL_TEXTURE_2D, texture1);
    // set the texture wrapping parameters
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);   // set texture wrapping to GL_REPEAT (default wrapping method)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    // set texture filtering parameters
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    // load image, create texture and generate mipmaps
    CImage img_handler;
    img_handler.Load(_T("texture.tif"));
    texture_w = img_handler.GetWidth();
    texture_h = img_handler.GetHeight();
    texture = new byte[texture_w * texture_h * 3];
    int cnt = 0;
    for (int y = 0; y < texture_h; y++) {
        for (int x = 0; x < texture_w; x++) {
            COLORREF c = img_handler.GetPixel(x, y);
            texture[cnt++] = GetRValue(c);
            texture[cnt++] = GetGValue(c);
            texture[cnt++] = GetBValue(c);
        }
    }
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, texture_w, texture_h, 0, GL_RGB, GL_UNSIGNED_BYTE, texture);
    glGenerateMipmap(GL_TEXTURE_2D);

    // tell opengl for each sampler to which texture unit it belongs to (only has to be done once)
    // -------------------------------------------------------------------------------------------
    glUseProgram(shaderProgram);
    // either set it manually like so:
    glUniform1i(glGetUniformLocation(shaderProgram, "texture1"), 0);

    // render loop
    // -----------
    while (!glfwWindowShouldClose(window))
    {
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        // bind textures on corresponding texture units
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, texture1);

        // render container
        glUseProgram(shaderProgram);
        glBindVertexArray(VAO);
        glDrawArrays(GL_TRIANGLES, 0, 3);
        //glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

        // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
        // -------------------------------------------------------------------------------
        glfwSwapBuffers(window);
        glfwPollEvents();
    }

    // optional: de-allocate all resources once they've outlived their purpose:
    // ------------------------------------------------------------------------
    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(1, &VBO);

    // glfw: terminate, clearing all previously allocated GLFW resources.
    // ------------------------------------------------------------------
    glfwTerminate();
    return 0;
}

shaders:

const char *vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"layout (location = 1) in vec2 aTexCoord;\n"
"out vec2 TexCoord;\n"
"uniform mat4 u_mvp;\n"
"void main()\n"
"{\n"
"   TexCoord = aTexCoord;\n"
"   gl_Position = u_mvp * vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"}\0";

const char *fragmentShaderSource = "#version 330 core\n"
"in vec2 TexCoord;\n"
"out vec4 FragColor;\n"
"uniform sampler2D tex_sampler;\n"
"void main()\n"
"{\n"
"   FragColor = texture(tex_sampler, TexCoord);\n"
"}\n\0";

However, the texture is not working, with only a single color displayed. (I used microsoft CImage library, so the above code will only run on Windows, but it can be replaced by other code to work on other platform)

How can I fix this?

RenderDoc output:

enter image description here

Rabbid76
  • 202,892
  • 27
  • 131
  • 174
AccM
  • 53
  • 5
  • The 2nd and the 3rd texture coordinate are identically! (`1.0f, 1.0f` ) – Rabbid76 Jan 22 '19 at 09:13
  • @Rabbid76 Yes that's a mistake. I corrected the value and tried another time, still not working... Any other suggestion? – AccM Jan 22 '19 at 09:27
  • 2
    @AccM I do not see any `glEnable(GL_TEXTURE_2D);`, I do not see the shaders used nor the GLSL logs result so I can only guess ... – Spektre Jan 22 '19 at 10:03
  • @Spektre Sorry I forgot to paste my shader code. I've added them. The original tutorial code doesn't have `glEnable(GL_TEXTURE_2D)` and it worked. I tried to add this line of code but it didn't help.. – AccM Jan 22 '19 at 16:19
  • Have you tried taking a capture using a tool such as RenderDoc? You could look at the pipeline for your draw call and try to see if anything seems out of place (like making sure your TexCoord is correct after the VS has run, and that your texture is bound properly). – Borgleader Jan 22 '19 at 16:27
  • @Borgleader I tried RenderDoc last night, but it seems there's no texture. I'll have another try.. – AccM Jan 22 '19 at 16:31
  • @AccM I would add the `glEnable(GL_TEXTURE_2D)` just before the rendering. What are GLSL logs saying? I see you encoded shaders directly into source code so there is a possibility your compiler is not using ASCII but UNICODE instead which might prevent you from compiling/linking properly (that is why I asked for the logs there you would see such thing directly) . Otherwise the shaders looks OK ... – Spektre Jan 22 '19 at 16:31
  • @Spektre I add `glEnable(GL_TEXTURE_2D)` before `glActiveTexture(GL_TEXTURE0)` but nothing happened. I tried to use RenderDoc to see the texture, but texture input is a "pink" image (even when texture is correctly drawn when I switched to the working code). Then I see the "Pipeline Status" tab and I pasted the screenshot above. Does this mean `aTexCoord` is not used? And do you know what is `attribute`? – AccM Jan 22 '19 at 16:57
  • 2
    **1)** If you don't use a MVP matrix, remove it from VShader. **2)** To pass the *active texture* to shader use `tex_sampler` (the name in shader) and not `texture1` in the call `glUniform1i(...)` – Ripi2 Jan 22 '19 at 17:04
  • OpenGL have their own coordinates for textures. You may expect it is working like in pixel array matrix, i.e. top-left corner is 0 - for x, and 0 for y when x - growing left and y - grown down. But for OpenGL it is bottom left corner, an x - growing left, and y growing up. Looks like you have only one texture, so plase check your uv texture mappings, or simply mirror your image pixels up-down before transferring it texture. Please note, that texture width and height - must be power of 2. I.e. 64x64, 256x256, 512x512 etc. – Victor Gubin Jan 22 '19 at 17:07
  • This [article](https://learnopengl.com/Getting-started/Textures) may help. [Example code](https://github.com/JoeyDeVries/LearnOpenGL/tree/master/src/1.getting_started/4.1.textures) – Victor Gubin Jan 22 '19 at 17:12
  • @VictorGubin Power of two is not required anymore since at least 2006. – Ripi2 Jan 22 '19 at 17:17
  • The uniform `uniform mat4 u_mvp;` is never set. So alle fields are default initialized by 0! At least you have to set the identity matrix. Try `gl_Position = vec4(aPos.xyz, 1.0);` for debug reasons. – Rabbid76 Jan 22 '19 at 17:30
  • @AccM the image you added suggest you got layout location miss match for texture attributes ... location 2 is disabled but shader is using it and expecting texture coordinates there and the data is passed by location 1 or the other way arround. That might suggest your shader did not compile/link or is not used correctly and fixed function is used instead which might have different location setup ... so again what is in the shader logs? `glGetShaderInfoLog` – Spektre Jan 22 '19 at 17:30
  • @AccM see [complete GL+GLSL+VAO/VBO C++ example](http://stackoverflow.com/a/31913542/2521214) and look for the `glGetShaderInfoLog` usage – Spektre Jan 22 '19 at 17:32
  • Thanks guys.. I've found the problem using RenderDoc. I didn't change the attribute location in the shader and now it works! – AccM Jan 22 '19 at 17:34

0 Answers0