OpenGL ES 2.0 上的着色器与 WebGL 上的着色器的工作方式不同

问题描述 投票:0回答:1

我在shadertoy.com上创建了一个波动方程着色器:您可以通过链接查看它是如何工作的https://www.shadertoy.com/view/dtsyD2

然后我将代码复制到使用 GLES 2.0 的 Android 项目中,将

texture()
更改为
texture2D()
,并将
fragColor
fragCoord
替换为全局
gl_FragColor
gl_FragCoord
。但结果看起来与在shadertoy(与WebGL一起使用)上不同。

这是它在 Android 上的样子:

我做错了什么?也许有什么我没有考虑到的地方。

这是我的顶点着色器代码(主程序和缓冲区程序相同):

attribute vec2 pos;

void main()
{
    gl_Position = vec4(pos.xy, 0.0, 1.0);
}

这是我的主片段着色器代码:

precision lowp float;

uniform vec2 iResolution;
uniform sampler2D iChannel0;

void main()
{
    vec2 uv = gl_FragCoord.xy / iResolution.xy;
    gl_FragColor = texture2D(iChannel0, uv);
}

这是我的缓冲区片段着色器代码:

precision lowp float;

uniform vec3 iMouse;
uniform vec2 iResolution;
uniform float iTime;
uniform sampler2D iChannel0;

const float delta = 1.0;

void main()
{
    float pressure = texture2D(iChannel0, gl_FragCoord.xy / iResolution.xy).x;
    float pVel = texture2D(iChannel0, gl_FragCoord.xy / iResolution.xy).y;

    float pright = texture2D(iChannel0, (gl_FragCoord.xy + vec2(1., 0.)) / iResolution.xy).x;
    float pleft = texture2D(iChannel0, (gl_FragCoord.xy + vec2(-1., 0.)) / iResolution.xy).x;
    float pup = texture2D(iChannel0, (gl_FragCoord.xy + vec2(0., 1.)) / iResolution.xy).x;
    float pdown = texture2D(iChannel0, (gl_FragCoord.xy + vec2(0., -1.)) / iResolution.xy).x;

    // Apply horizontal wave function
    pVel += delta * (-2.0 * pressure + pright + pleft) / 4.0;
    // Apply vertical wave function (these could just as easily have been one line)
    pVel += delta * (-2.0 * pressure + pup + pdown) / 4.0;

    // Change pressure by pressure velocity
    pressure += delta * pVel;

    // "Spring" motion. This makes the waves look more like water waves and less like sound waves.
    pVel -= 0.005 * delta * pressure;

    // Velocity damping so things eventually calm down
    pVel *= 1.0 - 0.002 * delta;

    // Pressure damping to prevent it from building up forever.
    pressure *= 0.999;

    //x = pressure. y = pressure velocity. Z and W = X and Y gradient
    gl_FragColor.xyzw = vec4(pressure, pVel, (pright - pleft) / 2.0, (pup - pdown) / 2.0);

    if (iMouse.z > 1.0) {
        float dist = distance(gl_FragCoord.xy, iMouse.xy);
        if (dist <= 20.0) {
            gl_FragColor.x += 1.0 - dist / 20.0;
        }
    }
}
android opengl-es glsl
1个回答
0
投票

答案:OpenGL 的

GL_RGBA
格式将值限制在
[0,1]
范围内: https://registry.khronos.org/OpenGL-Refpages/gl4/html/glTexImage2D.xhtml

所以我对我的着色器做了一些调整。

在写入 gl_FragColor 并更改之前,在缓冲区着色器中将我的值从

[-1; 1]
映射到
[0; 1]

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, null)

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 0, GL_RGBA, GL_FLOAT, null)

帮助了我。我还必须将版本从

2.0
切换到
3.0

着色器也存在一些差异,因为值不在

[-1; 1]
范围内。但 99% 的情况下它都能正常工作。 谢谢 Ruud Helderman 的假设。

© www.soinside.com 2019 - 2024. All rights reserved.