three+EventEmitter+gsap实现三维虫洞星际之门穿越效果代码

代码语言:html

所属分类:三维

代码描述:three+EventEmitter+gsap实现三维虫洞星际之门穿越效果代码,鼠标双击大门即可进入穿越到另外一个地方,从老树干穿越到沙漠城堡只在一秒钟。

代码标签: three EventEmitter gsap 三维 虫洞 星际 之门 穿越

下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开

<!DOCTYPE html>
<html lang="en" >

<head>
  <meta charset="UTF-8">
  


  
  
<style>
@import url(https://fonts.googleapis.com/css?family=Open+Sans:800);
.webgl {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  outline: none;
  background-color: #000000;
  cursor: move;
  width: 100%;
  height: 100%;
  /* fallback if grab cursor is unsupported */
  cursor: grab;
  cursor: -webkit-grab;
}

#credits {
  position: absolute;
  bottom: 0;
  left: 30px;
  margin-bottom: 20px;
  font-family: "Open Sans", sans-serif;
  color: #544027;
  font-size: 0.7em;
  text-transform: uppercase;
}

#credits a {
  color: #544027;
}

#credits a:hover {
  color: #d3cfcf;
}

#instructions {
  position: absolute;
  bottom: 60px;
  left: 30px;
  font-family: "Open Sans", sans-serif;
  color: #ffffff;
  font-size: 0.7em;
  line-height: 1.3;
  text-transform: uppercase;
  letter-spacing: 1px;
}
</style>

  
  
</head>

<body translate="no">
  <canvas class="webgl"></canvas>
<div id="instructions">Drag to turn around<br />Scroll to zoom in / out<br />Click on portals to explore</div>


<script type="x-shader/x-vertex" id="vertexShader">
  precision highp float;
  varying vec2 vUv;
  void main() {
    vUv = uv;
    vec4 modelViewPosition = modelViewMatrix * vec4(position, 1.0);
    gl_Position = projectionMatrix * modelViewPosition; 
  }
</script>

<script type="x-shader/x-fragment" id="fragmentShader">
  #define PI 3.1415
  #define TAU 6.2832
  uniform sampler2D map;
  uniform sampler2D noiseMap;
  uniform float time;
  uniform float effectIntensity;
  uniform float effectMultiplier;
  varying vec2 vUv;
  
  void main() {
    
    // center uv
    vec2 vUv2 = vUv - .5; 
    // get each point angle
    float angle = atan(vUv2.y, vUv2.x); 
    // get distance to each point
    float l = length(vUv2); 
    float l2 = pow(l, .5);
    
    // create a radial moving noise 
    float u = angle * 2. / TAU + time * .1;
    float v = fract(l + time * .2);
    vec4 noise = texture2D( noiseMap, vec2(u, v));
    
    // create waves
    float noiseDisp = noise.r * noise.g * 4. * effectMultiplier;
    float radialMask = l;
    float wavesCount = 5.0;
    float wavesSpeed = time * 5.;
    float pnt = sin(2.0 * l * PI * wavesCount + noiseDisp + wavesSpeed) * radialMask;
    
    // calculate displacement according to waves
    float dx = pnt * cos(angle) ;
    
    // normalize
    float dy = pnt * sin(angle);
    
    // sample texture and apply wave displacement
    vec4 color = texture2D( map, vUv + vec2(dx,dy) * l * .3 * effectIntensity * effectMultiplier);
    
    // lighten according to waves
    color *= 1. + pnt * .5 * effectIntensity;
    
    // highlights 
    float highlight = smoothstep(.0, .2, dx * dy);
    color += highlight * effectIntensity;
    
    // gradient greyscale at the borders
    float grey = dot(color.rgb, vec3(0.299, 0.587, 0.114));
    color.rgb = mix(color.rgb, vec3(grey), effectIntensity * l * effectMultiplier);
    
    // add redish color at the borders
    color.r += smoothstep( .1, .7, l) * .5 * effectIntensity;
   
    gl_FragColor = linearToOutputTexel(color);
    //gl_FragColor = linearToOutputTexel(vec4(highlight,highlight,highlight,1.));
    
  }
</script>
<script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/three.160.js"></script>
  <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/CameraUtils.js"></script>
 <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/OrbitControls.133.js"></script>
  <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/GLTFLoader.133.js"></script>
  <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/gsap.3.10.1.js"></script>
  <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/EventEmitter.min.js"></script>
      <script >


const FILES = {
  desertFile: "//repo.bfw.wiki/bfwrepo/threemodel/desert33.glb",
  forestFile: "//repo.bfw.wiki/bfwrepo/threemodel/forest33.glb",
  noiseFile: "//repo.bfw.wiki/bfwrepo/image/6114547459a9c.png" };

const ASSETS = {};

document.addEventListener("DOMContentLoaded", () => new App());

