threepipe
Version:
A 3D viewer framework built on top of three.js in TypeScript with a focus on quality rendering, modularity and extensibility.
66 lines • 2.9 kB
JavaScript
import { ShaderMaterial2 } from './ShaderMaterial2';
import { getTexelDecoding } from '../../three';
import { LinearSRGBColorSpace, Vector2, } from 'three';
import { shaderReplaceString } from '../../utils';
// earlier it was ShaderMaterialEncodingSupport
export class ExtendedShaderMaterial extends ShaderMaterial2 {
constructor(parameters, textureIds, isRawShaderMaterial = false) {
super(parameters, isRawShaderMaterial);
this.textures = [];
this.setTextureIds(textureIds);
}
setTextureIds(ids) {
if (this.textures.map(t => t.id).join(';') !== ids.join(';')) {
this.textures = ids.map(t => ({ id: t, colorSpace: LinearSRGBColorSpace }));
this.setDirty();
}
}
_setUniformTexSize(uniform, t) {
if (!t || !uniform)
return;
const w = t?.width ?? 512;
const h = t?.height ?? 512;
const last = uniform.value;
if (!last.isVector2)
console.warn('uniform is not a Vector2');
if (last && Math.abs(last.x - w) + Math.abs(last.y - h) > 0.1) {
last.x = w;
last.y = h;
this.uniformsNeedUpdate = true;
}
}
onBeforeRender(renderer, scene, camera, geometry, object) {
this.uniforms.screenSize && this._setUniformTexSize(this.uniforms.screenSize, renderer.getRenderTarget() ?? renderer.getSize(new Vector2()));
for (const item of this.textures) {
const textureID = item.id;
const t = this.uniforms[textureID]?.value;
if (t) {
this._setUniformTexSize(this.uniforms[textureID + 'Size'], t.image);
if (t.colorSpace !== item.colorSpace) {
item.colorSpace = t.colorSpace;
this.needsUpdate = true;
}
}
}
super.onBeforeRender(renderer, scene, camera, geometry, object);
}
onBeforeCompile(s, renderer) {
const pars = '\n' + this.textures
.map(t => `uniform sampler2D ${t.id}; \n`
+ getTexelDecoding(t.id ?? 'input', t, renderer.capabilities.isWebGL2)).join('\n');
if (s.fragmentShader.includes('#include <encodings_pars_fragment>')) {
s.fragmentShader = shaderReplaceString(s.fragmentShader, '#include <encodings_pars_fragment>', pars, { append: true });
}
else if (s.fragmentShader.includes('precision highp float;')) {
s.fragmentShader = shaderReplaceString(s.fragmentShader, 'precision highp float;', pars, { append: true });
}
else {
s.fragmentShader = pars + s.fragmentShader;
}
super.onBeforeCompile(s, renderer);
}
customProgramCacheKey() {
return super.customProgramCacheKey() + this.textures.map(t => t.id + t.colorSpace).join(';');
}
}
//# sourceMappingURL=ExtendedShaderMaterial.js.map