[+] Lights
This commit is contained in:
+10
-8
@@ -1,16 +1,16 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="">
|
<html lang="">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta content="IE=edge" http-equiv="X-UA-Compatible">
|
<meta content="IE=edge" http-equiv="X-UA-Compatible">
|
||||||
<meta content="width=device-width,initial-scale=1.0" name="viewport">
|
<meta content="width=device-width,initial-scale=1.0" name="viewport">
|
||||||
<link href="<%= BASE_URL %>favicon.ico" rel="icon">
|
<link href="<%= BASE_URL %>favicon.ico" rel="icon">
|
||||||
<title><%= htmlWebpackPlugin.options.title %></title>
|
<title><%= htmlWebpackPlugin.options.title %></title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<noscript>
|
<noscript>
|
||||||
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without
|
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without
|
||||||
JavaScript enabled. Please enable it to continue.</strong>
|
JavaScript enabled. Please enable it to continue.</strong>
|
||||||
</noscript>
|
</noscript>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
<!-- built files will be auto injected -->
|
<!-- built files will be auto injected -->
|
||||||
@@ -18,6 +18,8 @@
|
|||||||
|
|
||||||
<style>
|
<style>
|
||||||
/* Load this last */
|
/* Load this last */
|
||||||
* { transition: all .25s ease }
|
* {
|
||||||
|
transition: all .25s ease
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
import {Color} from "three";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configurations
|
||||||
|
*/
|
||||||
|
export const config = {
|
||||||
|
|
||||||
|
background: '#333',
|
||||||
|
|
||||||
|
// Field of vision and cutoff frustum for near and far
|
||||||
|
cam: {fov: 50, near: 1, far: 5000},
|
||||||
|
|
||||||
|
// Mouse movement factor
|
||||||
|
mouseFactor: 20,
|
||||||
|
|
||||||
|
// Smooth movements (speeds are in terms of pixels per ms)
|
||||||
|
smooth: {mouseSpeed: 10 * window.devicePixelRatio},
|
||||||
|
|
||||||
|
// Debug mode
|
||||||
|
debug: true
|
||||||
|
}
|
||||||
|
|
||||||
|
export const colors = {
|
||||||
|
sky: {
|
||||||
|
top: new Color('#3284ff'),
|
||||||
|
bottom: new Color('#ffffff'),
|
||||||
|
ground: new Color('#ffc87f'),
|
||||||
|
dirLight: new Color('#fff4e5')
|
||||||
|
},
|
||||||
|
}
|
||||||
@@ -37,12 +37,13 @@ export function box(width: number, height: number, depth: number): THREE.BufferG
|
|||||||
* @param color
|
* @param color
|
||||||
* @param z
|
* @param z
|
||||||
* @param r
|
* @param r
|
||||||
|
* @param hollow
|
||||||
*/
|
*/
|
||||||
export function circle(color: number, z: number, r: number): THREE.Mesh
|
export function circle(color: number, z: number, r: number, hollow = false): THREE.Object3D
|
||||||
{
|
{
|
||||||
const geometry = new THREE.CircleGeometry(r, 32)
|
const geometry = new THREE.CircleGeometry(r, 32)
|
||||||
const material = new THREE.MeshBasicMaterial({color})
|
const material = new THREE.MeshBasicMaterial({color})
|
||||||
const circle = new THREE.Mesh(geometry, material)
|
const circle = hollow ? new THREE.Line(geometry, material) : new THREE.Mesh(geometry, material)
|
||||||
circle.position.z = z
|
circle.position.z = z
|
||||||
return circle
|
return circle
|
||||||
}
|
}
|
||||||
|
|||||||
+54
-30
@@ -1,40 +1,33 @@
|
|||||||
import * as THREE from 'three'
|
import * as THREE from 'three'
|
||||||
import * as helper from "@/animation/Helpers";
|
import * as helper from "@/animation/Helpers"
|
||||||
import {initMouseTracker, moused} from "@/animation/Trackers";
|
import {circle} from "@/animation/Helpers"
|
||||||
import {circle} from "@/animation/Helpers";
|
import {initMouseTracker, moused} from "@/animation/Trackers"
|
||||||
|
import {addDirLight, addGround, addHemiLight, addSky} from "@/animation/Shaders"
|
||||||
|
import {colors, config} from "@/animation/Config"
|
||||||
|
|
||||||
let renderer: THREE.WebGLRenderer, scene: THREE.Scene, camera: THREE.PerspectiveCamera
|
let renderer: THREE.WebGLRenderer, scene: THREE.Scene, camera: THREE.PerspectiveCamera
|
||||||
const clock = new THREE.Clock()
|
const clock = new THREE.Clock()
|
||||||
const objects = []
|
const objects: { [id: string]: THREE.Object3D } = {}
|
||||||
|
|
||||||
const config = {
|
|
||||||
background: '#333',
|
|
||||||
|
|
||||||
// Field of vision and cutoff frustum for near and far
|
|
||||||
cam: {fov: 50, near: 1, far: 2000},
|
|
||||||
|
|
||||||
// Mouse movement factor
|
|
||||||
mouseFactor: 20,
|
|
||||||
|
|
||||||
// Smooth movements (speeds are in terms of pixels per ms)
|
|
||||||
smooth: {mouseSpeed: 10 * window.devicePixelRatio},
|
|
||||||
}
|
|
||||||
|
|
||||||
// ////////////////////
|
// ////////////////////
|
||||||
// Three.js scene code
|
// Three.js scene code
|
||||||
|
|
||||||
function init(): void
|
function init(): void
|
||||||
{
|
{
|
||||||
const geometryBox = helper.box(50, 50, 50);
|
const geometryBox = helper.box(50, 50, 50)
|
||||||
|
|
||||||
const lineSegments = new THREE.LineSegments(geometryBox, new THREE.LineDashedMaterial({
|
const lineSegments = new THREE.LineSegments(geometryBox, new THREE.LineDashedMaterial({
|
||||||
color: 0xffaa00,
|
color: 0xffaa00,
|
||||||
dashSize: 3,
|
dashSize: 3,
|
||||||
gapSize: 1
|
gapSize: 1
|
||||||
}));
|
}))
|
||||||
lineSegments.computeLineDistances()
|
lineSegments.computeLineDistances()
|
||||||
|
|
||||||
objects.push(lineSegments)
|
const cursor = circle(0xffaa00, 100, 1)
|
||||||
|
objects.cursor = cursor
|
||||||
|
scene.add(cursor)
|
||||||
|
|
||||||
|
objects.box = lineSegments
|
||||||
scene.add(lineSegments)
|
scene.add(lineSegments)
|
||||||
|
|
||||||
scene.add(circle(0xffff00, 0, 5))
|
scene.add(circle(0xffff00, 0, 5))
|
||||||
@@ -59,16 +52,25 @@ function pn(b: boolean): number
|
|||||||
*/
|
*/
|
||||||
function update(dt: number): void
|
function update(dt: number): void
|
||||||
{
|
{
|
||||||
smoothBuffer.cam.x = moused.x * config.mouseFactor
|
// objects['cursor'].position.set(moused.x, moused.y, 150)
|
||||||
smoothBuffer.cam.y = moused.y * config.mouseFactor
|
|
||||||
|
const vector = new THREE.Vector3(moused.x, moused.y, 0.5)
|
||||||
|
vector.unproject(camera)
|
||||||
|
const dir = vector.sub(camera.position).normalize()
|
||||||
|
const distance = -camera.position.z / dir.z
|
||||||
|
const pos = camera.position.clone().add(dir.multiplyScalar(distance))
|
||||||
|
objects.cursor.position.copy(pos)
|
||||||
|
|
||||||
|
// smoothBuffer.cam.x = moused.x * config.mouseFactor
|
||||||
|
// smoothBuffer.cam.y = moused.y * config.mouseFactor
|
||||||
smoothUpdate()
|
smoothUpdate()
|
||||||
|
|
||||||
// const time = Date.now() * 0.001
|
// const time = Date.now() * 0.001
|
||||||
// scene.traverse((object) =>
|
// scene.traverse((object) =>
|
||||||
// {
|
// {
|
||||||
// object.rotation.x = 0.25 * time;
|
// object.rotation.x = 0.25 * time
|
||||||
// object.rotation.y = 0.25 * time;
|
// object.rotation.y = 0.25 * time
|
||||||
// });
|
// })
|
||||||
|
|
||||||
function smoothUpdate(): void
|
function smoothUpdate(): void
|
||||||
{
|
{
|
||||||
@@ -79,11 +81,21 @@ function update(dt: number): void
|
|||||||
// Target position
|
// Target position
|
||||||
const tp = smoothBuffer.cam
|
const tp = smoothBuffer.cam
|
||||||
|
|
||||||
if (Math.abs(cp.x - tp.x) > delta) { cp.x = cp.x + delta * pn(cp.x < tp.x) }
|
if (Math.abs(cp.x - tp.x) > delta)
|
||||||
else { cp.x = tp.x }
|
{
|
||||||
|
cp.x = cp.x + delta * pn(cp.x < tp.x)
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
cp.x = tp.x
|
||||||
|
}
|
||||||
|
|
||||||
if (Math.abs(cp.y - tp.y) > delta) { cp.y = cp.y + delta * pn(cp.y < tp.y) }
|
if (Math.abs(cp.y - tp.y) > delta)
|
||||||
else { cp.y = tp.y }
|
{
|
||||||
|
cp.y = cp.y + delta * pn(cp.y < tp.y)
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
cp.y = tp.y
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,7 +111,6 @@ export function start(id: string): void
|
|||||||
{
|
{
|
||||||
scene = new THREE.Scene()
|
scene = new THREE.Scene()
|
||||||
scene.background = new THREE.Color(config.background)
|
scene.background = new THREE.Color(config.background)
|
||||||
|
|
||||||
// Create camera
|
// Create camera
|
||||||
camera = new THREE.PerspectiveCamera(config.cam.fov, window.innerWidth / window.innerHeight,
|
camera = new THREE.PerspectiveCamera(config.cam.fov, window.innerWidth / window.innerHeight,
|
||||||
config.cam.near, config.cam.far)
|
config.cam.near, config.cam.far)
|
||||||
@@ -111,11 +122,24 @@ export function start(id: string): void
|
|||||||
onWindowResize()
|
onWindowResize()
|
||||||
window.addEventListener('resize', onWindowResize)
|
window.addEventListener('resize', onWindowResize)
|
||||||
|
|
||||||
|
addLights()
|
||||||
|
|
||||||
init()
|
init()
|
||||||
initMouseTracker()
|
initMouseTracker()
|
||||||
animate()
|
animate()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function addLights(): void
|
||||||
|
{
|
||||||
|
objects.hemiLight = addHemiLight(scene)
|
||||||
|
objects.dirLight = addDirLight(scene)
|
||||||
|
objects.ground = addGround(scene)
|
||||||
|
objects.sky = addSky(scene)
|
||||||
|
|
||||||
|
renderer.outputEncoding = THREE.sRGBEncoding
|
||||||
|
renderer.shadowMap.enabled = true
|
||||||
|
}
|
||||||
|
|
||||||
function onWindowResize()
|
function onWindowResize()
|
||||||
{
|
{
|
||||||
camera.aspect = window.innerWidth / window.innerHeight
|
camera.aspect = window.innerWidth / window.innerHeight
|
||||||
|
|||||||
@@ -0,0 +1,118 @@
|
|||||||
|
import * as THREE from 'three'
|
||||||
|
import {colors, config} from "@/animation/Config";
|
||||||
|
import {DirectionalLight, HemisphereLight, Mesh} from "three";
|
||||||
|
|
||||||
|
export const vertexShader = `
|
||||||
|
varying vec3 vWorldPosition;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec4 worldPosition = modelMatrix * vec4( position, 1.0 );
|
||||||
|
vWorldPosition = worldPosition.xyz;
|
||||||
|
|
||||||
|
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
|
||||||
|
}`;
|
||||||
|
|
||||||
|
export const fragmentShader = `
|
||||||
|
uniform vec3 topColor;
|
||||||
|
uniform vec3 bottomColor;
|
||||||
|
uniform float offset;
|
||||||
|
uniform float exponent;
|
||||||
|
|
||||||
|
varying vec3 vWorldPosition;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
float h = normalize( vWorldPosition + offset ).y;
|
||||||
|
gl_FragColor = vec4( mix( bottomColor, topColor, max( pow( max( h , 0.0), exponent ), 0.0 ) ), 1.0 );
|
||||||
|
}`;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create sky dome
|
||||||
|
* @param scene
|
||||||
|
*/
|
||||||
|
export function addSky(scene: THREE.Scene): Mesh
|
||||||
|
{
|
||||||
|
const uniforms = {
|
||||||
|
"topColor": { value: colors.sky.top },
|
||||||
|
"bottomColor": { value: colors.sky.bottom },
|
||||||
|
"offset": { value: 33 },
|
||||||
|
"exponent": { value: 0.6 }
|
||||||
|
}
|
||||||
|
|
||||||
|
const skyGeo = new THREE.SphereGeometry( 4000, 32, 15 );
|
||||||
|
const skyMat = new THREE.ShaderMaterial({
|
||||||
|
uniforms: uniforms,
|
||||||
|
vertexShader: vertexShader,
|
||||||
|
fragmentShader: fragmentShader,
|
||||||
|
side: THREE.BackSide
|
||||||
|
});
|
||||||
|
|
||||||
|
const sky = new THREE.Mesh(skyGeo, skyMat)
|
||||||
|
scene.add(sky)
|
||||||
|
scene.fog = new THREE.Fog(colors.sky.bottom, 1, 5000)
|
||||||
|
|
||||||
|
return sky
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create ground
|
||||||
|
* @param scene
|
||||||
|
*/
|
||||||
|
export function addGround(scene: THREE.Scene): Mesh
|
||||||
|
{
|
||||||
|
const groundGeo = new THREE.PlaneGeometry(10000, 10000)
|
||||||
|
const groundMat = new THREE.MeshLambertMaterial({color: colors.sky.ground})
|
||||||
|
const ground = new THREE.Mesh(groundGeo, groundMat)
|
||||||
|
ground.position.y = -33
|
||||||
|
ground.rotation.x = -Math.PI / 2
|
||||||
|
ground.receiveShadow = true
|
||||||
|
scene.add(ground)
|
||||||
|
|
||||||
|
return ground
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add hemisphere light
|
||||||
|
* @param scene
|
||||||
|
*/
|
||||||
|
export function addHemiLight(scene: THREE.Scene): HemisphereLight
|
||||||
|
{
|
||||||
|
const hemiLight = new THREE.HemisphereLight(colors.sky.top, colors.sky.ground, 0.6)
|
||||||
|
hemiLight.position.set(0, 50, 0)
|
||||||
|
scene.add(hemiLight)
|
||||||
|
|
||||||
|
if (config.debug) scene.add(new THREE.HemisphereLightHelper(hemiLight, 10))
|
||||||
|
|
||||||
|
return hemiLight
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add directional light
|
||||||
|
* @param scene
|
||||||
|
*/
|
||||||
|
export function addDirLight(scene: THREE.Scene): DirectionalLight
|
||||||
|
{
|
||||||
|
// Directional light
|
||||||
|
const dirLight = new THREE.DirectionalLight(colors.sky.dirLight, 1)
|
||||||
|
dirLight.position.set(-1, 1.75, 1)
|
||||||
|
dirLight.position.multiplyScalar(30)
|
||||||
|
scene.add(dirLight)
|
||||||
|
|
||||||
|
dirLight.castShadow = true
|
||||||
|
|
||||||
|
dirLight.shadow.mapSize.width = 2048
|
||||||
|
dirLight.shadow.mapSize.height = 2048
|
||||||
|
|
||||||
|
const d = 50
|
||||||
|
|
||||||
|
dirLight.shadow.camera.left = -d
|
||||||
|
dirLight.shadow.camera.right = d
|
||||||
|
dirLight.shadow.camera.top = d
|
||||||
|
dirLight.shadow.camera.bottom = -d
|
||||||
|
|
||||||
|
dirLight.shadow.camera.far = 3500
|
||||||
|
dirLight.shadow.bias = -0.0001
|
||||||
|
|
||||||
|
if (config.debug) scene.add(new THREE.DirectionalLightHelper(dirLight, 10))
|
||||||
|
|
||||||
|
return dirLight
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user