Foamy water webgl 1 to 2

Hi, I have a problem with shaders. I need foamy water. I only found this code, but I don’t know how to use this code in WEBGL 2.0. I know that “WEBGL_depth_texture” is for WEBGL 1.0

Does anyone know how to rewrite this to work in webgl 2.0?

Link to code: black-mountain-gojcn - CodeSandbox

I think it should work with webGL2 already? Are you hitting some errors when using latest threejs?

In WebGL2 things are different in shaders. Varying does not exist in WebGL2. You have to use “in” and “out”. You also have to set the “presicion” for the variable types used in the shader. And in the three.js code you have to use “glslVersion: THREE.GLSL3,” so that three.js knows that it is a WebGL2 shader. I turned the ShaderMaterial into a RawShaderMaterial because ShaderMaterial uses buildins that certainly won’t work with WebGL2. I can’t say whether my suggestions alone are enough, because codesandbox with the tablet is terrible. I can hardly select anything. Otherwise I would have tested it straight away.

Once you know these small differences, WebGL2 shaders hardly feel different than WebGL1. Personally, I haven’t used WebGL1 for a long time.

var waterMaterial = new THREE.RawShaderMaterial({
    glslVersion: THREE.GLSL3,
    defines: {
      DEPTH_PACKING: supportsDepthTextureExtension === true ? 0 : 1,

And the shaders:

<script id="vertexShader" type="x-shader/x-vertex">

#include <fog_pars_vertex>

in vec2 uv;
out vec2 vUv;

void main() {

  vUv = uv;

  #include <begin_vertex>
  #include <project_vertex>
  #include <fog_vertex>



<script id="fragmentShader" type="x-shader/x-fragment">

precision highp float;
precision highp int;
precision highp sampler2D;

#include <common>
#include <packing>
#include <fog_pars_fragment>

in vec2 vUv;

out vec4 outColor;

uniform sampler2D tDepth;
uniform sampler2D tDudv;
uniform vec3 waterColor;
uniform vec3 foamColor;
uniform float cameraNear;
uniform float cameraFar;
uniform float time;
uniform float threshold;
uniform vec2 resolution;

float getDepth( const in vec2 screenPosition ) {
  #if DEPTH_PACKING == 1
    return unpackRGBAToDepth( texture2D( tDepth, screenPosition ) );
    return texture2D( tDepth, screenPosition ).x;

float getViewZ( const in float depth ) {
    return orthographicDepthToViewZ( depth, cameraNear, cameraFar );
    return perspectiveDepthToViewZ( depth, cameraNear, cameraFar );

void main() {

  vec2 screenUV = gl_FragCoord.xy / resolution;
  float fragmentLinearEyeDepth = getViewZ( gl_FragCoord.z );
  float linearEyeDepth = getViewZ( getDepth( screenUV ) );

  float diff = saturate( fragmentLinearEyeDepth - linearEyeDepth );
  vec2 displacement = texture2D( tDudv, ( vUv * 2.0 ) - time * 0.05 ).rg;
  displacement = ( ( displacement * 2.0 ) - 1.0 ) * 1.0;
  diff += displacement.x;

  outColor.rgb = mix( foamColor, waterColor, step( threshold, diff ) );
  outColor.a = 1.0;

  #include <tonemapping_fragment>
  #include <encodings_fragment>
  #include <fog_fragment>


1 Like

@Attila_Schroeder Now such errors appeared to me :smiley:

I think what @manthrax was saying is that three.js performs the conversion of webgl-1 shaders when the context is webgl-2, so you dont really have to.

edit: here is original code working in webgl-2 almost unchanged (only edited geometry names)


Ya that’s what i meant. :smiley: :+1: