Skip to content

Commit 26e0683

Browse files
committed
WebGPURenderer: ShaderMaterial support prototype
1 parent 9ee09d6 commit 26e0683

File tree

4 files changed

+425
-77
lines changed

4 files changed

+425
-77
lines changed

examples/jsm/renderers/webgpu/WebGPUBindings.js

Lines changed: 166 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import WebGPUUniformsGroup from './WebGPUUniformsGroup.js';
22
import WebGPUSampler from './WebGPUSampler.js';
33
import WebGPUSampledTexture from './WebGPUSampledTexture.js';
4-
import { Matrix4 } from '../../../../build/three.module.js';
4+
import { Matrix3, Matrix4, Vector2, Vector3, Vector4 } from '../../../../build/three.module.js';
55

66
class WebGPUBindings {
77

@@ -22,7 +22,17 @@ class WebGPUBindings {
2222

2323
}
2424

25-
get( object ) {
25+
// Here taking shaderUniforms is what I don't really like.
26+
// To set up bindings, uniforms information in shader is necessary.
27+
// But just getting existing bindings doesn't need uniforms information.
28+
// I moved bindings.update() in WebGPURenderer after render pipeline get/creation
29+
// (See _renderObject() in WebGPURenderer), and bindings.get() in WebGPURenderPipelines
30+
// is only the place where bindings setup can cause now.
31+
// So passing bindings.get() call in WebGPURenderPipelines passes shaderUniforms
32+
// and other bindings.get() doesn't pass.
33+
// I don't think this is a good design and want to simplify...
34+
35+
get( object, shaderUniforms ) {
2636

2737
let data = this.uniformsData.get( object );
2838

@@ -45,6 +55,10 @@ class WebGPUBindings {
4555

4656
bindings = this._getLinesBasicBindings();
4757

58+
} else if ( material.isShaderMaterial ) {
59+
60+
bindings = this._getShaderBindings( material, shaderUniforms );
61+
4862
} else {
4963

5064
console.error( 'THREE.WebGPURenderer: Unknwon shader type.' );
@@ -115,7 +129,23 @@ class WebGPUBindings {
115129
} else if ( binding.isSampler ) {
116130

117131
const material = object.material;
118-
const texture = material[ binding.name ];
132+
133+
// Here may be tricky.
134+
// Needs to search texture.
135+
// Assuming binding name has path from material to texture
136+
// separated by '.', like "map" or "uniforms.mySampler.value".
137+
// I want to simplify.
138+
139+
const names = binding.name.split( '.' );
140+
let target = material;
141+
142+
for ( const name of names ) {
143+
144+
target = target[ name ];
145+
146+
}
147+
148+
const texture = target;
119149

120150
textures.updateSampler( texture );
121151

@@ -131,7 +161,17 @@ class WebGPUBindings {
131161
} else if ( binding.isSampledTexture ) {
132162

133163
const material = object.material;
134-
const texture = material[ binding.name ];
164+
165+
const names = binding.name.split( '.' );
166+
let target = material;
167+
168+
for ( const name of names ) {
169+
170+
target = target[ name ];
171+
172+
}
173+
174+
const texture = target;
135175

136176
const forceUpdate = textures.updateTexture( texture );
137177
const textureGPU = textures.getTextureGPU( texture );
@@ -379,6 +419,128 @@ class WebGPUBindings {
379419

380420
}
381421

422+
_getShaderBindings( material, shaderUniforms ) {
423+
424+
// Creates bindings from shader uniforms information
425+
426+
const bindings = [];
427+
428+
for ( const shaderUniform of shaderUniforms ) {
429+
430+
const name = shaderUniform.name;
431+
const type = shaderUniform.type;
432+
const groupType = shaderUniform.groupType;
433+
const visibility = shaderUniform.visibility === 'vertex|fragment' ? GPUShaderStage.VERTEX | GPUShaderStage.FRAGMENT :
434+
shaderUniform.visibility === 'vertex' ? GPUShaderStage.VERTEX : GPUShaderStage.FRAGMENT;
435+
let group;
436+
437+
if ( name === 'modelUniforms' ) {
438+
439+
// Reserved name 'modelUniforms'
440+
441+
group = new WebGPUUniformsGroup();
442+
group.setName( name );
443+
group.visibility = visibility;
444+
group.setUniform( 'modelMatrix', new Matrix4() );
445+
group.setUniform( 'modelViewMatrix', new Matrix4() );
446+
447+
group.setUpdateCallback( function ( object/*, camera */ ) {
448+
449+
let updated = false;
450+
451+
if ( this.updateMatrix4( object.matrixWorld, 0 ) ) updated = true;
452+
if ( this.updateMatrix4( object.modelViewMatrix, 16 ) ) updated = true;
453+
454+
return updated;
455+
456+
} );
457+
458+
} else if ( name === 'cameraUniforms' ) {
459+
460+
// Reserved name 'cameraUniforms'
461+
462+
group = this.sharedUniformsGroups.get( 'cameraUniforms' );
463+
464+
} else if ( groupType === 'uniform-buffer' ) {
465+
466+
group = new WebGPUUniformsGroup();
467+
group.setName( name );
468+
group.visibility = visibility;
469+
470+
const entries = shaderUniform.entries;
471+
472+
for ( const entry of entries ) {
473+
474+
group.setUniform( entry.name, getInitialValue( entry.type ) );
475+
476+
}
477+
478+
group.setUpdateCallback( function ( array, object/*, camera */ ) {
479+
480+
const values = material.uniforms[ name ].value;
481+
let offset = 0;
482+
let updated = false;
483+
484+
for ( let i = 0; i < entries.length; i ++ ) {
485+
486+
const entry = entries[ i ];
487+
const value = values[ i ];
488+
if ( this.updateByType( value, offset ) ) updated = true;
489+
offset += this.getUniformByteLength( value ) / 4; // Assuming array is Float32 so far
490+
491+
}
492+
493+
return updated;
494+
495+
} );
496+
497+
} else if ( groupType === 'sampler' ) {
498+
499+
group = new WebGPUSampler();
500+
group.setName( 'uniforms.' + name + '.value' );
501+
group.visibility = visibility;
502+
503+
} else if ( groupType === 'sampled-texture' ) {
504+
505+
group = new WebGPUSampledTexture();
506+
group.setName( 'uniforms.' + name + '.value' );
507+
group.visibility = visibility;
508+
509+
} else {
510+
511+
console.error( 'THREE.WebGPURenderer: Unknown uniform type ' + type );
512+
513+
}
514+
515+
bindings.push( group );
516+
517+
}
518+
519+
return bindings;
520+
521+
}
522+
523+
}
524+
525+
function getInitialValue( type ) {
526+
527+
switch ( type ) {
528+
case 'float':
529+
return 0.0;
530+
case 'vec2':
531+
return new Vector2();
532+
case 'vec3':
533+
return new Vector3();
534+
case 'vec4':
535+
return new Vector4();
536+
case 'mat3':
537+
return new Matrix3();
538+
case 'mat4':
539+
return new Matrix4();
540+
}
541+
542+
console.error( 'THREE.WebGPURenderer: Unknown uniform type ' + type );
543+
382544
}
383545

384546
export default WebGPUBindings;

0 commit comments

Comments
 (0)