繁体   English   中英

C++/OpenGL 纹理出现像素化

[英]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] ,这意味着为该三角形生成的所有片段将采样纹理的完全相同位置,从而产生完全相同的输出颜色,于是图像的“像素化”结构就出现了。 就像您已经为NormalFragPos ,您应该转发每个顶点的数据。 这已经应该可以解决您的问题。

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM