当前位置: 首页 > 知识库问答 >
问题:

Opengl-极端纹理质量损失

笪涛
2023-03-14

我正在尝试纹理球体。我的顶点着色器:

attribute vec3 a_position;
attribute vec3 a_normal;
attribute vec3 a_texCoord0;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
uniform sampler2D u_texture;
varying vec3 fragPos;
varying vec3 normal;
varying vec3 color;

void main()
{
    gl_Position = projection * view * model * vec4(a_position, 1.0);
    fragPos = vec3(model * vec4(a_position, 1.0));
    normal = a_normal;
    if(a_texCoord0.x > 50){
        color = vec3(1f, 0.0f, 0.0f);
    } else {
        color = texture(u_texture, a_texCoord0);
    }
}

我的片段着色器:

#ifdef GL_ES
    precision mediump float;
#endif
varying vec3 normal;
varying vec3 color;
varying vec3 fragPos;

uniform vec3 lightPos;
uniform vec3 lightColor;

void main()
{
    // Ambient
    float ambientStrength = 0.1;
    vec3 ambient = ambientStrength * lightColor;

    // Diffuse
    vec3 norm = normalize(normal);
    vec3 lightDir = normalize(lightPos - fragPos);
    float diff = max(dot(norm, lightDir), 0.0);
    vec3 diffuse = diff * lightColor;

    //vec3 result = (ambient + diffuse) * color;
    vec3 result = color;
    gl_FragColor = vec4(result, 1.0);
}

我从二十面体构建球体,但使用6种相同的纹理对其进行纹理处理,并通过立方体映射原理将其连接起来。这是我如何将球坐标转换为UV的代码:

public void fillTexInformation(Vertex vertex){
        float[] sphericalCoord = GeometryHelper.toSphericalCoordinates(vertex.getPosition());
        vertex.setTexCoord(projection(sphericalCoord[1], sphericalCoord[2]));
    }

    /**
     * Project point on shpere to texture coordinate
     * @param theta
     * @param phi
     * @return
     */
    //https://stackoverflow.com/questions/29678510/convert-21-equirectangular-panorama-to-cube-map
    private Vector2 projection(float theta, float phi) {
        if (theta < 0.615) {
            return projectRight(theta, phi);
        } else if (theta > 2.527) {
            return projectLeft(theta, phi);
        } else if (phi <= Math.PI / 4 || phi > 7 * Math.PI / 4) {
            return projectBack(theta, phi);
        } else if (phi > Math.PI / 4 && phi <= 3 * Math.PI / 4) {
            return projectBottom(theta, phi);
        } else if (phi >3 * Math.PI / 4 && phi <= 5 * Math.PI / 4) {
            return projectFront(theta, phi);
        } else if (phi > 5 * Math.PI / 4 && phi <= 7 * Math.PI / 4) {
            return projectTop(theta, phi);
        } else {
            throw new RuntimeException("Algorithm error");
        }
    }

    private Vector2 projectBack(float theta, float phi) {
        float y = (float) Math.tan(phi);
        float z = (float) ((1 / Math.tan(theta)) / Math.cos(phi));
        if (z < -1) {
            return projectLeft(theta, phi);
        }
        if (z > 1) {
            return projectRight(theta, phi);
        }

        return new Vector2(normilizeTexCoord(y), normilizeTexCoord(z));
    }

    private Vector2 projectBottom(float theta, float phi) {
        float x = (float) Math.tan(phi - Math.PI / 2);
        float z = (float) ((1 / Math.tan(theta)) / Math.cos(phi - Math.PI / 2));
        if (z < -1) {
            return projectLeft(theta, phi);
        }
        if (z > 1) {
            return projectRight(theta, phi);
        }

//        return new Vector2(normilizeTexCoord(x), normilizeTexCoord(z));
        return new Vector2(100, 100);
    }

    private Vector2 projectFront(float theta, float phi) {
        float y = (float) Math.tan(phi);
        float z = (float) (-(1 / Math.tan(theta)) / Math.cos(phi));
        if (z < -1) {
            return projectLeft(theta, phi);
        }
        if (z > 1) {
            return projectRight(theta, phi);
        }

//        return new Vector2(normilizeTexCoord(y), normilizeTexCoord(z));
        return new Vector2(100, 100);
    }

    private Vector2 projectTop(float theta, float phi) {
        float x = (float) Math.tan(phi - 3 * Math.PI / 2);
        float z = (float) ((1 / Math.tan(theta)) / Math.cos(phi - 3 * Math.PI / 2));
        if (z < -1) {
            return projectLeft(theta, phi);
        }
        if (z > 1) {
            return projectRight(theta, phi);
        }

//        return new Vector2(normilizeTexCoord(x), normilizeTexCoord(z));
        return new Vector2(100, 100);
    }

    private Vector2 projectRight(float theta, float phi) {
        float x = (float) (Math.tan(theta) * Math.cos(phi));
        float y = (float) (Math.tan(theta) * Math.sin(phi));
//        return new Vector2(normilizeTexCoord(x), normilizeTexCoord(y));
        return new Vector2(100, 100);
    }

    private Vector2 projectLeft(float theta, float phi) {
        float x = (float) (-Math.tan(theta) * Math.cos(phi));
        float y = (float) (-Math.tan(theta) * Math.sin(phi));
//        return new Vector2(normilizeTexCoord(x), normilizeTexCoord(-y));
        return new Vector2(100, 100);
    }

    private float normilizeTexCoord(float coord){
        return (coord + 1) / 2;
    }

