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.
Files changed (256) hide show
  1. package/.configs/tsconfig.lib.json +43 -0
  2. package/.configs/tsconfig.website.json +34 -0
  3. package/.github/workflows/static.yml +88 -0
  4. package/.vscode/launch.json +29 -0
  5. package/.vscode/tasks.json +19 -0
  6. package/README.md +127 -0
  7. package/assets/images/disappointed.jpg +0 -0
  8. package/assets/images/skybox/grimmnight_back.png +0 -0
  9. package/assets/images/skybox/grimmnight_bottom.png +0 -0
  10. package/assets/images/skybox/grimmnight_front.png +0 -0
  11. package/assets/images/skybox/grimmnight_left.png +0 -0
  12. package/assets/images/skybox/grimmnight_right.png +0 -0
  13. package/assets/images/skybox/grimmnight_top.png +0 -0
  14. package/assets/images/skybox/miramar_back.png +0 -0
  15. package/assets/images/skybox/miramar_bottom.png +0 -0
  16. package/assets/images/skybox/miramar_front.png +0 -0
  17. package/assets/images/skybox/miramar_left.png +0 -0
  18. package/assets/images/skybox/miramar_right.png +0 -0
  19. package/assets/images/skybox/miramar_top.png +0 -0
  20. package/assets/images/uv.jpg +0 -0
  21. package/assets/models/gltf/flight_helmet/FlightHelmet_Materials_GlassPlasticMat_BaseColor.png +0 -0
  22. package/assets/models/gltf/flight_helmet/FlightHelmet_Materials_GlassPlasticMat_Normal.png +0 -0
  23. package/assets/models/gltf/flight_helmet/FlightHelmet_Materials_GlassPlasticMat_OcclusionRoughMetal.png +0 -0
  24. package/assets/models/gltf/flight_helmet/FlightHelmet_Materials_LeatherPartsMat_BaseColor.png +0 -0
  25. package/assets/models/gltf/flight_helmet/FlightHelmet_Materials_LeatherPartsMat_Normal.png +0 -0
  26. package/assets/models/gltf/flight_helmet/FlightHelmet_Materials_LeatherPartsMat_OcclusionRoughMetal.png +0 -0
  27. package/assets/models/gltf/flight_helmet/FlightHelmet_Materials_LensesMat_BaseColor.png +0 -0
  28. package/assets/models/gltf/flight_helmet/FlightHelmet_Materials_LensesMat_Normal.png +0 -0
  29. package/assets/models/gltf/flight_helmet/FlightHelmet_Materials_LensesMat_OcclusionRoughMetal.png +0 -0
  30. package/assets/models/gltf/flight_helmet/FlightHelmet_Materials_MetalPartsMat_BaseColor.png +0 -0
  31. package/assets/models/gltf/flight_helmet/FlightHelmet_Materials_MetalPartsMat_Normal.png +0 -0
  32. package/assets/models/gltf/flight_helmet/FlightHelmet_Materials_MetalPartsMat_OcclusionRoughMetal.png +0 -0
  33. package/assets/models/gltf/flight_helmet/FlightHelmet_Materials_RubberWoodMat_BaseColor.png +0 -0
  34. package/assets/models/gltf/flight_helmet/FlightHelmet_Materials_RubberWoodMat_Normal.png +0 -0
  35. package/assets/models/gltf/flight_helmet/FlightHelmet_Materials_RubberWoodMat_OcclusionRoughMetal.png +0 -0
  36. package/assets/models/gltf/flight_helmet/index.bin +0 -0
  37. package/assets/models/gltf/flight_helmet/index.gltf +705 -0
  38. package/assets/models/gltf/object.gltf +23 -0
  39. package/assets/models/gltf/pirate_girl/index.bin +0 -0
  40. package/assets/models/gltf/pirate_girl/index.gltf +2082 -0
  41. package/assets/models/obj/pirate_girl/pirate_girl.obj +18459 -0
  42. package/assets/models/obj/pirate_girl/pirate_girl.png +0 -0
  43. package/astro.config.mjs +45 -0
  44. package/content/guide/api-map.md +89 -0
  45. package/content/guide/camera-and-controls.md +98 -0
  46. package/content/guide/first-scene.md +176 -0
  47. package/content/guide/index.md +72 -0
  48. package/content/guide/installation.md +179 -0
  49. package/content/guide/materials-and-lighting.md +138 -0
  50. package/content/guide/plugins-and-render-pipeline.md +124 -0
  51. package/content/guide/render-targets-and-views.md +147 -0
  52. package/content/guide/scene-graph-and-transforms.md +113 -0
  53. package/content/guide/textures-and-assets.md +120 -0
  54. package/content/guide/troubleshooting.md +49 -0
  55. package/env.d.ts +19 -0
  56. package/examples/addons/rendergraph_gui.js +580 -0
  57. package/examples/camera/orthographic.js +120 -0
  58. package/examples/camera/perspective.js +138 -0
  59. package/examples/lights/directional.js +397 -0
  60. package/examples/lights/multiple_spot_lights.js +304 -0
  61. package/examples/lights/point.js +337 -0
  62. package/examples/lights/spot.js +366 -0
  63. package/examples/loader/gltf_material.js +111 -0
  64. package/examples/loader/gltfloader.js +78 -0
  65. package/examples/loader/objloader.js +95 -0
  66. package/examples/material/cullface.js +111 -0
  67. package/examples/material/materials.js +126 -0
  68. package/examples/material/standard/basic.js +164 -0
  69. package/examples/mesh/circle.js +117 -0
  70. package/examples/mesh/cuboid.js +151 -0
  71. package/examples/mesh/cylinder.js +139 -0
  72. package/examples/mesh/geometries.js +108 -0
  73. package/examples/mesh/meshTopology.js +103 -0
  74. package/examples/mesh/plane.js +117 -0
  75. package/examples/mesh/skinning.js +136 -0
  76. package/examples/mesh/uvsphere.js +113 -0
  77. package/examples/other/rotatingCube.js +93 -0
  78. package/examples/other/rotatingSphere.js +96 -0
  79. package/examples/rendertarget/basic_canvas.js +130 -0
  80. package/examples/rendertarget/depth_texture.js +130 -0
  81. package/examples/rendertarget/image_target.js +140 -0
  82. package/examples/rendertarget/multiple_views.js +158 -0
  83. package/examples/rendertarget/render_masks.js +173 -0
  84. package/examples/rendertarget/split_screen.js +123 -0
  85. package/examples/rendertarget/split_view.js +137 -0
  86. package/examples/skybox/skybox.js +111 -0
  87. package/examples/texture/arrays.js +156 -0
  88. package/examples/texture/textureWrap.js +118 -0
  89. package/examples/transform/propagation.js +92 -0
  90. package/package.json +55 -0
  91. package/rollup.config.js +66 -0
  92. package/scripts/stage-chorama.mjs +29 -0
  93. package/src/caches/cache.js +420 -0
  94. package/src/caches/index.js +2 -0
  95. package/src/caches/uniformbuffers.js +104 -0
  96. package/src/cameracontrols/index.js +258 -0
  97. package/src/constants/index.js +3 -0
  98. package/src/constants/mesh.js +197 -0
  99. package/src/constants/others.js +218 -0
  100. package/src/constants/texture.js +183 -0
  101. package/src/core/constants.js +14 -0
  102. package/src/core/extensions.js +42 -0
  103. package/src/core/index.js +7 -0
  104. package/src/core/layouts/index.js +4 -0
  105. package/src/core/layouts/meshvertex.js +60 -0
  106. package/src/core/layouts/uniform.js +21 -0
  107. package/src/core/layouts/uniformbuffer.js +15 -0
  108. package/src/core/layouts/vertexbuffer.js +43 -0
  109. package/src/core/limits.js +247 -0
  110. package/src/core/resources/blendparams.js +89 -0
  111. package/src/core/resources/framebuffer.js +127 -0
  112. package/src/core/resources/gpubuffer.js +32 -0
  113. package/src/core/resources/gpumesh.js +43 -0
  114. package/src/core/resources/gputexture.js +73 -0
  115. package/src/core/resources/index.js +5 -0
  116. package/src/core/shader.js +62 -0
  117. package/src/core/webgl/bindgroup.js +89 -0
  118. package/src/core/webgl/descriptors.js +104 -0
  119. package/src/core/webgl/index.js +5 -0
  120. package/src/core/webgl/renderpassencoder.js +96 -0
  121. package/src/core/webgl/renderpipeline.js +54 -0
  122. package/src/core/webgl/utils.js +371 -0
  123. package/src/core/webgl/webglrenderdevice.js +235 -0
  124. package/src/function.js +358 -0
  125. package/src/index.js +15 -0
  126. package/src/loader/gltf.js +2172 -0
  127. package/src/loader/index.js +3 -0
  128. package/src/loader/loader.js +174 -0
  129. package/src/loader/obj.js +188 -0
  130. package/src/loader/texture.js +85 -0
  131. package/src/loader/utils.js +16 -0
  132. package/src/material/basic.js +75 -0
  133. package/src/material/depth.js +73 -0
  134. package/src/material/index.js +8 -0
  135. package/src/material/lambert.js +73 -0
  136. package/src/material/material.js +106 -0
  137. package/src/material/normal.js +30 -0
  138. package/src/material/phong.js +86 -0
  139. package/src/material/raw.js +52 -0
  140. package/src/material/standard.js +221 -0
  141. package/src/math/index.js +3 -0
  142. package/src/math/transform.js +38 -0
  143. package/src/mesh/attribute/attribute.js +79 -0
  144. package/src/mesh/attribute/index.js +1 -0
  145. package/src/mesh/attributedata/index.js +1 -0
  146. package/src/mesh/attributedata/separate.js +180 -0
  147. package/src/mesh/builders/base.js +41 -0
  148. package/src/mesh/builders/circle.js +63 -0
  149. package/src/mesh/builders/cuboid.js +135 -0
  150. package/src/mesh/builders/cylinder.js +131 -0
  151. package/src/mesh/builders/index.js +7 -0
  152. package/src/mesh/builders/plane.js +73 -0
  153. package/src/mesh/builders/utils.js +20 -0
  154. package/src/mesh/builders/uvsphere.js +80 -0
  155. package/src/mesh/builders/wireframe.js +62 -0
  156. package/src/mesh/index.js +4 -0
  157. package/src/mesh/mesh.js +149 -0
  158. package/src/objects/bone.js +17 -0
  159. package/src/objects/camera/camera.js +56 -0
  160. package/src/objects/camera/index.js +2 -0
  161. package/src/objects/camera/projection.js +203 -0
  162. package/src/objects/debug/index.js +1 -0
  163. package/src/objects/debug/skeleton.js +28 -0
  164. package/src/objects/index.js +7 -0
  165. package/src/objects/light/ambient.js +20 -0
  166. package/src/objects/light/directional.js +29 -0
  167. package/src/objects/light/index.js +5 -0
  168. package/src/objects/light/point.js +32 -0
  169. package/src/objects/light/shadow/index.js +1 -0
  170. package/src/objects/light/shadow/shadow.js +67 -0
  171. package/src/objects/light/spot.js +56 -0
  172. package/src/objects/mesh.js +141 -0
  173. package/src/objects/object3d.js +167 -0
  174. package/src/objects/skybox.js +38 -0
  175. package/src/plugins/camera/camera.js +19 -0
  176. package/src/plugins/camera/index.js +2 -0
  177. package/src/plugins/camera/nodes/cameraview.js +46 -0
  178. package/src/plugins/camera/nodes/index.js +2 -0
  179. package/src/plugins/camera/nodes/opaquepass.js +79 -0
  180. package/src/plugins/index.js +6 -0
  181. package/src/plugins/light/index.js +2 -0
  182. package/src/plugins/light/light.js +23 -0
  183. package/src/plugins/light/nodes/index.js +1 -0
  184. package/src/plugins/light/nodes/light.js +127 -0
  185. package/src/plugins/meshmaterial/index.js +3 -0
  186. package/src/plugins/meshmaterial/meshmaterial.js +381 -0
  187. package/src/plugins/meshmaterial/nodes/index.js +1 -0
  188. package/src/plugins/meshmaterial/nodes/meshmaterial.js +50 -0
  189. package/src/plugins/meshmaterial/resources/index.js +1 -0
  190. package/src/plugins/meshmaterial/resources/meshmaterialpipelines.js +50 -0
  191. package/src/plugins/shadow/index.js +3 -0
  192. package/src/plugins/shadow/nodes/index.js +3 -0
  193. package/src/plugins/shadow/nodes/shadow.js +272 -0
  194. package/src/plugins/shadow/nodes/shadowOccluder.js +112 -0
  195. package/src/plugins/shadow/nodes/shadowOpaquePass.js +73 -0
  196. package/src/plugins/shadow/resources/ShadowMap.js +99 -0
  197. package/src/plugins/shadow/resources/index.js +2 -0
  198. package/src/plugins/shadow/resources/shadowpipelines.js +25 -0
  199. package/src/plugins/shadow/shadow.js +31 -0
  200. package/src/plugins/skeletonhelper/index.js +1 -0
  201. package/src/plugins/skeletonhelper/skeletonhelper.js +160 -0
  202. package/src/plugins/skybox/index.js +3 -0
  203. package/src/plugins/skybox/nodes/index.js +1 -0
  204. package/src/plugins/skybox/nodes/skybox.js +143 -0
  205. package/src/plugins/skybox/resources/index.js +2 -0
  206. package/src/plugins/skybox/resources/skyboxmesh.js +14 -0
  207. package/src/plugins/skybox/resources/skyboxpipeline.js +6 -0
  208. package/src/plugins/skybox/skybox.js +137 -0
  209. package/src/renderer/core/index.js +179 -0
  210. package/src/renderer/graph/index.js +3 -0
  211. package/src/renderer/graph/nodes.js +34 -0
  212. package/src/renderer/graph/rendergraph.js +182 -0
  213. package/src/renderer/index.js +5 -0
  214. package/src/renderer/plugin.js +36 -0
  215. package/src/renderer/renderer.js +179 -0
  216. package/src/renderer/views.js +28 -0
  217. package/src/rendertarget/canvastarget.js +30 -0
  218. package/src/rendertarget/image.js +132 -0
  219. package/src/rendertarget/index.js +3 -0
  220. package/src/rendertarget/rendertarget.js +89 -0
  221. package/src/shader/basicFragment.glsl +30 -0
  222. package/src/shader/basicVertex.glsl +87 -0
  223. package/src/shader/common/color.glsl +7 -0
  224. package/src/shader/common/common.glsl +25 -0
  225. package/src/shader/common/index.js +4 -0
  226. package/src/shader/common/light.glsl +437 -0
  227. package/src/shader/common/math.glsl +12 -0
  228. package/src/shader/debug/index.js +2 -0
  229. package/src/shader/debug/skeletonFragment.glsl +8 -0
  230. package/src/shader/debug/skeletonVertex.glsl +27 -0
  231. package/src/shader/depthFragment.glsl +37 -0
  232. package/src/shader/index.js +11 -0
  233. package/src/shader/lambertFragment.glsl +126 -0
  234. package/src/shader/normalFragment.glsl +25 -0
  235. package/src/shader/phongFragment.glsl +140 -0
  236. package/src/shader/skyboxFragment.glsl +16 -0
  237. package/src/shader/skyboxVertex.glsl +20 -0
  238. package/src/shader/standardFragment.glsl +274 -0
  239. package/src/texture/index.js +2 -0
  240. package/src/texture/sampler.js +111 -0
  241. package/src/texture/texture.js +234 -0
  242. package/src/utils/index.js +115 -0
  243. package/tsconfig.json +11 -0
  244. package/website/config/index.ts +1 -0
  245. package/website/config/navigation.ts +53 -0
  246. package/website/content.config.ts +92 -0
  247. package/website/layouts/DocLayout.astro +501 -0
  248. package/website/layouts/Example.astro +91 -0
  249. package/website/pages/examples/[...slug].astro +77 -0
  250. package/website/pages/examples/index.astro +98 -0
  251. package/website/pages/examples/samples/[...slug].astro +17 -0
  252. package/website/pages/guide/[slug].astro +30 -0
  253. package/website/pages/guide/index.astro +21 -0
  254. package/website/pages/index.astro +9 -0
  255. package/website/plugins/remark-link-base.js +23 -0
  256. package/website/utils/url.ts +30 -0
