gpu-curtains
Version:
gpu-curtains is a 3D WebGPU rendering engine. It can be used as a standalone 3D engine, but also includes extra classes focused on mapping 3d objects to DOM elements; It allows users to synchronize values such as position, sizing, or scale between them.
79 lines (65 loc) • 2.48 kB
JavaScript
import { constants } from "../../chunks/utils/constants.mjs";
//#region src/core/shaders/full/compute/compute-cubemap-from-HDR.ts
/**
* Compute a cube map texture from HDR image data.
*/
const computeCubemapFromHDR = `
${constants}
// Cube face lookup vectors
// positive and negative Y need to be inverted
const faceVectors = array<array<vec3f, 2>, 6>(
array<vec3f, 2>(vec3f(1.0, 0.0, 0.0), vec3f(0.0, 1.0, 0.0)), // +X
array<vec3f, 2>(vec3f(-1.0, 0.0, 0.0), vec3f(0.0, 1.0, 0.0)), // -X
array<vec3f, 2>(vec3f(0.0, -1.0, 0.0), vec3f(0.0, 0.0, 1.0)), // -Y
array<vec3f, 2>(vec3f(0.0, 1.0, 0.0), vec3f(0.0, 0.0, -1.0)), // +Y
array<vec3f, 2>(vec3f(0.0, 0.0, 1.0), vec3f(0.0, 1.0, 0.0)), // +Z
array<vec3f, 2>(vec3f(0.0, 0.0, -1.0), vec3f(0.0, 1.0, 0.0)) // -Z
);
// Utility to calculate 3D direction for a given cube face pixel
fn texelDirection(faceIndex : u32, u : f32, v : f32) -> vec3f {
let forward = faceVectors[faceIndex][0];
let up = faceVectors[faceIndex][1];
let right = normalize(cross(up, forward));
return normalize(forward + (2.0 * u - 1.0) * right + (2.0 * v - 1.0) * up);
}
// Map 3D direction to equirectangular coordinates
fn dirToEquirect(dir : vec3f) -> vec2f {
let phi = atan2(dir.z, dir.x);
let theta = asin(dir.y);
let u = 0.5 + 0.5 * phi / PI;
let v = 0.5 - theta / PI;
return vec2f(u, v);
}
fn main( global_id : vec3u) {
let faceSize = params.faceSize;
let cubeFaceIndex = global_id.z;
let x = global_id.x;
let y = global_id.y;
if (x >= faceSize || y >= faceSize || cubeFaceIndex >= 6u) {
return;
}
let u = f32(x) / f32(faceSize - 1);
let v = f32(y) / f32(faceSize - 1);
// Get the 3D direction for this cube face texel
let dir = texelDirection(cubeFaceIndex, u, v);
// Map to equirectangular coordinates
let uv = dirToEquirect(dir);
let hdrWidth = params.imageSize.x;
let hdrHeight = params.imageSize.y;
let texX = u32(clamp(uv.x * hdrWidth, 0.0, hdrWidth - 1.0));
let texY = u32(clamp(uv.y * hdrHeight, 0.0, hdrHeight - 1.0));
let hdrTexelIndex = texY * u32(hdrWidth) + texX;
// Sample the equirectangular texture
let sampledColor = params.hdrImageData[hdrTexelIndex];
// Correct cube face order in texture store (fix for reversed face indices)
textureStore(
storageCubemap,
vec2u(x, y),
cubeFaceIndex,
sampledColor
);
}
`;
//#endregion
export { computeCubemapFromHDR };