Search code examples
c++openglgraphics3dtextures

C++/OpenGL Texture appearing Pixelated


Here is my code for generating the texture(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);

Here is how Tex Coords are generated:

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;
        }
    }
}

Here is the shader: 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;
}

GEOM:

#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();
} 

FRAG:

#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);
} 

I am getting pixilated texture even thought I am using a 8K texture.

If you want to see the entire source : https://github.com/Jaysmito101/TerraGen3D

Here is the result:

enter image description here

enter image description here


Solution

  • Your geometry shader does not make sense:

    First of all, you use the same data_in.TexCoords[0] for all 3 vertices of of the output triangle, which means that all fragments generated for this triangle will sample the exact same location of the texture, resulting in the exact same output color, so the "pixelated" structure of the image emerges. Like you do already for Normal and FragPos, you should forward the data for each vertex. This already should solve your issue.

    However, there are more issues with your approach. You do forward mat4 PV as per-Vertex data from the VS to the GS. However, the data you forward is an uniform, so this is a waste of resources. Every shader stage has access to all of the uniforms, so there is no need to forward this data per vertex.

    But the real elephant in the room is what this geometry shader is supposed to be doing. The actual transformation with the uniform matrices can - and absolutely should - be carried out directly in the vertex shader. And the rest of your geometry shader is basically an attempt at a pass-through implementation (just a faulty one). So what do you need this shader for? You can do the transformation in the VS and completely remove the geometry shader. And performance-wise, this will also be a win as geometry shaders are rather inefficent and should be avoided if not absolutely needed.