├── 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 | ![recording-ezgif com-video-to-gif-converter](https://github.com/sreya-satheesh/haunted-house/assets/168891722/3e697e7c-5a14-4639-b8ea-b793a4b35cf1) 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 | } --------------------------------------------------------------------------------