Skip to content

Commit

Permalink
WebGPURenderer: PMREM (#27829)
Browse files Browse the repository at this point in the history
* WebGPURenderer: PMREM (WIP)

* add temporary example

* Added fromCubemap()

* added pmrem and examples

* cleanup

* fix circular dependency

* Revert "fix circular dependency"

This reverts commit 83d6882.

* update pmrem examples

* NodeBuilder: Rename .getRenderTarget() -> .createRenderTarget()

* fix circular dependency (2)

* revision

* revision

* update `webgpu_cubemap_mix` example

* update `webgpu_cubemap_adjustments` example

* update `webgpu_equirectangular` example

* update screenshots
  • Loading branch information
sunag committed Feb 29, 2024
1 parent ef80ac7 commit 12b08b2
Show file tree
Hide file tree
Showing 31 changed files with 1,626 additions and 142 deletions.
3 changes: 3 additions & 0 deletions examples/files.json
Expand Up @@ -372,6 +372,9 @@
"webgpu_tsl_editor",
"webgpu_tsl_transpiler",
"webgpu_video_panorama",
"webgpu_pmrem_cubemap",
"webgpu_pmrem_equirectangular",
"webgpu_pmrem_scene",
"webgpu_postprocessing_afterimage",
"webgpu_postprocessing_anamorphic",
"webgpu_mirror",
Expand Down
5 changes: 4 additions & 1 deletion examples/jsm/nodes/Nodes.js
Expand Up @@ -64,7 +64,6 @@ export { default as RemapNode, remap, remapClamp } from './utils/RemapNode.js';
export { default as RotateUVNode, rotateUV } from './utils/RotateUVNode.js';
export { default as RotateNode, rotate } from './utils/RotateNode.js';
export { default as SetNode } from './utils/SetNode.js';
export { default as SpecularMIPLevelNode, specularMIPLevel } from './utils/SpecularMIPLevelNode.js';
export { default as SplitNode } from './utils/SplitNode.js';
export { default as SpriteSheetUVNode, spritesheetUV } from './utils/SpriteSheetUVNode.js';
export { default as StorageArrayElementNode } from './utils/StorageArrayElementNode.js';
Expand Down Expand Up @@ -160,6 +159,10 @@ export { default as EnvironmentNode } from './lighting/EnvironmentNode.js';
export { default as AONode } from './lighting/AONode.js';
export { default as AnalyticLightNode } from './lighting/AnalyticLightNode.js';

// pmrem
export { default as PMREMNode, pmremTexture } from './pmrem/PMREMNode.js';
export * as PMREMUtils from './pmrem/PMREMUtils.js';

// procedural
export { default as CheckerNode, checker } from './procedural/CheckerNode.js';

Expand Down
6 changes: 0 additions & 6 deletions examples/jsm/nodes/accessors/TextureNode.js
Expand Up @@ -126,12 +126,6 @@ class TextureNode extends UniformNode {

}

if ( levelNode !== null && builder.context.getTextureLevelAlgorithm !== undefined ) {

levelNode = builder.context.getTextureLevelAlgorithm( this, levelNode );

}

//

properties.uvNode = uvNode;
Expand Down
16 changes: 14 additions & 2 deletions examples/jsm/nodes/core/NodeBuilder.js
Expand Up @@ -23,6 +23,8 @@ import { getCurrentStack, setCurrentStack } from '../shadernode/ShaderNode.js';
import CubeRenderTarget from '../../renderers/common/CubeRenderTarget.js';
import ChainMap from '../../renderers/common/ChainMap.js';

import PMREMGenerator from '../../renderers/common/extras/PMREMGenerator.js';

const uniformsGroupCache = new ChainMap();

const typeFromLength = new Map( [
Expand Down Expand Up @@ -113,18 +115,26 @@ class NodeBuilder {

}

getRenderTarget( width, height, options ) {
createRenderTarget( width, height, options ) {

return new RenderTarget( width, height, options );

}

getCubeRenderTarget( size, options ) {
createCubeRenderTarget( size, options ) {

return new CubeRenderTarget( size, options );

}

createPMREMGenerator() {

// TODO: Move Materials.js to outside of the Nodes.js in order to remove this function and improve tree-shaking support

return new PMREMGenerator( this.renderer );

}

includes( node ) {

return this.nodes.includes( node );
Expand Down Expand Up @@ -1168,6 +1178,8 @@ class NodeBuilder {

createNodeMaterial( type = 'NodeMaterial' ) {

// TODO: Move Materials.js to outside of the Nodes.js in order to remove this function and improve tree-shaking support

return createNodeMaterialFromType( type );

}
Expand Down
2 changes: 1 addition & 1 deletion examples/jsm/nodes/lighting/AnalyticLightNode.js
Expand Up @@ -63,7 +63,7 @@ class AnalyticLightNode extends LightingNode {
}

const shadow = this.light.shadow;
const rtt = builder.getRenderTarget( shadow.mapSize.width, shadow.mapSize.height );
const rtt = builder.createRenderTarget( shadow.mapSize.width, shadow.mapSize.height );

const depthTexture = new DepthTexture();
depthTexture.minFilter = NearestFilter;
Expand Down
78 changes: 10 additions & 68 deletions examples/jsm/nodes/lighting/EnvironmentNode.js
@@ -1,17 +1,14 @@
import LightingNode from './LightingNode.js';
import { cache } from '../core/CacheNode.js';
import { context } from '../core/ContextNode.js';
import { maxMipLevel } from '../utils/MaxMipLevelNode.js';
import { roughness, clearcoatRoughness } from '../core/PropertyNode.js';
import { equirectUV } from '../utils/EquirectUVNode.js';
import { specularMIPLevel } from '../utils/SpecularMIPLevelNode.js';
import { cameraViewMatrix } from '../accessors/CameraNode.js';
import { transformedClearcoatNormalView, transformedNormalView, transformedNormalWorld } from '../accessors/NormalNode.js';
import { positionViewDirection } from '../accessors/PositionNode.js';
import { addNodeClass } from '../core/Node.js';
import { vec2 } from '../shadernode/ShaderNode.js';
import { cubeTexture } from '../accessors/CubeTextureNode.js';
import { float } from '../shadernode/ShaderNode.js';
import { reference } from '../accessors/ReferenceNode.js';
import { pmremTexture } from '../pmrem/PMREMNode.js';

const envNodeCache = new WeakMap();

Expand All @@ -29,19 +26,13 @@ class EnvironmentNode extends LightingNode {

let envNode = this.envNode;

if ( envNode.isTextureNode && envNode.value.isCubeTexture !== true ) {
if ( envNode.isTextureNode ) {

let cacheEnvNode = envNodeCache.get( envNode.value );

if ( cacheEnvNode === undefined ) {

const texture = envNode.value;
const renderer = builder.renderer;

// @TODO: Add dispose logic here
const cubeRTT = builder.getCubeRenderTarget( 512 ).fromEquirectangularTexture( renderer, texture );

cacheEnvNode = cubeTexture( cubeRTT.texture );
cacheEnvNode = pmremTexture( envNode.value );

envNodeCache.set( envNode.value, cacheEnvNode );

Expand Down Expand Up @@ -86,12 +77,9 @@ class EnvironmentNode extends LightingNode {
const createRadianceContext = ( roughnessNode, normalViewNode ) => {

let reflectVec = null;
let textureUVNode = null;

return {
getUV: ( textureNode ) => {

let node = null;
getUV: () => {

if ( reflectVec === null ) {

Expand All @@ -101,75 +89,29 @@ const createRadianceContext = ( roughnessNode, normalViewNode ) => {

}

if ( textureNode.isCubeTextureNode ) {

node = reflectVec;

} else if ( textureNode.isTextureNode ) {

if ( textureUVNode === null ) {

// @TODO: Needed PMREM

textureUVNode = equirectUV( reflectVec );

}

node = textureUVNode;

}

return node;
return reflectVec;

},
getTextureLevel: () => {

return roughnessNode;

},
getTextureLevelAlgorithm: ( textureNode, levelNode ) => {

return specularMIPLevel( textureNode, levelNode );

}
};

};

const createIrradianceContext = ( normalWorldNode ) => {

let textureUVNode = null;

return {
getUV: ( textureNode ) => {

let node = null;

if ( textureNode.isCubeTextureNode ) {

node = normalWorldNode;

} else if ( textureNode.isTextureNode ) {

if ( textureUVNode === null ) {
getUV: () => {

// @TODO: Needed PMREM

textureUVNode = equirectUV( normalWorldNode );
textureUVNode = vec2( textureUVNode.x, textureUVNode.y.oneMinus() );

}

node = textureUVNode;

}

return node;
return normalWorldNode;

},
getTextureLevel: ( textureNode ) => {
getTextureLevel: () => {

return maxMipLevel( textureNode );
return float( 1.0 );

}
};
Expand Down

0 comments on commit 12b08b2

Please sign in to comment.