Skip to content

Commit

Permalink
NodeMaterial: CubeTexture WebGPU and WebGL (#23743)
Browse files Browse the repository at this point in the history
* fix camera ref

* add viewMatrix, cameraPosition and cleanup

* fi texture parameter

* add getCubeTexture() and bias API update

* WebGLNodeBuilder: update bias API

* fix refresh uniforms of shared materials

* add WebGPUNodeSampledCubeTexture

* WebGPURenderer: CubeTexture support

* TextureNode: update bias API

* add CubeTextureNode and ReflectNode

* update examples

* Revert "WebGPURenderer: CubeTexture support"

This reverts commit 6c62b26.

* Revert "Revert "WebGPURenderer: CubeTexture support""

This reverts commit 4498f37.

* fix default value of baseArrayLayer

* CubeTextureNode instanceof of TextureNode
  • Loading branch information
sunag authored Mar 21, 2022
1 parent 74e6f4c commit 70b9ae8
Show file tree
Hide file tree
Showing 18 changed files with 347 additions and 88 deletions.
6 changes: 6 additions & 0 deletions examples/jsm/nodes/Nodes.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import VaryNode from './core/VaryNode.js';
// accessors
import BufferNode from './accessors/BufferNode.js';
import CameraNode from './accessors/CameraNode.js';
import CubeTextureNode from './accessors/CubeTextureNode.js';
import MaterialNode from './accessors/MaterialNode.js';
import MaterialReferenceNode from './accessors/MaterialReferenceNode.js';
import ModelNode from './accessors/ModelNode.js';
Expand All @@ -36,6 +37,7 @@ import Object3DNode from './accessors/Object3DNode.js';
import PointUVNode from './accessors/PointUVNode.js';
import PositionNode from './accessors/PositionNode.js';
import ReferenceNode from './accessors/ReferenceNode.js';
import ReflectNode from './accessors/ReflectNode.js';
import SkinningNode from './accessors/SkinningNode.js';
import TextureNode from './accessors/TextureNode.js';
import UVNode from './accessors/UVNode.js';
Expand Down Expand Up @@ -118,6 +120,7 @@ const nodeLib = {
// accessors
BufferNode,
CameraNode,
CubeTextureNode,
MaterialNode,
MaterialReferenceNode,
ModelNode,
Expand All @@ -127,6 +130,7 @@ const nodeLib = {
PointUVNode,
PositionNode,
ReferenceNode,
ReflectNode,
SkinningNode,
TextureNode,
UVNode,
Expand Down Expand Up @@ -205,6 +209,7 @@ export {
// accessors
BufferNode,
CameraNode,
CubeTextureNode,
MaterialNode,
MaterialReferenceNode,
ModelNode,
Expand All @@ -214,6 +219,7 @@ export {
PointUVNode,
PositionNode,
ReferenceNode,
ReflectNode,
SkinningNode,
TextureNode,
UVNode,
Expand Down
18 changes: 8 additions & 10 deletions examples/jsm/nodes/ShaderNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import UniformNode from './core/UniformNode.js';
import BufferNode from './accessors/BufferNode.js';
import PositionNode from './accessors/PositionNode.js';
import NormalNode from './accessors/NormalNode.js';
import CameraNode from './accessors/CameraNode.js';
import ModelNode from './accessors/ModelNode.js';
import TextureNode from './accessors/TextureNode.js';
import UVNode from './accessors/UVNode.js';

Expand Down Expand Up @@ -269,22 +271,14 @@ export const imat4 = new ConvertType( 'imat4', Matrix4 );
export const umat4 = new ConvertType( 'umat4', Matrix4 );
export const bmat4 = new ConvertType( 'bmat4', Matrix4 );

export const join = ( ...params ) => {

return nodeObject( new JoinNode( getShaderNodeArray( params ) ) );

};
export const join = ( ...params ) => nodeObject( new JoinNode( getShaderNodeArray( params ) ) );

export const uv = ( ...params ) => nodeObject( new UVNode( ...params ) );
export const attribute = ( ...params ) => nodeObject( new AttributeNode( ...params ) );
export const buffer = ( ...params ) => nodeObject( new BufferNode( ...params ) );
export const texture = ( ...params ) => nodeObject( new TextureNode( ...params ) );

export const cond = ( ...params ) => {

return nodeObject( new CondNode( ...getShaderNodeArray( params ) ) );

};
export const cond = ( ...params ) => nodeObject( new CondNode( ...getShaderNodeArray( params ) ) );

export const addTo = ( varNode, ...params ) => {

Expand Down Expand Up @@ -327,6 +321,10 @@ export const positionWorld = new ShaderNodeObject( new PositionNode( PositionNod
export const positionView = new ShaderNodeObject( new PositionNode( PositionNode.VIEW ) );
export const positionViewDirection = new ShaderNodeObject( new PositionNode( PositionNode.VIEW_DIRECTION ) );

export const viewMatrix = new ShaderNodeObject( new ModelNode( ModelNode.VIEW_MATRIX ) );

export const cameraPosition = new ShaderNodeObject( new CameraNode( CameraNode.POSITION ) );

export const PI = float( 3.141592653589793 );
export const PI2 = float( 6.283185307179586 );
export const PI_HALF = float( 1.5707963267948966 );
Expand Down
2 changes: 2 additions & 0 deletions examples/jsm/nodes/accessors/CameraNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ class CameraNode extends Object3DNode {

} else {

this.object3d = camera;

super.update( frame );

}
Expand Down
76 changes: 76 additions & 0 deletions examples/jsm/nodes/accessors/CubeTextureNode.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import TextureNode from './TextureNode.js';
import UniformNode from '../core/UniformNode.js';
import ReflectNode from './ReflectNode.js';

class CubeTextureNode extends TextureNode {

constructor( value, uvNode = new ReflectNode(), biasNode = null ) {

super( value, uvNode, biasNode );

}

getInputType( /*builder*/ ) {

return 'cubeTexture';

}

generate( builder, output ) {

const texture = this.value;

if ( ! texture || texture.isCubeTexture !== true ) {

throw new Error( 'CubeTextureNode: Need a three.js cube texture.' );

}

const textureProperty = UniformNode.prototype.generate.call( this, builder, 'cubeTexture' );

if ( output === 'samplerCube' || output === 'textureCube' ) {

return textureProperty;

} else if ( output === 'sampler' ) {

return textureProperty + '_sampler';

} else {

const nodeData = builder.getDataFromNode( this );

let snippet = nodeData.snippet;

if ( snippet === undefined ) {

const uvSnippet = this.uvNode.build( builder, 'vec3' );
const biasNode = this.biasNode;

if ( biasNode !== null ) {

const biasSnippet = biasNode.build( builder, 'float' );

snippet = builder.getCubeTextureBias( textureProperty, uvSnippet, biasSnippet );

} else {

snippet = builder.getCubeTexture( textureProperty, uvSnippet );

}

nodeData.snippet = snippet;

}

return builder.format( snippet, 'vec4', output );

}

}

}

CubeTextureNode.prototype.isCubeTextureNode = true;

export default CubeTextureNode;
63 changes: 63 additions & 0 deletions examples/jsm/nodes/accessors/ReflectNode.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import Node from '../core/Node.js';
import { nodeObject, normalWorld, positionWorld, cameraPosition, sub, normalize, join, negate, reflect } from '../ShaderNode.js';

class ReflectNode extends Node {

static VECTOR = 'vector';
static CUBE = 'cube';

constructor( scope = ReflectNode.CUBE ) {

super( 'vec3' );

this.scope = scope;

}

getHash( /*builder*/ ) {

return `reflect-${this.scope}`;

}

generate( builder ) {

const scope = this.scope;

if ( scope === ReflectNode.VECTOR ) {

const cameraToFrag = normalize( sub( positionWorld, cameraPosition ) );
const reflectVec = reflect( cameraToFrag, normalWorld );

return reflectVec.build( builder );

} else if ( scope === ReflectNode.CUBE ) {

const reflectVec = nodeObject( new ReflectNode( ReflectNode.VECTOR ) );
const cubeUV = join( negate( reflectVec.x ), reflectVec.yz );

return cubeUV.build( builder );

}

}

serialize( data ) {

super.serialize( data );

data.scope = this.scope;

}

deserialize( data ) {

super.deserialize( data );

this.scope = data.scope;

}

}

export default ReflectNode;
14 changes: 8 additions & 6 deletions examples/jsm/nodes/accessors/TextureNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,21 +55,23 @@ class TextureNode extends UniformNode {
const uvSnippet = this.uvNode.build( builder, 'vec2' );
const biasNode = this.biasNode;

let biasSnippet = null;

if ( biasNode !== null ) {

biasSnippet = biasNode.build( builder, 'float' );
const biasSnippet = biasNode.build( builder, 'float' );

}
snippet = builder.getTextureBias( textureProperty, uvSnippet, biasSnippet );

} else {

snippet = builder.getTexture( textureProperty, uvSnippet, biasSnippet );
snippet = builder.getTexture( textureProperty, uvSnippet );

}

nodeData.snippet = snippet;

}

return builder.format( snippet, 'texture', output );
return builder.format( snippet, 'vec4', output );

}

Expand Down
16 changes: 14 additions & 2 deletions examples/jsm/nodes/core/NodeBuilder.js
Original file line number Diff line number Diff line change
Expand Up @@ -142,13 +142,25 @@ class NodeBuilder {

}

getTexture( /* textureProperty, uvSnippet, biasSnippet = null */ ) {
getTexture( /* textureProperty, uvSnippet */ ) {

console.warn( 'Abstract function.' );

}

getCubeTexture( /* textureProperty, uvSnippet, biasSnippet = null */ ) {
getTextureBias( /* textureProperty, uvSnippet, biasSnippet */ ) {

console.warn( 'Abstract function.' );

}

getCubeTexture( /* textureProperty, uvSnippet */ ) {

console.warn( 'Abstract function.' );

}

getCubeTextureBias( /* textureProperty, uvSnippet, biasSnippet */ ) {

console.warn( 'Abstract function.' );

Expand Down
27 changes: 12 additions & 15 deletions examples/jsm/renderers/webgl/nodes/WebGLNodeBuilder.js
Original file line number Diff line number Diff line change
Expand Up @@ -159,33 +159,31 @@ class WebGLNodeBuilder extends NodeBuilder {

}

getTexture( textureProperty, uvSnippet, biasSnippet = null ) {
getTexture( textureProperty, uvSnippet ) {

if ( biasSnippet !== null ) {
return `texture2D( ${textureProperty}, ${uvSnippet} )`;

return `texture2D( ${textureProperty}, ${uvSnippet}, ${biasSnippet} )`;
}

} else {
getTextureBias( textureProperty, uvSnippet, biasSnippet ) {

return `texture2D( ${textureProperty}, ${uvSnippet} )`;
if ( this.material.extensions !== undefined ) this.material.extensions.shaderTextureLOD = true;

}
return `textureLod( ${textureProperty}, ${uvSnippet}, ${biasSnippet} )`;

}

getCubeTexture( textureProperty, uvSnippet, biasSnippet = null ) {

const textureCube = 'textureCubeLodEXT'; // textureCubeLodEXT textureLod
getCubeTexture( textureProperty, uvSnippet ) {

if ( biasSnippet !== null ) {
return `textureCube( ${textureProperty}, ${uvSnippet} )`;

return `${textureCube}( ${textureProperty}, ${uvSnippet}, ${biasSnippet} )`;
}

} else {
getCubeTextureBias( textureProperty, uvSnippet, biasSnippet ) {

return `${textureCube}( ${textureProperty}, ${uvSnippet} )`;
if ( this.material.extensions !== undefined ) this.material.extensions.shaderTextureLOD = true;

}
return `textureLod( ${textureProperty}, ${uvSnippet}, ${biasSnippet} )`;

}

Expand Down Expand Up @@ -367,7 +365,6 @@ ${this.shader[ getShaderStageProperty( shaderStage ) ]}
this.vertexShader = shaderData.vertex;
this.fragmentShader = shaderData.fragment;


}

build() {
Expand Down
15 changes: 13 additions & 2 deletions examples/jsm/renderers/webgl/nodes/WebGLNodes.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,21 @@ Material.prototype.onBeforeRender = function ( renderer, scene, camera, geometry
nodeFrame.object = object;
nodeFrame.renderer = renderer;

for ( const node of nodeBuilder.updateNodes ) {
const updateNodes = nodeBuilder.updateNodes;

nodeFrame.updateNode( node );
if ( updateNodes.length > 0 ) {

// force refresh material uniforms
renderer.state.useProgram( null );

//this.uniformsNeedUpdate = true;

for ( const node of updateNodes ) {

nodeFrame.updateNode( node );

}

}

}
Expand Down
Loading

0 comments on commit 70b9ae8

Please sign in to comment.