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
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Alex Wayne
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# Luxscura
|
|
2
|
+
|
|
3
|
+
## A TypeGPU Raymarching Renderer
|
|
4
|
+
|
|
5
|
+
Luxscura is currently in early development. Its package structure and public API
|
|
6
|
+
may change.
|
|
7
|
+
|
|
8
|
+
## TypeGPU setup
|
|
9
|
+
|
|
10
|
+
Luxscura is build on top of TypeGPU. You will want to set it up in your project as well as the the build plugin so your shaders can get compiled from TypeScript.
|
|
11
|
+
|
|
12
|
+
- https://docs.swmansion.com/TypeGPU/getting-started/
|
|
13
|
+
- https://docs.swmansion.com/TypeGPU/tooling/unplugin-typegpu/
|
|
14
|
+
|
|
15
|
+
## Usage
|
|
16
|
+
|
|
17
|
+
1. Create a raymarching program:
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
import { createRaymarchProgram } from 'luxscura'
|
|
21
|
+
|
|
22
|
+
// This is a camera position and view projection matrix
|
|
23
|
+
const camera = createCamera()
|
|
24
|
+
|
|
25
|
+
const program = createRaymarchProgram({ epsilon: 0.001 }, () => {
|
|
26
|
+
return {
|
|
27
|
+
camera: () => {
|
|
28
|
+
'use gpu'
|
|
29
|
+
return RaymarchCamera({
|
|
30
|
+
position: camera.cameraPosition,
|
|
31
|
+
viewProjectionMatrix: camera.viewProjectionMatrix,
|
|
32
|
+
})
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
surface: {
|
|
36
|
+
bounds: () => {
|
|
37
|
+
'use gpu'
|
|
38
|
+
return AABB({ min: vec3f(-1), max: vec3f(1) })
|
|
39
|
+
},
|
|
40
|
+
sd: (point) => {
|
|
41
|
+
'use gpu'
|
|
42
|
+
return sdSphere(point, 1)
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
|
|
46
|
+
appearance: createMatteAppearance({
|
|
47
|
+
color: () => {
|
|
48
|
+
'use gpu'
|
|
49
|
+
return vec3f(0.15, 0.5, 0.85)
|
|
50
|
+
},
|
|
51
|
+
lighting: createRaymarchConstantLighting({
|
|
52
|
+
ambient: vec3f(0.2, 0.05, 0.05),
|
|
53
|
+
directionalLights: [
|
|
54
|
+
{
|
|
55
|
+
direction: vec3f(-1, 1, -1),
|
|
56
|
+
color: vec3f(1, 0.9, 0.75),
|
|
57
|
+
intensity: 1,
|
|
58
|
+
},
|
|
59
|
+
],
|
|
60
|
+
}),
|
|
61
|
+
}),
|
|
62
|
+
}
|
|
63
|
+
})
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
2. And then create a renderer
|
|
67
|
+
|
|
68
|
+
```ts
|
|
69
|
+
import { createRaymarchRenderer } from 'luxscura'
|
|
70
|
+
|
|
71
|
+
const canvas = document.getElementById('canvas') as HTMLCanvasElement
|
|
72
|
+
const root = await tgpu.init()
|
|
73
|
+
const canvasContext = root.configureContext({ canvas })
|
|
74
|
+
|
|
75
|
+
// A depth buffer is currently required
|
|
76
|
+
const depthTexture = root
|
|
77
|
+
.createTexture({
|
|
78
|
+
size: [canvas.width, canvas.height],
|
|
79
|
+
format: 'depth24plus',
|
|
80
|
+
})
|
|
81
|
+
.$usage('render')
|
|
82
|
+
|
|
83
|
+
// This function renders the scene
|
|
84
|
+
const render = createRaymarchRenderer({ root, program })
|
|
85
|
+
|
|
86
|
+
// Render loop
|
|
87
|
+
function renderFrame() {
|
|
88
|
+
render({
|
|
89
|
+
colorAttachment: { view: canvasContext },
|
|
90
|
+
depthStencilAttachment: { view: depthTexture },
|
|
91
|
+
})
|
|
92
|
+
requestAnimationFrame(renderFrame)
|
|
93
|
+
}
|
|
94
|
+
requestAnimationFrame(renderFrame)
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## More documentation coming soon
|
|
98
|
+
|
|
99
|
+
See [the examples on the website](https://alexjwayne.github.io/luxscura/).
|
package/dist/aabb.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type Infer, type v3f } from 'typegpu/data';
|
|
2
|
+
export declare const AABB: import("typegpu/data").WgslStruct<{
|
|
3
|
+
min: import("typegpu/data").Vec3f;
|
|
4
|
+
max: import("typegpu/data").Vec3f;
|
|
5
|
+
}>;
|
|
6
|
+
export type AABB = Infer<typeof AABB>;
|
|
7
|
+
export declare function aabbPoint(aabb: AABB, corner: v3f): v3f;
|
|
8
|
+
export declare function aabbCenter(aabb: AABB): v3f;
|
|
9
|
+
export declare function aabbExitDistance(aabb: AABB, point: v3f, direction: v3f): number;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { RaymarchLighting } from '../../lighting';
|
|
2
|
+
import type { RaymarchAppearance, RaymarchResult } from '../../program';
|
|
3
|
+
import type { GlossyMaterial } from './material';
|
|
4
|
+
/** GPU function sampling a glossy material from the raymarch result. */
|
|
5
|
+
export type GlossyMaterialSampler = (result: RaymarchResult) => GlossyMaterial;
|
|
6
|
+
/**
|
|
7
|
+
* Creates a glossy appearance using diffuse lighting and Blinn-Phong highlights.
|
|
8
|
+
* Ambient fill affects the diffuse color; emission is added independently.
|
|
9
|
+
*
|
|
10
|
+
* Material sampling runs for hits and misses so derivatives remain available.
|
|
11
|
+
* Lighting runs only for hits. Colors and lighting values are linear RGB.
|
|
12
|
+
*/
|
|
13
|
+
export declare function createGlossyAppearance({ material, lighting, }: {
|
|
14
|
+
material: GlossyMaterialSampler;
|
|
15
|
+
lighting: () => RaymarchLighting;
|
|
16
|
+
}): RaymarchAppearance;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type Infer } from 'typegpu/data';
|
|
2
|
+
/**
|
|
3
|
+
* GPU material schema for an opaque surface with adjustable shiny highlights.
|
|
4
|
+
* Colors are linear RGB. Callers must supply finite values within the documented
|
|
5
|
+
* ranges; constructing this struct does not clamp or validate material values.
|
|
6
|
+
*/
|
|
7
|
+
export declare const GlossyMaterial: import("typegpu/data").WgslStruct<{
|
|
8
|
+
/** Diffuse surface color. Each channel is in [0, 1]. */
|
|
9
|
+
baseColor: import("typegpu/data").Vec3f;
|
|
10
|
+
/** Highlight color and strength. Each channel is in [0, 1]; black disables highlights. */
|
|
11
|
+
specular: import("typegpu/data").Vec3f;
|
|
12
|
+
/**
|
|
13
|
+
* Highlight tightness: lower values produce broad highlights, higher values
|
|
14
|
+
* small ones. Use values of at least 1; shading applies an internal floor of 1.
|
|
15
|
+
*/
|
|
16
|
+
shininess: import("typegpu/data").F32;
|
|
17
|
+
/** Nonnegative outgoing linear RGB added independently of illumination; may exceed 1. */
|
|
18
|
+
emission: import("typegpu/data").Vec3f;
|
|
19
|
+
}>;
|
|
20
|
+
export type GlossyMaterial = Infer<typeof GlossyMaterial>;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type v3f } from 'typegpu/data';
|
|
2
|
+
import type { RaymarchLighting } from '../lighting';
|
|
3
|
+
import type { RaymarchAppearance, RaymarchResult } from '../program';
|
|
4
|
+
/** GPU function sampling a surface's linear RGB color from the raymarch result. */
|
|
5
|
+
export type MatteColorSampler = (result: RaymarchResult) => v3f;
|
|
6
|
+
/**
|
|
7
|
+
* Creates a matte appearance using ambient fill and Lambert diffuse lighting.
|
|
8
|
+
* Surfaces facing a light receive its full contribution, with no shiny highlights.
|
|
9
|
+
*
|
|
10
|
+
* Color sampling runs for hits and misses so derivatives remain available.
|
|
11
|
+
* Lighting runs only for hits. Colors and lighting values are linear RGB.
|
|
12
|
+
*/
|
|
13
|
+
export declare function createMatteAppearance({ color, lighting, }: {
|
|
14
|
+
color: MatteColorSampler;
|
|
15
|
+
lighting: () => RaymarchLighting;
|
|
16
|
+
}): RaymarchAppearance;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { type Infer, type v3f } from 'typegpu/data';
|
|
2
|
+
import type { RaymarchLighting } from '../../lighting';
|
|
3
|
+
import type { RaymarchAppearance, RaymarchResult } from '../../program';
|
|
4
|
+
import { PbrMaterial } from './material';
|
|
5
|
+
/** Position, normal, and PBR material consumed by the lighting calculation. */
|
|
6
|
+
export declare const PbrSurfaceSample: import("typegpu/data").WgslStruct<{
|
|
7
|
+
position: import("typegpu/data").Vec3f;
|
|
8
|
+
normal: import("typegpu/data").Vec3f;
|
|
9
|
+
material: import("typegpu/data").WgslStruct<{
|
|
10
|
+
baseColor: import("typegpu/data").Vec3f;
|
|
11
|
+
metallic: import("typegpu/data").F32;
|
|
12
|
+
roughness: import("typegpu/data").F32;
|
|
13
|
+
emission: import("typegpu/data").Vec3f;
|
|
14
|
+
}>;
|
|
15
|
+
}>;
|
|
16
|
+
export type PbrSurfaceSample = Infer<typeof PbrSurfaceSample>;
|
|
17
|
+
/**
|
|
18
|
+
* Creates a GPU surface shader combining direct lighting, material emission,
|
|
19
|
+
* and environment reflections.
|
|
20
|
+
*/
|
|
21
|
+
export declare function createPbrShadeSurface({ lighting, environment, }: {
|
|
22
|
+
lighting: () => RaymarchLighting;
|
|
23
|
+
environment: (direction: v3f, roughness: number) => v3f;
|
|
24
|
+
}): (cameraPosition: v3f, sample: PbrSurfaceSample) => v3f;
|
|
25
|
+
/** GPU function sampling a PBR material from the raymarch result. */
|
|
26
|
+
export type PbrMaterialSampler = (result: RaymarchResult) => PbrMaterial;
|
|
27
|
+
/**
|
|
28
|
+
* Creates a metallic/roughness appearance for a raymarch program.
|
|
29
|
+
*
|
|
30
|
+
* Material sampling runs for hits and misses so derivatives remain available.
|
|
31
|
+
* Lighting runs only for hits. The returned color on a miss is ignored by the
|
|
32
|
+
* renderer.
|
|
33
|
+
*/
|
|
34
|
+
export declare function createPbrAppearance({ material, lighting, environment, }: {
|
|
35
|
+
material: PbrMaterialSampler;
|
|
36
|
+
lighting: () => RaymarchLighting;
|
|
37
|
+
/**
|
|
38
|
+
* Incoming linear RGB from a normalized reflection direction. Called only on
|
|
39
|
+
* hits; texture sampling here should use an explicit level of detail.
|
|
40
|
+
*/
|
|
41
|
+
environment: (direction: v3f, roughness: number) => v3f;
|
|
42
|
+
}): RaymarchAppearance;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type Infer } from 'typegpu/data';
|
|
2
|
+
/**
|
|
3
|
+
* GPU material schema for an opaque surface using metallic/roughness shading.
|
|
4
|
+
* Colors are linear RGB. Callers must supply finite values within the documented
|
|
5
|
+
* ranges; constructing this struct does not clamp or validate material values.
|
|
6
|
+
*/
|
|
7
|
+
export declare const PbrMaterial: import("typegpu/data").WgslStruct<{
|
|
8
|
+
/** Diffuse color for nonmetals, specular reflection color for metals. Each channel is in [0, 1]. */
|
|
9
|
+
baseColor: import("typegpu/data").Vec3f;
|
|
10
|
+
/** Nonmetal at 0, metal at 1; intermediate values blend the responses. Not a shininess control. */
|
|
11
|
+
metallic: import("typegpu/data").F32;
|
|
12
|
+
/**
|
|
13
|
+
* Surface roughness in [0, 1]: 0 produces sharp direct highlights, 1 broad ones.
|
|
14
|
+
* Direct shading applies a small internal floor at the smooth end for stability.
|
|
15
|
+
* Passed to the environment callback; the consumer owns reflection filtering.
|
|
16
|
+
*/
|
|
17
|
+
roughness: import("typegpu/data").F32;
|
|
18
|
+
/**
|
|
19
|
+
* Nonnegative outgoing linear RGB added independently of illumination; may exceed 1.
|
|
20
|
+
* Does not illuminate other surfaces or disable this material's reflections.
|
|
21
|
+
*/
|
|
22
|
+
emission: import("typegpu/data").Vec3f;
|
|
23
|
+
}>;
|
|
24
|
+
export type PbrMaterial = Infer<typeof PbrMaterial>;
|
|
25
|
+
/** Debug material for visualizing a normalized float That varies over the surface. */
|
|
26
|
+
export declare function debugPbrMaterial(luminance: number): PbrMaterial;
|
|
27
|
+
export declare function mixPbrMaterials(a: PbrMaterial, b: PbrMaterial, amount: number): PbrMaterial;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const cubeVertices: import("typegpu").TgpuConst<import("typegpu/data").WgslArray<import("typegpu/data").Vec3f>>;
|
package/dist/glossy.js
ADDED
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
import { f32 as e, struct as t, vec3f as n } from "typegpu/data";
|
|
2
|
+
import { dot as r, max as i, normalize as a, pow as o, saturate as s } from "typegpu/std";
|
|
3
|
+
//#region src/appearances/glossy/appearance.ts
|
|
4
|
+
function c({ material: e, lighting: t }) {
|
|
5
|
+
return /*#__PURE__*/ ((c) => (globalThis.__TYPEGPU_META__ ??= /* @__PURE__ */ new WeakMap()).set(c.f = (function(c) {
|
|
6
|
+
"use gpu";
|
|
7
|
+
let l = e(c);
|
|
8
|
+
if (!c.isHit) return n(0);
|
|
9
|
+
let u = t(), d = __tsover_add(__tsover_mul(l.baseColor, u.ambient), l.emission), f = __tsover_mul(-1, c.rayDirection), p = r(c.normal, f) > 0, m = i(l.shininess, 1);
|
|
10
|
+
for (let e of u.directionalLights) {
|
|
11
|
+
if (e.intensity === 0) continue;
|
|
12
|
+
let t = __tsover_mul(-1, a(e.direction)), n = s(r(c.normal, t));
|
|
13
|
+
if (n === 0) continue;
|
|
14
|
+
let i = __tsover_mul(l.baseColor, n);
|
|
15
|
+
if (p) {
|
|
16
|
+
let e = a(__tsover_add(f, t)), n = o(s(r(c.normal, e)), m);
|
|
17
|
+
i = __tsover_add(i, __tsover_mul(l.specular, n));
|
|
18
|
+
}
|
|
19
|
+
d = __tsover_add(d, __tsover_mul(__tsover_mul(e.color, e.intensity), i));
|
|
20
|
+
}
|
|
21
|
+
return d;
|
|
22
|
+
}), {
|
|
23
|
+
v: 2,
|
|
24
|
+
name: "glossyAppearance",
|
|
25
|
+
ast: {
|
|
26
|
+
params: [{
|
|
27
|
+
type: "i",
|
|
28
|
+
name: "result"
|
|
29
|
+
}],
|
|
30
|
+
body: [0, [
|
|
31
|
+
[
|
|
32
|
+
13,
|
|
33
|
+
"materialSample",
|
|
34
|
+
[
|
|
35
|
+
6,
|
|
36
|
+
"material",
|
|
37
|
+
["result"]
|
|
38
|
+
]
|
|
39
|
+
],
|
|
40
|
+
[
|
|
41
|
+
11,
|
|
42
|
+
[
|
|
43
|
+
4,
|
|
44
|
+
"!",
|
|
45
|
+
[
|
|
46
|
+
7,
|
|
47
|
+
"result",
|
|
48
|
+
"isHit"
|
|
49
|
+
]
|
|
50
|
+
],
|
|
51
|
+
[10, [
|
|
52
|
+
6,
|
|
53
|
+
"vec3f",
|
|
54
|
+
[[5, "0"]]
|
|
55
|
+
]]
|
|
56
|
+
],
|
|
57
|
+
[
|
|
58
|
+
13,
|
|
59
|
+
"lights",
|
|
60
|
+
[
|
|
61
|
+
6,
|
|
62
|
+
"lighting",
|
|
63
|
+
[]
|
|
64
|
+
]
|
|
65
|
+
],
|
|
66
|
+
[
|
|
67
|
+
12,
|
|
68
|
+
"color",
|
|
69
|
+
[
|
|
70
|
+
1,
|
|
71
|
+
[
|
|
72
|
+
1,
|
|
73
|
+
[
|
|
74
|
+
7,
|
|
75
|
+
"materialSample",
|
|
76
|
+
"baseColor"
|
|
77
|
+
],
|
|
78
|
+
"*",
|
|
79
|
+
[
|
|
80
|
+
7,
|
|
81
|
+
"lights",
|
|
82
|
+
"ambient"
|
|
83
|
+
]
|
|
84
|
+
],
|
|
85
|
+
"+",
|
|
86
|
+
[
|
|
87
|
+
7,
|
|
88
|
+
"materialSample",
|
|
89
|
+
"emission"
|
|
90
|
+
]
|
|
91
|
+
]
|
|
92
|
+
],
|
|
93
|
+
[
|
|
94
|
+
13,
|
|
95
|
+
"viewDirection",
|
|
96
|
+
[
|
|
97
|
+
1,
|
|
98
|
+
[
|
|
99
|
+
4,
|
|
100
|
+
"-",
|
|
101
|
+
[5, "1"]
|
|
102
|
+
],
|
|
103
|
+
"*",
|
|
104
|
+
[
|
|
105
|
+
7,
|
|
106
|
+
"result",
|
|
107
|
+
"rayDirection"
|
|
108
|
+
]
|
|
109
|
+
]
|
|
110
|
+
],
|
|
111
|
+
[
|
|
112
|
+
13,
|
|
113
|
+
"facingCamera",
|
|
114
|
+
[
|
|
115
|
+
1,
|
|
116
|
+
[
|
|
117
|
+
6,
|
|
118
|
+
"dot",
|
|
119
|
+
[[
|
|
120
|
+
7,
|
|
121
|
+
"result",
|
|
122
|
+
"normal"
|
|
123
|
+
], "viewDirection"]
|
|
124
|
+
],
|
|
125
|
+
">",
|
|
126
|
+
[5, "0"]
|
|
127
|
+
]
|
|
128
|
+
],
|
|
129
|
+
[
|
|
130
|
+
13,
|
|
131
|
+
"shininess",
|
|
132
|
+
[
|
|
133
|
+
6,
|
|
134
|
+
"max",
|
|
135
|
+
[[
|
|
136
|
+
7,
|
|
137
|
+
"materialSample",
|
|
138
|
+
"shininess"
|
|
139
|
+
], [5, "1"]]
|
|
140
|
+
]
|
|
141
|
+
],
|
|
142
|
+
[
|
|
143
|
+
18,
|
|
144
|
+
[13, "light"],
|
|
145
|
+
[
|
|
146
|
+
7,
|
|
147
|
+
"lights",
|
|
148
|
+
"directionalLights"
|
|
149
|
+
],
|
|
150
|
+
[0, [
|
|
151
|
+
[
|
|
152
|
+
11,
|
|
153
|
+
[
|
|
154
|
+
1,
|
|
155
|
+
[
|
|
156
|
+
7,
|
|
157
|
+
"light",
|
|
158
|
+
"intensity"
|
|
159
|
+
],
|
|
160
|
+
"===",
|
|
161
|
+
[5, "0"]
|
|
162
|
+
],
|
|
163
|
+
[16]
|
|
164
|
+
],
|
|
165
|
+
[
|
|
166
|
+
13,
|
|
167
|
+
"lightDirection",
|
|
168
|
+
[
|
|
169
|
+
1,
|
|
170
|
+
[
|
|
171
|
+
4,
|
|
172
|
+
"-",
|
|
173
|
+
[5, "1"]
|
|
174
|
+
],
|
|
175
|
+
"*",
|
|
176
|
+
[
|
|
177
|
+
6,
|
|
178
|
+
"normalize",
|
|
179
|
+
[[
|
|
180
|
+
7,
|
|
181
|
+
"light",
|
|
182
|
+
"direction"
|
|
183
|
+
]]
|
|
184
|
+
]
|
|
185
|
+
]
|
|
186
|
+
],
|
|
187
|
+
[
|
|
188
|
+
13,
|
|
189
|
+
"diffuse",
|
|
190
|
+
[
|
|
191
|
+
6,
|
|
192
|
+
"saturate",
|
|
193
|
+
[[
|
|
194
|
+
6,
|
|
195
|
+
"dot",
|
|
196
|
+
[[
|
|
197
|
+
7,
|
|
198
|
+
"result",
|
|
199
|
+
"normal"
|
|
200
|
+
], "lightDirection"]
|
|
201
|
+
]]
|
|
202
|
+
]
|
|
203
|
+
],
|
|
204
|
+
[
|
|
205
|
+
11,
|
|
206
|
+
[
|
|
207
|
+
1,
|
|
208
|
+
"diffuse",
|
|
209
|
+
"===",
|
|
210
|
+
[5, "0"]
|
|
211
|
+
],
|
|
212
|
+
[16]
|
|
213
|
+
],
|
|
214
|
+
[
|
|
215
|
+
12,
|
|
216
|
+
"response",
|
|
217
|
+
[
|
|
218
|
+
1,
|
|
219
|
+
[
|
|
220
|
+
7,
|
|
221
|
+
"materialSample",
|
|
222
|
+
"baseColor"
|
|
223
|
+
],
|
|
224
|
+
"*",
|
|
225
|
+
"diffuse"
|
|
226
|
+
]
|
|
227
|
+
],
|
|
228
|
+
[
|
|
229
|
+
11,
|
|
230
|
+
"facingCamera",
|
|
231
|
+
[0, [
|
|
232
|
+
[
|
|
233
|
+
13,
|
|
234
|
+
"halfwayDirection",
|
|
235
|
+
[
|
|
236
|
+
6,
|
|
237
|
+
"normalize",
|
|
238
|
+
[[
|
|
239
|
+
1,
|
|
240
|
+
"viewDirection",
|
|
241
|
+
"+",
|
|
242
|
+
"lightDirection"
|
|
243
|
+
]]
|
|
244
|
+
]
|
|
245
|
+
],
|
|
246
|
+
[
|
|
247
|
+
13,
|
|
248
|
+
"highlight",
|
|
249
|
+
[
|
|
250
|
+
6,
|
|
251
|
+
"pow",
|
|
252
|
+
[[
|
|
253
|
+
6,
|
|
254
|
+
"saturate",
|
|
255
|
+
[[
|
|
256
|
+
6,
|
|
257
|
+
"dot",
|
|
258
|
+
[[
|
|
259
|
+
7,
|
|
260
|
+
"result",
|
|
261
|
+
"normal"
|
|
262
|
+
], "halfwayDirection"]
|
|
263
|
+
]]
|
|
264
|
+
], "shininess"]
|
|
265
|
+
]
|
|
266
|
+
],
|
|
267
|
+
[
|
|
268
|
+
2,
|
|
269
|
+
"response",
|
|
270
|
+
"+=",
|
|
271
|
+
[
|
|
272
|
+
1,
|
|
273
|
+
[
|
|
274
|
+
7,
|
|
275
|
+
"materialSample",
|
|
276
|
+
"specular"
|
|
277
|
+
],
|
|
278
|
+
"*",
|
|
279
|
+
"highlight"
|
|
280
|
+
]
|
|
281
|
+
]
|
|
282
|
+
]]
|
|
283
|
+
],
|
|
284
|
+
[
|
|
285
|
+
2,
|
|
286
|
+
"color",
|
|
287
|
+
"+=",
|
|
288
|
+
[
|
|
289
|
+
1,
|
|
290
|
+
[
|
|
291
|
+
1,
|
|
292
|
+
[
|
|
293
|
+
7,
|
|
294
|
+
"light",
|
|
295
|
+
"color"
|
|
296
|
+
],
|
|
297
|
+
"*",
|
|
298
|
+
[
|
|
299
|
+
7,
|
|
300
|
+
"light",
|
|
301
|
+
"intensity"
|
|
302
|
+
]
|
|
303
|
+
],
|
|
304
|
+
"*",
|
|
305
|
+
"response"
|
|
306
|
+
]
|
|
307
|
+
]
|
|
308
|
+
]]
|
|
309
|
+
],
|
|
310
|
+
[10, "color"]
|
|
311
|
+
]]
|
|
312
|
+
},
|
|
313
|
+
externals: {
|
|
314
|
+
material: () => e,
|
|
315
|
+
vec3f: () => n,
|
|
316
|
+
lighting: () => t,
|
|
317
|
+
dot: () => r,
|
|
318
|
+
max: () => i,
|
|
319
|
+
normalize: () => a,
|
|
320
|
+
saturate: () => s,
|
|
321
|
+
pow: () => o
|
|
322
|
+
}
|
|
323
|
+
}) && c.f)({});
|
|
324
|
+
}
|
|
325
|
+
//#endregion
|
|
326
|
+
//#region src/appearances/glossy/material.ts
|
|
327
|
+
var l = /*#__PURE__*/ (globalThis.__TYPEGPU_AUTONAME__ ?? ((e) => e))(t({
|
|
328
|
+
baseColor: n,
|
|
329
|
+
specular: n,
|
|
330
|
+
shininess: e,
|
|
331
|
+
emission: n
|
|
332
|
+
}), "GlossyMaterial");
|
|
333
|
+
//#endregion
|
|
334
|
+
export { l as GlossyMaterial, c as createGlossyAppearance };
|
|
335
|
+
|
|
336
|
+
//# sourceMappingURL=glossy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"glossy.js","names":[],"sources":["../src/appearances/glossy/appearance.ts","../src/appearances/glossy/material.ts"],"sourcesContent":["import { type v3f, vec3f } from 'typegpu/data'\nimport { dot, max, normalize, pow, saturate } from 'typegpu/std'\nimport type { RaymarchLighting } from '../../lighting'\nimport type { RaymarchAppearance, RaymarchResult } from '../../program'\nimport type { GlossyMaterial } from './material'\n\n/** GPU function sampling a glossy material from the raymarch result. */\nexport type GlossyMaterialSampler = (result: RaymarchResult) => GlossyMaterial\n\n/**\n * Creates a glossy appearance using diffuse lighting and Blinn-Phong highlights.\n * Ambient fill affects the diffuse color; emission is added independently.\n *\n * Material 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 createGlossyAppearance({\n\tmaterial,\n\tlighting,\n}: {\n\tmaterial: GlossyMaterialSampler\n\tlighting: () => RaymarchLighting\n}): RaymarchAppearance {\n\treturn function glossyAppearance(result: RaymarchResult): v3f {\n\t\t'use gpu'\n\t\tconst materialSample = material(result)\n\t\tif (!result.isHit) return vec3f(0)\n\n\t\tconst lights = lighting()\n\t\tlet color =\n\t\t\tmaterialSample.baseColor * lights.ambient + materialSample.emission\n\t\tconst viewDirection = -1 * result.rayDirection\n\t\tconst facingCamera = dot(result.normal, viewDirection) > 0\n\t\tconst shininess = max(materialSample.shininess, 1)\n\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\tif (diffuse === 0) continue\n\n\t\t\tlet response = materialSample.baseColor * diffuse\n\t\t\tif (facingCamera) {\n\t\t\t\tconst halfwayDirection = normalize(viewDirection + lightDirection)\n\t\t\t\tconst highlight = pow(\n\t\t\t\t\tsaturate(dot(result.normal, halfwayDirection)),\n\t\t\t\t\tshininess,\n\t\t\t\t)\n\t\t\t\tresponse += materialSample.specular * highlight\n\t\t\t}\n\n\t\t\tcolor += light.color * light.intensity * response\n\t\t}\n\n\t\treturn color\n\t}\n}\n","import { f32, type Infer, struct, vec3f } from 'typegpu/data'\n\n/**\n * GPU material schema for an opaque surface with adjustable shiny highlights.\n * Colors are linear RGB. Callers must supply finite values within the documented\n * ranges; constructing this struct does not clamp or validate material values.\n */\nexport const GlossyMaterial = struct({\n\t/** Diffuse surface color. Each channel is in [0, 1]. */\n\tbaseColor: vec3f,\n\n\t/** Highlight color and strength. Each channel is in [0, 1]; black disables highlights. */\n\tspecular: vec3f,\n\n\t/**\n\t * Highlight tightness: lower values produce broad highlights, higher values\n\t * small ones. Use values of at least 1; shading applies an internal floor of 1.\n\t */\n\tshininess: f32,\n\n\t/** Nonnegative outgoing linear RGB added independently of illumination; may exceed 1. */\n\temission: vec3f,\n})\nexport type GlossyMaterial = Infer<typeof GlossyMaterial>\n"],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { AABB } from './aabb';
|
|
2
|
+
export { createRaymarchConstantLighting, RaymarchDirectionalLight, type RaymarchLighting, } from './lighting';
|
|
3
|
+
export { createRaymarchProgram, type RaymarchAppearance, type RaymarchBoundsProvider, RaymarchCamera, type RaymarchDistanceFunction, type RaymarchInitializer, type RaymarchProgram, type RaymarchProgramDefinition, type RaymarchProgramOptions, RaymarchResult, type RaymarchSurface, type RaymarchVisibilityTest, } from './program';
|
|
4
|
+
export { createRaymarchRenderer, type RaymarchRenderOptions, type RaymarchRenderTargetOptions, } from './renderer';
|