"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var __publicField = (obj, key, value) => { __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); return value; }; // dist/index.js var dist_exports = {}; __export(dist_exports, { ShaderAssembler: () => ShaderAssembler, ShaderModuleInstance: () => ShaderModuleInstance, _ShaderModuleInstance: () => ShaderModuleInstance, _getDependencyGraph: () => getDependencyGraph, _resolveModules: () => resolveModules, _warp: () => warp, assembleShaderPairGLSL: () => assembleShaderPairGLSL, brightnessContrast: () => brightnessContrast, bulgePinch: () => bulgePinch, capitalize: () => capitalize, colorHalftone: () => colorHalftone, combineInjects: () => combineInjects, convertToVec4: () => convertToVec4, denoise: () => denoise, dirlight: () => dirlight, dirlight1: () => dirlight2, dotScreen: () => dotScreen, edgeWork: () => edgeWork, fp32: () => fp32, fp64: () => fp64, fp64arithmetic: () => fp64arithmetic, fxaa: () => fxaa, generateShaderForModule: () => generateShaderForModule, geometry1: () => geometry, getPassthroughFS: () => getPassthroughFS, getQualifierDetails: () => getQualifierDetails, getShaderInfo: () => getShaderInfo, getShaderLayoutFromWGSL: () => getShaderLayoutFromWGSL, glsl: () => glsl, gouraudLighting: () => gouraudLighting, gouraudMaterial: () => gouraudMaterial, hexagonalPixelate: () => hexagonalPixelate, hueSaturation: () => hueSaturation, ink: () => ink, lighting: () => lighting, lights1: () => lights, magnify: () => magnify, noise: () => noise, normalizeShaderModule: () => normalizeShaderModule, pbr: () => pbr, pbrMaterial: () => pbrMaterial, phongLighting: () => phongLighting, phongMaterial: () => phongMaterial, picking: () => picking, project1: () => project, random: () => random, sepia: () => sepia, swirl: () => swirl, tiltShift: () => tiltShift, triangleBlur: () => triangleBlur, typeToChannelCount: () => typeToChannelCount, typeToChannelSuffix: () => typeToChannelSuffix, vibrance: () => vibrance, vignette: () => vignette, zoomBlur: () => zoomBlur }); module.exports = __toCommonJS(dist_exports); // dist/lib/glsl-utils/highlight.js var glsl = (x) => `${x}`; // dist/lib/utils/assert.js function assert(condition, message) { if (!condition) { throw new Error(message || "shadertools: assertion failed."); } } // dist/lib/filters/prop-types.js var DEFAULT_PROP_VALIDATORS = { number: { type: "number", validate(value, propType) { return Number.isFinite(value) && typeof propType === "object" && (propType.max === void 0 || value <= propType.max) && (propType.min === void 0 || value >= propType.min); } }, array: { type: "array", validate(value, propType) { return Array.isArray(value) || ArrayBuffer.isView(value); } } }; function makePropValidators(propTypes) { const propValidators = {}; for (const [name, propType] of Object.entries(propTypes)) { propValidators[name] = makePropValidator(propType); } return propValidators; } function getValidatedProperties(properties, propValidators, errorMessage) { const validated = {}; for (const [key, propsValidator] of Object.entries(propValidators)) { if (properties && key in properties && !propsValidator.private) { if (propsValidator.validate) { assert(propsValidator.validate(properties[key], propsValidator), `${errorMessage}: invalid ${key}`); } validated[key] = properties[key]; } else { validated[key] = propsValidator.value; } } return validated; } function makePropValidator(propType) { let type = getTypeOf(propType); if (type !== "object") { return { value: propType, ...DEFAULT_PROP_VALIDATORS[type], type }; } if (typeof propType === "object") { if (!propType) { return { type: "object", value: null }; } if (propType.type !== void 0) { return { ...propType, ...DEFAULT_PROP_VALIDATORS[propType.type], type: propType.type }; } if (propType.value === void 0) { return { type: "object", value: propType }; } type = getTypeOf(propType.value); return { ...propType, ...DEFAULT_PROP_VALIDATORS[type], type }; } throw new Error("props"); } function getTypeOf(value) { if (Array.isArray(value) || ArrayBuffer.isView(value)) { return "array"; } return typeof value; } // dist/module-injectors.js var MODULE_INJECTORS_VS = `#ifdef MODULE_LOGDEPTH logdepth_adjustPosition(gl_Position); #endif `; var MODULE_INJECTORS_FS = `#ifdef MODULE_MATERIAL gl_FragColor = material_filterColor(gl_FragColor); #endif #ifdef MODULE_LIGHTING gl_FragColor = lighting_filterColor(gl_FragColor); #endif #ifdef MODULE_FOG gl_FragColor = fog_filterColor(gl_FragColor); #endif #ifdef MODULE_PICKING gl_FragColor = picking_filterHighlightColor(gl_FragColor); gl_FragColor = picking_filterPickingColor(gl_FragColor); #endif #ifdef MODULE_LOGDEPTH logdepth_setFragDepth(); #endif `; // dist/lib/shader-assembly/shader-injections.js var MODULE_INJECTORS = { vertex: MODULE_INJECTORS_VS, fragment: MODULE_INJECTORS_FS }; var REGEX_START_OF_MAIN = /void\s+main\s*\([^)]*\)\s*\{\n?/; var REGEX_END_OF_MAIN = /}\n?[^{}]*$/; var fragments = []; var DECLARATION_INJECT_MARKER = "__LUMA_INJECT_DECLARATIONS__"; function normalizeInjections(injections) { const result = { vertex: {}, fragment: {} }; for (const hook in injections) { let injection = injections[hook]; const stage = getHookStage(hook); if (typeof injection === "string") { injection = { order: 0, injection }; } result[stage][hook] = injection; } return result; } function getHookStage(hook) { const type = hook.slice(0, 2); switch (type) { case "vs": return "vertex"; case "fs": return "fragment"; default: throw new Error(type); } } function injectShader(source, stage, inject, injectStandardStubs = false) { const isVertex = stage === "vertex"; for (const key in inject) { const fragmentData = inject[key]; fragmentData.sort((a, b) => a.order - b.order); fragments.length = fragmentData.length; for (let i = 0, len = fragmentData.length; i < len; ++i) { fragments[i] = fragmentData[i].injection; } const fragmentString = `${fragments.join("\n")} `; switch (key) { case "vs:#decl": if (isVertex) { source = source.replace(DECLARATION_INJECT_MARKER, fragmentString); } break; case "vs:#main-start": if (isVertex) { source = source.replace(REGEX_START_OF_MAIN, (match) => match + fragmentString); } break; case "vs:#main-end": if (isVertex) { source = source.replace(REGEX_END_OF_MAIN, (match) => fragmentString + match); } break; case "fs:#decl": if (!isVertex) { source = source.replace(DECLARATION_INJECT_MARKER, fragmentString); } break; case "fs:#main-start": if (!isVertex) { source = source.replace(REGEX_START_OF_MAIN, (match) => match + fragmentString); } break; case "fs:#main-end": if (!isVertex) { source = source.replace(REGEX_END_OF_MAIN, (match) => fragmentString + match); } break; default: source = source.replace(key, (match) => match + fragmentString); } } source = source.replace(DECLARATION_INJECT_MARKER, ""); if (injectStandardStubs) { source = source.replace(/\}\s*$/, (match) => match + MODULE_INJECTORS[stage]); } return source; } function combineInjects(injects) { const result = {}; assert(Array.isArray(injects) && injects.length > 1); injects.forEach((inject) => { for (const key in inject) { result[key] = result[key] ? `${result[key]} ${inject[key]}` : inject[key]; } }); return result; } // dist/lib/shader-module/shader-module-instance.js var index = 1; var ShaderModuleInstance = class { name; vs; fs; getModuleUniforms; dependencies; deprecations; defines; injections; uniforms = {}; uniformTypes = {}; static instantiateModules(modules) { return modules.map((module2) => { if (module2 instanceof ShaderModuleInstance) { return module2; } assert(typeof module2 !== "string", `Shader module use by name is deprecated. Import shader module '${JSON.stringify(module2)}' and use it directly.`); if (!module2.name) { console.warn("shader module has no name"); module2.name = `shader-module-${index++}`; } const moduleObject = new ShaderModuleInstance(module2); moduleObject.dependencies = ShaderModuleInstance.instantiateModules(module2.dependencies || []); return moduleObject; }); } constructor(props) { const { name, vs: vs6, fs: fs28, dependencies = [], uniformTypes = {}, uniformPropTypes = {}, getUniforms: getUniforms9, deprecations = [], defines = {}, inject = {} } = props; assert(typeof name === "string"); this.name = name; this.vs = vs6; this.fs = fs28; this.getModuleUniforms = getUniforms9; this.dependencies = ShaderModuleInstance.instantiateModules(dependencies); this.deprecations = this._parseDeprecationDefinitions(deprecations); this.defines = defines; this.injections = normalizeInjections(inject); this.uniformTypes = uniformTypes; if (uniformPropTypes) { this.uniforms = makePropValidators(uniformPropTypes); } } // Extracts the source code chunk for the specified shader type from the named shader module getModuleSource(stage) { let moduleSource; switch (stage) { case "vertex": moduleSource = this.vs || ""; break; case "fragment": moduleSource = this.fs || ""; break; default: assert(false); } const moduleName = this.name.toUpperCase().replace(/[^0-9a-z]/gi, "_"); return `// ----- MODULE ${this.name} --------------- #define MODULE_${moduleName} ${moduleSource} `; } getUniforms(userProps, uniforms) { if (this.getModuleUniforms) { return this.getModuleUniforms(userProps, uniforms); } return getValidatedProperties(userProps, this.uniforms, this.name); } getDefines() { return this.defines; } // Warn about deprecated uniforms or functions checkDeprecations(shaderSource, log3) { this.deprecations.forEach((def) => { var _a; if ((_a = def.regex) == null ? void 0 : _a.test(shaderSource)) { if (def.deprecated) { log3.deprecated(def.old, def.new)(); } else { log3.removed(def.old, def.new)(); } } }); } _parseDeprecationDefinitions(deprecations) { deprecations.forEach((def) => { switch (def.type) { case "function": def.regex = new RegExp(`\\b${def.old}\\(`); break; default: def.regex = new RegExp(`${def.type} ${def.old};`); } }); return deprecations; } _defaultGetUniforms(opts = {}) { const uniforms = {}; const propTypes = this.uniforms; for (const key in propTypes) { const propDef = propTypes[key]; if (key in opts && !propDef.private) { if (propDef.validate) { assert(propDef.validate(opts[key], propDef), `${this.name}: invalid ${key}`); } uniforms[key] = opts[key]; } else { uniforms[key] = propDef.value; } } return uniforms; } }; // dist/lib/shader-assembly/select-shaders.js function selectShaders(props) { if (props.source && props.platformInfo.type === "webgpu") { const propsCopy = { ...props, vs: void 0, fs: void 0 }; return propsCopy; } if (!props.vs) { throw new Error("no vertex shader"); } const vs6 = getShaderSource(props.platformInfo, props.vs); let fs28; if (props.fs) { fs28 = getShaderSource(props.platformInfo, props.fs); } return { ...props, vs: vs6, fs: fs28 }; } function getShaderSource(platformInfo, shader) { if (typeof shader === "string") { return shader; } switch (platformInfo.type) { case "webgpu": if (shader == null ? void 0 : shader.wgsl) { return shader.wgsl; } throw new Error("WebGPU does not support GLSL shaders"); default: if (shader == null ? void 0 : shader.glsl) { return shader.glsl; } throw new Error("WebGL does not support WGSL shaders"); } } // dist/lib/shader-assembly/resolve-modules.js function resolveModules(modules) { const instances = ShaderModuleInstance.instantiateModules(modules); return getShaderDependencies(instances); } function getShaderDependencies(modules) { const moduleMap = {}; const moduleDepth = {}; getDependencyGraph({ modules, level: 0, moduleMap, moduleDepth }); return Object.keys(moduleDepth).sort((a, b) => moduleDepth[b] - moduleDepth[a]).map((name) => moduleMap[name]); } function getDependencyGraph(options) { const { modules, level, moduleMap, moduleDepth } = options; if (level >= 5) { throw new Error("Possible loop in shader dependency graph"); } for (const module2 of modules) { moduleMap[module2.name] = module2; if (moduleDepth[module2.name] === void 0 || moduleDepth[module2.name] < level) { moduleDepth[module2.name] = level; } } for (const module2 of modules) { if (module2.dependencies) { getDependencyGraph({ modules: module2.dependencies, level: level + 1, moduleMap, moduleDepth }); } } } // dist/lib/shader-assembly/platform-defines.js function getPlatformShaderDefines(platformInfo) { switch (platformInfo == null ? void 0 : platformInfo.gpu.toLowerCase()) { case "apple": return `#define APPLE_GPU #define LUMA_FP64_CODE_ELIMINATION_WORKAROUND 1 #define LUMA_FP32_TAN_PRECISION_WORKAROUND 1 #define LUMA_FP64_HIGH_BITS_OVERFLOW_WORKAROUND 1 `; case "nvidia": return `#define NVIDIA_GPU #define LUMA_FP64_CODE_ELIMINATION_WORKAROUND 1 `; case "intel": return `#define INTEL_GPU #define LUMA_FP64_CODE_ELIMINATION_WORKAROUND 1 #define LUMA_FP32_TAN_PRECISION_WORKAROUND 1 #define LUMA_FP64_HIGH_BITS_OVERFLOW_WORKAROUND 1 `; case "amd": return `#define AMD_GPU `; default: return `#define DEFAULT_GPU #define LUMA_FP64_CODE_ELIMINATION_WORKAROUND 1 #define LUMA_FP32_TAN_PRECISION_WORKAROUND 1 #define LUMA_FP64_HIGH_BITS_OVERFLOW_WORKAROUND 1 `; } } // dist/lib/shader-transpiler/transpile-glsl-shader.js function transpileGLSLShader(source, stage) { var _a; const sourceGLSLVersion = Number(((_a = source.match(/^#version[ \t]+(\d+)/m)) == null ? void 0 : _a[1]) || 100); if (sourceGLSLVersion !== 300) { throw new Error("luma.gl v9 only supports GLSL 3.00 shader sources"); } switch (stage) { case "vertex": source = convertShader(source, ES300_VERTEX_REPLACEMENTS); return source; case "fragment": source = convertShader(source, ES300_FRAGMENT_REPLACEMENTS); return source; default: throw new Error(stage); } } var ES300_REPLACEMENTS = [ // Fix poorly formatted version directive [/^(#version[ \t]+(100|300[ \t]+es))?[ \t]*\n/, "#version 300 es\n"], // The individual `texture...()` functions were replaced with `texture()` overloads [/\btexture(2D|2DProj|Cube)Lod(EXT)?\(/g, "textureLod("], [/\btexture(2D|2DProj|Cube)(EXT)?\(/g, "texture("] ]; var ES300_VERTEX_REPLACEMENTS = [ ...ES300_REPLACEMENTS, // `attribute` keyword replaced with `in` [makeVariableTextRegExp("attribute"), "in $1"], // `varying` keyword replaced with `out` [makeVariableTextRegExp("varying"), "out $1"] ]; var ES300_FRAGMENT_REPLACEMENTS = [ ...ES300_REPLACEMENTS, // `varying` keyword replaced with `in` [makeVariableTextRegExp("varying"), "in $1"] ]; function convertShader(source, replacements) { for (const [pattern, replacement] of replacements) { source = source.replace(pattern, replacement); } return source; } function makeVariableTextRegExp(qualifier) { return new RegExp(`\\b${qualifier}[ \\t]+(\\w+[ \\t]+\\w+(\\[\\w+\\])?;)`, "g"); } // dist/lib/shader-assembly/shader-hooks.js function getShaderHooks(hookFunctions, hookInjections) { let result = ""; for (const hookName in hookFunctions) { const hookFunction = hookFunctions[hookName]; result += `void ${hookFunction.signature} { `; if (hookFunction.header) { result += ` ${hookFunction.header}`; } if (hookInjections[hookName]) { const injections = hookInjections[hookName]; injections.sort((a, b) => a.order - b.order); for (const injection of injections) { result += ` ${injection.injection} `; } } if (hookFunction.footer) { result += ` ${hookFunction.footer}`; } result += "}\n"; } return result; } function normalizeShaderHooks(hookFunctions) { const result = { vertex: {}, fragment: {} }; for (const hookFunction of hookFunctions) { let opts; let hook; if (typeof hookFunction !== "string") { opts = hookFunction; hook = opts.hook; } else { opts = {}; hook = hookFunction; } hook = hook.trim(); const [shaderStage, signature] = hook.split(":"); const name = hook.replace(/\(.+/, ""); const normalizedHook = Object.assign(opts, { signature }); switch (shaderStage) { case "vs": result.vertex[name] = normalizedHook; break; case "fs": result.fragment[name] = normalizedHook; break; default: throw new Error(shaderStage); } } return result; } // dist/lib/glsl-utils/get-shader-info.js function getShaderInfo(source, defaultName) { return { name: getShaderName(source, defaultName), language: "glsl", version: getShaderVersion(source) }; } function getShaderName(shader, defaultName = "unnamed") { const SHADER_NAME_REGEXP = /#define[^\S\r\n]*SHADER_NAME[^\S\r\n]*([A-Za-z0-9_-]+)\s*/; const match = SHADER_NAME_REGEXP.exec(shader); return match ? match[1] : defaultName; } function getShaderVersion(source) { let version = 100; const words = source.match(/[^\s]+/g); if (words && words.length >= 2 && words[0] === "#version") { const parsedVersion = parseInt(words[1], 10); if (Number.isFinite(parsedVersion)) { version = parsedVersion; } } if (version !== 100 && version !== 300) { throw new Error(`Invalid GLSL version ${version}`); } return version; } // dist/lib/shader-assembly/assemble-shaders.js var INJECT_SHADER_DECLARATIONS = ` ${DECLARATION_INJECT_MARKER} `; var FRAGMENT_SHADER_PROLOGUE = `precision highp float; `; function assembleShaderWGSL(options) { const modules = resolveModules(options.modules || []); return { source: assembleWGSLShader(options.platformInfo, { ...options, source: options.source, stage: "vertex", modules }), getUniforms: assembleGetUniforms(modules) }; } function assembleShaderPairWGSL(options) { const modules = resolveModules(options.modules || []); return { vs: assembleWGSLShader(options.platformInfo, { ...options, source: options.vs, stage: "vertex", modules }), fs: assembleWGSLShader(options.platformInfo, { ...options, source: options.fs, stage: "fragment", modules }), getUniforms: assembleGetUniforms(modules) }; } function assembleShaderPairGLSL(options) { const { vs: vs6, fs: fs28 } = options; const modules = resolveModules(options.modules || []); return { vs: assembleGLSLShader(options.platformInfo, { ...options, source: vs6, stage: "vertex", modules }), fs: assembleGLSLShader(options.platformInfo, { ...options, source: fs28, stage: "fragment", modules }), getUniforms: assembleGetUniforms(modules) }; } function assembleWGSLShader(platformInfo, options) { const { // id, source, stage, modules, // defines = {}, hookFunctions = [], inject = {}, log: log3 } = options; assert(typeof source === "string", "shader source must be a string"); const coreSource = source; let assembledSource = ""; const hookFunctionMap = normalizeShaderHooks(hookFunctions); const hookInjections = {}; const declInjections = {}; const mainInjections = {}; for (const key in inject) { const injection = typeof inject[key] === "string" ? { injection: inject[key], order: 0 } : inject[key]; const match = /^(v|f)s:(#)?([\w-]+)$/.exec(key); if (match) { const hash = match[2]; const name = match[3]; if (hash) { if (name === "decl") { declInjections[key] = [injection]; } else { mainInjections[key] = [injection]; } } else { hookInjections[key] = [injection]; } } else { mainInjections[key] = [injection]; } } const modulesToInject = platformInfo.type !== "webgpu" ? modules : []; for (const module2 of modulesToInject) { if (log3) { module2.checkDeprecations(coreSource, log3); } const moduleSource = module2.getModuleSource(stage, "wgsl"); assembledSource += moduleSource; const injections = module2.injections[stage]; for (const key in injections) { const match = /^(v|f)s:#([\w-]+)$/.exec(key); if (match) { const name = match[2]; const injectionType = name === "decl" ? declInjections : mainInjections; injectionType[key] = injectionType[key] || []; injectionType[key].push(injections[key]); } else { hookInjections[key] = hookInjections[key] || []; hookInjections[key].push(injections[key]); } } } assembledSource += INJECT_SHADER_DECLARATIONS; assembledSource = injectShader(assembledSource, stage, declInjections); assembledSource += getShaderHooks(hookFunctionMap[stage], hookInjections); assembledSource += coreSource; assembledSource = injectShader(assembledSource, stage, mainInjections); return assembledSource; } function assembleGLSLShader(platformInfo, options) { const { id, source, stage, language = "glsl", modules, defines = {}, hookFunctions = [], inject = {}, prologue = true, log: log3 } = options; assert(typeof source === "string", "shader source must be a string"); const sourceVersion = language === "glsl" ? getShaderInfo(source).version : -1; const targetVersion = platformInfo.shaderLanguageVersion; const sourceVersionDirective = sourceVersion === 100 ? "#version 100" : "#version 300 es"; const sourceLines = source.split("\n"); const coreSource = sourceLines.slice(1).join("\n"); const allDefines = {}; modules.forEach((module2) => { Object.assign(allDefines, module2.getDefines()); }); Object.assign(allDefines, defines); let assembledSource = ""; switch (language) { case "wgsl": break; case "glsl": assembledSource = prologue ? `${sourceVersionDirective} // ----- PROLOGUE ------------------------- ${getShaderNameDefine({ id, source, stage })} ${`#define SHADER_TYPE_${stage.toUpperCase()}`} ${getPlatformShaderDefines(platformInfo)} ${stage === "fragment" ? FRAGMENT_SHADER_PROLOGUE : ""} // ----- APPLICATION DEFINES ------------------------- ${getApplicationDefines(allDefines)} ` : `${sourceVersionDirective} `; break; } const hookFunctionMap = normalizeShaderHooks(hookFunctions); const hookInjections = {}; const declInjections = {}; const mainInjections = {}; for (const key in inject) { const injection = typeof inject[key] === "string" ? { injection: inject[key], order: 0 } : inject[key]; const match = /^(v|f)s:(#)?([\w-]+)$/.exec(key); if (match) { const hash = match[2]; const name = match[3]; if (hash) { if (name === "decl") { declInjections[key] = [injection]; } else { mainInjections[key] = [injection]; } } else { hookInjections[key] = [injection]; } } else { mainInjections[key] = [injection]; } } for (const module2 of modules) { if (log3) { module2.checkDeprecations(coreSource, log3); } const moduleSource = module2.getModuleSource(stage); assembledSource += moduleSource; const injections = module2.injections[stage]; for (const key in injections) { const match = /^(v|f)s:#([\w-]+)$/.exec(key); if (match) { const name = match[2]; const injectionType = name === "decl" ? declInjections : mainInjections; injectionType[key] = injectionType[key] || []; injectionType[key].push(injections[key]); } else { hookInjections[key] = hookInjections[key] || []; hookInjections[key].push(injections[key]); } } } assembledSource += "// ----- MAIN SHADER SOURCE -------------------------"; assembledSource += INJECT_SHADER_DECLARATIONS; assembledSource = injectShader(assembledSource, stage, declInjections); assembledSource += getShaderHooks(hookFunctionMap[stage], hookInjections); assembledSource += coreSource; assembledSource = injectShader(assembledSource, stage, mainInjections); if (language === "glsl" && sourceVersion !== targetVersion) { assembledSource = transpileGLSLShader(assembledSource, stage); } return assembledSource.trim(); } function assembleGetUniforms(modules) { return function getUniforms9(opts) { const uniforms = {}; for (const module2 of modules) { const moduleUniforms = module2.getUniforms(opts, uniforms); Object.assign(uniforms, moduleUniforms); } return uniforms; }; } function getShaderNameDefine(options) { const { id, source, stage } = options; const injectShaderName = id && source.indexOf("SHADER_NAME") === -1; return injectShaderName ? ` #define SHADER_NAME ${id}_${stage} ` : ""; } function getApplicationDefines(defines = {}) { let sourceText = ""; for (const define in defines) { const value = defines[define]; if (value || Number.isFinite(value)) { sourceText += `#define ${define.toUpperCase()} ${defines[define]} `; } } return sourceText; } // dist/lib/shader-assembler.js var _ShaderAssembler = class { /** Hook functions */ _hookFunctions = []; /** Shader modules */ _defaultModules = []; /** * A default shader assembler instance - the natural place to register default modules and hooks * @returns */ static getDefaultShaderAssembler() { _ShaderAssembler.defaultShaderAssembler = _ShaderAssembler.defaultShaderAssembler || new _ShaderAssembler(); return _ShaderAssembler.defaultShaderAssembler; } /** * Add a default module that does not have to be provided with every call to assembleShaders() */ addDefaultModule(module2) { if (!this._defaultModules.find((m) => m.name === (typeof module2 === "string" ? module2 : module2.name))) { this._defaultModules.push(module2); } } /** * Remove a default module */ removeDefaultModule(module2) { const moduleName = typeof module2 === "string" ? module2 : module2.name; this._defaultModules = this._defaultModules.filter((m) => m.name !== moduleName); } /** * Register a shader hook * @param hook * @param opts */ addShaderHook(hook, opts) { if (opts) { hook = Object.assign(opts, { hook }); } this._hookFunctions.push(hook); } /** * Assemble a pair of shaders into a single shader program * @param platformInfo * @param props * @returns */ assembleShader(props) { const modules = this._getModuleList(props.modules); const hookFunctions = this._hookFunctions; const options = selectShaders(props); const assembled = assembleShaderWGSL({ platformInfo: props.platformInfo, ...options, modules, hookFunctions }); return { ...assembled, modules }; } /** * Assemble a pair of shaders into a single shader program * @param platformInfo * @param props * @returns */ assembleShaderPair(props) { const options = selectShaders(props); const modules = this._getModuleList(props.modules); const hookFunctions = this._hookFunctions; const { platformInfo } = props; const isWGSL = props.platformInfo.shaderLanguage === "wgsl"; const assembled = isWGSL ? assembleShaderPairWGSL({ platformInfo, ...options, modules, hookFunctions }) : assembleShaderPairGLSL({ platformInfo, ...options, modules, hookFunctions }); return { ...assembled, modules }; } /** * Dedupe and combine with default modules */ _getModuleList(appModules = []) { const modules = new Array(this._defaultModules.length + appModules.length); const seen = {}; let count = 0; for (let i = 0, len = this._defaultModules.length; i < len; ++i) { const module2 = this._defaultModules[i]; const name = module2.name; modules[count++] = module2; seen[name] = true; } for (let i = 0, len = appModules.length; i < len; ++i) { const module2 = appModules[i]; const name = module2.name; if (!seen[name]) { modules[count++] = module2; seen[name] = true; } } modules.length = count; return ShaderModuleInstance.instantiateModules(modules); } }; var ShaderAssembler = _ShaderAssembler; /** Default ShaderAssembler instance */ __publicField(ShaderAssembler, "defaultShaderAssembler"); // dist/lib/shader-module/normalize-shader-module.js function normalizeShaderModule(module2) { if (!module2.normalized) { module2.normalized = true; if (module2.uniformPropTypes && !module2.getUniforms) { const shaderModule = new ShaderModuleInstance(module2); module2.getUniforms = shaderModule.getUniforms.bind(shaderModule); } } return module2; } // dist/lib/glsl-utils/shader-utils.js var FS_GLES = `out vec4 transform_output; void main() { transform_output = vec4(0); }`; var FS300 = `#version 300 es ${FS_GLES}`; function getQualifierDetails(line, qualifiers) { qualifiers = Array.isArray(qualifiers) ? qualifiers : [qualifiers]; const words = line.replace(/^\s+/, "").split(/\s+/); const [qualifier, type, definition] = words; if (!qualifiers.includes(qualifier) || !type || !definition) { return null; } const name = definition.split(";")[0]; return { qualifier, type, name }; } function getPassthroughFS(options) { const { input, inputChannels, output } = options || {}; if (!input) { return FS300; } if (!inputChannels) { throw new Error("inputChannels"); } const inputType = channelCountToType(inputChannels); const outputValue = convertToVec4(input, inputChannels); return `#version 300 es in ${inputType} ${input}; out vec4 ${output}; void main() { ${output} = ${outputValue}; }`; } function typeToChannelSuffix(type) { switch (type) { case "float": return "x"; case "vec2": return "xy"; case "vec3": return "xyz"; case "vec4": return "xyzw"; default: throw new Error(type); } } function typeToChannelCount(type) { switch (type) { case "float": return 1; case "vec2": return 2; case "vec3": return 3; case "vec4": return 4; default: throw new Error(type); } } function channelCountToType(channels) { switch (channels) { case 1: return "float"; case 2: return "vec2"; case 3: return "vec3"; case 4: return "vec4"; default: throw new Error(`invalid channels: ${channels}`); } } function convertToVec4(variable, channels) { switch (channels) { case 1: return `vec4(${variable}, 0.0, 0.0, 1.0)`; case 2: return `vec4(${variable}, 0.0, 1.0)`; case 3: return `vec4(${variable}, 1.0)`; case 4: return variable; default: throw new Error(`invalid channels: ${channels}`); } } // dist/lib/shader-generator/utils/capitalize.js function capitalize(str) { return typeof str === "string" ? str.charAt(0).toUpperCase() + str.slice(1) : str; } // dist/lib/shader-generator/glsl/generate-glsl.js function generateGLSLForModule(module2, options) { return generateGLSLUniformDeclarations(module2, options); } function generateGLSLUniformDeclarations(module2, options) { const glsl2 = []; switch (options.uniforms) { case "scoped-interface-blocks": case "unscoped-interface-blocks": glsl2.push(`uniform ${capitalize(module2.name)} {`); break; case "uniforms": } for (const [uniformName, uniformFormat] of Object.entries(module2.uniformTypes || {})) { const glslUniformType = getGLSLUniformType(uniformFormat); switch (options.uniforms) { case "scoped-interface-blocks": glsl2.push(` ${glslUniformType} ${uniformName};`); break; case "unscoped-interface-blocks": glsl2.push(` ${glslUniformType} ${module2.name}_${uniformName};`); break; case "uniforms": glsl2.push(`uniform ${glslUniformType} ${module2.name}_${uniformName};`); } } switch (options.uniforms) { case "scoped-interface-blocks": glsl2.push(`} ${module2.name};`); break; case "unscoped-interface-blocks": glsl2.push("};"); break; case "uniforms": } glsl2.push(""); return glsl2.join("\n"); } function getGLSLUniformType(uniformFormat) { const UNIFORM_TYPE_TO_GLSL = { f32: "float", i32: "int", u32: "uint", "vec2": "vec2", "vec3": "vec3", "vec4": "vec4", "vec2": "ivec2", "vec3": "ivec3", "vec4": "ivec4", "vec2": "uvec2", "vec3": "uvec3", "vec4": "uvec4", "mat2x2": "mat2", "mat2x3": "mat2x3", "mat2x4": "mat2x4", "mat3x2": "mat3x2", "mat3x3": "mat3", "mat3x4": "mat3x4", "mat4x2": "mat4x2", "mat4x3": "mat4x3", "mat4x4": "mat4" }; const glsl2 = UNIFORM_TYPE_TO_GLSL[uniformFormat]; return glsl2; } // dist/lib/shader-generator/wgsl/generate-wgsl.js function generateWGSLForModule(module2, options) { return generateWGSLUniformDeclarations(module2, options); } function generateWGSLUniformDeclarations(module2, options) { const wgsl = []; wgsl.push(`struct ${capitalize(module2.name)} {`); for (const [uniformName, uniformFormat] of Object.entries((module2 == null ? void 0 : module2.uniformTypes) || {})) { const wgslUniformType = uniformFormat; wgsl.push(` ${uniformName} : ${wgslUniformType};`); } wgsl.push("};"); wgsl.push(`var ${module2.name} : ${capitalize(module2.name)};`); return wgsl.join("\n"); } // dist/lib/shader-generator/generate-shader.js function generateShaderForModule(module2, options) { switch (options.shaderLanguage) { case "glsl": return generateGLSLForModule(module2, options); case "wgsl": return generateWGSLForModule(module2, options); } } // dist/lib/wgsl/get-shader-layout-wgsl.js var import_core = require("@luma.gl/core"); var import_wgsl_reflect = require("wgsl_reflect"); function getShaderLayoutFromWGSL(source) { var _a; const shaderLayout = { attributes: [], bindings: [] }; let parsedWGSL; try { parsedWGSL = parseWGSL(source); } catch (error) { import_core.log.error(error.message)(); return shaderLayout; } for (const uniform of parsedWGSL.uniforms) { const members = []; for (const attribute of ((_a = uniform.type) == null ? void 0 : _a.members) || []) { members.push({ name: attribute.name, type: getType(attribute.type) }); } shaderLayout.bindings.push({ type: "uniform", name: uniform.name, location: uniform.binding, // @ts-expect-error group: uniform.group, members }); } const vertex = parsedWGSL.entry.vertex[0]; const attributeCount = (vertex == null ? void 0 : vertex.inputs.length) || 0; for (let i = 0; i < attributeCount; i++) { const wgslAttribute = vertex.inputs[i]; if (wgslAttribute.locationType === "location") { const type = getType(wgslAttribute.type); shaderLayout.attributes.push({ name: wgslAttribute.name, location: Number(wgslAttribute.location), type }); } } return shaderLayout; } function getType(type) { return type.format ? `${type.name}<${type.format.name}>` : type.name; } function parseWGSL(source) { try { return new import_wgsl_reflect.WgslReflect(source); } catch (error) { if (error instanceof Error) { throw error; } let message = "WGSL parse error"; if (typeof error === "object" && (error == null ? void 0 : error.message)) { message += `: ${error.message} `; } if (typeof error === "object" && (error == null ? void 0 : error.token)) { message += error.token.line || ""; } throw new Error(message, { cause: error }); } } // dist/modules/math/random/random.js var fs = `float random(vec3 scale, float seed) { return fract(sin(dot(gl_FragCoord.xyz + seed, scale)) * 43758.5453 + seed); } `; var random = { name: "random", fs }; // dist/modules/math/fp32/fp32.js var fp32shader = `#ifdef LUMA_FP32_TAN_PRECISION_WORKAROUND const float TWO_PI = 6.2831854820251465; const float PI_2 = 1.5707963705062866; const float PI_16 = 0.1963495463132858; const float SIN_TABLE_0 = 0.19509032368659973; const float SIN_TABLE_1 = 0.3826834261417389; const float SIN_TABLE_2 = 0.5555702447891235; const float SIN_TABLE_3 = 0.7071067690849304; const float COS_TABLE_0 = 0.9807852506637573; const float COS_TABLE_1 = 0.9238795042037964; const float COS_TABLE_2 = 0.8314695954322815; const float COS_TABLE_3 = 0.7071067690849304; const float INVERSE_FACTORIAL_3 = 1.666666716337204e-01; const float INVERSE_FACTORIAL_5 = 8.333333767950535e-03; const float INVERSE_FACTORIAL_7 = 1.9841270113829523e-04; const float INVERSE_FACTORIAL_9 = 2.75573188446287533e-06; float sin_taylor_fp32(float a) { float r, s, t, x; if (a == 0.0) { return 0.0; } x = -a * a; s = a; r = a; r = r * x; t = r * INVERSE_FACTORIAL_3; s = s + t; r = r * x; t = r * INVERSE_FACTORIAL_5; s = s + t; r = r * x; t = r * INVERSE_FACTORIAL_7; s = s + t; r = r * x; t = r * INVERSE_FACTORIAL_9; s = s + t; return s; } void sincos_taylor_fp32(float a, out float sin_t, out float cos_t) { if (a == 0.0) { sin_t = 0.0; cos_t = 1.0; } sin_t = sin_taylor_fp32(a); cos_t = sqrt(1.0 - sin_t * sin_t); } float tan_taylor_fp32(float a) { float sin_a; float cos_a; if (a == 0.0) { return 0.0; } float z = floor(a / TWO_PI); float r = a - TWO_PI * z; float t; float q = floor(r / PI_2 + 0.5); int j = int(q); if (j < -2 || j > 2) { return 1.0 / 0.0; } t = r - PI_2 * q; q = floor(t / PI_16 + 0.5); int k = int(q); int abs_k = int(abs(float(k))); if (abs_k > 4) { return 1.0 / 0.0; } else { t = t - PI_16 * q; } float u = 0.0; float v = 0.0; float sin_t, cos_t; float s, c; sincos_taylor_fp32(t, sin_t, cos_t); if (k == 0) { s = sin_t; c = cos_t; } else { if (abs(float(abs_k) - 1.0) < 0.5) { u = COS_TABLE_0; v = SIN_TABLE_0; } else if (abs(float(abs_k) - 2.0) < 0.5) { u = COS_TABLE_1; v = SIN_TABLE_1; } else if (abs(float(abs_k) - 3.0) < 0.5) { u = COS_TABLE_2; v = SIN_TABLE_2; } else if (abs(float(abs_k) - 4.0) < 0.5) { u = COS_TABLE_3; v = SIN_TABLE_3; } if (k > 0) { s = u * sin_t + v * cos_t; c = u * cos_t - v * sin_t; } else { s = u * sin_t - v * cos_t; c = u * cos_t + v * sin_t; } } if (j == 0) { sin_a = s; cos_a = c; } else if (j == 1) { sin_a = c; cos_a = -s; } else if (j == -1) { sin_a = -c; cos_a = s; } else { sin_a = -s; cos_a = -c; } return sin_a / cos_a; } #endif float tan_fp32(float a) { #ifdef LUMA_FP32_TAN_PRECISION_WORKAROUND return tan_taylor_fp32(a); #else return tan(a); #endif } `; var fp32 = { name: "fp32", vs: fp32shader }; // dist/modules/engine/picking/picking.js var DEFAULT_HIGHLIGHT_COLOR = [0, 1, 1, 1]; var vs = `uniform pickingUniforms { float isActive; float isAttribute; float isHighlightActive; float useFloatColors; vec3 highlightedObjectColor; vec4 highlightColor; } picking; out vec4 picking_vRGBcolor_Avalid; vec3 picking_normalizeColor(vec3 color) { return picking.useFloatColors > 0.5 ? color : color / 255.0; } vec4 picking_normalizeColor(vec4 color) { return picking.useFloatColors > 0.5 ? color : color / 255.0; } bool picking_isColorZero(vec3 color) { return dot(color, vec3(1.0)) < 0.00001; } bool picking_isColorValid(vec3 color) { return dot(color, vec3(1.0)) > 0.00001; } bool isVertexHighlighted(vec3 vertexColor) { vec3 highlightedObjectColor = picking_normalizeColor(picking.highlightedObjectColor); return bool(picking.isHighlightActive) && picking_isColorZero(abs(vertexColor - highlightedObjectColor)); } void picking_setPickingColor(vec3 pickingColor) { pickingColor = picking_normalizeColor(pickingColor); if (bool(picking.isActive)) { picking_vRGBcolor_Avalid.a = float(picking_isColorValid(pickingColor)); if (!bool(picking.isAttribute)) { picking_vRGBcolor_Avalid.rgb = pickingColor; } } else { picking_vRGBcolor_Avalid.a = float(isVertexHighlighted(pickingColor)); } } void picking_setPickingAttribute(float value) { if (bool(picking.isAttribute)) { picking_vRGBcolor_Avalid.r = value; } } void picking_setPickingAttribute(vec2 value) { if (bool(picking.isAttribute)) { picking_vRGBcolor_Avalid.rg = value; } } void picking_setPickingAttribute(vec3 value) { if (bool(picking.isAttribute)) { picking_vRGBcolor_Avalid.rgb = value; } } `; var fs2 = `uniform pickingUniforms { float isActive; float isAttribute; float isHighlightActive; float useFloatColors; vec3 highlightedObjectColor; vec4 highlightColor; } picking; in vec4 picking_vRGBcolor_Avalid; vec4 picking_filterHighlightColor(vec4 color) { if (picking.isActive > 0.5) { return color; } bool selected = bool(picking_vRGBcolor_Avalid.a); if (selected) { float highLightAlpha = picking.highlightColor.a; float blendedAlpha = highLightAlpha + color.a * (1.0 - highLightAlpha); float highLightRatio = highLightAlpha / blendedAlpha; vec3 blendedRGB = mix(color.rgb, picking.highlightColor.rgb, highLightRatio); return vec4(blendedRGB, blendedAlpha); } else { return color; } } vec4 picking_filterPickingColor(vec4 color) { if (bool(picking.isActive)) { if (picking_vRGBcolor_Avalid.a == 0.0) { discard; } return picking_vRGBcolor_Avalid; } return color; } vec4 picking_filterColor(vec4 color) { vec4 highlightColor = picking_filterHighlightColor(color); return picking_filterPickingColor(highlightColor); } `; var picking = { name: "picking", vs, fs: fs2, uniformTypes: { isActive: "f32", isAttribute: "f32", isHighlightActive: "f32", useFloatColors: "f32", highlightedObjectColor: "vec3", highlightColor: "vec4" }, defaultUniforms: { isActive: false, isAttribute: false, isHighlightActive: false, useFloatColors: true, highlightedObjectColor: [0, 0, 0], highlightColor: DEFAULT_HIGHLIGHT_COLOR }, getUniforms }; function getUniforms(opts = {}, prevUniforms) { const uniforms = {}; if (opts.highlightedObjectColor === void 0) { } else if (opts.highlightedObjectColor === null) { uniforms.isHighlightActive = false; } else { uniforms.isHighlightActive = true; const highlightedObjectColor = opts.highlightedObjectColor.slice(0, 3); uniforms.highlightedObjectColor = highlightedObjectColor; } if (opts.highlightColor) { const color = Array.from(opts.highlightColor, (x) => x / 255); if (!Number.isFinite(color[3])) { color[3] = 1; } uniforms.highlightColor = color; } if (opts.isActive !== void 0) { uniforms.isActive = Boolean(opts.isActive); uniforms.isAttribute = Boolean(opts.isAttribute); } if (opts.useFloatColors !== void 0) { uniforms.useFloatColors = Boolean(opts.useFloatColors); } return uniforms; } // dist/modules/lighting/lights/lighting-uniforms-glsl.js var lightingUniforms = `precision highp int; struct AmbientLight { vec3 color; }; struct PointLight { vec3 color; vec3 position; vec3 attenuation; }; struct DirectionalLight { vec3 color; vec3 direction; }; uniform lightingUniforms { int enabled; int lightType; int directionalLightCount; int pointLightCount; vec3 ambientColor; vec3 lightColor0; vec3 lightPosition0; vec3 lightDirection0; vec3 lightAttenuation0; vec3 lightColor1; vec3 lightPosition1; vec3 lightDirection1; vec3 lightAttenuation1; vec3 lightColor2; vec3 lightPosition2; vec3 lightDirection2; vec3 lightAttenuation2; } lighting; PointLight lighting_getPointLight(int index) { switch (index) { case 0: return PointLight(lighting.lightColor0, lighting.lightPosition0, lighting.lightAttenuation0); case 1: return PointLight(lighting.lightColor1, lighting.lightPosition1, lighting.lightAttenuation1); case 2: default: return PointLight(lighting.lightColor2, lighting.lightPosition2, lighting.lightAttenuation2); } } DirectionalLight lighting_getDirectionalLight(int index) { switch (index) { case 0: return DirectionalLight(lighting.lightColor0, lighting.lightDirection0); case 1: return DirectionalLight(lighting.lightColor1, lighting.lightDirection1); case 2: default: return DirectionalLight(lighting.lightColor2, lighting.lightDirection2); } } float getPointLightAttenuation(PointLight pointLight, float distance) { return pointLight.attenuation.x + pointLight.attenuation.y * distance + pointLight.attenuation.z * distance * distance; } `; // dist/modules/lighting/lights/lighting-uniforms.js var import_core2 = require("@luma.gl/core"); var MAX_LIGHTS = 3; var COLOR_FACTOR = 255; var LIGHT_TYPE; (function(LIGHT_TYPE2) { LIGHT_TYPE2[LIGHT_TYPE2["POINT"] = 0] = "POINT"; LIGHT_TYPE2[LIGHT_TYPE2["DIRECTIONAL"] = 1] = "DIRECTIONAL"; })(LIGHT_TYPE || (LIGHT_TYPE = {})); var lighting = { name: "lighting", vs: lightingUniforms, fs: lightingUniforms, getUniforms(props, prevUniforms) { return getUniforms2(props); }, defines: { MAX_LIGHTS }, uniformTypes: { enabled: "i32", lightType: "i32", directionalLightCount: "i32", pointLightCount: "i32", ambientLightColor: "vec3", // TODO define as arrays once we have appropriate uniformTypes lightColor0: "vec3", lightPosition0: "vec3", // TODO - could combine direction and attenuation lightDirection0: "vec3", lightAttenuation0: "vec3", lightColor1: "vec3", lightPosition1: "vec3", lightDirection1: "vec3", lightAttenuation1: "vec3", lightColor2: "vec3", lightPosition2: "vec3", lightDirection2: "vec3", lightAttenuation2: "vec3" }, defaultUniforms: { enabled: 1, lightType: LIGHT_TYPE.POINT, directionalLightCount: 0, pointLightCount: 0, ambientLightColor: [0.1, 0.1, 0.1], lightColor0: [1, 1, 1], lightPosition0: [1, 1, 2], // TODO - could combine direction and attenuation lightDirection0: [1, 1, 1], lightAttenuation0: [1, 0, 0], lightColor1: [1, 1, 1], lightPosition1: [1, 1, 2], lightDirection1: [1, 1, 1], lightAttenuation1: [1, 0, 0], lightColor2: [1, 1, 1], lightPosition2: [1, 1, 2], lightDirection2: [1, 1, 1], lightAttenuation2: [1, 0, 0] } }; function getUniforms2(props, prevUniforms = {}) { props = props ? { ...props } : props; if (!props) { return { ...lighting.defaultUniforms }; } if (props.lights) { props = { ...props, ...extractLightTypes(props.lights), lights: void 0 }; } const { ambientLight, pointLights, directionalLights } = props || {}; const hasLights = ambientLight || pointLights && pointLights.length > 0 || directionalLights && directionalLights.length > 0; if (!hasLights) { return { ...lighting.defaultUniforms, enabled: 0 }; } const uniforms = { ...lighting.defaultUniforms, ...prevUniforms, ...getLightSourceUniforms({ ambientLight, pointLights, directionalLights }) }; if (props.enabled !== void 0) { uniforms.enabled = props.enabled ? 1 : 0; } return uniforms; } function getLightSourceUniforms({ ambientLight, pointLights = [], directionalLights = [] }) { const lightSourceUniforms = {}; lightSourceUniforms.ambientLightColor = convertColor(ambientLight); let currentLight = 0; for (const pointLight of pointLights) { lightSourceUniforms.lightType = LIGHT_TYPE.POINT; const i = currentLight; lightSourceUniforms[`lightColor${i}`] = convertColor(pointLight); lightSourceUniforms[`lightPosition${i}`] = pointLight.position; lightSourceUniforms[`lightAttenuation${i}`] = pointLight.attenuation || [1, 0, 0]; currentLight++; } for (const directionalLight of directionalLights) { lightSourceUniforms.lightType = LIGHT_TYPE.DIRECTIONAL; const i = currentLight; lightSourceUniforms[`lightColor${i}`] = convertColor(directionalLight); lightSourceUniforms[`lightDirection${i}`] = directionalLight.direction; currentLight++; } if (currentLight > MAX_LIGHTS) { import_core2.log.warn("MAX_LIGHTS exceeded")(); } lightSourceUniforms.directionalLightCount = directionalLights.length; lightSourceUniforms.pointLightCount = pointLights.length; return lightSourceUniforms; } function extractLightTypes(lights2) { var _a, _b; const lightSources = { pointLights: [], directionalLights: [] }; for (const light of lights2 || []) { switch (light.type) { case "ambient": lightSources.ambientLight = light; break; case "directional": (_a = lightSources.directionalLights) == null ? void 0 : _a.push(light); break; case "point": (_b = lightSources.pointLights) == null ? void 0 : _b.push(light); break; default: } } return lightSources; } function convertColor(colorDef = {}) { const { color = [0, 0, 0], intensity = 1 } = colorDef; return color.map((component) => component * intensity / COLOR_FACTOR); } // dist/modules/lighting/no-material/dirlight.js var VS_GLSL = `out vec3 dirlight_vNormal; void dirlight_setNormal(vec3 normal) { dirlight_vNormal = normalize(normal); } `; var FS_GLSL = `uniform dirlightUniforms { vec3 lightDirection; } dirlight; in vec3 dirlight_vNormal; vec4 dirlight_filterColor(vec4 color) { float d = abs(dot(dirlight_vNormal, normalize(dirlight.lightDirection))); return vec4(color.rgb * d, color.a); } `; var dirlight = { name: "dirlight", dependencies: [], vs: VS_GLSL, fs: FS_GLSL, // fragmentInputs: [ // { // name: 'dirlight_vNormal', // type: 'vec3' // } // ], uniformTypes: { lightDirection: "vec3" }, defaultUniforms: { lightDirection: [1, 1, 2] }, getUniforms: getUniforms3 }; function getUniforms3(opts = dirlight.defaultUniforms) { const uniforms = {}; if (opts.lightDirection) { uniforms.dirlight_uLightDirection = opts.lightDirection; } return uniforms; } // dist/modules/lighting/phong-material/phong-shaders-glsl.js var PHONG_VS = `uniform phongMaterialUniforms { uniform float ambient; uniform float diffuse; uniform float shininess; uniform vec3 specularColor; } material; `; var PHONG_FS = `uniform phongMaterialUniforms { uniform float ambient; uniform float diffuse; uniform float shininess; uniform vec3 specularColor; } material; vec3 lighting_getLightColor(vec3 surfaceColor, vec3 light_direction, vec3 view_direction, vec3 normal_worldspace, vec3 color) { vec3 halfway_direction = normalize(light_direction + view_direction); float lambertian = dot(light_direction, normal_worldspace); float specular = 0.0; if (lambertian > 0.0) { float specular_angle = max(dot(normal_worldspace, halfway_direction), 0.0); specular = pow(specular_angle, material.shininess); } lambertian = max(lambertian, 0.0); return (lambertian * material.diffuse * surfaceColor + specular * material.specularColor) * color; } vec3 lighting_getLightColor(vec3 surfaceColor, vec3 cameraPosition, vec3 position_worldspace, vec3 normal_worldspace) { vec3 lightColor = surfaceColor; if (lighting.enabled == 0) { return lightColor; } vec3 view_direction = normalize(cameraPosition - position_worldspace); lightColor = material.ambient * surfaceColor * lighting.ambientColor; for (int i = 0; i < lighting.pointLightCount; i++) { PointLight pointLight = lighting_getPointLight(i); vec3 light_position_worldspace = pointLight.position; vec3 light_direction = normalize(light_position_worldspace - position_worldspace); float light_attenuation = getPointLightAttenuation(pointLight, distance(light_position_worldspace, position_worldspace)); lightColor += lighting_getLightColor(surfaceColor, light_direction, view_direction, normal_worldspace, pointLight.color / light_attenuation); } int totalLights = min(MAX_LIGHTS, lighting.pointLightCount + lighting.directionalLightCount); for (int i = lighting.pointLightCount; i < totalLights; i++) { DirectionalLight directionalLight = lighting_getDirectionalLight(i); lightColor += lighting_getLightColor(surfaceColor, -directionalLight.direction, view_direction, normal_worldspace, directionalLight.color); } return lightColor; } `; // dist/modules/lighting/gouraud-material/gouraud-material.js var gouraudMaterial = { name: "gouraudMaterial", // Note these are switched between phong and gouraud vs: PHONG_FS.replace("phongMaterial", "gouraudMaterial"), fs: PHONG_VS.replace("phongMaterial", "gouraudMaterial"), defines: { LIGHTING_VERTEX: 1 }, dependencies: [lighting], uniformTypes: { ambient: "f32", diffuse: "f32", shininess: "f32", specularColor: "vec3" }, defaultUniforms: { ambient: 0.35, diffuse: 0.6, shininess: 32, specularColor: [0.15, 0.15, 0.15] }, getUniforms(props) { const uniforms = { ...props }; if (uniforms.specularColor) { uniforms.specularColor = uniforms.specularColor.map((x) => x / 255); } return { ...gouraudMaterial.defaultUniforms, ...uniforms }; } }; // dist/modules/lighting/phong-material/phong-material.js var phongMaterial = { name: "phongMaterial", // Note these are switched between phong and gouraud vs: PHONG_VS, fs: PHONG_FS, defines: { LIGHTING_FRAGMENT: 1 }, dependencies: [lighting], uniformTypes: { ambient: "f32", diffuse: "f32", shininess: "f32", specularColor: "vec3" }, defaultUniforms: { ambient: 0.35, diffuse: 0.6, shininess: 32, specularColor: [0.15, 0.15, 0.15] }, getUniforms(props) { const uniforms = { ...props }; if (uniforms.specularColor) { uniforms.specularColor = uniforms.specularColor.map((x) => x / 255); } return { ...phongMaterial.defaultUniforms, ...uniforms }; } }; // dist/modules/lighting/pbr-material/pbr-vertex-glsl.js var vs2 = `uniform projection { mat4 u_MVPMatrix; mat4 u_ModelMatrix; mat4 u_NormalMatrix; vec3 u_Camera; } varying vec3 pbr_vPosition; varying vec2 pbr_vUV; #ifdef HAS_NORMALS # ifdef HAS_TANGENTS varying mat3 pbr_vTBN; # else varying vec3 pbr_vNormal; # endif #endif void pbr_setPositionNormalTangentUV(vec4 position, vec4 normal, vec4 tangent, vec2 uv) { vec4 pos = u_ModelMatrix * position; pbr_vPosition = vec3(pos.xyz) / pos.w; #ifdef HAS_NORMALS #ifdef HAS_TANGENTS vec3 normalW = normalize(vec3(u_NormalMatrix * vec4(normal.xyz, 0.0))); vec3 tangentW = normalize(vec3(u_ModelMatrix * vec4(tangent.xyz, 0.0))); vec3 bitangentW = cross(normalW, tangentW) * tangent.w; pbr_vTBN = mat3(tangentW, bitangentW, normalW); #else pbr_vNormal = normalize(vec3(u_ModelMatrix * vec4(normal.xyz, 0.0))); #endif #endif #ifdef HAS_UV pbr_vUV = uv; #else pbr_vUV = vec2(0.,0.); #endif } `; // dist/modules/lighting/pbr-material/pbr-fragment-glsl.js var fs3 = `precision highp float; uniform Projection { uniform vec3 u_Camera; }; uniform pbrMaterial { bool unlit; bool baseColorMapEnabled; vec4 baseColorFactor; bool normalMapEnabled; float normalScale; bool emissiveMapEnabled; vec3 emissiveFactor; vec2 metallicRoughnessValues; bool metallicRoughnessMapEnabled; bool occlusionMapEnabled; float occlusionStrength; bool alphaCutoffEnabled; float alphaCutoff; bool IBLenabled; vec2 scaleIBLAmbient; vec4 scaleDiffBaseMR; vec4 scaleFGDSpec; } u_pbrMaterial; #ifdef HAS_BASECOLORMAP uniform sampler2D u_BaseColorSampler; #endif #ifdef HAS_NORMALMAP uniform sampler2D u_NormalSampler; #endif #ifdef HAS_EMISSIVEMAP uniform sampler2D u_EmissiveSampler; #endif #ifdef HAS_METALROUGHNESSMAP uniform sampler2D u_MetallicRoughnessSampler; #endif #ifdef HAS_OCCLUSIONMAP uniform sampler2D u_OcclusionSampler; #endif #ifdef USE_IBL uniform samplerCube u_DiffuseEnvSampler; uniform samplerCube u_SpecularEnvSampler; uniform sampler2D u_brdfLUT; #endif varying vec3 pbr_vPosition; varying vec2 pbr_vUV; #ifdef HAS_NORMALS #ifdef HAS_TANGENTS varying mat3 pbr_vTBN; #else varying vec3 pbr_vNormal; #endif #endif struct PBRInfo { float NdotL; float NdotV; float NdotH; float LdotH; float VdotH; float perceptualRoughness; float metalness; vec3 reflectance0; vec3 reflectance90; float alphaRoughness; vec3 diffuseColor; vec3 specularColor; vec3 n; vec3 v; }; const float M_PI = 3.141592653589793; const float c_MinRoughness = 0.04; vec4 SRGBtoLINEAR(vec4 srgbIn) { #ifdef MANUAL_SRGB #ifdef SRGB_FAST_APPROXIMATION vec3 linOut = pow(srgbIn.xyz,vec3(2.2)); #else vec3 bLess = step(vec3(0.04045),srgbIn.xyz); vec3 linOut = mix( srgbIn.xyz/vec3(12.92), pow((srgbIn.xyz+vec3(0.055))/vec3(1.055),vec3(2.4)), bLess ); #endif return vec4(linOut,srgbIn.w);; #else return srgbIn; #endif } vec3 getNormal() { #ifndef HAS_TANGENTS vec3 pos_dx = dFdx(pbr_vPosition); vec3 pos_dy = dFdy(pbr_vPosition); vec3 tex_dx = dFdx(vec3(pbr_vUV, 0.0)); vec3 tex_dy = dFdy(vec3(pbr_vUV, 0.0)); vec3 t = (tex_dy.t * pos_dx - tex_dx.t * pos_dy) / (tex_dx.s * tex_dy.t - tex_dy.s * tex_dx.t); #ifdef HAS_NORMALS vec3 ng = normalize(pbr_vNormal); #else vec3 ng = cross(pos_dx, pos_dy); #endif t = normalize(t - ng * dot(ng, t)); vec3 b = normalize(cross(ng, t)); mat3 tbn = mat3(t, b, ng); #else mat3 tbn = pbr_vTBN; #endif #ifdef HAS_NORMALMAP vec3 n = texture2D(u_NormalSampler, pbr_vUV).rgb; n = normalize(tbn * ((2.0 * n - 1.0) * vec3(u_pbrMaterial.normalScale, u_pbrMaterial.normalScale, 1.0))); #else vec3 n = normalize(tbn[2].xyz); #endif return n; } #ifdef USE_IBL vec3 getIBLContribution(PBRInfo pbrInfo, vec3 n, vec3 reflection) { float mipCount = 9.0; float lod = (pbrInfo.perceptualRoughness * mipCount); vec3 brdf = SRGBtoLINEAR(texture2D(u_brdfLUT, vec2(pbrInfo.NdotV, 1.0 - pbrInfo.perceptualRoughness))).rgb; vec3 diffuseLight = SRGBtoLINEAR(textureCube(u_DiffuseEnvSampler, n)).rgb; #ifdef USE_TEX_LOD vec3 specularLight = SRGBtoLINEAR(textureCubeLod(u_SpecularEnvSampler, reflection, lod)).rgb; #else vec3 specularLight = SRGBtoLINEAR(textureCube(u_SpecularEnvSampler, reflection)).rgb; #endif vec3 diffuse = diffuseLight * pbrInfo.diffuseColor; vec3 specular = specularLight * (pbrInfo.specularColor * brdf.x + brdf.y); diffuse *= u_pbrMaterial.scaleIBLAmbient.x; specular *= u_pbrMaterial.scaleIBLAmbient.y; return diffuse + specular; } #endif vec3 diffuse(PBRInfo pbrInfo) { return pbrInfo.diffuseColor / M_PI; } vec3 specularReflection(PBRInfo pbrInfo) { return pbrInfo.reflectance0 + (pbrInfo.reflectance90 - pbrInfo.reflectance0) * pow(clamp(1.0 - pbrInfo.VdotH, 0.0, 1.0), 5.0); } float geometricOcclusion(PBRInfo pbrInfo) { float NdotL = pbrInfo.NdotL; float NdotV = pbrInfo.NdotV; float r = pbrInfo.alphaRoughness; float attenuationL = 2.0 * NdotL / (NdotL + sqrt(r * r + (1.0 - r * r) * (NdotL * NdotL))); float attenuationV = 2.0 * NdotV / (NdotV + sqrt(r * r + (1.0 - r * r) * (NdotV * NdotV))); return attenuationL * attenuationV; } float microfacetDistribution(PBRInfo pbrInfo) { float roughnessSq = pbrInfo.alphaRoughness * pbrInfo.alphaRoughness; float f = (pbrInfo.NdotH * roughnessSq - pbrInfo.NdotH) * pbrInfo.NdotH + 1.0; return roughnessSq / (M_PI * f * f); } void PBRInfo_setAmbientLight(inout PBRInfo pbrInfo) { pbrInfo.NdotL = 1.0; pbrInfo.NdotH = 0.0; pbrInfo.LdotH = 0.0; pbrInfo.VdotH = 1.0; } void PBRInfo_setDirectionalLight(inout PBRInfo pbrInfo, vec3 lightDirection) { vec3 n = pbrInfo.n; vec3 v = pbrInfo.v; vec3 l = normalize(lightDirection); vec3 h = normalize(l+v); pbrInfo.NdotL = clamp(dot(n, l), 0.001, 1.0); pbrInfo.NdotH = clamp(dot(n, h), 0.0, 1.0); pbrInfo.LdotH = clamp(dot(l, h), 0.0, 1.0); pbrInfo.VdotH = clamp(dot(v, h), 0.0, 1.0); } void PBRInfo_setPointLight(inout PBRInfo pbrInfo, PointLight pointLight) { vec3 light_direction = normalize(pointLight.position - pbr_vPosition); PBRInfo_setDirectionalLight(pbrInfo, light_direction); } vec3 calculateFinalColor(PBRInfo pbrInfo, vec3 lightColor) { vec3 F = specularReflection(pbrInfo); float G = geometricOcclusion(pbrInfo); float D = microfacetDistribution(pbrInfo); vec3 diffuseContrib = (1.0 - F) * diffuse(pbrInfo); vec3 specContrib = F * G * D / (4.0 * pbrInfo.NdotL * pbrInfo.NdotV); return pbrInfo.NdotL * lightColor * (diffuseContrib + specContrib); } vec4 pbr_filterColor(vec4 colorUnused) { #ifdef HAS_BASECOLORMAP vec4 baseColor = SRGBtoLINEAR(texture2D(u_BaseColorSampler, pbr_vUV)) * u_pbrMaterial.baseColorFactor; #else vec4 baseColor = u_pbrMaterial.baseColorFactor; #endif #ifdef ALPHA_CUTOFF if (baseColor.a < u_pbrMaterial.alphaCutoff) { discard; } #endif vec3 color = vec3(0, 0, 0); if(u_pbrMaterial.unlit){ color.rgb = baseColor.rgb; } else{ float perceptualRoughness = u_pbrMaterial.metallicRoughnessValues.y; float metallic = u_pbrMaterial.metallicRoughnessValues.x; #ifdef HAS_METALROUGHNESSMAP vec4 mrSample = texture2D(u_MetallicRoughnessSampler, pbr_vUV); perceptualRoughness = mrSample.g * perceptualRoughness; metallic = mrSample.b * metallic; #endif perceptualRoughness = clamp(perceptualRoughness, c_MinRoughness, 1.0); metallic = clamp(metallic, 0.0, 1.0); float alphaRoughness = perceptualRoughness * perceptualRoughness; vec3 f0 = vec3(0.04); vec3 diffuseColor = baseColor.rgb * (vec3(1.0) - f0); diffuseColor *= 1.0 - metallic; vec3 specularColor = mix(f0, baseColor.rgb, metallic); float reflectance = max(max(specularColor.r, specularColor.g), specularColor.b); float reflectance90 = clamp(reflectance * 25.0, 0.0, 1.0); vec3 specularEnvironmentR0 = specularColor.rgb; vec3 specularEnvironmentR90 = vec3(1.0, 1.0, 1.0) * reflectance90; vec3 n = getNormal(); vec3 v = normalize(u_Camera - pbr_vPosition); float NdotV = clamp(abs(dot(n, v)), 0.001, 1.0); vec3 reflection = -normalize(reflect(v, n)); PBRInfo pbrInfo = PBRInfo( 0.0, NdotV, 0.0, 0.0, 0.0, perceptualRoughness, metallic, specularEnvironmentR0, specularEnvironmentR90, alphaRoughness, diffuseColor, specularColor, n, v ); #ifdef USE_LIGHTS PBRInfo_setAmbientLight(pbrInfo); color += calculateFinalColor(pbrInfo, lighting_uAmbientLight.color); for(int i = 0; i < lighting_uDirectionalLightCount; i++) { if (i < lighting_uDirectionalLightCount) { PBRInfo_setDirectionalLight(pbrInfo, lighting_uDirectionalLight[i].direction); color += calculateFinalColor(pbrInfo, lighting_uDirectionalLight[i].color); } } for(int i = 0; i < lighting_uPointLightCount; i++) { if (i < lighting_uPointLightCount) { PBRInfo_setPointLight(pbrInfo, lighting_uPointLight[i]); float attenuation = getPointLightAttenuation(lighting_uPointLight[i], distance(lighting_uPointLight[i].position, pbr_vPosition)); color += calculateFinalColor(pbrInfo, lighting_uPointLight[i].color / attenuation); } } #endif #ifdef USE_IBL if (u_pbrMateral.IBLEnabled) { color += getIBLContribution(pbrInfo, n, reflection); } #endif #ifdef HAS_OCCLUSIONMAP if (u_pbrMaterial.occlusionMapEnabled) { float ao = texture2D(u_OcclusionSampler, pbr_vUV).r; color = mix(color, color * ao, u_pbrMaterial.occlusionStrength); } #endif #ifdef HAS_EMISSIVEMAP if (u_pbrMaterial.emmissiveMapEnabled) { vec3 emissive = SRGBtoLINEAR(texture2D(u_EmissiveSampler, pbr_vUV)).rgb * u_pbrMaterial.emissiveFactor; color += emissive; } #endif #ifdef PBR_DEBUG color = mix(color, baseColor.rgb, u_pbrMaterial.scaleDiffBaseMR.y); color = mix(color, vec3(metallic), u_pbrMaterial.scaleDiffBaseMR.z); color = mix(color, vec3(perceptualRoughness), u_pbrMaterial.scaleDiffBaseMR.w); #endif } return vec4(pow(color,vec3(1.0/2.2)), baseColor.a); } `; // dist/modules/lighting/pbr-material/pbr-material.js var pbrMaterial = { name: "pbr", vs: vs2, fs: fs3, defines: { LIGHTING_FRAGMENT: 1, HAS_NORMALMAP: 0, HAS_EMISSIVEMAP: 0, HAS_OCCLUSIONMAP: 0, HAS_BASECOLORMAP: 0, HAS_METALROUGHNESSMAP: 0, ALPHA_CUTOFF: 0, USE_IBL: 0, PBR_DEBUG: 0 }, uniformTypes: { // Material is unlit unlit: "i32", // Base color map baseColorMapEnabled: "i32", baseColorFactor: "vec4", normalMapEnabled: "i32", normalScale: "f32", // #ifdef HAS_NORMALMAP emissiveMapEnabled: "i32", emissiveFactor: "vec3", // #ifdef HAS_EMISSIVEMAP metallicRoughnessValues: "vec2", metallicRoughnessMapEnabled: "i32", occlusionMapEnabled: "i32", occlusionStrength: "f32", // #ifdef HAS_OCCLUSIONMAP alphaCutoffEnabled: "i32", alphaCutoff: "f32", // #ifdef ALPHA_CUTOFF // IBL IBLenabled: "i32", scaleIBLAmbient: "vec2", // #ifdef USE_IBL // debugging flags used for shader output of intermediate PBR variables // #ifdef PBR_DEBUG scaleDiffBaseMR: "vec4", scaleFGDSpec: "vec4" }, dependencies: [lighting] }; // dist/modules/postprocessing/image-adjust-filters/brightnesscontrast.js var fs4 = `uniform brightnessContrastUniforms { float brightness; float contrast; } brightnessContrast; vec4 brightnessContrast_filterColor(vec4 color) { color.rgb += brightnessContrast.brightness; if (brightnessContrast.contrast > 0.0) { color.rgb = (color.rgb - 0.5) / (1.0 - brightnessContrast.contrast) + 0.5; } else { color.rgb = (color.rgb - 0.5) * (1.0 + brightnessContrast.contrast) + 0.5; } return color; } vec4 brightnessContrast_filterColor(vec4 color, vec2 texSize, vec2 texCoords) { return brightnessContrast_filterColor(color); } `; var brightnessContrast = { name: "brightnessContrast", uniformTypes: { brightness: "f32", contrast: "f32" }, uniformPropTypes: { brightness: { format: "f32", value: 0, min: -1, max: 1 }, contrast: { format: "f32", value: 0, min: -1, max: 1 } }, fs: fs4, passes: [{ filter: true }] }; // dist/modules/postprocessing/image-adjust-filters/denoise.js var fs5 = `uniform denoiseUniforms { float strength; } noise; vec4 denoise_sampleColor(sampler2D source, vec2 texSize, vec2 texCoord) { float adjustedExponent = 3. + 200. * pow(1. - noise.strength, 4.); vec4 center = texture(source, texCoord); vec4 color = vec4(0.0); float total = 0.0; for (float x = -4.0; x <= 4.0; x += 1.0) { for (float y = -4.0; y <= 4.0; y += 1.0) { vec4 offsetColor = texture(source, texCoord + vec2(x, y) / texSize); float weight = 1.0 - abs(dot(offsetColor.rgb - center.rgb, vec3(0.25))); weight = pow(weight, adjustedExponent); color += offsetColor * weight; total += weight; } } return color / total; } `; var denoise = { name: "denoise", uniformTypes: { strength: "f32" }, uniformPropTypes: { strength: { format: "f32", value: 0.5, min: 0, max: 1 } // strength: {..., adjust: (strength: number): number => 0.53 + 200 * Math.pow(1 - strength, 4) // TODO - JS preprocessing }, fs: fs5, passes: [{ sampler: true }, { sampler: true }] }; // dist/modules/postprocessing/image-adjust-filters/huesaturation.js var fs6 = `uniform hueSaturationUniforms { float hue; float saturation; } hueSaturation; vec4 hueSaturation_filterColor(vec4 color) { float angle = hueSaturation.hue * 3.14159265; float s = sin(angle), c = cos(angle); vec3 weights = (vec3(2.0 * c, -sqrt(3.0) * s - c, sqrt(3.0) * s - c) + 1.0) / 3.0; float len = length(color.rgb); color.rgb = vec3( dot(color.rgb, weights.xyz), dot(color.rgb, weights.zxy), dot(color.rgb, weights.yzx) ); float average = (color.r + color.g + color.b) / 3.0; if (hueSaturation.saturation > 0.0) { color.rgb += (average - color.rgb) * (1.0 - 1.0 / (1.001 - hueSaturation.saturation)); } else { color.rgb += (average - color.rgb) * (-hueSaturation.saturation); } return color; } vec4 hueSaturation_filterColor(vec4 color, vec2 texSize, vec2 texCoord) { return hueSaturation_filterColor(color); } `; var hueSaturation = { name: "hueSaturation", uniformTypes: { hue: "f32", saturation: "f32" }, uniformPropTypes: { hue: { value: 0, min: -1, max: 1 }, saturation: { value: 0, min: -1, max: 1 } }, fs: fs6, passes: [{ filter: true }] }; // dist/modules/postprocessing/image-adjust-filters/noise.js var fs7 = `uniform noiseUniforms { float amount; } noise; float rand(vec2 co) { return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453); } vec4 noise_filterColor(vec4 color, vec2 texCoord) { float diff = (rand(texCoord) - 0.5) * noise.amount; color.r += diff; color.g += diff; color.b += diff; return color; } vec4 noise_filterColor(vec4 color, vec2 texSize, vec2 texCoord) { return noise_filterColor(color, texCoord); } `; var noise = { name: "noise", uniformTypes: { amount: "f32" }, uniformPropTypes: { amount: { value: 0.5, min: 0, max: 1 } }, fs: fs7, passes: [{ filter: true }] }; // dist/modules/postprocessing/image-adjust-filters/sepia.js var fs8 = `uniform sepiaUniforms { float amount; } sepia; vec4 sepia_filterColor(vec4 color) { float r = color.r; float g = color.g; float b = color.b; color.r = min(1.0, (r * (1.0 - (0.607 * sepia.amount))) + (g * (0.769 * sepia.amount)) + (b * (0.189 * sepia.amount))); color.g = min(1.0, (r * 0.349 * sepia.amount) + (g * (1.0 - (0.314 * sepia.amount))) + (b * 0.168 * sepia.amount)); color.b = min(1.0, (r * 0.272 * sepia.amount) + (g * 0.534 * sepia.amount) + (b * (1.0 - (0.869 * sepia.amount)))); return color; } vec4 sepia_filterColor(vec4 color, vec2 texSize, vec2 texCoord) { return sepia_filterColor(color); } `; var sepia = { name: "sepia", uniformTypes: { amount: "f32" }, uniformPropTypes: { amount: { value: 0.5, min: 0, max: 1 } }, fs: fs8, passes: [{ filter: true }] }; // dist/modules/postprocessing/image-adjust-filters/vibrance.js var fs9 = `uniform vibranceUniforms { float amount; } vibrance; vec4 vibrance_filterColor(vec4 color) { float average = (color.r + color.g + color.b) / 3.0; float mx = max(color.r, max(color.g, color.b)); float amt = (mx - average) * (-vibrance.amount * 3.0); color.rgb = mix(color.rgb, vec3(mx), amt); return color; } vec4 vibrance_filterColor(vec4 color, vec2 texSize, vec2 texCoord) { return vibrance_filterColor(color); } `; var vibrance = { name: "vibrance", uniformPropTypes: { amount: { value: 0, min: -1, max: 1 } }, fs: fs9, passes: [{ filter: true }] }; // dist/modules/postprocessing/image-adjust-filters/vignette.js var fs10 = `uniform vignetteUniforms { float radius; float amount; } vignette; vec4 vignette_filterColor(vec4 color, vec2 texCoord) { float dist = distance(texCoord, vec2(0.5, 0.5)); float ratio = smoothstep(0.8, vignette.radius * 0.799, dist * (vignette.amount + vignette.radius)); return color.rgba * ratio + (1.0 - ratio)*vec4(0.0, 0.0, 0.0, 1.0); } vec4 vignette_filterColor(vec4 color, vec2 texSize, vec2 texCoord) { return vignette_filterColor(color, texCoord); } `; var vignette = { name: "vignette", fs: fs10, uniformTypes: { radius: "f32", amount: "f32" }, uniformPropTypes: { radius: { value: 0.5, min: 0, max: 1 }, amount: { value: 0.5, min: 0, max: 1 } }, passes: [{ filter: true }] }; // dist/modules/postprocessing/image-blur-filters/tiltshift.js var fs11 = `uniform tiltShiftUniforms { float blurRadius; float gradientRadius; vec2 start; vec2 end; bool invert; } tiltShift; vec2 tiltShift_getDelta(vec2 texSize) { vec2 vector = normalize((tiltShift.end - tiltShift.start) * texSize); return tiltShift.invert ? vec2(-vector.y, vector.x) : vector; } vec4 tiltShift_sampleColor(sampler2D source, vec2 texSize, vec2 texCoord) { vec4 color = vec4(0.0); float total = 0.0; float offset = random(vec3(12.9898, 78.233, 151.7182), 0.0); vec2 normal = normalize(vec2((tiltShift.start.y - tiltShift.end.y) * texSize.y, (tiltShift.end.x - tiltShift.start.x) * texSize.x)); float radius = smoothstep(0.0, 1.0, abs(dot(texCoord * texSize - tiltShift.start * texSize, normal)) / tiltShift.gradientRadius) * tiltShift.blurRadius; for (float t = -30.0; t <= 30.0; t++) { float percent = (t + offset - 0.5) / 30.0; float weight = 1.0 - abs(percent); vec4 offsetColor = texture(source, texCoord + tiltShift_getDelta(texSize) / texSize * percent * radius); offsetColor.rgb *= offsetColor.a; color += offsetColor * weight; total += weight; } color = color / total; color.rgb /= color.a + 0.00001; return color; } `; var tiltShift = { name: "tiltShift", uniformTypes: { blurRadius: "f32", gradientRadius: "f32", start: "vec2", end: "vec2", invert: "i32" }, uniformPropTypes: { blurRadius: { value: 15, min: 0, max: 50 }, gradientRadius: { value: 200, min: 0, max: 400 }, start: { value: [0, 0] }, end: { value: [1, 1] }, invert: { value: false, private: true } }, passes: [ { sampler: true, uniforms: { invert: false } }, { sampler: true, uniforms: { invert: true } } ], dependencies: [random], fs: fs11 }; // dist/modules/postprocessing/image-blur-filters/triangleblur.js var fs12 = `uniform triangleBlurUniforms { float radius; vec2 delta; } triangleBlur; vec4 triangleBlur_sampleColor(sampler2D source, vec2 texSize, vec2 texCoord) { vec2 adjustedDelta = triangleBlur.delta * triangleBlur.radius / texSize; vec4 color = vec4(0.0); float total = 0.0; float offset = random(vec3(12.9898, 78.233, 151.7182), 0.0); for (float t = -30.0; t <= 30.0; t++) { float percent = (t + offset - 0.5) / 30.0; float weight = 1.0 - abs(percent); vec4 offsetColor = texture(source, texCoord + adjustedDelta * percent); offsetColor.rgb *= offsetColor.a; color += offsetColor * weight; total += weight; } color = color / total; color.rgb /= color.a + 0.00001; return color; } `; var triangleBlur = { name: "triangleBlur", uniformTypes: { radius: "f32", delta: "vec2" }, uniformPropTypes: { radius: { value: 20, min: 0, softMax: 100 }, delta: { value: [1, 0], private: true } }, fs: fs12, dependencies: [random], passes: [ { sampler: true, uniforms: { delta: [1, 0] } }, { sampler: true, uniforms: { delta: [0, 1] } } ] }; // dist/modules/postprocessing/image-blur-filters/zoomblur.js var fs13 = ` uniform zoomBlurUniforms { vec2 center; float strength; } zoomBlur; vec4 zoomBlur_sampleColor(sampler2D source, vec2 texSize, vec2 texCoord) { vec4 color = vec4(0.0); float total = 0.0; vec2 toCenter = zoomBlur.center * texSize - texCoord * texSize; /* randomize the lookup values to hide the fixed number of samples */ float offset = random(vec3(12.9898, 78.233, 151.7182), 0.0); for (float t = 0.0; t <= 40.0; t++) { float percent = (t + offset) / 40.0; float weight = 4.0 * (percent - percent * percent); vec4 offsetColor = texture(source, texCoord + toCenter * percent * zoomBlur.strength / texSize); /* switch to pre-multiplied alpha to correctly blur transparent images */ offsetColor.rgb *= offsetColor.a; color += offsetColor * weight; total += weight; } color = color / total; /* switch back from pre-multiplied alpha */ color.rgb /= color.a + 0.00001; return color; } `; var zoomBlur = { name: "zoomBlur", uniformTypes: { center: "vec2", strength: "f32" }, uniformPropTypes: { center: { value: [0.5, 0.5] }, strength: { value: 0.3, min: 0, softMax: 1 } }, fs: fs13, dependencies: [random], passes: [{ sampler: true }] }; // dist/modules/postprocessing/image-fun-filters/colorhalftone.js var fs14 = `uniform colorHalftoneUniforms { vec2 center; float angle; float size; } colorHalftone; float pattern(float angle, float scale, vec2 texSize, vec2 texCoord) { float s = sin(angle), c = cos(angle); vec2 tex = texCoord * texSize - colorHalftone.center * texSize; vec2 point = vec2( c * tex.x - s * tex.y, s * tex.x + c * tex.y ) * scale; return (sin(point.x) * sin(point.y)) * 4.0; } vec4 colorHalftone_filterColor(vec4 color, vec2 texSize, vec2 texCoord) { float scale = 3.1514 / colorHalftone.size; vec3 cmy = 1.0 - color.rgb; float k = min(cmy.x, min(cmy.y, cmy.z)); cmy = (cmy - k) / (1.0 - k); cmy = clamp( cmy * 10.0 - 3.0 + vec3( pattern(colorHalftone.angle + 0.26179, scale, texSize, texCoord), pattern(colorHalftone.angle + 1.30899, scale, texSize, texCoord), pattern(colorHalftone.angle, scale, texSize, texCoord) ), 0.0, 1.0 ); k = clamp(k * 10.0 - 5.0 + pattern(colorHalftone.angle + 0.78539, scale, texSize, texCoord), 0.0, 1.0); return vec4(1.0 - cmy - k, color.a); } `; var colorHalftone = { name: "colorHalftone", uniformTypes: { center: "vec2", angle: "f32", size: "f32" }, uniformPropTypes: { center: { value: [0.5, 0.5] }, angle: { value: 1.1, softMin: 0, softMax: Math.PI / 2 }, size: { value: 4, min: 1, softMin: 3, softMax: 20 } }, fs: fs14, passes: [{ filter: true }] }; // dist/modules/postprocessing/image-fun-filters/dotscreen.js var fs15 = `uniform dotScreenUniforms { vec2 center; float angle; float size; } dotScreen; float pattern(vec2 texSize, vec2 texCoord) { float scale = 3.1415 / dotScreen.size; float s = sin(dotScreen.angle), c = cos(dotScreen.angle); vec2 tex = texCoord * texSize - dotScreen.center * texSize; vec2 point = vec2( c * tex.x - s * tex.y, s * tex.x + c * tex.y ) * scale; return (sin(point.x) * sin(point.y)) * 4.0; } vec4 dotScreen_filterColor(vec4 color, vec2 texSize, vec2 texCoord) { float average = (color.r + color.g + color.b) / 3.0; return vec4(vec3(average * 10.0 - 5.0 + pattern(texSize, texCoord)), color.a); } `; var dotScreen = { name: "dotScreen", uniformTypes: { center: "vec2", angle: "f32", size: "f32" }, uniformPropTypes: { center: { value: [0.5, 0.5] }, angle: { value: 1.1, softMin: 0, softMax: Math.PI / 2 }, size: { value: 3, min: 1, softMin: 3, softMax: 20 } }, fs: fs15, passes: [{ filter: true }] }; // dist/modules/postprocessing/image-fun-filters/edgework.js var fs16 = `uniform edgeWorkUniforms { float radius; vec2 delta; } edgeWork; vec4 edgeWork_sampleColor1(sampler2D source, vec2 texSize, vec2 texCoord) { vec2 relativeDelta = edgeWork.radius * edgeWork.delta / texSize; vec2 color = vec2(0.0); vec2 total = vec2(0.0); float offset = random(vec3(12.9898, 78.233, 151.7182), 0.0); for (float t = -30.0; t <= 30.0; t++) { float percent = (t + offset - 0.5) / 30.0; float weight = 1.0 - abs(percent); vec3 sampleColor = texture(source, texCoord + relativeDelta * percent).rgb; float average = (sampleColor.r + sampleColor.g + sampleColor.b) / 3.0; color.x += average * weight; total.x += weight; if (abs(t) < 15.0) { weight = weight * 2.0 - 1.0; color.y += average * weight; total.y += weight; } } return vec4(color / total, 0.0, 1.0); } vec4 edgeWork_sampleColor2(sampler2D source, vec2 texSize, vec2 texCoord) { vec2 relativeDelta = edgeWork.radius * edgeWork.delta / texSize; vec2 color = vec2(0.0); vec2 total = vec2(0.0); float offset = random(vec3(12.9898, 78.233, 151.7182), 0.0); for (float t = -30.0; t <= 30.0; t++) { float percent = (t + offset - 0.5) / 30.0; float weight = 1.0 - abs(percent); vec2 sampleColor = texture(source, texCoord + relativeDelta * percent).xy; color.x += sampleColor.x * weight; total.x += weight; if (abs(t) < 15.0) { weight = weight * 2.0 - 1.0; color.y += sampleColor.y * weight; total.y += weight; } } float c = clamp(10000.0 * (color.y / total.y - color.x / total.x) + 0.5, 0.0, 1.0); return vec4(c, c, c, 1.0); } `; var edgeWork = { name: "edgeWork", uniformPropTypes: { radius: { value: 2, min: 1, softMax: 50 }, delta: { value: [1, 0], private: true } }, fs: fs16, dependencies: [random], passes: [ { // @ts-expect-error sampler: "edgeWork_sampleColor1", uniformPropTypes: { delta: [1, 0] } }, { // @ts-expect-error sampler: "edgeWork_sampleColor2", uniformPropTypes: { delta: [0, 1] } } ] }; // dist/modules/postprocessing/image-fun-filters/hexagonalpixelate.js var fs17 = `uniform hexagonalPixelateUniforms { vec2 center; float scale; } hexagonalPixelate; vec4 hexagonalPixelate_sampleColor(sampler2D source, vec2 texSize, vec2 texCoord) { vec2 tex = (texCoord * texSize - hexagonalPixelate.center * texSize) / hexagonalPixelate.scale; tex.y /= 0.866025404; tex.x -= tex.y * 0.5; vec2 a; if (tex.x + tex.y - floor(tex.x) - floor(tex.y) < 1.0) { a = vec2(floor(tex.x), floor(tex.y)); } else a = vec2(ceil(tex.x), ceil(tex.y)); vec2 b = vec2(ceil(tex.x), floor(tex.y)); vec2 c = vec2(floor(tex.x), ceil(tex.y)); vec3 TEX = vec3(tex.x, tex.y, 1.0 - tex.x - tex.y); vec3 A = vec3(a.x, a.y, 1.0 - a.x - a.y); vec3 B = vec3(b.x, b.y, 1.0 - b.x - b.y); vec3 C = vec3(c.x, c.y, 1.0 - c.x - c.y); float alen = length(TEX - A); float blen = length(TEX - B); float clen = length(TEX - C); vec2 choice; if (alen < blen) { if (alen < clen) choice = a; else choice = c; } else { if (blen < clen) choice = b; else choice = c; } choice.x += choice.y * 0.5; choice.y *= 0.866025404; choice *= hexagonalPixelate.scale / texSize; return texture(source, choice + hexagonalPixelate.center); } `; var hexagonalPixelate = { name: "hexagonalPixelate", uniformTypes: { center: "vec2", scale: "f32" }, uniformPropTypes: { center: { value: [0.5, 0.5], hint: "screenspace" }, scale: { value: 10, min: 1, softMin: 5, softMax: 50 } }, fs: fs17, passes: [{ sampler: true }] }; // dist/modules/postprocessing/image-fun-filters/ink.js var fs18 = `uniform inkUniforms { float strength; } ink; vec4 ink_sampleColor(sampler2D source, vec2 texSize, vec2 texCoord) { vec2 dx = vec2(1.0 / texSize.x, 0.0); vec2 dy = vec2(0.0, 1.0 / texSize.y); vec4 color = texture(source, texCoord); float bigTotal = 0.0; float smallTotal = 0.0; vec3 bigAverage = vec3(0.0); vec3 smallAverage = vec3(0.0); for (float x = -2.0; x <= 2.0; x += 1.0) { for (float y = -2.0; y <= 2.0; y += 1.0) { vec3 offsetColor = texture(source, texCoord + dx * x + dy * y).rgb; bigAverage += offsetColor; bigTotal += 1.0; if (abs(x) + abs(y) < 2.0) { smallAverage += offsetColor; smallTotal += 1.0; } } } vec3 edge = max(vec3(0.0), bigAverage / bigTotal - smallAverage / smallTotal); float power = ink.strength * ink.strength * ink.strength * ink.strength * ink.strength; return vec4(color.rgb - dot(edge, edge) * power * 100000.0, color.a); } `; var ink = { name: "ink", uniformTypes: { strength: "f32" }, uniformPropTypes: { strength: { value: 0.25, min: 0, softMax: 1 } }, fs: fs18, passes: [{ sampler: true }] }; // dist/modules/postprocessing/image-fun-filters/magnify.js var fs19 = `uniform magnifyUniforms { vec2 screenXY; float radiusPixels; float zoom; float borderWidthPixels; vec4 borderColor; } magnify; vec4 magnify_sampleColor(sampler2D source, vec2 texSize, vec2 texCoord) { vec2 pos = vec2(magnify.screenXY.x, 1.0 - magnify.screenXY.y); float dist = distance(texCoord * texSize, pos * texSize); if (dist < magnify.radiusPixels) { return texture(source, (texCoord - pos) / magnify.zoom + pos); } if (dist <= magnify.radiusPixels + magnify.borderWidthPixels) { return magnify.borderColor; } return texture(source, texCoord); } `; var magnify = { name: "magnify", uniformTypes: { screenXY: "vec2", radiusPixels: "f32", zoom: "f32", borderWidthPixels: "f32", borderColor: "vec4" }, uniformPropTypes: { // range 0 to 1 screenXY: { value: [0, 0] }, radiusPixels: 200, zoom: 2, borderWidthPixels: 0, borderColor: { value: [255, 255, 255, 255] } }, fs: fs19, passes: [{ sampler: true }] }; // dist/modules/postprocessing/image-warp-filters/warp.js var fs20 = `vec4 warp_sampleColor(sampler2D source, vec2 texSize, vec2 coord) { vec4 color = texture(source, coord / texSize); vec2 clampedCoord = clamp(coord, vec2(0.0), texSize); if (coord != clampedCoord) { color.a *= max(0.0, 1.0 - length(coord - clampedCoord)); } return color; } `; var warp = { name: "warp", passes: [], fs: fs20 }; // dist/modules/postprocessing/image-warp-filters/bulgepinch.js var fs21 = `uniform bulgePinchUniforms { float radius; float strength; vec2 center; } bulgePinch; vec2 bulgePinch_warp(vec2 coord, vec2 texCenter) { coord -= texCenter; float distance = length(coord); if (distance < bulgePinch.radius) { float percent = distance / bulgePinch.radius; if (bulgePinch.strength > 0.0) { coord *= mix(1.0, smoothstep(0.0, bulgePinch.radius / distance, percent), bulgePinch.strength * 0.75); } else { coord *= mix(1.0, pow(percent, 1.0 + bulgePinch.strength * 0.75) * bulgePinch.radius / distance, 1.0 - percent); } } coord += texCenter; return coord; } vec4 bulgePinch_sampleColor(sampler2D source, vec2 texSize, vec2 texCoord) { vec2 coord = texCoord * texSize; coord = bulgePinch_warp(coord, bulgePinch.center * texSize); return warp_sampleColor(source, texSize, coord); } `; var bulgePinch = { name: "bulgePinch", fs: fs21, uniformTypes: { center: "vec2", radius: "f32", strength: "f32" }, uniformPropTypes: { center: { value: [0.5, 0.5] }, radius: { value: 200, min: 1, softMax: 600 }, strength: { value: 0.5, min: -1, max: 1 } }, dependencies: [warp], passes: [{ sampler: true }] }; // dist/modules/postprocessing/image-warp-filters/swirl.js var fs22 = `uniform swirlUniforms { float radius; float angle; vec2 center; } swirl; vec2 swirl_warp(vec2 coord, vec2 texCenter) { coord -= texCenter; float distance = length(coord); if (distance < swirl.radius) { float percent = (swirl.radius - distance) / swirl.radius; float theta = percent * percent * swirl.angle; float s = sin(theta); float c = cos(theta); coord = vec2( coord.x * c - coord.y * s, coord.x * s + coord.y * c ); } coord += texCenter; return coord; } vec4 swirl_sampleColor(sampler2D source, vec2 texSize, vec2 texCoord) { vec2 coord = texCoord * texSize; coord = swirl_warp(coord, swirl.center * texSize); return warp_sampleColor(source, texSize, coord); } `; var swirl = { name: "swirl", fs: fs22, uniformTypes: { center: "vec2", radius: "f32", angle: "f32" }, uniformPropTypes: { center: { value: [0.5, 0.5] }, radius: { value: 200, min: 1, softMax: 600 }, angle: { value: 3, softMin: -25, softMax: 25 } }, dependencies: [warp], passes: [{ sampler: true }] }; // dist/modules/postprocessing/fxaa/fxaa.js var fs23 = ` #define FXAA_QUALITY_PRESET 29 #if (FXAA_QUALITY_PRESET == 10) #define FXAA_QUALITY_PS 3 #define FXAA_QUALITY_P0 1.5 #define FXAA_QUALITY_P1 3.0 #define FXAA_QUALITY_P2 12.0 #endif #if (FXAA_QUALITY_PRESET == 11) #define FXAA_QUALITY_PS 4 #define FXAA_QUALITY_P0 1.0 #define FXAA_QUALITY_P1 1.5 #define FXAA_QUALITY_P2 3.0 #define FXAA_QUALITY_P3 12.0 #endif #if (FXAA_QUALITY_PRESET == 12) #define FXAA_QUALITY_PS 5 #define FXAA_QUALITY_P0 1.0 #define FXAA_QUALITY_P1 1.5 #define FXAA_QUALITY_P2 2.0 #define FXAA_QUALITY_P3 4.0 #define FXAA_QUALITY_P4 12.0 #endif #if (FXAA_QUALITY_PRESET == 13) #define FXAA_QUALITY_PS 6 #define FXAA_QUALITY_P0 1.0 #define FXAA_QUALITY_P1 1.5 #define FXAA_QUALITY_P2 2.0 #define FXAA_QUALITY_P3 2.0 #define FXAA_QUALITY_P4 4.0 #define FXAA_QUALITY_P5 12.0 #endif #if (FXAA_QUALITY_PRESET == 14) #define FXAA_QUALITY_PS 7 #define FXAA_QUALITY_P0 1.0 #define FXAA_QUALITY_P1 1.5 #define FXAA_QUALITY_P2 2.0 #define FXAA_QUALITY_P3 2.0 #define FXAA_QUALITY_P4 2.0 #define FXAA_QUALITY_P5 4.0 #define FXAA_QUALITY_P6 12.0 #endif #if (FXAA_QUALITY_PRESET == 15) #define FXAA_QUALITY_PS 8 #define FXAA_QUALITY_P0 1.0 #define FXAA_QUALITY_P1 1.5 #define FXAA_QUALITY_P2 2.0 #define FXAA_QUALITY_P3 2.0 #define FXAA_QUALITY_P4 2.0 #define FXAA_QUALITY_P5 2.0 #define FXAA_QUALITY_P6 4.0 #define FXAA_QUALITY_P7 12.0 #endif #if (FXAA_QUALITY_PRESET == 20) #define FXAA_QUALITY_PS 3 #define FXAA_QUALITY_P0 1.5 #define FXAA_QUALITY_P1 2.0 #define FXAA_QUALITY_P2 8.0 #endif #if (FXAA_QUALITY_PRESET == 21) #define FXAA_QUALITY_PS 4 #define FXAA_QUALITY_P0 1.0 #define FXAA_QUALITY_P1 1.5 #define FXAA_QUALITY_P2 2.0 #define FXAA_QUALITY_P3 8.0 #endif #if (FXAA_QUALITY_PRESET == 22) #define FXAA_QUALITY_PS 5 #define FXAA_QUALITY_P0 1.0 #define FXAA_QUALITY_P1 1.5 #define FXAA_QUALITY_P2 2.0 #define FXAA_QUALITY_P3 2.0 #define FXAA_QUALITY_P4 8.0 #endif #if (FXAA_QUALITY_PRESET == 23) #define FXAA_QUALITY_PS 6 #define FXAA_QUALITY_P0 1.0 #define FXAA_QUALITY_P1 1.5 #define FXAA_QUALITY_P2 2.0 #define FXAA_QUALITY_P3 2.0 #define FXAA_QUALITY_P4 2.0 #define FXAA_QUALITY_P5 8.0 #endif #if (FXAA_QUALITY_PRESET == 24) #define FXAA_QUALITY_PS 7 #define FXAA_QUALITY_P0 1.0 #define FXAA_QUALITY_P1 1.5 #define FXAA_QUALITY_P2 2.0 #define FXAA_QUALITY_P3 2.0 #define FXAA_QUALITY_P4 2.0 #define FXAA_QUALITY_P5 3.0 #define FXAA_QUALITY_P6 8.0 #endif #if (FXAA_QUALITY_PRESET == 25) #define FXAA_QUALITY_PS 8 #define FXAA_QUALITY_P0 1.0 #define FXAA_QUALITY_P1 1.5 #define FXAA_QUALITY_P2 2.0 #define FXAA_QUALITY_P3 2.0 #define FXAA_QUALITY_P4 2.0 #define FXAA_QUALITY_P5 2.0 #define FXAA_QUALITY_P6 4.0 #define FXAA_QUALITY_P7 8.0 #endif #if (FXAA_QUALITY_PRESET == 26) #define FXAA_QUALITY_PS 9 #define FXAA_QUALITY_P0 1.0 #define FXAA_QUALITY_P1 1.5 #define FXAA_QUALITY_P2 2.0 #define FXAA_QUALITY_P3 2.0 #define FXAA_QUALITY_P4 2.0 #define FXAA_QUALITY_P5 2.0 #define FXAA_QUALITY_P6 2.0 #define FXAA_QUALITY_P7 4.0 #define FXAA_QUALITY_P8 8.0 #endif #if (FXAA_QUALITY_PRESET == 27) #define FXAA_QUALITY_PS 10 #define FXAA_QUALITY_P0 1.0 #define FXAA_QUALITY_P1 1.5 #define FXAA_QUALITY_P2 2.0 #define FXAA_QUALITY_P3 2.0 #define FXAA_QUALITY_P4 2.0 #define FXAA_QUALITY_P5 2.0 #define FXAA_QUALITY_P6 2.0 #define FXAA_QUALITY_P7 2.0 #define FXAA_QUALITY_P8 4.0 #define FXAA_QUALITY_P9 8.0 #endif #if (FXAA_QUALITY_PRESET == 28) #define FXAA_QUALITY_PS 11 #define FXAA_QUALITY_P0 1.0 #define FXAA_QUALITY_P1 1.5 #define FXAA_QUALITY_P2 2.0 #define FXAA_QUALITY_P3 2.0 #define FXAA_QUALITY_P4 2.0 #define FXAA_QUALITY_P5 2.0 #define FXAA_QUALITY_P6 2.0 #define FXAA_QUALITY_P7 2.0 #define FXAA_QUALITY_P8 2.0 #define FXAA_QUALITY_P9 4.0 #define FXAA_QUALITY_P10 8.0 #endif #if (FXAA_QUALITY_PRESET == 29) #define FXAA_QUALITY_PS 12 #define FXAA_QUALITY_P0 1.0 #define FXAA_QUALITY_P1 1.5 #define FXAA_QUALITY_P2 2.0 #define FXAA_QUALITY_P3 2.0 #define FXAA_QUALITY_P4 2.0 #define FXAA_QUALITY_P5 2.0 #define FXAA_QUALITY_P6 2.0 #define FXAA_QUALITY_P7 2.0 #define FXAA_QUALITY_P8 2.0 #define FXAA_QUALITY_P9 2.0 #define FXAA_QUALITY_P10 4.0 #define FXAA_QUALITY_P11 8.0 #endif #if (FXAA_QUALITY_PRESET == 39) #define FXAA_QUALITY_PS 12 #define FXAA_QUALITY_P0 1.0 #define FXAA_QUALITY_P1 1.0 #define FXAA_QUALITY_P2 1.0 #define FXAA_QUALITY_P3 1.0 #define FXAA_QUALITY_P4 1.0 #define FXAA_QUALITY_P5 1.5 #define FXAA_QUALITY_P6 2.0 #define FXAA_QUALITY_P7 2.0 #define FXAA_QUALITY_P8 2.0 #define FXAA_QUALITY_P9 2.0 #define FXAA_QUALITY_P10 4.0 #define FXAA_QUALITY_P11 8.0 #endif #define FxaaBool bool #define FxaaFloat float #define FxaaFloat2 vec2 #define FxaaFloat3 vec3 #define FxaaFloat4 vec4 #define FxaaHalf float #define FxaaHalf2 vec2 #define FxaaHalf3 vec3 #define FxaaHalf4 vec4 #define FxaaInt2 vec2 #define FxaaTex sampler2D #define FxaaSat(x) clamp(x, 0.0, 1.0) #define FxaaTexTop(t, p) texture(t, p) #define FxaaTexOff(t, p, o, r) texture(t, p + (o * r)) FxaaFloat FxaaLuma_(FxaaFloat4 rgba) { return dot(rgba.rgb, vec3(0.2126, 0.7152, 0.0722)); } FxaaFloat4 FxaaPixelShader_( // // Use noperspective interpolation here (turn off perspective interpolation). // {xy} = center of pixel FxaaFloat2 pos, // // Input color texture. // {rgb_} = color in linear or perceptual color space // if (FXAA_GREEN_AS_LUMA == 0) // {___a} = luma in perceptual color space (not linear) FxaaTex tex, // // Only used on FXAA Quality. // This must be from a constant/uniform. // {x_} = 1.0/screenWidthInPixels // {_y} = 1.0/screenHeightInPixels FxaaFloat2 fxaaQualityRcpFrame, // // Only used on FXAA Quality. // This used to be the FXAA_QUALITY_SUBPIX define. // It is here now to allow easier tuning. // Choose the amount of sub-pixel aliasing removal. // This can effect sharpness. // 1.00 - upper limit (softer) // 0.75 - default amount of filtering // 0.50 - lower limit (sharper, less sub-pixel aliasing removal) // 0.25 - almost off // 0.00 - completely off FxaaFloat fxaaQualitySubpix, // // Only used on FXAA Quality. // This used to be the FXAA_QUALITY_EDGE_THRESHOLD define. // It is here now to allow easier tuning. // The minimum amount of local contrast required to apply algorithm. // 0.333 - too little (faster) // 0.250 - low quality // 0.166 - default // 0.125 - high quality // 0.063 - overkill (slower) FxaaFloat fxaaQualityEdgeThreshold, // // Only used on FXAA Quality. // This used to be the FXAA_QUALITY_EDGE_THRESHOLD_MIN define. // It is here now to allow easier tuning. // Trims the algorithm from processing darks. // 0.0833 - upper limit (default, the start of visible unfiltered edges) // 0.0625 - high quality (faster) // 0.0312 - visible limit (slower) // Special notes when using FXAA_GREEN_AS_LUMA, // Likely want to set this to zero. // As colors that are mostly not-green // will appear very dark in the green channel! // Tune by looking at mostly non-green content, // then start at zero and increase until aliasing is a problem. FxaaFloat fxaaQualityEdgeThresholdMin ) { /*--------------------------------------------------------------------------*/ FxaaFloat2 posM; posM.x = pos.x; posM.y = pos.y; FxaaFloat4 rgbyM = FxaaTexTop(tex, posM); #define lumaM rgbyM.y FxaaFloat lumaS = FxaaLuma_(FxaaTexOff(tex, posM, FxaaInt2( 0, 1), fxaaQualityRcpFrame.xy)); FxaaFloat lumaE = FxaaLuma_(FxaaTexOff(tex, posM, FxaaInt2( 1, 0), fxaaQualityRcpFrame.xy)); FxaaFloat lumaN = FxaaLuma_(FxaaTexOff(tex, posM, FxaaInt2( 0,-1), fxaaQualityRcpFrame.xy)); FxaaFloat lumaW = FxaaLuma_(FxaaTexOff(tex, posM, FxaaInt2(-1, 0), fxaaQualityRcpFrame.xy)); /*--------------------------------------------------------------------------*/ FxaaFloat maxSM = max(lumaS, lumaM); FxaaFloat minSM = min(lumaS, lumaM); FxaaFloat maxESM = max(lumaE, maxSM); FxaaFloat minESM = min(lumaE, minSM); FxaaFloat maxWN = max(lumaN, lumaW); FxaaFloat minWN = min(lumaN, lumaW); FxaaFloat rangeMax = max(maxWN, maxESM); FxaaFloat rangeMin = min(minWN, minESM); FxaaFloat rangeMaxScaled = rangeMax * fxaaQualityEdgeThreshold; FxaaFloat range = rangeMax - rangeMin; FxaaFloat rangeMaxClamped = max(fxaaQualityEdgeThresholdMin, rangeMaxScaled); FxaaBool earlyExit = range < rangeMaxClamped; /*--------------------------------------------------------------------------*/ if(earlyExit) return rgbyM; /*--------------------------------------------------------------------------*/ FxaaFloat lumaNW = FxaaLuma_(FxaaTexOff(tex, posM, FxaaInt2(-1,-1), fxaaQualityRcpFrame.xy)); FxaaFloat lumaSE = FxaaLuma_(FxaaTexOff(tex, posM, FxaaInt2( 1, 1), fxaaQualityRcpFrame.xy)); FxaaFloat lumaNE = FxaaLuma_(FxaaTexOff(tex, posM, FxaaInt2( 1,-1), fxaaQualityRcpFrame.xy)); FxaaFloat lumaSW = FxaaLuma_(FxaaTexOff(tex, posM, FxaaInt2(-1, 1), fxaaQualityRcpFrame.xy)); /*--------------------------------------------------------------------------*/ FxaaFloat lumaNS = lumaN + lumaS; FxaaFloat lumaWE = lumaW + lumaE; FxaaFloat subpixRcpRange = 1.0/range; FxaaFloat subpixNSWE = lumaNS + lumaWE; FxaaFloat edgeHorz1 = (-2.0 * lumaM) + lumaNS; FxaaFloat edgeVert1 = (-2.0 * lumaM) + lumaWE; /*--------------------------------------------------------------------------*/ FxaaFloat lumaNESE = lumaNE + lumaSE; FxaaFloat lumaNWNE = lumaNW + lumaNE; FxaaFloat edgeHorz2 = (-2.0 * lumaE) + lumaNESE; FxaaFloat edgeVert2 = (-2.0 * lumaN) + lumaNWNE; /*--------------------------------------------------------------------------*/ FxaaFloat lumaNWSW = lumaNW + lumaSW; FxaaFloat lumaSWSE = lumaSW + lumaSE; FxaaFloat edgeHorz4 = (abs(edgeHorz1) * 2.0) + abs(edgeHorz2); FxaaFloat edgeVert4 = (abs(edgeVert1) * 2.0) + abs(edgeVert2); FxaaFloat edgeHorz3 = (-2.0 * lumaW) + lumaNWSW; FxaaFloat edgeVert3 = (-2.0 * lumaS) + lumaSWSE; FxaaFloat edgeHorz = abs(edgeHorz3) + edgeHorz4; FxaaFloat edgeVert = abs(edgeVert3) + edgeVert4; /*--------------------------------------------------------------------------*/ FxaaFloat subpixNWSWNESE = lumaNWSW + lumaNESE; FxaaFloat lengthSign = fxaaQualityRcpFrame.x; FxaaBool horzSpan = edgeHorz >= edgeVert; FxaaFloat subpixA = subpixNSWE * 2.0 + subpixNWSWNESE; /*--------------------------------------------------------------------------*/ if(!horzSpan) lumaN = lumaW; if(!horzSpan) lumaS = lumaE; if(horzSpan) lengthSign = fxaaQualityRcpFrame.y; FxaaFloat subpixB = (subpixA * (1.0/12.0)) - lumaM; /*--------------------------------------------------------------------------*/ FxaaFloat gradientN = lumaN - lumaM; FxaaFloat gradientS = lumaS - lumaM; FxaaFloat lumaNN = lumaN + lumaM; FxaaFloat lumaSS = lumaS + lumaM; FxaaBool pairN = abs(gradientN) >= abs(gradientS); FxaaFloat gradient = max(abs(gradientN), abs(gradientS)); if(pairN) lengthSign = -lengthSign; FxaaFloat subpixC = FxaaSat(abs(subpixB) * subpixRcpRange); /*--------------------------------------------------------------------------*/ FxaaFloat2 posB; posB.x = posM.x; posB.y = posM.y; FxaaFloat2 offNP; offNP.x = (!horzSpan) ? 0.0 : fxaaQualityRcpFrame.x; offNP.y = ( horzSpan) ? 0.0 : fxaaQualityRcpFrame.y; if(!horzSpan) posB.x += lengthSign * 0.5; if( horzSpan) posB.y += lengthSign * 0.5; /*--------------------------------------------------------------------------*/ FxaaFloat2 posN; posN.x = posB.x - offNP.x * FXAA_QUALITY_P0; posN.y = posB.y - offNP.y * FXAA_QUALITY_P0; FxaaFloat2 posP; posP.x = posB.x + offNP.x * FXAA_QUALITY_P0; posP.y = posB.y + offNP.y * FXAA_QUALITY_P0; FxaaFloat subpixD = ((-2.0)*subpixC) + 3.0; FxaaFloat lumaEndN = FxaaLuma_(FxaaTexTop(tex, posN)); FxaaFloat subpixE = subpixC * subpixC; FxaaFloat lumaEndP = FxaaLuma_(FxaaTexTop(tex, posP)); /*--------------------------------------------------------------------------*/ if(!pairN) lumaNN = lumaSS; FxaaFloat gradientScaled = gradient * 1.0/4.0; FxaaFloat lumaMM = lumaM - lumaNN * 0.5; FxaaFloat subpixF = subpixD * subpixE; FxaaBool lumaMLTZero = lumaMM < 0.0; /*--------------------------------------------------------------------------*/ lumaEndN -= lumaNN * 0.5; lumaEndP -= lumaNN * 0.5; FxaaBool doneN = abs(lumaEndN) >= gradientScaled; FxaaBool doneP = abs(lumaEndP) >= gradientScaled; if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P1; if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P1; FxaaBool doneNP = (!doneN) || (!doneP); if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P1; if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P1; /*--------------------------------------------------------------------------*/ if(doneNP) { if(!doneN) lumaEndN = FxaaLuma_(FxaaTexTop(tex, posN.xy)); if(!doneP) lumaEndP = FxaaLuma_(FxaaTexTop(tex, posP.xy)); if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; doneN = abs(lumaEndN) >= gradientScaled; doneP = abs(lumaEndP) >= gradientScaled; if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P2; if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P2; doneNP = (!doneN) || (!doneP); if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P2; if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P2; /*--------------------------------------------------------------------------*/ #if (FXAA_QUALITY_PS > 3) if(doneNP) { if(!doneN) lumaEndN = FxaaLuma_(FxaaTexTop(tex, posN.xy)); if(!doneP) lumaEndP = FxaaLuma_(FxaaTexTop(tex, posP.xy)); if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; doneN = abs(lumaEndN) >= gradientScaled; doneP = abs(lumaEndP) >= gradientScaled; if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P3; if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P3; doneNP = (!doneN) || (!doneP); if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P3; if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P3; /*--------------------------------------------------------------------------*/ #if (FXAA_QUALITY_PS > 4) if(doneNP) { if(!doneN) lumaEndN = FxaaLuma_(FxaaTexTop(tex, posN.xy)); if(!doneP) lumaEndP = FxaaLuma_(FxaaTexTop(tex, posP.xy)); if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; doneN = abs(lumaEndN) >= gradientScaled; doneP = abs(lumaEndP) >= gradientScaled; if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P4; if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P4; doneNP = (!doneN) || (!doneP); if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P4; if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P4; /*--------------------------------------------------------------------------*/ #if (FXAA_QUALITY_PS > 5) if(doneNP) { if(!doneN) lumaEndN = FxaaLuma_(FxaaTexTop(tex, posN.xy)); if(!doneP) lumaEndP = FxaaLuma_(FxaaTexTop(tex, posP.xy)); if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; doneN = abs(lumaEndN) >= gradientScaled; doneP = abs(lumaEndP) >= gradientScaled; if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P5; if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P5; doneNP = (!doneN) || (!doneP); if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P5; if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P5; /*--------------------------------------------------------------------------*/ #if (FXAA_QUALITY_PS > 6) if(doneNP) { if(!doneN) lumaEndN = FxaaLuma_(FxaaTexTop(tex, posN.xy)); if(!doneP) lumaEndP = FxaaLuma_(FxaaTexTop(tex, posP.xy)); if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; doneN = abs(lumaEndN) >= gradientScaled; doneP = abs(lumaEndP) >= gradientScaled; if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P6; if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P6; doneNP = (!doneN) || (!doneP); if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P6; if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P6; /*--------------------------------------------------------------------------*/ #if (FXAA_QUALITY_PS > 7) if(doneNP) { if(!doneN) lumaEndN = FxaaLuma_(FxaaTexTop(tex, posN.xy)); if(!doneP) lumaEndP = FxaaLuma_(FxaaTexTop(tex, posP.xy)); if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; doneN = abs(lumaEndN) >= gradientScaled; doneP = abs(lumaEndP) >= gradientScaled; if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P7; if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P7; doneNP = (!doneN) || (!doneP); if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P7; if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P7; /*--------------------------------------------------------------------------*/ #if (FXAA_QUALITY_PS > 8) if(doneNP) { if(!doneN) lumaEndN = FxaaLuma_(FxaaTexTop(tex, posN.xy)); if(!doneP) lumaEndP = FxaaLuma_(FxaaTexTop(tex, posP.xy)); if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; doneN = abs(lumaEndN) >= gradientScaled; doneP = abs(lumaEndP) >= gradientScaled; if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P8; if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P8; doneNP = (!doneN) || (!doneP); if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P8; if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P8; /*--------------------------------------------------------------------------*/ #if (FXAA_QUALITY_PS > 9) if(doneNP) { if(!doneN) lumaEndN = FxaaLuma_(FxaaTexTop(tex, posN.xy)); if(!doneP) lumaEndP = FxaaLuma_(FxaaTexTop(tex, posP.xy)); if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; doneN = abs(lumaEndN) >= gradientScaled; doneP = abs(lumaEndP) >= gradientScaled; if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P9; if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P9; doneNP = (!doneN) || (!doneP); if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P9; if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P9; /*--------------------------------------------------------------------------*/ #if (FXAA_QUALITY_PS > 10) if(doneNP) { if(!doneN) lumaEndN = FxaaLuma_(FxaaTexTop(tex, posN.xy)); if(!doneP) lumaEndP = FxaaLuma_(FxaaTexTop(tex, posP.xy)); if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; doneN = abs(lumaEndN) >= gradientScaled; doneP = abs(lumaEndP) >= gradientScaled; if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P10; if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P10; doneNP = (!doneN) || (!doneP); if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P10; if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P10; /*--------------------------------------------------------------------------*/ #if (FXAA_QUALITY_PS > 11) if(doneNP) { if(!doneN) lumaEndN = FxaaLuma_(FxaaTexTop(tex, posN.xy)); if(!doneP) lumaEndP = FxaaLuma_(FxaaTexTop(tex, posP.xy)); if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; doneN = abs(lumaEndN) >= gradientScaled; doneP = abs(lumaEndP) >= gradientScaled; if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P11; if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P11; doneNP = (!doneN) || (!doneP); if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P11; if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P11; /*--------------------------------------------------------------------------*/ #if (FXAA_QUALITY_PS > 12) if(doneNP) { if(!doneN) lumaEndN = FxaaLuma_(FxaaTexTop(tex, posN.xy)); if(!doneP) lumaEndP = FxaaLuma_(FxaaTexTop(tex, posP.xy)); if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; doneN = abs(lumaEndN) >= gradientScaled; doneP = abs(lumaEndP) >= gradientScaled; if(!doneN) posN.x -= offNP.x * FXAA_QUALITY_P12; if(!doneN) posN.y -= offNP.y * FXAA_QUALITY_P12; doneNP = (!doneN) || (!doneP); if(!doneP) posP.x += offNP.x * FXAA_QUALITY_P12; if(!doneP) posP.y += offNP.y * FXAA_QUALITY_P12; /*--------------------------------------------------------------------------*/ } #endif /*--------------------------------------------------------------------------*/ } #endif /*--------------------------------------------------------------------------*/ } #endif /*--------------------------------------------------------------------------*/ } #endif /*--------------------------------------------------------------------------*/ } #endif /*--------------------------------------------------------------------------*/ } #endif /*--------------------------------------------------------------------------*/ } #endif /*--------------------------------------------------------------------------*/ } #endif /*--------------------------------------------------------------------------*/ } #endif /*--------------------------------------------------------------------------*/ } #endif /*--------------------------------------------------------------------------*/ } /*--------------------------------------------------------------------------*/ FxaaFloat dstN = posM.x - posN.x; FxaaFloat dstP = posP.x - posM.x; if(!horzSpan) dstN = posM.y - posN.y; if(!horzSpan) dstP = posP.y - posM.y; /*--------------------------------------------------------------------------*/ FxaaBool goodSpanN = (lumaEndN < 0.0) != lumaMLTZero; FxaaFloat spanLength = (dstP + dstN); FxaaBool goodSpanP = (lumaEndP < 0.0) != lumaMLTZero; FxaaFloat spanLengthRcp = 1.0/spanLength; /*--------------------------------------------------------------------------*/ FxaaBool directionN = dstN < dstP; FxaaFloat dst = min(dstN, dstP); FxaaBool goodSpan = directionN ? goodSpanN : goodSpanP; FxaaFloat subpixG = subpixF * subpixF; FxaaFloat pixelOffset = (dst * (-spanLengthRcp)) + 0.5; FxaaFloat subpixH = subpixG * fxaaQualitySubpix; /*--------------------------------------------------------------------------*/ FxaaFloat pixelOffsetGood = goodSpan ? pixelOffset : 0.0; FxaaFloat pixelOffsetSubpix = max(pixelOffsetGood, subpixH); if(!horzSpan) posM.x += pixelOffsetSubpix * lengthSign; if( horzSpan) posM.y += pixelOffsetSubpix * lengthSign; return FxaaTexTop(tex, posM); } vec4 fxaa_sampleColor(sampler2D source, vec2 texSize, vec2 texCoord) { const float fxaa_QualitySubpix = 0.5; const float fxaa_QualityEdgeThreshold = 0.125; const float fxaa_QualityEdgeThresholdMin = 0.0833; return FxaaPixelShader_( texCoord, source, vec2(1.0) / texSize, fxaa_QualitySubpix, fxaa_QualityEdgeThreshold, fxaa_QualityEdgeThresholdMin ); } `; var fxaa = { name: "fxaa", uniformPropTypes: {}, fs: fs23, passes: [{ sampler: true }] }; // dist/modules-webgl1/math/fp64/fp64-utils.js function fp64ify(a, out = [], startIndex = 0) { const hiPart = Math.fround(a); const loPart = a - hiPart; out[startIndex] = hiPart; out[startIndex + 1] = loPart; return out; } function fp64LowPart(a) { return a - Math.fround(a); } function fp64ifyMatrix4(matrix) { const matrixFP64 = new Float32Array(32); for (let i = 0; i < 4; ++i) { for (let j = 0; j < 4; ++j) { const index2 = i * 4 + j; fp64ify(matrix[j * 4 + i], matrixFP64, index2 * 2); } } return matrixFP64; } // dist/modules-webgl1/math/fp64/fp64-arithmetic-glsl.js var fp64arithmeticShader = `uniform float ONE; vec2 split(float a) { const float SPLIT = 4097.0; float t = a * SPLIT; #if defined(LUMA_FP64_CODE_ELIMINATION_WORKAROUND) float a_hi = t * ONE - (t - a); float a_lo = a * ONE - a_hi; #else float a_hi = t - (t - a); float a_lo = a - a_hi; #endif return vec2(a_hi, a_lo); } vec2 split2(vec2 a) { vec2 b = split(a.x); b.y += a.y; return b; } vec2 quickTwoSum(float a, float b) { #if defined(LUMA_FP64_CODE_ELIMINATION_WORKAROUND) float sum = (a + b) * ONE; float err = b - (sum - a) * ONE; #else float sum = a + b; float err = b - (sum - a); #endif return vec2(sum, err); } vec2 twoSum(float a, float b) { float s = (a + b); #if defined(LUMA_FP64_CODE_ELIMINATION_WORKAROUND) float v = (s * ONE - a) * ONE; float err = (a - (s - v) * ONE) * ONE * ONE * ONE + (b - v); #else float v = s - a; float err = (a - (s - v)) + (b - v); #endif return vec2(s, err); } vec2 twoSub(float a, float b) { float s = (a - b); #if defined(LUMA_FP64_CODE_ELIMINATION_WORKAROUND) float v = (s * ONE - a) * ONE; float err = (a - (s - v) * ONE) * ONE * ONE * ONE - (b + v); #else float v = s - a; float err = (a - (s - v)) - (b + v); #endif return vec2(s, err); } vec2 twoSqr(float a) { float prod = a * a; vec2 a_fp64 = split(a); #if defined(LUMA_FP64_CODE_ELIMINATION_WORKAROUND) float err = ((a_fp64.x * a_fp64.x - prod) * ONE + 2.0 * a_fp64.x * a_fp64.y * ONE * ONE) + a_fp64.y * a_fp64.y * ONE * ONE * ONE; #else float err = ((a_fp64.x * a_fp64.x - prod) + 2.0 * a_fp64.x * a_fp64.y) + a_fp64.y * a_fp64.y; #endif return vec2(prod, err); } vec2 twoProd(float a, float b) { float prod = a * b; vec2 a_fp64 = split(a); vec2 b_fp64 = split(b); float err = ((a_fp64.x * b_fp64.x - prod) + a_fp64.x * b_fp64.y + a_fp64.y * b_fp64.x) + a_fp64.y * b_fp64.y; return vec2(prod, err); } vec2 sum_fp64(vec2 a, vec2 b) { vec2 s, t; s = twoSum(a.x, b.x); t = twoSum(a.y, b.y); s.y += t.x; s = quickTwoSum(s.x, s.y); s.y += t.y; s = quickTwoSum(s.x, s.y); return s; } vec2 sub_fp64(vec2 a, vec2 b) { vec2 s, t; s = twoSub(a.x, b.x); t = twoSub(a.y, b.y); s.y += t.x; s = quickTwoSum(s.x, s.y); s.y += t.y; s = quickTwoSum(s.x, s.y); return s; } vec2 mul_fp64(vec2 a, vec2 b) { vec2 prod = twoProd(a.x, b.x); prod.y += a.x * b.y; #if defined(LUMA_FP64_HIGH_BITS_OVERFLOW_WORKAROUND) prod = split2(prod); #endif prod = quickTwoSum(prod.x, prod.y); prod.y += a.y * b.x; #if defined(LUMA_FP64_HIGH_BITS_OVERFLOW_WORKAROUND) prod = split2(prod); #endif prod = quickTwoSum(prod.x, prod.y); return prod; } vec2 div_fp64(vec2 a, vec2 b) { float xn = 1.0 / b.x; #if defined(LUMA_FP64_HIGH_BITS_OVERFLOW_WORKAROUND) vec2 yn = mul_fp64(a, vec2(xn, 0)); #else vec2 yn = a * xn; #endif float diff = (sub_fp64(a, mul_fp64(b, yn))).x; vec2 prod = twoProd(xn, diff); return sum_fp64(yn, prod); } vec2 sqrt_fp64(vec2 a) { if (a.x == 0.0 && a.y == 0.0) return vec2(0.0, 0.0); if (a.x < 0.0) return vec2(0.0 / 0.0, 0.0 / 0.0); float x = 1.0 / sqrt(a.x); float yn = a.x * x; #if defined(LUMA_FP64_CODE_ELIMINATION_WORKAROUND) vec2 yn_sqr = twoSqr(yn) * ONE; #else vec2 yn_sqr = twoSqr(yn); #endif float diff = sub_fp64(a, yn_sqr).x; vec2 prod = twoProd(x * 0.5, diff); #if defined(LUMA_FP64_HIGH_BITS_OVERFLOW_WORKAROUND) return sum_fp64(split(yn), prod); #else return sum_fp64(vec2(yn, 0.0), prod); #endif } `; // dist/modules-webgl1/math/fp64/fp64-functions-glsl.js var fp64functionShader = `const vec2 E_FP64 = vec2(2.7182817459106445e+00, 8.254840366817007e-08); const vec2 LOG2_FP64 = vec2(0.6931471824645996e+00, -1.9046542121259336e-09); const vec2 PI_FP64 = vec2(3.1415927410125732, -8.742278012618954e-8); const vec2 TWO_PI_FP64 = vec2(6.2831854820251465, -1.7484556025237907e-7); const vec2 PI_2_FP64 = vec2(1.5707963705062866, -4.371139006309477e-8); const vec2 PI_4_FP64 = vec2(0.7853981852531433, -2.1855695031547384e-8); const vec2 PI_16_FP64 = vec2(0.19634954631328583, -5.463923757886846e-9); const vec2 PI_16_2_FP64 = vec2(0.39269909262657166, -1.0927847515773692e-8); const vec2 PI_16_3_FP64 = vec2(0.5890486240386963, -1.4906100798128818e-9); const vec2 PI_180_FP64 = vec2(0.01745329238474369, 1.3519960498364902e-10); const vec2 SIN_TABLE_0_FP64 = vec2(0.19509032368659973, -1.6704714833615242e-9); const vec2 SIN_TABLE_1_FP64 = vec2(0.3826834261417389, 6.22335089017767e-9); const vec2 SIN_TABLE_2_FP64 = vec2(0.5555702447891235, -1.1769521357507529e-8); const vec2 SIN_TABLE_3_FP64 = vec2(0.7071067690849304, 1.2101617041793133e-8); const vec2 COS_TABLE_0_FP64 = vec2(0.9807852506637573, 2.9739473106360492e-8); const vec2 COS_TABLE_1_FP64 = vec2(0.9238795042037964, 2.8307490351764386e-8); const vec2 COS_TABLE_2_FP64 = vec2(0.8314695954322815, 1.6870263741530778e-8); const vec2 COS_TABLE_3_FP64 = vec2(0.7071067690849304, 1.2101617152815436e-8); const vec2 INVERSE_FACTORIAL_3_FP64 = vec2(1.666666716337204e-01, -4.967053879312289e-09); const vec2 INVERSE_FACTORIAL_4_FP64 = vec2(4.16666679084301e-02, -1.2417634698280722e-09); const vec2 INVERSE_FACTORIAL_5_FP64 = vec2(8.333333767950535e-03, -4.34617203337595e-10); const vec2 INVERSE_FACTORIAL_6_FP64 = vec2(1.3888889225199819e-03, -3.3631094437103215e-11); const vec2 INVERSE_FACTORIAL_7_FP64 = vec2(1.9841270113829523e-04, -2.725596874933456e-12); const vec2 INVERSE_FACTORIAL_8_FP64 = vec2(2.4801587642286904e-05, -3.406996025904184e-13); const vec2 INVERSE_FACTORIAL_9_FP64 = vec2(2.75573188446287533e-06, 3.7935713937038186e-14); const vec2 INVERSE_FACTORIAL_10_FP64 = vec2(2.755731998149713e-07, -7.575112367869873e-15); float nint(float d) { if (d == floor(d)) return d; return floor(d + 0.5); } vec2 nint_fp64(vec2 a) { float hi = nint(a.x); float lo; vec2 tmp; if (hi == a.x) { lo = nint(a.y); tmp = quickTwoSum(hi, lo); } else { lo = 0.0; if (abs(hi - a.x) == 0.5 && a.y < 0.0) { hi -= 1.0; } tmp = vec2(hi, lo); } return tmp; } vec2 exp_fp64(vec2 a) { const int k_power = 4; const float k = 16.0; const float inv_k = 1.0 / k; if (a.x <= -88.0) return vec2(0.0, 0.0); if (a.x >= 88.0) return vec2(1.0 / 0.0, 1.0 / 0.0); if (a.x == 0.0 && a.y == 0.0) return vec2(1.0, 0.0); if (a.x == 1.0 && a.y == 0.0) return E_FP64; float m = floor(a.x / LOG2_FP64.x + 0.5); vec2 r = sub_fp64(a, mul_fp64(LOG2_FP64, vec2(m, 0.0))) * inv_k; vec2 s, t, p; p = mul_fp64(r, r); s = sum_fp64(r, p * 0.5); p = mul_fp64(p, r); t = mul_fp64(p, INVERSE_FACTORIAL_3_FP64); s = sum_fp64(s, t); p = mul_fp64(p, r); t = mul_fp64(p, INVERSE_FACTORIAL_4_FP64); s = sum_fp64(s, t); p = mul_fp64(p, r); t = mul_fp64(p, INVERSE_FACTORIAL_5_FP64); s = sum_fp64(s, t); for (int i = 0; i < k_power; i++) { s = sum_fp64(s * 2.0, mul_fp64(s, s)); } #if defined(NVIDIA_FP64_WORKAROUND) || defined(INTEL_FP64_WORKAROUND) s = sum_fp64(s, vec2(ONE, 0.0)); #else s = sum_fp64(s, vec2(1.0, 0.0)); #endif return s * pow(2.0, m); } vec2 log_fp64(vec2 a) { if (a.x == 1.0 && a.y == 0.0) return vec2(0.0, 0.0); if (a.x <= 0.0) return vec2(0.0 / 0.0, 0.0 / 0.0); vec2 x = vec2(log(a.x), 0.0); vec2 s; #if defined(NVIDIA_FP64_WORKAROUND) || defined(INTEL_FP64_WORKAROUND) s = vec2(ONE, 0.0); #else s = vec2(1.0, 0.0); #endif x = sub_fp64(sum_fp64(x, mul_fp64(a, exp_fp64(-x))), s); return x; } vec2 sin_taylor_fp64(vec2 a) { vec2 r, s, t, x; if (a.x == 0.0 && a.y == 0.0) { return vec2(0.0, 0.0); } x = -mul_fp64(a, a); s = a; r = a; r = mul_fp64(r, x); t = mul_fp64(r, INVERSE_FACTORIAL_3_FP64); s = sum_fp64(s, t); r = mul_fp64(r, x); t = mul_fp64(r, INVERSE_FACTORIAL_5_FP64); s = sum_fp64(s, t); return s; } vec2 cos_taylor_fp64(vec2 a) { vec2 r, s, t, x; if (a.x == 0.0 && a.y == 0.0) { return vec2(1.0, 0.0); } x = -mul_fp64(a, a); r = x; s = sum_fp64(vec2(1.0, 0.0), r * 0.5); r = mul_fp64(r, x); t = mul_fp64(r, INVERSE_FACTORIAL_4_FP64); s = sum_fp64(s, t); r = mul_fp64(r, x); t = mul_fp64(r, INVERSE_FACTORIAL_6_FP64); s = sum_fp64(s, t); return s; } void sincos_taylor_fp64(vec2 a, out vec2 sin_t, out vec2 cos_t) { if (a.x == 0.0 && a.y == 0.0) { sin_t = vec2(0.0, 0.0); cos_t = vec2(1.0, 0.0); } sin_t = sin_taylor_fp64(a); cos_t = sqrt_fp64(sub_fp64(vec2(1.0, 0.0), mul_fp64(sin_t, sin_t))); } vec2 sin_fp64(vec2 a) { if (a.x == 0.0 && a.y == 0.0) { return vec2(0.0, 0.0); } vec2 z = nint_fp64(div_fp64(a, TWO_PI_FP64)); vec2 r = sub_fp64(a, mul_fp64(TWO_PI_FP64, z)); vec2 t; float q = floor(r.x / PI_2_FP64.x + 0.5); int j = int(q); if (j < -2 || j > 2) { return vec2(0.0 / 0.0, 0.0 / 0.0); } t = sub_fp64(r, mul_fp64(PI_2_FP64, vec2(q, 0.0))); q = floor(t.x / PI_16_FP64.x + 0.5); int k = int(q); if (k == 0) { if (j == 0) { return sin_taylor_fp64(t); } else if (j == 1) { return cos_taylor_fp64(t); } else if (j == -1) { return -cos_taylor_fp64(t); } else { return -sin_taylor_fp64(t); } } int abs_k = int(abs(float(k))); if (abs_k > 4) { return vec2(0.0 / 0.0, 0.0 / 0.0); } else { t = sub_fp64(t, mul_fp64(PI_16_FP64, vec2(q, 0.0))); } vec2 u = vec2(0.0, 0.0); vec2 v = vec2(0.0, 0.0); #if defined(NVIDIA_FP64_WORKAROUND) || defined(INTEL_FP64_WORKAROUND) if (abs(float(abs_k) - 1.0) < 0.5) { u = COS_TABLE_0_FP64; v = SIN_TABLE_0_FP64; } else if (abs(float(abs_k) - 2.0) < 0.5) { u = COS_TABLE_1_FP64; v = SIN_TABLE_1_FP64; } else if (abs(float(abs_k) - 3.0) < 0.5) { u = COS_TABLE_2_FP64; v = SIN_TABLE_2_FP64; } else if (abs(float(abs_k) - 4.0) < 0.5) { u = COS_TABLE_3_FP64; v = SIN_TABLE_3_FP64; } #else if (abs_k == 1) { u = COS_TABLE_0_FP64; v = SIN_TABLE_0_FP64; } else if (abs_k == 2) { u = COS_TABLE_1_FP64; v = SIN_TABLE_1_FP64; } else if (abs_k == 3) { u = COS_TABLE_2_FP64; v = SIN_TABLE_2_FP64; } else if (abs_k == 4) { u = COS_TABLE_3_FP64; v = SIN_TABLE_3_FP64; } #endif vec2 sin_t, cos_t; sincos_taylor_fp64(t, sin_t, cos_t); vec2 result = vec2(0.0, 0.0); if (j == 0) { if (k > 0) { result = sum_fp64(mul_fp64(u, sin_t), mul_fp64(v, cos_t)); } else { result = sub_fp64(mul_fp64(u, sin_t), mul_fp64(v, cos_t)); } } else if (j == 1) { if (k > 0) { result = sub_fp64(mul_fp64(u, cos_t), mul_fp64(v, sin_t)); } else { result = sum_fp64(mul_fp64(u, cos_t), mul_fp64(v, sin_t)); } } else if (j == -1) { if (k > 0) { result = sub_fp64(mul_fp64(v, sin_t), mul_fp64(u, cos_t)); } else { result = -sum_fp64(mul_fp64(v, sin_t), mul_fp64(u, cos_t)); } } else { if (k > 0) { result = -sum_fp64(mul_fp64(u, sin_t), mul_fp64(v, cos_t)); } else { result = sub_fp64(mul_fp64(v, cos_t), mul_fp64(u, sin_t)); } } return result; } vec2 cos_fp64(vec2 a) { if (a.x == 0.0 && a.y == 0.0) { return vec2(1.0, 0.0); } vec2 z = nint_fp64(div_fp64(a, TWO_PI_FP64)); vec2 r = sub_fp64(a, mul_fp64(TWO_PI_FP64, z)); vec2 t; float q = floor(r.x / PI_2_FP64.x + 0.5); int j = int(q); if (j < -2 || j > 2) { return vec2(0.0 / 0.0, 0.0 / 0.0); } t = sub_fp64(r, mul_fp64(PI_2_FP64, vec2(q, 0.0))); q = floor(t.x / PI_16_FP64.x + 0.5); int k = int(q); if (k == 0) { if (j == 0) { return cos_taylor_fp64(t); } else if (j == 1) { return -sin_taylor_fp64(t); } else if (j == -1) { return sin_taylor_fp64(t); } else { return -cos_taylor_fp64(t); } } int abs_k = int(abs(float(k))); if (abs_k > 4) { return vec2(0.0 / 0.0, 0.0 / 0.0); } else { t = sub_fp64(t, mul_fp64(PI_16_FP64, vec2(q, 0.0))); } vec2 u = vec2(0.0, 0.0); vec2 v = vec2(0.0, 0.0); #if defined(NVIDIA_FP64_WORKAROUND) || defined(INTEL_FP64_WORKAROUND) if (abs(float(abs_k) - 1.0) < 0.5) { u = COS_TABLE_0_FP64; v = SIN_TABLE_0_FP64; } else if (abs(float(abs_k) - 2.0) < 0.5) { u = COS_TABLE_1_FP64; v = SIN_TABLE_1_FP64; } else if (abs(float(abs_k) - 3.0) < 0.5) { u = COS_TABLE_2_FP64; v = SIN_TABLE_2_FP64; } else if (abs(float(abs_k) - 4.0) < 0.5) { u = COS_TABLE_3_FP64; v = SIN_TABLE_3_FP64; } #else if (abs_k == 1) { u = COS_TABLE_0_FP64; v = SIN_TABLE_0_FP64; } else if (abs_k == 2) { u = COS_TABLE_1_FP64; v = SIN_TABLE_1_FP64; } else if (abs_k == 3) { u = COS_TABLE_2_FP64; v = SIN_TABLE_2_FP64; } else if (abs_k == 4) { u = COS_TABLE_3_FP64; v = SIN_TABLE_3_FP64; } #endif vec2 sin_t, cos_t; sincos_taylor_fp64(t, sin_t, cos_t); vec2 result = vec2(0.0, 0.0); if (j == 0) { if (k > 0) { result = sub_fp64(mul_fp64(u, cos_t), mul_fp64(v, sin_t)); } else { result = sum_fp64(mul_fp64(u, cos_t), mul_fp64(v, sin_t)); } } else if (j == 1) { if (k > 0) { result = -sum_fp64(mul_fp64(u, sin_t), mul_fp64(v, cos_t)); } else { result = sub_fp64(mul_fp64(v, cos_t), mul_fp64(u, sin_t)); } } else if (j == -1) { if (k > 0) { result = sum_fp64(mul_fp64(u, sin_t), mul_fp64(v, cos_t)); } else { result = sub_fp64(mul_fp64(u, sin_t), mul_fp64(v, cos_t)); } } else { if (k > 0) { result = sub_fp64(mul_fp64(v, sin_t), mul_fp64(u, cos_t)); } else { result = -sum_fp64(mul_fp64(u, cos_t), mul_fp64(v, sin_t)); } } return result; } vec2 tan_fp64(vec2 a) { vec2 sin_a; vec2 cos_a; if (a.x == 0.0 && a.y == 0.0) { return vec2(0.0, 0.0); } vec2 z = nint_fp64(div_fp64(a, TWO_PI_FP64)); vec2 r = sub_fp64(a, mul_fp64(TWO_PI_FP64, z)); vec2 t; float q = floor(r.x / PI_2_FP64.x + 0.5); int j = int(q); if (j < -2 || j > 2) { return vec2(0.0 / 0.0, 0.0 / 0.0); } t = sub_fp64(r, mul_fp64(PI_2_FP64, vec2(q, 0.0))); q = floor(t.x / PI_16_FP64.x + 0.5); int k = int(q); int abs_k = int(abs(float(k))); if (abs_k > 4) { return vec2(0.0 / 0.0, 0.0 / 0.0); } else { t = sub_fp64(t, mul_fp64(PI_16_FP64, vec2(q, 0.0))); } vec2 u = vec2(0.0, 0.0); vec2 v = vec2(0.0, 0.0); vec2 sin_t, cos_t; vec2 s, c; sincos_taylor_fp64(t, sin_t, cos_t); if (k == 0) { s = sin_t; c = cos_t; } else { #if defined(NVIDIA_FP64_WORKAROUND) || defined(INTEL_FP64_WORKAROUND) if (abs(float(abs_k) - 1.0) < 0.5) { u = COS_TABLE_0_FP64; v = SIN_TABLE_0_FP64; } else if (abs(float(abs_k) - 2.0) < 0.5) { u = COS_TABLE_1_FP64; v = SIN_TABLE_1_FP64; } else if (abs(float(abs_k) - 3.0) < 0.5) { u = COS_TABLE_2_FP64; v = SIN_TABLE_2_FP64; } else if (abs(float(abs_k) - 4.0) < 0.5) { u = COS_TABLE_3_FP64; v = SIN_TABLE_3_FP64; } #else if (abs_k == 1) { u = COS_TABLE_0_FP64; v = SIN_TABLE_0_FP64; } else if (abs_k == 2) { u = COS_TABLE_1_FP64; v = SIN_TABLE_1_FP64; } else if (abs_k == 3) { u = COS_TABLE_2_FP64; v = SIN_TABLE_2_FP64; } else if (abs_k == 4) { u = COS_TABLE_3_FP64; v = SIN_TABLE_3_FP64; } #endif if (k > 0) { s = sum_fp64(mul_fp64(u, sin_t), mul_fp64(v, cos_t)); c = sub_fp64(mul_fp64(u, cos_t), mul_fp64(v, sin_t)); } else { s = sub_fp64(mul_fp64(u, sin_t), mul_fp64(v, cos_t)); c = sum_fp64(mul_fp64(u, cos_t), mul_fp64(v, sin_t)); } } if (j == 0) { sin_a = s; cos_a = c; } else if (j == 1) { sin_a = c; cos_a = -s; } else if (j == -1) { sin_a = -c; cos_a = s; } else { sin_a = -s; cos_a = -c; } return div_fp64(sin_a, cos_a); } vec2 radians_fp64(vec2 degree) { return mul_fp64(degree, PI_180_FP64); } vec2 mix_fp64(vec2 a, vec2 b, float x) { vec2 range = sub_fp64(b, a); return sum_fp64(a, mul_fp64(range, vec2(x, 0.0))); } void vec2_sum_fp64(vec2 a[2], vec2 b[2], out vec2 out_val[2]) { out_val[0] = sum_fp64(a[0], b[0]); out_val[1] = sum_fp64(a[1], b[1]); } void vec2_sub_fp64(vec2 a[2], vec2 b[2], out vec2 out_val[2]) { out_val[0] = sub_fp64(a[0], b[0]); out_val[1] = sub_fp64(a[1], b[1]); } void vec2_mul_fp64(vec2 a[2], vec2 b[2], out vec2 out_val[2]) { out_val[0] = mul_fp64(a[0], b[0]); out_val[1] = mul_fp64(a[1], b[1]); } void vec2_div_fp64(vec2 a[2], vec2 b[2], out vec2 out_val[2]) { out_val[0] = div_fp64(a[0], b[0]); out_val[1] = div_fp64(a[1], b[1]); } void vec2_mix_fp64(vec2 x[2], vec2 y[2], float a, out vec2 out_val[2]) { vec2 range[2]; vec2_sub_fp64(y, x, range); vec2 portion[2]; portion[0] = range[0] * a; portion[1] = range[1] * a; vec2_sum_fp64(x, portion, out_val); } vec2 vec2_length_fp64(vec2 x[2]) { return sqrt_fp64(sum_fp64(mul_fp64(x[0], x[0]), mul_fp64(x[1], x[1]))); } void vec2_normalize_fp64(vec2 x[2], out vec2 out_val[2]) { vec2 length = vec2_length_fp64(x); vec2 length_vec2[2]; length_vec2[0] = length; length_vec2[1] = length; vec2_div_fp64(x, length_vec2, out_val); } vec2 vec2_distance_fp64(vec2 x[2], vec2 y[2]) { vec2 diff[2]; vec2_sub_fp64(x, y, diff); return vec2_length_fp64(diff); } vec2 vec2_dot_fp64(vec2 a[2], vec2 b[2]) { vec2 v[2]; v[0] = mul_fp64(a[0], b[0]); v[1] = mul_fp64(a[1], b[1]); return sum_fp64(v[0], v[1]); } void vec3_sub_fp64(vec2 a[3], vec2 b[3], out vec2 out_val[3]) { for (int i = 0; i < 3; i++) { out_val[i] = sum_fp64(a[i], b[i]); } } void vec3_sum_fp64(vec2 a[3], vec2 b[3], out vec2 out_val[3]) { for (int i = 0; i < 3; i++) { out_val[i] = sum_fp64(a[i], b[i]); } } vec2 vec3_length_fp64(vec2 x[3]) { return sqrt_fp64(sum_fp64(sum_fp64(mul_fp64(x[0], x[0]), mul_fp64(x[1], x[1])), mul_fp64(x[2], x[2]))); } vec2 vec3_distance_fp64(vec2 x[3], vec2 y[3]) { vec2 diff[3]; vec3_sub_fp64(x, y, diff); return vec3_length_fp64(diff); } void vec4_fp64(vec4 a, out vec2 out_val[4]) { out_val[0].x = a[0]; out_val[0].y = 0.0; out_val[1].x = a[1]; out_val[1].y = 0.0; out_val[2].x = a[2]; out_val[2].y = 0.0; out_val[3].x = a[3]; out_val[3].y = 0.0; } void vec4_scalar_mul_fp64(vec2 a[4], vec2 b, out vec2 out_val[4]) { out_val[0] = mul_fp64(a[0], b); out_val[1] = mul_fp64(a[1], b); out_val[2] = mul_fp64(a[2], b); out_val[3] = mul_fp64(a[3], b); } void vec4_sum_fp64(vec2 a[4], vec2 b[4], out vec2 out_val[4]) { for (int i = 0; i < 4; i++) { out_val[i] = sum_fp64(a[i], b[i]); } } void vec4_dot_fp64(vec2 a[4], vec2 b[4], out vec2 out_val) { vec2 v[4]; v[0] = mul_fp64(a[0], b[0]); v[1] = mul_fp64(a[1], b[1]); v[2] = mul_fp64(a[2], b[2]); v[3] = mul_fp64(a[3], b[3]); out_val = sum_fp64(sum_fp64(v[0], v[1]), sum_fp64(v[2], v[3])); } void mat4_vec4_mul_fp64(vec2 b[16], vec2 a[4], out vec2 out_val[4]) { vec2 tmp[4]; for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { tmp[j] = b[j + i * 4]; } vec4_dot_fp64(a, tmp, out_val[i]); } } `; // dist/modules-webgl1/math/fp64/fp64.js var CONST_UNIFORMS = { // Used in LUMA_FP64_CODE_ELIMINATION_WORKAROUND ONE: 1 }; function getUniforms4() { return CONST_UNIFORMS; } var fp64arithmetic = { name: "fp64-arithmetic", vs: fp64arithmeticShader, getUniforms: getUniforms4, fp64ify, fp64LowPart, fp64ifyMatrix4 }; var fp64 = { name: "fp64", vs: fp64functionShader, dependencies: [fp64arithmetic], // Additional Functions fp64ify, fp64LowPart, fp64ifyMatrix4 }; // dist/modules-webgl1/geometry/geometry.js var vs3 = `varying vec4 geometry_vPosition; varying vec3 geometry_vNormal; void geometry_setNormal(vec3 normal) { geometry_vNormal = normal; } void geometry_setPosition(vec4 position) { geometry_vPosition = position; } void geometry_setPosition(vec3 position) { geometry_vPosition = vec4(position, 1.); } `; var fs24 = `varying vec4 geometry_vPosition; varying vec3 geometry_vNormal; vec4 geometry_getPosition() { return geometry_vPosition; } vec3 geometry_getNormal() { return geometry_vNormal; } `; var geometry = { name: "geometry", vs: vs3, fs: fs24 }; // dist/modules-webgl1/project/project.js var import_core3 = require("@math.gl/core"); var IDENTITY_MATRIX = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]; var DEFAULT_MODULE_OPTIONS = { modelMatrix: IDENTITY_MATRIX, viewMatrix: IDENTITY_MATRIX, projectionMatrix: IDENTITY_MATRIX, cameraPositionWorld: [0, 0, 0] }; function getUniforms5(opts = DEFAULT_MODULE_OPTIONS, prevUniforms = {}) { const uniforms = {}; if (opts.modelMatrix !== void 0) { uniforms.modelMatrix = opts.modelMatrix; } if (opts.viewMatrix !== void 0) { uniforms.viewMatrix = opts.viewMatrix; } if (opts.projectionMatrix !== void 0) { uniforms.projectionMatrix = opts.projectionMatrix; } if (opts.cameraPositionWorld !== void 0) { uniforms.cameraPositionWorld = opts.cameraPositionWorld; } if (opts.projectionMatrix !== void 0 || opts.viewMatrix !== void 0) { uniforms.viewProjectionMatrix = new import_core3.Matrix4(opts.projectionMatrix).multiplyRight(opts.viewMatrix); } return uniforms; } var common = `varying vec4 project_vPositionWorld; varying vec3 project_vNormalWorld; vec4 project_getPosition_World() { return project_vPositionWorld; } vec3 project_getNormal_World() { return project_vNormalWorld; } `; var vs4 = `${common} // Unprefixed uniforms uniform mat4 modelMatrix; uniform mat4 viewMatrix; uniform mat4 projectionMatrix; uniform mat4 viewProjectionMatrix; uniform vec3 cameraPositionWorld; struct World { vec3 position; vec3 normal; }; World world; void project_setPosition(vec4 position) { project_vPositionWorld = position; } void project_setNormal(vec3 normal) { project_vNormalWorld = normal; } void project_setPositionAndNormal_World(vec3 position, vec3 normal) { world.position = position; world.normal = normal; } void project_setPositionAndNormal_Model(vec3 position, vec3 normal) { world.position = (modelMatrix * vec4(position, 1.)).xyz; world.normal = mat3(modelMatrix) * normal; } vec4 project_model_to_clipspace(vec4 position) { return viewProjectionMatrix * modelMatrix * position; } vec4 project_model_to_clipspace(vec3 position) { return viewProjectionMatrix * modelMatrix * vec4(position, 1.); } vec4 project_world_to_clipspace(vec3 position) { return viewProjectionMatrix * vec4(position, 1.); } vec4 project_view_to_clipspace(vec3 position) { return projectionMatrix * vec4(position, 1.); } vec4 project_to_clipspace(vec3 position) { return viewProjectionMatrix * vec4(position, 1.); } `; var fs25 = ` ${common}`; var project = { name: "project", getUniforms: getUniforms5, vs: vs4, fs: fs25 }; // dist/modules-webgl1/lighting/lights/lights-glsl.js var lightingShader = `#if (defined(SHADER_TYPE_FRAGMENT) && defined(LIGHTING_FRAGMENT)) || (defined(SHADER_TYPE_VERTEX) && defined(LIGHTING_VERTEX)) struct AmbientLight { vec3 color; }; struct PointLight { vec3 color; vec3 position; vec3 attenuation; }; struct DirectionalLight { vec3 color; vec3 direction; }; uniform AmbientLight lighting_uAmbientLight; uniform PointLight lighting_uPointLight[MAX_LIGHTS]; uniform DirectionalLight lighting_uDirectionalLight[MAX_LIGHTS]; uniform int lighting_uPointLightCount; uniform int lighting_uDirectionalLightCount; uniform bool lighting_uEnabled; float getPointLightAttenuation(PointLight pointLight, float distance) { return pointLight.attenuation.x + pointLight.attenuation.y * distance + pointLight.attenuation.z * distance * distance; } #endif `; // dist/modules-webgl1/lighting/lights/lights.js var INITIAL_MODULE_OPTIONS = { lightSources: {} }; function convertColor2(colorDef = {}) { const { color = [0, 0, 0], intensity = 1 } = colorDef; return color.map((component) => component * intensity / 255); } function getLightSourceUniforms2({ ambientLight, pointLights = [], directionalLights = [] }) { const lightSourceUniforms = {}; if (ambientLight) { lightSourceUniforms["lighting_uAmbientLight.color"] = convertColor2(ambientLight); } else { lightSourceUniforms["lighting_uAmbientLight.color"] = [0, 0, 0]; } pointLights.forEach((pointLight, index2) => { lightSourceUniforms[`lighting_uPointLight[${index2}].color`] = convertColor2(pointLight); lightSourceUniforms[`lighting_uPointLight[${index2}].position`] = pointLight.position; lightSourceUniforms[`lighting_uPointLight[${index2}].attenuation`] = pointLight.attenuation || [ 1, 0, 0 ]; }); lightSourceUniforms.lighting_uPointLightCount = pointLights.length; directionalLights.forEach((directionalLight, index2) => { lightSourceUniforms[`lighting_uDirectionalLight[${index2}].color`] = convertColor2(directionalLight); lightSourceUniforms[`lighting_uDirectionalLight[${index2}].direction`] = directionalLight.direction; }); lightSourceUniforms.lighting_uDirectionalLightCount = directionalLights.length; return lightSourceUniforms; } function getUniforms6(opts = INITIAL_MODULE_OPTIONS) { var _a, _b; if ("lightSources" in opts) { const { ambientLight, pointLights, directionalLights } = opts.lightSources || {}; const hasLights = ambientLight || pointLights && pointLights.length > 0 || directionalLights && directionalLights.length > 0; if (!hasLights) { return { lighting_uEnabled: false }; } return Object.assign({}, getLightSourceUniforms2({ ambientLight, pointLights, directionalLights }), { lighting_uEnabled: true }); } if ("lights" in opts) { const lightSources = { pointLights: [], directionalLights: [] }; for (const light of opts.lights || []) { switch (light.type) { case "ambient": lightSources.ambientLight = light; break; case "directional": (_a = lightSources.directionalLights) == null ? void 0 : _a.push(light); break; case "point": (_b = lightSources.pointLights) == null ? void 0 : _b.push(light); break; default: } } return getUniforms6({ lightSources }); } return {}; } var lights = { name: "lights", vs: lightingShader, fs: lightingShader, getUniforms: getUniforms6, defines: { MAX_LIGHTS: 3 } }; // dist/modules-webgl1/lighting/dirlight/dirlight.js var DEFAULT_MODULE_OPTIONS2 = { lightDirection: new Float32Array([1, 1, 2]) }; function getUniforms7(opts = DEFAULT_MODULE_OPTIONS2) { const uniforms = {}; if (opts.lightDirection) { uniforms.dirlight_uLightDirection = opts.lightDirection; } return uniforms; } var fs26 = `uniform vec3 dirlight_uLightDirection; vec4 dirlight_filterColor(vec4 color) { vec3 normal = project_getNormal_World(); float d = abs(dot(normalize(normal), normalize(dirlight_uLightDirection))); return vec4(color.rgb * d, color.a); } `; var dirlight2 = { name: "dirlight", // vs // TODO - reuse normal from geometry module fs: fs26, getUniforms: getUniforms7, dependencies: [project] }; // dist/modules-webgl1/lighting/phong-lighting/phong-lighting-glsl.js var lightingShader2 = `uniform float lighting_uAmbient; uniform float lighting_uDiffuse; uniform float lighting_uShininess; uniform vec3 lighting_uSpecularColor; vec3 lighting_getLightColor(vec3 surfaceColor, vec3 light_direction, vec3 view_direction, vec3 normal_worldspace, vec3 color) { vec3 halfway_direction = normalize(light_direction + view_direction); float lambertian = dot(light_direction, normal_worldspace); float specular = 0.0; if (lambertian > 0.0) { float specular_angle = max(dot(normal_worldspace, halfway_direction), 0.0); specular = pow(specular_angle, lighting_uShininess); } lambertian = max(lambertian, 0.0); return (lambertian * lighting_uDiffuse * surfaceColor + specular * lighting_uSpecularColor) * color; } vec3 lighting_getLightColor(vec3 surfaceColor, vec3 cameraPosition, vec3 position_worldspace, vec3 normal_worldspace) { vec3 lightColor = surfaceColor; if (lighting_uEnabled) { vec3 view_direction = normalize(cameraPosition - position_worldspace); lightColor = lighting_uAmbient * surfaceColor * lighting_uAmbientLight.color; for (int i = 0; i < MAX_LIGHTS; i++) { if (i >= lighting_uPointLightCount) { break; } PointLight pointLight = lighting_uPointLight[i]; vec3 light_position_worldspace = pointLight.position; vec3 light_direction = normalize(light_position_worldspace - position_worldspace); lightColor += lighting_getLightColor(surfaceColor, light_direction, view_direction, normal_worldspace, pointLight.color); } for (int i = 0; i < MAX_LIGHTS; i++) { if (i >= lighting_uDirectionalLightCount) { break; } DirectionalLight directionalLight = lighting_uDirectionalLight[i]; lightColor += lighting_getLightColor(surfaceColor, -directionalLight.direction, view_direction, normal_worldspace, directionalLight.color); } } return lightColor; } vec3 lighting_getSpecularLightColor(vec3 cameraPosition, vec3 position_worldspace, vec3 normal_worldspace) { vec3 lightColor = vec3(0, 0, 0); vec3 surfaceColor = vec3(0, 0, 0); if (lighting_uEnabled) { vec3 view_direction = normalize(cameraPosition - position_worldspace); for (int i = 0; i < MAX_LIGHTS; i++) { if (i >= lighting_uPointLightCount) { break; } PointLight pointLight = lighting_uPointLight[i]; vec3 light_position_worldspace = pointLight.position; vec3 light_direction = normalize(light_position_worldspace - position_worldspace); lightColor += lighting_getLightColor(surfaceColor, light_direction, view_direction, normal_worldspace, pointLight.color); } for (int i = 0; i < MAX_LIGHTS; i++) { if (i >= lighting_uDirectionalLightCount) { break; } DirectionalLight directionalLight = lighting_uDirectionalLight[i]; lightColor += lighting_getLightColor(surfaceColor, -directionalLight.direction, view_direction, normal_worldspace, directionalLight.color); } } return lightColor; } `; // dist/modules-webgl1/lighting/phong-lighting/phong-lighting.js var INITIAL_MODULE_OPTIONS2 = {}; function getMaterialUniforms(material) { const { ambient = 0.35, diffuse = 0.6, shininess = 32, specularColor = [30, 30, 30] } = material; return { lighting_uAmbient: ambient, lighting_uDiffuse: diffuse, lighting_uShininess: shininess, lighting_uSpecularColor: specularColor.map((x) => x / 255) }; } function getUniforms8(opts = INITIAL_MODULE_OPTIONS2) { if (!("material" in opts)) { return {}; } const { material } = opts; if (!material) { return { lighting_uEnabled: false }; } return getMaterialUniforms(material); } var gouraudLighting = { name: "gouraud-lighting", dependencies: [lights], vs: lightingShader2, defines: { LIGHTING_VERTEX: 1 }, getUniforms: getUniforms8 }; var phongLighting = { name: "phong-lighting", dependencies: [lights], fs: lightingShader2, defines: { LIGHTING_FRAGMENT: 1 }, getUniforms: getUniforms8 }; // dist/modules-webgl1/lighting/pbr/pbr-vertex-glsl.js var vs5 = `uniform mat4 u_MVPMatrix; uniform mat4 u_ModelMatrix; uniform mat4 u_NormalMatrix; out vec3 pbr_vPosition; out vec2 pbr_vUV; #ifdef HAS_NORMALS # ifdef HAS_TANGENTS out mat3 pbr_vTBN; # else out vec3 pbr_vNormal; # endif #endif void pbr_setPositionNormalTangentUV(vec4 position, vec4 normal, vec4 tangent, vec2 uv) { vec4 pos = u_ModelMatrix * position; pbr_vPosition = vec3(pos.xyz) / pos.w; #ifdef HAS_NORMALS #ifdef HAS_TANGENTS vec3 normalW = normalize(vec3(u_NormalMatrix * vec4(normal.xyz, 0.0))); vec3 tangentW = normalize(vec3(u_ModelMatrix * vec4(tangent.xyz, 0.0))); vec3 bitangentW = cross(normalW, tangentW) * tangent.w; pbr_vTBN = mat3(tangentW, bitangentW, normalW); #else pbr_vNormal = normalize(vec3(u_ModelMatrix * vec4(normal.xyz, 0.0))); #endif #endif #ifdef HAS_UV pbr_vUV = uv; #else pbr_vUV = vec2(0.,0.); #endif } `; // dist/modules-webgl1/lighting/pbr/pbr-fragment-glsl.js var fs27 = `precision highp float; uniform bool pbr_uUnlit; #ifdef USE_IBL uniform samplerCube u_DiffuseEnvSampler; uniform samplerCube u_SpecularEnvSampler; uniform sampler2D u_brdfLUT; uniform vec2 u_ScaleIBLAmbient; #endif #ifdef HAS_BASECOLORMAP uniform sampler2D u_BaseColorSampler; #endif #ifdef HAS_NORMALMAP uniform sampler2D u_NormalSampler; uniform float u_NormalScale; #endif #ifdef HAS_EMISSIVEMAP uniform sampler2D u_EmissiveSampler; uniform vec3 u_EmissiveFactor; #endif #ifdef HAS_METALROUGHNESSMAP uniform sampler2D u_MetallicRoughnessSampler; #endif #ifdef HAS_OCCLUSIONMAP uniform sampler2D u_OcclusionSampler; uniform float u_OcclusionStrength; #endif #ifdef ALPHA_CUTOFF uniform float u_AlphaCutoff; #endif uniform vec2 u_MetallicRoughnessValues; uniform vec4 u_BaseColorFactor; uniform vec3 u_Camera; #ifdef PBR_DEBUG uniform vec4 u_ScaleDiffBaseMR; uniform vec4 u_ScaleFGDSpec; #endif in vec3 pbr_vPosition; in vec2 pbr_vUV; #ifdef HAS_NORMALS #ifdef HAS_TANGENTS in mat3 pbr_vTBN; #else in vec3 pbr_vNormal; #endif #endif struct PBRInfo { float NdotL; float NdotV; float NdotH; float LdotH; float VdotH; float perceptualRoughness; float metalness; vec3 reflectance0; vec3 reflectance90; float alphaRoughness; vec3 diffuseColor; vec3 specularColor; vec3 n; vec3 v; }; const float M_PI = 3.141592653589793; const float c_MinRoughness = 0.04; vec4 SRGBtoLINEAR(vec4 srgbIn) { #ifdef MANUAL_SRGB #ifdef SRGB_FAST_APPROXIMATION vec3 linOut = pow(srgbIn.xyz,vec3(2.2)); #else vec3 bLess = step(vec3(0.04045),srgbIn.xyz); vec3 linOut = mix( srgbIn.xyz/vec3(12.92), pow((srgbIn.xyz+vec3(0.055))/vec3(1.055),vec3(2.4)), bLess ); #endif return vec4(linOut,srgbIn.w);; #else return srgbIn; #endif } vec3 getNormal() { #ifndef HAS_TANGENTS vec3 pos_dx = dFdx(pbr_vPosition); vec3 pos_dy = dFdy(pbr_vPosition); vec3 tex_dx = dFdx(vec3(pbr_vUV, 0.0)); vec3 tex_dy = dFdy(vec3(pbr_vUV, 0.0)); vec3 t = (tex_dy.t * pos_dx - tex_dx.t * pos_dy) / (tex_dx.s * tex_dy.t - tex_dy.s * tex_dx.t); #ifdef HAS_NORMALS vec3 ng = normalize(pbr_vNormal); #else vec3 ng = cross(pos_dx, pos_dy); #endif t = normalize(t - ng * dot(ng, t)); vec3 b = normalize(cross(ng, t)); mat3 tbn = mat3(t, b, ng); #else mat3 tbn = pbr_vTBN; #endif #ifdef HAS_NORMALMAP vec3 n = texture(u_NormalSampler, pbr_vUV).rgb; n = normalize(tbn * ((2.0 * n - 1.0) * vec3(u_NormalScale, u_NormalScale, 1.0))); #else vec3 n = normalize(tbn[2].xyz); #endif return n; } #ifdef USE_IBL vec3 getIBLContribution(PBRInfo pbrInputs, vec3 n, vec3 reflection) { float mipCount = 9.0; float lod = (pbrInputs.perceptualRoughness * mipCount); vec3 brdf = SRGBtoLINEAR(texture(u_brdfLUT, vec2(pbrInputs.NdotV, 1.0 - pbrInputs.perceptualRoughness))).rgb; vec3 diffuseLight = SRGBtoLINEAR(textureCube(u_DiffuseEnvSampler, n)).rgb; #ifdef USE_TEX_LOD vec3 specularLight = SRGBtoLINEAR(textureCubeLod(u_SpecularEnvSampler, reflection, lod)).rgb; #else vec3 specularLight = SRGBtoLINEAR(textureCube(u_SpecularEnvSampler, reflection)).rgb; #endif vec3 diffuse = diffuseLight * pbrInputs.diffuseColor; vec3 specular = specularLight * (pbrInputs.specularColor * brdf.x + brdf.y); diffuse *= u_ScaleIBLAmbient.x; specular *= u_ScaleIBLAmbient.y; return diffuse + specular; } #endif vec3 diffuse(PBRInfo pbrInputs) { return pbrInputs.diffuseColor / M_PI; } vec3 specularReflection(PBRInfo pbrInputs) { return pbrInputs.reflectance0 + (pbrInputs.reflectance90 - pbrInputs.reflectance0) * pow(clamp(1.0 - pbrInputs.VdotH, 0.0, 1.0), 5.0); } float geometricOcclusion(PBRInfo pbrInputs) { float NdotL = pbrInputs.NdotL; float NdotV = pbrInputs.NdotV; float r = pbrInputs.alphaRoughness; float attenuationL = 2.0 * NdotL / (NdotL + sqrt(r * r + (1.0 - r * r) * (NdotL * NdotL))); float attenuationV = 2.0 * NdotV / (NdotV + sqrt(r * r + (1.0 - r * r) * (NdotV * NdotV))); return attenuationL * attenuationV; } float microfacetDistribution(PBRInfo pbrInputs) { float roughnessSq = pbrInputs.alphaRoughness * pbrInputs.alphaRoughness; float f = (pbrInputs.NdotH * roughnessSq - pbrInputs.NdotH) * pbrInputs.NdotH + 1.0; return roughnessSq / (M_PI * f * f); } void PBRInfo_setAmbientLight(inout PBRInfo pbrInputs) { pbrInputs.NdotL = 1.0; pbrInputs.NdotH = 0.0; pbrInputs.LdotH = 0.0; pbrInputs.VdotH = 1.0; } void PBRInfo_setDirectionalLight(inout PBRInfo pbrInputs, vec3 lightDirection) { vec3 n = pbrInputs.n; vec3 v = pbrInputs.v; vec3 l = normalize(lightDirection); vec3 h = normalize(l+v); pbrInputs.NdotL = clamp(dot(n, l), 0.001, 1.0); pbrInputs.NdotH = clamp(dot(n, h), 0.0, 1.0); pbrInputs.LdotH = clamp(dot(l, h), 0.0, 1.0); pbrInputs.VdotH = clamp(dot(v, h), 0.0, 1.0); } void PBRInfo_setPointLight(inout PBRInfo pbrInputs, PointLight pointLight) { vec3 light_direction = normalize(pointLight.position - pbr_vPosition); PBRInfo_setDirectionalLight(pbrInputs, light_direction); } vec3 calculateFinalColor(PBRInfo pbrInputs, vec3 lightColor) { vec3 F = specularReflection(pbrInputs); float G = geometricOcclusion(pbrInputs); float D = microfacetDistribution(pbrInputs); vec3 diffuseContrib = (1.0 - F) * diffuse(pbrInputs); vec3 specContrib = F * G * D / (4.0 * pbrInputs.NdotL * pbrInputs.NdotV); return pbrInputs.NdotL * lightColor * (diffuseContrib + specContrib); } vec4 pbr_filterColor(vec4 colorUnused) { #ifdef HAS_BASECOLORMAP vec4 baseColor = SRGBtoLINEAR(texture(u_BaseColorSampler, pbr_vUV)) * u_BaseColorFactor; #else vec4 baseColor = u_BaseColorFactor; #endif #ifdef ALPHA_CUTOFF if (baseColor.a < u_AlphaCutoff) { discard; } #endif vec3 color = vec3(0, 0, 0); if(pbr_uUnlit){ color.rgb = baseColor.rgb; } else{ float perceptualRoughness = u_MetallicRoughnessValues.y; float metallic = u_MetallicRoughnessValues.x; #ifdef HAS_METALROUGHNESSMAP vec4 mrSample = texture(u_MetallicRoughnessSampler, pbr_vUV); perceptualRoughness = mrSample.g * perceptualRoughness; metallic = mrSample.b * metallic; #endif perceptualRoughness = clamp(perceptualRoughness, c_MinRoughness, 1.0); metallic = clamp(metallic, 0.0, 1.0); float alphaRoughness = perceptualRoughness * perceptualRoughness; vec3 f0 = vec3(0.04); vec3 diffuseColor = baseColor.rgb * (vec3(1.0) - f0); diffuseColor *= 1.0 - metallic; vec3 specularColor = mix(f0, baseColor.rgb, metallic); float reflectance = max(max(specularColor.r, specularColor.g), specularColor.b); float reflectance90 = clamp(reflectance * 25.0, 0.0, 1.0); vec3 specularEnvironmentR0 = specularColor.rgb; vec3 specularEnvironmentR90 = vec3(1.0, 1.0, 1.0) * reflectance90; vec3 n = getNormal(); vec3 v = normalize(u_Camera - pbr_vPosition); float NdotV = clamp(abs(dot(n, v)), 0.001, 1.0); vec3 reflection = -normalize(reflect(v, n)); PBRInfo pbrInputs = PBRInfo( 0.0, NdotV, 0.0, 0.0, 0.0, perceptualRoughness, metallic, specularEnvironmentR0, specularEnvironmentR90, alphaRoughness, diffuseColor, specularColor, n, v ); #ifdef USE_LIGHTS PBRInfo_setAmbientLight(pbrInputs); color += calculateFinalColor(pbrInputs, lighting_uAmbientLight.color); for(int i = 0; i < lighting_uDirectionalLightCount; i++) { if (i < lighting_uDirectionalLightCount) { PBRInfo_setDirectionalLight(pbrInputs, lighting_uDirectionalLight[i].direction); color += calculateFinalColor(pbrInputs, lighting_uDirectionalLight[i].color); } } for(int i = 0; i < lighting_uPointLightCount; i++) { if (i < lighting_uPointLightCount) { PBRInfo_setPointLight(pbrInputs, lighting_uPointLight[i]); float attenuation = getPointLightAttenuation(lighting_uPointLight[i], distance(lighting_uPointLight[i].position, pbr_vPosition)); color += calculateFinalColor(pbrInputs, lighting_uPointLight[i].color / attenuation); } } #endif #ifdef USE_IBL color += getIBLContribution(pbrInputs, n, reflection); #endif #ifdef HAS_OCCLUSIONMAP float ao = texture(u_OcclusionSampler, pbr_vUV).r; color = mix(color, color * ao, u_OcclusionStrength); #endif #ifdef HAS_EMISSIVEMAP vec3 emissive = SRGBtoLINEAR(texture(u_EmissiveSampler, pbr_vUV)).rgb * u_EmissiveFactor; color += emissive; #endif #ifdef PBR_DEBUG color = mix(color, baseColor.rgb, u_ScaleDiffBaseMR.y); color = mix(color, vec3(metallic), u_ScaleDiffBaseMR.z); color = mix(color, vec3(perceptualRoughness), u_ScaleDiffBaseMR.w); #endif } return vec4(pow(color,vec3(1.0/2.2)), baseColor.a); } `; // dist/modules-webgl1/lighting/pbr/pbr.js var pbr = { name: "pbr", vs: vs5, fs: fs27, defines: { LIGHTING_FRAGMENT: 1 }, dependencies: [lights] }; /** * ORIGINAL LICENCE * @license * Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of NVIDIA CORPORATION nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ //# sourceMappingURL=index.cjs.map