Displacement pass
Create a new shader named DisplacementShader, then a new pass named displacementPass from the ShaderPass and add it to effectComposer:
const DisplacementShader = {
uniforms:
{
tDiffuse: { value: null }
},
vertexShader: `
varying vec2 vUv;
void main()
{
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
vUv = uv;
}
`,
fragmentShader: `
uniform sampler2D tDiffuse;
varying vec2 vUv;
void main()
{
vec4 color = texture2D(tDiffuse, vUv);
gl_FragColor = color;
}
`
}
const displacementPass = new ShaderPass(DisplacementShader)
effectComposer.addPass(displacementPass)
create a newUv based on vUv but with some distortion:
const DisplacementShader = {
// ...
fragmentShader: `
uniform sampler2D tDiffuse;
varying vec2 vUv;
void main()
{
vec2 newUv = vec2(
vUv.x,
vUv.y + sin(vUv.x * 10.0) * 0.1
);
vec4 color = texture2D(tDiffuse, newUv);
gl_FragColor = color;
}
`
}
Here, we solely applied a sin(...) on the y axis based on the x axis. You should see the render waving.
Add a uTime uniform:
const DisplacementShader = {
uniforms:
{
tDiffuse: { value: null },
uTime: { value: null }
},
// ...
fragmentShader: `
uniform sampler2D tDiffuse;
uniform float uTime;
varying vec2 vUv;
void main()
{
vec2 newUv = vec2(
vUv.x,
vUv.y + sin(vUv.x * 10.0 + uTime) * 0.1
);
vec4 color = texture2D(tDiffuse, newUv);
gl_FragColor = color;
}
`
}
Set its value to 0 after creating the pass:
const displacementPass = new ShaderPass(DisplacementShader) displacementPass.material.uniforms.uTime.value = 0 effectComposer.addPass(displacementPass)
update it in the tick function:
const clock = new THREE.Clock()
const tick = () =>
{
const elapsedTime = clock.getElapsedTime()
// Update passes
displacementPass.material.uniforms.uTime.value = elapsedTime
// ...
}
Futuristic interface displacement
Add a uNormalMap uniform:
const DisplacementShader = {
uniforms:
{
// ...
uNormalMap: { value: null }
},
// ...
}
Update it while loading the texture —the TextureLoader is already in the code:
displacementPass.material.uniforms.uNormalMap.value = textureLoader.load('/textures/interfaceNormalMap.png')
Now update the fragmentShader of the DisplacementShader:
const DisplacementShader = {
// ...
fragmentShader: `
uniform sampler2D tDiffuse;
uniform float uTime;
uniform sampler2D uNormalMap;
varying vec2 vUv;
void main()
{
vec3 normalColor = texture2D(uNormalMap, vUv).xyz * 2.0 - 1.0;
vec2 newUv = vUv + normalColor.xy * 0.1;
vec4 color = texture2D(tDiffuse, newUv);
vec3 lightDirection = normalize(vec3(- 1.0, 1.0, 0.0));
float lightness = clamp(dot(normalColor, lightDirection), 0.0, 1.0);
color.rgb += lightness * 2.0;
gl_FragColor = color;
}
`
}