class App {
  constructor() {
    this.winWidth = window.innerWidth;
    this.winHeight = window.innerHeight;
    this.raycaster = new THREE.Raycaster();
    this.mouse = new THREE.Vector2();
    this.clock = new THREE.Clock();
    this.time = 0;
    this.deltaTime = 0;
    this.isInTransition = false;
    this.portalHover = false;
    this.loadAssets();
  }

  async loadAssets() {
    ASSETS.desertScene = await this.loadModel(FILES.desertFile);
    ASSETS.forestScene = await this.loadModel(FILES.forestFile);
    ASSETS.noiseMap = await this.loadTexture(FILES.noiseFile);
    this.initApp();
  }

  loadModel(file) {
    const loaderModel = new THREE.GLTFLoader();
    return new Promise(resolve => {
      loaderModel.load(file, gltf => {
        resolve(gltf.scene);
      });
    });
  }

  loadTexture(file) {
    const textureLoader = new THREE.TextureLoader();
    return new Promise(resolve => {
      textureLoader.load(file, texture => {
        texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
        resolve(texture);
      });
    });
  }

  initApp() {
    this.createWorlds();
    this.createRenderer();
    this.createControls();
    this.createListeners();
    this.onWindowResize();
    this.loop();
  }

  createWorlds() {
    this.desertWorld = new World(ASSETS.desertScene, "desert");
    this.forestWorld = new World(ASSETS.forestScene, "forest");

    this.desertWorld.addListener("moveToPortalComplete", () =>
    this.onMoveToPortalComplete());

    this.forestWorld.addListener("moveToPortalComplete", () =>
    this.onMoveToPortalComplete());

    this.desertWorld.addListener("moveToOriginComplete", () =>
    this.onMoveToOriginComplete());

    this.forestWorld.addListener("moveToOriginComplete", () =>
    this.onMoveToOriginComplete());


    this.currentWorld = this.forestWorld;
    this.otherWorld = this.desertWorld;

    // portalWorldStart and portalWorldEnd are virtual object in each world, they define where to position, scale and rotate the initial and final transforms of the virtual world during the camera transition.
    this.desertWorld.setTransitionTransforms(
    this.forestWorld.portalWorldStart,
    this.forestWorld.portalWorldEnd);

    this.forestWorld.setTransitionTransforms(
    this.desertWorld.portalWorldStart,
    this.desertWorld.portalWorldEnd);


    this.otherWorld.placeToStart();
    this.currentWorld.reset();
  }

  // used once the camera reaches the portal. The virtual world becomes the main one and vice versa
  switchWorlds() {
    const w = this.otherWorld;
    this.otherWorld = this.currentWorld;
    this.currentWorld = w;

    this.otherWorld.placeToStart();
    this.currentWorld.reset();

    this.onWindowResize();
  }

  /* 
  The transition is done in 3 steps :
  1 - the cameras moves towards the portal + the virtual world moves to portalWorldEnd
  2 - When the camera reaches the portal, main world and virtual world are switched
  3 - The cameras move back to their start position. Main world transform are moved back to their origin : scale = 1, rotation = 0, position = 0 
  */
  moveCameraToPortal() {
    this.isInTransition = true;
    this.controls.enabled = false;
    this.currentWorld.moveCameraToPortal();
    this.otherWorld.moveWorldToEnd();
  }

  onMoveToPortalComplete() {
    this.switchWorlds();
    this.currentWorld.moveWorldAndCameraToOrigin();
  }

  onMoveToOriginComplete() {
    this.controls.object = this.currentWorld.camera;
    this.controls.target = this.currentWorld.cameraTarget.position;
    this.isInTransition = false;
    this.controls.enabled = true;
  }

  createRenderer() {
    const canvas = document.querySelector("canvas.webgl");
    this.renderer = new THREE.WebGLRenderer({
      canvas,
      alpha: true,
      antialias: true,
      preserveDrawingBuffer: true });


    this.renderer.setPixelRatio(window.devicePixelRatio);
    this.renderer.setSize(window.innerWidth, window.innerHeight);
    this.renderer.toneMapping = THREE.CineonToneMapping;
    this.renderer.localClippingEnabled = true;
  }

  createControls() {
    this.controls = new THREE.OrbitControls(
    this.currentWorld.camera,
    this.renderer.domElement);

    this.controls.minDistance = 0;
    this.controls.maxDistance = 50;
    this.controls.maxPolarAngle = Math.PI / 2 + 0.1;
    this.controls.enabled = true;
  }

  createListeners() {
    window.addEventListener("resize", this.onWindowResize.bind(this));
    document.addEventListener("mousemove", this.onMouseMove.bind(this), false);
    document.addEventListener("touchmove", this.onTouchMove.bind(this), false);
    document.addEventListener("mousedown", this.onMouseDown.bind(this), false);
  }

  loop() {
    this.delta.........完整代码请登录后点击上方下载按钮下载查看

网友评论0