我一直有困难纹理我做的飞机。平面上的第一个四边形是正确的纹理,但平面的其余部分似乎只使用纹理的第一个像素,所以它最终都是纯色。如果我制作一个巨大的平面并只是纹理,它似乎可以正常工作,但当我试图将平面分解成部分时,我一直遇到这个问题。我假设我遗漏了一些关于坐标的东西,但是根据我的理解,我认为它们应该总是在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
存储每个顶点数据。
2和GL_FLOAT参数在glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, NULL);
中声明您在vboTex
每个顶点中有2个浮点数,但您还没有这样做,您在第一个四象素中每个顶点有2个浮点数。
同样,glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
中的3和GL_FLOAT参数声明您在vbo
每个顶点中有3个浮点数。
最简单的修复方法是创建一个更大的GL_ARRAY_BUFFER
,它为每个四边形重复相同的纹理坐标。