[英]C++/OpenGL Texture appearing Pixelated
这是我生成纹理(MRE)的代码:
glGenTextures(1, &id);
glBindTexture(GL_TEXTURE_2D, id);
if(readAlpha)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
else
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glGenerateMipmap(GL_TEXTURE_2D);
以下是 Tex 坐标的生成方式:
for (int y = 0; y < resolution; y++)
{
for (int x = 0; x < resolution; x++)
{
int i = x + y * resolution;
glm::vec2 percent = glm::vec2(x, y) / ((float)resolution - 1);
glm::vec3 pointOnPlane = (percent.x - .5f) * 2 * right + (percent.y - .5f) * 2 * front;
pointOnPlane *= scale;
vertices[i] = Vert();
vertices[i].position = glm::vec3(0.0f);
vertices[i].position.x = (float)pointOnPlane.x;
vertices[i].position.y = (float)pointOnPlane.y;
vertices[i].position.z = (float)pointOnPlane.z;
vertices[i].texCoord = glm::vec2(percent.x, percent.y)*textureScale;
vertices[i].normal = glm::vec3(0.0f);
if (x != resolution - 1 && y != resolution - 1)
{
inds[triIndex] = i;
inds[triIndex + 1] = i + resolution + 1;
inds[triIndex + 2] = i + resolution;
inds[triIndex + 3] = i;
inds[triIndex + 4] = i + 1;
inds[triIndex + 5] = i + resolution + 1;
triIndex += 6;
}
}
}
这是着色器:VERT:
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNorm;
layout (location = 2) in vec2 aTexCoord;
uniform mat4 _PV;
uniform mat4 _Model;
out DATA
{
vec3 FragPos;
vec3 Normal;
vec2 TexCoord;
mat4 PV;
} data_out;
void main()
{
gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
data_out.FragPos = aPos;
data_out.Normal = aNorm;
data_out.TexCoord = aTexCoord;
data_out.PV = _PV;
}
几何:
#version 330 core
layout(triangles) in;
layout(triangle_strip, max_vertices = 3) out;
out vec3 FragPos;
out vec3 Normal;
out vec2 TexCoord;
in DATA
{
vec3 FragPos;
vec3 Normal;
vec2 TexCoord;
mat4 PV;
} data_in[];
void main()
{
gl_Position = data_in[0].PV * gl_in[0].gl_Position;
Normal = data_in[0].Normal;
TexCoord = data_in[0].TexCoord;
FragPos = data_in[0].FragPos;
EmitVertex();
gl_Position = data_in[0].PV * gl_in[1].gl_Position;
Normal = data_in[1].Normal;
TexCoord = data_in[0].TexCoord;
FragPos = data_in[1].FragPos;
EmitVertex();
gl_Position = data_in[0].PV * gl_in[2].gl_Position;
Normal = data_in[2].Normal;
TexCoord = data_in[0].TexCoord;
FragPos = data_in[2].FragPos;
EmitVertex();
EndPrimitive();
}
碎片:
#version 330 core
out vec4 FragColor;
uniform vec3 _LightPosition;
uniform vec3 _LightColor;
uniform sampler2D _Diffuse;
//unifrom float _UseTexutres;
in vec3 FragPos;
in vec3 Normal;
in vec2 TexCoord;
void main()
{
//vec3 objectColor = vec3(0.34f, 0.49f, 0.27f);
vec3 objectColor = vec3(1, 1, 1);
objectColor = texture(_Diffuse, TexCoord).xyz;
vec3 norm = normalize(Normal);
vec3 lightDir = normalize(_LightPosition - FragPos);
float diff = max(dot(norm, lightDir), 0.0f);
vec3 diffuse = diff * _LightColor;
vec3 result = (vec3(0.2, 0.2, 0.2) + diffuse) * objectColor;
FragColor = vec4(result, 1.0);
}
即使我使用的是 8K 纹理,我也会得到像素化的纹理。
如果您想查看整个源代码: https : //github.com/Jaysmito101/TerraGen3D
结果如下:
你的几何着色器没有意义:
首先,您对输出三角形的所有 3 个顶点使用相同的data_in.TexCoords[0]
,这意味着为该三角形生成的所有片段将采样纹理的完全相同位置,从而产生完全相同的输出颜色,于是图像的“像素化”结构就出现了。 就像您已经为Normal
和FragPos
,您应该转发每个顶点的数据。 这已经应该可以解决您的问题。
但是,您的方法存在更多问题。 您确实将mat4 PV
作为每个顶点的数据从 VS 转发到 GS。 但是,你转发的数据是uniform
,所以这是一种资源浪费。 每个着色器阶段都可以访问所有制服,因此无需为每个顶点转发此数据。
但是房间里真正的大象是这个几何着色器应该做的。 均匀矩阵的实际变换可以——而且绝对应该——直接在顶点着色器中进行。 而几何着色器的其余部分基本上是对传递实现的尝试(只是一个错误的实现)。 那么你需要这个着色器做什么? 您可以在 VS 中进行转换并完全删除几何着色器。 在性能方面,这也将是一个胜利,因为几何着色器效率很低,如果不是绝对需要,应该避免使用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.