├── README.md
├── package.json
├── src
├── index.html
├── script.js
└── style.css
├── static
├── bush
│ └── leaves_forest_ground_1k
│ │ ├── leaves_forest_ground_arm_1k.webp
│ │ ├── leaves_forest_ground_diff_1k.webp
│ │ └── leaves_forest_ground_nor_gl_1k.webp
├── door
│ ├── alpha.webp
│ ├── ambientOcclusion.webp
│ ├── color.webp
│ ├── height.webp
│ ├── metalness.webp
│ ├── normal.webp
│ └── roughness.webp
├── floor
│ ├── alpha.webp
│ └── coast_sand_rocks_02_1k
│ │ ├── coast_sand_rocks_02_arm_1k.webp
│ │ ├── coast_sand_rocks_02_diff_1k.webp
│ │ ├── coast_sand_rocks_02_disp_1k.webp
│ │ └── coast_sand_rocks_02_nor_gl_1k.webp
├── grave
│ └── plastered_stone_wall_1k
│ │ ├── plastered_stone_wall_arm_1k.webp
│ │ ├── plastered_stone_wall_diff_1k.webp
│ │ └── plastered_stone_wall_nor_gl_1k.webp
├── roof
│ └── roof_slates_02_1k
│ │ ├── roof_slates_02_arm_1k.webp
│ │ ├── roof_slates_02_diff_1k.webp
│ │ └── roof_slates_02_nor_gl_1k.webp
└── wall
│ └── castle_brick_broken_06_1k
│ ├── castle_brick_broken_06_arm_1k.webp
│ ├── castle_brick_broken_06_diff_1k.webp
│ └── castle_brick_broken_06_nor_gl_1k.webp
└── vite.config.js
/README.md:
--------------------------------------------------------------------------------
1 | # Haunted House using Three.js
2 |
3 | 
4 |
5 | In this project, we'll be creating a spooky scene entirely from primitive shapes using Three.js. The goal is to learn how to build a real project without relying on pre-made models, focusing on mastering primitive shapes and enhancing the scene with textures and effects.
6 |
7 | ## Installation
8 |
9 | - Run npm install to install dependencies
10 | - Run npm run dev to launch the local server
11 |
12 | ## Live Demo
13 |
14 | [https://neon-conkies-f9e9e4.netlify.app/](https://6675708d6a08c6792eeb4bc5--cosmic-puffpuff-6a7e94.netlify.app/)
15 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "haunted-house",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "vite build"
9 | },
10 | "devDependencies": {
11 | "vite": "^5.2.10",
12 | "vite-plugin-restart": "^0.4.0"
13 | },
14 | "dependencies": {
15 | "lil-gui": "^0.19.2",
16 | "three": "^0.164.1"
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Haunted House
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/script.js:
--------------------------------------------------------------------------------
1 | import * as THREE from 'three'
2 | import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
3 | import { Timer } from 'three/addons/misc/Timer.js'
4 | import { Sky } from 'three/addons/objects/Sky.js'
5 | import GUI from 'lil-gui'
6 |
7 | /**
8 | * Base
9 | */
10 | // Debug
11 | const gui = new GUI()
12 |
13 | // Canvas
14 | const canvas = document.querySelector('canvas.webgl')
15 |
16 | // Scene
17 | const scene = new THREE.Scene()
18 |
19 | /**
20 | * Textures
21 | */
22 | const textureLoader = new THREE.TextureLoader()
23 |
24 | // Floor
25 | const floorAlphaTexture = textureLoader.load('./floor/alpha.webp')
26 | const floorColorTexture = textureLoader.load('./floor/coast_sand_rocks_02_1k/coast_sand_rocks_02_diff_1k.webp')
27 | const floorARMTexture = textureLoader.load('./floor/coast_sand_rocks_02_1k/coast_sand_rocks_02_arm_1k.webp')
28 | const floorNormalTexture = textureLoader.load('./floor/coast_sand_rocks_02_1k/coast_sand_rocks_02_nor_gl_1k.webp')
29 | const floorDisplacementTexture = textureLoader.load('./floor/coast_sand_rocks_02_1k/coast_sand_rocks_02_disp_1k.webp')
30 |
31 | floorColorTexture.colorSpace = THREE.SRGBColorSpace
32 |
33 | floorColorTexture.repeat.set(8, 8)
34 | floorARMTexture.repeat.set(8, 8)
35 | floorNormalTexture.repeat.set(8, 8)
36 | floorDisplacementTexture.repeat.set(8, 8)
37 |
38 | floorColorTexture.wrapS = THREE.RepeatWrapping
39 | floorARMTexture.wrapS = THREE.RepeatWrapping
40 | floorNormalTexture.wrapS = THREE.RepeatWrapping
41 | floorDisplacementTexture.wrapS = THREE.RepeatWrapping
42 |
43 | floorColorTexture.wrapT = THREE.RepeatWrapping
44 | floorARMTexture.wrapT = THREE.RepeatWrapping
45 | floorNormalTexture.wrapT = THREE.RepeatWrapping
46 | floorDisplacementTexture.wrapT = THREE.RepeatWrapping
47 |
48 | // Wall
49 | const wallColorTexture = textureLoader.load('./wall/castle_brick_broken_06_1k/castle_brick_broken_06_diff_1k.webp')
50 | const wallARMTexture = textureLoader.load('./wall/castle_brick_broken_06_1k/castle_brick_broken_06_arm_1k.webp')
51 | const wallNormalTexture = textureLoader.load('./wall/castle_brick_broken_06_1k/castle_brick_broken_06_nor_gl_1k.webp')
52 |
53 | wallColorTexture.colorSpace = THREE.SRGBColorSpace
54 |
55 | // Roof
56 | const roofColorTexture = textureLoader.load('./roof/roof_slates_02_1k/roof_slates_02_diff_1k.webp')
57 | const roofARMTexture = textureLoader.load('./roof/roof_slates_02_1k/roof_slates_02_arm_1k.webp')
58 | const roofNormalTexture = textureLoader.load('./roof/roof_slates_02_1k/roof_slates_02_nor_gl_1k.webp')
59 |
60 | roofColorTexture.colorSpace = THREE.SRGBColorSpace
61 |
62 | roofColorTexture.repeat.set(3, 1)
63 | roofARMTexture.repeat.set(3, 1)
64 | roofNormalTexture.repeat.set(3, 1)
65 |
66 | roofColorTexture.wrapS = THREE.RepeatWrapping
67 | roofARMTexture.wrapS = THREE.RepeatWrapping
68 | roofNormalTexture.wrapS = THREE.RepeatWrapping
69 |
70 | // Bush
71 | const bushColorTexture = textureLoader.load('./bush/leaves_forest_ground_1k/leaves_forest_ground_diff_1k.webp')
72 | const bushARMTexture = textureLoader.load('./bush/leaves_forest_ground_1k/leaves_forest_ground_arm_1k.webp')
73 | const bushNormalTexture = textureLoader.load('./bush/leaves_forest_ground_1k/leaves_forest_ground_nor_gl_1k.webp')
74 |
75 | bushColorTexture.colorSpace = THREE.SRGBColorSpace
76 |
77 | bushColorTexture.repeat.set(2, 1)
78 | bushARMTexture.repeat.set(2, 1)
79 | bushNormalTexture.repeat.set(2, 1)
80 |
81 | bushColorTexture.wrapS = THREE.RepeatWrapping
82 | bushARMTexture.wrapS = THREE.RepeatWrapping
83 | bushNormalTexture.wrapS = THREE.RepeatWrapping
84 |
85 | // Grave
86 | const graveColorTexture = textureLoader.load('./grave/plastered_stone_wall_1k/plastered_stone_wall_diff_1k.webp')
87 | const graveARMTexture = textureLoader.load('./grave/plastered_stone_wall_1k/plastered_stone_wall_arm_1k.webp')
88 | const graveNormalTexture = textureLoader.load('./grave/plastered_stone_wall_1k/plastered_stone_wall_nor_gl_1k.webp')
89 |
90 | graveColorTexture.colorSpace = THREE.SRGBColorSpace
91 |
92 | graveColorTexture.repeat.set(0.3, 0.4)
93 | graveARMTexture.repeat.set(0.3, 0.4)
94 | graveNormalTexture.repeat.set(0.3, 0.4)
95 |
96 | // Door
97 | const doorColorTexture = textureLoader.load('./door/color.webp')
98 | const doorAlphaTexture = textureLoader.load('./door/alpha.webp')
99 | const doorAmbientOcclusionTexture = textureLoader.load('./door/ambientOcclusion.webp')
100 | const doorHeightTexture = textureLoader.load('./door/height.webp')
101 | const doorNormalTexture = textureLoader.load('./door/normal.webp')
102 | const doorMetalnessTexture = textureLoader.load('./door/metalness.webp')
103 | const doorRoughnessTexture = textureLoader.load('./door/roughness.webp')
104 |
105 | doorColorTexture.colorSpace = THREE.SRGBColorSpace
106 |
107 | /**
108 | * House
109 | */
110 | // Floor
111 | const floor = new THREE.Mesh(
112 | new THREE.PlaneGeometry(20, 20, 100, 100),
113 | new THREE.MeshStandardMaterial({
114 | alphaMap: floorAlphaTexture,
115 | transparent: true,
116 | map: floorColorTexture,
117 | aoMap: floorARMTexture,
118 | roughnessMap: floorARMTexture,
119 | metalnessMap: floorARMTexture,
120 | normalMap: floorNormalTexture,
121 | displacementMap: floorDisplacementTexture,
122 | displacementScale: 0.3,
123 | displacementScale: 0.3,
124 | displacementBias: - 0.2
125 | })
126 | )
127 | floor.rotation.x = - Math.PI * 0.5
128 | scene.add(floor)
129 |
130 | gui.add(floor.material, 'displacementScale').min(0).max(1).step(0.001).name('floorDisplacementScale')
131 | gui.add(floor.material, 'displacementBias').min(-1).max(1).step(0.001).name('floorDisplacementBias')
132 |
133 | // House container
134 | const house = new THREE.Group()
135 | scene.add(house)
136 |
137 | // Walls
138 | const walls = new THREE.Mesh(
139 | new THREE.BoxGeometry(4, 2.5, 4),
140 | new THREE.MeshStandardMaterial({
141 | map: wallColorTexture,
142 | aoMap: wallARMTexture,
143 | roughnessMap: wallARMTexture,
144 | metalnessMap: wallARMTexture,
145 | normalMap: wallNormalTexture
146 | })
147 | )
148 | walls.position.y += 1.25
149 | house.add(walls)
150 |
151 | // Roof
152 | const roof = new THREE.Mesh(
153 | new THREE.ConeGeometry(3.5, 1.5, 4),
154 | new THREE.MeshStandardMaterial({
155 | map: roofColorTexture,
156 | aoMap: roofARMTexture,
157 | roughnessMap: roofARMTexture,
158 | metalnessMap: roofARMTexture,
159 | normalMap: roofNormalTexture
160 | })
161 | )
162 | roof.position.y = 2.5 + 0.75
163 | roof.rotation.y = Math.PI * 0.25
164 | house.add(roof)
165 |
166 | // Door
167 | const door = new THREE.Mesh(
168 | new THREE.PlaneGeometry(2.2, 2.2, 100, 100),
169 | new THREE.MeshStandardMaterial({
170 | map: doorColorTexture,
171 | transparent: true,
172 | alphaMap: doorAlphaTexture,
173 | aoMap: doorAmbientOcclusionTexture,
174 | displacementMap: doorHeightTexture,
175 | displacementScale: 0.15,
176 | displacementBias: -0.04,
177 | normalMap: doorNormalTexture,
178 | metalnessMap: doorMetalnessTexture,
179 | roughnessMap: doorRoughnessTexture
180 | })
181 | )
182 | door.position.y = 1
183 | door.position.z = 2 + 0.01
184 | house.add(door)
185 |
186 | // Bushes
187 | const bushGeometry = new THREE.SphereGeometry(1, 16, 16)
188 | const bushMaterial = new THREE.MeshStandardMaterial({
189 | color: '#ccffcc',
190 | map: bushColorTexture,
191 | aoMap: bushARMTexture,
192 | roughnessMap: bushARMTexture,
193 | metalnessMap: bushARMTexture,
194 | normalMap: bushNormalTexture
195 | })
196 |
197 | const bush1 = new THREE.Mesh(bushGeometry, bushMaterial)
198 | bush1.scale.set(0.5, 0.5, 0.5)
199 | bush1.position.set(0.8, 0.2, 2.2)
200 | bush1.rotation.x = - 0.75
201 |
202 | const bush2 = new THREE.Mesh(bushGeometry, bushMaterial)
203 | bush2.scale.set(0.25, 0.25, 0.25)
204 | bush2.position.set(1.4, 0.1, 2.1)
205 | bush2.rotation.x = - 0.75
206 |
207 | const bush3 = new THREE.Mesh(bushGeometry, bushMaterial)
208 | bush3.scale.set(0.4, 0.4, 0.4)
209 | bush3.position.set(- 0.8, 0.1, 2.2)
210 | bush3.rotation.x = - 0.75
211 |
212 | const bush4 = new THREE.Mesh(bushGeometry, bushMaterial)
213 | bush4.scale.set(0.15, 0.15, 0.15)
214 | bush4.position.set(- 1, 0.05, 2.6)
215 | bush4.rotation.x = - 0.75
216 |
217 | house.add(bush1, bush2, bush3, bush4)
218 |
219 | // Graves
220 | const graveGeometry = new THREE.BoxGeometry(0.6, 0.8, 0.2)
221 | const graveMaterial = new THREE.MeshStandardMaterial({
222 | map: graveColorTexture,
223 | normalMap: graveNormalTexture,
224 | aoMap: graveARMTexture,
225 | roughnessMap: graveARMTexture,
226 | metalnessMap: graveARMTexture
227 | })
228 |
229 | const graves = new THREE.Group()
230 | scene.add(graves)
231 |
232 | for(let i = 0; i < 30; i++)
233 | {
234 | const angle = Math.random() * Math.PI * 2
235 | const radius = 3 + Math.random() * 4
236 | const x = Math.sin(angle) * radius
237 | const z = Math.cos(angle) * radius
238 |
239 | // Mesh
240 | const grave = new THREE.Mesh(graveGeometry, graveMaterial)
241 | grave.position.x = x
242 | grave.position.y = Math.random() * 0.4
243 | grave.position.z = z
244 | grave.rotation.x = (Math.random() - 0.5) * 0.4
245 | grave.rotation.y = (Math.random() - 0.5) * 0.4
246 | grave.rotation.z = (Math.random() - 0.5) * 0.4
247 |
248 | // Add to the graves group
249 | graves.add(grave)
250 | }
251 |
252 | /**
253 | * Lights
254 | */
255 | // Ambient light
256 | const ambientLight = new THREE.AmbientLight('#86cdff', 0.275)
257 | scene.add(ambientLight)
258 |
259 | // Directional light
260 | const directionalLight = new THREE.DirectionalLight('#86cdff', 1)
261 | directionalLight.position.set(3, 2, -8)
262 | scene.add(directionalLight)
263 |
264 | // Door light
265 | const doorLight = new THREE.PointLight('#ff7d46', 5)
266 | doorLight.position.set(0, 2.2, 2.5)
267 | house.add(doorLight)
268 |
269 | /**
270 | * Ghosts
271 | */
272 | const ghost1 = new THREE.PointLight('#8800ff', 6)
273 | const ghost2 = new THREE.PointLight('#ff0088', 6)
274 | const ghost3 = new THREE.PointLight('#ff0000', 6)
275 | scene.add(ghost1, ghost2, ghost3)
276 |
277 | /**
278 | * Sizes
279 | */
280 | const sizes = {
281 | width: window.innerWidth,
282 | height: window.innerHeight
283 | }
284 |
285 | window.addEventListener('resize', () =>
286 | {
287 | // Update sizes
288 | sizes.width = window.innerWidth
289 | sizes.height = window.innerHeight
290 |
291 | // Update camera
292 | camera.aspect = sizes.width / sizes.height
293 | camera.updateProjectionMatrix()
294 |
295 | // Update renderer
296 | renderer.setSize(sizes.width, sizes.height)
297 | renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
298 | })
299 |
300 | /**
301 | * Camera
302 | */
303 | // Base camera
304 | const camera = new THREE.PerspectiveCamera(75, sizes.width / sizes.height, 0.1, 100)
305 | camera.position.x = 4
306 | camera.position.y = 2
307 | camera.position.z = 5
308 | scene.add(camera)
309 |
310 | // Controls
311 | const controls = new OrbitControls(camera, canvas)
312 | controls.enableDamping = true
313 |
314 | /**
315 | * Renderer
316 | */
317 | const renderer = new THREE.WebGLRenderer({
318 | canvas: canvas
319 | })
320 | renderer.setSize(sizes.width, sizes.height)
321 | renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
322 |
323 | /**
324 | * Shadows
325 | */
326 | // Renderer
327 | renderer.shadowMap.enabled = true
328 | renderer.shadowMap.type = THREE.PCFSoftShadowMap
329 |
330 | // Cast and receive
331 | directionalLight.castShadow = true
332 | ghost1.castShadow = true
333 | ghost2.castShadow = true
334 | ghost3.castShadow = true
335 |
336 | walls.castShadow = true
337 | walls.receiveShadow = true
338 | roof.castShadow = true
339 | floor.receiveShadow = true
340 |
341 | for(const grave of graves.children)
342 | {
343 | grave.castShadow = true
344 | grave.receiveShadow = true
345 | }
346 |
347 | // Mappings
348 | directionalLight.shadow.mapSize.width = 256
349 | directionalLight.shadow.mapSize.height = 256
350 | directionalLight.shadow.camera.top = 8
351 | directionalLight.shadow.camera.right = 8
352 | directionalLight.shadow.camera.bottom = - 8
353 | directionalLight.shadow.camera.left = - 8
354 | directionalLight.shadow.camera.near = 1
355 | directionalLight.shadow.camera.far = 20
356 |
357 | ghost1.shadow.mapSize.width = 256
358 | ghost1.shadow.mapSize.height = 256
359 | ghost1.shadow.camera.far = 10
360 |
361 | ghost2.shadow.mapSize.width = 256
362 | ghost2.shadow.mapSize.height = 256
363 | ghost2.shadow.camera.far = 10
364 |
365 | ghost3.shadow.mapSize.width = 256
366 | ghost3.shadow.mapSize.height = 256
367 | ghost3.shadow.camera.far = 10
368 |
369 | /**
370 | * Sky
371 | */
372 | const sky = new Sky()
373 | sky.scale.set(100, 100, 100)
374 | scene.add(sky)
375 |
376 | sky.material.uniforms['turbidity'].value = 10
377 | sky.material.uniforms['rayleigh'].value = 3
378 | sky.material.uniforms['mieCoefficient'].value = 0.1
379 | sky.material.uniforms['mieDirectionalG'].value = 0.95
380 | sky.material.uniforms['sunPosition'].value.set(0.3, -0.038, -0.95)
381 |
382 | /**
383 | * Fog
384 | */
385 | // scene.fog = new THREE.Fog('#04343f', 1, 13)
386 | scene.fog = new THREE.FogExp2('#04343f', 0.1)
387 |
388 | /**
389 | * Animate
390 | */
391 | const timer = new Timer()
392 |
393 | const tick = () =>
394 | {
395 | // Timer
396 | timer.update()
397 | const elapsedTime = timer.getElapsed()
398 |
399 | // Ghosts
400 | const ghost1Angle = elapsedTime * 0.5
401 | ghost1.position.x = Math.cos(ghost1Angle) * 4
402 | ghost1.position.z = Math.sin(ghost1Angle) * 4
403 | ghost1.position.y = Math.sin(ghost1Angle) * Math.sin(ghost1Angle * 2.34) * Math.sin(ghost1Angle * 3.45)
404 |
405 | const ghost2Angle = - elapsedTime * 0.38
406 | ghost2.position.x = Math.cos(ghost2Angle) * 5
407 | ghost2.position.z = Math.sin(ghost2Angle) * 5
408 | ghost2.position.y = Math.sin(ghost2Angle) * Math.sin(ghost2Angle * 2.34) * Math.sin(ghost2Angle * 3.45)
409 |
410 | const ghost3Angle = elapsedTime * 0.23
411 | ghost3.position.x = Math.cos(ghost3Angle) * 6
412 | ghost3.position.z = Math.sin(ghost3Angle) * 6
413 | ghost3.position.y = Math.sin(ghost3Angle) * Math.sin(ghost3Angle * 2.34) * Math.sin(ghost3Angle * 3.45)
414 |
415 | controls.update()
416 |
417 | renderer.render(scene, camera)
418 |
419 | window.requestAnimationFrame(tick)
420 | }
421 |
422 | tick()
--------------------------------------------------------------------------------
/src/style.css:
--------------------------------------------------------------------------------
1 | *
2 | {
3 | margin: 0;
4 | padding: 0;
5 | }
6 |
7 | html,
8 | body
9 | {
10 | overflow: hidden;
11 | }
12 |
13 | .webgl
14 | {
15 | position: fixed;
16 | top: 0;
17 | left: 0;
18 | outline: none;
19 | }
20 |
--------------------------------------------------------------------------------
/static/bush/leaves_forest_ground_1k/leaves_forest_ground_arm_1k.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sreya-satheesh/haunted-house/3f302f66e2d3094610ccfe36042679012e423285/static/bush/leaves_forest_ground_1k/leaves_forest_ground_arm_1k.webp
--------------------------------------------------------------------------------
/static/bush/leaves_forest_ground_1k/leaves_forest_ground_diff_1k.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sreya-satheesh/haunted-house/3f302f66e2d3094610ccfe36042679012e423285/static/bush/leaves_forest_ground_1k/leaves_forest_ground_diff_1k.webp
--------------------------------------------------------------------------------
/static/bush/leaves_forest_ground_1k/leaves_forest_ground_nor_gl_1k.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sreya-satheesh/haunted-house/3f302f66e2d3094610ccfe36042679012e423285/static/bush/leaves_forest_ground_1k/leaves_forest_ground_nor_gl_1k.webp
--------------------------------------------------------------------------------
/static/door/alpha.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sreya-satheesh/haunted-house/3f302f66e2d3094610ccfe36042679012e423285/static/door/alpha.webp
--------------------------------------------------------------------------------
/static/door/ambientOcclusion.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sreya-satheesh/haunted-house/3f302f66e2d3094610ccfe36042679012e423285/static/door/ambientOcclusion.webp
--------------------------------------------------------------------------------
/static/door/color.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sreya-satheesh/haunted-house/3f302f66e2d3094610ccfe36042679012e423285/static/door/color.webp
--------------------------------------------------------------------------------
/static/door/height.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sreya-satheesh/haunted-house/3f302f66e2d3094610ccfe36042679012e423285/static/door/height.webp
--------------------------------------------------------------------------------
/static/door/metalness.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sreya-satheesh/haunted-house/3f302f66e2d3094610ccfe36042679012e423285/static/door/metalness.webp
--------------------------------------------------------------------------------
/static/door/normal.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sreya-satheesh/haunted-house/3f302f66e2d3094610ccfe36042679012e423285/static/door/normal.webp
--------------------------------------------------------------------------------
/static/door/roughness.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sreya-satheesh/haunted-house/3f302f66e2d3094610ccfe36042679012e423285/static/door/roughness.webp
--------------------------------------------------------------------------------
/static/floor/alpha.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sreya-satheesh/haunted-house/3f302f66e2d3094610ccfe36042679012e423285/static/floor/alpha.webp
--------------------------------------------------------------------------------
/static/floor/coast_sand_rocks_02_1k/coast_sand_rocks_02_arm_1k.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sreya-satheesh/haunted-house/3f302f66e2d3094610ccfe36042679012e423285/static/floor/coast_sand_rocks_02_1k/coast_sand_rocks_02_arm_1k.webp
--------------------------------------------------------------------------------
/static/floor/coast_sand_rocks_02_1k/coast_sand_rocks_02_diff_1k.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sreya-satheesh/haunted-house/3f302f66e2d3094610ccfe36042679012e423285/static/floor/coast_sand_rocks_02_1k/coast_sand_rocks_02_diff_1k.webp
--------------------------------------------------------------------------------
/static/floor/coast_sand_rocks_02_1k/coast_sand_rocks_02_disp_1k.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sreya-satheesh/haunted-house/3f302f66e2d3094610ccfe36042679012e423285/static/floor/coast_sand_rocks_02_1k/coast_sand_rocks_02_disp_1k.webp
--------------------------------------------------------------------------------
/static/floor/coast_sand_rocks_02_1k/coast_sand_rocks_02_nor_gl_1k.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sreya-satheesh/haunted-house/3f302f66e2d3094610ccfe36042679012e423285/static/floor/coast_sand_rocks_02_1k/coast_sand_rocks_02_nor_gl_1k.webp
--------------------------------------------------------------------------------
/static/grave/plastered_stone_wall_1k/plastered_stone_wall_arm_1k.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sreya-satheesh/haunted-house/3f302f66e2d3094610ccfe36042679012e423285/static/grave/plastered_stone_wall_1k/plastered_stone_wall_arm_1k.webp
--------------------------------------------------------------------------------
/static/grave/plastered_stone_wall_1k/plastered_stone_wall_diff_1k.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sreya-satheesh/haunted-house/3f302f66e2d3094610ccfe36042679012e423285/static/grave/plastered_stone_wall_1k/plastered_stone_wall_diff_1k.webp
--------------------------------------------------------------------------------
/static/grave/plastered_stone_wall_1k/plastered_stone_wall_nor_gl_1k.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sreya-satheesh/haunted-house/3f302f66e2d3094610ccfe36042679012e423285/static/grave/plastered_stone_wall_1k/plastered_stone_wall_nor_gl_1k.webp
--------------------------------------------------------------------------------
/static/roof/roof_slates_02_1k/roof_slates_02_arm_1k.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sreya-satheesh/haunted-house/3f302f66e2d3094610ccfe36042679012e423285/static/roof/roof_slates_02_1k/roof_slates_02_arm_1k.webp
--------------------------------------------------------------------------------
/static/roof/roof_slates_02_1k/roof_slates_02_diff_1k.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sreya-satheesh/haunted-house/3f302f66e2d3094610ccfe36042679012e423285/static/roof/roof_slates_02_1k/roof_slates_02_diff_1k.webp
--------------------------------------------------------------------------------
/static/roof/roof_slates_02_1k/roof_slates_02_nor_gl_1k.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sreya-satheesh/haunted-house/3f302f66e2d3094610ccfe36042679012e423285/static/roof/roof_slates_02_1k/roof_slates_02_nor_gl_1k.webp
--------------------------------------------------------------------------------
/static/wall/castle_brick_broken_06_1k/castle_brick_broken_06_arm_1k.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sreya-satheesh/haunted-house/3f302f66e2d3094610ccfe36042679012e423285/static/wall/castle_brick_broken_06_1k/castle_brick_broken_06_arm_1k.webp
--------------------------------------------------------------------------------
/static/wall/castle_brick_broken_06_1k/castle_brick_broken_06_diff_1k.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sreya-satheesh/haunted-house/3f302f66e2d3094610ccfe36042679012e423285/static/wall/castle_brick_broken_06_1k/castle_brick_broken_06_diff_1k.webp
--------------------------------------------------------------------------------
/static/wall/castle_brick_broken_06_1k/castle_brick_broken_06_nor_gl_1k.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sreya-satheesh/haunted-house/3f302f66e2d3094610ccfe36042679012e423285/static/wall/castle_brick_broken_06_1k/castle_brick_broken_06_nor_gl_1k.webp
--------------------------------------------------------------------------------
/vite.config.js:
--------------------------------------------------------------------------------
1 | import restart from 'vite-plugin-restart'
2 |
3 | export default {
4 | root: 'src/',
5 | publicDir: '../static/',
6 | server:
7 | {
8 | host: true,
9 | open: !('SANDBOX_URL' in process.env || 'CODESANDBOX_HOST' in process.env)
10 | },
11 | build:
12 | {
13 | outDir: '../dist',
14 | emptyOutDir: true,
15 | sourcemap: true
16 | },
17 | plugins:
18 | [
19 | restart({ restart: [ '../static/**', ] })
20 | ],
21 | }
--------------------------------------------------------------------------------