Skip to content

Commit

Permalink
MeshVelocityMaterial: render a scene's velocity field to a buffer (us…
Browse files Browse the repository at this point in the history
…eful for motion blur, TRAA post effects) (#23784)

* beginning work on TRAA pass.

* more work on TRAA.

* remove TRAA for now.

* velocity material is working.

* update default channel in example.

* Update MeshVelocityMaterial.js

* Update ShaderLib.js

* add mention of velocity in channel example description

* clean up MeshVelocityMaterial class.

* Update MeshVelocityMaterial.js

* move velocity shader out of core and into examples.

* channel example working again.

* make Object3D.matrixWorldPrevious optional.

* cleanup of PR.

* Update webgl_materials_channels.html

Co-authored-by: Michael Herzog <michael.herzog@human-interactive.org>
bhouston and Mugen87 authored Oct 25, 2022
1 parent 426c4ba commit 20c13f1
Showing 3 changed files with 175 additions and 3 deletions.
128 changes: 128 additions & 0 deletions examples/jsm/shaders/VelocityShader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import {
UniformsLib,
UniformsUtils,
Matrix4
} from 'three';

/**
* Mesh Velocity Shader @bhouston
*/

const VelocityShader = {

uniforms: UniformsUtils.merge( [
UniformsLib.common,
UniformsLib.displacementmap,
{
modelMatrixPrev: { value: new Matrix4() },
currentProjectionViewMatrix: { value: new Matrix4() },
previousProjectionViewMatrix: { value: new Matrix4() }
}
] ),

vertexShader: /* glsl */`
#define NORMAL
#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )
varying vec3 vViewPosition;
#endif
#include <common>
#include <packing>
#include <uv_pars_vertex>
#include <displacementmap_pars_vertex>
#include <normal_pars_vertex>
#include <morphtarget_pars_vertex>
#include <skinning_pars_vertex>
#include <logdepthbuf_pars_vertex>
#include <clipping_planes_pars_vertex>
uniform mat4 previousProjectionViewMatrix;
uniform mat4 currentProjectionViewMatrix;
uniform mat4 modelMatrixPrev;
varying vec4 clipPositionCurrent;
varying vec4 clipPositionPrevious;
void main() {
#include <uv_vertex>
#include <beginnormal_vertex>
#include <morphnormal_vertex>
#include <skinbase_vertex>
#include <skinnormal_vertex>
#include <defaultnormal_vertex>
#include <normal_vertex>
#include <begin_vertex>
#include <morphtarget_vertex>
#include <displacementmap_vertex>
#include <morphtarget_vertex>
#include <skinning_vertex>
#ifdef USE_SKINNING
vec4 mvPosition = modelViewMatrix * skinned;
clipPositionCurrent = currentProjectionViewMatrix * modelMatrix * skinned;
clipPositionPrevious = previousProjectionViewMatrix * modelMatrixPrev * skinned;
#else
vec4 mvPosition = modelViewMatrix * vec4( transformed, 1.0 );
clipPositionCurrent = currentProjectionViewMatrix * modelMatrix * vec4( transformed, 1.0 );
clipPositionPrevious = previousProjectionViewMatrix * modelMatrixPrev * vec4( transformed, 1.0 );
#endif
gl_Position = projectionMatrix * mvPosition;
#include <logdepthbuf_vertex>
#include <clipping_planes_vertex>
}
`,
fragmentShader: /* glsl */`
#define NORMAL
uniform float opacity;
#include <packing>
#include <uv_pars_fragment>
#include <map_pars_fragment>
#include <alphamap_pars_fragment>
#include <alphatest_pars_fragment>
#include <logdepthbuf_pars_fragment>
#include <clipping_planes_pars_fragment>
varying vec4 clipPositionCurrent;
varying vec4 clipPositionPrevious;
void main() {
vec4 diffuseColor = vec4( 1.0 );
diffuseColor.a = opacity;
#include <map_fragment>
#include <alphamap_fragment>
#include <alphatest_fragment>
vec2 ndcPositionCurrent = clipPositionCurrent.xy/clipPositionCurrent.w;
vec2 ndcPositionPrevious = clipPositionPrevious.xy/clipPositionPrevious.w;
vec2 vel = ( ndcPositionCurrent - ndcPositionPrevious ) * 0.5;
vel = vel * 0.5 + 0.5;
vec2 v1 = packDepthToRG(vel.x);
vec2 v2 = packDepthToRG(vel.y);
gl_FragColor = vec4(v1.x, v1.y, v2.x, v2.y);
#include <logdepthbuf_fragment>
}
`
};

export { VelocityShader };
42 changes: 39 additions & 3 deletions examples/webgl_materials_channels.html
Original file line number Diff line number Diff line change
@@ -9,7 +9,7 @@
<body>

<div id="info">
<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> - <span id="description">Normal, Depth, DepthRGBA, DepthRGBAUnpacked, Materials</span><br/>
<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> - <span id="description">Normal, Velocity, Depth, DepthRGBA, DepthRGBAUnpacked, Materials</span><br/>
by <a href="https://Clara.io">Ben Houston</a>. ninja head from <a href="https://gpuopen.com/archive/gamescgi/amd-gpu-meshmapper/" target="_blank" rel="noopener">AMD GPU MeshMapper</a>
</div>

@@ -35,6 +35,8 @@
import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
import { OBJLoader } from 'three/addons/loaders/OBJLoader.js';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { VelocityShader } from 'three/addons/shaders/VelocityShader.js';


let stats;

@@ -55,7 +57,7 @@
let cameraOrtho, cameraPerspective;
let controlsOrtho, controlsPerspective;

let mesh, materialStandard, materialDepthBasic, materialDepthRGBA, materialNormal;
let mesh, materialStandard, materialDepthBasic, materialDepthRGBA, materialNormal, materialVelocity;

const SCALE = 2.436143; // from original model
const BIAS = - 0.428408; // from original model
@@ -68,7 +70,7 @@
function initGui() {

const gui = new GUI();
gui.add( params, 'material', [ 'standard', 'normal', 'depthBasic', 'depthRGBA' ] );
gui.add( params, 'material', [ 'standard', 'normal', 'velocity', 'depthBasic', 'depthRGBA' ] );
gui.add( params, 'camera', [ 'perspective', 'ortho' ] );
gui.add( params, 'side', [ 'front', 'back', 'double' ] );

@@ -191,6 +193,17 @@
side: THREE.DoubleSide
} );

