luxscura 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +99 -0
- package/dist/aabb.d.ts +9 -0
- package/dist/appearances/glossy/appearance.d.ts +16 -0
- package/dist/appearances/glossy/index.d.ts +2 -0
- package/dist/appearances/glossy/material.d.ts +20 -0
- package/dist/appearances/matte.d.ts +16 -0
- package/dist/appearances/pbr/appearance.d.ts +42 -0
- package/dist/appearances/pbr/index.d.ts +2 -0
- package/dist/appearances/pbr/material.d.ts +27 -0
- package/dist/cube-vertices.d.ts +1 -0
- package/dist/glossy.js +336 -0
- package/dist/glossy.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +1393 -0
- package/dist/index.js.map +1 -0
- package/dist/lighting.d.ts +44 -0
- package/dist/matte.js +182 -0
- package/dist/matte.js.map +1 -0
- package/dist/pbr.js +1179 -0
- package/dist/pbr.js.map +1 -0
- package/dist/program.d.ts +128 -0
- package/dist/renderer.d.ts +64 -0
- package/package.json +68 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/aabb.ts","../src/lighting.ts","../src/program.ts","../src/cube-vertices.ts","../src/renderer.ts"],"sourcesContent":["import { f32, type Infer, struct, type v3f, vec3b, vec3f } from 'typegpu/data'\nimport { min, select } from 'typegpu/std'\n\nexport const AABB = struct({\n\tmin: vec3f,\n\tmax: vec3f,\n})\nexport type AABB = Infer<typeof AABB>\n\nexport function aabbPoint(aabb: AABB, corner: v3f): v3f {\n\t'use gpu'\n\treturn select(\n\t\taabb.min,\n\t\taabb.max,\n\t\tvec3b(corner.x > 0, corner.y > 0, corner.z > 0),\n\t)\n}\n\nexport function aabbCenter(aabb: AABB): v3f {\n\t'use gpu'\n\treturn (aabb.min + aabb.max) * 0.5\n}\n\nexport function aabbExitDistance(\n\taabb: AABB,\n\tpoint: v3f,\n\tdirection: v3f,\n): number {\n\t'use gpu'\n\n\treturn min(\n\t\taxisExitDistance(point.x, direction.x, aabb.min.x, aabb.max.x),\n\t\tmin(\n\t\t\taxisExitDistance(point.y, direction.y, aabb.min.y, aabb.max.y),\n\t\t\taxisExitDistance(point.z, direction.z, aabb.min.z, aabb.max.z),\n\t\t),\n\t)\n}\n\nfunction axisExitDistance(\n\tposition: number,\n\tdirection: number,\n\tminimum: number,\n\tmaximum: number,\n): number {\n\t'use gpu'\n\n\tif (direction > 0) return (maximum - position) / direction\n\tif (direction < 0) return (minimum - position) / direction\n\treturn f32(1e9)\n}\n","import { arrayOf, f32, type Infer, struct, vec3f } from 'typegpu/data'\n\n/** Shared GPU schema for a directional light used by lit appearances. */\nexport const RaymarchDirectionalLight = struct({\n\t/** Nonzero world-space direction of travel; normalized during shading. */\n\tdirection: vec3f,\n\n\t/** Linear RGB light color. */\n\tcolor: vec3f,\n\n\t/** Brightness multiplier; zero disables the light. */\n\tintensity: f32,\n})\n\n/** Directional-light values accepted by lighting providers. */\nexport type RaymarchDirectionalLight = Infer<typeof RaymarchDirectionalLight>\n\nconst fallbackDirectionalLights = [\n\tRaymarchDirectionalLight({\n\t\tdirection: vec3f(0, -1, 0),\n\t\tcolor: vec3f(0),\n\t\tintensity: 0,\n\t}),\n]\n\n/**\n * Creates a GPU lighting schema with a fixed number of light slots.\n * @throws {RangeError} If capacity is not a positive integer.\n */\nfunction createRaymarchLightingStruct(capacity: number) {\n\tif (!Number.isInteger(capacity) || capacity < 1) {\n\t\tthrow new RangeError('Lighting capacity must be a positive integer.')\n\t}\n\n\treturn struct({\n\t\t/** Additive linear RGB diffuse fill; black adds no ambient illumination. */\n\t\tambient: vec3f,\n\n\t\t/** Directional lights evaluated independently and added together. */\n\t\tdirectionalLights: arrayOf(RaymarchDirectionalLight, capacity),\n\t})\n}\n/** Ambient fill and directional-light values returned by a GPU lighting provider. */\nexport type RaymarchLighting = Infer<\n\tReturnType<typeof createRaymarchLightingStruct>\n>\n\n/**\n * Creates a GPU lighting callback with values embedded during shader compilation.\n * Infers capacity from directionalLights; an empty list uses one disabled slot.\n */\nexport function createRaymarchConstantLighting(lighting: RaymarchLighting) {\n\tconst directionalLights =\n\t\tlighting.directionalLights.length > 0\n\t\t\t? lighting.directionalLights\n\t\t\t: fallbackDirectionalLights\n\n\tconst RaymarchConstantLighting = createRaymarchLightingStruct(\n\t\tdirectionalLights.length,\n\t)\n\n\treturn function raymarchLighting() {\n\t\t'use gpu'\n\t\treturn RaymarchConstantLighting({\n\t\t\tambient: lighting.ambient,\n\t\t\tdirectionalLights: directionalLights,\n\t\t})\n\t}\n}\n","import {\n\tbool,\n\tf32,\n\ttype Infer,\n\tmat4x4f,\n\tstruct,\n\tu32,\n\ttype v3f,\n\tvec2f,\n\tvec3f,\n} from 'typegpu/data'\nimport { AABB } from './aabb'\n\nexport const RaymarchCamera = struct({\n\tviewProjectionMatrix: mat4x4f,\n\tposition: vec3f,\n})\nexport type RaymarchCamera = Infer<typeof RaymarchCamera>\n\n/** Result of the primary ray march, with data available for appearance. */\nexport const RaymarchResult = struct({\n\t/** Whether the primary ray reached the surface within the march limits. */\n\tisHit: bool,\n\t/** Hit position, or the final ray sample position on a miss, in world space. */\n\tposition: vec3f,\n\t/** Outward surface normal on a hit; -rayDirection on a miss. */\n\tnormal: vec3f,\n\t/** Camera position in world space. */\n\trayOrigin: vec3f,\n\t/** Unit direction from the camera into the scene. */\n\trayDirection: vec3f,\n\t/** World-space distance from rayOrigin to position. */\n\trayDistance: f32,\n\t/** Number of primary ray-march iterations, excluding normal/shadow samples. */\n\tstepCount: u32,\n\t/** Projected depth written for a hit; 1 on a miss. */\n\tprojectedDepth: f32,\n\t/** Pixel-space fragment coordinates, with pixel centers at half-integers. */\n\tfragmentCoord: vec2f,\n\t/** Index of the bounds instance being rendered. */\n\tinstanceIndex: u32,\n\t/** World-space bounds for this instance. */\n\tbounds: AABB,\n})\nexport type RaymarchResult = Infer<typeof RaymarchResult>\n\n/**\n * GPU function calculating linear RGB for every visible fragment after marching.\n * The renderer uses the result only on hits, with opaque coverage and its own\n * depth. Derivative-dependent work must run outside hit-dependent branches.\n */\nexport type RaymarchAppearance = (result: RaymarchResult) => v3f\n\nexport type RaymarchBoundsProvider = (instanceIdx: number) => AABB\n\nexport type RaymarchInitializer = (instanceIdx: number) => void\n\nexport type RaymarchVisibilityTest = (\n\trayPoint: v3f,\n\tinstanceIdx: number,\n\tbounds: AABB,\n) => boolean\n\nexport type RaymarchDistanceFunction = (\n\tpoint: v3f,\n\tinstanceIdx: number,\n\taabb: AABB,\n) => number\n\nexport type RaymarchProgramOptions = {\n\t/** Diagnostic metadata for consumers. Unused by the renderer. */\n\tlabel?: string\n\t/** Surface hit tolerance in world units. */\n\tepsilon: number\n\t/** Normal sampling offset; defaults to epsilon. */\n\tepsilonNormal?: number\n\t/** Maximum number of marching steps per ray; defaults to 100. */\n\tmaxSteps?: number\n\t/** Write surface hit depth to the depth buffer; defaults to true. */\n\tdepthWriteEnabled?: boolean\n\t/** Comparison used to test surface hit depth against the depth buffer; defaults to 'less'. */\n\tdepthCompare?: GPUCompareFunction\n} & (\n\t| {\n\t\t\t/** Allow marching past the bounding-box exit. Defaults to false; requires maxDistance when true. */\n\t\t\tmarchBeyondBounds?: false\n\t\t\t/** Maximum distance to march from the bounding-box entry point, in world units. */\n\t\t\tmaxDistance?: number\n\t }\n\t| {\n\t\t\t/** Allow marching past the bounding-box exit. Defaults to false; requires maxDistance when true. */\n\t\t\tmarchBeyondBounds: true\n\t\t\t/** Maximum distance to march from the bounding-box entry point, in world units. */\n\t\t\tmaxDistance: number\n\t }\n)\n\n/** Geometry and visibility callbacks compiled into a raymarching pipeline. */\nexport interface RaymarchSurface {\n\t/** GPU function initializing per-fragment state before raymarching. */\n\tinit?: RaymarchInitializer\n\n\t/** GPU function providing each instance's axis-aligned bounding box. */\n\tbounds: RaymarchBoundsProvider\n\n\t/**\n\t * GPU function masking out rays that should not render. Returning false\n\t * skips raymarching for that fragment.\n\t */\n\tisRayVisible?: RaymarchVisibilityTest\n\n\t/** GPU function returning the signed distance from a point to the surface. */\n\tsd: RaymarchDistanceFunction\n}\n\n/** Camera, geometry, and appearance compiled into one raymarching pipeline. */\nexport interface RaymarchProgram {\n\t/** GPU function providing the current camera state. */\n\tcamera: () => RaymarchCamera\n\n\t/** Surface bounds, signed distance, and optional visibility behavior. */\n\tsurface: RaymarchSurface\n\n\t/** GPU function returning linear RGB for the raymarch result. */\n\tappearance: RaymarchAppearance\n}\n\n/** Versioned factory that creates a program from setup-time context. */\nexport interface RaymarchProgramDefinition<TContext> {\n\tversion: number\n\toptions: RaymarchProgramOptions\n\tcreate: (context: TContext) => RaymarchProgram\n}\n\n/** Minimal hot-module context used to retain a program across reevaluations. */\nexport interface RaymarchHotContext {\n\tdata: Record<string, unknown>\n}\n\nconst HOT_DATA_KEY = 'raymarchProgramDefinition'\n\n/**\n * Creates a versioned program definition without allocating GPU resources. It\n * owns the factory for surface, camera, and appearance callbacks,\n * and the options used to compile them into a raymarching pipeline. Callbacks\n * may read changing buffer data without rebuilding the pipeline.\n *\n * When `hot` is provided, reevaluating the module updates the existing program\n * definition and increments its version. Renderer instances observe that\n * version and rebuild their pipelines while retaining setup-time resources. The\n * defining module must call `import.meta.hot?.accept()` for this behavior, and\n * may currently define only one HMR-backed raymarch program.\n *\n * ```ts\n * const program = createRaymarchProgram(options, create, import.meta.hot)\n * import.meta.hot?.accept()\n * ```\n *\n * @returns A read-only program definition consumed by raymarch renderer factories.\n */\nexport function createRaymarchProgram<TContext = undefined>(\n\toptions: RaymarchProgramOptions,\n\tcreate: (context: TContext) => RaymarchProgram,\n\n\t/**\n\t * Optional hot-module context used to preserve and update the program\n\t * across module reevaluations.\n\t */\n\thot?: RaymarchHotContext,\n): Readonly<RaymarchProgramDefinition<TContext>> {\n\tconst definition = (hot?.data[HOT_DATA_KEY] as\n\t\t| RaymarchProgramDefinition<TContext>\n\t\t| undefined) ?? { version: 0, options, create }\n\n\tdefinition.version += 1\n\tdefinition.options = options\n\tdefinition.create = create\n\tif (hot) hot.data[HOT_DATA_KEY] = definition\n\n\treturn definition\n}\n","import { tgpu } from 'typegpu'\nimport { arrayOf, vec3f } from 'typegpu/data'\n\nexport const cubeVertices = tgpu.const(arrayOf(vec3f, 36), [\n\tvec3f(0, 0, 1),\n\tvec3f(1, 0, 1),\n\tvec3f(1, 1, 1),\n\tvec3f(1, 1, 1),\n\tvec3f(0, 1, 1),\n\tvec3f(0, 0, 1),\n\tvec3f(1, 0, 0),\n\tvec3f(0, 0, 0),\n\tvec3f(0, 1, 0),\n\tvec3f(0, 1, 0),\n\tvec3f(1, 1, 0),\n\tvec3f(1, 0, 0),\n\tvec3f(0, 1, 1),\n\tvec3f(1, 1, 1),\n\tvec3f(1, 1, 0),\n\tvec3f(1, 1, 0),\n\tvec3f(0, 1, 0),\n\tvec3f(0, 1, 1),\n\tvec3f(0, 0, 0),\n\tvec3f(1, 0, 0),\n\tvec3f(1, 0, 1),\n\tvec3f(1, 0, 1),\n\tvec3f(0, 0, 1),\n\tvec3f(0, 0, 0),\n\tvec3f(1, 0, 1),\n\tvec3f(1, 0, 0),\n\tvec3f(1, 1, 0),\n\tvec3f(1, 1, 0),\n\tvec3f(1, 1, 1),\n\tvec3f(1, 0, 1),\n\tvec3f(0, 0, 0),\n\tvec3f(0, 0, 1),\n\tvec3f(0, 1, 1),\n\tvec3f(0, 1, 1),\n\tvec3f(0, 1, 0),\n\tvec3f(0, 0, 0),\n])\n","import {\n\ttype ColorAttachment,\n\ttype DepthStencilAttachment,\n\ttype TgpuRenderPipeline,\n\ttype TgpuRoot,\n\ttgpu,\n} from 'typegpu'\nimport {\n\tbool,\n\tbuiltin,\n\tf32,\n\ttype Infer,\n\tinterpolate,\n\tstruct,\n\tu32,\n\ttype Vec4f,\n\ttype v3f,\n\tvec2f,\n\tvec3f,\n\tvec4f,\n} from 'typegpu/data'\nimport { discard, length, min, normalize } from 'typegpu/std'\nimport { type AABB, aabbExitDistance, aabbPoint } from './aabb'\nimport { cubeVertices } from './cube-vertices'\nimport {\n\ttype RaymarchAppearance,\n\ttype RaymarchCamera,\n\ttype RaymarchDistanceFunction,\n\ttype RaymarchProgram,\n\ttype RaymarchProgramDefinition,\n\ttype RaymarchProgramOptions,\n\tRaymarchResult,\n\ttype RaymarchSurface,\n\ttype RaymarchVisibilityTest,\n} from './program'\n\nexport interface RaymarchRenderTargetOptions {\n\t/**\n\t * Format of the color attachment.\n\t * @default navigator.gpu.getPreferredCanvasFormat()\n\t */\n\tcolorFormat?: GPUTextureFormat\n\n\t/**\n\t * Format of the depth/stencil attachment.\n\t * @default 'depth24plus'\n\t */\n\tdepthStencilFormat?: Extract<GPUTextureFormat, `depth${string}`>\n\n\t/**\n\t * Number of samples per pixel in each attachment.\n\t * @default 1\n\t */\n\tsampleCount?: 1 | 4\n}\n\n/** Attachments and instance count for one raymarch draw submission. */\nexport interface RaymarchRenderOptions {\n\tcolorAttachment: ColorAttachment\n\tdepthStencilAttachment: DepthStencilAttachment\n\t/** @default 1 */\n\tinstances?: number\n}\n\nconst RayHit = struct({\n\tisHit: bool,\n\tpos: vec3f,\n\tdepth: f32,\n\trayDirection: vec3f,\n\trayDistance: f32,\n\tstepCount: u32,\n})\ntype RayHit = Infer<typeof RayHit>\n\nfunction createRaymarch({\n\tsdSurface,\n\tmaxSteps,\n\tmaxDistance,\n\tepsilon,\n\tmarchBeyondBounds,\n}: {\n\tsdSurface: RaymarchDistanceFunction\n\tmaxSteps: number\n\tmaxDistance?: number\n\tepsilon: number\n\tmarchBeyondBounds: boolean\n}) {\n\treturn function raymarch(\n\t\tcamera: RaymarchCamera,\n\t\tworldPosition: v3f,\n\t\taabb: AABB,\n\t\tinstanceIndex: number,\n\t): RayHit {\n\t\t'use gpu'\n\t\tconst triangleDifference = worldPosition.xyz - camera.position\n\t\tconst triangleDistance = length(triangleDifference)\n\t\tconst rayDirection = normalize(triangleDifference)\n\n\t\tlet marchedDistance = f32(0)\n\t\tlet point = camera.position + rayDirection * triangleDistance\n\t\tlet stepCount = u32(0)\n\n\t\tlet marchLimit = aabbExitDistance(aabb, point, rayDirection)\n\t\tif (marchBeyondBounds) {\n\t\t\tmarchLimit = f32(maxDistance ?? 0)\n\t\t} else if (maxDistance !== undefined) {\n\t\t\tmarchLimit = min(marchLimit, maxDistance)\n\t\t}\n\n\t\tfor (let stepIndex = 0; stepIndex < maxSteps; stepIndex++) {\n\t\t\tif (marchedDistance > marchLimit) break\n\t\t\tstepCount += 1\n\n\t\t\tpoint =\n\t\t\t\tcamera.position + rayDirection * (triangleDistance + marchedDistance)\n\n\t\t\tconst distance = sdSurface(point, instanceIndex, aabb)\n\n\t\t\tif (distance < epsilon) {\n\t\t\t\tconst hitClipPosition = camera.viewProjectionMatrix * vec4f(point, 1)\n\n\t\t\t\treturn RayHit({\n\t\t\t\t\tisHit: true,\n\t\t\t\t\tpos: point,\n\t\t\t\t\tdepth: hitClipPosition.z / hitClipPosition.w,\n\t\t\t\t\trayDirection,\n\t\t\t\t\trayDistance: triangleDistance + marchedDistance,\n\t\t\t\t\tstepCount,\n\t\t\t\t})\n\t\t\t}\n\t\t\tmarchedDistance += distance\n\t\t}\n\n\t\treturn RayHit({\n\t\t\tisHit: false,\n\t\t\tpos: point,\n\t\t\tdepth: 1,\n\t\t\trayDirection,\n\t\t\trayDistance: length(point - camera.position),\n\t\t\tstepCount,\n\t\t})\n\t}\n}\n\nfunction createCalculateNormal({\n\tsdSurface,\n\tepsilonNormal,\n}: {\n\tsdSurface: RaymarchDistanceFunction\n\tepsilonNormal: number\n}) {\n\treturn function calculateNormal(\n\t\tpoint: v3f,\n\t\taabb: AABB,\n\t\tinstanceIndex: number,\n\t): v3f {\n\t\t'use gpu'\n\t\tconst k = vec2f(1, -1)\n\t\treturn normalize(\n\t\t\tk.xyy * sdSurface(point + k.xyy * epsilonNormal, instanceIndex, aabb) +\n\t\t\t\t(k.yyx * sdSurface(point + k.yyx * epsilonNormal, instanceIndex, aabb) +\n\t\t\t\t\t(k.yxy *\n\t\t\t\t\t\tsdSurface(point + k.yxy * epsilonNormal, instanceIndex, aabb) +\n\t\t\t\t\t\tk.xxx *\n\t\t\t\t\t\t\tsdSurface(point + k.xxx * epsilonNormal, instanceIndex, aabb))),\n\t\t)\n\t}\n}\n\n/**\n * Creates a GPU pipeline that renders a raymarched surface.\n *\n * @returns A function that draws the requested number of instances.\n */\nfunction createRaymarchPipeline({\n\troot,\n\toptions,\n\tcamera,\n\tappearance,\n\tsurface,\n\tpreparePipeline = (pipeline) => pipeline,\n\trenderTarget,\n}: {\n\troot: TgpuRoot\n\toptions: RaymarchProgramOptions\n\tcamera: () => RaymarchCamera\n\tappearance: RaymarchAppearance\n\tsurface: RaymarchSurface\n\tpreparePipeline?: (\n\t\tpipeline: TgpuRenderPipeline<{ color: Vec4f }>,\n\t) => TgpuRenderPipeline<{ color: Vec4f }>\n\trenderTarget?: Readonly<RaymarchRenderTargetOptions>\n}) {\n\tconst isRayVisible: RaymarchVisibilityTest =\n\t\tsurface.isRayVisible ??\n\t\t(() => {\n\t\t\t'use gpu'\n\t\t\treturn true\n\t\t})\n\n\tconst calculateNormal = createCalculateNormal({\n\t\tsdSurface: surface.sd,\n\t\tepsilonNormal: options.epsilonNormal ?? options.epsilon,\n\t})\n\n\tconst raymarch = createRaymarch({\n\t\tsdSurface: surface.sd,\n\t\tepsilon: options.epsilon,\n\t\tmaxSteps: options.maxSteps ?? 100,\n\t\tmaxDistance: options.maxDistance,\n\t\tmarchBeyondBounds: options.marchBeyondBounds ?? false,\n\t})\n\n\tconst pipeline = preparePipeline(\n\t\troot.createRenderPipeline({\n\t\t\tmultisample: { count: renderTarget?.sampleCount },\n\t\t\tdepthStencil: {\n\t\t\t\tformat: renderTarget?.depthStencilFormat ?? 'depth24plus',\n\t\t\t\tdepthWriteEnabled: options.depthWriteEnabled ?? true,\n\t\t\t\tdepthCompare: options.depthCompare ?? 'less',\n\t\t\t},\n\t\t\tprimitive: { topology: 'triangle-list', cullMode: 'back' },\n\t\t\ttargets: {\n\t\t\t\tcolor: {\n\t\t\t\t\tformat: renderTarget?.colorFormat,\n\t\t\t\t\tblend: {\n\t\t\t\t\t\tcolor: {\n\t\t\t\t\t\t\tsrcFactor: 'src-alpha',\n\t\t\t\t\t\t\tdstFactor: 'one-minus-src-alpha',\n\t\t\t\t\t\t\toperation: 'add',\n\t\t\t\t\t\t},\n\t\t\t\t\t\talpha: {\n\t\t\t\t\t\t\tsrcFactor: 'one',\n\t\t\t\t\t\t\tdstFactor: 'one-minus-src-alpha',\n\t\t\t\t\t\t\toperation: 'add',\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\n\t\t\tvertex: tgpu.vertexFn({\n\t\t\t\tin: {\n\t\t\t\t\tvertexIdx: builtin.vertexIndex,\n\t\t\t\t\tinstanceIdx: builtin.instanceIndex,\n\t\t\t\t},\n\t\t\t\tout: {\n\t\t\t\t\tposition: builtin.position,\n\t\t\t\t\tworldPos: vec3f,\n\t\t\t\t\tinstanceIdx: interpolate('flat, either', u32),\n\t\t\t\t},\n\t\t\t})(({ vertexIdx, instanceIdx }) => {\n\t\t\t\t'use gpu'\n\n\t\t\t\tconst aabb = surface.bounds(instanceIdx)\n\t\t\t\tconst localPos = cubeVertices.$[vertexIdx]\n\t\t\t\tconst worldPos = aabbPoint(aabb, localPos)\n\t\t\t\tconst position = camera().viewProjectionMatrix * vec4f(worldPos, 1)\n\n\t\t\t\treturn {\n\t\t\t\t\tposition,\n\t\t\t\t\tworldPos,\n\t\t\t\t\tinstanceIdx,\n\t\t\t\t}\n\t\t\t}),\n\n\t\t\tfragment: ({ $position, worldPos, instanceIdx }) => {\n\t\t\t\t'use gpu'\n\n\t\t\t\tconst aabb = surface.bounds(instanceIdx)\n\t\t\t\tif (surface.init !== undefined) surface.init(instanceIdx)\n\t\t\t\tif (!isRayVisible(worldPos.xyz, instanceIdx, aabb)) discard()\n\n\t\t\t\tconst activeCamera = camera()\n\t\t\t\tconst hit = raymarch(activeCamera, worldPos.xyz, aabb, instanceIdx)\n\t\t\t\tlet normal = -1 * hit.rayDirection\n\n\t\t\t\tif (hit.isHit) {\n\t\t\t\t\tnormal = calculateNormal(hit.pos, aabb, instanceIdx)\n\t\t\t\t}\n\n\t\t\t\t// Appearance runs before the hit branch so it may use derivatives.\n\t\t\t\tconst color = appearance(\n\t\t\t\t\tRaymarchResult({\n\t\t\t\t\t\tisHit: hit.isHit,\n\t\t\t\t\t\tposition: hit.pos,\n\t\t\t\t\t\tnormal,\n\t\t\t\t\t\trayOrigin: activeCamera.position,\n\t\t\t\t\t\trayDirection: hit.rayDirection,\n\t\t\t\t\t\trayDistance: hit.rayDistance,\n\t\t\t\t\t\tstepCount: hit.stepCount,\n\t\t\t\t\t\tprojectedDepth: hit.depth,\n\t\t\t\t\t\tfragmentCoord: $position.xy,\n\t\t\t\t\t\tinstanceIndex: instanceIdx,\n\t\t\t\t\t\tbounds: aabb,\n\t\t\t\t\t}),\n\t\t\t\t)\n\n\t\t\t\tif (hit.isHit) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcolor: vec4f(color, 1),\n\t\t\t\t\t\t$fragDepth: hit.depth,\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn {\n\t\t\t\t\tcolor: vec4f(),\n\t\t\t\t\t$fragDepth: 1,\n\t\t\t\t}\n\t\t\t},\n\t\t}),\n\t)\n\n\treturn function render({\n\t\tcolorAttachment,\n\t\tdepthStencilAttachment,\n\t\tinstances = 1,\n\t}: RaymarchRenderOptions) {\n\t\tpipeline\n\t\t\t.withColorAttachment({ color: colorAttachment })\n\t\t\t.withDepthStencilAttachment(depthStencilAttachment)\n\t\t\t.draw(cubeVertices.$.length, instances)\n\t}\n}\n\n/**\n * Creates a renderer for a raymarch program. It adds bounds rendering,\n * raymarching, normal calculation, appearance, depth, and draw submission to the\n * surface supplied by the program.\n *\n * Program creation and preparation are repeated when the program version\n * changes, allowing shader HMR to rebuild the pipeline without replacing the\n * supplied setup-time context.\n *\n * @returns A function that draws a requested number of raymarched instances.\n */\nexport function createRaymarchRenderer<TContext = undefined>({\n\troot,\n\tprogram,\n\tcontext = undefined as TContext,\n\trenderTarget,\n\tprepare = (program) => program,\n\tpreparePipeline,\n}: {\n\troot: TgpuRoot\n\n\t/** Program providing pipeline options, a version, and the shader factory. */\n\tprogram: Readonly<RaymarchProgramDefinition<TContext>>\n\n\t/** Render target configuration used to create a compatible pipeline. */\n\trenderTarget?: Readonly<RaymarchRenderTargetOptions>\n\n\t/**\n\t * Optional program transformation applied after program creation and before\n\t * pipeline compilation.\n\t */\n\tprepare?: (program: RaymarchProgram) => RaymarchProgram\n\n\t/**\n\t * Optional pipeline transformation applied after pipeline creation and before\n\t * the pipeline is captured by the render function.\n\t */\n\tpreparePipeline?: (\n\t\tpipeline: TgpuRenderPipeline<{ color: Vec4f }>,\n\t) => TgpuRenderPipeline<{ color: Vec4f }>\n} & (undefined extends TContext\n\t? { context?: TContext }\n\t: {\n\t\t\t/** @deprecated use closures instead. */\n\t\t\tcontext: TContext\n\t\t})) {\n\tfunction createRenderer() {\n\t\tconst { camera, surface, appearance } = prepare(program.create(context))\n\t\tconst renderer = createRaymarchPipeline({\n\t\t\troot,\n\t\t\toptions: program.options,\n\t\t\tsurface,\n\t\t\tcamera,\n\t\t\tappearance,\n\t\t\tpreparePipeline,\n\t\t\trenderTarget,\n\t\t})\n\n\t\treturn renderer\n\t}\n\n\tlet activeVersion = program.version\n\tlet activeRenderer = createRenderer()\n\n\treturn function renderRaymarchedInstances(options: RaymarchRenderOptions) {\n\t\tif (activeVersion !== program.version) {\n\t\t\tconst nextRenderer = createRenderer()\n\n\t\t\tactiveRenderer = nextRenderer\n\t\t\tactiveVersion = program.version\n\t\t}\n\n\t\tactiveRenderer(options)\n\t}\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { type Infer } from 'typegpu/data';
|
|
2
|
+
/** Shared GPU schema for a directional light used by lit appearances. */
|
|
3
|
+
export declare const RaymarchDirectionalLight: import("typegpu/data").WgslStruct<{
|
|
4
|
+
/** Nonzero world-space direction of travel; normalized during shading. */
|
|
5
|
+
direction: import("typegpu/data").Vec3f;
|
|
6
|
+
/** Linear RGB light color. */
|
|
7
|
+
color: import("typegpu/data").Vec3f;
|
|
8
|
+
/** Brightness multiplier; zero disables the light. */
|
|
9
|
+
intensity: import("typegpu/data").F32;
|
|
10
|
+
}>;
|
|
11
|
+
/** Directional-light values accepted by lighting providers. */
|
|
12
|
+
export type RaymarchDirectionalLight = Infer<typeof RaymarchDirectionalLight>;
|
|
13
|
+
/**
|
|
14
|
+
* Creates a GPU lighting schema with a fixed number of light slots.
|
|
15
|
+
* @throws {RangeError} If capacity is not a positive integer.
|
|
16
|
+
*/
|
|
17
|
+
declare function createRaymarchLightingStruct(capacity: number): import("typegpu/data").WgslStruct<{
|
|
18
|
+
/** Additive linear RGB diffuse fill; black adds no ambient illumination. */
|
|
19
|
+
ambient: import("typegpu/data").Vec3f;
|
|
20
|
+
/** Directional lights evaluated independently and added together. */
|
|
21
|
+
directionalLights: import("typegpu/data").WgslArray<import("typegpu/data").WgslStruct<{
|
|
22
|
+
/** Nonzero world-space direction of travel; normalized during shading. */
|
|
23
|
+
direction: import("typegpu/data").Vec3f;
|
|
24
|
+
/** Linear RGB light color. */
|
|
25
|
+
color: import("typegpu/data").Vec3f;
|
|
26
|
+
/** Brightness multiplier; zero disables the light. */
|
|
27
|
+
intensity: import("typegpu/data").F32;
|
|
28
|
+
}>>;
|
|
29
|
+
}>;
|
|
30
|
+
/** Ambient fill and directional-light values returned by a GPU lighting provider. */
|
|
31
|
+
export type RaymarchLighting = Infer<ReturnType<typeof createRaymarchLightingStruct>>;
|
|
32
|
+
/**
|
|
33
|
+
* Creates a GPU lighting callback with values embedded during shader compilation.
|
|
34
|
+
* Infers capacity from directionalLights; an empty list uses one disabled slot.
|
|
35
|
+
*/
|
|
36
|
+
export declare function createRaymarchConstantLighting(lighting: RaymarchLighting): () => {
|
|
37
|
+
ambient: import("typegpu/data").v3f;
|
|
38
|
+
directionalLights: {
|
|
39
|
+
direction: import("typegpu/data").v3f;
|
|
40
|
+
color: import("typegpu/data").v3f;
|
|
41
|
+
intensity: number;
|
|
42
|
+
}[];
|
|
43
|
+
};
|
|
44
|
+
export {};
|
package/dist/matte.js
ADDED
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import { vec3f as e } from "typegpu/data";
|
|
2
|
+
import { dot as t, normalize as n, saturate as r } from "typegpu/std";
|
|
3
|
+
//#region src/appearances/matte.ts
|
|
4
|
+
function i({ color: i, lighting: a }) {
|
|
5
|
+
return /*#__PURE__*/ ((o) => (globalThis.__TYPEGPU_META__ ??= /* @__PURE__ */ new WeakMap()).set(o.f = (function(o) {
|
|
6
|
+
"use gpu";
|
|
7
|
+
let s = i(o);
|
|
8
|
+
if (!o.isHit) return e(0);
|
|
9
|
+
let c = a(), l = e(c.ambient);
|
|
10
|
+
for (let e of c.directionalLights) {
|
|
11
|
+
if (e.intensity === 0) continue;
|
|
12
|
+
let i = __tsover_mul(-1, n(e.direction)), a = r(t(o.normal, i));
|
|
13
|
+
l = __tsover_add(l, __tsover_mul(__tsover_mul(e.color, e.intensity), a));
|
|
14
|
+
}
|
|
15
|
+
return __tsover_mul(s, l);
|
|
16
|
+
}), {
|
|
17
|
+
v: 2,
|
|
18
|
+
name: "matteAppearance",
|
|
19
|
+
ast: {
|
|
20
|
+
params: [{
|
|
21
|
+
type: "i",
|
|
22
|
+
name: "result"
|
|
23
|
+
}],
|
|
24
|
+
body: [0, [
|
|
25
|
+
[
|
|
26
|
+
13,
|
|
27
|
+
"surfaceColor",
|
|
28
|
+
[
|
|
29
|
+
6,
|
|
30
|
+
"color",
|
|
31
|
+
["result"]
|
|
32
|
+
]
|
|
33
|
+
],
|
|
34
|
+
[
|
|
35
|
+
11,
|
|
36
|
+
[
|
|
37
|
+
4,
|
|
38
|
+
"!",
|
|
39
|
+
[
|
|
40
|
+
7,
|
|
41
|
+
"result",
|
|
42
|
+
"isHit"
|
|
43
|
+
]
|
|
44
|
+
],
|
|
45
|
+
[10, [
|
|
46
|
+
6,
|
|
47
|
+
"vec3f",
|
|
48
|
+
[[5, "0"]]
|
|
49
|
+
]]
|
|
50
|
+
],
|
|
51
|
+
[
|
|
52
|
+
13,
|
|
53
|
+
"lights",
|
|
54
|
+
[
|
|
55
|
+
6,
|
|
56
|
+
"lighting",
|
|
57
|
+
[]
|
|
58
|
+
]
|
|
59
|
+
],
|
|
60
|
+
[
|
|
61
|
+
12,
|
|
62
|
+
"illumination",
|
|
63
|
+
[
|
|
64
|
+
6,
|
|
65
|
+
"vec3f",
|
|
66
|
+
[[
|
|
67
|
+
7,
|
|
68
|
+
"lights",
|
|
69
|
+
"ambient"
|
|
70
|
+
]]
|
|
71
|
+
]
|
|
72
|
+
],
|
|
73
|
+
[
|
|
74
|
+
18,
|
|
75
|
+
[13, "light"],
|
|
76
|
+
[
|
|
77
|
+
7,
|
|
78
|
+
"lights",
|
|
79
|
+
"directionalLights"
|
|
80
|
+
],
|
|
81
|
+
[0, [
|
|
82
|
+
[
|
|
83
|
+
11,
|
|
84
|
+
[
|
|
85
|
+
1,
|
|
86
|
+
[
|
|
87
|
+
7,
|
|
88
|
+
"light",
|
|
89
|
+
"intensity"
|
|
90
|
+
],
|
|
91
|
+
"===",
|
|
92
|
+
[5, "0"]
|
|
93
|
+
],
|
|
94
|
+
[16]
|
|
95
|
+
],
|
|
96
|
+
[
|
|
97
|
+
13,
|
|
98
|
+
"lightDirection",
|
|
99
|
+
[
|
|
100
|
+
1,
|
|
101
|
+
[
|
|
102
|
+
4,
|
|
103
|
+
"-",
|
|
104
|
+
[5, "1"]
|
|
105
|
+
],
|
|
106
|
+
"*",
|
|
107
|
+
[
|
|
108
|
+
6,
|
|
109
|
+
"normalize",
|
|
110
|
+
[[
|
|
111
|
+
7,
|
|
112
|
+
"light",
|
|
113
|
+
"direction"
|
|
114
|
+
]]
|
|
115
|
+
]
|
|
116
|
+
]
|
|
117
|
+
],
|
|
118
|
+
[
|
|
119
|
+
13,
|
|
120
|
+
"diffuse",
|
|
121
|
+
[
|
|
122
|
+
6,
|
|
123
|
+
"saturate",
|
|
124
|
+
[[
|
|
125
|
+
6,
|
|
126
|
+
"dot",
|
|
127
|
+
[[
|
|
128
|
+
7,
|
|
129
|
+
"result",
|
|
130
|
+
"normal"
|
|
131
|
+
], "lightDirection"]
|
|
132
|
+
]]
|
|
133
|
+
]
|
|
134
|
+
],
|
|
135
|
+
[
|
|
136
|
+
2,
|
|
137
|
+
"illumination",
|
|
138
|
+
"+=",
|
|
139
|
+
[
|
|
140
|
+
1,
|
|
141
|
+
[
|
|
142
|
+
1,
|
|
143
|
+
[
|
|
144
|
+
7,
|
|
145
|
+
"light",
|
|
146
|
+
"color"
|
|
147
|
+
],
|
|
148
|
+
"*",
|
|
149
|
+
[
|
|
150
|
+
7,
|
|
151
|
+
"light",
|
|
152
|
+
"intensity"
|
|
153
|
+
]
|
|
154
|
+
],
|
|
155
|
+
"*",
|
|
156
|
+
"diffuse"
|
|
157
|
+
]
|
|
158
|
+
]
|
|
159
|
+
]]
|
|
160
|
+
],
|
|
161
|
+
[10, [
|
|
162
|
+
1,
|
|
163
|
+
"surfaceColor",
|
|
164
|
+
"*",
|
|
165
|
+
"illumination"
|
|
166
|
+
]]
|
|
167
|
+
]]
|
|
168
|
+
},
|
|
169
|
+
externals: {
|
|
170
|
+
color: () => i,
|
|
171
|
+
vec3f: () => e,
|
|
172
|
+
lighting: () => a,
|
|
173
|
+
normalize: () => n,
|
|
174
|
+
saturate: () => r,
|
|
175
|
+
dot: () => t
|
|
176
|
+
}
|
|
177
|
+
}) && o.f)({});
|
|
178
|
+
}
|
|
179
|
+
//#endregion
|
|
180
|
+
export { i as createMatteAppearance };
|
|
181
|
+
|
|
182
|
+
//# sourceMappingURL=matte.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"matte.js","names":[],"sources":["../src/appearances/matte.ts"],"sourcesContent":["import { type v3f, vec3f } from 'typegpu/data'\nimport { dot, normalize, saturate } from 'typegpu/std'\nimport type { RaymarchLighting } from '../lighting'\nimport type { RaymarchAppearance, RaymarchResult } from '../program'\n\n/** GPU function sampling a surface's linear RGB color from the raymarch result. */\nexport type MatteColorSampler = (result: RaymarchResult) => v3f\n\n/**\n * Creates a matte appearance using ambient fill and Lambert diffuse lighting.\n * Surfaces facing a light receive its full contribution, with no shiny highlights.\n *\n * Color sampling runs for hits and misses so derivatives remain available.\n * Lighting runs only for hits. Colors and lighting values are linear RGB.\n */\nexport function createMatteAppearance({\n\tcolor,\n\tlighting,\n}: {\n\tcolor: MatteColorSampler\n\tlighting: () => RaymarchLighting\n}): RaymarchAppearance {\n\treturn function matteAppearance(result: RaymarchResult): v3f {\n\t\t'use gpu'\n\t\tconst surfaceColor = color(result)\n\t\tif (!result.isHit) return vec3f(0)\n\n\t\tconst lights = lighting()\n\t\tlet illumination = vec3f(lights.ambient)\n\t\tfor (const light of lights.directionalLights) {\n\t\t\tif (light.intensity === 0) continue\n\n\t\t\tconst lightDirection = -1 * normalize(light.direction)\n\t\t\tconst diffuse = saturate(dot(result.normal, lightDirection))\n\t\t\tillumination += light.color * light.intensity * diffuse\n\t\t}\n\n\t\treturn surfaceColor * illumination\n\t}\n}\n"],"mappings":";;;AAeA,SAAgB,EAAsB,EACrC,UACA,eAIsB;CACtB,OAAO,gBAAA,OAAA,WAAA,qCAAA,IAAA,QAAA,EAAA,CAAA,IAAA,EAAA,KAAA,SAAA,GAAA;EAAA;EAAA,IAAA,IAAA,EAAA,CAAA;EAAA,IAAA,CAAA,EAAA,OAAA,OAAA,EAAA,CAAA;EAAA,IAAA,IAAA,EAAA,GAAA,IAAA,EAAA,EAAA,OAAA;EAAA,KAAA,IAAA,KAAA,EAAA,mBAAA;GAAA,IAAA,EAAA,cAAA,GAAA;GAAA,IAAA,IAAA,aAAA,IAAA,EAAA,EAAA,SAAA,CAAA,GAAA,IAAA,EAAA,EAAA,EAAA,QAAA,CAAA,CAAA;GAAA,IAAA,aAAA,GAAA,aAAA,aAAA,EAAA,OAAA,EAAA,SAAA,GAAA,CAAA,CAAA;EAAA;EAAA,OAAA,aAAA,GAAA,CAAA;CAAA,IAAA;EAAA,GAAA;EAAA,MAAA;EAAA,KAAA;GAAA,QAAA,CAAA;IAAA,MAAA;IAAA,MAAA;GAAA,CAAA;GAAA,MAAA,CAAA,GAAA;IAAA;KAAA;KAAA;KAAA;MAAA;MAAA;MAAA,CAAA,QAAA;KAAA;IAAA;IAAA;KAAA;KAAA;MAAA;MAAA;MAAA;OAAA;OAAA;OAAA;MAAA;KAAA;KAAA,CAAA,IAAA;MAAA;MAAA;MAAA,CAAA,CAAA,GAAA,GAAA,CAAA;KAAA,CAAA;IAAA;IAAA;KAAA;KAAA;KAAA;MAAA;MAAA;MAAA,CAAA;KAAA;IAAA;IAAA;KAAA;KAAA;KAAA;MAAA;MAAA;MAAA,CAAA;OAAA;OAAA;OAAA;MAAA,CAAA;KAAA;IAAA;IAAA;KAAA;KAAA,CAAA,IAAA,OAAA;KAAA;MAAA;MAAA;MAAA;KAAA;KAAA,CAAA,GAAA;MAAA;OAAA;OAAA;QAAA;QAAA;SAAA;SAAA;SAAA;QAAA;QAAA;QAAA,CAAA,GAAA,GAAA;OAAA;OAAA,CAAA,EAAA;MAAA;MAAA;OAAA;OAAA;OAAA;QAAA;QAAA;SAAA;SAAA;SAAA,CAAA,GAAA,GAAA;QAAA;QAAA;QAAA;SAAA;SAAA;SAAA,CAAA;UAAA;UAAA;UAAA;SAAA,CAAA;QAAA;OAAA;MAAA;MAAA;OAAA;OAAA;OAAA;QAAA;QAAA;QAAA,CAAA;SAAA;SAAA;SAAA,CAAA;UAAA;UAAA;UAAA;SAAA,GAAA,gBAAA;QAAA,CAAA;OAAA;MAAA;MAAA;OAAA;OAAA;OAAA;OAAA;QAAA;QAAA;SAAA;SAAA;UAAA;UAAA;UAAA;SAAA;SAAA;SAAA;UAAA;UAAA;UAAA;SAAA;QAAA;QAAA;QAAA;OAAA;MAAA;KAAA,CAAA;IAAA;IAAA,CAAA,IAAA;KAAA;KAAA;KAAA;KAAA;IAAA,CAAA;GAAA,CAAA;EAAA;EAAA,WAAA;GAAA,aAAA;GAAA,aAAA;GAAA,gBAAA;GAAA,iBAAA;GAAA,gBAAA;GAAA,WAAA;EAAA;CAAA,CAAA,KAAA,EAAA,EAAA,CAAA,CAAA,CAAA;AAiBR"}
|