2

I have been having difficulty texturing a plane I made. The first quad on the plane is textured properly, but the rest of the plane then only seems to use the first pixel of the texture so it all ends up as a solid color. It seems to work properly if I make one giant plane and just texture that, but when I try to break up the plane into sections I keep getting this issue. I’m assuming I am missing something as far as the coordinates go, but from my understanding I thought they were always supposed to be between 0 and 1? Any help is appreciated.

[![enter image description here][1]][1]

Texture coordinates

GLfloat grassTexCoords[]
{
    0.0f, 0.0f,
    0.0f, 1.0f,
    1.0f, 0.0f,
    1.0f, 0.0f,
    0.0f, 1.0f,
    1.0f, 1.0f
};

Setting up VAO

GLuint makePlane()
{
    float size = 5;
    for (int i = -5; i < 5; ++i)
    {
        for (int j = -5; j < 5; ++j)
        {
            verts.push_back({ glm::vec3((i * size), -11.f, (j * size)) });
            verts.push_back({ glm::vec3((i * size), -11.f, (j * size) + size) });
            verts.push_back({ glm::vec3((i * size) + size, -11.f, (j * size)) });

            verts.push_back({ glm::vec3((i * size) + size, -11.f, (j * size)) });
            verts.push_back({ glm::vec3((i * size), -11.f, (j * size) + size) });
            verts.push_back({ glm::vec3((i * size) + size, -11.f, (j * size) + size) });
        }
    }

    GLuint vbo;
    glGenBuffers(1, &vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glBufferData(GL_ARRAY_BUFFER, verts.size() * sizeof(VertexPos), verts.data(), GL_STATIC_DRAW);

    GLuint vboTex;
    glGenBuffers(1, &vboTex);
    glBindBuffer(GL_ARRAY_BUFFER, vboTex);
    glBufferData(GL_ARRAY_BUFFER, 2 * 6 * sizeof(GLfloat), &grassTexCoords, GL_STATIC_DRAW);

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

    glEnableVertexAttribArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);

    glEnableVertexAttribArray(1);
    glBindBuffer(GL_ARRAY_BUFFER, vboTex);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, NULL);

    return vao;
}

Rendering

void render()
{
    glViewport(0, 0, window.getSize().x, window.getSize().y);
    glClearColor(.4f, .4f, .4f, 1.f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    //1st program
    glUseProgram(sphereProgram);
    glEnable(GL_CULL_FACE);
    glEnable(GL_DEPTH_TEST);
    glBindVertexArray(vao);
    glDrawArrays(GL_TRIANGLES, 0, objPointCount);

    //2nd program
    glFrontFace(GL_CCW);
    glDepthMask(GL_FALSE);
    glUseProgram(cubeProgram);
    glBindTexture(GL_TEXTURE_CUBE_MAP, textureID);
    glBindVertexArray(cubeVao);
    glDrawArrays(GL_TRIANGLES, 0, 36);
    glDepthMask(GL_TRUE);

    //3rd program
    glFrontFace(GL_CCW);
    glDisable(GL_CULL_FACE);
    glEnable(GL_TEXTURE_2D);
    sf::Texture::bind(&grassTex);
    glUseProgram(planeProgram);
    glBindVertexArray(planeVao);
    glDrawArrays(GL_TRIANGLES, 0, verts.size());
    //-----------------------

    window.display();
    //window.setFramerateLimit(FPS);
    window.setVerticalSyncEnabled(true);
}

Vertex shader

#version 410

layout (location = 0) in vec3 vertexPos;
layout (location = 1) in vec2 texCoords;

uniform mat4 view, proj;

out vec3 posEye;
out vec2 coords;

void main()
{
    coords = texCoords; //repeat texture over plane
    gl_Position = proj * view * vec4(vertexPos, 1.0);

    posEye = (view * vec4(vertexPos, 1.0)).xyz;
}

Fragment shader

#version 410

in vec3 posEye;
in vec2 coords;
out vec4 fragColor;

uniform sampler2D tex;

//fog
const vec3 fogColor = vec3(0.2, 0.2, 0.2);
const float minFogRad = 300;
const float maxFogRad = 900;

void main()
{
    vec4 texture = texture2D(tex, coords);
    fragColor = texture;

    float distance = length(-posEye);
    float fogFactor = (distance - minFogRad) / (maxFogRad - minFogRad);
    fogFactor = clamp(fogFactor, 0.0, 1.0);

    fragColor.rgb = mix(fragColor.rgb, fogColor, fogFactor);
}
  • It looks like you tried to post an image attachment. Can you try that again? It might help others to answer the question more easily. – Matt Fichman Sep 21 '15 at 20:17

2 Answers2

1

The problem here is, that texture coordinates are just supplied for the first quad (for the first 6 vertices). All other vertices seem to get [0,0], which causes them to only read the top-left texel. The solution here is to provide enough texture coordinates for all of the vertices.

Texture coordinates in general are not necessarily between 0 and 1. One can specify how values outside of [0,1] should be treated by setting GL_TEXTURE_WRAP_[RST].

Note, that not supplying enough data in a VBO can lead to crashes (depends on the driver) when OpenGL tries to read outside the buffer.

BDL
  • 21,052
  • 22
  • 49
  • 55
1

You are using a GL_ARRAY_BUFFER which stores per vertex data.

The 2 and GL_FLOAT arguments in glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, NULL); are declaring that you have 2 floats in vboTex per vertex but you haven't done this, you have 2 floats for each vertex in the first quad only.

In the same way, the 3 and GL_FLOAT arguments in glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL); are declaring that you have 3 floats in vbo per vertex which you have done.

The easiest fix for this is to create a bigger GL_ARRAY_BUFFER which repeats the same texture coordinates for every quad.

Gyan aka Gary Buyn
  • 12,242
  • 2
  • 23
  • 26