现代OpenGL发布纹理平面



我一直有困难纹理我做的飞机。平面上的第一个四边形是正确的纹理,但平面的其余部分似乎只使用纹理的第一个像素,所以它最终都是纯色。如果我制作一个巨大的平面并只是纹理,它似乎可以正常工作,但当我试图将平面分解成部分时,我一直遇到这个问题。我假设我遗漏了一些关于坐标的东西,但是根据我的理解,我认为它们应该总是在0到1之间?如有任何帮助,不胜感激。

[![1]][1]

纹理坐标

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
};

设置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;
}
渲染

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);
}

顶点着色器

#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;
}

片段着色器

#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);
}

这里的问题是,纹理坐标只是为第一个四边形(为前6个顶点)提供的。所有其他顶点似乎都得到[0,0],这导致它们只读取左上角的文本。这里的解决方案是为所有顶点提供足够的纹理坐标。

纹理坐标通常不一定在0和1之间。可以通过设置GL_TEXTURE_WRAP_[RST]来指定如何处理[0,1]之外的值。

注意,当OpenGL试图读取缓冲区外的数据时,在VBO中不提供足够的数据可能导致崩溃(取决于驱动程序)。

您正在使用的GL_ARRAY_BUFFER存储每个顶点数据。

2GL_FLOAT参数在glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, NULL);中声明您在vboTex 每个顶点中有2个浮点数,但您还没有这样做,您在第一个四象素中每个顶点有2个浮点数。

同样,glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);中的3GL_FLOAT参数声明您在vbo 每个顶点中有3个浮点数。

最简单的修复方法是创建一个更大的GL_ARRAY_BUFFER,它为每个四边形重复相同的纹理坐标。

相关内容

  • 没有找到相关文章