1
votes

I'm trying to texture the ground with grass. Would someone mind looking through my steps to get a 2D texture to show up in 3D space? I haven't had any luck with online tutorials.

Here is my steps:

1) Call the sprite class initialization to set the vertex coordinates and uv data

void Sprite::init(vec3 bottomleft, vec3 topLeft, vec3 topRight, vec3 bottomRight, std::string texturePath)
{

    _texture = ImageLoader::loadPNG(texturePath);

    _points = { bottomleft.x, bottomleft.y, bottomleft.z, topLeft.x, topLeft.y, topLeft.z, topRight.x, topRight.y, topRight.z, topRight.x, topRight.y, topRight.z, bottomRight.x, bottomRight.y, bottomRight.z, bottomleft.x, bottomleft.y, bottomleft.z };
    _uv = { 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f };

}

I use the uniform sampler and activate the texture

    //draw ground texture
    glUniform1i(samplerLocation, 0);
    glActiveTexture(GL_TEXTURE0);
    _grassTexture.draw();

The draw function is implemented as follows, which puts the data in the buffer and draws the triangle:

    void Sprite::draw()
    {
        if (_vboID == 0)
        {
            glGenBuffers(1, &_vboID);
        }

        glBindTexture(GL_TEXTURE_2D, _texture.id);

        glBindBuffer(GL_ARRAY_BUFFER, _vboID);
        glBufferData(GL_ARRAY_BUFFER, _points.size() * sizeof(float) + _uv.size() * sizeof(float), nullptr, GL_STATIC_DRAW);
        glBufferSubData(GL_ARRAY_BUFFER, 0, _points.size() * sizeof(float), &_points.front());
        glBufferSubData(GL_ARRAY_BUFFER, _points.size() * sizeof(float), _uv.size() * sizeof(float), &_uv.front());

        glEnableVertexAttribArray(0);
        glEnableVertexAttribArray(1);

        //position attribute pointer
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, &_points.front());

        //uv attribute pointer
        glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, &_uv.front());

        glDrawArrays(GL_TRIANGLES, 0, 6);

        glDisableVertexAttribArray(0);
        glDisableVertexAttribArray(1);

        glBindBuffer(GL_ARRAY_BUFFER, 0);
    }

The vertex shader:

#version 400

in vec4 vertexPosition;
in vec2 vertexUV;

out vec4 fragmentColor;
out vec2 fragmentUV;

uniform mat4 MVP;
uniform vec4 COLOR;

void main()
{
    gl_Position = MVP * vertexPosition;
    fragmentColor = COLOR;
    fragmentUV = vec2(vertexUV.x, 1.0 - vertexUV.y);
}

and fragment shader:

#version 400

in vec4 fragmentColor;
in vec2 fragmentUV;

out vec4 fragColor;

uniform sampler2D SAMPLER;

void main()
{
    vec4 textureColor = texture(SAMPLER, fragmentUV);
    fragColor = textureColor * fragmentColor;
}

At this point, nothing displays in the screen. I do know that the textureColor in the fragment shader is green, so it appears the uniform is being set correctly. My best guess is that I'm either missing a texture initialization step or am not filling the buffer correctly.

1

1 Answers

1
votes

I think there's a problem with the pointer parameter in your calls to glVertexAttribPointer. You're passing the address of your _points and _uv arrays, but you should be passing the offset relative to the base of your vbo.

Try:

    //position attribute pointer
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);

    //uv attribute pointer
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid*)(_points.size() * sizeof(float)));