最新代码
This commit is contained in:
@ -0,0 +1,162 @@
|
||||
import NodeMaterial, { addNodeMaterial } from './NodeMaterial.js';
|
||||
import { varying } from '../core/VaryingNode.js';
|
||||
import { property } from '../core/PropertyNode.js';
|
||||
import { attribute } from '../core/AttributeNode.js';
|
||||
import { cameraProjectionMatrix } from '../accessors/CameraNode.js';
|
||||
import { materialColor, materialPointWidth } from '../accessors/MaterialNode.js'; // or should this be a property, instead?
|
||||
import { modelViewMatrix } from '../accessors/ModelNode.js';
|
||||
import { positionGeometry } from '../accessors/PositionNode.js';
|
||||
import { smoothstep } from '../math/MathNode.js';
|
||||
import { tslFn, vec2, vec4 } from '../shadernode/ShaderNode.js';
|
||||
import { uv } from '../accessors/UVNode.js';
|
||||
import { viewport } from '../display/ViewportNode.js';
|
||||
|
||||
import { PointsMaterial } from 'three';
|
||||
|
||||
const defaultValues = new PointsMaterial();
|
||||
|
||||
class InstancedPointsNodeMaterial extends NodeMaterial {
|
||||
|
||||
constructor( params = {} ) {
|
||||
|
||||
super();
|
||||
|
||||
this.normals = false;
|
||||
|
||||
this.lights = false;
|
||||
|
||||
this.useAlphaToCoverage = true;
|
||||
|
||||
this.useColor = params.vertexColors;
|
||||
|
||||
this.pointWidth = 1;
|
||||
|
||||
this.pointColorNode = null;
|
||||
|
||||
this.setDefaultValues( defaultValues );
|
||||
|
||||
this.setupShaders();
|
||||
|
||||
this.setValues( params );
|
||||
|
||||
}
|
||||
|
||||
setupShaders() {
|
||||
|
||||
const useAlphaToCoverage = this.alphaToCoverage;
|
||||
const useColor = this.useColor;
|
||||
|
||||
this.vertexNode = tslFn( () => {
|
||||
|
||||
//vUv = uv;
|
||||
varying( vec2(), 'vUv' ).assign( uv() ); // @TODO: Analyze other way to do this
|
||||
|
||||
const instancePosition = attribute( 'instancePosition' );
|
||||
|
||||
// camera space
|
||||
const mvPos = property( 'vec4', 'mvPos' );
|
||||
mvPos.assign( modelViewMatrix.mul( vec4( instancePosition, 1.0 ) ) );
|
||||
|
||||
const aspect = viewport.z.div( viewport.w );
|
||||
|
||||
// clip space
|
||||
const clipPos = cameraProjectionMatrix.mul( mvPos );
|
||||
|
||||
// offset in ndc space
|
||||
const offset = property( 'vec2', 'offset' );
|
||||
offset.assign( positionGeometry.xy );
|
||||
offset.assign( offset.mul( materialPointWidth ) );
|
||||
offset.assign( offset.div( viewport.z ) );
|
||||
offset.y.assign( offset.y.mul( aspect ) );
|
||||
|
||||
// back to clip space
|
||||
offset.assign( offset.mul( clipPos.w ) );
|
||||
|
||||
//clipPos.xy += offset;
|
||||
clipPos.assign( clipPos.add( vec4( offset, 0, 0 ) ) );
|
||||
|
||||
return clipPos;
|
||||
|
||||
//vec4 mvPosition = mvPos; // this was used for somethihng...
|
||||
|
||||
} )();
|
||||
|
||||
this.fragmentNode = tslFn( () => {
|
||||
|
||||
const vUv = varying( vec2(), 'vUv' );
|
||||
|
||||
// force assignment into correct place in flow
|
||||
const alpha = property( 'float', 'alpha' );
|
||||
alpha.assign( 1 );
|
||||
|
||||
const a = vUv.x;
|
||||
const b = vUv.y;
|
||||
|
||||
const len2 = a.mul( a ).add( b.mul( b ) );
|
||||
|
||||
if ( useAlphaToCoverage ) {
|
||||
|
||||
// force assignment out of following 'if' statement - to avoid uniform control flow errors
|
||||
const dlen = property( 'float', 'dlen' );
|
||||
dlen.assign( len2.fwidth() );
|
||||
|
||||
alpha.assign( smoothstep( dlen.oneMinus(), dlen.add( 1 ), len2 ).oneMinus() );
|
||||
|
||||
} else {
|
||||
|
||||
len2.greaterThan( 1.0 ).discard();
|
||||
|
||||
}
|
||||
|
||||
let pointColorNode;
|
||||
|
||||
if ( this.pointColorNode ) {
|
||||
|
||||
pointColorNode = this.pointColorNode;
|
||||
|
||||
} else {
|
||||
|
||||
if ( useColor ) {
|
||||
|
||||
const instanceColor = attribute( 'instanceColor' );
|
||||
|
||||
pointColorNode = instanceColor.mul( materialColor );
|
||||
|
||||
} else {
|
||||
|
||||
pointColorNode = materialColor;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return vec4( pointColorNode, alpha );
|
||||
|
||||
} )();
|
||||
|
||||
this.needsUpdate = true;
|
||||
|
||||
}
|
||||
|
||||
get alphaToCoverage() {
|
||||
|
||||
return this.useAlphaToCoverage;
|
||||
|
||||
}
|
||||
|
||||
set alphaToCoverage( value ) {
|
||||
|
||||
if ( this.useAlphaToCoverage !== value ) {
|
||||
|
||||
this.useAlphaToCoverage = value;
|
||||
this.setupShaders();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default InstancedPointsNodeMaterial;
|
||||
|
||||
addNodeMaterial( 'InstancedPointsNodeMaterial', InstancedPointsNodeMaterial );
|
440
public/sdk/three/jsm/nodes/materials/Line2NodeMaterial.js
Normal file
440
public/sdk/three/jsm/nodes/materials/Line2NodeMaterial.js
Normal file
@ -0,0 +1,440 @@
|
||||
import NodeMaterial, { addNodeMaterial } from './NodeMaterial.js';
|
||||
import { temp } from '../core/VarNode.js';
|
||||
import { varying } from '../core/VaryingNode.js';
|
||||
import { property, varyingProperty } from '../core/PropertyNode.js';
|
||||
import { attribute } from '../core/AttributeNode.js';
|
||||
import { cameraProjectionMatrix } from '../accessors/CameraNode.js';
|
||||
import { materialColor, materialLineScale, materialLineDashSize, materialLineGapSize, materialLineDashOffset, materialLineWidth } from '../accessors/MaterialNode.js';
|
||||
import { modelViewMatrix } from '../accessors/ModelNode.js';
|
||||
import { positionGeometry } from '../accessors/PositionNode.js';
|
||||
import { mix, smoothstep } from '../math/MathNode.js';
|
||||
import { tslFn, float, vec2, vec3, vec4, If } from '../shadernode/ShaderNode.js';
|
||||
import { uv } from '../accessors/UVNode.js';
|
||||
import { viewport } from '../display/ViewportNode.js';
|
||||
import { dashSize, gapSize } from '../core/PropertyNode.js';
|
||||
|
||||
import { LineDashedMaterial } from 'three';
|
||||
|
||||
const defaultValues = new LineDashedMaterial();
|
||||
|
||||
class Line2NodeMaterial extends NodeMaterial {
|
||||
|
||||
constructor( params = {} ) {
|
||||
|
||||
super();
|
||||
|
||||
this.normals = false;
|
||||
this.lights = false;
|
||||
|
||||
this.setDefaultValues( defaultValues );
|
||||
|
||||
this.useAlphaToCoverage = true;
|
||||
this.useColor = params.vertexColors;
|
||||
this.useDash = params.dashed;
|
||||
this.useWorldUnits = false;
|
||||
|
||||
this.dashOffset = 0;
|
||||
this.lineWidth = 1;
|
||||
|
||||
this.lineColorNode = null;
|
||||
|
||||
this.offsetNode = null;
|
||||
this.dashScaleNode = null;
|
||||
this.dashSizeNode = null;
|
||||
this.gapSizeNode = null;
|
||||
|
||||
this.setValues( params );
|
||||
|
||||
}
|
||||
|
||||
setup( builder ) {
|
||||
|
||||
this.setupShaders();
|
||||
|
||||
super.setup( builder );
|
||||
|
||||
}
|
||||
|
||||
setupShaders() {
|
||||
|
||||
const useAlphaToCoverage = this.alphaToCoverage;
|
||||
const useColor = this.useColor;
|
||||
const useDash = this.dashed;
|
||||
const useWorldUnits = this.worldUnits;
|
||||
|
||||
const trimSegment = tslFn( ( { start, end } ) => {
|
||||
|
||||
const a = cameraProjectionMatrix.element( 2 ).element( 2 ); // 3nd entry in 3th column
|
||||
const b = cameraProjectionMatrix.element( 3 ).element( 2 ); // 3nd entry in 4th column
|
||||
const nearEstimate = b.mul( - 0.5 ).div( a );
|
||||
|
||||
const alpha = nearEstimate.sub( start.z ).div( end.z.sub( start.z ) );
|
||||
|
||||
return vec4( mix( start.xyz, end.xyz, alpha ), end.w );
|
||||
|
||||
} );
|
||||
|
||||
this.vertexNode = tslFn( () => {
|
||||
|
||||
varyingProperty( 'vec2', 'vUv' ).assign( uv() );
|
||||
|
||||
const instanceStart = attribute( 'instanceStart' );
|
||||
const instanceEnd = attribute( 'instanceEnd' );
|
||||
|
||||
// camera space
|
||||
|
||||
const start = property( 'vec4', 'start' );
|
||||
const end = property( 'vec4', 'end' );
|
||||
|
||||
start.assign( modelViewMatrix.mul( vec4( instanceStart, 1.0 ) ) ); // force assignment into correct place in flow
|
||||
end.assign( modelViewMatrix.mul( vec4( instanceEnd, 1.0 ) ) );
|
||||
|
||||
if ( useWorldUnits ) {
|
||||
|
||||
varyingProperty( 'vec3', 'worldStart' ).assign( start.xyz );
|
||||
varyingProperty( 'vec3', 'worldEnd' ).assign( end.xyz );
|
||||
|
||||
}
|
||||
|
||||
const aspect = viewport.z.div( viewport.w );
|
||||
|
||||
// special case for perspective projection, and segments that terminate either in, or behind, the camera plane
|
||||
// clearly the gpu firmware has a way of addressing this issue when projecting into ndc space
|
||||
// but we need to perform ndc-space calculations in the shader, so we must address this issue directly
|
||||
// perhaps there is a more elegant solution -- WestLangley
|
||||
|
||||
const perspective = cameraProjectionMatrix.element( 2 ).element( 3 ).equal( - 1.0 ); // 4th entry in the 3rd column
|
||||
|
||||
If( perspective, () => {
|
||||
|
||||
If( start.z.lessThan( 0.0 ).and( end.z.greaterThan( 0.0 ) ), () => {
|
||||
|
||||
end.assign( trimSegment( { start: start, end: end } ) );
|
||||
|
||||
} ).elseif( end.z.lessThan( 0.0 ).and( start.z.greaterThanEqual( 0.0 ) ), () => {
|
||||
|
||||
start.assign( trimSegment( { start: end, end: start } ) );
|
||||
|
||||
} );
|
||||
|
||||
} );
|
||||
|
||||
// clip space
|
||||
const clipStart = cameraProjectionMatrix.mul( start );
|
||||
const clipEnd = cameraProjectionMatrix.mul( end );
|
||||
|
||||
// ndc space
|
||||
const ndcStart = clipStart.xyz.div( clipStart.w );
|
||||
const ndcEnd = clipEnd.xyz.div( clipEnd.w );
|
||||
|
||||
// direction
|
||||
const dir = ndcEnd.xy.sub( ndcStart.xy ).temp();
|
||||
|
||||
// account for clip-space aspect ratio
|
||||
dir.x.assign( dir.x.mul( aspect ) );
|
||||
dir.assign( dir.normalize() );
|
||||
|
||||
const clip = temp( vec4() );
|
||||
|
||||
if ( useWorldUnits ) {
|
||||
|
||||
// get the offset direction as perpendicular to the view vector
|
||||
|
||||
const worldDir = end.xyz.sub( start.xyz ).normalize();
|
||||
const tmpFwd = mix( start.xyz, end.xyz, 0.5 ).normalize();
|
||||
const worldUp = worldDir.cross( tmpFwd ).normalize();
|
||||
const worldFwd = worldDir.cross( worldUp );
|
||||
|
||||
const worldPos = varyingProperty( 'vec4', 'worldPos' );
|
||||
|
||||
worldPos.assign( positionGeometry.y.lessThan( 0.5 ).cond( start, end) );
|
||||
|
||||
// height offset
|
||||
const hw = materialLineWidth.mul( 0.5 );
|
||||
worldPos.addAssign( vec4( positionGeometry.x.lessThan( 0.0 ).cond( worldUp.mul( hw ), worldUp.mul( hw ).negate() ), 0 ) );
|
||||
|
||||
// don't extend the line if we're rendering dashes because we
|
||||
// won't be rendering the endcaps
|
||||
if ( ! useDash ) {
|
||||
|
||||
// cap extension
|
||||
worldPos.addAssign( vec4( positionGeometry.y.lessThan( 0.5 ).cond( worldDir.mul( hw ).negate(), worldDir.mul( hw ) ), 0 ) );
|
||||
|
||||
// add width to the box
|
||||
worldPos.addAssign( vec4( worldFwd.mul( hw ), 0 ) );
|
||||
|
||||
// endcaps
|
||||
If( positionGeometry.y.greaterThan( 1.0 ).or( positionGeometry.y.lessThan( 0.0 ) ), () => {
|
||||
|
||||
worldPos.subAssign( vec4( worldFwd.mul( 2.0 ).mul( hw ), 0 ) );
|
||||
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
// project the worldpos
|
||||
clip.assign( cameraProjectionMatrix.mul( worldPos ) );
|
||||
|
||||
// shift the depth of the projected points so the line
|
||||
// segments overlap neatly
|
||||
const clipPose = temp( vec3() );
|
||||
|
||||
clipPose.assign( positionGeometry.y.lessThan( 0.5 ).cond( ndcStart, ndcEnd ) );
|
||||
clip.z.assign( clipPose.z.mul( clip.w ) );
|
||||
|
||||
} else {
|
||||
|
||||
const offset = property( 'vec2', 'offset' );
|
||||
|
||||
offset.assign( vec2( dir.y, dir.x.negate() ) );
|
||||
|
||||
// undo aspect ratio adjustment
|
||||
dir.x.assign( dir.x.div( aspect ) );
|
||||
offset.x.assign( offset.x.div( aspect ) );
|
||||
|
||||
// sign flip
|
||||
offset.assign( positionGeometry.x.lessThan( 0.0 ).cond( offset.negate(), offset ) );
|
||||
|
||||
// endcaps
|
||||
If( positionGeometry.y.lessThan( 0.0 ), () => {
|
||||
|
||||
offset.assign( offset.sub( dir ) );
|
||||
|
||||
} ).elseif( positionGeometry.y.greaterThan( 1.0 ), () => {
|
||||
|
||||
offset.assign( offset.add( dir ) );
|
||||
|
||||
} );
|
||||
|
||||
// adjust for linewidth
|
||||
offset.assign( offset.mul( materialLineWidth ) );
|
||||
|
||||
// adjust for clip-space to screen-space conversion // maybe resolution should be based on viewport ...
|
||||
offset.assign( offset.div( viewport.w ) );
|
||||
|
||||
// select end
|
||||
clip.assign( positionGeometry.y.lessThan( 0.5 ).cond( clipStart, clipEnd ) );
|
||||
|
||||
// back to clip space
|
||||
offset.assign( offset.mul( clip.w ) );
|
||||
|
||||
clip.assign( clip.add( vec4( offset, 0, 0 ) ) );
|
||||
|
||||
}
|
||||
|
||||
return clip;
|
||||
|
||||
} )();
|
||||
|
||||
const closestLineToLine = tslFn( ( { p1, p2, p3, p4 } ) => {
|
||||
|
||||
const p13 = p1.sub( p3 );
|
||||
const p43 = p4.sub( p3 );
|
||||
|
||||
const p21 = p2.sub( p1 );
|
||||
|
||||
const d1343 = p13.dot( p43 );
|
||||
const d4321 = p43.dot( p21 );
|
||||
const d1321 = p13.dot( p21 );
|
||||
const d4343 = p43.dot( p43 );
|
||||
const d2121 = p21.dot( p21 );
|
||||
|
||||
const denom = d2121.mul( d4343 ).sub( d4321.mul( d4321 ) );
|
||||
const numer = d1343.mul( d4321 ).sub( d1321.mul( d4343 ) );
|
||||
|
||||
const mua = numer.div( denom ).clamp();
|
||||
const mub = d1343.add( d4321.mul( mua ) ).div( d4343 ).clamp();
|
||||
|
||||
return vec2( mua, mub );
|
||||
|
||||
} );
|
||||
|
||||
this.fragmentNode = tslFn( () => {
|
||||
|
||||
const vUv = varyingProperty( 'vec2', 'vUv' );
|
||||
|
||||
if ( useDash ) {
|
||||
|
||||
const offsetNode = this.offsetNode ? float( this.offsetNodeNode ) : materialLineDashOffset;
|
||||
const dashScaleNode = this.dashScaleNode ? float( this.dashScaleNode ) : materialLineScale;
|
||||
const dashSizeNode = this.dashSizeNode ? float( this.dashSizeNode ) : materialLineDashSize;
|
||||
const gapSizeNode = this.dashSizeNode ? float( this.dashGapNode ) : materialLineGapSize;
|
||||
|
||||
dashSize.assign( dashSizeNode );
|
||||
gapSize.assign( gapSizeNode );
|
||||
|
||||
const instanceDistanceStart = attribute( 'instanceDistanceStart' );
|
||||
const instanceDistanceEnd = attribute( 'instanceDistanceEnd' );
|
||||
|
||||
const lineDistance = positionGeometry.y.lessThan( 0.5 ).cond( dashScaleNode.mul( instanceDistanceStart ), materialLineScale.mul( instanceDistanceEnd ) );
|
||||
|
||||
const vLineDistance = varying( lineDistance.add( materialLineDashOffset ) );
|
||||
const vLineDistanceOffset = offsetNode ? vLineDistance.add( offsetNode ) : vLineDistance;
|
||||
|
||||
vUv.y.lessThan( - 1.0 ).or( vUv.y.greaterThan( 1.0 ) ).discard(); // discard endcaps
|
||||
vLineDistanceOffset.mod( dashSize.add( gapSize ) ).greaterThan( dashSize ).discard(); // todo - FIX
|
||||
|
||||
}
|
||||
|
||||
// force assignment into correct place in flow
|
||||
const alpha = property( 'float', 'alpha' );
|
||||
alpha.assign( 1 );
|
||||
|
||||
if ( useWorldUnits ) {
|
||||
|
||||
const worldStart = varyingProperty( 'vec3', 'worldStart' );
|
||||
const worldEnd = varyingProperty( 'vec3', 'worldEnd' );
|
||||
|
||||
// Find the closest points on the view ray and the line segment
|
||||
const rayEnd = varyingProperty( 'vec4', 'worldPos' ).xyz.normalize().mul( 1e5 );
|
||||
const lineDir = worldEnd.sub( worldStart );
|
||||
const params = closestLineToLine( { p1: worldStart, p2: worldEnd, p3: vec3( 0.0, 0.0, 0.0 ), p4: rayEnd } );
|
||||
|
||||
const p1 = worldStart.add( lineDir.mul( params.x ) );
|
||||
const p2 = rayEnd.mul( params.y );
|
||||
const delta = p1.sub( p2 );
|
||||
const len = delta.length();
|
||||
const norm = len.div( materialLineWidth );
|
||||
|
||||
if ( ! useDash ) {
|
||||
|
||||
if ( useAlphaToCoverage ) {
|
||||
|
||||
const dnorm = norm.fwidth();
|
||||
alpha.assign( smoothstep( dnorm.negate().add( 0.5 ), dnorm.add( 0.5 ), norm ).oneMinus() );
|
||||
|
||||
} else {
|
||||
|
||||
norm.greaterThan( 0.5 ).discard();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// round endcaps
|
||||
|
||||
if ( useAlphaToCoverage ) {
|
||||
|
||||
const a = vUv.x;
|
||||
const b = vUv.y.greaterThan( 0.0 ).cond( vUv.y.sub( 1.0 ), vUv.y.add( 1.0 ) );
|
||||
|
||||
const len2 = a.mul( a ).add( b.mul( b ) );
|
||||
|
||||
// force assignment out of following 'if' statement - to avoid uniform control flow errors
|
||||
const dlen = property( 'float', 'dlen' );
|
||||
dlen.assign( len2.fwidth() );
|
||||
|
||||
If( vUv.y.abs().greaterThan( 1.0 ), () => {
|
||||
|
||||
alpha.assign( smoothstep( dlen.oneMinus(), dlen.add( 1 ), len2 ).oneMinus() );
|
||||
|
||||
} );
|
||||
|
||||
} else {
|
||||
|
||||
If( vUv.y.abs().greaterThan( 1.0 ), () => {
|
||||
|
||||
const a = vUv.x;
|
||||
const b = vUv.y.greaterThan( 0.0 ).cond( vUv.y.sub( 1.0 ), vUv.y.add( 1.0 ) );
|
||||
const len2 = a.mul( a ).add( b.mul( b ) );
|
||||
|
||||
len2.greaterThan( 1.0 ).discard();
|
||||
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
let lineColorNode;
|
||||
|
||||
if ( this.lineColorNode ) {
|
||||
|
||||
lineColorNode = this.lineColorNode;
|
||||
|
||||
} else {
|
||||
|
||||
if ( useColor ) {
|
||||
|
||||
const instanceColorStart = attribute( 'instanceColorStart' );
|
||||
const instanceColorEnd = attribute( 'instanceColorEnd' );
|
||||
|
||||
const instanceColor = positionGeometry.y.lessThan( 0.5 ).cond( instanceColorStart, instanceColorEnd );
|
||||
|
||||
lineColorNode = instanceColor.mul( materialColor );
|
||||
|
||||
} else {
|
||||
|
||||
lineColorNode = materialColor;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return vec4( lineColorNode, alpha );
|
||||
|
||||
} )();
|
||||
|
||||
}
|
||||
|
||||
|
||||
get worldUnits() {
|
||||
|
||||
return this.useWorldUnits;
|
||||
|
||||
}
|
||||
|
||||
set worldUnits( value ) {
|
||||
|
||||
if ( this.useWorldUnits !== value ) {
|
||||
|
||||
this.useWorldUnits = value;
|
||||
this.needsUpdate = true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
get dashed() {
|
||||
|
||||
return this.useDash;
|
||||
|
||||
}
|
||||
|
||||
set dashed( value ) {
|
||||
|
||||
if ( this.useDash !== value ) {
|
||||
|
||||
this.useDash = value;
|
||||
this.needsUpdate = true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
get alphaToCoverage() {
|
||||
|
||||
return this.useAlphaToCoverage;
|
||||
|
||||
}
|
||||
|
||||
set alphaToCoverage( value ) {
|
||||
|
||||
if ( this.useAlphaToCoverage !== value ) {
|
||||
|
||||
this.useAlphaToCoverage = value;
|
||||
this.needsUpdate = true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default Line2NodeMaterial;
|
||||
|
||||
addNodeMaterial( 'Line2NodeMaterial', Line2NodeMaterial );
|
@ -0,0 +1,28 @@
|
||||
import NodeMaterial, { addNodeMaterial } from './NodeMaterial.js';
|
||||
|
||||
import { LineBasicMaterial } from 'three';
|
||||
|
||||
const defaultValues = new LineBasicMaterial();
|
||||
|
||||
class LineBasicNodeMaterial extends NodeMaterial {
|
||||
|
||||
constructor( parameters ) {
|
||||
|
||||
super();
|
||||
|
||||
this.isLineBasicNodeMaterial = true;
|
||||
|
||||
this.lights = false;
|
||||
this.normals = false;
|
||||
|
||||
this.setDefaultValues( defaultValues );
|
||||
|
||||
this.setValues( parameters );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default LineBasicNodeMaterial;
|
||||
|
||||
addNodeMaterial( 'LineBasicNodeMaterial', LineBasicNodeMaterial );
|
@ -0,0 +1,54 @@
|
||||
import NodeMaterial, { addNodeMaterial } from './NodeMaterial.js';
|
||||
import { attribute } from '../core/AttributeNode.js';
|
||||
import { varying } from '../core/VaryingNode.js';
|
||||
import { materialLineDashSize, materialLineGapSize, materialLineScale } from '../accessors/MaterialNode.js';
|
||||
import { dashSize, gapSize } from '../core/PropertyNode.js';
|
||||
import { float } from '../shadernode/ShaderNode.js';
|
||||
import { LineDashedMaterial } from 'three';
|
||||
|
||||
const defaultValues = new LineDashedMaterial();
|
||||
|
||||
class LineDashedNodeMaterial extends NodeMaterial {
|
||||
|
||||
constructor( parameters ) {
|
||||
|
||||
super();
|
||||
|
||||
this.isLineDashedNodeMaterial = true;
|
||||
|
||||
this.lights = false;
|
||||
this.normals = false;
|
||||
|
||||
this.setDefaultValues( defaultValues );
|
||||
|
||||
this.offsetNode = null;
|
||||
this.dashScaleNode = null;
|
||||
this.dashSizeNode = null;
|
||||
this.gapSizeNode = null;
|
||||
|
||||
this.setValues( parameters );
|
||||
|
||||
}
|
||||
|
||||
setupVariants() {
|
||||
|
||||
const offsetNode = this.offsetNode;
|
||||
const dashScaleNode = this.dashScaleNode ? float( this.dashScaleNode ) : materialLineScale;
|
||||
const dashSizeNode = this.dashSizeNode ? float( this.dashSizeNode ) : materialLineDashSize;
|
||||
const gapSizeNode = this.dashSizeNode ? float( this.dashGapNode ) : materialLineGapSize;
|
||||
|
||||
dashSize.assign( dashSizeNode );
|
||||
gapSize.assign( gapSizeNode );
|
||||
|
||||
const vLineDistance = varying( attribute( 'lineDistance' ).mul( dashScaleNode ) );
|
||||
const vLineDistanceOffset = offsetNode ? vLineDistance.add( offsetNode ) : vLineDistance;
|
||||
|
||||
vLineDistanceOffset.mod( dashSize.add( gapSize ) ).greaterThan( dashSize ).discard();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default LineDashedNodeMaterial;
|
||||
|
||||
addNodeMaterial( 'LineDashedNodeMaterial', LineDashedNodeMaterial );
|
17
public/sdk/three/jsm/nodes/materials/Materials.js
Normal file
17
public/sdk/three/jsm/nodes/materials/Materials.js
Normal file
@ -0,0 +1,17 @@
|
||||
// @TODO: We can simplify "export { default as SomeNode, other, exports } from '...'" to just "export * from '...'" if we will use only named exports
|
||||
|
||||
export { default as NodeMaterial, addNodeMaterial, createNodeMaterialFromType } from './NodeMaterial.js';
|
||||
export { default as InstancedPointsNodeMaterial } from './InstancedPointsNodeMaterial.js';
|
||||
export { default as LineBasicNodeMaterial } from './LineBasicNodeMaterial.js';
|
||||
export { default as LineDashedNodeMaterial } from './LineDashedNodeMaterial.js';
|
||||
export { default as Line2NodeMaterial } from './Line2NodeMaterial.js';
|
||||
export { default as MeshNormalNodeMaterial } from './MeshNormalNodeMaterial.js';
|
||||
export { default as MeshBasicNodeMaterial } from './MeshBasicNodeMaterial.js';
|
||||
export { default as MeshLambertNodeMaterial } from './MeshLambertNodeMaterial.js';
|
||||
export { default as MeshPhongNodeMaterial } from './MeshPhongNodeMaterial.js';
|
||||
export { default as MeshStandardNodeMaterial } from './MeshStandardNodeMaterial.js';
|
||||
export { default as MeshPhysicalNodeMaterial } from './MeshPhysicalNodeMaterial.js';
|
||||
export { default as MeshSSSNodeMaterial } from './MeshSSSNodeMaterial.js';
|
||||
export { default as PointsNodeMaterial } from './PointsNodeMaterial.js';
|
||||
export { default as SpriteNodeMaterial } from './SpriteNodeMaterial.js';
|
||||
export { default as ShadowNodeMaterial } from './ShadowNodeMaterial.js';
|
@ -0,0 +1,28 @@
|
||||
import NodeMaterial, { addNodeMaterial } from './NodeMaterial.js';
|
||||
|
||||
import { MeshBasicMaterial } from 'three';
|
||||
|
||||
const defaultValues = new MeshBasicMaterial();
|
||||
|
||||
class MeshBasicNodeMaterial extends NodeMaterial {
|
||||
|
||||
constructor( parameters ) {
|
||||
|
||||
super();
|
||||
|
||||
this.isMeshBasicNodeMaterial = true;
|
||||
|
||||
this.lights = false;
|
||||
//this.normals = false; @TODO: normals usage by context
|
||||
|
||||
this.setDefaultValues( defaultValues );
|
||||
|
||||
this.setValues( parameters );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default MeshBasicNodeMaterial;
|
||||
|
||||
addNodeMaterial( 'MeshBasicNodeMaterial', MeshBasicNodeMaterial );
|
@ -0,0 +1,34 @@
|
||||
import NodeMaterial, { addNodeMaterial } from './NodeMaterial.js';
|
||||
import PhongLightingModel from '../functions/PhongLightingModel.js';
|
||||
|
||||
import { MeshLambertMaterial } from 'three';
|
||||
|
||||
const defaultValues = new MeshLambertMaterial();
|
||||
|
||||
class MeshLambertNodeMaterial extends NodeMaterial {
|
||||
|
||||
constructor( parameters ) {
|
||||
|
||||
super();
|
||||
|
||||
this.isMeshLambertNodeMaterial = true;
|
||||
|
||||
this.lights = true;
|
||||
|
||||
this.setDefaultValues( defaultValues );
|
||||
|
||||
this.setValues( parameters );
|
||||
|
||||
}
|
||||
|
||||
setupLightingModel( /*builder*/ ) {
|
||||
|
||||
return new PhongLightingModel( false ); // ( specular ) -> force lambert
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default MeshLambertNodeMaterial;
|
||||
|
||||
addNodeMaterial( 'MeshLambertNodeMaterial', MeshLambertNodeMaterial );
|
@ -0,0 +1,38 @@
|
||||
import NodeMaterial, { addNodeMaterial } from './NodeMaterial.js';
|
||||
import { diffuseColor } from '../core/PropertyNode.js';
|
||||
import { directionToColor } from '../utils/PackingNode.js';
|
||||
import { materialOpacity } from '../accessors/MaterialNode.js';
|
||||
import { transformedNormalView } from '../accessors/NormalNode.js';
|
||||
import { float, vec4 } from '../shadernode/ShaderNode.js';
|
||||
|
||||
import { MeshNormalMaterial } from 'three';
|
||||
|
||||
const defaultValues = new MeshNormalMaterial();
|
||||
|
||||
class MeshNormalNodeMaterial extends NodeMaterial {
|
||||
|
||||
constructor( parameters ) {
|
||||
|
||||
super();
|
||||
|
||||
this.isMeshNormalNodeMaterial = true;
|
||||
|
||||
this.setDefaultValues( defaultValues );
|
||||
|
||||
this.setValues( parameters );
|
||||
|
||||
}
|
||||
|
||||
setupDiffuseColor() {
|
||||
|
||||
const opacityNode = this.opacityNode ? float( this.opacityNode ) : materialOpacity;
|
||||
|
||||
diffuseColor.assign( vec4( directionToColor( transformedNormalView ), opacityNode ) );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default MeshNormalNodeMaterial;
|
||||
|
||||
addNodeMaterial( 'MeshNormalNodeMaterial', MeshNormalNodeMaterial );
|
@ -0,0 +1,65 @@
|
||||
import NodeMaterial, { addNodeMaterial } from './NodeMaterial.js';
|
||||
import { shininess, specularColor } from '../core/PropertyNode.js';
|
||||
import { materialShininess, materialSpecular } from '../accessors/MaterialNode.js';
|
||||
import { float } from '../shadernode/ShaderNode.js';
|
||||
import PhongLightingModel from '../functions/PhongLightingModel.js';
|
||||
|
||||
import { MeshPhongMaterial } from 'three';
|
||||
|
||||
const defaultValues = new MeshPhongMaterial();
|
||||
|
||||
class MeshPhongNodeMaterial extends NodeMaterial {
|
||||
|
||||
constructor( parameters ) {
|
||||
|
||||
super();
|
||||
|
||||
this.isMeshPhongNodeMaterial = true;
|
||||
|
||||
this.lights = true;
|
||||
|
||||
this.shininessNode = null;
|
||||
this.specularNode = null;
|
||||
|
||||
this.setDefaultValues( defaultValues );
|
||||
|
||||
this.setValues( parameters );
|
||||
|
||||
}
|
||||
|
||||
setupLightingModel( /*builder*/ ) {
|
||||
|
||||
return new PhongLightingModel();
|
||||
|
||||
}
|
||||
|
||||
setupVariants() {
|
||||
|
||||
// SHININESS
|
||||
|
||||
const shininessNode = ( this.shininessNode ? float( this.shininessNode ) : materialShininess ).max( 1e-4 ); // to prevent pow( 0.0, 0.0 )
|
||||
|
||||
shininess.assign( shininessNode );
|
||||
|
||||
// SPECULAR COLOR
|
||||
|
||||
const specularNode = this.specularNode || materialSpecular;
|
||||
|
||||
specularColor.assign( specularNode );
|
||||
|
||||
}
|
||||
|
||||
copy( source ) {
|
||||
|
||||
this.shininessNode = source.shininessNode;
|
||||
this.specularNode = source.specularNode;
|
||||
|
||||
return super.copy( source );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default MeshPhongNodeMaterial;
|
||||
|
||||
addNodeMaterial( 'MeshPhongNodeMaterial', MeshPhongNodeMaterial );
|
226
public/sdk/three/jsm/nodes/materials/MeshPhysicalNodeMaterial.js
Normal file
226
public/sdk/three/jsm/nodes/materials/MeshPhysicalNodeMaterial.js
Normal file
@ -0,0 +1,226 @@
|
||||
import { addNodeMaterial } from './NodeMaterial.js';
|
||||
import { transformedClearcoatNormalView } from '../accessors/NormalNode.js';
|
||||
import { clearcoat, clearcoatRoughness, sheen, sheenRoughness, iridescence, iridescenceIOR, iridescenceThickness, specularColor, specularF90, diffuseColor, metalness, roughness, anisotropy, alphaT, anisotropyT, anisotropyB, ior, transmission, thickness, attenuationDistance, attenuationColor } from '../core/PropertyNode.js';
|
||||
import { materialClearcoat, materialClearcoatRoughness, materialClearcoatNormal, materialSheen, materialSheenRoughness, materialIridescence, materialIridescenceIOR, materialIridescenceThickness, materialSpecularIntensity, materialSpecularColor, materialAnisotropy, materialIOR, materialTransmission, materialThickness, materialAttenuationDistance, materialAttenuationColor } from '../accessors/MaterialNode.js';
|
||||
import { float, vec2, vec3, If } from '../shadernode/ShaderNode.js';
|
||||
import { TBNViewMatrix } from '../accessors/AccessorsUtils.js';
|
||||
import PhysicalLightingModel from '../functions/PhysicalLightingModel.js';
|
||||
import MeshStandardNodeMaterial from './MeshStandardNodeMaterial.js';
|
||||
import { mix, pow2, min } from '../math/MathNode.js';
|
||||
import { MeshPhysicalMaterial } from 'three';
|
||||
|
||||
const defaultValues = new MeshPhysicalMaterial();
|
||||
|
||||
class MeshPhysicalNodeMaterial extends MeshStandardNodeMaterial {
|
||||
|
||||
constructor( parameters ) {
|
||||
|
||||
super();
|
||||
|
||||
this.isMeshPhysicalNodeMaterial = true;
|
||||
|
||||
this.clearcoatNode = null;
|
||||
this.clearcoatRoughnessNode = null;
|
||||
this.clearcoatNormalNode = null;
|
||||
|
||||
this.sheenNode = null;
|
||||
this.sheenRoughnessNode = null;
|
||||
|
||||
this.iridescenceNode = null;
|
||||
this.iridescenceIORNode = null;
|
||||
this.iridescenceThicknessNode = null;
|
||||
|
||||
this.specularIntensityNode = null;
|
||||
this.specularColorNode = null;
|
||||
|
||||
this.iorNode = null;
|
||||
this.transmissionNode = null;
|
||||
this.thicknessNode = null;
|
||||
this.attenuationDistanceNode = null;
|
||||
this.attenuationColorNode = null;
|
||||
|
||||
this.anisotropyNode = null;
|
||||
|
||||
this.setDefaultValues( defaultValues );
|
||||
|
||||
this.setValues( parameters );
|
||||
|
||||
}
|
||||
|
||||
get useClearcoat() {
|
||||
|
||||
return this.clearcoat > 0 || this.clearcoatNode !== null;
|
||||
|
||||
}
|
||||
|
||||
get useIridescence() {
|
||||
|
||||
return this.iridescence > 0 || this.iridescenceNode !== null;
|
||||
|
||||
}
|
||||
|
||||
get useSheen() {
|
||||
|
||||
return this.sheen > 0 || this.sheenNode !== null;
|
||||
|
||||
}
|
||||
|
||||
get useAnisotropy() {
|
||||
|
||||
return this.anisotropy > 0 || this.anisotropyNode !== null;
|
||||
|
||||
}
|
||||
|
||||
get useTransmission() {
|
||||
|
||||
return this.transmission > 0 || this.transmissionNode !== null;
|
||||
|
||||
}
|
||||
|
||||
setupSpecular() {
|
||||
|
||||
const iorNode = this.iorNode ? float( this.iorNode ) : materialIOR;
|
||||
|
||||
ior.assign( iorNode );
|
||||
specularColor.assign( mix( min( pow2( ior.sub( 1.0 ).div( ior.add( 1.0 ) ) ).mul( materialSpecularColor ), vec3( 1.0 ) ).mul( materialSpecularIntensity ), diffuseColor.rgb, metalness ) );
|
||||
specularF90.assign( mix( materialSpecularIntensity, 1.0, metalness ) );
|
||||
|
||||
}
|
||||
|
||||
setupLightingModel( /*builder*/ ) {
|
||||
|
||||
return new PhysicalLightingModel( this.useClearcoat, this.useSheen, this.useIridescence, this.useAnisotropy, this.useTransmission );
|
||||
|
||||
}
|
||||
|
||||
setupVariants( builder ) {
|
||||
|
||||
super.setupVariants( builder );
|
||||
|
||||
// CLEARCOAT
|
||||
|
||||
if ( this.useClearcoat ) {
|
||||
|
||||
const clearcoatNode = this.clearcoatNode ? float( this.clearcoatNode ) : materialClearcoat;
|
||||
const clearcoatRoughnessNode = this.clearcoatRoughnessNode ? float( this.clearcoatRoughnessNode ) : materialClearcoatRoughness;
|
||||
|
||||
clearcoat.assign( clearcoatNode );
|
||||
clearcoatRoughness.assign( clearcoatRoughnessNode );
|
||||
|
||||
}
|
||||
|
||||
// SHEEN
|
||||
|
||||
if ( this.useSheen ) {
|
||||
|
||||
const sheenNode = this.sheenNode ? vec3( this.sheenNode ) : materialSheen;
|
||||
const sheenRoughnessNode = this.sheenRoughnessNode ? float( this.sheenRoughnessNode ) : materialSheenRoughness;
|
||||
|
||||
sheen.assign( sheenNode );
|
||||
sheenRoughness.assign( sheenRoughnessNode );
|
||||
|
||||
}
|
||||
|
||||
// IRIDESCENCE
|
||||
|
||||
if ( this.useIridescence ) {
|
||||
|
||||
const iridescenceNode = this.iridescenceNode ? float( this.iridescenceNode ) : materialIridescence;
|
||||
const iridescenceIORNode = this.iridescenceIORNode ? float( this.iridescenceIORNode ) : materialIridescenceIOR;
|
||||
const iridescenceThicknessNode = this.iridescenceThicknessNode ? float( this.iridescenceThicknessNode ) : materialIridescenceThickness;
|
||||
|
||||
iridescence.assign( iridescenceNode );
|
||||
iridescenceIOR.assign( iridescenceIORNode );
|
||||
iridescenceThickness.assign( iridescenceThicknessNode );
|
||||
|
||||
}
|
||||
|
||||
// ANISOTROPY
|
||||
|
||||
if ( this.useAnisotropy ) {
|
||||
|
||||
const anisotropyV = ( this.anisotropyNode ? vec2( this.anisotropyNode ) : materialAnisotropy ).toVar();
|
||||
|
||||
anisotropy.assign( anisotropyV.length() );
|
||||
|
||||
If( anisotropy.equal( 0.0 ), () => {
|
||||
|
||||
anisotropyV.assign( vec2( 1.0, 0.0 ) );
|
||||
|
||||
} ).else( () => {
|
||||
|
||||
anisotropyV.divAssign( anisotropy );
|
||||
anisotropy.assign( anisotropy.saturate() );
|
||||
|
||||
} );
|
||||
|
||||
// Roughness along the anisotropy bitangent is the material roughness, while the tangent roughness increases with anisotropy.
|
||||
alphaT.assign( anisotropy.pow2().mix( roughness.pow2(), 1.0 ) );
|
||||
|
||||
anisotropyT.assign( TBNViewMatrix[ 0 ].mul( anisotropyV.x ).add( TBNViewMatrix[ 1 ].mul( anisotropyV.y ) ) );
|
||||
anisotropyB.assign( TBNViewMatrix[ 1 ].mul( anisotropyV.x ).sub( TBNViewMatrix[ 0 ].mul( anisotropyV.y ) ) );
|
||||
|
||||
}
|
||||
|
||||
// TRANSMISSION
|
||||
|
||||
if ( this.useTransmission ) {
|
||||
|
||||
const transmissionNode = this.transmissionNode ? float( this.transmissionNode ) : materialTransmission;
|
||||
const thicknessNode = this.thicknessNode ? float( this.thicknessNode ) : materialThickness;
|
||||
const attenuationDistanceNode = this.attenuationDistanceNode ? float( this.attenuationDistanceNode ) : materialAttenuationDistance;
|
||||
const attenuationColorNode = this.attenuationColorNode ? vec3( this.attenuationColorNode ) : materialAttenuationColor;
|
||||
|
||||
transmission.assign( transmissionNode );
|
||||
thickness.assign( thicknessNode );
|
||||
attenuationDistance.assign( attenuationDistanceNode );
|
||||
attenuationColor.assign( attenuationColorNode );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
setupNormal( builder ) {
|
||||
|
||||
super.setupNormal( builder );
|
||||
|
||||
// CLEARCOAT NORMAL
|
||||
|
||||
const clearcoatNormalNode = this.clearcoatNormalNode ? vec3( this.clearcoatNormalNode ) : materialClearcoatNormal;
|
||||
|
||||
transformedClearcoatNormalView.assign( clearcoatNormalNode );
|
||||
|
||||
}
|
||||
|
||||
copy( source ) {
|
||||
|
||||
this.clearcoatNode = source.clearcoatNode;
|
||||
this.clearcoatRoughnessNode = source.clearcoatRoughnessNode;
|
||||
this.clearcoatNormalNode = source.clearcoatNormalNode;
|
||||
|
||||
this.sheenNode = source.sheenNode;
|
||||
this.sheenRoughnessNode = source.sheenRoughnessNode;
|
||||
|
||||
this.iridescenceNode = source.iridescenceNode;
|
||||
this.iridescenceIORNode = source.iridescenceIORNode;
|
||||
this.iridescenceThicknessNode = source.iridescenceThicknessNode;
|
||||
|
||||
this.specularIntensityNode = source.specularIntensityNode;
|
||||
this.specularColorNode = source.specularColorNode;
|
||||
|
||||
this.transmissionNode = source.transmissionNode;
|
||||
this.thicknessNode = source.thicknessNode;
|
||||
this.attenuationDistanceNode = source.attenuationDistanceNode;
|
||||
this.attenuationColorNode = source.attenuationColorNode;
|
||||
|
||||
this.anisotropyNode = source.anisotropyNode;
|
||||
|
||||
return super.copy( source );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default MeshPhysicalNodeMaterial;
|
||||
|
||||
addNodeMaterial( 'MeshPhysicalNodeMaterial', MeshPhysicalNodeMaterial );
|
84
public/sdk/three/jsm/nodes/materials/MeshSSSNodeMaterial.js
Normal file
84
public/sdk/three/jsm/nodes/materials/MeshSSSNodeMaterial.js
Normal file
@ -0,0 +1,84 @@
|
||||
import { addNodeMaterial } from './NodeMaterial.js';
|
||||
import { transformedNormalView } from '../accessors/NormalNode.js';
|
||||
import { positionViewDirection } from '../accessors/PositionNode.js';
|
||||
import PhysicalLightingModel from '../functions/PhysicalLightingModel.js';
|
||||
import MeshPhysicalNodeMaterial from './MeshPhysicalNodeMaterial.js';
|
||||
import { float, vec3 } from '../shadernode/ShaderNode.js';
|
||||
|
||||
class SSSLightingModel extends PhysicalLightingModel {
|
||||
|
||||
constructor( useClearcoat, useSheen, useIridescence, useSSS ) {
|
||||
|
||||
super( useClearcoat, useSheen, useIridescence );
|
||||
|
||||
this.useSSS = useSSS;
|
||||
|
||||
}
|
||||
|
||||
direct( { lightDirection, lightColor, reflectedLight }, stack, builder ) {
|
||||
|
||||
if ( this.useSSS === true ) {
|
||||
|
||||
const material = builder.material;
|
||||
|
||||
const { thicknessColorNode, thicknessDistortionNode, thicknessAmbientNode, thicknessAttenuationNode, thicknessPowerNode, thicknessScaleNode } = material;
|
||||
|
||||
const scatteringHalf = lightDirection.add( transformedNormalView.mul( thicknessDistortionNode ) ).normalize();
|
||||
const scatteringDot = float( positionViewDirection.dot( scatteringHalf.negate() ).saturate().pow( thicknessPowerNode ).mul( thicknessScaleNode ) );
|
||||
const scatteringIllu = vec3( scatteringDot.add( thicknessAmbientNode ).mul( thicknessColorNode ) );
|
||||
|
||||
reflectedLight.directDiffuse.addAssign( scatteringIllu.mul( thicknessAttenuationNode.mul( lightColor ) ) );
|
||||
|
||||
}
|
||||
|
||||
super.direct( { lightDirection, lightColor, reflectedLight }, stack, builder );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class MeshSSSNodeMaterial extends MeshPhysicalNodeMaterial {
|
||||
|
||||
constructor( parameters ) {
|
||||
|
||||
super( parameters );
|
||||
|
||||
this.thicknessColorNode = null;
|
||||
this.thicknessDistortionNode = float( 0.1 );
|
||||
this.thicknessAmbientNode = float( 0.0 );
|
||||
this.thicknessAttenuationNode = float( .1 );
|
||||
this.thicknessPowerNode = float( 2.0 );
|
||||
this.thicknessScaleNode = float( 10.0 );
|
||||
|
||||
}
|
||||
|
||||
get useSSS() {
|
||||
|
||||
return this.thicknessColorNode !== null;
|
||||
|
||||
}
|
||||
|
||||
setupLightingModel( /*builder*/ ) {
|
||||
|
||||
return new SSSLightingModel( this.useClearcoat, this.useSheen, this.useIridescence, this.useSSS );
|
||||
|
||||
}
|
||||
|
||||
copy( source ) {
|
||||
|
||||
this.thicknessColorNode = source.thicknessColorNode;
|
||||
this.thicknessDistortionNode = source.thicknessDistortionNode;
|
||||
this.thicknessAmbientNode = source.thicknessAmbientNode;
|
||||
this.thicknessAttenuationNode = source.thicknessAttenuationNode;
|
||||
this.thicknessPowerNode = source.thicknessPowerNode;
|
||||
this.thicknessScaleNode = source.thicknessScaleNode;
|
||||
|
||||
return super.copy( source );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default MeshSSSNodeMaterial;
|
||||
|
||||
addNodeMaterial( 'MeshSSSNodeMaterial', MeshSSSNodeMaterial );
|
@ -0,0 +1,87 @@
|
||||
import NodeMaterial, { addNodeMaterial } from './NodeMaterial.js';
|
||||
import { diffuseColor, metalness, roughness, specularColor, specularF90 } from '../core/PropertyNode.js';
|
||||
import { mix } from '../math/MathNode.js';
|
||||
import { materialRoughness, materialMetalness } from '../accessors/MaterialNode.js';
|
||||
import getRoughness from '../functions/material/getRoughness.js';
|
||||
import PhysicalLightingModel from '../functions/PhysicalLightingModel.js';
|
||||
import { float, vec3, vec4 } from '../shadernode/ShaderNode.js';
|
||||
|
||||
import { MeshStandardMaterial } from 'three';
|
||||
|
||||
const defaultValues = new MeshStandardMaterial();
|
||||
|
||||
class MeshStandardNodeMaterial extends NodeMaterial {
|
||||
|
||||
constructor( parameters ) {
|
||||
|
||||
super();
|
||||
|
||||
this.isMeshStandardNodeMaterial = true;
|
||||
|
||||
this.emissiveNode = null;
|
||||
|
||||
this.metalnessNode = null;
|
||||
this.roughnessNode = null;
|
||||
|
||||
this.setDefaultValues( defaultValues );
|
||||
|
||||
this.setValues( parameters );
|
||||
|
||||
}
|
||||
|
||||
setupLightingModel( /*builder*/ ) {
|
||||
|
||||
return new PhysicalLightingModel();
|
||||
|
||||
}
|
||||
|
||||
setupSpecular() {
|
||||
|
||||
const specularColorNode = mix( vec3( 0.04 ), diffuseColor.rgb, metalness );
|
||||
|
||||
specularColor.assign( specularColorNode );
|
||||
specularF90.assign( 1.0 );
|
||||
|
||||
}
|
||||
|
||||
setupVariants() {
|
||||
|
||||
// METALNESS
|
||||
|
||||
const metalnessNode = this.metalnessNode ? float( this.metalnessNode ) : materialMetalness;
|
||||
|
||||
metalness.assign( metalnessNode );
|
||||
|
||||
// ROUGHNESS
|
||||
|
||||
let roughnessNode = this.roughnessNode ? float( this.roughnessNode ) : materialRoughness;
|
||||
roughnessNode = getRoughness( { roughness: roughnessNode } );
|
||||
|
||||
roughness.assign( roughnessNode );
|
||||
|
||||
// SPECULAR COLOR
|
||||
|
||||
this.setupSpecular();
|
||||
|
||||
// DIFFUSE COLOR
|
||||
|
||||
diffuseColor.assign( vec4( diffuseColor.rgb.mul( metalnessNode.oneMinus() ), diffuseColor.a ) );
|
||||
|
||||
}
|
||||
|
||||
copy( source ) {
|
||||
|
||||
this.emissiveNode = source.emissiveNode;
|
||||
|
||||
this.metalnessNode = source.metalnessNode;
|
||||
this.roughnessNode = source.roughnessNode;
|
||||
|
||||
return super.copy( source );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default MeshStandardNodeMaterial;
|
||||
|
||||
addNodeMaterial( 'MeshStandardNodeMaterial', MeshStandardNodeMaterial );
|
613
public/sdk/three/jsm/nodes/materials/NodeMaterial.js
Normal file
613
public/sdk/three/jsm/nodes/materials/NodeMaterial.js
Normal file
@ -0,0 +1,613 @@
|
||||
import { Material, ShaderMaterial } from 'three';
|
||||
import { getNodeChildren, getCacheKey } from '../core/NodeUtils.js';
|
||||
import { attribute } from '../core/AttributeNode.js';
|
||||
import { output, diffuseColor, varyingProperty } from '../core/PropertyNode.js';
|
||||
import { materialAlphaTest, materialColor, materialOpacity, materialEmissive, materialNormal } from '../accessors/MaterialNode.js';
|
||||
import { modelViewProjection } from '../accessors/ModelViewProjectionNode.js';
|
||||
import { transformedNormalView } from '../accessors/NormalNode.js';
|
||||
import { instance } from '../accessors/InstanceNode.js';
|
||||
import { batch } from '../accessors/BatchNode.js';
|
||||
import { materialReference } from '../accessors/MaterialReferenceNode.js';
|
||||
import { positionLocal, positionView } from '../accessors/PositionNode.js';
|
||||
import { skinningReference } from '../accessors/SkinningNode.js';
|
||||
import { morphReference } from '../accessors/MorphNode.js';
|
||||
import { texture } from '../accessors/TextureNode.js';
|
||||
import { cubeTexture } from '../accessors/CubeTextureNode.js';
|
||||
import { lightsNode } from '../lighting/LightsNode.js';
|
||||
import { mix } from '../math/MathNode.js';
|
||||
import { float, vec3, vec4 } from '../shadernode/ShaderNode.js';
|
||||
import AONode from '../lighting/AONode.js';
|
||||
import { lightingContext } from '../lighting/LightingContextNode.js';
|
||||
import EnvironmentNode from '../lighting/EnvironmentNode.js';
|
||||
import IrradianceNode from '../lighting/IrradianceNode.js';
|
||||
import { depthPixel } from '../display/ViewportDepthNode.js';
|
||||
import { cameraLogDepth } from '../accessors/CameraNode.js';
|
||||
import { clipping, clippingAlpha } from '../accessors/ClippingNode.js';
|
||||
import { faceDirection } from '../display/FrontFacingNode.js';
|
||||
|
||||
const NodeMaterials = new Map();
|
||||
|
||||
class NodeMaterial extends ShaderMaterial {
|
||||
|
||||
constructor() {
|
||||
|
||||
super();
|
||||
|
||||
this.isNodeMaterial = true;
|
||||
|
||||
this.type = this.constructor.type;
|
||||
|
||||
this.forceSinglePass = false;
|
||||
|
||||
this.fog = true;
|
||||
this.lights = true;
|
||||
this.normals = true;
|
||||
|
||||
this.lightsNode = null;
|
||||
this.envNode = null;
|
||||
this.aoNode = null;
|
||||
|
||||
this.colorNode = null;
|
||||
this.normalNode = null;
|
||||
this.opacityNode = null;
|
||||
this.backdropNode = null;
|
||||
this.backdropAlphaNode = null;
|
||||
this.alphaTestNode = null;
|
||||
|
||||
this.positionNode = null;
|
||||
|
||||
this.depthNode = null;
|
||||
this.shadowNode = null;
|
||||
this.shadowPositionNode = null;
|
||||
|
||||
this.outputNode = null;
|
||||
|
||||
this.fragmentNode = null;
|
||||
this.vertexNode = null;
|
||||
|
||||
}
|
||||
|
||||
customProgramCacheKey() {
|
||||
|
||||
return this.type + getCacheKey( this );
|
||||
|
||||
}
|
||||
|
||||
build( builder ) {
|
||||
|
||||
this.setup( builder );
|
||||
|
||||
}
|
||||
|
||||
setup( builder ) {
|
||||
|
||||
// < VERTEX STAGE >
|
||||
|
||||
builder.addStack();
|
||||
|
||||
builder.stack.outputNode = this.vertexNode || this.setupPosition( builder );
|
||||
|
||||
builder.addFlow( 'vertex', builder.removeStack() );
|
||||
|
||||
// < FRAGMENT STAGE >
|
||||
|
||||
builder.addStack();
|
||||
|
||||
let resultNode;
|
||||
|
||||
const clippingNode = this.setupClipping( builder );
|
||||
|
||||
if ( this.depthWrite === true ) this.setupDepth( builder );
|
||||
|
||||
if ( this.fragmentNode === null ) {
|
||||
|
||||
if ( this.normals === true ) this.setupNormal( builder );
|
||||
|
||||
this.setupDiffuseColor( builder );
|
||||
this.setupVariants( builder );
|
||||
|
||||
const outgoingLightNode = this.setupLighting( builder );
|
||||
|
||||
if ( clippingNode !== null ) builder.stack.add( clippingNode );
|
||||
|
||||
// force unsigned floats - useful for RenderTargets
|
||||
|
||||
const basicOutput = vec4( outgoingLightNode, diffuseColor.a ).max( 0 );
|
||||
|
||||
resultNode = this.setupOutput( builder, basicOutput );
|
||||
|
||||
// OUTPUT NODE
|
||||
|
||||
output.assign( resultNode );
|
||||
|
||||
//
|
||||
|
||||
if ( this.outputNode !== null ) resultNode = this.outputNode;
|
||||
|
||||
} else {
|
||||
|
||||
let fragmentNode = this.fragmentNode;
|
||||
|
||||
if ( fragmentNode.isOutputStructNode !== true ) {
|
||||
|
||||
fragmentNode = vec4( fragmentNode );
|
||||
|
||||
}
|
||||
|
||||
resultNode = this.setupOutput( builder, fragmentNode );
|
||||
|
||||
}
|
||||
|
||||
builder.stack.outputNode = resultNode;
|
||||
|
||||
builder.addFlow( 'fragment', builder.removeStack() );
|
||||
|
||||
}
|
||||
|
||||
setupClipping( builder ) {
|
||||
|
||||
if ( builder.clippingContext === null ) return null;
|
||||
|
||||
const { globalClippingCount, localClippingCount } = builder.clippingContext;
|
||||
|
||||
let result = null;
|
||||
|
||||
if ( globalClippingCount || localClippingCount ) {
|
||||
|
||||
if ( this.alphaToCoverage ) {
|
||||
|
||||
// to be added to flow when the color/alpha value has been determined
|
||||
result = clippingAlpha();
|
||||
|
||||
} else {
|
||||
|
||||
builder.stack.add( clipping() );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
setupDepth( builder ) {
|
||||
|
||||
const { renderer } = builder;
|
||||
|
||||
// Depth
|
||||
|
||||
let depthNode = this.depthNode;
|
||||
|
||||
if ( depthNode === null && renderer.logarithmicDepthBuffer === true ) {
|
||||
|
||||
const fragDepth = modelViewProjection().w.add( 1 );
|
||||
|
||||
depthNode = fragDepth.log2().mul( cameraLogDepth ).mul( 0.5 );
|
||||
|
||||
}
|
||||
|
||||
if ( depthNode !== null ) {
|
||||
|
||||
depthPixel.assign( depthNode ).append();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
setupPosition( builder ) {
|
||||
|
||||
const { object } = builder;
|
||||
const geometry = object.geometry;
|
||||
|
||||
builder.addStack();
|
||||
|
||||
// Vertex
|
||||
|
||||
if ( geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color ) {
|
||||
|
||||
morphReference( object ).append();
|
||||
|
||||
}
|
||||
|
||||
if ( object.isSkinnedMesh === true ) {
|
||||
|
||||
skinningReference( object ).append();
|
||||
|
||||
}
|
||||
|
||||
if ( object.isBatchedMesh ) {
|
||||
|
||||
batch( object ).append();
|
||||
|
||||
}
|
||||
|
||||
if ( ( object.instanceMatrix && object.instanceMatrix.isInstancedBufferAttribute === true ) && builder.isAvailable( 'instance' ) === true ) {
|
||||
|
||||
instance( object ).append();
|
||||
|
||||
}
|
||||
|
||||
if ( this.positionNode !== null ) {
|
||||
|
||||
positionLocal.assign( this.positionNode );
|
||||
|
||||
}
|
||||
|
||||
const mvp = modelViewProjection();
|
||||
|
||||
builder.context.vertex = builder.removeStack();
|
||||
builder.context.mvp = mvp;
|
||||
|
||||
return mvp;
|
||||
|
||||
}
|
||||
|
||||
setupDiffuseColor( { object, geometry } ) {
|
||||
|
||||
let colorNode = this.colorNode ? vec4( this.colorNode ) : materialColor;
|
||||
|
||||
// VERTEX COLORS
|
||||
|
||||
if ( this.vertexColors === true && geometry.hasAttribute( 'color' ) ) {
|
||||
|
||||
colorNode = vec4( colorNode.xyz.mul( attribute( 'color', 'vec3' ) ), colorNode.a );
|
||||
|
||||
}
|
||||
|
||||
// Instanced colors
|
||||
|
||||
if ( object.instanceColor ) {
|
||||
|
||||
const instanceColor = varyingProperty( 'vec3', 'vInstanceColor' );
|
||||
|
||||
colorNode = instanceColor.mul( colorNode );
|
||||
|
||||
}
|
||||
|
||||
// COLOR
|
||||
|
||||
diffuseColor.assign( colorNode );
|
||||
|
||||
// OPACITY
|
||||
|
||||
const opacityNode = this.opacityNode ? float( this.opacityNode ) : materialOpacity;
|
||||
diffuseColor.a.assign( diffuseColor.a.mul( opacityNode ) );
|
||||
|
||||
// ALPHA TEST
|
||||
|
||||
if ( this.alphaTestNode !== null || this.alphaTest > 0 ) {
|
||||
|
||||
const alphaTestNode = this.alphaTestNode !== null ? float( this.alphaTestNode ) : materialAlphaTest;
|
||||
|
||||
diffuseColor.a.lessThanEqual( alphaTestNode ).discard();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
setupVariants( /*builder*/ ) {
|
||||
|
||||
// Interface function.
|
||||
|
||||
}
|
||||
|
||||
setupNormal() {
|
||||
|
||||
// NORMAL VIEW
|
||||
|
||||
if ( this.flatShading === true ) {
|
||||
|
||||
const normalNode = positionView.dFdx().cross( positionView.dFdy() ).normalize();
|
||||
|
||||
transformedNormalView.assign( normalNode.mul( faceDirection ) );
|
||||
|
||||
} else {
|
||||
|
||||
const normalNode = this.normalNode ? vec3( this.normalNode ) : materialNormal;
|
||||
|
||||
transformedNormalView.assign( normalNode.mul( faceDirection ) );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
getEnvNode( builder ) {
|
||||
|
||||
let node = null;
|
||||
|
||||
if ( this.envNode ) {
|
||||
|
||||
node = this.envNode;
|
||||
|
||||
} else if ( this.envMap ) {
|
||||
|
||||
node = this.envMap.isCubeTexture ? cubeTexture( this.envMap ) : texture( this.envMap );
|
||||
|
||||
} else if ( builder.environmentNode ) {
|
||||
|
||||
node = builder.environmentNode;
|
||||
|
||||
}
|
||||
|
||||
return node;
|
||||
|
||||
}
|
||||
|
||||
setupLights( builder ) {
|
||||
|
||||
const envNode = this.getEnvNode( builder );
|
||||
|
||||
//
|
||||
|
||||
const materialLightsNode = [];
|
||||
|
||||
if ( envNode ) {
|
||||
|
||||
materialLightsNode.push( new EnvironmentNode( envNode ) );
|
||||
|
||||
}
|
||||
|
||||
if ( builder.material.lightMap ) {
|
||||
|
||||
materialLightsNode.push( new IrradianceNode( materialReference( 'lightMap', 'texture' ) ) );
|
||||
|
||||
}
|
||||
|
||||
if ( this.aoNode !== null || builder.material.aoMap ) {
|
||||
|
||||
const aoNode = this.aoNode !== null ? this.aoNode : texture( builder.material.aoMap );
|
||||
|
||||
materialLightsNode.push( new AONode( aoNode ) );
|
||||
|
||||
}
|
||||
|
||||
let lightsN = this.lightsNode || builder.lightsNode;
|
||||
|
||||
if ( materialLightsNode.length > 0 ) {
|
||||
|
||||
lightsN = lightsNode( [ ...lightsN.lightNodes, ...materialLightsNode ] );
|
||||
|
||||
}
|
||||
|
||||
return lightsN;
|
||||
|
||||
}
|
||||
|
||||
setupLightingModel( /*builder*/ ) {
|
||||
|
||||
// Interface function.
|
||||
|
||||
}
|
||||
|
||||
setupLighting( builder ) {
|
||||
|
||||
const { material } = builder;
|
||||
const { backdropNode, backdropAlphaNode, emissiveNode } = this;
|
||||
|
||||
// OUTGOING LIGHT
|
||||
|
||||
const lights = this.lights === true || this.lightsNode !== null;
|
||||
|
||||
const lightsNode = lights ? this.setupLights( builder ) : null;
|
||||
|
||||
let outgoingLightNode = diffuseColor.rgb;
|
||||
|
||||
if ( lightsNode && lightsNode.hasLight !== false ) {
|
||||
|
||||
const lightingModel = this.setupLightingModel( builder );
|
||||
|
||||
outgoingLightNode = lightingContext( lightsNode, lightingModel, backdropNode, backdropAlphaNode );
|
||||
|
||||
} else if ( backdropNode !== null ) {
|
||||
|
||||
outgoingLightNode = vec3( backdropAlphaNode !== null ? mix( outgoingLightNode, backdropNode, backdropAlphaNode ) : backdropNode );
|
||||
|
||||
}
|
||||
|
||||
// EMISSIVE
|
||||
|
||||
if ( ( emissiveNode && emissiveNode.isNode === true ) || ( material.emissive && material.emissive.isColor === true ) ) {
|
||||
|
||||
outgoingLightNode = outgoingLightNode.add( vec3( emissiveNode ? emissiveNode : materialEmissive ) );
|
||||
|
||||
}
|
||||
|
||||
return outgoingLightNode;
|
||||
|
||||
}
|
||||
|
||||
setupOutput( builder, outputNode ) {
|
||||
|
||||
// FOG
|
||||
|
||||
const fogNode = builder.fogNode;
|
||||
|
||||
if ( fogNode ) outputNode = vec4( fogNode.mix( outputNode.rgb, fogNode.colorNode ), outputNode.a );
|
||||
|
||||
return outputNode;
|
||||
|
||||
}
|
||||
|
||||
setDefaultValues( material ) {
|
||||
|
||||
// This approach is to reuse the native refreshUniforms*
|
||||
// and turn available the use of features like transmission and environment in core
|
||||
|
||||
for ( const property in material ) {
|
||||
|
||||
const value = material[ property ];
|
||||
|
||||
if ( this[ property ] === undefined ) {
|
||||
|
||||
this[ property ] = value;
|
||||
|
||||
if ( value && value.clone ) this[ property ] = value.clone();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Object.assign( this.defines, material.defines );
|
||||
|
||||
const descriptors = Object.getOwnPropertyDescriptors( material.constructor.prototype );
|
||||
|
||||
for ( const key in descriptors ) {
|
||||
|
||||
if ( Object.getOwnPropertyDescriptor( this.constructor.prototype, key ) === undefined &&
|
||||
descriptors[ key ].get !== undefined ) {
|
||||
|
||||
Object.defineProperty( this.constructor.prototype, key, descriptors[ key ] );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
toJSON( meta ) {
|
||||
|
||||
const isRoot = ( meta === undefined || typeof meta === 'string' );
|
||||
|
||||
if ( isRoot ) {
|
||||
|
||||
meta = {
|
||||
textures: {},
|
||||
images: {},
|
||||
nodes: {}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
const data = Material.prototype.toJSON.call( this, meta );
|
||||
const nodeChildren = getNodeChildren( this );
|
||||
|
||||
data.inputNodes = {};
|
||||
|
||||
for ( const { property, childNode } of nodeChildren ) {
|
||||
|
||||
data.inputNodes[ property ] = childNode.toJSON( meta ).uuid;
|
||||
|
||||
}
|
||||
|
||||
// TODO: Copied from Object3D.toJSON
|
||||
|
||||
function extractFromCache( cache ) {
|
||||
|
||||
const values = [];
|
||||
|
||||
for ( const key in cache ) {
|
||||
|
||||
const data = cache[ key ];
|
||||
delete data.metadata;
|
||||
values.push( data );
|
||||
|
||||
}
|
||||
|
||||
return values;
|
||||
|
||||
}
|
||||
|
||||
if ( isRoot ) {
|
||||
|
||||
const textures = extractFromCache( meta.textures );
|
||||
const images = extractFromCache( meta.images );
|
||||
const nodes = extractFromCache( meta.nodes );
|
||||
|
||||
if ( textures.length > 0 ) data.textures = textures;
|
||||
if ( images.length > 0 ) data.images = images;
|
||||
if ( nodes.length > 0 ) data.nodes = nodes;
|
||||
|
||||
}
|
||||
|
||||
return data;
|
||||
|
||||
}
|
||||
|
||||
copy( source ) {
|
||||
|
||||
this.lightsNode = source.lightsNode;
|
||||
this.envNode = source.envNode;
|
||||
|
||||
this.colorNode = source.colorNode;
|
||||
this.normalNode = source.normalNode;
|
||||
this.opacityNode = source.opacityNode;
|
||||
this.backdropNode = source.backdropNode;
|
||||
this.backdropAlphaNode = source.backdropAlphaNode;
|
||||
this.alphaTestNode = source.alphaTestNode;
|
||||
|
||||
this.positionNode = source.positionNode;
|
||||
|
||||
this.depthNode = source.depthNode;
|
||||
this.shadowNode = source.shadowNode;
|
||||
this.shadowPositionNode = source.shadowPositionNode;
|
||||
|
||||
this.outputNode = source.outputNode;
|
||||
|
||||
this.fragmentNode = source.fragmentNode;
|
||||
this.vertexNode = source.vertexNode;
|
||||
|
||||
return super.copy( source );
|
||||
|
||||
}
|
||||
|
||||
static fromMaterial( material ) {
|
||||
|
||||
if ( material.isNodeMaterial === true ) { // is already a node material
|
||||
|
||||
return material;
|
||||
|
||||
}
|
||||
|
||||
const type = material.type.replace( 'Material', 'NodeMaterial' );
|
||||
|
||||
const nodeMaterial = createNodeMaterialFromType( type );
|
||||
|
||||
if ( nodeMaterial === undefined ) {
|
||||
|
||||
throw new Error( `NodeMaterial: Material "${ material.type }" is not compatible.` );
|
||||
|
||||
}
|
||||
|
||||
for ( const key in material ) {
|
||||
|
||||
nodeMaterial[ key ] = material[ key ];
|
||||
|
||||
}
|
||||
|
||||
return nodeMaterial;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default NodeMaterial;
|
||||
|
||||
export function addNodeMaterial( type, nodeMaterial ) {
|
||||
|
||||
if ( typeof nodeMaterial !== 'function' || ! type ) throw new Error( `Node material ${ type } is not a class` );
|
||||
if ( NodeMaterials.has( type ) ) {
|
||||
|
||||
console.warn( `Redefinition of node material ${ type }` );
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
NodeMaterials.set( type, nodeMaterial );
|
||||
nodeMaterial.type = type;
|
||||
|
||||
}
|
||||
|
||||
export function createNodeMaterialFromType( type ) {
|
||||
|
||||
const Material = NodeMaterials.get( type );
|
||||
|
||||
if ( Material !== undefined ) {
|
||||
|
||||
return new Material();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
addNodeMaterial( 'NodeMaterial', NodeMaterial );
|
39
public/sdk/three/jsm/nodes/materials/PointsNodeMaterial.js
Normal file
39
public/sdk/three/jsm/nodes/materials/PointsNodeMaterial.js
Normal file
@ -0,0 +1,39 @@
|
||||
import NodeMaterial, { addNodeMaterial } from './NodeMaterial.js';
|
||||
|
||||
import { PointsMaterial } from 'three';
|
||||
|
||||
const defaultValues = new PointsMaterial();
|
||||
|
||||
class PointsNodeMaterial extends NodeMaterial {
|
||||
|
||||
constructor( parameters ) {
|
||||
|
||||
super();
|
||||
|
||||
this.isPointsNodeMaterial = true;
|
||||
|
||||
this.lights = false;
|
||||
this.normals = false;
|
||||
this.transparent = true;
|
||||
|
||||
this.sizeNode = null;
|
||||
|
||||
this.setDefaultValues( defaultValues );
|
||||
|
||||
this.setValues( parameters );
|
||||
|
||||
}
|
||||
|
||||
copy( source ) {
|
||||
|
||||
this.sizeNode = source.sizeNode;
|
||||
|
||||
return super.copy( source );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default PointsNodeMaterial;
|
||||
|
||||
addNodeMaterial( 'PointsNodeMaterial', PointsNodeMaterial );
|
34
public/sdk/three/jsm/nodes/materials/ShadowNodeMaterial.js
Normal file
34
public/sdk/three/jsm/nodes/materials/ShadowNodeMaterial.js
Normal file
@ -0,0 +1,34 @@
|
||||
import NodeMaterial, { addNodeMaterial } from './NodeMaterial.js';
|
||||
import ShadowMaskModel from '../functions/ShadowMaskModel.js';
|
||||
|
||||
import { ShadowMaterial } from 'three';
|
||||
|
||||
const defaultValues = new ShadowMaterial();
|
||||
|
||||
class ShadowNodeMaterial extends NodeMaterial {
|
||||
|
||||
constructor( parameters ) {
|
||||
|
||||
super();
|
||||
|
||||
this.isShadowNodeMaterial = true;
|
||||
|
||||
this.lights = true;
|
||||
|
||||
this.setDefaultValues( defaultValues );
|
||||
|
||||
this.setValues( parameters );
|
||||
|
||||
}
|
||||
|
||||
setupLightingModel( /*builder*/ ) {
|
||||
|
||||
return new ShadowMaskModel();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default ShadowNodeMaterial;
|
||||
|
||||
addNodeMaterial( 'ShadowNodeMaterial', ShadowNodeMaterial );
|
90
public/sdk/three/jsm/nodes/materials/SpriteNodeMaterial.js
Normal file
90
public/sdk/three/jsm/nodes/materials/SpriteNodeMaterial.js
Normal file
@ -0,0 +1,90 @@
|
||||
import NodeMaterial, { addNodeMaterial } from './NodeMaterial.js';
|
||||
import { uniform } from '../core/UniformNode.js';
|
||||
import { cameraProjectionMatrix } from '../accessors/CameraNode.js';
|
||||
import { materialRotation } from '../accessors/MaterialNode.js';
|
||||
import { modelViewMatrix, modelWorldMatrix } from '../accessors/ModelNode.js';
|
||||
import { positionLocal } from '../accessors/PositionNode.js';
|
||||
import { float, vec2, vec3, vec4 } from '../shadernode/ShaderNode.js';
|
||||
|
||||
import { SpriteMaterial } from 'three';
|
||||
|
||||
const defaultValues = new SpriteMaterial();
|
||||
|
||||
class SpriteNodeMaterial extends NodeMaterial {
|
||||
|
||||
constructor( parameters ) {
|
||||
|
||||
super();
|
||||
|
||||
this.isSpriteNodeMaterial = true;
|
||||
|
||||
this.lights = false;
|
||||
this.normals = false;
|
||||
|
||||
this.positionNode = null;
|
||||
this.rotationNode = null;
|
||||
this.scaleNode = null;
|
||||
|
||||
this.setDefaultValues( defaultValues );
|
||||
|
||||
this.setValues( parameters );
|
||||
|
||||
}
|
||||
|
||||
setupPosition( { object, context } ) {
|
||||
|
||||
// < VERTEX STAGE >
|
||||
|
||||
const { positionNode, rotationNode, scaleNode } = this;
|
||||
|
||||
const vertex = positionLocal;
|
||||
|
||||
let mvPosition = modelViewMatrix.mul( vec3( positionNode || 0 ) );
|
||||
|
||||
let scale = vec2( modelWorldMatrix[ 0 ].xyz.length(), modelWorldMatrix[ 1 ].xyz.length() );
|
||||
|
||||
if ( scaleNode !== null ) {
|
||||
|
||||
scale = scale.mul( scaleNode );
|
||||
|
||||
}
|
||||
|
||||
let alignedPosition = vertex.xy;
|
||||
|
||||
if ( object.center && object.center.isVector2 === true ) {
|
||||
|
||||
alignedPosition = alignedPosition.sub( uniform( object.center ).sub( 0.5 ) );
|
||||
|
||||
}
|
||||
|
||||
alignedPosition = alignedPosition.mul( scale );
|
||||
|
||||
const rotation = float( rotationNode || materialRotation );
|
||||
|
||||
const rotatedPosition = alignedPosition.rotate( rotation );
|
||||
|
||||
mvPosition = vec4( mvPosition.xy.add( rotatedPosition ), mvPosition.zw );
|
||||
|
||||
const modelViewProjection = cameraProjectionMatrix.mul( mvPosition );
|
||||
|
||||
context.vertex = vertex;
|
||||
|
||||
return modelViewProjection;
|
||||
|
||||
}
|
||||
|
||||
copy( source ) {
|
||||
|
||||
this.positionNode = source.positionNode;
|
||||
this.rotationNode = source.rotationNode;
|
||||
this.scaleNode = source.scaleNode;
|
||||
|
||||
return super.copy( source );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default SpriteNodeMaterial;
|
||||
|
||||
addNodeMaterial( 'SpriteNodeMaterial', SpriteNodeMaterial );
|
Reference in New Issue
Block a user