123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375 |
- import * as THREE from './threejs/build/three.module.js';
- import { GLTFLoader } from './threejs/examples/jsm/loaders/GLTFLoader.js';
- import { OrbitControls } from './threejs/examples/jsm/controls/OrbitControls.js';
- import { Water } from './threejs/examples/jsm/objects/Water.js';
- import { Sky } from './threejs/examples/jsm/objects/Sky.js';
- import { Ship } from './Ship.js';
- // scene size
- var WIDTH = window.innerWidth;
- var HEIGHT = window.innerHeight;
- // camera
- var VIEW_ANGLE = 45;
- var ASPECT = WIDTH / HEIGHT;
- var NEAR = 1;
- var FAR = 5000;
- var camera, scene, renderer, raycaster;
- var clock;
- var intersects;
- export var keys = [];
- var mouse;
- var controls;
- var ship, water, sun, sky;
- var parameters;
- var simpleWater, wireframe;
- function init() {
- raycaster = new THREE.Raycaster();
- mouse = new THREE.Vector2(-1, -1);
- intersects = [];
- // renderer
- renderer = new THREE.WebGLRenderer();
- renderer.setPixelRatio(window.devicePixelRatio);
- renderer.setSize(WIDTH, HEIGHT);
- renderer.shadowMap.enabled = true;
- renderer.shadowMap.type = THREE.PCFSoftShadowMap;
- // renderer.outputEncoding = THREE.sRGBEncoding;
- // scene
- scene = new THREE.Scene();
- scene.fog = new THREE.Fog(0xFFFFFF, 50, 500);
- // camera
- camera = new THREE.PerspectiveCamera(VIEW_ANGLE, ASPECT, NEAR, FAR);
- camera.position.set(16, 22, 16);
- camera.lookAt(0, 0, 0);
- let container = document.getElementById('container');
- container.appendChild(renderer.domElement);
- controls = new OrbitControls(camera, renderer.domElement);
- controls.maxPolarAngle = Math.PI * 0.495;
- controls.target.set(0, 0, 0);
- controls.minDistance = 10.0;
- controls.maxDistance = 100.0;
- controls.update();
- clock = new THREE.Clock();
- }
- function fillScene() {
- //sky
- let cubeloader = new THREE.CubeTextureLoader();
- let texture = cubeloader.load([
- './textures/cubemap/posx.png',
- './textures/cubemap/negx.png',
- './textures/cubemap/posy.png',
- './textures/cubemap/negy.png',
- './textures/cubemap/posz.png',
- './textures/cubemap/negz.png',
- ]);
- scene.background = texture;
- //ground
- // let textureLoader = new THREE.TextureLoader();
- // let lawnTex = textureLoader.load("textures/lawn.jpg");
- // var planeGeo = new THREE.PlaneBufferGeometry(1000, 1000, 32, 32);
- // let floorMat = new THREE.MeshPhongMaterial({ map: lawnTex });
- // floorMat.flatShading = true;
- // floorMat.shininess = 0;
- // lawnTex.wrapS = lawnTex.wrapT = THREE.RepeatWrapping;
- // lawnTex.repeat.set(5, 5);
- // ground = new THREE.Mesh(planeGeo, floorMat);
- // ground.rotateX(- Math.PI / 2);
- // ground.receiveShadow = true;
- // scene.add(ground);
- // lights
- var sunlight = new THREE.PointLight(0xffffff, 1, 0, 2);
- sunlight.position.x = 400;
- sunlight.position.y = 400;
- sunlight.position.z = 100;
- sunlight.castShadow = true;
- sunlight.shadow.camera.far = 1600;
- scene.add(sunlight);
- // var mainLight = new THREE.HemisphereLight(0xB1E1FF, 0xB97A20, 0.8);
- // mainLight.position.x = 1;
- // mainLight.position.y = 1;
- // mainLight.position.z = 1;
- // mainLight.lookAt(0, 0, 0);
- // scene.add(mainLight);
- //ground
- // let textureLoader = new THREE.TextureLoader();
- // let lawnTex = textureLoader.load("textures/lawn.jpg");
- var planeGeo = new THREE.PlaneBufferGeometry(5000, 5000, 32, 32);
- water = new Water(
- planeGeo,
- {
- textureWidth: 512,
- textureHeight: 512,
- waterNormals: new THREE.TextureLoader().load('./js/threejs/examples/textures/waternormals.jpg', function (texture) {
- texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
- //texture.repeat.set(5,5);
- }),
- alpha: 1.0,
- sunDirection: new THREE.Vector3(),
- sunColor: 0xffffff,
- waterColor: 0x001e0f,
- distortionScale: 3.7,
- fog: scene.fog !== undefined
- }
- );
- water.rotation.x = - Math.PI / 2;
- water.material.uniforms['size'].value = 20;
- water.material.uniforms['eye'].value = new THREE.Vector3(16, 22, 16);
- // scene.add(water);
- //simple water
- // https://csantosbh.wordpress.com/2014/01/09/custom-shaders-with-three-js-uniforms-textures-and-lighting/
- let simplePlane = new THREE.PlaneBufferGeometry(500, 500, 100, 100);
- let simpleMaterial = new THREE.MeshPhongMaterial({ color: 0x4080EE });
- let simpleUniforms = new THREE.UniformsUtils.merge([
- THREE.UniformsLib.lights,
- THREE.UniformsLib.fog,
- {
- waterColor: { value: new THREE.Color(0x0880AA) },
- u_time: { value: 0 },
- lightIntensity: { value: 1 },
- }
- ]
- );
- let shaderMaterial = new THREE.ShaderMaterial({
- wireframe: false,
- lights: true,
- vertexShader: `
- varying vec3 vecPos;
- varying vec3 vecNormal;
- uniform float u_time;
- void main() {
- vec3 p = position;
- p.z = p.z + 0.3 * (sin(2.5 * (u_time + (p.y * 0.1)))) + 0.5;
- p.z = p.z + 0.3 * (sin(3.5 * (u_time + (p.x * 0.1)))) + 0.5;
- // Since the light is in camera coordinates,
- // I'll need the vertex position in camera coords too
- vecPos = (modelViewMatrix * vec4(p, 1.0)).xyz;
- // That's NOT exacly how you should transform your
- // normals but this will work fine, since my model
- // matrix is pretty basic
- vecNormal = (modelViewMatrix * vec4(normal, 0.0)).xyz;
- gl_Position = projectionMatrix *
- vec4(vecPos, 1.0);
- }`,
- fragmentShader: `
- precision highp float;
- varying vec3 vecPos;
- varying vec3 vecNormal;
- uniform float lightIntensity;
- uniform sampler2D textureSampler;
- uniform vec3 waterColor;
- struct PointLight {
- vec3 color;
- vec3 position; // light position, in camera coordinates
- float distance; // used for attenuation purposes. Since
- // we're writing our own shader, it can
- // really be anything we want (as long as
- // we assign it to our light in its
- // "distance" field
- };
- uniform PointLight pointLights[NUM_POINT_LIGHTS];
- void main(void) {
- // Pretty basic lambertian lighting...
- vec4 addedLights = vec4(0.0,
- 0.0,
- 0.0,
- 1.0);
- for(int l = 0; l < NUM_POINT_LIGHTS; l++) {
- vec3 lightDirection = normalize(vecPos
- - pointLights[l].position);
- addedLights.rgb += clamp(dot(-lightDirection,
- vecNormal), 0.0, 1.0)
- * pointLights[l].color
- * lightIntensity;
- }
- gl_FragColor = vec4(waterColor, 1.0) * addedLights;
- }`,
- uniforms: simpleUniforms,
- });
- simpleWater = new THREE.Mesh(simplePlane, shaderMaterial);
- simpleWater.receiveShadow = true;
- simpleWater.rotation.x = -Math.PI / 2;
- wireframe = simpleWater.clone();
- wireframe.position.y += 0.01;
- wireframe.material = wireframe.material.clone();
- wireframe.material.wireframe = true;
- wireframe.material.uniforms['waterColor'].value = new THREE.Color(0x28A0CA);
- scene.add(simpleWater);
- scene.add(wireframe);
- Ship.loadShip().then(gltf => {
- ship = new Ship(gltf.scene);
- ship.init();
- scene.add(gltf.scene);
- });
- // sun = new THREE.Vector3();
- // sky = new Sky();
- // sky.scale.setScalar(10000);
- // scene.add(sky);
- // var uniforms = sky.material.uniforms;
- // uniforms['turbidity'].value = 1;
- // uniforms['rayleigh'].value = 2;
- // uniforms['mieCoefficient'].value = 0.005;
- // uniforms['mieDirectionalG'].value = 0.8;
- // parameters = {
- // inclination: -0.5,
- // azimuth: 0.205
- // };
- // updateSun();
- update();
- }
- function updateSun() {
- var pmremGenerator = new THREE.PMREMGenerator(renderer);
- var theta = Math.PI * (parameters.inclination - 0.5);
- var phi = 2 * Math.PI * (parameters.azimuth - 0.5);
- sun.x = Math.cos(phi);
- sun.y = Math.sin(phi) * Math.sin(theta);
- sun.z = Math.sin(phi) * Math.cos(theta);
- sky.material.uniforms['sunPosition'].value.copy(sun);
- water.material.uniforms['sunDirection'].value.copy(sun).normalize();
- scene.environment = pmremGenerator.fromScene(sky).texture;
- }
- function update() {
- requestAnimationFrame(update);
- water.material.uniforms['time'].value += 1.0 / 60.0;
- if (simpleWater.material) {
- simpleWater.material.uniforms['u_time'].value = clock.getElapsedTime();
- wireframe.material.uniforms['u_time'].value = clock.getElapsedTime();
- // simpleWater.material.uniforms['eye'].value = camera.position;
- // simpleWater.material.uniforms['sunDirection'].value.copy(sun).normalize();
- }
- // water.material.uniforms['eye'].value = new THREE.Vector3(scene.position.x, scene.position.y, scene.position.z);
- let cameraMoveSpeed = 1;
- //camera controls
- if (keys["ArrowLeft"]) { //left
- scene.translateX(cameraMoveSpeed);
- }
- if (keys["ArrowRight"]) { //right
- scene.translateX(-cameraMoveSpeed);
- }
- if (keys["ArrowUp"]) { //up
- scene.translateZ(cameraMoveSpeed);
- }
- if (keys["ArrowDown"]) { //down
- scene.translateZ(-cameraMoveSpeed);
- }
- ship.handleInput();
- // if (keys["KeyF"]) {
- // scene.position.set(ship.position.x + 16, ship.position.y + 22, ship.position.z + 16);
- // }
- ship.updateModel();
- // camera.lookAt(ship.scene.position);
- // parameters.inclination += 0.0005;
- // parameters.inclination %= 2 * Math.PI;
- // updateSun();
- scene.position.set(-ship.position.x, 0, -ship.position.z);
- renderer.render(scene, camera);
- }
- document.addEventListener("DOMContentLoaded", () => {
- init();
- fillScene();
- });
- window.addEventListener("keydown", e => keys[e.code] = true);
- window.addEventListener("keyup", e => keys[e.code] = false);
- window.addEventListener("mousemove", event => {
- mouse.x = normalize(event.clientX / window.innerWidth);
- mouse.y = -normalize(event.clientY / window.innerHeight);
- });
- window.addEventListener("mousedown", event => {
- mouse.x = normalize(event.clientX / window.innerWidth);
- mouse.y = -normalize(event.clientY / window.innerHeight);
- });
- window.addEventListener("contextmenu", event => {
- event.preventDefault();
- });
- window.addEventListener("mouseup", event => {
- });
- window.addEventListener("wheel", event => {
- });
- window.addEventListener("touchmove", event => {
- mouse.x = normalize(event.touches[0].clientX / window.innerWidth);
- mouse.y = -normalize(event.touches[0].clientY / window.innerHeight);
- });
- window.addEventListener("resize", () => {
- WIDTH = window.innerWidth;
- HEIGHT = window.innerHeight;
- ASPECT = WIDTH / HEIGHT;
- camera.aspect = ASPECT;
- renderer.setSize(WIDTH, HEIGHT);
- camera.updateProjectionMatrix();
- });
- function normalize(value) {
- return (2 * value) - 1;
- }
|