我在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;
}
}
}
答案: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 的假设。