【问题标题】:C++/OpenGL Texture appearing PixelatedC++/OpenGL 纹理出现像素化
【发布时间】:2021-12-05 15:36:40
【问题描述】:

这是我生成纹理(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;
        }
    }
}

这是着色器: 垂直:

#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

结果如下:

【问题讨论】:

  • @Frank 我解决了你所说的问题,但它仍然是相同的像素化图像
  • 您遇到的错误将导致您所描述的视觉伪影。我非常有信心这是问题所在。要么你在其他地方有相同的代码,要么你需要做一个干净的构建。
  • @Frank 我做了一个干净的构建,我已经更新了代码,但问题仍然存在。还有其他问题可能导致这种伪影吗?
  • 嗯,那张截图清楚地展示了 GL_NEAREST 过滤,所以 something 正在纹理上设置它。
  • @Frank 我所有与纹理相关的 opengl 代码都来自一个文件,我从不故意使用 NEAREST

标签: c++ opengl graphics 3d textures


【解决方案1】:

您的几何着色器没有意义:

首先,您对输出三角形的所有 3 个顶点使用相同的data_in.TexCoords[0],这意味着为该三角形生成的所有片段都将对纹理的完全相同的位置进行采样,从而产生完全相同的输出颜色,于是出现了图像的“像素化”结构。就像您已经为NormalFragPos 所做的那样,您应该转发每个顶点的数据。这应该已经解决了您的问题。

但是,您的方法存在更多问题。您将mat4 PV 作为每个顶点数据从 VS 转发到 GS。但是,您转发的数据是uniform,所以这是一种资源浪费。每个着色器阶段都可以访问所有的制服,因此无需为每个顶点转发这些数据。

但房间里真正的大象是这个几何着色器应该做的事情。使用统一矩阵的实际转换可以——而且绝对应该——直接在顶点着色器中进行。而你的几何着色器的其余部分基本上是一种直通实现的尝试(只是一个错误的实现)。那么你需要这个着色器做什么?你 可以在 VS 中进行转换并完全移除几何着色器。在性能方面,这也将是一个胜利,因为几何着色器相当低效,如果不是绝对需要,应该避免使用。

【讨论】:

  • 非常感谢这解决了我的问题。而且我知道几何着色器什么都不做,删除它更好,但我希望它在那里,以便应用程序的用户可以从应用程序着色器编辑器中编辑几何着色器。是的,我不会将 _PV 从 vert 传递到 geom。
猜你喜欢
  • 1970-01-01
  • 2013-10-02
  • 1970-01-01
  • 1970-01-01
  • 2012-05-05
  • 2011-08-11
  • 2016-09-02
  • 2011-11-08
  • 1970-01-01
相关资源
最近更新 更多