0
votes

Beforehand, sorry for a lot of posted code. I will try to be as straightforward as possible.

My texture is 4x4 texture image in bmp format (if someone interested here it is ->4x4 texture image). And as a result of mapping i get color of top leftpixel (0.0, 1.0) (i checked it, it is always color of top left pixel) and my triangle color results in color of that pixel, which is white. enter image description here I tried changing GL_NEARESTtoGL_LINEAR in GL_TEXTURE_MAG_FILTER

glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

and i get bottom right pixel (1.0, 0.0), which is some kind of green: enter image description here I am loading texture using stb_image. So in my Texture.cpp:

Texture::Texture(const std::string& fileName)
{
    int width, height, numComponents;
    unsigned char* imageData = stbi_load(fileName.c_str(), &width, &height, &numComponents, 4);
    if (imageData == NULL)
    {
        std::cerr << "Error: Texture load failed for texture: " << fileName << std::endl;
    }

    glEnable(GL_TEXTURE_2D);
    glGenTextures(1, &_texture);

    glBindTexture(GL_TEXTURE_2D, _texture);

    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);

    stbi_image_free(imageData);
}
Texture::~Texture(void)
{
    glDeleteTextures(1, &_texture);
}

void Texture::Bind(unsigned int unit)
{
    assert(unit >= 0 && unit <= 31);
    glActiveTexture(GL_TEXTURE0 + unit);
    glBindTexture(GL_TEXTURE_2D, _texture);
}

In my vertex shader:

#version 150

in vec3 position;
in vec2 texCoord;

out vec2 texCoord0;

void main(void)
{
    texCoord0 = texCoord;
    gl_Position = vec4(position, 1.0);
}

In my fragment shader:

#version 150

in vec2 textCoord0;
uniform sampler2D texture;

void main(void)
{
    gl_FragColor = texture2D(texture, textCoord0);
}

In my main.cpp

#include <iostream>
#include <GL/glew.h>
#include "Display.h"
#include "Shader.h"
#include "Mesh.h"
#include "Texture.h"
int main(int argc, char** argv)
{
    Display display(800, 600, " ");
    display.Clear(0.0f, 0.15f, 0.3f, 1.0f);
    Vertex vertices[] = {
                            Vertex(glm::vec3(-1.0f, -1.0f, 0.0f), glm::vec2(0.0f, 0.0f)),
                            Vertex(glm::vec3( 0.0f,  1.0f, 0.0f), glm::vec2(0.5f, 1.0f)),
                            Vertex(glm::vec3( 1.0f, -1.0f, 0.0f), glm::vec2(1.0f, 0.0f))
    };
    Texture texture("./res/a.bmp");
    Shader shader("./res/testShader");
    Mesh mesh(vertices, sizeof(vertices) / sizeof(vertices[0]));
    while (display.IsClosed() != true)
    {
        shader.Bind();
        texture.Bind(0);
        mesh.Draw();
        display.Update();
    }
    return 0;
} 

In Mesh.cpp i am splitting Vertices attributes (glm::vec3 _position and glm::vec2 _texture) into 2 stl vectors and using 2 buffers ("0" - for position of vertex and "1" - for texture) :

Mesh::Mesh(Vertex* vertices, unsigned int numVertices, GLenum usage)
{
    _drawCount = numVertices;

    glGenVertexArrays(1, &_vertexArrayObject);

    glBindVertexArray(_vertexArrayObject);

    std::vector<glm::vec3> positions;
    std::vector<glm::vec2> texCoords;

    positions.reserve(numVertices);
    texCoords.reserve(numVertices);

    for (unsigned int i = 0; i < numVertices; ++i)
    {
        positions.push_back(*vertices[i].Position());
        texCoords.push_back(*vertices[i].TexCoord());
    }
    glGenBuffers(NUM_BUFFERS, _vertexArrayBuffers);


    glBindBuffer(GL_ARRAY_BUFFER, _vertexArrayBuffers[POSITION_VB]);
    glBufferData(GL_ARRAY_BUFFER, numVertices * sizeof(positions[0]), positions.data(), usage);

    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);


    glBindBuffer(GL_ARRAY_BUFFER, _vertexArrayBuffers[TEXCOORD_VB]);
    glBufferData(GL_ARRAY_BUFFER, numVertices * sizeof(texCoords[0]), texCoords.data(), usage);

    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);


    glBindVertexArray(0);
}


Mesh::~Mesh(void)
{
    glDeleteVertexArrays(1, &_vertexArrayObject);
}

void Mesh::Draw(GLenum mode)
{
    glBindVertexArray(_vertexArrayObject);
    glDrawArrays(mode, 0, _drawCount);
    glBindVertexArray(0);
}

In Shader.cpp i binded atributes like this:

glBindAttribLocation(_program, 0, "position");
glBindAttribLocation(_program, 1, "texCoord");

----------------------------EDIT--------------------------------- After changing vertex shader to:

#version 330 core

layout (location = 0) in vec3 position;
layout (location = 1) in vec2 texCoord;

out vec2 TexCoord;

void main()
{
    gl_Position = vec4(position, 1.0f);
    TexCoord = texCoord;
}

and fragment shader to:

#version 330 core
in vec2 TexCoord;

out vec4 color;

uniform sampler2D ourTexture;

void main()
{
    color = texture(ourTexture, TexCoord);
}

texture is mapped correctly.

But i still want to know why my first solution doesn't work.

1
It seems to me that your second glVertexAttribPointer call is missing an offset (the last parameter) the UV data is after the position data. If I'm right you're reading the posisiton.xy as UVs. (You can try running this in renderdoc to see what's coming out of the vertex shader and confirm/infirm my diagnosis)Borgleader
@Borgleader i thought the idea of using more then 1 buffer is to split data and then send it to GPU by portions? Or am i wrong and it doesn't work that way? Because then i don't know what offset i should set. After your edit i will try use renderdoc now and let you know of my resultsEvil Penguin
Oh nvm, I missed that part, I saw your initial array of vertices and missed the two std::vectors. (According to this answer the initialization of your VAO seems correct)Borgleader
What does it look like if you color the triangle using the texcoord(gl_FragColor=vec4(texcoord,0,0,1);)?LJᛃ
Maybe not related, but your glTexParameterf should be glTexParameteri.SurvivalMachine

1 Answers

1
votes

But i still want to know why my first solution doesn't work.

Because you're using

#version 330 core

and texture2D is deprecated since version 130

The shader compiler should've warned or errored about that. Check your shader logs via glGetShaderInfoLog and glGetProgramInfoLog.