| for (const vElement of f) shader.fragmentShader = shaderReplaceString(shader.fragmentShader, vElement[0], '#glMarker ' + vElement[1] + '\n' + vElement[0]) | for (const vElement of f) shader.fragmentShader = shaderReplaceString(shader.fragmentShader, vElement[0], '#glMarker ' + vElement[1] + '\n' + vElement[0]) | ||||
| iMaterialCommons.onBeforeCompile.call(this, shader, renderer) | iMaterialCommons.onBeforeCompile.call(this, shader, renderer) | ||||
| // ;(shader as any).defines.INVERSE_ALPHAMAP = this.userData.inverseAlphaMap ? 1 : 0 // todo | |||||
| // shader.defines.INVERSE_ALPHAMAP = this.userData.inverseAlphaMap ? 1 : 0 // todo | |||||
| super.onBeforeCompile(shader, renderer) | super.onBeforeCompile(shader, renderer) | ||||
| } | } |
| return super.customProgramCacheKey() + iMaterialCommons.customProgramCacheKey.call(this) | return super.customProgramCacheKey() + iMaterialCommons.customProgramCacheKey.call(this) | ||||
| } | } | ||||
| onBeforeCompile(shader: Shader, renderer: WebGLRenderer): void { // shader is not Shader but WebglUniforms.getParameters return value type so includes defines | |||||
| onBeforeCompile(shader: Shader&{defines: any}, renderer: WebGLRenderer): void { // shader is not Shader but WebglUniforms.getParameters return value type so includes defines | |||||
| const f = [ | const f = [ | ||||
| ['vec3 totalDiffuse = ', 'afterModulation'], | ['vec3 totalDiffuse = ', 'afterModulation'], | ||||
| ['#include <aomap_fragment>', 'beforeModulation'], | ['#include <aomap_fragment>', 'beforeModulation'], | ||||
| iMaterialCommons.onBeforeCompile.call(this, shader, renderer) | iMaterialCommons.onBeforeCompile.call(this, shader, renderer) | ||||
| ;(shader as any).defines && ((shader as any).defines.INVERSE_ALPHAMAP = this.userData.inverseAlphaMap ? 1 : 0) | |||||
| shader.defines && (shader.defines.INVERSE_ALPHAMAP = this.userData.inverseAlphaMap ? 1 : 0) | |||||
| super.onBeforeCompile(shader, renderer) | super.onBeforeCompile(shader, renderer) | ||||
| } | } |
| for (const vElement of f) shader.fragmentShader = shaderReplaceString(shader.fragmentShader, vElement[0], '#glMarker ' + vElement[1] + '\n' + vElement[0]) | for (const vElement of f) shader.fragmentShader = shaderReplaceString(shader.fragmentShader, vElement[0], '#glMarker ' + vElement[1] + '\n' + vElement[0]) | ||||
| iMaterialCommons.onBeforeCompile.call(this, shader, renderer) | iMaterialCommons.onBeforeCompile.call(this, shader, renderer) | ||||
| // ;(shader as any).defines.INVERSE_ALPHAMAP = this.userData.inverseAlphaMap ? 1 : 0 // todo | |||||
| // shader.defines.INVERSE_ALPHAMAP = this.userData.inverseAlphaMap ? 1 : 0 // todo | |||||
| super.onBeforeCompile(shader, renderer) | super.onBeforeCompile(shader, renderer) | ||||
| } | } |
| updateMaterialDefines(materialExtension.extraDefines, material) | updateMaterialDefines(materialExtension.extraDefines, material) | ||||
| // Call shaderExtender if defined | // Call shaderExtender if defined | ||||
| materialExtension.shaderExtender?.(shader, material, renderer) | |||||
| materialExtension.shaderExtender?.(shader as any, material, renderer) | |||||
| // Save last shader so that it can be used to check if shader has changed in extensions | // Save last shader so that it can be used to check if shader has changed in extensions | ||||
| material.lastShader = shader | material.lastShader = shader | ||||
| } | } | ||||
| value.onAfterRender?.(object, material, renderer) | value.onAfterRender?.(object, material, renderer) | ||||
| } | } | ||||
| } | } | ||||
| /** | |||||
| * Creates a {@link MaterialExtension} with getUiConfig that also caches the config for the material based on uuid | |||||
| * @param getUiConfig - function that returns a ui config. make sure its static. | |||||
| * @param uuid uuid to use. | |||||
| */ | |||||
| export function uiConfigMaterialExtension(getUiConfig: Required<MaterialExtension>['getUiConfig'], uuid?: string) { | |||||
| const uuid1 = uuid || generateUUID() | |||||
| return { | |||||
| uuid: uuid1, | |||||
| // todo clean code. | |||||
| getUiConfig: material => { | |||||
| if (!(material as any).__uiConfigs) (material as any).__uiConfigs = {} as any // todo remove reference sometime after plugin removed | |||||
| if ((material as any).__uiConfigs[uuid1]) return (material as any).__uiConfigs[uuid1] | |||||
| const config = getUiConfig(material); | |||||
| (material as any).__uiConfigs[uuid1] = config | |||||
| return config | |||||
| }, | |||||
| isCompatible: () => true, | |||||
| } as MaterialExtension | |||||
| } |
| * @param material | * @param material | ||||
| * @param renderer | * @param renderer | ||||
| */ | */ | ||||
| shaderExtender?: (shader: Shader, material: IMaterial, renderer: WebGLRenderer) => void, | |||||
| shaderExtender?: (shader: Shader&{defines: any; extensionDerivatives?: boolean}, material: IMaterial, renderer: WebGLRenderer) => void, | |||||
| /** | /** | ||||
| * Extra code to add to the top of the fragment shader | * Extra code to add to the top of the fragment shader | ||||
| * Value can be a string or a function that returns a string | * Value can be a string or a function that returns a string |
| 'outgoingLight = outgoingLight * ( 1.0 - material.clearcoat * Fcc ) + clearcoatSpecular * material.clearcoat;', | 'outgoingLight = outgoingLight * ( 1.0 - material.clearcoat * Fcc ) + clearcoatSpecular * material.clearcoat;', | ||||
| 'outgoingLight *= clearcoatTint(dotNVcc, dotNVcc, material.clearcoat);\n', {prepend: true}) | 'outgoingLight *= clearcoatTint(dotNVcc, dotNVcc, material.clearcoat);\n', {prepend: true}) | ||||
| ;(shader as any).defines.USE_UV = '' | |||||
| shader.defines.USE_UV = '' | |||||
| }, | }, | ||||
| onObjectRender: (_, material) => { | onObjectRender: (_, material) => { |
| `, {prepend: true}, | `, {prepend: true}, | ||||
| ) | ) | ||||
| ;(shader as any).defines.USE_UV = '' | |||||
| shader.defines.USE_UV = '' | |||||
| }, | }, | ||||
| onObjectRender: (object: IObject3D, material) => { | onObjectRender: (object: IObject3D, material) => { | ||||
| const userData = material.userData | const userData = material.userData |
| shaderExtender: (shader, material: PhysicalMaterial) => { | shaderExtender: (shader, material: PhysicalMaterial) => { | ||||
| if (this.isDisabled() || !material?.userData._noiseBumpMat?.hasBump) return | if (this.isDisabled() || !material?.userData._noiseBumpMat?.hasBump) return | ||||
| shader.fragmentShader = shaderReplaceString(shader.fragmentShader, '#glMarker beforeAccumulation', NoiseBumpMaterialPluginPatch, {prepend: true}) | shader.fragmentShader = shaderReplaceString(shader.fragmentShader, '#glMarker beforeAccumulation', NoiseBumpMaterialPluginPatch, {prepend: true}) | ||||
| ;(shader as any).defines.USE_UV = '' | |||||
| ;(shader as any).extensionDerivatives = true | |||||
| shader.defines.USE_UV = '' | |||||
| shader.extensionDerivatives = true | |||||
| }, | }, | ||||
| onObjectRender: (_: IObject3D, material) => { | onObjectRender: (_: IObject3D, material) => { | ||||
| const tfUd = material.userData._noiseBumpMat | const tfUd = material.userData._noiseBumpMat |
| import {IPassID, IPipelinePass} from './Pass' | import {IPassID, IPipelinePass} from './Pass' | ||||
| import {uiDropdown, uiFolderContainer, UiObjectConfig, uiToggle} from 'uiconfig.js' | import {uiDropdown, uiFolderContainer, UiObjectConfig, uiToggle} from 'uiconfig.js' | ||||
| import {ViewerRenderManager} from '../viewer' | import {ViewerRenderManager} from '../viewer' | ||||
| import {matDefine, threeConstMappings} from '../three' | |||||
| import {matDefineBool, threeConstMappings} from '../three' | |||||
| import ScreenPassShader from './ScreenPass.glsl' | import ScreenPassShader from './ScreenPass.glsl' | ||||
| import {shaderReplaceString} from '../utils' | import {shaderReplaceString} from '../utils' | ||||
| super.dispose() | super.dispose() | ||||
| } | } | ||||
| @matDefine('CLIP_BACKGROUND', undefined, undefined, ScreenPass.prototype.setDirty, (v)=>v ? '1' : undefined, (v)=>!!v) | |||||
| @uiToggle() clipBackground = false | |||||
| // todo test | |||||
| @matDefineBool('CLIP_BACKGROUND', undefined, undefined, ScreenPass.prototype.setDirty, true) | |||||
| @uiToggle() clipBackground = false // todo show warning that gbuffer is required | |||||
| beforeRender(_: IScene, _1: ICamera, renderManager: ViewerRenderManager) { | beforeRender(_: IScene, _1: ICamera, renderManager: ViewerRenderManager) { | ||||
| this.material.uniforms.tTransparent.value = renderManager.renderPass.preserveTransparentTarget ? renderManager.renderPass.transparentTarget?.texture || null : null | this.material.uniforms.tTransparent.value = renderManager.renderPass.preserveTransparentTarget ? renderManager.renderPass.transparentTarget?.texture || null : null |
| } | } | ||||
| /** | /** | ||||
| * Decorator to create a three.js style define in this or this.material and bind to a property. | |||||
| * Decorator to create a three.js style define in this.material or this and bind to a property. | |||||
| * see also - {@link matDefineBool} | * see also - {@link matDefineBool} | ||||
| * @param key - define name | * @param key - define name | ||||
| * @param customDefines - object for setting define value (like ShaderMaterial.defines), otherwise this.material.defines is taken | * @param customDefines - object for setting define value (like ShaderMaterial.defines), otherwise this.material.defines is taken |
| export {computeScreenSpaceBoundingBox} from './bbox' | export {computeScreenSpaceBoundingBox} from './bbox' | ||||
| export {overrideThreeCache} from './cache' | export {overrideThreeCache} from './cache' | ||||
| export {dataTextureFromColor, dataTextureFromVec4, halfFloatToRgbe} from './conversion' | export {dataTextureFromColor, dataTextureFromVec4, halfFloatToRgbe} from './conversion' | ||||
| export {uniform, matDefine} from './decorators' | |||||
| export {uniform, matDefine, matDefineBool, bindToValue} from './decorators' | |||||
| export {getEncodingComponents, getTexelEncoding, getTexelDecoding, getTexelDecoding2, getTexelDecodingFunction, getTexelEncodingFunction, getTextureColorSpaceFromMap} from './encoding' | export {getEncodingComponents, getTexelEncoding, getTexelDecoding, getTexelDecoding2, getTexelDecodingFunction, getTexelEncodingFunction, getTextureColorSpaceFromMap} from './encoding' | ||||
| export {generateUUID, toIndexedGeometry, isInScene, localToWorldQuaternion, worldToLocalQuaternion} from './misc' | export {generateUUID, toIndexedGeometry, isInScene, localToWorldQuaternion, worldToLocalQuaternion} from './misc' | ||||
| export {getTextureDataType, textureToCanvas, textureDataToImageData, textureToDataUrl, textureToBlob, texImageToCanvas} from './texture' | export {getTextureDataType, textureToCanvas, textureDataToImageData, textureToDataUrl, textureToBlob, texImageToCanvas} from './texture' |
| #ifndef BASIC_RANDOM_HELPERS | #ifndef BASIC_RANDOM_HELPERS | ||||
| #define BASIC_RANDOM_HELPERS | #define BASIC_RANDOM_HELPERS | ||||
| uniform float frameCount; | |||||
| float random(float n){return fract(sin(n) * 43758.5453123);} | float random(float n){return fract(sin(n) * 43758.5453123);} | ||||