| Scene, | Scene, | ||||
| Shader, | Shader, | ||||
| ShaderMaterialParameters, | ShaderMaterialParameters, | ||||
| Texture, | |||||
| Vector2, | |||||
| WebGLRenderer, | WebGLRenderer, | ||||
| } from 'three' | } from 'three' | ||||
| import {shaderReplaceString} from '../../utils' | |||||
| export class ExtendedShaderMaterial extends ShaderMaterial2 { | export class ExtendedShaderMaterial extends ShaderMaterial2 { | ||||
| declare ['constructor']: (typeof ExtendedShaderMaterial) & (typeof ShaderMaterial2) | declare ['constructor']: (typeof ExtendedShaderMaterial) & (typeof ShaderMaterial2) | ||||
| textures: {colorSpace: ColorSpace, id: string}[] = [] | textures: {colorSpace: ColorSpace, id: string}[] = [] | ||||
| constructor(parameters: ShaderMaterialParameters, textureIds: string[]) { | |||||
| super(parameters) | |||||
| constructor(parameters: ShaderMaterialParameters, textureIds: string[], isRawShaderMaterial = false) { | |||||
| super(parameters, isRawShaderMaterial) | |||||
| this.setTextureIds(textureIds) | this.setTextureIds(textureIds) | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| private _setUniformTexSize(uniform?: IUniform, t?: Texture) { | |||||
| private _setUniformTexSize(uniform?: IUniform, t?: {width: number, height: number}) { | |||||
| if (!t || !uniform) return | if (!t || !uniform) return | ||||
| const w = t.image?.width ?? 512 | |||||
| const h = t.image?.height ?? 512 | |||||
| const w = t?.width ?? 512 | |||||
| const h = t?.height ?? 512 | |||||
| const last = uniform.value | const last = uniform.value | ||||
| if (!last.isVector2) console.warn('uniform is not a Vector2') | if (!last.isVector2) console.warn('uniform is not a Vector2') | ||||
| if (last && Math.abs(last.x - w) + Math.abs(last.y - h) > 0.1) { | if (last && Math.abs(last.x - w) + Math.abs(last.y - h) > 0.1) { | ||||
| } | } | ||||
| } | } | ||||
| onBeforeRender(renderer: WebGLRenderer, scene: Scene, camera: Camera, geometry: BufferGeometry, object: Object3D): void { | onBeforeRender(renderer: WebGLRenderer, scene: Scene, camera: Camera, geometry: BufferGeometry, object: Object3D): void { | ||||
| this._setUniformTexSize(this.uniforms.screenSize, renderer.getRenderTarget()?.texture) | |||||
| this._setUniformTexSize(this.uniforms.screenSize, renderer.getRenderTarget() ?? renderer.getSize(new Vector2())) | |||||
| for (const item of this.textures) { | for (const item of this.textures) { | ||||
| const textureID = item.id | const textureID = item.id | ||||
| const t = this.uniforms[textureID]?.value | const t = this.uniforms[textureID]?.value | ||||
| if (t) { | if (t) { | ||||
| this._setUniformTexSize(this.uniforms[textureID + 'Size'], t) | |||||
| this._setUniformTexSize(this.uniforms[textureID + 'Size'], t.image) | |||||
| if (t.colorSpace !== item.colorSpace) { | if (t.colorSpace !== item.colorSpace) { | ||||
| item.colorSpace = t.colorSpace | item.colorSpace = t.colorSpace | ||||
| this.needsUpdate = true | this.needsUpdate = true | ||||
| } | } | ||||
| onBeforeCompile(s: Shader, renderer: WebGLRenderer) { | onBeforeCompile(s: Shader, renderer: WebGLRenderer) { | ||||
| s.fragmentShader = this.textures | |||||
| const pars = '\n' + this.textures | |||||
| .map(t=>`uniform sampler2D ${t.id}; \n` | .map(t=>`uniform sampler2D ${t.id}; \n` | ||||
| + getTexelDecoding2(t.id ?? 'input', t.colorSpace ?? LinearSRGBColorSpace)).join('\n') | + getTexelDecoding2(t.id ?? 'input', t.colorSpace ?? LinearSRGBColorSpace)).join('\n') | ||||
| + s.fragmentShader | |||||
| 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) | super.onBeforeCompile(s, renderer) | ||||
| } | } | ||||