chorama 0.0.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/.configs/tsconfig.lib.json +43 -0
- package/.configs/tsconfig.website.json +34 -0
- package/.github/workflows/static.yml +88 -0
- package/.vscode/launch.json +29 -0
- package/.vscode/tasks.json +19 -0
- package/README.md +127 -0
- package/assets/images/disappointed.jpg +0 -0
- package/assets/images/skybox/grimmnight_back.png +0 -0
- package/assets/images/skybox/grimmnight_bottom.png +0 -0
- package/assets/images/skybox/grimmnight_front.png +0 -0
- package/assets/images/skybox/grimmnight_left.png +0 -0
- package/assets/images/skybox/grimmnight_right.png +0 -0
- package/assets/images/skybox/grimmnight_top.png +0 -0
- package/assets/images/skybox/miramar_back.png +0 -0
- package/assets/images/skybox/miramar_bottom.png +0 -0
- package/assets/images/skybox/miramar_front.png +0 -0
- package/assets/images/skybox/miramar_left.png +0 -0
- package/assets/images/skybox/miramar_right.png +0 -0
- package/assets/images/skybox/miramar_top.png +0 -0
- package/assets/images/uv.jpg +0 -0
- package/assets/models/gltf/flight_helmet/FlightHelmet_Materials_GlassPlasticMat_BaseColor.png +0 -0
- package/assets/models/gltf/flight_helmet/FlightHelmet_Materials_GlassPlasticMat_Normal.png +0 -0
- package/assets/models/gltf/flight_helmet/FlightHelmet_Materials_GlassPlasticMat_OcclusionRoughMetal.png +0 -0
- package/assets/models/gltf/flight_helmet/FlightHelmet_Materials_LeatherPartsMat_BaseColor.png +0 -0
- package/assets/models/gltf/flight_helmet/FlightHelmet_Materials_LeatherPartsMat_Normal.png +0 -0
- package/assets/models/gltf/flight_helmet/FlightHelmet_Materials_LeatherPartsMat_OcclusionRoughMetal.png +0 -0
- package/assets/models/gltf/flight_helmet/FlightHelmet_Materials_LensesMat_BaseColor.png +0 -0
- package/assets/models/gltf/flight_helmet/FlightHelmet_Materials_LensesMat_Normal.png +0 -0
- package/assets/models/gltf/flight_helmet/FlightHelmet_Materials_LensesMat_OcclusionRoughMetal.png +0 -0
- package/assets/models/gltf/flight_helmet/FlightHelmet_Materials_MetalPartsMat_BaseColor.png +0 -0
- package/assets/models/gltf/flight_helmet/FlightHelmet_Materials_MetalPartsMat_Normal.png +0 -0
- package/assets/models/gltf/flight_helmet/FlightHelmet_Materials_MetalPartsMat_OcclusionRoughMetal.png +0 -0
- package/assets/models/gltf/flight_helmet/FlightHelmet_Materials_RubberWoodMat_BaseColor.png +0 -0
- package/assets/models/gltf/flight_helmet/FlightHelmet_Materials_RubberWoodMat_Normal.png +0 -0
- package/assets/models/gltf/flight_helmet/FlightHelmet_Materials_RubberWoodMat_OcclusionRoughMetal.png +0 -0
- package/assets/models/gltf/flight_helmet/index.bin +0 -0
- package/assets/models/gltf/flight_helmet/index.gltf +705 -0
- package/assets/models/gltf/object.gltf +23 -0
- package/assets/models/gltf/pirate_girl/index.bin +0 -0
- package/assets/models/gltf/pirate_girl/index.gltf +2082 -0
- package/assets/models/obj/pirate_girl/pirate_girl.obj +18459 -0
- package/assets/models/obj/pirate_girl/pirate_girl.png +0 -0
- package/astro.config.mjs +45 -0
- package/content/guide/api-map.md +89 -0
- package/content/guide/camera-and-controls.md +98 -0
- package/content/guide/first-scene.md +176 -0
- package/content/guide/index.md +72 -0
- package/content/guide/installation.md +179 -0
- package/content/guide/materials-and-lighting.md +138 -0
- package/content/guide/plugins-and-render-pipeline.md +124 -0
- package/content/guide/render-targets-and-views.md +147 -0
- package/content/guide/scene-graph-and-transforms.md +113 -0
- package/content/guide/textures-and-assets.md +120 -0
- package/content/guide/troubleshooting.md +49 -0
- package/env.d.ts +19 -0
- package/examples/addons/rendergraph_gui.js +580 -0
- package/examples/camera/orthographic.js +120 -0
- package/examples/camera/perspective.js +138 -0
- package/examples/lights/directional.js +397 -0
- package/examples/lights/multiple_spot_lights.js +304 -0
- package/examples/lights/point.js +337 -0
- package/examples/lights/spot.js +366 -0
- package/examples/loader/gltf_material.js +111 -0
- package/examples/loader/gltfloader.js +78 -0
- package/examples/loader/objloader.js +95 -0
- package/examples/material/cullface.js +111 -0
- package/examples/material/materials.js +126 -0
- package/examples/material/standard/basic.js +164 -0
- package/examples/mesh/circle.js +117 -0
- package/examples/mesh/cuboid.js +151 -0
- package/examples/mesh/cylinder.js +139 -0
- package/examples/mesh/geometries.js +108 -0
- package/examples/mesh/meshTopology.js +103 -0
- package/examples/mesh/plane.js +117 -0
- package/examples/mesh/skinning.js +136 -0
- package/examples/mesh/uvsphere.js +113 -0
- package/examples/other/rotatingCube.js +93 -0
- package/examples/other/rotatingSphere.js +96 -0
- package/examples/rendertarget/basic_canvas.js +130 -0
- package/examples/rendertarget/depth_texture.js +130 -0
- package/examples/rendertarget/image_target.js +140 -0
- package/examples/rendertarget/multiple_views.js +158 -0
- package/examples/rendertarget/render_masks.js +173 -0
- package/examples/rendertarget/split_screen.js +123 -0
- package/examples/rendertarget/split_view.js +137 -0
- package/examples/skybox/skybox.js +111 -0
- package/examples/texture/arrays.js +156 -0
- package/examples/texture/textureWrap.js +118 -0
- package/examples/transform/propagation.js +92 -0
- package/package.json +55 -0
- package/rollup.config.js +66 -0
- package/scripts/stage-chorama.mjs +29 -0
- package/src/caches/cache.js +420 -0
- package/src/caches/index.js +2 -0
- package/src/caches/uniformbuffers.js +104 -0
- package/src/cameracontrols/index.js +258 -0
- package/src/constants/index.js +3 -0
- package/src/constants/mesh.js +197 -0
- package/src/constants/others.js +218 -0
- package/src/constants/texture.js +183 -0
- package/src/core/constants.js +14 -0
- package/src/core/extensions.js +42 -0
- package/src/core/index.js +7 -0
- package/src/core/layouts/index.js +4 -0
- package/src/core/layouts/meshvertex.js +60 -0
- package/src/core/layouts/uniform.js +21 -0
- package/src/core/layouts/uniformbuffer.js +15 -0
- package/src/core/layouts/vertexbuffer.js +43 -0
- package/src/core/limits.js +247 -0
- package/src/core/resources/blendparams.js +89 -0
- package/src/core/resources/framebuffer.js +127 -0
- package/src/core/resources/gpubuffer.js +32 -0
- package/src/core/resources/gpumesh.js +43 -0
- package/src/core/resources/gputexture.js +73 -0
- package/src/core/resources/index.js +5 -0
- package/src/core/shader.js +62 -0
- package/src/core/webgl/bindgroup.js +89 -0
- package/src/core/webgl/descriptors.js +104 -0
- package/src/core/webgl/index.js +5 -0
- package/src/core/webgl/renderpassencoder.js +96 -0
- package/src/core/webgl/renderpipeline.js +54 -0
- package/src/core/webgl/utils.js +371 -0
- package/src/core/webgl/webglrenderdevice.js +235 -0
- package/src/function.js +358 -0
- package/src/index.js +15 -0
- package/src/loader/gltf.js +2172 -0
- package/src/loader/index.js +3 -0
- package/src/loader/loader.js +174 -0
- package/src/loader/obj.js +188 -0
- package/src/loader/texture.js +85 -0
- package/src/loader/utils.js +16 -0
- package/src/material/basic.js +75 -0
- package/src/material/depth.js +73 -0
- package/src/material/index.js +8 -0
- package/src/material/lambert.js +73 -0
- package/src/material/material.js +106 -0
- package/src/material/normal.js +30 -0
- package/src/material/phong.js +86 -0
- package/src/material/raw.js +52 -0
- package/src/material/standard.js +221 -0
- package/src/math/index.js +3 -0
- package/src/math/transform.js +38 -0
- package/src/mesh/attribute/attribute.js +79 -0
- package/src/mesh/attribute/index.js +1 -0
- package/src/mesh/attributedata/index.js +1 -0
- package/src/mesh/attributedata/separate.js +180 -0
- package/src/mesh/builders/base.js +41 -0
- package/src/mesh/builders/circle.js +63 -0
- package/src/mesh/builders/cuboid.js +135 -0
- package/src/mesh/builders/cylinder.js +131 -0
- package/src/mesh/builders/index.js +7 -0
- package/src/mesh/builders/plane.js +73 -0
- package/src/mesh/builders/utils.js +20 -0
- package/src/mesh/builders/uvsphere.js +80 -0
- package/src/mesh/builders/wireframe.js +62 -0
- package/src/mesh/index.js +4 -0
- package/src/mesh/mesh.js +149 -0
- package/src/objects/bone.js +17 -0
- package/src/objects/camera/camera.js +56 -0
- package/src/objects/camera/index.js +2 -0
- package/src/objects/camera/projection.js +203 -0
- package/src/objects/debug/index.js +1 -0
- package/src/objects/debug/skeleton.js +28 -0
- package/src/objects/index.js +7 -0
- package/src/objects/light/ambient.js +20 -0
- package/src/objects/light/directional.js +29 -0
- package/src/objects/light/index.js +5 -0
- package/src/objects/light/point.js +32 -0
- package/src/objects/light/shadow/index.js +1 -0
- package/src/objects/light/shadow/shadow.js +67 -0
- package/src/objects/light/spot.js +56 -0
- package/src/objects/mesh.js +141 -0
- package/src/objects/object3d.js +167 -0
- package/src/objects/skybox.js +38 -0
- package/src/plugins/camera/camera.js +19 -0
- package/src/plugins/camera/index.js +2 -0
- package/src/plugins/camera/nodes/cameraview.js +46 -0
- package/src/plugins/camera/nodes/index.js +2 -0
- package/src/plugins/camera/nodes/opaquepass.js +79 -0
- package/src/plugins/index.js +6 -0
- package/src/plugins/light/index.js +2 -0
- package/src/plugins/light/light.js +23 -0
- package/src/plugins/light/nodes/index.js +1 -0
- package/src/plugins/light/nodes/light.js +127 -0
- package/src/plugins/meshmaterial/index.js +3 -0
- package/src/plugins/meshmaterial/meshmaterial.js +381 -0
- package/src/plugins/meshmaterial/nodes/index.js +1 -0
- package/src/plugins/meshmaterial/nodes/meshmaterial.js +50 -0
- package/src/plugins/meshmaterial/resources/index.js +1 -0
- package/src/plugins/meshmaterial/resources/meshmaterialpipelines.js +50 -0
- package/src/plugins/shadow/index.js +3 -0
- package/src/plugins/shadow/nodes/index.js +3 -0
- package/src/plugins/shadow/nodes/shadow.js +272 -0
- package/src/plugins/shadow/nodes/shadowOccluder.js +112 -0
- package/src/plugins/shadow/nodes/shadowOpaquePass.js +73 -0
- package/src/plugins/shadow/resources/ShadowMap.js +99 -0
- package/src/plugins/shadow/resources/index.js +2 -0
- package/src/plugins/shadow/resources/shadowpipelines.js +25 -0
- package/src/plugins/shadow/shadow.js +31 -0
- package/src/plugins/skeletonhelper/index.js +1 -0
- package/src/plugins/skeletonhelper/skeletonhelper.js +160 -0
- package/src/plugins/skybox/index.js +3 -0
- package/src/plugins/skybox/nodes/index.js +1 -0
- package/src/plugins/skybox/nodes/skybox.js +143 -0
- package/src/plugins/skybox/resources/index.js +2 -0
- package/src/plugins/skybox/resources/skyboxmesh.js +14 -0
- package/src/plugins/skybox/resources/skyboxpipeline.js +6 -0
- package/src/plugins/skybox/skybox.js +137 -0
- package/src/renderer/core/index.js +179 -0
- package/src/renderer/graph/index.js +3 -0
- package/src/renderer/graph/nodes.js +34 -0
- package/src/renderer/graph/rendergraph.js +182 -0
- package/src/renderer/index.js +5 -0
- package/src/renderer/plugin.js +36 -0
- package/src/renderer/renderer.js +179 -0
- package/src/renderer/views.js +28 -0
- package/src/rendertarget/canvastarget.js +30 -0
- package/src/rendertarget/image.js +132 -0
- package/src/rendertarget/index.js +3 -0
- package/src/rendertarget/rendertarget.js +89 -0
- package/src/shader/basicFragment.glsl +30 -0
- package/src/shader/basicVertex.glsl +87 -0
- package/src/shader/common/color.glsl +7 -0
- package/src/shader/common/common.glsl +25 -0
- package/src/shader/common/index.js +4 -0
- package/src/shader/common/light.glsl +437 -0
- package/src/shader/common/math.glsl +12 -0
- package/src/shader/debug/index.js +2 -0
- package/src/shader/debug/skeletonFragment.glsl +8 -0
- package/src/shader/debug/skeletonVertex.glsl +27 -0
- package/src/shader/depthFragment.glsl +37 -0
- package/src/shader/index.js +11 -0
- package/src/shader/lambertFragment.glsl +126 -0
- package/src/shader/normalFragment.glsl +25 -0
- package/src/shader/phongFragment.glsl +140 -0
- package/src/shader/skyboxFragment.glsl +16 -0
- package/src/shader/skyboxVertex.glsl +20 -0
- package/src/shader/standardFragment.glsl +274 -0
- package/src/texture/index.js +2 -0
- package/src/texture/sampler.js +111 -0
- package/src/texture/texture.js +234 -0
- package/src/utils/index.js +115 -0
- package/tsconfig.json +11 -0
- package/website/config/index.ts +1 -0
- package/website/config/navigation.ts +53 -0
- package/website/content.config.ts +92 -0
- package/website/layouts/DocLayout.astro +501 -0
- package/website/layouts/Example.astro +91 -0
- package/website/pages/examples/[...slug].astro +77 -0
- package/website/pages/examples/index.astro +98 -0
- package/website/pages/examples/samples/[...slug].astro +17 -0
- package/website/pages/guide/[slug].astro +30 -0
- package/website/pages/guide/index.astro +21 -0
- package/website/pages/index.astro +9 -0
- package/website/plugins/remark-link-base.js +23 -0
- package/website/utils/url.ts +30 -0
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Materials and Lighting"
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Materials and Lighting
|
|
6
|
+
|
|
7
|
+
This guide assumes you already have a working scene from [First Scene](/guide/first-scene).
|
|
8
|
+
Here, you will add lit materials and light objects in small steps.
|
|
9
|
+
|
|
10
|
+
## What You Will Add
|
|
11
|
+
|
|
12
|
+
- a material choice based on visual style
|
|
13
|
+
- renderer plugins required for lighting
|
|
14
|
+
- ambient light for base visibility
|
|
15
|
+
- one direct light source
|
|
16
|
+
- a render list that includes lights
|
|
17
|
+
|
|
18
|
+
## Step 1: Import Material and Light APIs
|
|
19
|
+
|
|
20
|
+
```js
|
|
21
|
+
import {
|
|
22
|
+
BasicMaterial,
|
|
23
|
+
LambertMaterial,
|
|
24
|
+
PhongMaterial,
|
|
25
|
+
StandardMaterial,
|
|
26
|
+
AmbientLight,
|
|
27
|
+
DirectionalLight,
|
|
28
|
+
LightPlugin
|
|
29
|
+
} from "chorama";
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Use `BasicMaterial` when you do not need scene lighting.
|
|
33
|
+
Use `LambertMaterial`, `PhongMaterial`, or `StandardMaterial` when you want lights to affect the surface.
|
|
34
|
+
|
|
35
|
+
## Step 2: Pick a Material Model
|
|
36
|
+
|
|
37
|
+
```js
|
|
38
|
+
const basic = new BasicMaterial();
|
|
39
|
+
const lambert = new LambertMaterial();
|
|
40
|
+
const phong = new PhongMaterial();
|
|
41
|
+
const standard = new StandardMaterial({ roughness: 0.5, metallic: 0.1 });
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Quick guidance:
|
|
45
|
+
|
|
46
|
+
- `BasicMaterial`: unlit shading
|
|
47
|
+
- `LambertMaterial`: diffuse lit shading
|
|
48
|
+
- `PhongMaterial`: diffuse + specular highlight shading
|
|
49
|
+
- `StandardMaterial`: physically-based roughness/metallic shasing
|
|
50
|
+
|
|
51
|
+
For a first lit scene, start with `LambertMaterial`.
|
|
52
|
+
|
|
53
|
+
## Step 3: Apply the Material to Your Mesh Object
|
|
54
|
+
|
|
55
|
+
```js
|
|
56
|
+
const object = new MeshMaterial3D(mesh, lambert);
|
|
57
|
+
```
|
|
58
|
+
The second parameter can be any of the materials shown in the previous step.
|
|
59
|
+
If you keep `BasicMaterial` as the material of the object, lights will not change the object's appearance.
|
|
60
|
+
|
|
61
|
+
## Step 4: Enable the Lighting Pipeline in the Renderer
|
|
62
|
+
|
|
63
|
+
```js
|
|
64
|
+
const renderer = new WebGLRenderer({
|
|
65
|
+
plugins: [
|
|
66
|
+
new LightPlugin(),
|
|
67
|
+
new MeshMaterialPlugin(),
|
|
68
|
+
new CameraPlugin()
|
|
69
|
+
]
|
|
70
|
+
});
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
`LightPlugin` must be present on the renderer for lit materials to respond to lights.
|
|
74
|
+
|
|
75
|
+
## Step 5: Add Ambient Light
|
|
76
|
+
|
|
77
|
+
```js
|
|
78
|
+
const ambient = new AmbientLight();
|
|
79
|
+
ambient.intensity = 0.15;
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Ambient light gives a soft base so unlit sides are still visible.
|
|
83
|
+
It is used to approximate indirect lighting for the entire scene.
|
|
84
|
+
Keep this low so directional/point/spot lights can affect the object's appearance.
|
|
85
|
+
|
|
86
|
+
## Step 6: Add a Directional Light
|
|
87
|
+
|
|
88
|
+
```js
|
|
89
|
+
const sun = new DirectionalLight();
|
|
90
|
+
sun.intensity = 1.0;
|
|
91
|
+
sun.transform.orientation.rotateX(-Math.PI / 4);
|
|
92
|
+
sun.transform.orientation.rotateZ(-Math.PI / 4);
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Directional light is a good first light because it is simple and predictable.
|
|
96
|
+
It behaves like a distant light source with parallel rays. In this case, the light
|
|
97
|
+
will point downwards onto the scene.
|
|
98
|
+
|
|
99
|
+
## Step 7: Render with Object, Lights, and Camera
|
|
100
|
+
|
|
101
|
+
```js
|
|
102
|
+
renderer.render([object, ambient, sun, camera], device);
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Your render list must include light objects each frame.
|
|
106
|
+
If lights are missing from the list, lit materials may look black or flat.
|
|
107
|
+
|
|
108
|
+
## Step 8: Animate and Keep Scene Responsive
|
|
109
|
+
|
|
110
|
+
```js
|
|
111
|
+
function frame() {
|
|
112
|
+
renderer.render([object, ambient, sun, camera], device);
|
|
113
|
+
requestAnimationFrame(frame);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
requestAnimationFrame(frame);
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Keep your existing resize handler from [First Scene](/guide/first-scene).
|
|
120
|
+
Perspective scenes still require `camera.projection.aspect` updates on resize.
|
|
121
|
+
|
|
122
|
+
## Switching Between Material Types
|
|
123
|
+
|
|
124
|
+
You can swap material at runtime to compare look and performance:
|
|
125
|
+
|
|
126
|
+
```js
|
|
127
|
+
object.material = phong;
|
|
128
|
+
// object.material = standard;
|
|
129
|
+
// object.material = lambert;
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## Reference Examples
|
|
133
|
+
|
|
134
|
+
- [Directional Light](/examples/lights/directional)
|
|
135
|
+
- [Point Light](/examples/lights/point)
|
|
136
|
+
- [Spot Light](/examples/lights/spot)
|
|
137
|
+
|
|
138
|
+
After this works, continue with [Textures and Assets](/guide/textures-and-assets)
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Plugins and Render Pipeline"
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Plugins and Render Pipeline
|
|
6
|
+
|
|
7
|
+
This renderer is plugin-driven.
|
|
8
|
+
Plugins discover scene objects, prepare render data, and contribute render work.
|
|
9
|
+
|
|
10
|
+
## What You Will Add
|
|
11
|
+
|
|
12
|
+
- a plugin stack for your renderer
|
|
13
|
+
- a clear plugin order strategy
|
|
14
|
+
|
|
15
|
+
## Step 1: Import Core Renderer and Plugins
|
|
16
|
+
|
|
17
|
+
```js
|
|
18
|
+
import {
|
|
19
|
+
WebGLRenderer,
|
|
20
|
+
CameraPlugin,
|
|
21
|
+
MeshMaterialPlugin,
|
|
22
|
+
LightPlugin,
|
|
23
|
+
ShadowPlugin,
|
|
24
|
+
SkyboxPlugin
|
|
25
|
+
} from "chorama";
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Start with the smallest plugin set your scene needs.
|
|
29
|
+
Add others only when features require them.
|
|
30
|
+
|
|
31
|
+
## Step 2: Build a Minimal Plugin Stack
|
|
32
|
+
|
|
33
|
+
```js
|
|
34
|
+
const renderer = new WebGLRenderer({
|
|
35
|
+
plugins: [
|
|
36
|
+
new MeshMaterialPlugin(),
|
|
37
|
+
new CameraPlugin()
|
|
38
|
+
]
|
|
39
|
+
});
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
This stack is enough for camera + mesh/material scenes without lighting.
|
|
43
|
+
|
|
44
|
+
## Step 3: Add Lighting Support
|
|
45
|
+
|
|
46
|
+
```js
|
|
47
|
+
const renderer = new WebGLRenderer({
|
|
48
|
+
plugins: [
|
|
49
|
+
new LightPlugin(),
|
|
50
|
+
new MeshMaterialPlugin(),
|
|
51
|
+
new CameraPlugin()
|
|
52
|
+
]
|
|
53
|
+
});
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
`LightPlugin` provides light uniform data for lit shaders.
|
|
57
|
+
Without it, lit materials may render incorrectly.
|
|
58
|
+
|
|
59
|
+
## Step 4: Add Shadows and Skybox When Needed
|
|
60
|
+
|
|
61
|
+
```js
|
|
62
|
+
const renderer = new WebGLRenderer({
|
|
63
|
+
plugins: [
|
|
64
|
+
new ShadowPlugin(),
|
|
65
|
+
new LightPlugin(),
|
|
66
|
+
new SkyboxPlugin(),
|
|
67
|
+
new MeshMaterialPlugin(),
|
|
68
|
+
new CameraPlugin()
|
|
69
|
+
]
|
|
70
|
+
});
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Use this fuller stack only when your scene needs shadows/skybox.
|
|
74
|
+
It is heavier than the minimal stack.
|
|
75
|
+
|
|
76
|
+
## Step 5: Render as Usual
|
|
77
|
+
|
|
78
|
+
```js
|
|
79
|
+
renderer.render(objects, device);
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
The pipeline stays behind this single call.
|
|
83
|
+
You choose behavior by changing plugins and scene objects.
|
|
84
|
+
|
|
85
|
+
## What Happens During `render()`
|
|
86
|
+
|
|
87
|
+
High-level flow:
|
|
88
|
+
|
|
89
|
+
1. Object transforms are updated through scene traversal.
|
|
90
|
+
2. Each plugin preprocesses scene data.
|
|
91
|
+
3. Plugins contribute views/render items.
|
|
92
|
+
4. Views are sorted and rendered.
|
|
93
|
+
|
|
94
|
+
This is why missing plugins often look like "nothing happens" rather than hard errors.
|
|
95
|
+
|
|
96
|
+
## Plugin Roles
|
|
97
|
+
|
|
98
|
+
- `CameraPlugin`: creates camera views and per-view camera data.
|
|
99
|
+
- `MeshMaterialPlugin`: converts `MeshMaterial3D` objects into draw items.
|
|
100
|
+
- `LightPlugin`: collects light objects and uploads light blocks.
|
|
101
|
+
- `ShadowPlugin`: builds shadow passes/resources for shadow-casting lights.
|
|
102
|
+
- `SkyboxPlugin`: adds skybox rendering behavior.
|
|
103
|
+
|
|
104
|
+
## Create a Custom Plugin
|
|
105
|
+
|
|
106
|
+
```js
|
|
107
|
+
class MyPlugin extends Plugin {
|
|
108
|
+
init(renderer) {
|
|
109
|
+
// register resources, shader defines, or view fillers
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
preprocess(objects, device, renderer) {
|
|
113
|
+
// inspect scene, prepare data, push views/resources
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
getRenderItem(object, device, renderer) {
|
|
117
|
+
// return a render item for supported object types
|
|
118
|
+
return undefined;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
A custom plugin should solve one focused concern.
|
|
124
|
+
Avoid mixing unrelated responsibilities in one plugin.
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Render Targets and Views"
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Render Targets and Views
|
|
6
|
+
|
|
7
|
+
This guide assumes you already have a scene rendering from [First Scene](/guide/first-scene).
|
|
8
|
+
Here, we focus on where the camera renders and how to split output.
|
|
9
|
+
|
|
10
|
+
## What You Will Add
|
|
11
|
+
|
|
12
|
+
- a canvas render target
|
|
13
|
+
- an offscreen image render target
|
|
14
|
+
- viewport/scissor based view layouts
|
|
15
|
+
|
|
16
|
+
## Step 1: Import Render Target APIs
|
|
17
|
+
|
|
18
|
+
```js
|
|
19
|
+
import {
|
|
20
|
+
CanvasTarget,
|
|
21
|
+
ImageRenderTarget,
|
|
22
|
+
ViewRectangle,
|
|
23
|
+
Texture,
|
|
24
|
+
TextureType,
|
|
25
|
+
TextureFormat,
|
|
26
|
+
Camera
|
|
27
|
+
} from "chorama";
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Use `CanvasTarget` for on-screen output.
|
|
31
|
+
Use `ImageRenderTarget` for offscreen passes.
|
|
32
|
+
|
|
33
|
+
## Step 2: Create a Canvas Target (Most Common)
|
|
34
|
+
|
|
35
|
+
```js
|
|
36
|
+
const canvasTarget = new CanvasTarget(canvas);
|
|
37
|
+
const camera = new Camera(canvasTarget);
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
This is the default path for rendering directly to the page.
|
|
41
|
+
|
|
42
|
+
## Step 3: Render a Scene to the Canvas Target
|
|
43
|
+
|
|
44
|
+
```js
|
|
45
|
+
renderer.render([object, camera], device);
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
If your scene is blank, first confirm the camera uses the expected target.
|
|
49
|
+
|
|
50
|
+
## Step 4: Create an Offscreen Image Target
|
|
51
|
+
|
|
52
|
+
```js
|
|
53
|
+
const imageTarget = new ImageRenderTarget({
|
|
54
|
+
width: 1024,
|
|
55
|
+
height: 1024,
|
|
56
|
+
color: [
|
|
57
|
+
new Texture({
|
|
58
|
+
type: TextureType.Texture2D,
|
|
59
|
+
format: TextureFormat.RGBA8Unorm,
|
|
60
|
+
width: 1024,
|
|
61
|
+
height: 1024
|
|
62
|
+
})
|
|
63
|
+
],
|
|
64
|
+
internalDepthStencil: TextureFormat.Depth24PlusStencil8
|
|
65
|
+
});
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
This creates a texture-backed target you can render into.
|
|
69
|
+
|
|
70
|
+
## Step 5: Render Offscreen with a Dedicated Camera
|
|
71
|
+
|
|
72
|
+
```js
|
|
73
|
+
const offscreenCamera = new Camera(imageTarget);
|
|
74
|
+
renderer.render([offscreenObject, offscreenCamera], device);
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Use a separate camera when offscreen pass framing differs from main pass.
|
|
78
|
+
|
|
79
|
+
## Step 6: Use Offscreen Output as a Texture
|
|
80
|
+
|
|
81
|
+
```js
|
|
82
|
+
const screenObject = new MeshMaterial3D(
|
|
83
|
+
mesh,
|
|
84
|
+
new BasicMaterial({ mainTexture: imageTarget.color[0] })
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
renderer.render([screenObject, camera], device);
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
This is the core pattern for mirrors, portals, and postprocessing chains.
|
|
91
|
+
|
|
92
|
+
## Step 7: Split Canvas with Viewports
|
|
93
|
+
|
|
94
|
+
Use multiple `CanvasTarget` instances on the same canvas.
|
|
95
|
+
|
|
96
|
+
```js
|
|
97
|
+
const leftTarget = new CanvasTarget(canvas);
|
|
98
|
+
const rightTarget = new CanvasTarget(canvas);
|
|
99
|
+
|
|
100
|
+
leftTarget.viewport.offset.set(0, 0);
|
|
101
|
+
leftTarget.viewport.size.set(0.5, 1);
|
|
102
|
+
|
|
103
|
+
rightTarget.viewport.offset.set(0.5, 0);
|
|
104
|
+
rightTarget.viewport.size.set(0.5, 1);
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Viewport values are normalized (0 to 1) relative to full canvas size.
|
|
108
|
+
|
|
109
|
+
## Step 8: Bind Cameras to Each View and Render
|
|
110
|
+
|
|
111
|
+
```js
|
|
112
|
+
const leftCamera = new Camera(leftTarget);
|
|
113
|
+
const rightCamera = new Camera(rightTarget);
|
|
114
|
+
|
|
115
|
+
renderer.render([scene, leftCamera], device);
|
|
116
|
+
renderer.render([scene, rightCamera], device);
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
This gives independent camera views in a single canvas.
|
|
120
|
+
|
|
121
|
+
## Step 9: Use Scissor for Hard Split/Masking
|
|
122
|
+
|
|
123
|
+
```js
|
|
124
|
+
leftTarget.scissor = new ViewRectangle();
|
|
125
|
+
rightTarget.scissor = new ViewRectangle();
|
|
126
|
+
|
|
127
|
+
leftTarget.scissor.offset.set(0, 0);
|
|
128
|
+
leftTarget.scissor.size.set(0.5, 1);
|
|
129
|
+
|
|
130
|
+
rightTarget.scissor.offset.set(0.5, 0);
|
|
131
|
+
rightTarget.scissor.size.set(0.5, 1);
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Scissor restricts actual draw area, useful for editor layouts and split bars.
|
|
135
|
+
|
|
136
|
+
## Resize Rule for Multi-View Scenes
|
|
137
|
+
|
|
138
|
+
Keep canvas size and camera projection in sync on resize.
|
|
139
|
+
For split views, compute aspect per view region (not full canvas).
|
|
140
|
+
|
|
141
|
+
## Reference Examples
|
|
142
|
+
|
|
143
|
+
- [Basic Canvas Target](/examples/rendertarget/basic_canvas)
|
|
144
|
+
- [Image Target](/examples/rendertarget/image_target)
|
|
145
|
+
- [Split Screen](/examples/rendertarget/split_screen)
|
|
146
|
+
- [Multiple Views](/examples/rendertarget/multiple_views)
|
|
147
|
+
- [Split View](/examples/rendertarget/split_view)
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Scene Graph and Transforms"
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Scene Graph and Transforms
|
|
6
|
+
|
|
7
|
+
This guide assumes you already have a running scene from [First Scene](/guide/first-scene).
|
|
8
|
+
Here, we focus on parent-child relationships and transform behavior.
|
|
9
|
+
|
|
10
|
+
## What You Will Add
|
|
11
|
+
|
|
12
|
+
- a parent object
|
|
13
|
+
- one or more child objects
|
|
14
|
+
- local transforms per node
|
|
15
|
+
- frame updates that propagate through hierarchy
|
|
16
|
+
|
|
17
|
+
## Step 1: Import What You Need
|
|
18
|
+
|
|
19
|
+
```js
|
|
20
|
+
import { Object3D, MeshMaterial3D, Quaternion } from "chorama";
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Use `Object3D` for grouping and transform hierarchy.
|
|
24
|
+
Use `MeshMaterial3D` when the node should be renderable.
|
|
25
|
+
|
|
26
|
+
## Step 2: Create Parent and Child Nodes
|
|
27
|
+
|
|
28
|
+
```js
|
|
29
|
+
const root = new Object3D();
|
|
30
|
+
const parent = new MeshMaterial3D(mesh, material);
|
|
31
|
+
const child = new MeshMaterial3D(mesh, material);
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
`root` is a logical container.
|
|
35
|
+
`parent` and `child` are visible mesh nodes.
|
|
36
|
+
|
|
37
|
+
## Step 3: Build the Hierarchy
|
|
38
|
+
|
|
39
|
+
```js
|
|
40
|
+
root.add(parent);
|
|
41
|
+
parent.add(child);
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Now `child` inherits `parent` transform changes.
|
|
45
|
+
If parent rotates or moves, child follows automatically.
|
|
46
|
+
|
|
47
|
+
## Step 4: Set Local Transforms
|
|
48
|
+
|
|
49
|
+
```js
|
|
50
|
+
parent.transform.position.x = 0;
|
|
51
|
+
child.transform.position.x = 1;
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
`child.transform.position.x = 1` means "one unit from parent", not world origin.
|
|
55
|
+
Think in local space first when building hierarchies.
|
|
56
|
+
|
|
57
|
+
## Step 5: Animate the Parent
|
|
58
|
+
|
|
59
|
+
```js
|
|
60
|
+
const stepRotation = Quaternion.fromEuler(0.01, 0.01, 0.0);
|
|
61
|
+
|
|
62
|
+
function updateScene() {
|
|
63
|
+
parent.transform.orientation.multiply(stepRotation);
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Rotating the parent creates orbital motion for the child due to inheritance.
|
|
68
|
+
This is the simplest way to verify propagation is working.
|
|
69
|
+
|
|
70
|
+
## Step 6: Render the Hierarchy
|
|
71
|
+
|
|
72
|
+
```js
|
|
73
|
+
function frame() {
|
|
74
|
+
updateScene();
|
|
75
|
+
renderer.render([root, camera], device);
|
|
76
|
+
requestAnimationFrame(frame);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
requestAnimationFrame(frame);
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
You can render the root and let traversal include descendants.
|
|
83
|
+
You do not need to pass every child separately if already attached.
|
|
84
|
+
|
|
85
|
+
## Traverse the Graph for Bulk Operations
|
|
86
|
+
|
|
87
|
+
```js
|
|
88
|
+
root.traverseDFS((node) => {
|
|
89
|
+
// Example: debug flags, tagging, filtering, or custom updates
|
|
90
|
+
return true;
|
|
91
|
+
});
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Use traversal when you need one operation across many descendants.
|
|
95
|
+
Return `true` to continue deeper traversal.
|
|
96
|
+
|
|
97
|
+
## Reparent Safely
|
|
98
|
+
|
|
99
|
+
```js
|
|
100
|
+
const newParent = new Object3D();
|
|
101
|
+
root.add(newParent);
|
|
102
|
+
newParent.add(child);
|
|
103
|
+
parent.remove(child);
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Reparenting changes which transform chain affects the object.
|
|
107
|
+
|
|
108
|
+
## Reference Examples
|
|
109
|
+
|
|
110
|
+
- [Transform Propagation](/examples/transform/propagation)
|
|
111
|
+
- [Skinning](/examples/mesh/skinning)
|
|
112
|
+
|
|
113
|
+
After this works, continue with [Render Targets and Views](/guide/render-targets-and-views)
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Textures and Assets"
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
This guide assumes your scene already renders from [First Scene](/guide/first-scene).
|
|
6
|
+
Here, we focus only on bringing external assets into that scene.
|
|
7
|
+
|
|
8
|
+
## What You Will Add
|
|
9
|
+
|
|
10
|
+
- image textures
|
|
11
|
+
- OBJ models
|
|
12
|
+
- glTF models
|
|
13
|
+
- safe runtime handling while assets stream in
|
|
14
|
+
|
|
15
|
+
## Step 1: Import Loaders
|
|
16
|
+
|
|
17
|
+
```js
|
|
18
|
+
import { TextureLoader, OBJLoader, GLTFLoader } from "chorama";
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Create one loader instance per asset type and reuse it.
|
|
22
|
+
|
|
23
|
+
## Step 2: Load a Texture
|
|
24
|
+
|
|
25
|
+
```js
|
|
26
|
+
const textureLoader = new TextureLoader();
|
|
27
|
+
|
|
28
|
+
const texture = textureLoader.load({
|
|
29
|
+
paths: ["/images/uv.jpg"],
|
|
30
|
+
textureSettings: { flipY: true }
|
|
31
|
+
});
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Keep paths relative to your app's static/public asset root.
|
|
35
|
+
|
|
36
|
+
## Step 3: Apply the Texture to a Material
|
|
37
|
+
|
|
38
|
+
```js
|
|
39
|
+
const material = new BasicMaterial({
|
|
40
|
+
mainTexture: texture
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
const object = new MeshMaterial3D(mesh, material);
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Once assigned, the texture updates automatically when loading completes.
|
|
47
|
+
You can render immediately, no manual onready callback is required for basic flow.
|
|
48
|
+
|
|
49
|
+
## Step 4: Load an OBJ Model
|
|
50
|
+
|
|
51
|
+
```js
|
|
52
|
+
const objLoader = new OBJLoader();
|
|
53
|
+
|
|
54
|
+
const objRoot = objLoader.load({
|
|
55
|
+
paths: ["/models/model.obj"]
|
|
56
|
+
});
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
`objRoot` is available immediately and fills as data arrives.
|
|
60
|
+
You can include it in your render list right away.
|
|
61
|
+
|
|
62
|
+
## Step 5: Optionally Patch Imported OBJ Materials
|
|
63
|
+
|
|
64
|
+
If you want to force a change across imported meshes, use `postprocessor`.
|
|
65
|
+
An example is to assign a texture to all objects in an obj file
|
|
66
|
+
|
|
67
|
+
```js
|
|
68
|
+
const objRoot = objLoader.load({
|
|
69
|
+
paths: ["/models/obj/pirate_girl/pirate_girl.obj"],
|
|
70
|
+
postprocessor: (asset) => {
|
|
71
|
+
asset.traverseDFS((node) => {
|
|
72
|
+
if (node instanceof MeshMaterial3D) {
|
|
73
|
+
node.material.mainTexture = texture;
|
|
74
|
+
}
|
|
75
|
+
return true;
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Step 6: Load a glTF Scene
|
|
82
|
+
|
|
83
|
+
```js
|
|
84
|
+
const gltfLoader = new GLTFLoader();
|
|
85
|
+
|
|
86
|
+
const sceneRoot = gltfLoader.load({
|
|
87
|
+
paths: ["/models/pirate_girl.gltf"]
|
|
88
|
+
});
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Use glTF when you want richer material data and better modern tooling support.
|
|
92
|
+
|
|
93
|
+
## Step 7: Render Streaming Assets Safely
|
|
94
|
+
|
|
95
|
+
```js
|
|
96
|
+
function frame() {
|
|
97
|
+
renderer.render([object, objRoot, sceneRoot, camera], device);
|
|
98
|
+
requestAnimationFrame(frame);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
requestAnimationFrame(frame);
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Does not block rendering while waiting for loaders;
|
|
105
|
+
Render continuously with placeholders and loaded data will appear as they become ready.
|
|
106
|
+
|
|
107
|
+
## Path Rules That Prevent Most Loading Errors
|
|
108
|
+
|
|
109
|
+
1. Use forward slashes in URLs, even on Windows.
|
|
110
|
+
2. Use absolute app-root paths like `...` when possible.
|
|
111
|
+
3. Keep `.gltf` sidecar files (`.bin`, textures) in expected relative locations.
|
|
112
|
+
4. Confirm your dev server actually serves the asset directory.
|
|
113
|
+
|
|
114
|
+
## Reference Examples
|
|
115
|
+
|
|
116
|
+
- [OBJ Loader](/examples/loader/objloader)
|
|
117
|
+
- [glTF Loader](/examples/loader/gltfloader)
|
|
118
|
+
- [glTF Material Example](/examples/loader/gltf_material)
|
|
119
|
+
|
|
120
|
+
After this works, continue with [Scene Graph and Transforms](/guide/scene-graph-and-transforms)
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Troubleshooting"
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Troubleshooting
|
|
6
|
+
|
|
7
|
+
## Blank Canvas
|
|
8
|
+
|
|
9
|
+
- Confirm WebGL2 is available in your browser.
|
|
10
|
+
- Ensure you created `WebGLRenderDevice` with a valid canvas.
|
|
11
|
+
- Ensure `renderer.render([... , camera], device)` includes a camera.
|
|
12
|
+
|
|
13
|
+
```js
|
|
14
|
+
const device = new WebGLRenderDevice(canvas, { depth: true });
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Object Is Black or Unlit
|
|
18
|
+
|
|
19
|
+
- Add `LightPlugin` for lit materials.
|
|
20
|
+
- Add at least one light (`AmbientLight`, `DirectionalLight`, etc.).
|
|
21
|
+
- Keep `MeshMaterialPlugin` and `CameraPlugin` enabled.
|
|
22
|
+
|
|
23
|
+
## Distorted Aspect Ratio
|
|
24
|
+
|
|
25
|
+
Update canvas size and camera projection on resize.
|
|
26
|
+
|
|
27
|
+
```js
|
|
28
|
+
if (camera.projection instanceof PerspectiveProjection) {
|
|
29
|
+
camera.projection.aspect = innerWidth / innerHeight;
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Missing Textures or Models
|
|
34
|
+
|
|
35
|
+
- Use correct asset URLs under `...`.
|
|
36
|
+
- Check browser network tab for 404s.
|
|
37
|
+
- For cube maps, provide all six faces in the expected order.
|
|
38
|
+
|
|
39
|
+
## Shadows Not Visible
|
|
40
|
+
|
|
41
|
+
- Add `ShadowPlugin`.
|
|
42
|
+
- Assign `light.shadow` and tune `bias`/`normalBias`.
|
|
43
|
+
- Verify shadow camera bounds include your objects.
|
|
44
|
+
|
|
45
|
+
Useful full examples:
|
|
46
|
+
|
|
47
|
+
- [Rotating Cube](/examples/other/rotatingCube)
|
|
48
|
+
- [Directional Light](/examples/lights/directional)
|
|
49
|
+
- [Image Target](/examples/rendertarget/image_target)
|
package/env.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
declare module "*.glsl" {
|
|
2
|
+
const source: string;
|
|
3
|
+
|
|
4
|
+
export default source;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
// Assisted by ChatGPT 5.3 Codex
|
|
8
|
+
declare module "@examples/rendergraph_gui" {
|
|
9
|
+
export function addRenderGraphGuiAddon(options: {
|
|
10
|
+
gui: import("dat.gui").GUI
|
|
11
|
+
renderer: import("chorama").WebGLRenderer
|
|
12
|
+
title?: string
|
|
13
|
+
position?: { x: number; y: number }
|
|
14
|
+
width?: number
|
|
15
|
+
}): {
|
|
16
|
+
refresh: () => void
|
|
17
|
+
dispose: () => void
|
|
18
|
+
}
|
|
19
|
+
}
|