materialVelocity = new THREE.ShaderMaterial( {
uniforms: THREE.UniformsUtils.clone( VelocityShader.uniforms ),
vertexShader: VelocityShader.vertexShader,
fragmentShader: VelocityShader.fragmentShader,
side: THREE.DoubleSide
} );
materialVelocity.uniforms.displacementMap.value = displacementMap;
materialVelocity.uniforms.displacementScale.value = SCALE;
materialVelocity.uniforms.displacementBias.value = BIAS;
materialVelocity.extensions.derivatives = true;

//

const loader = new OBJLoader();
@@ -202,6 +215,7 @@

mesh = new THREE.Mesh( geometry, materialNormal );
mesh.scale.multiplyScalar( 25 );
mesh.userData.matrixWorldPrevious = new THREE.Matrix4(); // for velocity
scene.add( mesh );

} );
@@ -261,6 +275,7 @@
case 'depthBasic': material = materialDepthBasic; break;
case 'depthRGBA': material = materialDepthRGBA; break;
case 'normal': material = materialNormal; break;
case 'velocity': material = materialVelocity; break;

}

@@ -296,8 +311,29 @@
controlsPerspective.update();
controlsOrtho.update(); // must update both controls for damping to complete

// remember camera projection changes

materialVelocity.uniforms.previousProjectionViewMatrix.value.copy( materialVelocity.uniforms.currentProjectionViewMatrix.value );
materialVelocity.uniforms.currentProjectionViewMatrix.value.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );

if ( mesh && mesh.userData.matrixWorldPrevious ) {

materialVelocity.uniforms.modelMatrixPrev.value.copy( mesh.userData.matrixWorldPrevious );

}

renderer.render( scene, camera );

scene.traverse( function ( object ) {

if ( object.isMesh ) {

object.userData.matrixWorldPrevious.copy( object.matrixWorld );

}

} );

}

</script>
8 changes: 8 additions & 0 deletions src/renderers/shaders/ShaderChunk/packing.glsl.js
Original file line number Diff line number Diff line change
@@ -25,6 +25,14 @@ float unpackRGBAToDepth( const in vec4 v ) {
return dot( v, UnpackFactors );
}
vec2 packDepthToRG( in highp float v ) {
return packDepthToRGBA( v ).yx;
}
float unpackRGToDepth( const in highp vec2 v ) {
return unpackRGBAToDepth( vec4( v.xy, 0.0, 0.0 ) );
}
vec4 pack2HalfToRGBA( vec2 v ) {
vec4 r = vec4( v.x, fract( v.x * 255.0 ), v.y, fract( v.y * 255.0 ) );
return vec4( r.x - r.y / 255.0, r.y, r.z - r.w / 255.0, r.w );

0 comments on commit 20c13f1

Please sign in to comment.