球体纹理映射旋转时出现暗带问题求助
解决球体纹理暗带问题
看起来你遇到的暗带问题主要来自三个地方:纹理坐标计算错误、索引生成逻辑有误,还有顶点着色器里的一个小类型不匹配。让我们一步步解决:
1. 修复顶点着色器的纹理坐标输入
你的顶点着色器里把纹理坐标声明成了vec3 aTexCoord,但实际你传入的是vec2类型的sphere_texcoords,这会导致GPU读取到未初始化的第三个分量,虽然你只取了xy,但可能引发奇怪的采样问题。修改成vec2即可:
#version 330 core layout (location = 0) in vec3 aPos; layout (location = 1) in vec2 aTexCoord; // 修正为vec2类型 out vec4 vertexColor; out vec2 TexCoord; uniform mat4 model; uniform mat4 view; uniform mat4 projection; void main() { gl_Position = projection * view * model * vec4(aPos, 1.0); vertexColor = vec4(0.5, 0.2, 0.5, 1.0); TexCoord = aTexCoord; // 直接赋值,无需额外转换 }
2. 正确计算球体纹理坐标
你之前用(x+1)/2和(y+1)/2生成UV的方式,会导致球体接缝处(theta=2π的位置)出现UV不连续,而且两极纹理会严重拉伸。正确的做法是直接用生成顶点时的theta和phi角度来计算UV:
for (int i = 0; i <= stacks; ++i) { float s = (float)i / (float)stacks; float theta = s * 2 * glm::pi<float>(); for (int j = 0; j <= slices; ++j) { float sl = (float)j / (float)slices; float phi = sl * glm::pi<float>(); const float x = cos(theta) * sin(phi); const float y = sin(theta) * sin(phi); const float z = cos(phi); sphere_vertices.push_back(radius * glm::vec3(x, y, z)); // 用角度生成均匀UV:u对应水平环绕,v对应垂直方向(反转sl适配纹理Y轴方向) sphere_texcoords.push_back(glm::vec2(s, 1.0f - sl)); } }
这样生成的UV会均匀覆盖整个球体,接缝处的UV从1自然过渡到0(纹理默认重复模式),不会出现断裂。
3. 修复索引生成逻辑
你原来的索引循环逻辑有问题,导致接缝处的三角形拼接错误,进而出现暗带。正确的球体索引生成应该遍历每个栈和切片,生成四边形对应的两个三角形:
// 重新生成索引 sphere_indices.clear(); for (int i = 0; i < stacks; ++i) { for (int j = 0; j < slices; ++j) { // 计算当前四边形的四个顶点索引 int topLeft = i * (slices + 1) + j; int topRight = topLeft + 1; int bottomLeft = (i + 1) * (slices + 1) + j; int bottomRight = bottomLeft + 1; // 第一个三角形:左上 -> 左下 -> 右上 sphere_indices.push_back(topLeft); sphere_indices.push_back(bottomLeft); sphere_indices.push_back(topRight); // 第二个三角形:右上 -> 左下 -> 右下 sphere_indices.push_back(topRight); sphere_indices.push_back(bottomLeft); sphere_indices.push_back(bottomRight); } }
这个逻辑会正确连接每个相邻顶点,避免出现错误的三角形拼接。
做完这三个修改后,纹理应该能正常映射到球体上,旋转时的暗带也会消失。如果还是遇到接缝问题,可以显式确认纹理的环绕模式:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
内容的提问来源于stack exchange,提问作者George
相关产品推荐
相关产品推荐

