├── static └── .gitkeep ├── .gitignore ├── src ├── style │ └── main.css ├── index.html └── index.js ├── bundler ├── webpack.prod.js ├── webpack.dev.js └── webpack.common.js ├── readme.md └── package.json /static/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | .cache 5 | 6 | # Editor directories and files 7 | .idea 8 | .vscode 9 | *.suo 10 | *.ntvs* 11 | *.njsproj 12 | *.sln 13 | *.sw? 14 | -------------------------------------------------------------------------------- /src/style/main.css: -------------------------------------------------------------------------------- 1 | * 2 | { 3 | padding: 0; 4 | margin: 0; 5 | } 6 | 7 | body, 8 | html 9 | { 10 | overflow: hidden; 11 | } 12 | 13 | .webgl 14 | { 15 | position: fixed; 16 | top: 0; 17 | left: 0; 18 | width: 100%; 19 | height: 100%; 20 | background: #000000; 21 | } 22 | -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Webpack THREE.js Template 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /bundler/webpack.prod.js: -------------------------------------------------------------------------------- 1 | const webpackMerge = require('webpack-merge') 2 | const commonConfiguration = require('./webpack.common.js') 3 | const { CleanWebpackPlugin } = require('clean-webpack-plugin') 4 | 5 | module.exports = webpackMerge( 6 | commonConfiguration, 7 | { 8 | mode: 'production', 9 | plugins: 10 | [ 11 | new CleanWebpackPlugin() 12 | ] 13 | } 14 | ) 15 | -------------------------------------------------------------------------------- /bundler/webpack.dev.js: -------------------------------------------------------------------------------- 1 | const webpackMerge = require('webpack-merge') 2 | const commonConfiguration = require('./webpack.common.js') 3 | 4 | module.exports = webpackMerge( 5 | commonConfiguration, 6 | { 7 | mode: 'development', 8 | devServer: 9 | { 10 | host: '0.0.0.0', 11 | contentBase: './dist', 12 | open: true, 13 | https: false, 14 | useLocalIp: true 15 | } 16 | } 17 | ) 18 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Three.js Template / Boilerplate 2 | 3 | *Get started with Three.js to render 3d Web Experience* 4 | 5 | ![Image Title](https://github.com/mohnishlandge/webgl-assets/blob/main/Screenshot%20(159).png) 6 | 7 | [Youtube Setup Video](https://youtu.be/MmjZG-UX30g) 8 | 9 | [Demo](https://threejs-template.netlify.app/) 10 | 11 | 12 | ## Installation 13 | 14 | Install dependencies (only for first time) : 15 | 16 | ``` 17 | yarn 18 | ``` 19 | 20 | Compile the code for development and start a local server: 21 | 22 | ``` 23 | yarn dev 24 | ``` 25 | 26 | Local Server will open on: 27 | 28 | ``` 29 | http://localhost:8080/ 30 | ``` 31 | 32 | Create the build: 33 | 34 | ``` 35 | yarn build 36 | ``` 37 | 38 | ## Credits 39 | 40 | - [Webpack THREE.js Template](https://github.com/brunosimon/webpack-three-js-template) 41 | 42 | ## Misc 43 | 44 | Follow *@iviixio*: [Twitter](https://twitter.com/iviixio), [Instagram](https://www.instagram.com/iviixio/) 45 | 46 | Youtube Video: [Twitter](https://youtu.be/MmjZG-UX30g) 47 | 48 | ## License 49 | [MIT](LICENSE) 50 | 51 | Made with :blue_heart: by [Mohnish Landge](http://mohnishlandge.me) 52 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "threejs-starter", 3 | "version": "1.0.0", 4 | "description": "*Get started with Three.js to render 3d Web Experience*", 5 | "main": "index.js", 6 | "scripts": { 7 | "build": "webpack --config ./bundler/webpack.prod.js", 8 | "dev": "webpack-dev-server --config ./bundler/webpack.dev.js" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "git+https://github.com/mohnishlandge/threejs-template.git" 13 | }, 14 | "keywords": [], 15 | "author": "Mohnish Landge", 16 | "license": "ISC", 17 | "bugs": { 18 | "url": "https://github.com/mohnishlandge/threejs-template/issues" 19 | }, 20 | "homepage": "https://github.com/mohnishlandge/threejs-template#readme", 21 | "devDependencies": { 22 | "@babel/core": "^7.9.6", 23 | "@babel/preset-env": "^7.9.6", 24 | "babel-loader": "^8.1.0", 25 | "clean-webpack-plugin": "^3.0.0", 26 | "copy-webpack-plugin": "^5.1.1", 27 | "css-loader": "^3.5.3", 28 | "file-loader": "^6.0.0", 29 | "glslify-loader": "^2.0.0", 30 | "html-loader": "^1.1.0", 31 | "html-webpack-plugin": "^4.3.0", 32 | "raw-loader": "^4.0.1", 33 | "style-loader": "^1.2.1", 34 | "three": "^0.116.1", 35 | "webpack": "^4.43.0", 36 | "webpack-cli": "^3.3.11", 37 | "webpack-dev-server": "^3.11.0", 38 | "webpack-merge": "^4.2.2" 39 | }, 40 | "dependencies": { 41 | "dat.gui": "^0.7.7" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /bundler/webpack.common.js: -------------------------------------------------------------------------------- 1 | const CopyWebpackPlugin = require('copy-webpack-plugin') 2 | const HtmlWebpackPlugin = require('html-webpack-plugin') 3 | const path = require('path') 4 | 5 | module.exports = { 6 | entry: path.resolve(__dirname, '../src/index.js'), 7 | output: 8 | { 9 | filename: 'bundle.[hash].js', 10 | path: path.resolve(__dirname, '../dist') 11 | }, 12 | devtool: 'source-map', 13 | plugins: 14 | [ 15 | new CopyWebpackPlugin([ { from: path.resolve(__dirname, '../static') } ]), 16 | new HtmlWebpackPlugin({ 17 | template: path.resolve(__dirname, '../src/index.html'), 18 | minify: true 19 | }) 20 | ], 21 | module: 22 | { 23 | rules: 24 | [ 25 | // HTML 26 | { 27 | test: /\.(html)$/, 28 | use: ['html-loader'] 29 | }, 30 | 31 | // JS 32 | { 33 | test: /\.js$/, 34 | exclude: /node_modules/, 35 | use: 36 | [ 37 | 'babel-loader' 38 | ] 39 | }, 40 | 41 | // CSS 42 | { 43 | test: /\.css$/, 44 | use: 45 | [ 46 | 'style-loader', 47 | 'css-loader' 48 | ] 49 | }, 50 | 51 | // Images 52 | { 53 | test: /\.(jpg|png|gif|svg)$/, 54 | use: 55 | [ 56 | { 57 | loader: 'file-loader', 58 | options: 59 | { 60 | outputPath: 'assets/images/' 61 | } 62 | } 63 | ] 64 | }, 65 | 66 | // Shaders 67 | { 68 | test: /\.(glsl|vs|fs|vert|frag)$/, 69 | exclude: /node_modules/, 70 | use: [ 71 | 'raw-loader', 72 | 'glslify-loader' 73 | ] 74 | } 75 | ] 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import './style/main.css' 2 | import * as THREE from 'three' 3 | import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js' 4 | /** 5 | * GUI Controls 6 | */ 7 | import * as dat from 'dat.gui' 8 | const gui = new dat.GUI() 9 | 10 | /** 11 | * Base 12 | */ 13 | // Canvas 14 | const canvas = document.querySelector('canvas.webgl') 15 | 16 | // Scene 17 | const scene = new THREE.Scene() 18 | 19 | /** 20 | * Object 21 | */ 22 | const geometry = new THREE.IcosahedronGeometry(20, 1) 23 | const material = new THREE.MeshNormalMaterial() 24 | // Material Props. 25 | material.wireframe = true 26 | // Create Mesh & Add To Scene 27 | const mesh = new THREE.Mesh(geometry, material) 28 | scene.add(mesh) 29 | 30 | /** 31 | * Sizes 32 | */ 33 | const sizes = { 34 | width: window.innerWidth, 35 | height: window.innerHeight, 36 | } 37 | 38 | window.addEventListener('resize', () => { 39 | // Update sizes 40 | sizes.width = window.innerWidth 41 | sizes.height = window.innerHeight 42 | 43 | // Update camera 44 | camera.aspect = sizes.width / sizes.height 45 | camera.updateProjectionMatrix() 46 | 47 | // Update renderer 48 | renderer.setSize(sizes.width, sizes.height) 49 | renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)) 50 | }) 51 | 52 | /** 53 | * Camera 54 | */ 55 | // Base camera 56 | const camera = new THREE.PerspectiveCamera( 57 | 75, 58 | sizes.width / sizes.height, 59 | 0.001, 60 | 5000 61 | ) 62 | camera.position.x = 1 63 | camera.position.y = 1 64 | camera.position.z = 50 65 | scene.add(camera) 66 | 67 | // Controls 68 | const controls = new OrbitControls(camera, canvas) 69 | controls.enableDamping = true 70 | controls.autoRotate = true 71 | // controls.enableZoom = false 72 | controls.enablePan = false 73 | controls.dampingFactor = 0.05 74 | controls.maxDistance = 1000 75 | controls.minDistance = 30 76 | controls.touches = { 77 | ONE: THREE.TOUCH.ROTATE, 78 | TWO: THREE.TOUCH.DOLLY_PAN, 79 | } 80 | /** 81 | * Renderer 82 | */ 83 | const renderer = new THREE.WebGLRenderer({ 84 | canvas: canvas, 85 | antialias: true, 86 | }) 87 | renderer.setSize(sizes.width, sizes.height) 88 | renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)) 89 | 90 | /** 91 | * Animate 92 | */ 93 | const clock = new THREE.Clock() 94 | const tick = () => { 95 | const elapsedTime = clock.getElapsedTime() 96 | 97 | //mesh.rotation.y += 0.01 * Math.sin(1) 98 | //mesh.rotation.y += 0.01 * Math.sin(1) 99 | mesh.rotation.z += 0.01 * Math.sin(1) 100 | 101 | // Update controls 102 | controls.update() 103 | // Render 104 | renderer.render(scene, camera) 105 | 106 | // Call tick again on the next frame 107 | window.requestAnimationFrame(tick) 108 | } 109 | 110 | tick() 111 | --------------------------------------------------------------------------------