因此,我得到的只是可怕的纹理质量损失。这是原始纹理,也是我在球体上得到的(这里只有立方体贴图的一部分,其他面是红色的)。我猜这可能与建筑方法(二十面体)和纹理(立方体贴图)的不同有关。但它可以解释纹理不均匀的边缘,但质量损失并不严重。有人能给我解释一下这里发生了什么吗?

共有1个答案

司马璞
2023-03-14

这是因为在顶点着色器中对纹理进行采样,这意味着在每个三角形的拐角处只能获得三种颜色。对其他像素进行插值。

为了获得更好的质量,应将纹理采样移动到片段着色器,并应插值uv坐标,而不是颜色:

顶点着色器:

attribute vec3 a_position;
attribute vec3 a_normal;
attribute vec3 a_texCoord0;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

varying vec3 fragPos;
varying vec3 normal;
varying vec2 texcoord0;

void main()
{
    gl_Position = projection * view * model * vec4(a_position, 1.0);
    fragPos = vec3(model * vec4(a_position, 1.0));
    normal = a_normal;
    texcoord0 = a_texCoord0;
}

碎片着色器:

varying vec3 normal;
varying vec2 texcoord0;
varying vec3 fragPos;

uniform sampler2D u_texture;
uniform vec3 lightPos;
uniform vec3 lightColor;

void main()
{
    vec3 color = texture(u_texture, texcoord0).rgb;

    // Ambient
    float ambientStrength = 0.1;
    vec3 ambient = ambientStrength * lightColor;

    // Diffuse
    vec3 norm = normalize(normal);
    vec3 lightDir = normalize(lightPos - fragPos);
    float diff = max(dot(norm, lightDir), 0.0);
    vec3 diffuse = diff * lightColor;

    //vec3 result = (ambient + diffuse) * color;
    vec3 result = color;
    gl_FragColor = vec4(result, 1.0);
}
 类似资料:
  • 我试图绘制一个核心图形图像生成(在屏幕分辨率)到OpenGL。然而,图像呈现的别名比CG输出的更多(在CG中禁止抗锯齿)。文本是纹理(蓝色背景分别在核心图形中为第一幅图像绘制,在OpenGL中为第二幅图像绘制)。 OpenGL渲染(在模拟器中): Framebuffer设置:

  • 我有一个用于OpenGL中模型渲染的纹理数组。此数组包含漫反射和镜面纹理。由于某些网格没有镜面纹理,因此我在每次渲染后简单地将NULL纹理绑定到我的镜面采样器,并且只有当网格具有镜面纹理时,我才绑定一个。但是,我仍然在没有镜面纹理的网格上看到镜面纹理。 这是我的渲染代码 材质索引保存数组中纹理的索引,如果网格没有镜面纹理 索引为-1 纹理单元0用于漫反射 纹理单元2用于镜面

  • 所以最近我开始阅读OpenGL维基文章。这就是我在这里描述OpenGL纹理的方式。不过,有几点尚不清楚。 以下陈述是真的、假的还是视情况而定? 将两个纹理绑定到同一个纹理单元是不可能的。 将两个采样器绑定到同一个纹理单元是不可能的。 将一个纹理绑定到两个不同的纹理单元是不可能的。 将一个采样器绑定到两个不同的纹理单元是不可能的。 应用程序有责任明确将什么采样器类型传递给什么统一变量。 着色器程序有

  • “我在我的申请中发现了一个奇怪的行为,希望你能解释给我听。”。你看,我有两个3D纹理,它们被发送到片段着色器,渲染得非常好。但有一个问题,当我创建另一个纹理(它是1D纹理)时,一个黑屏正在被渲染,而不是正确的前一个结果。 关于这个1D纹理,我甚至没有将其发送到片段着色器。当我调用glTexImage1D(…)时,黑屏就出现了。我评论这句话,它就消失了!!这两种纹理被渲染。 我觉得纹理单位肯定有问题

  • 在andrid上的opengl es中,当我将两个纹理相邻放置时,会有一个轻微的接缝,可以看到它们后面绘制的对象。基本上看起来是一个小差距。我把范围缩小到了地图上 glTexParameteri(GL_纹理_2D、GL_纹理_最小过滤器、GL_线性_MIPMAP_线性);glTexParameteri(GL_纹理_2D、GL_纹理_MAG_过滤器、GL_线性); 如果我将它们都设置为距接缝最近的G

  • 假设我有一个金字塔…我知道如何绘制它,我知道如何为整个金字塔设置纹理,但如何为每面墙设置不同的纹理? 我通过在 我试图通过添加<code>GL11.glBindTexture(GL11.GL_TEXTURE_2D,TEXTURE.getTextureID())来绑定纹理 后,但