Skip to content

Improved PMREM#710

Merged
elalish merged 29 commits intomasterfrom
improvedPMREM
Aug 22, 2019
Merged

Improved PMREM#710
elalish merged 29 commits intomasterfrom
improvedPMREM

Conversation

@elalish
Copy link
Contributor

@elalish elalish commented Aug 15, 2019

Fixes #587
Fixes #632

This is an improvement to the very simple PMREM approximation we were using before. It also includes several fixes to the three.js MeshStandardMaterial that we use. These changes mostly made HDR environment maps look more realistic, but also included is a change which cleans up the aliasing we were getting from high frequency normal maps. There is still room for improvement, but it's significantly better than what it was. I also updated our lighting & environment page to better showcase our rendering with HDR.

@elalish elalish requested a review from cdata August 15, 2019 22:39
@elalish elalish self-assigned this Aug 15, 2019
@elalish elalish requested a review from mrdoob August 16, 2019 18:01
Copy link
Contributor

@cdata cdata left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is still room for improvement

Can you share your thoughts on specific areas for future improvement?

Generally this looks really good. I have to trust you that some of these changes work as advertised until #682 , but maybe you would be willing to show off with some screenshots in the mean time? 🙏

(cubeTarget: WebGLRenderTargetCube, renderer: WebGLRenderer):
WebGLRenderTarget => {
const {cubeUVRenderTarget, cubeLods, meshes} = setup(cubeTarget);
const roughnessExtra = [0.5, 0.7, 1.0];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I eventually determined that these were referring to lods, but from this line the purpose of these numbers seems kind of obscure.

});
meshes.forEach((mesh) => {
(mesh.material as Material).dispose();
// (mesh.material as Material).dispose();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did we decide that we aren't going to dispose of this stuff? If so, maybe the meshes should just be a static array that gets updated as needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The shaders take longer to compile than they take to run, so it's very important that we don't dispose of them, since three does such a nice job caching them. Are we worried about a leak here? The programs are always identical, so three ensures they don't get duplicated. We shouldn't delete them until will not be loading any new environments anymore, and basing that on page navigation sounds reasonable?

const lodMax = 8;
// lodBase is the mip Level that is integrated to form all of the extra
// levels, but is not output directly into the PMREM texture. DO NOT
// CHANGE, as the Blur shader below is hard coded for this size.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💯

vec3 direction = vec3(clamp(uv, -1.0, 1.0), 1.0);
uv = abs(uv);
float over = max(uv.x, uv.y) - 1.0;
if(over > 0.0) direction.z -= over;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an interesting tweak. What case is being handled here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a comment above.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💯

#define cubeUV_faceSize (256.0)
#define cubeUV_maxMipLevel (8.0)
const float cubeUV_maxMipLevel = 8.0;
const float cubeUV_minMipLevel = 3.0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I almost wish these could be shared constants across this shader chunk and the PMREM generator (also mipBase). Or maybe uniforms? But that would be unnecessary since we can just "preprocess" them into the program source here..

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, really they should be uniforms, but since this is internal to three.js, we'll have to wait until it's upstreamed for that.


vec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm ) {

// Workaround for Adreno 3XX dFd*( vec3 ) bug. See #9988
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this file forked from Three.js? If so, can we document the nature of the changes? (ditto for lights_fragment_maps.glsl.js)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I can do that.

float f = fract(mip);
vec4 textureCubeUV(sampler2D envMap, vec3 sampleDir, float roughness) {
float filterMip = 0.0;
if(roughness >= 0.7){
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: kinda funky formatting in this conditional, maybe match the one below?

// This is a hack because IE claims that a shader which unrolls a loop to access
// 96 texture lookups has "complexity which exceeds allowed limits", however 48
// seems to be fine, so we subsample. This could be improved if someone cares a
// lot about IE.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if there are low-end devices that might also have issues with this.

Separately, it might be cleaner to read if this was written as a preprocessor directive. Although as I write that, I'm not 100% sure if that will prevent IE from barfing when linking the shader.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good idea; I'll give that a try.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was it too cumbersome to use Three.js' defines property for ShaderMaterial to do this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, those are really for defining constants, not just a switch. I noticed this is the way three tends to do it internally.

@elalish elalish requested a review from cdata August 20, 2019 15:26
* even more filtered mips at the same lodMin resolution, associated with higher
* roughness levels. These extra mips are stored at X rather than Y offsets to
* help distiguish them. In this way we maintain resolution to smoothly
* interpolate diffuse lighting while limiting sampling computation.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💯


//float envMapWidth = pow( 2.0, maxMIPLevelScalar );
//float desiredMIPLevel = log2( envMapWidth * sqrt( 3.0 ) ) - 0.5 * log2( pow2( blinnShininessExponent ) + 1.0 );
// (elalish) Changed from Blinn-Phong to Trowbridge-Reitz distribution and added anti-aliasing.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💯

}

vec3 getLightProbeIndirectRadiance( /*const in SpecularLightProbe specularLightProbe,*/ const in GeometricContext geometry, const in float blinnShininessExponent, const in int maxMIPLevel ) {
// (elalish) Changed the input from blinnShininessExponent to roughness, so that we can use the Trowbridge-Reitz distribution instead.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍


#endif

// (elalish) Mixing the reflection with the normal is more accurate and keeps rough objects from gathering light from behind their tangent plane.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

vec3 N = normalize( surf_norm );
mat3 tsn = mat3( S, T, N );

// (elalish) Biased the normal mip to anti-alias the normal's screen-space derivatives
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

<!-- Uncomment the following script in order to debug shader errors in Sauce Labs. When
a shader fails to compile, it logs a console.error ("Shader failed to compile!") before it logs
the debug output from WebGL. Without this script, WCT bails out on the first error, so you
never see the useful log, which tends to be especially critical for IE11. -->
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Copy link
Contributor

@cdata cdata left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So beautilful :shipit: Ship it!

@elalish elalish merged commit 52c38a3 into master Aug 22, 2019
@elalish elalish deleted the improvedPMREM branch August 22, 2019 23:15
@cdata cdata added this to the v0.6.0 milestone Aug 26, 2019
elalish added a commit to elalish/model-viewer that referenced this pull request Feb 4, 2020
 
Improved PMREM (google#710)

* starting to work

* blurShader working

* updated IBL lookup

* fixed roughness mapping

* gave fidelity tests orbit controls

* added antialiasing, corrected texelSize

* added single-pixel mip

* refactored blurShader

* added bottom of mipmap chain

* refactored antialiasing into cubeUV

* extra mipmaps working

* fixed moire mostly

* simplified PMREM

* minMip level => 3

* tweaked filtering function

* removed debug export

* switching const to #define for IE

* fixed IE shader complexity bug

* addressing feedback

* refactored IE11 #defines

* merging master

* updated asset paths

* replaced shader const with #define to support IE11

* fixed another const and a small math error

* using defines in gaussianBlur
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Moiré effect on certain materials Rendering inconsistencies with fine detailed normals + roughness

2 participants