| @@ -69,7 +69,7 @@ export class ExtendedShaderMaterial extends ShaderMaterial2 { | |||
| onBeforeCompile(s: Shader, renderer: WebGLRenderer) { | |||
| const pars = '\n' + this.textures | |||
| .map(t=>`uniform sampler2D ${t.id}; \n` | |||
| + getTexelDecoding(t.id ?? 'input', t, renderer.capabilities.isWebGL2)).join('\n') | |||
| + getTexelDecoding(t.id ?? 'input', t.colorSpace)).join('\n') | |||
| if (s.fragmentShader.includes('#include <encodings_pars_fragment>')) { | |||
| s.fragmentShader = shaderReplaceString(s.fragmentShader, '#include <encodings_pars_fragment>', pars, {append: true}) | |||
| @@ -65,7 +65,8 @@ export class MaterialExtender { | |||
| if (!Array.isArray(material.materialExtensions)) material.materialExtensions = [] | |||
| if (customMaterialExtensions) | |||
| for (const ext of customMaterialExtensions) { | |||
| if (!ext.isCompatible || !ext.isCompatible(material) || material.materialExtensions.includes(ext)) continue | |||
| if (material.materialExtensions.includes(ext)) continue | |||
| if (ext.isCompatible !== undefined && (!ext.isCompatible || !ext.isCompatible(material))) continue | |||
| exts.push(ext) | |||
| if (!ext.uuid) ext.uuid = generateUUID() | |||
| if (!ext.__setDirty) ext.__setDirty = ()=>{ | |||
| @@ -72,9 +72,11 @@ export interface MaterialExtension{ | |||
| * Function to check if this material extension is compatible with the given material. | |||
| * If not compatible, the material extension will not be applied. | |||
| * This is only checked when the extension is registered. | |||
| * | |||
| * The extension is assumed to be compatible if this function is not defined | |||
| * @param material | |||
| */ | |||
| isCompatible: (material: IMaterial) => boolean | |||
| isCompatible?: (material: IMaterial) => boolean|undefined | |||
| /** | |||
| * List of shader properties updaters to run on the material. | |||
| @@ -303,9 +303,9 @@ export class SSAOPluginPass extends ExtendedShaderPass implements IPipelinePass | |||
| material.needsUpdate = true | |||
| } | |||
| }, | |||
| parsFragmentSnippet: (renderer)=>glsl` | |||
| parsFragmentSnippet: ()=>glsl` | |||
| uniform sampler2D tSSAOMap; | |||
| ${getTexelDecoding('tSSAOMap', getOrCall(this.target)?.texture, renderer!.capabilities.isWebGL2)} | |||
| ${getTexelDecoding('tSSAOMap', getOrCall(this.target)?.texture.colorSpace)} | |||
| #include <simpleCameraHelpers> | |||
| `, | |||
| computeCacheKey: () => { | |||
| @@ -54,9 +54,9 @@ export class VirtualCamerasPlugin extends AViewerPluginSync<VirtualCamerasPlugin | |||
| }, | |||
| } | |||
| addCamera(camera: ICamera) { | |||
| addCamera(camera: ICamera, target?: IRenderTarget): VirtualCamera { | |||
| if (!this._viewer) throw 'Plugin not added to viewer' | |||
| const target = this._viewer.renderManager.composerTarget.clone(true) | |||
| target = target ?? this._viewer.renderManager.composerTarget.clone(true) | |||
| target.name = camera.name + '_virtualCamTarget' | |||
| const vCam: VirtualCamera = {camera, target, enabled: true} | |||
| this.cameras.push(vCam) | |||
| @@ -142,6 +142,7 @@ export class RenderManager<TE extends IRenderManagerEventMap = IRenderManagerEve | |||
| this._renderer = this._initWebGLRenderer(canvas, alpha) | |||
| this._context = this._renderer.getContext() | |||
| this._isWebGL2 = this._renderer.capabilities.isWebGL2 | |||
| if (!this._isWebGL2) console.error('RenderManager: WebGL 1 is not officially supported anymore. Some features may not work.') | |||
| this.resetShadows() | |||
| const composerTarget = this.createTarget<WebGLRenderTarget>(targetOptions, false) | |||
| @@ -162,7 +163,7 @@ export class RenderManager<TE extends IRenderManagerEventMap = IRenderManagerEve | |||
| }) | |||
| // renderer.info.autoReset = false // Not supported by ExtendedRenderPass | |||
| renderer.useLegacyLights = false | |||
| // renderer.useLegacyLights = false | |||
| renderer.setAnimationLoop(this._animationLoop) | |||
| renderer.onContextLost = (event: WebGLContextEvent) => { | |||
| this.dispatchEvent({type: 'contextLost', event}) | |||
| @@ -1,105 +1,37 @@ | |||
| import { | |||
| ColorSpace, | |||
| LinearSRGBColorSpace, | |||
| NoColorSpace, | |||
| RGBAFormat, | |||
| RGBM16ColorSpace, | |||
| SRGBColorSpace, | |||
| Texture, | |||
| UnsignedByteType, | |||
| WebGLRenderTarget, | |||
| } from 'three' | |||
| import {ColorSpace, LinearSRGBColorSpace, NoColorSpace, RGBM16ColorSpace, SRGBColorSpace} from 'three' | |||
| export function getEncodingComponents(colorSpace: ColorSpace) { | |||
| // three.js WebGLProgram.js | |||
| export function getTexelDecodingFunction(functionName: string, colorSpace: ColorSpace) { | |||
| let fn | |||
| switch (colorSpace) { | |||
| case NoColorSpace: | |||
| case LinearSRGBColorSpace: | |||
| return ['Linear', '( value )'] | |||
| fn = '' | |||
| break | |||
| case SRGBColorSpace: | |||
| return ['sRGB', '( value )'] | |||
| // case RGBEEncoding: | |||
| // return ['RGBE', '( value )'] | |||
| // case RGBM7Encoding: | |||
| // return ['RGBM', '( value, 7.0 )'] | |||
| // fn = 'sRGBToLinear' // todo required? | |||
| fn = '' | |||
| break | |||
| case RGBM16ColorSpace: | |||
| return ['RGBM', '( value, 16.0 )'] | |||
| // case RGBDEncoding: | |||
| // return ['RGBD', '( value, 256.0 )'] | |||
| // case GammaEncoding: | |||
| // return ['Gamma', '( value, float( GAMMA_FACTOR ) )'] | |||
| // case LogLuvEncoding: | |||
| // return ['LogLuv', '( value )'] | |||
| fn = 'RGBM16ToLinear' | |||
| break | |||
| default: | |||
| console.warn('utils: Unsupported colorspace:', colorSpace) | |||
| return ['Linear', '( value )'] | |||
| } | |||
| } | |||
| export function getTextureColorSpaceFromMap(map: Texture | WebGLRenderTarget | null | undefined, isWebGL2: boolean): ColorSpace { | |||
| let colorSpace | |||
| if (map && (<Texture>map).colorSpace !== undefined) { | |||
| colorSpace = (<Texture>map).colorSpace || NoColorSpace | |||
| } else if (map && (<WebGLRenderTarget>map).isWebGLRenderTarget) { | |||
| console.warn('THREE.WebGLPrograms.getTextureColorSpaceFromMap: don\'t use render targets as textures. Use their .texture property instead.') | |||
| colorSpace = (<WebGLRenderTarget>map).texture.colorSpace | |||
| } else { | |||
| colorSpace = LinearSRGBColorSpace | |||
| } | |||
| // See https://github.com/mrdoob/three.js/pull/22952 | |||
| // todo: just check if srgb8 is enabled, instead of relying on threejs. | |||
| if (isWebGL2 && map && (<Texture>map).isTexture && (<Texture>map).format === RGBAFormat && (<Texture>map).type === UnsignedByteType && (<Texture>map).colorSpace === SRGBColorSpace) { | |||
| colorSpace = LinearSRGBColorSpace // disable inline decode for sRGB textures in WebGL 2 | |||
| console.warn('THREE.WebGLProgram: Unsupported color space:', colorSpace) | |||
| fn = '' | |||
| break | |||
| } | |||
| return colorSpace | |||
| } | |||
| export function getTexelDecodingFunction(functionName: string, colorSpace: ColorSpace) { | |||
| const components = getEncodingComponents(colorSpace) | |||
| return 'vec4 ' + functionName + '( vec4 value ) { return ' + components[ 0 ] + 'ToLinear' + components[ 1 ] + '; }' | |||
| } | |||
| export function getTexelDecoding(mapName: string, map: Texture | WebGLRenderTarget | null | undefined | any, isWebGL2: boolean) { | |||
| return getTexelDecodingFunction(mapName + 'TexelToLinear', getTextureColorSpaceFromMap(map, isWebGL2)) + '\n' | |||
| } | |||
| export function getTexelDecoding2(mapName: string, colorSpace: ColorSpace) { | |||
| return getTexelDecodingFunction(mapName + 'TexelToLinear', colorSpace) + '\n' | |||
| } | |||
| export function getTexelEncodingFunction(functionName: string, colorSpace: ColorSpace) { | |||
| const components = getEncodingComponents(colorSpace) | |||
| return 'vec4 ' + functionName + '( vec4 value ) { return LinearTo' + components[ 0 ] + components[ 1 ] + '; }' | |||
| // return `vec4 ${functionName}( vec4 value ) { return ${components[ 0 ]}ToLinear${components[ 1 ]}; }`; | |||
| // return `vec4 ${functionName}( vec4 value ) { return ${fn} ( value ); }` | |||
| return `#define ${functionName}( value ) ${fn} ( value )` | |||
| } | |||
| export function getTexelEncoding(functionName: string, map: Texture | WebGLRenderTarget | null | undefined | any, isWebGL2: boolean) { | |||
| export function getTexelDecoding(mapName: string, colorSpace?: ColorSpace) { | |||
| return getTexelEncodingFunction(functionName, getTextureColorSpaceFromMap(map, isWebGL2)) | |||
| return getTexelDecodingFunction(mapName + 'TexelToLinear', colorSpace ?? LinearSRGBColorSpace) + '\n' | |||
| } | |||
| @@ -2,7 +2,7 @@ export {computeScreenSpaceBoundingBox} from './bbox' | |||
| export {overrideThreeCache} from './cache' | |||
| export {dataTextureFromColor, dataTextureFromVec4, halfFloatToRgbe} from './conversion' | |||
| export {uniform, matDefine, matDefineBool, bindToValue} from './decorators' | |||
| export {getEncodingComponents, getTexelEncoding, getTexelDecoding, getTexelDecoding2, getTexelDecodingFunction, getTexelEncodingFunction, getTextureColorSpaceFromMap} from './encoding' | |||
| export {getTexelDecoding, getTexelDecodingFunction} from './encoding' | |||
| export {generateUUID, toIndexedGeometry, isInScene, localToWorldQuaternion, worldToLocalQuaternion} from './misc' | |||
| export {getTextureDataType, textureToCanvas, textureDataToImageData, textureToDataUrl, textureToBlob, texImageToCanvas} from './texture' | |||
| export {threeConstMappings} from './const-mappings' | |||