I’m trying to recreate the following shader from shadertoy using Phaser 3:
I managed to fix the errors I was getting but it just loads an empty black square when trying to load it on my scene. Here’s a sample code:
const fragmentShader = `
#ifdef GL_ES
precision mediump float;
#endif
uniform float time;
uniform vec2 resolution;
uniform sampler2D iChannel0;
uniform sampler2D iChannel1;
uniform sampler2D iChannel2;
varying vec2 fragCoord;
float avg(vec4 color) {
return (color.r + color.g + color.b)/3.0;
}
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
// Flow Speed, increase to make the water flow faster.
float speed = 1.0;
// Water Scale, scales the water, not the background.
float scale = 0.8;
// Water opacity, higher opacity means the water reflects more light.
float opacity = 0.5;
// Normalized pixel coordinates (from 0 to 1)
vec2 uv = (fragCoord/resolution.xy);
vec2 scaledUv = uv*scale;
// Water layers, layered on top of eachother to produce the reflective effect
// Add 0.1 to both uv vectors to avoid the layers stacking perfectly and creating a huge unnatural highlight
vec4 water1 = texture2D(iChannel0, scaledUv + time*0.02*speed - 0.1);
vec4 water2 = texture2D(iChannel0, scaledUv.xy + time*speed*vec2(-0.02, -0.02) + 0.1);
// Water highlights
vec4 highlights1 = texture2D(iChannel2, scaledUv.xy + time*speed / vec2(-10, 100));
vec4 highlights2 = texture2D(iChannel2, scaledUv.xy + time*speed / vec2(10, 100));
// Background image
vec4 background = texture2D(iChannel1, vec2(uv) + avg(water1) * 0.05);
// Average the colors of the water layers (convert from 1 channel to 4 channel
water1.rgb = vec3(avg(water1));
water2.rgb = vec3(avg(water2));
// Average and smooth the colors of the highlight layers
highlights1.rgb = vec3(avg(highlights1)/1.5);
highlights2.rgb = vec3(avg(highlights2)/1.5);
float alpha = opacity;
if(avg(water1 + water2) > 0.3) {
alpha = 0.0;
}
if(avg(water1 + water2 + highlights1 + highlights2) > 0.75) {
alpha = 5.0 * opacity;
}
// Output to screen
fragColor = (water1 + water2) * alpha + background;
}
void main(void)
{
mainImage(gl_FragColor, fragCoord.xy);
gl_FragColor.a = 1.0;
}
`;
class Example extends Phaser.Scene {
constructor() {
super("Example");
}
preload() {
this.load.image("noise", "https://i.imgur.com/pZfKeRP.png");
this.load.image("pic", "https://i.imgur.com/NQFMq6r.jpg");
this.load.image("rocks", "https://i.imgur.com/fvHGrrU.png");
}
create() {
const baseShader = new Phaser.Display.BaseShader(
"BufferShader",
fragmentShader
);
this.add
.shader(baseShader, 0, 0, 800, 600, ["noise", "pic", "rocks"])
.setOrigin(0, 0);
}
}
const config = {
type: Phaser.WEBGL,
parent: "phaser-example",
width: 800,
height: 600,
scene: Example
};
const game = new Phaser.Game(config);
Is there anything I’m doing wrong? Here’s the same sample codepen so you can see the problem.
Thanks.