@@ -0,0 +1,304 @@
1
+ import {
2
+ MeshMaterial3D,
3
+ WebGLRenderer,
4
+ TextureLoader,
5
+ PerspectiveProjection,
6
+ Camera,
7
+ WebGLRenderDevice,
8
+ PlaneMeshBuilder,
9
+ OrbitCameraControls,
10
+ MeshMaterialPlugin,
11
+ ShadowPlugin,
12
+ LightPlugin,
13
+ DirectionalLight,
14
+ AmbientLight,
15
+ TextureType,
16
+ SkyBox,
17
+ UVSphereMeshBuilder,
18
+ CanvasTarget,
19
+ CuboidMeshBuilder,
20
+ LambertMaterial,
21
+ SkyboxPlugin,
22
+ SpotLight,
23
+ SpotLightShadow,
24
+ PCFShadowFilter,
25
+ PCSSShadowFilter,
26
+ Affine3,
27
+ Vector3,
28
+ BasicMaterial,
29
+ Color,
30
+ Object3D,
31
+ CameraPlugin
32
+ } from "chorama"
33
+ import { GUI } from "dat.gui"
34
+ import { addRenderGraphGuiAddon } from "@examples/rendergraph_gui"
35
+
36
+ const canvas = document.createElement('canvas')
37
+ const renderTarget = new CanvasTarget(canvas)
38
+ const renderDevice = new WebGLRenderDevice(canvas, {
39
+ depth: true
40
+ })
41
+ const renderer = new WebGLRenderer({
42
+ plugins: [
43
+ new CameraPlugin(),
44
+ new ShadowPlugin(),
45
+ new LightPlugin(),
46
+ new SkyboxPlugin(),
47
+ new MeshMaterialPlugin(),
48
+ ]
49
+ })
50
+
51
+ // assets and loaders
52
+ const textureLoader = new TextureLoader()
53
+ const texture = textureLoader.load({
54
+ paths: ["/images/uv.jpg"],
55
+ })
56
+ const skyboxTexture = textureLoader.load({
57
+ paths: [
58
+ "/images/skybox/miramar_right.png",
59
+ "/images/skybox/miramar_left.png",
60
+ "/images/skybox/miramar_top.png",
61
+ "/images/skybox/miramar_bottom.png",
62
+ "/images/skybox/miramar_back.png",
63
+ "/images/skybox/miramar_front.png",
64
+ ],
65
+ type: TextureType.TextureCubeMap,
66
+ })
67
+ const material = new LambertMaterial({
68
+ mainTexture: texture
69
+ })
70
+ const arrowBuilder = new CuboidMeshBuilder()
71
+ const meshBuilder = new PlaneMeshBuilder()
72
+
73
+ meshBuilder.width = 10
74
+ meshBuilder.height = 10
75
+ arrowBuilder.width = 0.1
76
+ arrowBuilder.height = 0.1
77
+ arrowBuilder.depth = 1
78
+
79
+ // objects
80
+ const ambientLight = new AmbientLight()
81
+ const sun = new DirectionalLight()
82
+ const spotShadow = new SpotLightShadow()
83
+ const lights = createLights()
84
+ const camera = new Camera(renderTarget)
85
+ const cameraControls = new OrbitCameraControls(camera, canvas)
86
+
87
+ const skyBox = new SkyBox({
88
+ day: skyboxTexture
89
+ })
90
+ const ground = new MeshMaterial3D(meshBuilder.build(), material)
91
+ const objects = createObjects()
92
+
93
+ ambientLight.intensity = 0.15
94
+ sun.transform.position.y = 2
95
+ sun.transform.position.z = 0
96
+ sun.transform.orientation.rotateX(- Math.PI / 2)
97
+ sun.intensity = 0.01
98
+
99
+ skyBox.transform.orientation.rotateY(Math.PI)
100
+ ground.transform.orientation.rotateX(-Math.PI / 2)
101
+
102
+ //set up the camera
103
+ cameraControls.distance = 3
104
+ if (camera.projection instanceof PerspectiveProjection) {
105
+ camera.projection.fov = Math.PI / 180 * 75
106
+ camera.projection.aspect = innerWidth / innerHeight
107
+ }
108
+
109
+ document.body.append(canvas)
110
+ addEventListener("resize", updateView)
111
+ updateView()
112
+ requestAnimationFrame(update)
113
+
114
+ function createObjects() {
115
+ const results = []
116
+ const meshBuilder2 = new UVSphereMeshBuilder()
117
+
118
+
119
+ meshBuilder2.radius = 0.25
120
+ const sphereMesh = meshBuilder2.build()
121
+
122
+ for (let x = -5; x < 5; x++) {
123
+ for (let y = -5; y < 5; y++) {
124
+ const object = new MeshMaterial3D(sphereMesh, material)
125
+
126
+ object.transform.position.x = x
127
+ object.transform.position.y = 0.5
128
+ object.transform.position.z = y
129
+ results.push(object)
130
+ }
131
+ }
132
+
133
+ return results
134
+ }
135
+
136
+ function createLights() {
137
+ const builder = new CuboidMeshBuilder()
138
+ const width = 10
139
+ const height = 10
140
+ const tallness = 4
141
+ const scale = 0.1
142
+ const lights = new Object3D()
143
+
144
+ builder.width = 0.1
145
+ builder.height = 0.1
146
+ builder.depth = 1
147
+
148
+ const mesh = builder.build()
149
+ for (let x = -width / 2; x <= width / 2; x += width) {
150
+ for (let y = -height / 2; y <= height / 2; y += height) {
151
+ const light = new SpotLight()
152
+ const helper = new MeshMaterial3D(mesh, new BasicMaterial({
153
+ color: Color.RED.clone()
154
+ }))
155
+ const space = new Affine3()
156
+
157
+ space.translate(new Vector3(x, tallness, y))
158
+ space.lookAt(new Vector3(x * scale, 0, y * scale), Vector3.Y)
159
+
160
+ const [position, orientation, _scale] = space.decompose()
161
+
162
+ helper.transform.position.z -= 0.5
163
+ light.intensity = 1
164
+ light.range = 20
165
+ light.outerAngle = Math.PI / 8
166
+ light.shadow = spotShadow
167
+ light.transform.position.copy(position)
168
+ light.transform.orientation.copy(orientation)
169
+ light.add(helper)
170
+ lights.add(light)
171
+ }
172
+ }
173
+ return lights
174
+ }
175
+
176
+ function update() {
177
+ cameraControls.update()
178
+ lights.transform.orientation.rotateY(0.01)
179
+ renderer.render([ground, ...objects, sun, lights, ambientLight, skyBox, camera], renderDevice)
180
+ requestAnimationFrame(update)
181
+ }
182
+
183
+ function updateView() {
184
+ canvas.style.width = innerWidth + "px"
185
+ canvas.style.height = innerHeight + "px"
186
+ canvas.width = innerWidth * devicePixelRatio
187
+ canvas.height = innerHeight * devicePixelRatio
188
+
189
+ if (camera.projection instanceof PerspectiveProjection) {
190
+ camera.projection.aspect = innerWidth / innerHeight
191
+ }
192
+ }
193
+
194
+ const settings = {
195
+ shadow: true
196
+ }
197
+ const shadowFilterSettings = {
198
+ mode: 'None',
199
+ get radius() {
200
+ return (spotShadow.filterMode instanceof PCFShadowFilter || spotShadow.filterMode instanceof PCSSShadowFilter)
201
+ ? spotShadow.filterMode.radius
202
+ : 1
203
+ },
204
+ set radius(value) {
205
+ if (spotShadow.filterMode instanceof PCFShadowFilter || spotShadow.filterMode instanceof PCSSShadowFilter) {
206
+ spotShadow.filterMode.radius = value
207
+ }
208
+ },
209
+ get searchRadius() {
210
+ return spotShadow.filterMode instanceof PCSSShadowFilter ? spotShadow.filterMode.searchRadius : 2
211
+ },
212
+ set searchRadius(value) {
213
+ if (spotShadow.filterMode instanceof PCSSShadowFilter) {
214
+ spotShadow.filterMode.searchRadius = value
215
+ }
216
+ },
217
+ get penumbra() {
218
+ return spotShadow.filterMode instanceof PCSSShadowFilter ? spotShadow.filterMode.penumbra : 1
219
+ },
220
+ set penumbra(value) {
221
+ if (spotShadow.filterMode instanceof PCSSShadowFilter) {
222
+ spotShadow.filterMode.penumbra = value
223
+ }
224
+ }
225
+ }
226
+ const controls = new GUI()
227
+ const shadowFolder = controls.addFolder("Shadows")
228
+ /**
229
+ * @type {import("dat.gui").GUIController<object>}
230
+ */
231
+ let shadowRadiusControl
232
+ /** @type {import("dat.gui").GUIController<object>} */
233
+ let shadowSearchRadiusControl
234
+ /** @type {import("dat.gui").GUIController<object>} */
235
+ let shadowPenumbraControl
236
+
237
+ shadowFolder
238
+ .add(settings, 'shadow')
239
+ .name("Enable Shadow")
240
+ .onChange(toggleShadows)
241
+ spotShadow.filterMode = undefined
242
+ shadowFolder
243
+ .add(shadowFilterSettings, 'mode', ['None', 'PCF', 'PCSS'])
244
+ .name("Shadow Filter")
245
+ .onChange(updateShadowFilterMode)
246
+ shadowRadiusControl = shadowFolder
247
+ .add(shadowFilterSettings, 'radius', 0, 4, 0.1)
248
+ .name("PCF Radius")
249
+ shadowSearchRadiusControl = shadowFolder
250
+ .add(shadowFilterSettings, 'searchRadius', 0, 8, 0.1)
251
+ .name("PCSS Search Radius")
252
+ shadowPenumbraControl = shadowFolder
253
+ .add(shadowFilterSettings, 'penumbra', 0, 6, 0.1)
254
+ .name("PCSS Penumbra")
255
+ updateShadowFilterControls()
256
+ shadowFolder.open()
257
+
258
+ /**
259
+ * @param {boolean} value
260
+ */
261
+ function toggleShadows(value) {
262
+ if (value) {
263
+ lights.traverseDFS(light => {
264
+ if(light instanceof SpotLight){
265
+ light.shadow = spotShadow
266
+ }
267
+ return true
268
+ })
269
+ } else {
270
+ lights.traverseDFS(light => {
271
+ if(light instanceof SpotLight){
272
+ light.shadow = undefined
273
+ }
274
+ return true
275
+ })
276
+ }
277
+ }
278
+
279
+ function updateShadowFilterControls() {
280
+ const isPCF = spotShadow.filterMode instanceof PCFShadowFilter
281
+ const isPCSS = spotShadow.filterMode instanceof PCSSShadowFilter
282
+ shadowRadiusControl.domElement.style.display = (isPCF || isPCSS) ? '' : 'none'
283
+ shadowSearchRadiusControl.domElement.style.display = isPCSS ? '' : 'none'
284
+ shadowPenumbraControl.domElement.style.display = isPCSS ? '' : 'none'
285
+ }
286
+
287
+ /**
288
+ * @param {string} value
289
+ */
290
+ function updateShadowFilterMode(value) {
291
+ if (value === 'PCF') {
292
+ spotShadow.filterMode = new PCFShadowFilter()
293
+ } else if (value === 'PCSS') {
294
+ spotShadow.filterMode = new PCSSShadowFilter()
295
+ } else {
296
+ spotShadow.filterMode = undefined
297
+ }
298
+ updateShadowFilterControls()
299
+ }
300
+
301
+ addRenderGraphGuiAddon({
302
+ gui: controls,
303
+ renderer
304
+ })
@@ -0,0 +1,337 @@
1
+ import {
2
+ MeshMaterial3D,
3
+ WebGLRenderer,
4
+ TextureLoader,
5
+ PerspectiveProjection,
6
+ Camera,
7
+ WebGLRenderDevice,
8
+ PlaneMeshBuilder,
9
+ OrbitCameraControls,
10
+ MeshMaterialPlugin,
11
+ LightPlugin,
12
+ AmbientLight,
13
+ TextureType,
14
+ SkyBox,
15
+ UVSphereMeshBuilder,
16
+ LambertMaterial,
17
+ PointLight,
18
+ BasicMaterial,
19
+ Color,
20
+ PhongMaterial,
21
+ StandardMaterial,
22
+ CanvasTarget,
23
+ SkyboxPlugin,
24
+ ShadowPlugin,
25
+ PCFShadowFilter,
26
+ PCSSShadowFilter,
27
+ SpotLightShadow,
28
+ CameraPlugin
29
+ } from "chorama"
30
+ import { GUI } from "dat.gui"
31
+ import { addRenderGraphGuiAddon } from "@examples/rendergraph_gui"
32
+
33
+ const canvas = document.createElement('canvas')
34
+ const renderTarget = new CanvasTarget(canvas)
35
+ const renderDevice = new WebGLRenderDevice(canvas, {
36
+ depth: true
37
+ })
38
+ const renderer = new WebGLRenderer({
39
+ plugins: [
40
+ new CameraPlugin(),
41
+ new ShadowPlugin(),
42
+ new LightPlugin(),
43
+ new SkyboxPlugin(),
44
+ new MeshMaterialPlugin(),
45
+ ]
46
+ })
47
+
48
+ // assets and loaders
49
+ const textureLoader = new TextureLoader()
50
+ const texture = textureLoader.load({
51
+ paths: ["/images/uv.jpg"],
52
+ })
53
+ /**@type {[LambertMaterial, PhongMaterial,StandardMaterial]} */
54
+ const materials = [
55
+ new LambertMaterial({
56
+ mainTexture: texture
57
+ }),
58
+ new PhongMaterial({
59
+ mainTexture: texture
60
+ }),
61
+ new StandardMaterial({
62
+ mainTexture: texture,
63
+ roughness: 0.4,
64
+ metallic: 0
65
+ })
66
+ ]
67
+ const meshBuilder = new PlaneMeshBuilder()
68
+ const lightMeshBuilder = new UVSphereMeshBuilder()
69
+ const environmentTexture = textureLoader.load({
70
+ paths: [
71
+ "/images/skybox/miramar_right.png",
72
+ "/images/skybox/miramar_left.png",
73
+ "/images/skybox/miramar_top.png",
74
+ "/images/skybox/miramar_bottom.png",
75
+ "/images/skybox/miramar_back.png",
76
+ "/images/skybox/miramar_front.png",
77
+ ],
78
+ type: TextureType.TextureCubeMap,
79
+ })
80
+
81
+ lightMeshBuilder.radius = 0.1
82
+ meshBuilder.width = 10
83
+ meshBuilder.height = 10
84
+
85
+ // objects
86
+ const ambientLight = new AmbientLight()
87
+ const shadow = new SpotLightShadow()
88
+ const shadowFilterSettings = {
89
+ mode: 'None',
90
+ get radius() {
91
+ return (shadow.filterMode instanceof PCFShadowFilter || shadow.filterMode instanceof PCSSShadowFilter)
92
+ ? shadow.filterMode.radius
93
+ : 1
94
+ },
95
+ set radius(value) {
96
+ if (shadow.filterMode instanceof PCFShadowFilter || shadow.filterMode instanceof PCSSShadowFilter) {
97
+ shadow.filterMode.radius = value
98
+ }
99
+ },
100
+ get searchRadius() {
101
+ return shadow.filterMode instanceof PCSSShadowFilter ? shadow.filterMode.searchRadius : 2
102
+ },
103
+ set searchRadius(value) {
104
+ if (shadow.filterMode instanceof PCSSShadowFilter) {
105
+ shadow.filterMode.searchRadius = value
106
+ }
107
+ },
108
+ get penumbra() {
109
+ return shadow.filterMode instanceof PCSSShadowFilter ? shadow.filterMode.penumbra : 1
110
+ },
111
+ set penumbra(value) {
112
+ if (shadow.filterMode instanceof PCSSShadowFilter) {
113
+ shadow.filterMode.penumbra = value
114
+ }
115
+ }
116
+ }
117
+ const light = new PointLight()
118
+ const camera = new Camera(renderTarget)
119
+ const cameraControls = new OrbitCameraControls(camera, canvas)
120
+ const skyBox = new SkyBox({
121
+ day: environmentTexture
122
+ })
123
+ const ground = new MeshMaterial3D(meshBuilder.build(), materials[0])
124
+ const objects = createObjects()
125
+ const lightHelper = new MeshMaterial3D(lightMeshBuilder.build(), new BasicMaterial({
126
+ color: new Color(1, 0, 0)
127
+ }))
128
+
129
+ light.intensity = 1
130
+ light.shadow = shadow
131
+ light.radius = 5
132
+ shadow.filterMode = undefined
133
+ light.add(lightHelper)
134
+ light.transform.position.y = 1
135
+ ambientLight.intensity = 0.15
136
+ skyBox.transform.orientation.rotateY(Math.PI)
137
+ ground.transform.orientation.rotateX(-Math.PI / 2)
138
+
139
+ //set up the camera
140
+ cameraControls.distance = 2
141
+ if (camera.projection instanceof PerspectiveProjection) {
142
+ camera.projection.fov = Math.PI / 180 * 75
143
+ camera.projection.aspect = innerWidth / innerHeight
144
+ }
145
+
146
+ document.body.append(canvas)
147
+ addEventListener("resize", updateView)
148
+ updateView()
149
+ requestAnimationFrame(update)
150
+
151
+ function createObjects() {
152
+ const results = []
153
+ const meshBuilder2 = new UVSphereMeshBuilder()
154
+ meshBuilder2.radius = 0.25
155
+ const sphereMesh = meshBuilder2.build()
156
+
157
+ for (let x = -5; x < 5; x++) {
158
+ for (let y = -5; y < 5; y++) {
159
+ const object = new MeshMaterial3D(sphereMesh, materials[0])
160
+
161
+ object.transform.position.x = x
162
+ object.transform.position.y = 0.5
163
+ object.transform.position.z = y
164
+ results.push(object)
165
+ }
166
+ }
167
+
168
+ return results
169
+ }
170
+
171
+ function update() {
172
+ cameraControls.update()
173
+ renderer.render([ground, ...objects, light, ambientLight, skyBox, camera], renderDevice)
174
+ requestAnimationFrame(update)
175
+ }
176
+
177
+ function updateView() {
178
+ canvas.style.width = innerWidth + "px"
179
+ canvas.style.height = innerHeight + "px"
180
+ canvas.width = innerWidth * devicePixelRatio
181
+ canvas.height = innerHeight * devicePixelRatio
182
+
183
+ if (camera.projection instanceof PerspectiveProjection) {
184
+ camera.projection.aspect = innerWidth / innerHeight
185
+ }
186
+ }
187
+
188
+ // gui controls
189
+ const options = [
190
+ 'LAMBERT',
191
+ 'PHONG',
192
+ 'STANDARD'
193
+ ]
194
+ const settings = {
195
+ x: light.transform.position.x,
196
+ y: light.transform.position.y,
197
+ z: light.transform.position.z,
198
+ color: {
199
+ r: 0,
200
+ g: 0,
201
+ b: 0
202
+ },
203
+ material: options[0],
204
+ shadow: true
205
+ }
206
+ const controls = new GUI()
207
+ const lightFolder = controls.addFolder("Light")
208
+ const shadowFolder = controls.addFolder("Shadow")
209
+ /**
210
+ * @type {import("dat.gui").GUIController<object>}
211
+ */
212
+ let shadowRadiusControl
213
+ /** @type {import("dat.gui").GUIController<object>} */
214
+ let shadowSearchRadiusControl
215
+ /** @type {import("dat.gui").GUIController<object>} */
216
+ let shadowPenumbraControl
217
+ lightFolder
218
+ .add(light.transform.position, 'x', -10, 10)
219
+ .name("Translate X")
220
+ lightFolder
221
+ .add(light.transform.position, 'y', 0, 2)
222
+ .name("Translate Y")
223
+ lightFolder
224
+ .add(light.transform.position, 'z', -10, 10)
225
+ .name("Translate Z")
226
+ lightFolder
227
+ .add(light, 'intensity', 0, 100)
228
+ .name("Intensity")
229
+ lightFolder
230
+ .add(light, 'radius', 0, 10)
231
+ .name("Falloff Radius")
232
+ lightFolder
233
+ .add(light, 'decay', 0, 100)
234
+ .name("Decay")
235
+ lightFolder
236
+ .add(settings, 'material', options)
237
+ .name("Material")
238
+ .onChange(changeMaterial)
239
+ lightFolder
240
+ .addColor(settings, 'color')
241
+ .name('Color')
242
+ .onChange((value) => {
243
+ light.color.set(
244
+ value.r / 255,
245
+ value.g / 255,
246
+ value.b / 255
247
+ )
248
+ })
249
+ shadowFolder
250
+ .add(settings, 'shadow')
251
+ .name("Enable Shadow")
252
+ .onChange(toggleShadows)
253
+ shadowFolder
254
+ .add(shadow, 'near', 0.01, 1)
255
+ .name('Near')
256
+ shadowFolder
257
+ .add(shadow, 'bias', 0, 1)
258
+ .name('Bias')
259
+ shadowFolder
260
+ .add(shadow, 'normalBias', 0, 0.005)
261
+ .name('Normal Bias')
262
+ shadowFolder
263
+ .add(shadowFilterSettings, 'mode', ['None', 'PCF', 'PCSS'])
264
+ .name('Shadow Filter')
265
+ .onChange(updateShadowFilterMode)
266
+ shadowRadiusControl = shadowFolder
267
+ .add(shadowFilterSettings, 'radius', 0, 4, 0.1)
268
+ .name('PCF Radius')
269
+ shadowSearchRadiusControl = shadowFolder
270
+ .add(shadowFilterSettings, 'searchRadius', 0, 8, 0.1)
271
+ .name('PCSS Search Radius')
272
+ shadowPenumbraControl = shadowFolder
273
+ .add(shadowFilterSettings, 'penumbra', 0, 6, 0.1)
274
+ .name('PCSS Penumbra')
275
+ updateShadowFilterControls()
276
+
277
+ shadowFolder.open()
278
+ lightFolder.open()
279
+ /**
280
+ * @param {string} value
281
+ */
282
+ function changeMaterial(value) {
283
+ switch (value) {
284
+ case options[0]:
285
+ objects.forEach((o) => o.material = materials[0])
286
+ ground.material = materials[0]
287
+ break;
288
+ case options[1]:
289
+ objects.forEach((o) => o.material = materials[1])
290
+ ground.material = materials[1]
291
+ break;
292
+ case options[2]:
293
+ objects.forEach((o) => o.material = materials[2])
294
+ ground.material = materials[2]
295
+ break;
296
+ default:
297
+ break;
298
+ }
299
+ }
300
+
301
+ /**
302
+ * @param {boolean} value
303
+ */
304
+ function toggleShadows(value) {
305
+ if (value) {
306
+ light.shadow = shadow
307
+ } else {
308
+ light.shadow = undefined
309
+ }
310
+ }
311
+
312
+ function updateShadowFilterControls() {
313
+ const isPCF = shadow.filterMode instanceof PCFShadowFilter
314
+ const isPCSS = shadow.filterMode instanceof PCSSShadowFilter
315
+ shadowRadiusControl.domElement.style.display = (isPCF || isPCSS) ? '' : 'none'
316
+ shadowSearchRadiusControl.domElement.style.display = isPCSS ? '' : 'none'
317
+ shadowPenumbraControl.domElement.style.display = isPCSS ? '' : 'none'
318
+ }
319
+
320
+ /**
321
+ * @param {string} value
322
+ */
323
+ function updateShadowFilterMode(value) {
324
+ if (value === 'PCF') {
325
+ shadow.filterMode = new PCFShadowFilter()
326
+ } else if (value === 'PCSS') {
327
+ shadow.filterMode = new PCSSShadowFilter()
328
+ } else {
329
+ shadow.filterMode = undefined
330
+ }
331
+ updateShadowFilterControls()
332
+ }
333
+
334
+ addRenderGraphGuiAddon({
335
+ gui: controls,
336
+ renderer
337
+ })