现代OpenGL问题纹理飞机

时间:2015-09-21 07:05:13

标签: c++ opengl opengl-4

我在制作一架飞机时遇到了困难。平面上的第一个四边形纹理正确,但平面的其余部分似乎只使用纹理的第一个像素,因此它最终都是纯色。如果我制作一个巨大的飞机并且只是纹理那么它似乎正常工作,但是当我试图将飞机分成几个部分时,我一直都会遇到这个问题。我假设我失去了一些东西,就坐标而言,但根据我的理解,我认为他们总是应该介于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);
}

2 个答案:

答案 0 :(得分:1)

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

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

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

答案 1 :(得分:1)

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

glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, NULL);中的 2 GL_FLOAT 参数声明每个顶点vboTex 中有2个浮点数但是你没有这样做,你只有第一个四边形中的每个顶点有2个浮点数。

以同样的方式,glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);中的 3 GL_FLOAT 参数声明您在vbo 中有3个浮点数您已完成的顶点

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