Skip to content

Commit

Permalink
Let groundReflector also follow settings.
Browse files Browse the repository at this point in the history
  • Loading branch information
gonnavis committed Feb 21, 2021
1 parent 1142c1b commit e19bc15
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 57 deletions.
140 changes: 93 additions & 47 deletions examples/jsm/objects/ReflectorForSSRPass.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,41 @@ var Reflector = function ( geometry, options ) {
var clipBias = options.clipBias || 0;
var shader = options.shader || Reflector.ReflectorShader;
var useDepthTexture = options.useDepthTexture
var yAxis = new Vector3(0, 1, 0);
var vecTemp0 = new Vector3();
var vecTemp1 = new Vector3();

//

scope.needsUpdate = false;
scope.maxDistance = Reflector.ReflectorShader.uniforms.maxDistance.value
scope.opacity = Reflector.ReflectorShader.uniforms.opacity.value

scope._isDistanceAttenuation = Reflector.ReflectorShader.defines.isDistanceAttenuation
Object.defineProperty(scope, 'isDistanceAttenuation', {
get() {
return scope._isDistanceAttenuation
},
set(val) {
if (scope._isDistanceAttenuation === val) return
scope._isDistanceAttenuation = val
scope.material.defines.isDistanceAttenuation = val
scope.material.needsUpdate = true
}
})

scope._isFresnel = Reflector.ReflectorShader.defines.isFresnel
Object.defineProperty(scope, 'isFresnel', {
get() {
return scope._isFresnel
},
set(val) {
if (scope._isFresnel === val) return
scope._isFresnel = val
scope.material.defines.isFresnel = val
scope.material.needsUpdate = true
}
})

var reflectorPlane = new Plane();
var normal = new Vector3();
Expand Down Expand Up @@ -77,7 +108,9 @@ var Reflector = function ( geometry, options ) {

var material = new ShaderMaterial( {
transparent: useDepthTexture,
defines: { useDepthTexture: useDepthTexture },
defines: Object.assign({
useDepthTexture: useDepthTexture
}, Reflector.ReflectorShader.defines),
uniforms: UniformsUtils.clone( shader.uniforms ),
fragmentShader: shader.fragmentShader,
vertexShader: shader.vertexShader
Expand All @@ -97,6 +130,18 @@ var Reflector = function ( geometry, options ) {
scope.needsUpdate = false;
// console.log('onBeforeRender')

material.uniforms['maxDistance'].value = scope.maxDistance * (camera.position.length() / camera.position.y);
// Temporary hack,
// need precise calculation like this https://github.com/mrdoob/three.js/pull/20156/commits/8181946068e386d14a283cbd4f8877bc7ae066d3 ,
// after fully understand http://www.terathon.com/lengyel/Lengyel-Oblique.pdf .

material.uniforms['opacity'].value = scope.opacity;

vecTemp0.copy(camera.position).normalize();
vecTemp1.copy(vecTemp0).reflect(yAxis);
material.uniforms['fresnel'].value = (vecTemp0.dot( vecTemp1 ) + 1.) / 2.;
// console.log(material.uniforms['fresnel'].value)

reflectorWorldPosition.setFromMatrixPosition( scope.matrixWorld );
cameraWorldPosition.setFromMatrixPosition( camera.matrixWorld );

Expand Down Expand Up @@ -220,25 +265,22 @@ var Reflector = function ( geometry, options ) {
Reflector.prototype = Object.create( Mesh.prototype );
Reflector.prototype.constructor = Reflector;

Reflector.ReflectorShader = {

uniforms: {

'color': {
value: null
},
Reflector.ReflectorShader = { ///todo: Will conflict with Reflector.js?

'tDiffuse': {
value: null
},
defines: {
isDistanceAttenuation: true,
isFresnel: true,
},

'tDepth': {
value: null
},
uniforms: {

'textureMatrix': {
value: null
}
color: { value: null },
tDiffuse: { value: null },
tDepth: { value: null },
textureMatrix: { value: null },
maxDistance: { value: 180 },
opacity: { value: .5 },
fresnel: { value: null },

},

Expand All @@ -255,36 +297,40 @@ Reflector.ReflectorShader = {
'}'
].join( '\n' ),

fragmentShader: [
'uniform vec3 color;',
'uniform sampler2D tDiffuse;',
'uniform sampler2D tDepth;',
'varying vec4 vUv;',

'float blendOverlay( float base, float blend ) {',

' return( base < 0.5 ? ( 2.0 * base * blend ) : ( 1.0 - 2.0 * ( 1.0 - base ) * ( 1.0 - blend ) ) );',

'}',

'vec3 blendOverlay( vec3 base, vec3 blend ) {',

' return vec3( blendOverlay( base.r, blend.r ), blendOverlay( base.g, blend.g ), blendOverlay( base.b, blend.b ) );',

'}',

'void main() {',

' vec4 base = texture2DProj( tDiffuse, vUv );',
' #ifdef useDepthTexture',
' vec4 depth = texture2DProj( tDepth, vUv );',
' gl_FragColor = vec4( blendOverlay( base.rgb, color ), pow(1.-depth.r,10./*temp*/) );',
' #else',
' gl_FragColor = vec4( blendOverlay( base.rgb, color ), 1.0 );',
' #endif',

'}'
].join( '\n' )
fragmentShader: `
uniform vec3 color;
uniform sampler2D tDiffuse;
uniform sampler2D tDepth;
uniform float maxDistance;
uniform float opacity;
uniform float fresnel;
varying vec4 vUv;
float blendOverlay( float base, float blend ) {
return( base < 0.5 ? ( 2.0 * base * blend ) : ( 1.0 - 2.0 * ( 1.0 - base ) * ( 1.0 - blend ) ) );
}
vec3 blendOverlay( vec3 base, vec3 blend ) {
return vec3( blendOverlay( base.r, blend.r ), blendOverlay( base.g, blend.g ), blendOverlay( base.b, blend.b ) );
}
void main() {
vec4 base = texture2DProj( tDiffuse, vUv );
#ifdef useDepthTexture
float op=opacity;
float depth = texture2DProj( tDepth, vUv ).r;
if(depth>maxDistance) discard;
#ifdef isDistanceAttenuation
float ratio=1.-(depth/maxDistance);
float attenuation=ratio*ratio;
op=opacity*attenuation;
#endif
#ifdef isFresnel
op*=fresnel;
#endif
gl_FragColor = vec4( blendOverlay( base.rgb, color ), op );
#else
gl_FragColor = vec4( blendOverlay( base.rgb, color ), 1.0 );
#endif
}
`,
};

export { Reflector };
2 changes: 1 addition & 1 deletion examples/jsm/postprocessing/SSRPass.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ var SSRPass = function({ scene, camera, width, height, selects, encoding, isPers
}
})

this._isBouncing = isBouncing
this._isBouncing = isBouncing ///todo: don't need defineProperty
Object.defineProperty(this, 'isBouncing', {
get() {
return this._isBouncing
Expand Down
30 changes: 21 additions & 9 deletions examples/webgl_postprocessing_ssr.html
Original file line number Diff line number Diff line change
Expand Up @@ -190,12 +190,6 @@

gui = new GUI({ width: 400 });
gui.add(params, 'enableSSR').name('Enable SSR');
gui.add(params, 'autoRotate').onChange(() => {
controls.enabled = !params.autoRotate
})
gui.add(ssrPass, 'isDistanceAttenuation');
ssrPass.maxDistance = .1
gui.add(ssrPass, 'maxDistance').min(0).max(1).step(.01);
gui.add(params, 'isGroundReflector').onChange(() => {
if (params.isGroundReflector) {
groundReflector.visible = true
Expand All @@ -205,14 +199,27 @@
ssrPass.selects = null
}
})
gui.add(params, 'autoRotate').onChange(() => {
controls.enabled = !params.autoRotate
})
gui.add(ssrPass, 'isFresnel').onChange(()=>{
groundReflector.isFresnel=ssrPass.isFresnel
});
gui.add(ssrPass, 'isDistanceAttenuation').onChange(()=>{
groundReflector.isDistanceAttenuation=ssrPass.isDistanceAttenuation
});
ssrPass.maxDistance = .1
groundReflector.maxDistance = ssrPass.maxDistance
gui.add(ssrPass, 'maxDistance').min(0).max(.5).step(.001).onChange(()=>{
groundReflector.maxDistance=ssrPass.maxDistance
});
gui.add(params, 'isOtherMeshes').onChange(() => {
if (params.isOtherMeshes) {
otherMeshes.forEach(mesh => mesh.visible = true)
} else {
otherMeshes.forEach(mesh => mesh.visible = false)
}
})
gui.add(ssrPass, 'isFresnel');
gui.add(ssrPass, 'isBouncing')
gui.add(ssrPass, 'output', {
'Default': SSRPass.OUTPUT.Default,
Expand All @@ -226,8 +233,11 @@
ssrPass.output = parseInt(value);

});
ssrPass.opacity = .8
gui.add(ssrPass, 'opacity').min(0).max(1);
ssrPass.opacity = 1
groundReflector.opacity=ssrPass.opacity
gui.add(ssrPass, 'opacity').min(0).max(1).onChange(()=>{
groundReflector.opacity=ssrPass.opacity
});
if (isPerspectiveCamera) {
ssrPass.surfDist = 0.0015
gui.add(ssrPass, 'surfDist').min(0).max(.005).step(.0001);
Expand Down Expand Up @@ -278,6 +288,8 @@

if (params.enableSSR) {
groundReflector.needsUpdate = true; // Just SSRPass's beautyRenderTarget (which rendered fisrt internally) need Reflector.
///todo: groundReflector has full ground info, need use it to solve reflection gaps problem on objects when camera near ground.
///todo: the normal info where groundReflector reflected need to be changed.
composer.render();
} else {
groundReflector.needsUpdate = true;
Expand Down

0 comments on commit e19bc15

Please sign in to comment.