Debug Notes¶
Three.js #14635 (Material instance)¶
test case:
test/html/greate-cd.html
About the Three Module Issue¶
Attention
This issue should no longer exists because all imports from packages/three/three.module.js are now directly from three package - not verified.
Note
It’s worth to have a note after days of debugging.
EffectComposer and its depending passes are not included in the threejs bundle. This makes x-visual have to import these modules via both by npm three/examples/ or by copying directly the source files.
As x-visual is using Mocha for test, the former method leads to another problem, (see the packages/README,) which makes the latter method the only plausible way - as to his knowledge limitation.
But the using threejs module source presented another issue, classes supposed to be the same class are not as expected when checking with “instanceof”.
There is a good example showing this issue.
In lib/sys/ext/finalcomposer.js, the system create a ShaderPass with a THREE.ShaderMaterial will makes ShaderPass failed to check the the instance.
There are similar issue like this question.
The code snippet causing the issue in lib/sys/ext/finalComposer.js/FinalComposer:
import * as THREE from 'three'
import {ShaderPass} from '../../../packages/three/postprocessing/ShaderPass'
import {EffectComposer} from '../../../packages/three/postprocessing/EffectComposer'
class FinalComposer extends XSys {
effects(x) {
var effects = x.composer;
effects.renderToScreen = false;
this.effectPass = effects;
this.finalCompose = new EffectComposer( x.renderer );
var finalPass = new ShaderPass(
// Should from packages/three.module.js, instead of THREE.ShaderMaterial
new THREE.ShaderMaterial( {
uniforms: {
texScene: { value: null },
texEffects: { value: effects.renderTarget2.texture },
},
vertexShader: finalVert,
fragmentShader: finalFrag,
} ),
"texScene");
finalPass.renderToScreen = true;
this.finalCompose.addPass( finalPass );
}
}
The final composer sharing texture from effects composer (effects) rendering target is essential to the result.
Here is where the problem comes from:
The packages/three/postprocessing/ShaderPass constructor check the shader arguments with “insanceof ShaderMaterial” which is actually another class from ../three.module.js, leading to an unexpected result.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | import {
ShaderMaterial,
UniformsUtils
} from "../three.module-MRTSupport.js"
import { Pass } from "../postprocessing/Pass.js";
var ShaderPass = function ( shader, textureID ) {
Pass.call( this );
this.textureID = ( textureID !== undefined ) ? textureID : "tDiffuse";
if ( shader instanceof ShaderMaterial ) {
this.uniforms = shader.uniforms;
this.material = shader;
} else if ( shader ) {
this.uniforms = UniformsUtils.clone( shader.uniforms );
this.material = new ShaderMaterial( {
defines: Object.assign( {}, shader.defines ),
uniforms: this.uniforms,
vertexShader: shader.vertexShader,
fragmentShader: shader.fragmentShader
} );
}
this.fsQuad = new Pass.FullScreenQuad( this.material );
|
Texture Referenced Across Shaders¶
Texture must been provided in uniforms to be bound to sampler2D in shader. Otherwise the texture can be bound to a wrong sampler.
The left results from bug that without setting image (loaded as texture) to material uniforms, making shader using wrong texture binding.
Hacking Three.js¶
Glsl Shader Source¶
THREE.Revision 110
ShaderId in renderers/webgl/WebGLPrograms.js,
In renderers/shaders/ShaderLib.js,
ShaderChunk packs all source grogram, like
Src: meshbasic_vert & meshbasic_frag.
And WebGLRenderer, the three.js renderer, using WebGLPrograms.acquireProgram() to get shader program.
Shader instance for LineBasicMaterial: