diff --git a/docs/upgrade-guide.md b/docs/upgrade-guide.md index 2f6c063f8a..a3176a3aad 100644 --- a/docs/upgrade-guide.md +++ b/docs/upgrade-guide.md @@ -15,18 +15,18 @@ luma.gl largely follows [SEMVER](https://semver.org) conventions. Breaking chang v9.2 brings full WebGPU support. Some additional deprecations and breaking changes have been necessary, but apart from the `Texture` -> `AsyncTexture` split, impact on most applications should be minimal. **Major change: Texture and AsyncTextures** -- `device.createTexture()` no longer accepts `props.mipmaps`: Use `AsyncTexture` or call texture.generateMipmapsWebGL()` -- `device.createTexture()` no longer accepts `props.mipmaps`: Use `AsyncTexture` or call `texture.generateMipmapsWebGL()` +- The `Texture` class has been simplified to the minimum API required for GPU portability. The `AsyncTexture` texture class provides a higher-level API and is recommended for most applications. +- `device.createTexture()` no longer accepts `props.data`: Use `AsyncTexture` or call `texture.setImageData()` +- `device.createTexture()` no longer accepts `props.mipmaps`: Use `AsyncTexture` (or call `texture.generateMipmapsWebGL()`) **Major change: Removal of WebGL uniform support** -- `Model.setUniformsWebGL()` dropped, use uniform buffer bindings -- `Renderpipeline.setUniformsWebGL()` dropped, use uniform buffer bindings +- The transition from uniforms to uniform buffers is complete, and remaining support for non-buffer uniforms has been removed. +- `core`: `Renderpipeline.setUniformsWebGL()` dropped, use uniform buffer bindings +- `engine`: `Model.setUniformsWebGL()` dropped, use uniform buffer bindings +- `shadertools`: WebGL1 shader modules have been removed, use the new modules uniform buffer-based counterparts. **Minor changes** -- The shader type system has been refactored, some shader type names have changed. These are typically not used directly by applications. - -**Minor changes** -- The shader type system has been refactored, some shader type names have changed. These are typically not used directly by applications. +- `core`: The shader types has been refactored, some shader type names have changed. These are typically not used directly by applications. ## Upgrading to v9.1 diff --git a/modules/shadertools/src/index.ts b/modules/shadertools/src/index.ts index 1e4f395295..25845b39d6 100644 --- a/modules/shadertools/src/index.ts +++ b/modules/shadertools/src/index.ts @@ -89,20 +89,3 @@ export type { export type {PBRProjectionProps} from './modules/lighting/pbr-material/pbr-projection'; export {pbrMaterial} from './modules/lighting/pbr-material/pbr-material'; - -// DEPRECATED - v8 legacy shader modules (non-uniform buffer) - -// math libraries -// export {fp64, fp64arithmetic} from './modules-webgl1/math/fp64/fp64'; - -// projection and lighting -export {geometry as geometry1} from './modules-webgl1/geometry/geometry'; -export {project as project1} from './modules-webgl1/project/project'; - -export {lights as lights1} from './modules-webgl1/lighting/lights/lights'; -export {dirlight as dirlight1} from './modules-webgl1/lighting/dirlight/dirlight'; -export { - gouraudLighting, - phongLighting -} from './modules-webgl1/lighting/phong-lighting/phong-lighting'; -export {pbr} from './modules-webgl1/lighting/pbr/pbr'; diff --git a/modules/shadertools/src/modules-webgl1/geometry/geometry.ts b/modules/shadertools/src/modules-webgl1/geometry/geometry.ts deleted file mode 100644 index bf3c1538fb..0000000000 --- a/modules/shadertools/src/modules-webgl1/geometry/geometry.ts +++ /dev/null @@ -1,41 +0,0 @@ -// import {ShaderModule} from '../../types'; - -// TODO - reuse normal from geometry module -const vs = /* glsl */ `\ -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.); -} -`; - -const fs = /* glsl */ `\ -varying vec4 geometry_vPosition; -varying vec3 geometry_vNormal; - -vec4 geometry_getPosition() { - return geometry_vPosition; -} - -vec3 geometry_getNormal() { - return geometry_vNormal; -} -`; - -/** - * Geometry varyings - */ -export const geometry = { - name: 'geometry', - vs, - fs -}; diff --git a/modules/shadertools/src/modules-webgl1/lighting/dirlight/dirlight.ts b/modules/shadertools/src/modules-webgl1/lighting/dirlight/dirlight.ts deleted file mode 100644 index 50283849cc..0000000000 --- a/modules/shadertools/src/modules-webgl1/lighting/dirlight/dirlight.ts +++ /dev/null @@ -1,50 +0,0 @@ -// luma.gl -// SPDX-License-Identifier: MIT -// Copyright (c) vis.gl contributors - -import {ShaderModule} from '../../../lib/shader-module/shader-module'; -import type {NumericArray} from '../../../types'; -import {project} from '../../project/project'; - -/* eslint-disable camelcase */ - -export type DirlightOptions = { - lightDirection?: NumericArray; -}; - -const DEFAULT_MODULE_OPTIONS: Required = { - lightDirection: new Float32Array([1, 1, 2]) -}; - -function getUniforms(opts: DirlightOptions = DEFAULT_MODULE_OPTIONS): Record { - const uniforms = {}; - if (opts.lightDirection) { - // @ts-expect-error TODO add types - uniforms.dirlight_uLightDirection = opts.lightDirection; - } - return uniforms; -} - -const fs = /* glsl */ `\ -uniform vec3 dirlight_uLightDirection; - -/* - * Returns color attenuated by angle from light source - */ -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); -} -`; - -/** - * Cheap lighting - single directional light, single dot product, one uniform - */ -export const dirlight: ShaderModule = { - name: 'dirlight', - // vs // TODO - reuse normal from geometry module - fs, - getUniforms, - dependencies: [project] -}; diff --git a/modules/shadertools/src/modules-webgl1/lighting/lights/lights-glsl.ts b/modules/shadertools/src/modules-webgl1/lighting/lights/lights-glsl.ts deleted file mode 100644 index 3ec9a0679d..0000000000 --- a/modules/shadertools/src/modules-webgl1/lighting/lights/lights-glsl.ts +++ /dev/null @@ -1,40 +0,0 @@ -// luma.gl -// SPDX-License-Identifier: MIT -// Copyright (c) vis.gl contributors - -export const lightingShader = /* glsl */ `\ -#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; - - // Constant-Linear-Exponential - 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 -`; diff --git a/modules/shadertools/src/modules-webgl1/lighting/lights/lights.ts b/modules/shadertools/src/modules-webgl1/lighting/lights/lights.ts deleted file mode 100644 index b8552bc1d9..0000000000 --- a/modules/shadertools/src/modules-webgl1/lighting/lights/lights.ts +++ /dev/null @@ -1,143 +0,0 @@ -// luma.gl -// SPDX-License-Identifier: MIT -// Copyright (c) vis.gl contributors - -import type {NumberArray} from '../../../types'; -import {lightingShader} from './lights-glsl'; - -/* eslint-disable camelcase */ - -type LightSources = { - ambientLight?: { - color: Readonly; - intensity: number; - }; - pointLights?: { - color: Readonly; - intensity: number; - position: NumberArray; - attenuation: number; - }[]; - directionalLights?: { - color: Readonly; - intensity: number; - position: NumberArray; - direction: NumberArray; - }[]; -}; - -export type LightsOptions = { - lightSources?: LightSources; -}; - -const INITIAL_MODULE_OPTIONS: Required = { - lightSources: {} -}; - -// Take color 0-255 and intensity as input and output 0.0-1.0 range -function convertColor( - colorDef: {color?: Readonly; intensity?: number} = {} -): NumberArray { - const {color = [0, 0, 0], intensity = 1.0} = colorDef; - return color.map(component => (component * intensity) / 255.0); -} - -function getLightSourceUniforms({ - ambientLight, - pointLights = [], - directionalLights = [] -}: LightSources): Record { - const lightSourceUniforms: Record = {}; - - if (ambientLight) { - lightSourceUniforms['lighting_uAmbientLight.color'] = convertColor(ambientLight); - } else { - lightSourceUniforms['lighting_uAmbientLight.color'] = [0, 0, 0]; - } - - pointLights.forEach((pointLight, index) => { - lightSourceUniforms[`lighting_uPointLight[${index}].color`] = convertColor(pointLight); - lightSourceUniforms[`lighting_uPointLight[${index}].position`] = pointLight.position; - lightSourceUniforms[`lighting_uPointLight[${index}].attenuation`] = pointLight.attenuation || [ - 1, 0, 0 - ]; - }); - lightSourceUniforms.lighting_uPointLightCount = pointLights.length; - - directionalLights.forEach((directionalLight, index) => { - lightSourceUniforms[`lighting_uDirectionalLight[${index}].color`] = - convertColor(directionalLight); - lightSourceUniforms[`lighting_uDirectionalLight[${index}].direction`] = - directionalLight.direction; - }); - lightSourceUniforms.lighting_uDirectionalLightCount = directionalLights.length; - - return lightSourceUniforms; -} - -// eslint-disable-next-line complexity -function getUniforms(opts: LightsOptions = INITIAL_MODULE_OPTIONS): Record { - // Specify lights separately - 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( - {}, - getLightSourceUniforms({ambientLight, pointLights, directionalLights}), - { - lighting_uEnabled: true - } - ); - } - - // Support for array of lights. Type of light is detected by type field - if ('lights' in opts) { - const lightSources: LightSources = {pointLights: [], directionalLights: []}; - // @ts-expect-error - for (const light of opts.lights || []) { - switch (light.type) { - case 'ambient': - // Note: Only uses last ambient light - // TODO - add ambient light sources on CPU? - lightSources.ambientLight = light; - break; - case 'directional': - lightSources.directionalLights?.push(light); - break; - case 'point': - lightSources.pointLights?.push(light); - break; - default: - // eslint-disable-next-line - // console.warn(light.type); - } - } - - // Call the `opts.lightSources`` version - return getUniforms({lightSources}); - } - - return {}; -} - -/** - * An implementation of PBR (Physically-Based Rendering). - * Physically Based Shading of a microfacet surface defined by a glTF material. - */ -export const lights = { - name: 'lights', - vs: lightingShader, - fs: lightingShader, - getUniforms, - defines: { - // MAX_LIGHTS: 3 - } -}; diff --git a/modules/shadertools/src/modules-webgl1/lighting/pbr/README.md b/modules/shadertools/src/modules-webgl1/lighting/pbr/README.md deleted file mode 100644 index 282acac44b..0000000000 --- a/modules/shadertools/src/modules-webgl1/lighting/pbr/README.md +++ /dev/null @@ -1,12 +0,0 @@ -# PBR (Shader Module) - -An implementation of PBR (Physically-Based Rendering) based on the [Khronos Reference Implementation](https://github.com/KhronosGroup/glTF-WebGL-PBR). - -A reference implementation for Physically Based Shading of a microfacet surface defined by a glTF material. - -References: - -- [Real Shading in Unreal Engine 4](http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf) -- [Physically Based Shading at Disney](http://blog.selfshadow.com/publications/s2012-shading-course/burley/s2012_pbs_disney_brdf_notes_v3.pdf) -- [README.md - Environment Maps](https://github.com/KhronosGroup/glTF-WebGL-PBR/#environment-maps) -- ["An Inexpensive BRDF Model for Physically based Rendering" by Christophe Schlick](https://www.cs.virginia.edu/~jdl/bib/appearance/analytic%20models/schlick94b.pdf) diff --git a/modules/shadertools/src/modules-webgl1/lighting/pbr/pbr-fragment-glsl.ts b/modules/shadertools/src/modules-webgl1/lighting/pbr/pbr-fragment-glsl.ts deleted file mode 100644 index 24384f8d1c..0000000000 --- a/modules/shadertools/src/modules-webgl1/lighting/pbr/pbr-fragment-glsl.ts +++ /dev/null @@ -1,396 +0,0 @@ -// luma.gl -// SPDX-License-Identifier: MIT -// Copyright (c) vis.gl contributors - -// Attribution: -// MIT license, Copyright (c) 2016-2017 Mohamad Moneimne and Contributors - -// This fragment shader defines a reference implementation for Physically Based Shading of -// a microfacet surface material defined by a glTF model. -// - -// TODO - better do the checks outside of shader - -export const fs = /* glsl */ `\ -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; - -// debugging flags used for shader output of intermediate PBR variables -#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 - -// Encapsulate the various inputs used by the various functions in the shading equation -// We store values in this struct to simplify the integration of alternative implementations -// of the shading terms, outlined in the Readme.MD Appendix. -struct PBRInfo -{ - float NdotL; // cos angle between normal and light direction - float NdotV; // cos angle between normal and view direction - float NdotH; // cos angle between normal and half vector - float LdotH; // cos angle between light direction and half vector - float VdotH; // cos angle between view direction and half vector - float perceptualRoughness; // roughness value, as authored by the model creator (input to shader) - float metalness; // metallic value at the surface - vec3 reflectance0; // full reflectance color (normal incidence angle) - vec3 reflectance90; // reflectance color at grazing angle - float alphaRoughness; // roughness mapped to a more linear change in the roughness (proposed by [2]) - vec3 diffuseColor; // color contribution from diffuse lighting - vec3 specularColor; // color contribution from specular lighting - vec3 n; // normal at surface point - vec3 v; // vector from surface point to camera -}; - -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 //SRGB_FAST_APPROXIMATION - 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 //SRGB_FAST_APPROXIMATION - return vec4(linOut,srgbIn.w);; -#else //MANUAL_SRGB - return srgbIn; -#endif //MANUAL_SRGB -} - -// Find the normal for this fragment, pulling either from a predefined normal map -// or from the interpolated mesh normal and tangent attributes. -vec3 getNormal() -{ - // Retrieve the tangent space matrix -#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 // HAS_TANGENTS - 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 - // The tbn matrix is linearly interpolated, so we need to re-normalize - vec3 n = normalize(tbn[2].xyz); -#endif - - return n; -} - -// Calculation of the lighting contribution from an optional Image Based Light source. -// Precomputed Environment Maps are required uniform inputs and are computed as outlined in [1]. -// See our README.md on Environment Maps [3] for additional discussion. -#ifdef USE_IBL -vec3 getIBLContribution(PBRInfo pbrInputs, vec3 n, vec3 reflection) -{ - float mipCount = 9.0; // resolution of 512x512 - float lod = (pbrInputs.perceptualRoughness * mipCount); - // retrieve a scale and bias to F0. See [1], Figure 3 - 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); - - // For presentation, this allows us to disable IBL terms - diffuse *= u_ScaleIBLAmbient.x; - specular *= u_ScaleIBLAmbient.y; - - return diffuse + specular; -} -#endif - -// Basic Lambertian diffuse -// Implementation from Lambert's Photometria https://archive.org/details/lambertsphotome00lambgoog -// See also [1], Equation 1 -vec3 diffuse(PBRInfo pbrInputs) -{ - return pbrInputs.diffuseColor / M_PI; -} - -// The following equation models the Fresnel reflectance term of the spec equation (aka F()) -// Implementation of fresnel from [4], Equation 15 -vec3 specularReflection(PBRInfo pbrInputs) -{ - return pbrInputs.reflectance0 + - (pbrInputs.reflectance90 - pbrInputs.reflectance0) * - pow(clamp(1.0 - pbrInputs.VdotH, 0.0, 1.0), 5.0); -} - -// This calculates the specular geometric attenuation (aka G()), -// where rougher material will reflect less light back to the viewer. -// This implementation is based on [1] Equation 4, and we adopt their modifications to -// alphaRoughness as input as originally proposed in [2]. -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; -} - -// The following equation(s) model the distribution of microfacet normals across -// the area being drawn (aka D()) -// Implementation from "Average Irregularity Representation of a Roughened Surface -// for Ray Reflection" by T. S. Trowbridge, and K. P. Reitz -// Follows the distribution function recommended in the SIGGRAPH 2013 course notes -// from EPIC Games [1], Equation 3. -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); // Vector from surface point to light - vec3 h = normalize(l+v); // Half vector between both l and 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) { - // Calculate the shading terms for the microfacet specular shading model - vec3 F = specularReflection(pbrInputs); - float G = geometricOcclusion(pbrInputs); - float D = microfacetDistribution(pbrInputs); - - // Calculation of analytical lighting contribution - vec3 diffuseContrib = (1.0 - F) * diffuse(pbrInputs); - vec3 specContrib = F * G * D / (4.0 * pbrInputs.NdotL * pbrInputs.NdotV); - // Obtain final intensity as reflectance (BRDF) scaled by the energy of the light (cosine law) - return pbrInputs.NdotL * lightColor * (diffuseContrib + specContrib); -} - -vec4 pbr_filterColor(vec4 colorUnused) -{ - // The albedo may be defined from a base texture or a flat color -#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{ - // Metallic and Roughness material properties are packed together - // In glTF, these factors can be specified by fixed scalar values - // or from a metallic-roughness map - float perceptualRoughness = u_MetallicRoughnessValues.y; - float metallic = u_MetallicRoughnessValues.x; -#ifdef HAS_METALROUGHNESSMAP - // Roughness is stored in the 'g' channel, metallic is stored in the 'b' channel. - // This layout intentionally reserves the 'r' channel for (optional) occlusion map data - 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); - // Roughness is authored as perceptual roughness; as is convention, - // convert to material roughness by squaring the perceptual roughness [2]. - 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); - - // Compute reflectance. - float reflectance = max(max(specularColor.r, specularColor.g), specularColor.b); - - // For typical incident reflectance range (between 4% to 100%) set the grazing - // reflectance to 100% for typical fresnel effect. - // For very low reflectance range on highly diffuse objects (below 4%), - // incrementally reduce grazing reflecance to 0%. - 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(); // normal at surface point - vec3 v = normalize(u_Camera - pbr_vPosition); // Vector from surface point to camera - - float NdotV = clamp(abs(dot(n, v)), 0.001, 1.0); - vec3 reflection = -normalize(reflect(v, n)); - - PBRInfo pbrInputs = PBRInfo( - 0.0, // NdotL - NdotV, - 0.0, // NdotH - 0.0, // LdotH - 0.0, // VdotH - perceptualRoughness, - metallic, - specularEnvironmentR0, - specularEnvironmentR90, - alphaRoughness, - diffuseColor, - specularColor, - n, - v - ); - -#ifdef USE_LIGHTS - // Apply ambient light - PBRInfo_setAmbientLight(pbrInputs); - color += calculateFinalColor(pbrInputs, lighting_uAmbientLight.color); - - // Apply directional light - 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); - } - } - - // Apply point light - 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 - - // Calculate lighting contribution from image based lighting source (IBL) -#ifdef USE_IBL - color += getIBLContribution(pbrInputs, n, reflection); -#endif - - // Apply optional PBR terms for additional (optional) shading -#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 - - // This section uses mix to override final color for reference app visualization - // of various parameters in the lighting equation. -#ifdef PBR_DEBUG - // TODO: Figure out how to debug multiple lights - - // color = mix(color, F, u_ScaleFGDSpec.x); - // color = mix(color, vec3(G), u_ScaleFGDSpec.y); - // color = mix(color, vec3(D), u_ScaleFGDSpec.z); - // color = mix(color, specContrib, u_ScaleFGDSpec.w); - - // color = mix(color, diffuseContrib, u_ScaleDiffBaseMR.x); - 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); -} -`; diff --git a/modules/shadertools/src/modules-webgl1/lighting/pbr/pbr-vertex-glsl.ts b/modules/shadertools/src/modules-webgl1/lighting/pbr/pbr-vertex-glsl.ts deleted file mode 100644 index 813bc800f7..0000000000 --- a/modules/shadertools/src/modules-webgl1/lighting/pbr/pbr-vertex-glsl.ts +++ /dev/null @@ -1,43 +0,0 @@ -// luma.gl -// SPDX-License-Identifier: MIT -// Copyright (c) vis.gl contributors - -export const vs = /* glsl */ `\ -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 // HAS_TANGENTS != 1 - 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 -} -`; diff --git a/modules/shadertools/src/modules-webgl1/lighting/pbr/pbr.ts b/modules/shadertools/src/modules-webgl1/lighting/pbr/pbr.ts deleted file mode 100644 index 48aad2c699..0000000000 --- a/modules/shadertools/src/modules-webgl1/lighting/pbr/pbr.ts +++ /dev/null @@ -1,23 +0,0 @@ -// luma.gl -// SPDX-License-Identifier: MIT -// Copyright (c) vis.gl contributors - -import {lights} from '../lights/lights'; - -import {vs} from './pbr-vertex-glsl'; -import {fs} from './pbr-fragment-glsl'; - -/** - * An implementation of PBR (Physically-Based Rendering). - * Physically Based Shading of a microfacet surface defined by a glTF material. - */ -export const pbr = { - name: 'pbr', - vs, - fs, - defines: { - LIGHTING_FRAGMENT: true - }, - dependencies: [lights], - getUniforms: (props: any) => props -}; diff --git a/modules/shadertools/src/modules-webgl1/lighting/phong-lighting/phong-lighting-glsl.ts b/modules/shadertools/src/modules-webgl1/lighting/phong-lighting/phong-lighting-glsl.ts deleted file mode 100644 index 6916bd978e..0000000000 --- a/modules/shadertools/src/modules-webgl1/lighting/phong-lighting/phong-lighting-glsl.ts +++ /dev/null @@ -1,79 +0,0 @@ -// luma.gl -// SPDX-License-Identifier: MIT -// Copyright (c) vis.gl contributors - -export const lightingShader = /* glsl */ `\ - -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; -} -`; diff --git a/modules/shadertools/src/modules-webgl1/lighting/phong-lighting/phong-lighting.ts b/modules/shadertools/src/modules-webgl1/lighting/phong-lighting/phong-lighting.ts deleted file mode 100644 index fd5d2b931a..0000000000 --- a/modules/shadertools/src/modules-webgl1/lighting/phong-lighting/phong-lighting.ts +++ /dev/null @@ -1,64 +0,0 @@ -// luma.gl -// SPDX-License-Identifier: MIT -// Copyright (c) vis.gl contributors - -import {lights} from '../lights/lights'; -import {lightingShader} from './phong-lighting-glsl'; - -/* eslint-disable camelcase */ - -export type PhongLightingProps = { - ambient?: number; - diffuse?: number; - shininess?: number; - specularColor?: [number, number, number]; -}; - -const INITIAL_MODULE_OPTIONS: {material?: PhongLightingProps} = {}; - -function getMaterialUniforms(material: PhongLightingProps) { - 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 getUniforms( - opts: {material?: PhongLightingProps} = INITIAL_MODULE_OPTIONS -): Record { - if (!('material' in opts)) { - return {}; - } - - const {material} = opts; - - if (!material) { - return {lighting_uEnabled: false}; - } - - return getMaterialUniforms(material); -} - -export const gouraudLighting = { - name: 'gouraud-lighting', - dependencies: [lights], - vs: lightingShader, - defines: { - LIGHTING_VERTEX: 1 - }, - getUniforms -}; - -export const phongLighting = { - name: 'phong-lighting', - dependencies: [lights], - fs: lightingShader, - defines: { - LIGHTING_FRAGMENT: 1 - }, - getUniforms -}; diff --git a/modules/shadertools/src/modules-webgl1/math/fp64/fp64-arithmetic-glsl.ts b/modules/shadertools/src/modules-webgl1/math/fp64/fp64-arithmetic-glsl.ts deleted file mode 100644 index c4ab0bbf63..0000000000 --- a/modules/shadertools/src/modules-webgl1/math/fp64/fp64-arithmetic-glsl.ts +++ /dev/null @@ -1,171 +0,0 @@ -// luma.gl -// SPDX-License-Identifier: MIT -// Copyright (c) vis.gl contributors - -export const fp64arithmeticShader = /* glsl */ `\ -uniform float ONE; - -/* -About LUMA_FP64_CODE_ELIMINATION_WORKAROUND - -The purpose of this workaround is to prevent shader compilers from -optimizing away necessary arithmetic operations by swapping their sequences -or transform the equation to some 'equivalent' form. - -The method is to multiply an artifical variable, ONE, which will be known to -the compiler to be 1 only at runtime. The whole expression is then represented -as a polynomial with respective to ONE. In the coefficients of all terms, only one a -and one b should appear - -err = (a + b) * ONE^6 - a * ONE^5 - (a + b) * ONE^4 + a * ONE^3 - b - (a + b) * ONE^2 + a * ONE -*/ - -// Divide float number to high and low floats to extend fraction bits -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); -} - -// Divide float number again when high float uses too many fraction bits -vec2 split2(vec2 a) { - vec2 b = split(a.x); - b.y += a.y; - return b; -} - -// Special sum operation when a > 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); -} - -// General sum operation -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); - // y component is for the error - 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 -} -`; diff --git a/modules/shadertools/src/modules-webgl1/math/fp64/fp64-functions-glsl.ts b/modules/shadertools/src/modules-webgl1/math/fp64/fp64-functions-glsl.ts deleted file mode 100644 index a75eebb78a..0000000000 --- a/modules/shadertools/src/modules-webgl1/math/fp64/fp64-functions-glsl.ts +++ /dev/null @@ -1,675 +0,0 @@ -// luma.gl -// SPDX-License-Identifier: MIT -// Copyright (c) vis.gl contributors - -export const fp64functionShader = /* glsl */ `\ -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); // 1/3! -const vec2 INVERSE_FACTORIAL_4_FP64 = vec2(4.16666679084301e-02, -1.2417634698280722e-09); // 1/4! -const vec2 INVERSE_FACTORIAL_5_FP64 = vec2(8.333333767950535e-03, -4.34617203337595e-10); // 1/5! -const vec2 INVERSE_FACTORIAL_6_FP64 = vec2(1.3888889225199819e-03, -3.3631094437103215e-11); // 1/6! -const vec2 INVERSE_FACTORIAL_7_FP64 = vec2(1.9841270113829523e-04, -2.725596874933456e-12); // 1/7! -const vec2 INVERSE_FACTORIAL_8_FP64 = vec2(2.4801587642286904e-05, -3.406996025904184e-13); // 1/8! -const vec2 INVERSE_FACTORIAL_9_FP64 = vec2(2.75573188446287533e-06, 3.7935713937038186e-14); // 1/9! -const vec2 INVERSE_FACTORIAL_10_FP64 = vec2(2.755731998149713e-07, -7.575112367869873e-15); // 1/10! - -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; -} - -/* k_power controls how much range reduction we would like to have -Range reduction uses the following method: -assume a = k_power * r + m * log(2), k and m being integers. -Set k_power = 4 (we can choose other k to trade accuracy with performance. -we only need to calculate exp(r) and using exp(a) = 2^m * exp(r)^k_power; -*/ - -vec2 exp_fp64(vec2 a) { - // We need to make sure these two numbers match - // as bit-wise shift is not available in GLSL 1.0 - 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); - // p = mul_fp64(p, r); - // t = mul_fp64(p, INVERSE_FACTORIAL_6_FP64); - - // s = sum_fp64(s, t); - // p = mul_fp64(p, r); - // t = mul_fp64(p, INVERSE_FACTORIAL_7_FP64); - - s = sum_fp64(s, t); - - - // At this point, s = exp(r) - 1; but after following 4 recursions, we will get exp(r) ^ 512 - 1. - 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); -// return r; -} - -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); - - /* keep the following commented code in case we need them - for extra accuracy from the Taylor expansion*/ - - // r = mul_fp64(r, x); - // t = mul_fp64(r, INVERSE_FACTORIAL_7_FP64); - // s = sum_fp64(s, t); - - // r = mul_fp64(r, x); - // t = mul_fp64(r, INVERSE_FACTORIAL_9_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); - - /* keep the following commented code in case we need them - for extra accuracy from the Taylor expansion*/ - - // r = mul_fp64(r, x); - // t = mul_fp64(r, INVERSE_FACTORIAL_8_FP64); - // s = sum_fp64(s, t); - - // r = mul_fp64(r, x); - // t = mul_fp64(r, INVERSE_FACTORIAL_10_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); - } - - // 2pi range reduction - 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); - } - - // 2pi range reduction - 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); - } - - // 2pi range reduction - 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))); - - // We just can't get PI/16 * 3.0 very accurately. - // so let's just store it - 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))); -} - -// Vector functions -// vec2 functions -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]); -} - -// vec3 functions -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); -} - -// vec4 functions -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]); - } -} -`; diff --git a/modules/shadertools/src/modules-webgl1/math/fp64/fp64.ts b/modules/shadertools/src/modules-webgl1/math/fp64/fp64.ts deleted file mode 100644 index f3fc21bc52..0000000000 --- a/modules/shadertools/src/modules-webgl1/math/fp64/fp64.ts +++ /dev/null @@ -1,44 +0,0 @@ -// luma.gl -// SPDX-License-Identifier: MIT -// Copyright (c) vis.gl contributors - -import {fp64ify, fp64LowPart, fp64ifyMatrix4} from '../../../modules/math/fp64/fp64-utils'; - -import {fp64arithmeticShader} from './fp64-arithmetic-glsl'; -import {fp64functionShader} from './fp64-functions-glsl'; - -const CONST_UNIFORMS = { - // Used in LUMA_FP64_CODE_ELIMINATION_WORKAROUND - ONE: 1.0 -}; -export {fp64ify, fp64LowPart, fp64ifyMatrix4}; - -function getUniforms() { - return CONST_UNIFORMS; -} - -/** - * 64bit arithmetic: add, sub, mul, div (small subset of fp64 module) - */ -export const fp64arithmetic = { - name: 'fp64-arithmetic', - vs: fp64arithmeticShader, - getUniforms, - fp64ify, - fp64LowPart, - fp64ifyMatrix4 -}; - -/** - * Full 64 bit math library - */ -export const fp64 = { - name: 'fp64', - vs: fp64functionShader, - dependencies: [fp64arithmetic], - - // Additional Functions - fp64ify, - fp64LowPart, - fp64ifyMatrix4 -}; diff --git a/modules/shadertools/src/modules-webgl1/project/README.md b/modules/shadertools/src/modules-webgl1/project/README.md deleted file mode 100644 index 33506dc4dd..0000000000 --- a/modules/shadertools/src/modules-webgl1/project/README.md +++ /dev/null @@ -1,52 +0,0 @@ -# Shader Module: Project - -A basic projection module. - -Makes it easy to ensure a set of shaders all use the same uniforms when -calculating positions. - -## Parameters - -`getUniforms` take the following parameters when the `picking` module is -included. - -- `projection` (Array[16], false) - -- `view` (Array[16], identity) - - -## Vertex Shader Functions - -### `vec4 project_toClipspace(vec4 point)` - -The most frequently used project operation. - -- `point` (`vec3`) - Projects a point to clipspace - -Example: - -``` -// A "minimal" vertex shader -void main(void) { - gl_Position = project_toClipspace(position); -} -``` - -## Fragment Shader Functions - -The same functions that are available to the vertex shader are also available -to the fragment shader. This is intended to support e.g. lighting calculations -in the fragment shader. - -## Remove - -// camera and object matrices -uniform mat4 viewMatrix; -uniform mat4 viewInverseMatrix; -uniform mat4 projectionMatrix; -uniform mat4 viewProjectionMatrix; - -// objectMatrix * viewMatrix = worldMatrix -uniform mat4 worldMatrix; -uniform mat4 worldInverseMatrix; -uniform mat4 worldInverseTransposeMatrix; -uniform mat4 objectMatrix; -uniform vec3 cameraPosition; diff --git a/modules/shadertools/src/modules-webgl1/project/project.ts b/modules/shadertools/src/modules-webgl1/project/project.ts deleted file mode 100644 index eb6af958c7..0000000000 --- a/modules/shadertools/src/modules-webgl1/project/project.ts +++ /dev/null @@ -1,135 +0,0 @@ -// luma.gl -// SPDX-License-Identifier: MIT -// Copyright (c) vis.gl contributors - -import {Vector3, Matrix4} from '@math.gl/core'; -import {ShaderModule} from '../../lib/shader-module/shader-module'; -import type {NumberArray3, NumberArray16} from '@math.gl/core'; - -type ProjectionProps = { - modelMatrix?: Readonly; - viewMatrix?: Readonly; - projectionMatrix?: Readonly; - cameraPositionWorld?: Readonly; -}; - -const IDENTITY_MATRIX: NumberArray16 = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]; - -const DEFAULT_MODULE_OPTIONS: ProjectionProps = { - modelMatrix: IDENTITY_MATRIX, - viewMatrix: IDENTITY_MATRIX, - projectionMatrix: IDENTITY_MATRIX, - cameraPositionWorld: [0, 0, 0] -}; - -function getUniforms(opts: ProjectionProps = DEFAULT_MODULE_OPTIONS, prevUniforms = {}) { - // const viewProjectionInverse = viewProjection.invert(); - // viewInverseMatrix: view.invert(), - // viewProjectionInverseMatrix: viewProjectionInverse - - const uniforms: Record = {}; - if (opts.modelMatrix !== undefined) { - uniforms.modelMatrix = opts.modelMatrix; - } - if (opts.viewMatrix !== undefined) { - uniforms.viewMatrix = opts.viewMatrix; - } - if (opts.projectionMatrix !== undefined) { - uniforms.projectionMatrix = opts.projectionMatrix; - } - if (opts.cameraPositionWorld !== undefined) { - uniforms.cameraPositionWorld = opts.cameraPositionWorld; - } - - // COMPOSITE UNIFORMS - if (opts.projectionMatrix !== undefined && opts.viewMatrix !== undefined) { - uniforms.viewProjectionMatrix = new Matrix4(opts.projectionMatrix).multiplyRight( - opts.viewMatrix - ); - } - - return uniforms; -} - -const common = /* glsl */ `\ -varying vec4 project_vPositionWorld; -varying vec3 project_vNormalWorld; - -vec4 project_getPosition_World() { - return project_vPositionWorld; -} - -vec3 project_getNormal_World() { - return project_vNormalWorld; -} -`; - -const vs = `\ -${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.); -} -`; - -const fs = ` -${common}\ -`; - -/** - * Projects coordinates - */ -export const project = { - name: 'project', - getUniforms, - vs, - fs -} as const satisfies ShaderModule; diff --git a/modules/shadertools/test/index.ts b/modules/shadertools/test/index.ts index fc1ddbcda0..9b46e175ea 100644 --- a/modules/shadertools/test/index.ts +++ b/modules/shadertools/test/index.ts @@ -41,22 +41,11 @@ import './modules/modules.spec'; import './modules/utils/random.spec'; // Lighting -import './modules/lighting/dirlight.spec'; // import './modules/lights/lights.spec'; +import './modules/lighting/dirlight.spec'; import './modules/lighting/phong-material.spec'; import './modules/lighting/gouraud-material.spec'; +// import './modules/lighting/pbr-material.spec'; // Engine import './modules/engine/picking.spec'; - -// Tests for V8 shader modules - -// Math modules -// TODO - these are breaking in test-browser but not in test-headless?? -// import './modules-webgl1/fp64/fp64-arithmetic-transform.spec'; - -// Light and picking -// import './modules-webgl1/dirlight/dirlight.spec'; -import './modules-webgl1/lights/lights.spec'; -// import './modules-webgl1/phong-lighting/phong-lighting.spec'; -// import './modules-webgl1/picking/picking.spec'; diff --git a/modules/shadertools/test/lib/shader-assembly/assemble-shaders.spec.ts b/modules/shadertools/test/lib/shader-assembly/assemble-shaders.spec.ts index aaa88c7a41..ad11d7a984 100644 --- a/modules/shadertools/test/lib/shader-assembly/assemble-shaders.spec.ts +++ b/modules/shadertools/test/lib/shader-assembly/assemble-shaders.spec.ts @@ -5,7 +5,13 @@ import test from 'tape-promise/tape'; import {Device} from '@luma.gl/core'; import {getWebGLTestDevice} from '@luma.gl/test-utils'; -import {assembleGLSLShaderPair, picking, fp64, pbr, PlatformInfo} from '@luma.gl/shadertools'; +import { + assembleGLSLShaderPair, + picking, + fp64, + pbrMaterial, + PlatformInfo +} from '@luma.gl/shadertools'; import type {WebGLDevice} from '@luma.gl/webgl'; import {isBrowser} from '@probe.gl/env'; @@ -609,7 +615,7 @@ test.skip('assembleGLSLShaderPair#transpilation', async t => { platformInfo: getInfo(webglDevice), vs: VS_GLSL_300_GLTF, fs: FS_GLSL_300_GLTF, - modules: [pbr] + modules: [pbrMaterial] }); t.ok( diff --git a/modules/shadertools/test/modules-webgl1/fp64/fp64-arithmetic-transform.spec.ts b/modules/shadertools/test/modules-webgl1/fp64/fp64-arithmetic-transform.spec.ts deleted file mode 100644 index 7296fffb2f..0000000000 --- a/modules/shadertools/test/modules-webgl1/fp64/fp64-arithmetic-transform.spec.ts +++ /dev/null @@ -1,153 +0,0 @@ -// luma.gl -// SPDX-License-Identifier: MIT -// Copyright (c) vis.gl contributors - -import test from 'tape-promise/tape'; -import {getWebGLTestDevice} from '@luma.gl/test-utils'; -import {runTests} from './fp64-test-utils-transform'; - -// Failing test cases are ignored based on gpu and glslFunc, using ignoreFor field -// ignoreFor: [{gpu: ['glslFunc-1', 'glslFunc-2']}] => ignores for `'glslFunc-1' and 'glslFunc-2` when running on `gpu` -// Many of these tests fail on Apple GPUs with very large margins, see https://github.com/visgl/luma.gl/issues/1764. -const commonTestCases = [ - {a: 2, b: 2}, - {a: 0.1, b: 0.1, ignoreFor: {apple: ['sum_fp64', 'mul_fp64', 'div_fp64']}}, - {a: 3.0e-19, b: 3.3e13, ignoreFor: {apple: ['sum_fp64', 'sub_fp64']}}, - {a: 9.9e-40, b: 1.7e3, ignoreFor: {}}, - {a: 1.5e-36, b: 1.7e-16, ignoreFor: {}}, - {a: 9.4e-26, b: 51, ignoreFor: {}}, - {a: 6.7e-20, b: 0.93, ignoreFor: {apple: ['sum_fp64', 'sub_fp64']}}, - - // mul_fp64: Large numbers once multipled, can't be represented by 32 bit precision and Math.fround() returns NAN - // sqrt_fp64: Fail on INTEL with margin 3.906051071870294e-12 - { - a: 2.4e3, - b: 5.9e31, - ignoreFor: {all: ['mul_fp64'], intel: ['sqrt_fp64'], apple: ['sum_fp64', 'sub_fp64']} - }, - - // div_fp64 fails on INTEL with margin 1.7318642528355118e-12 - // sqrt_fp64 fails on INTEL with margin 1.5518878351528786e-12 - { - a: 1.4e9, - b: 6.3e5, - ignoreFor: {intel: ['div_fp64', 'sqrt_fp64'], apple: ['mul_fp64', 'div_fp64']} - }, - - // div fails on INTEL with margin 1.7886288892678105e-14 - // sqrt fails on INTEL with margin 2.5362810256331708e-12 - {a: 3.0e9, b: 4.3e-23, ignoreFor: {intel: ['div_fp64', 'sqrt_fp64'], apple: ['div_fp64']}}, - - // div fail on INTEL with margin 1.137354350370519e-12 - {a: 1.7e-19, b: 2.7e-27, ignoreFor: {intel: ['div_fp64'], apple: ['div_fp64']}}, - - // div_fp64 fails on INTEL with margin 2.7291999999999997e-12 - // sqrt_fp64 fails on INTEL with margin 3.501857471494295e-12 - {a: 0.3, b: 3.2e-16, ignoreFor: {intel: ['div_fp64', 'sqrt_fp64'], apple: ['div_fp64']}}, - - // mul_fp64 : fails since result can't be represented by 32 bit floats - // div_fp64 : fails on INTEL with margin 1.9999999999999994e-15 - // sqrt_fp64 : fails on INTEL with margin 1.832115697751484e-12 - { - a: 4.1e30, - b: 8.2e15, - ignoreFor: {all: ['mul_fp64'], intel: ['div_fp64', 'sqrt_fp64'], apple: ['div_fp64']} - }, - - // Fails on INTEL, margin 3.752606081210107e-12 - { - a: 6.2e3, - b: 6.3e10, - ignoreFor: {intel: ['sqrt_fp64'], apple: ['sum_fp64', 'mul_fp64', 'sub_fp64']} - }, - // Fails on INTEL, margin 3.872578286363912e-13 - {a: 2.5e2, b: 5.1e-21, ignoreFor: {intel: ['sqrt_fp64'], apple: ['div_fp64']}}, - // Fails on INTEL, margin 1.5332142001740705e-12 - {a: 96, b: 1.7e4, ignoreFor: {intel: ['sqrt_fp64'], apple: ['div_fp64']}}, - // // Fail on INTEL, margin 1.593162047558726e-12 - { - a: 0.27, - b: 2.3e16, - ignoreFor: {intel: ['sqrt_fp64'], apple: ['sum_fp64', 'mul_fp64', 'sub_fp64']} - }, - // Fails on INTEL, margin 1.014956357028767e-12 - {a: 18, b: 9.1e-9, ignoreFor: {intel: ['sqrt_fp64'], apple: ['div_fp64']}} -]; - -// Filter all tests cases based on current gpu and glsFunc -function getTestCasesFor(device, glslFunc) { - const debugInfo = device.info; - const testCases = commonTestCases.filter(testCase => { - if (testCase.ignoreFor) { - for (const gpu in testCase.ignoreFor) { - if ( - (gpu === 'all' || debugInfo.vendor.toLowerCase().indexOf(gpu) >= 0) && - testCase.ignoreFor[gpu].includes(glslFunc) - ) { - return false; - } - } - } - return true; - }); - return testCases; -} - -test('fp64#sum_fp64', async t => { - const webglDevice = await getWebGLTestDevice(); - - const glslFunc = 'sum_fp64'; - const testCases = getTestCasesFor(webglDevice, glslFunc); - await runTests(webglDevice, {glslFunc, binary: true, op: (a, b) => a + b, testCases, t}); - t.end(); -}); - -test('fp64#sub_fp64', async t => { - const webglDevice = await getWebGLTestDevice(); - - const glslFunc = 'sub_fp64'; - const testCases = getTestCasesFor(webglDevice, glslFunc); - await runTests(webglDevice, {glslFunc, binary: true, op: (a, b) => a - b, testCases, t}); - t.end(); -}); - -test('fp64#mul_fp64', async t => { - const webglDevice = await getWebGLTestDevice(); - - const glslFunc = 'mul_fp64'; - const testCases = getTestCasesFor(webglDevice, glslFunc); - await runTests(webglDevice, { - glslFunc, - binary: true, - op: (a, b) => a * b, - limit: 128, - testCases, - t - }); - t.end(); -}); - -test('fp64#div_fp64', async t => { - const webglDevice = await getWebGLTestDevice(); - - const glslFunc = 'div_fp64'; - const testCases = getTestCasesFor(webglDevice, glslFunc); - await runTests(webglDevice, { - glslFunc, - binary: true, - op: (a, b) => a / b, - limit: 128, - testCases, - t - }); - t.end(); -}); - -test('fp64#sqrt_fp64', async t => { - const webglDevice = await getWebGLTestDevice(); - - const glslFunc = 'sqrt_fp64'; - const testCases = getTestCasesFor(webglDevice, glslFunc); - await runTests(webglDevice, {glslFunc, op: a => Math.sqrt(a), limit: 128, testCases, t}); - t.end(); -}); diff --git a/modules/shadertools/test/modules-webgl1/fp64/fp64-test-utils-transform.ts b/modules/shadertools/test/modules-webgl1/fp64/fp64-test-utils-transform.ts deleted file mode 100644 index ab54be6115..0000000000 --- a/modules/shadertools/test/modules-webgl1/fp64/fp64-test-utils-transform.ts +++ /dev/null @@ -1,130 +0,0 @@ -// luma.gl -// SPDX-License-Identifier: MIT -// Copyright (c) vis.gl contributors - -// Special utility functions for df64 tests - -/* eslint-disable camelcase, prefer-template, max-len */ - -import {Device} from '@luma.gl/core'; -import {BufferTransform} from '@luma.gl/engine'; -import {fp64} from '@luma.gl/shadertools'; -import {equals, config} from '@math.gl/core'; -const {fp64ify} = fp64; - -// Use 'invariant' specifier to work around some issues on Apple GPUs. The -// specifier may or may not have an effect, depending on the browser and the -// ANGLE backend, but it's an improvement when it's supported. -// See: https://github.com/visgl/luma.gl/issues/1764 - -function getBinaryShader(operation: string): string { - const shader = `\ -#version 300 es -in vec2 a; -in vec2 b; -invariant out vec2 result; -void main(void) { - result = ${operation}(a, b); -} -`; - return shader; -} - -function getUnaryShader(operation: string): string { - return `\ -#version 300 es -in vec2 a; -in vec2 b; -invariant out vec2 result; -void main(void) { - result = ${operation}(a); -} -`; -} - -config.EPSILON = 1e-11; - -function setupFloatData({limit, op, testCases}) { - const count = testCases.length; - const a_fp64 = new Float32Array(count * 2); - const b_fp64 = new Float32Array(count * 2); - const expected_fp64 = new Float32Array(count * 2); - const a = new Array(count); - const b = new Array(count); - const expected = new Array(count); - for (let idx = 0; idx < count; idx++) { - const index = idx * 2; - a[idx] = testCases[idx].a; - b[idx] = testCases[idx].b; - expected[idx] = op(a[idx], b[idx]); - - fp64ify(a[idx], a_fp64, index); - fp64ify(b[idx], b_fp64, index); - fp64ify(expected[idx], expected_fp64, index); - } - return {a, b, expected, a_fp64, b_fp64, expected_fp64}; -} - -function setupFloatTest(device: Device, {glslFunc, binary = false, limit = 256, op, testCases}) { - const {a, b, expected, a_fp64, b_fp64, expected_fp64} = setupFloatData({limit, op, testCases}); - const vs = binary ? getBinaryShader(glslFunc) : getUnaryShader(glslFunc); - const bufferA = device.createBuffer({data: a_fp64}); - const bufferB = device.createBuffer({data: b_fp64}); - const bufferResult = device.createBuffer({byteLength: a_fp64.byteLength}); - const transform = new BufferTransform(device, { - vs, - modules: [fp64], - attributes: {a: bufferA, b: bufferB}, - bufferLayout: [ - {name: 'a', format: 'float32x2'}, - {name: 'b', format: 'float32x2'} - ], - feedbackBuffers: {result: bufferResult}, - outputs: ['result'], - vertexCount: testCases.length - }); - return {a, b, expected, a_fp64, b_fp64, expected_fp64, transform}; -} - -export async function runTests( - device: Device, - {glslFunc, binary = false, op, limit = 256, testCases, t} -) { - if (!BufferTransform.isSupported(device)) { - t.comment('Transform not supported, skipping tests'); - t.end(); - return; - } - - const {a, b, a_fp64, b_fp64, expected_fp64, transform} = setupFloatTest(device, { - glslFunc, - binary, - op, - limit, - testCases - }); - - // transform.model.setUniformsWebGL(fp64arithmetic.getUniforms()); - transform.run(); - - const {buffer, byteOffset, byteLength} = await transform.readAsync('result'); - const gpuResult = new Float32Array( - buffer, - byteOffset, - byteLength / Float32Array.BYTES_PER_ELEMENT - ); - for (let idx = 0; idx < testCases.length; idx++) { - const reference64 = expected_fp64[2 * idx] + expected_fp64[2 * idx + 1]; - const result64 = gpuResult[2 * idx] + gpuResult[2 * idx + 1]; - - const args = binary - ? `(${a[idx].toPrecision(2)}, ${b[idx].toPrecision(2)})` - : `(${a[idx].toPrecision(2)})`; - const message = `${glslFunc}${args} error within tolerance`; - const isEqual = equals(reference64, result64); - t.ok(isEqual, message); - if (!isEqual) { - t.comment(` (tested ${a_fp64.toString()}, ${b_fp64.toString()})`); - } - } -} diff --git a/modules/shadertools/test/modules-webgl1/fp64/test/fp64-arithmetic.spec.js.disabled b/modules/shadertools/test/modules-webgl1/fp64/test/fp64-arithmetic.spec.js.disabled deleted file mode 100644 index 71f8c1892a..0000000000 --- a/modules/shadertools/test/modules-webgl1/fp64/test/fp64-arithmetic.spec.js.disabled +++ /dev/null @@ -1,28 +0,0 @@ -// luma.gl -// SPDX-License-Identifier: MIT -// Copyright (c) vis.gl contributors - -// Actual tests for different arithmetic functions - -import test from 'tape-promise/tape'; -import {testcase, gl} from './fp64-test-utils'; - -test('fp64#sum_fp64', (t) => { - testcase(gl, {glslFunc: 'sum_fp64', binary: true, op: (a, b) => a + b, t}); -}); - -test('fp64#sub_fp64', (t) => { - testcase(gl, {glslFunc: 'sub_fp64', binary: true, op: (a, b) => a - b, t}); -}); - -test('fp64#mul_fp64', (t) => { - testcase(gl, {glslFunc: 'mul_fp64', binary: true, op: (a, b) => a * b, limit: 128, t}); -}); - -test('fp64#div_fp64', (t) => { - testcase(gl, {glslFunc: 'div_fp64', binary: true, op: (a, b) => a / b, limit: 128, t}); -}); - -test('fp64#sqrt_fp64', (t) => { - testcase(gl, {glslFunc: 'sqrt_fp64', binary: false, op: (a) => Math.sqrt(a), limit: 128, t}); -}); diff --git a/modules/shadertools/test/modules-webgl1/fp64/test/fp64-functions.spec.js.disabled b/modules/shadertools/test/modules-webgl1/fp64/test/fp64-functions.spec.js.disabled deleted file mode 100644 index 15e04ae85d..0000000000 --- a/modules/shadertools/test/modules-webgl1/fp64/test/fp64-functions.spec.js.disabled +++ /dev/null @@ -1,41 +0,0 @@ -// luma.gl -// SPDX-License-Identifier: MIT -// Copyright (c) vis.gl contributors - -// Tests for fp64 analytic functions -// TODO - enable these - -/* -import test from 'tape-promise/tape'; -import {testcase, gl} from './fp64-test-utils'; - -addSpan('------------------------', di); -for (let idx0 = 0; idx0 < ITERATIONS; idx0++) { - testcase({gl, func: test_float_exp, title: 'Float exp test', t}); -} - -addSpan('------------------------', di); -for (let idx0 = 0; idx0 < ITERATIONS; idx0++) { - testcase({gl, func: test_float_log, title: 'Float log test', t}); -} - -addSpan('------------------------', di); -for (let idx0 = 0; idx0 < ITERATIONS; idx0++) { - testcase({gl, func: test_float_sin, title: 'Float sin test', t}); -} - -addSpan('------------------------', di); -for (let idx0 = 0; idx0 < ITERATIONS; idx0++) { - testcase({gl, func: test_float_cos, title: 'Float cos test', t}); -} - -addSpan('------------------------', di); -for (let idx0 = 0; idx0 < ITERATIONS; idx0++) { - testcase({gl, func: test_float_tan, title: 'Float tan test', t}); -} - -addSpan('------------------------', di); -for (let idx0 = 0; idx0 < ITERATIONS; idx0++) { - testcase({gl, func: test_float_radians, title: 'Float radians test', t}); -} -*/ diff --git a/modules/shadertools/test/modules-webgl1/fp64/test/fp64-test-utils.js.disabled b/modules/shadertools/test/modules-webgl1/fp64/test/fp64-test-utils.js.disabled deleted file mode 100644 index ac2604f4bf..0000000000 --- a/modules/shadertools/test/modules-webgl1/fp64/test/fp64-test-utils.js.disabled +++ /dev/null @@ -1,146 +0,0 @@ -// luma.gl -// SPDX-License-Identifier: MIT -// Copyright (c) vis.gl contributors - -// Special utility functions for df64 tests - -/* eslint-disable camelcase, prefer-template, max-len */ - -import {assembleShaders, fp64} from '@luma.gl/shadertools'; -import { - initializeGL, - initializeTexTarget, - render, - getGPUOutput -} from '@luma.gl/shadertools/test/gpu-test-utils'; - -const BUFFER_DATA = new Float32Array([1, 1, -1, 1, 1, -1, -1, -1]); - -function fp64ify(a) { - const hi = Math.fround(a); - const lo = a - Math.fround(a); - return new Float32Array([hi, lo]); -} - -function getFloat64(upper = 256) { - return Math.random() * Math.pow(2.0, (Math.random() - 0.5) * upper); -} - -export function getRelativeError64(result, reference) { - const reference64 = reference[0] + reference[1]; - const result64 = result[0] + result[1]; - // When refrence valu is < 1, dividing with it increases total value of difference. - if (reference64 < 1) { - return Math.abs(reference64 - result64); - } - return Math.abs((reference64 - result64) / reference64); -} - -export function getRelativeError(result, reference) { - return Math.abs((reference - result) / reference); -} - -function getBinaryShader(operation) { - return `\ -in vec3 positions; -uniform vec2 a; -uniform vec2 b; -out vec4 vColor; -void main(void) { - gl_Position = vec4(positions, 1.0); - vec2 result = ${operation}(a, b); - vColor = vec4(result.x, result.y, 0.0, 1.0); -} -`; -} - -function getUnaryShader(operation) { - return `\ -in vec3 positions; -uniform vec2 a; -out vec4 vColor; -void main(void) { - gl_Position = vec4(positions, 1.0); - vec2 result = ${operation}(a); - vColor = vec4(result.x, result.y, 0.0, 1.0); -} -`; -} - -const FS_RENDER_VCOLOR = `\ -precision highp float; -in vec4 vColor; -void main(void) { - gl_FragColor = vColor; -} -`; - -function setupFloatTest(gl, {glslFunc, binary = false, limit = 256, op}) { - const a = getFloat64(limit); - const b = getFloat64(limit); - const expected = op(a, b); - - const a_fp64 = fp64ify(a); - const b_fp64 = fp64ify(b); - const expected_fp64 = fp64ify(expected); - - const vs = binary ? getBinaryShader(glslFunc) : getUnaryShader(glslFunc); - - const program = new Program( - gl, - assembleShaders(gl, { - vs, - fs: FS_RENDER_VCOLOR, - modules: [fp64] - }) - ); - - program - // @ts-expect-error TODO - this looks like a real error? - .setBuffers({ - positions: new Buffer(gl, {target: gl.ARRAY_BUFFER, data: BUFFER_DATA, size: 2}) - }) - .setUniforms({ - a: a_fp64, - b: b_fp64, - ONE: 1.0 - }); - - return {a, b, expected, a_fp64, b_fp64, expected_fp64, program}; -} - -const ITERATIONS = 10; -const EPSILON = 1e-14; - -export function testcase(gl, {glslFunc, binary, op, limit = 256, t}) { - for (let idx0 = 0; idx0 < ITERATIONS; idx0++) { - const {a, b, a_fp64, b_fp64, expected_fp64} = setupFloatTest(gl, { - glslFunc, - binary, - op, - limit - }); - render(gl); - const gpu_result = getGPUOutput(gl); - const relativeError = getRelativeError64(gpu_result, expected_fp64); - const args = binary ? `(${a.toPrecision(2)}, ${b.toPrecision(2)})` : `(${a.toPrecision(2)})`; - const message = `${glslFunc}${args}: error=${relativeError}, within ${EPSILON}`; - t.ok(relativeError < EPSILON, message); - if (relativeError >= EPSILON) { - t.comment(` (tested ${a_fp64.toString()}, ${b_fp64.toString()})`); - } - } - t.end(); -} - -// Main entrance -const canvas = document.createElement('canvas'); -canvas.width = 16; -canvas.height = 16; - -export const gl = initializeGL(canvas); -initializeTexTarget(gl); - -window.onload = () => { - document.body.appendChild(canvas); -}; diff --git a/modules/shadertools/test/modules-webgl1/lights/lights.spec.ts b/modules/shadertools/test/modules/lighting/lights.spec.ts.disabled similarity index 100% rename from modules/shadertools/test/modules-webgl1/lights/lights.spec.ts rename to modules/shadertools/test/modules/lighting/lights.spec.ts.disabled