webgl canvas实现三维城市效果代码

代码语言:html

所属分类:三维

代码描述:webgl canvas实现三维城市效果代码

代码标签: 三维 城市 效果

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

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

<head>

  <meta charset="UTF-8">

  
<style>
html, body {
	overflow: hidden;
	touch-action: none;
	position: absolute;
	margin: 0;
	padding: 0;
	width: 100%;
	height: 100%;
	background: #000;
}
canvas {
	position: absolute;
	width: 100%; 
	height: 100%;
	user-select: none;
	background: #000;
	cursor: pointer;
}
</style>



</head>

<body >
  <canvas></canvas>

  <script>
      
  </script>
      <script type="module">
import {
WebGL,
Mesh,
Shader,
FrameBuffer } from
"//repo.bfw.wiki/bfwrepo/js/webgl-helpers.js";

{
  const [canvas, gl] = WebGL("canvas");
  gl.enable(gl.DEPTH_TEST);
  gl.enable(gl.CULL_FACE);
  console.clear();
  const matrices = [];
  const shapes = [];
  const stack = [];
  const rule = {};
  let ry = 0;
  let ex = 0;
  let ey = 0;
  let ez = 0;
  let nVertices = 0;
  let mustResize = true;
  let renderingTexture = null;
  let camDist = 0;
  let lightPosition = null;
  let ambientColor = null;
  let specularColor = null;
  let diffuseColor = null;
  let fog = null;
  let fogColor = null;
  let fov = 60;
  let pitch = 30;
  let background = null;
  let startRule = "start";
  let transformScene = null;
  let seed = Math.round(Date.now() / 86400000) - 18000;
  let minSize = 0;
  let maxDepth = 10000000;
  let minComplexity = 0;
  let maxPitch = 0;
  let cables = false;
  let zoomAcceleration = 0.0025;
  let speedRotation = 0.08;

  const transforms = {
    x(m, v) {
      m[12] += m[0] * v;
      m[13] += m[1] * v;
      m[14] += m[2] * v;
      m[15] += m[3] * v;
    },
    y(m, v) {
      m[12] += m[4] * v;
      m[13] += m[5] * v;
      m[14] += m[6] * v;
      m[15] += m[7] * v;
    },
    z(m, v) {
      m[12] += m[8] * v;
      m[13] += m[9] * v;
      m[14] += m[10] * v;
      m[15] += m[11] * v;
    },
    s(m, v) {
      const a = Array.isArray(v);
      const x = a ? v[0] : v;
      const y = a ? v[1] : x;
      const z = a ? v[2] : x;
      m[0] *= x;
      m[1] *= x;
      m[2] *= x;
      m[3] *= x;
      m[4] *= y;
      m[5] *= y;
      m[6] *= y;
      m[7] *= y;
      m[8] *= z;
      m[9] *= z;
      m[10] *= z;
      m[11] *= z;
    },
    rx(m, v) {
      const rad = Math.PI * (v / 180);
      const s = Math.sin(rad);
      const c = Math.cos(rad);
      const a10 = m[4];
      const a11 = m[5];
      const a12 = m[6];
      const a13 = m[7];
      const a20 = m[8];
      const a21 = m[9];
      const a22 = m[10];
      const a23 = m[11];
      m[4] = a10 * c + a20 * s;
      m[5] = a11 * c + a21 * s;
      m[6] = a12 * c + a22 * s;
      m[7] = a13 * c + a23 * s;
      m[8] = a10 * -s + a20 * c;
      m[9] = a11 * -s + a21 * c;
      m[10] = a12 * -s + a22 * c;
      m[11] = a13 * -s + a23 * c;
    },
    ry(m, v) {
      const rad = Math.PI * (v / 180);
      const s = Math.sin(rad);
      const c = Math.cos(rad);
      const a00 = m[0];
      const a01 = m[1];
      const a02 = m[2];
      const a03 = m[3];
      const a20 = m[8];
      const a21 = m[9];
      const a22 = m[10];
      const a23 = m[11];
      m[0] = a00 * c + a20 * -s;
      m[1] = a01 * c + a21 * -s;
      m[2] = a02 * c + a22 * -s;
      m[3] = a03 * c + a23 * -s;
      m[8] = a00 * s + a20 * c;
      m[9] = a01 * s + a21 * c;
      m[10] = a02 * s + a22 * c;
      m[11] = a03 * s + a23 * c;
    },
    rz(m, v) {
      const rad = Math.PI * (v / 180);
      const s = Math.sin(rad);
      const c = Math.cos(rad);
      const a00 = m[0];
      const a01 = m[1];
      const a02 = m[2];
      const a03 = m[3];
      const a10 = m[4];
      const a11 = m[5];
      const a12 = m[6];
      const a13 = m[7];
      m[0] = a00 * c + a10 * s;
      m[1] = a01 * c + a11 * s;
      m[2] = a02 * c + a12 * s;
      m[3] = a03 * c + a13 * s;
      m[4] = a00 * -s + a10 * c;
      m[5] = a01 * -s + a11 * c;
      m[6] = a02 * -s + a12 * c;
      m[7] = a03 * -s + a13 * c;
    },
    b(m, v) {
      if (v > 0) {
        m[16] += v * (1 - m[16]);
      } else {
        m[16] += v * m[16];
      }
    },
    l(m, v) {
      m[16] = v;
    } };


  const CUBE = (m, t) => {
    const s = copy(m);
    for (const c in t) transforms[c](s, t[c]);
    s[17] = 1;
    matrices.push(s);
    nVertices += 36;
  };

  const PYRAMID = (m, t) => {
    const s = copy(m);
    for (const c in t) transforms[c](s, t[c]);
    s[17] = 2;
    matrices.push(s);
    nVertices += 18;
  };

  const SIZE = m => {
    return Math.min(
    m[0] * m[0] + m[1] * m[1] + m[2] * m[2],
    m[4] * m[4] + m[5] * m[5] + m[6] * m[6],
    m[8] * m[8] + m[9] * m[9] + m[10] * m[10]);

  };

  const random = _ => {
    seed = seed * 16807 % 2147483647;
    return (seed - 1) / 2147483646;
  };

  const randint = (s, e = 0) => {
    if (e === 0) {
      e = s;
      s = 0;
    }
    return Math.floor(s + random() * (e - s + 1));
  };

  const transform = (s, p) => {
    const m = copy(s);
    m[18]++;
    for (const c in p) transforms[c](m, p[c]);
    if (minSize === 0) return m;else
    {
      if (SIZE(m) < minSize) m[17] = -1;
      return m;
    }
  };

  const copy = s => {
    return [
    s[0], s[1], s[2], s[3],
    s[4], s[5], s[6], s[7],
    s[8], s[9], s[10], s[11],
    s[12], s[13], s[14], s[15],
    s[16], // brillance
    s[17], // 1 = CUBE, 2 = PYRAMID
    s[18], // recurcivity depth
    s[19] // function index
    ];
  };

  const runshapes = (start, t) => {
    let comp = 0;
    let minComp = minComplexity;
    do {
      comp = 0;
      stack.length = 0;
      matrices.length = 0;
      nVertices = 0;
      rule[start](
      [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0],
      t);

      do {
        const s = stack.shift();
        if (s !== undefined && s[18] <= maxDepth) {
          shapes[s[19]](s);
          comp++;
        }
      } while (stack.length);
    } while (comp < minComp--);
  };

  const singlerule = i => {
    return (s, t) => {
      s = transform(s, t);
      if (s[17] === -1) return;
      s[19] = i;
      stack.push(s);
    };
  };

  const randomrule = (totalWeight, weight, index, len) => {
    return (s, t) => {
      s = transform(s, t);
      if (s[17] === -1) return;
      let w = 0;
      const r = random() * totalWeight;
      for (let i = 0; i < len; i++) {
        w += weight[i];
        if (r <= w) {
          s[19] = index[i];
          stack.push(s);
          return;
        }
      }
    };
  };

  const resize = () => {
    const dpr = window.devicePixelRatio || 1;
    canvas.width = canvas.offsetWidth * dpr;
    canvas.height = canvas.offsetHeight * dpr;
    gl.viewport(0, 0, canvas.width, canvas.height);
    camera.projection(fov);
    renderingTexture = FrameBuffer(canvas.width, canvas.height);
    mustResize = false;
  };

  window.addEventListener("resize", () => {
    mustResize = true;
  });

  const Pointer = {
    init() {
      this.x = 0;
      this.y = 0;
      this.xb = 0;
      this.yb = 0;
      this.dx = 0;
      this.dy = 0;
      this.isDown = false;
      window.addEventListener("pointermove", e => this.move(e), false);
      window.addEventListener("pointerdown", e => this.down(e), false);
      window.addEventListener("pointerup", e => this.up(e), false);
      window.addEventListener("pointerout", e => this.up(e), false);
      return this;
    },

    down(e) {
      this.move(e);
      this.xb = this.x;
      this.yb = this.y;
      this.isDown = true;
      e.preventDefault();
    },

    up(e) {
      this.isDown = false;
    },

    move(e) {
      this.x = e.clientX;
      this.y = e.clientY;
      if (this.isDown) {
        this.dx += this.x - this.xb;
        this.dy += this.y - this.yb;
      }
      this.xb = this.x;
      this.yb = this.y;
    } };


  const Camera = () => {
    const mView = new Float32Array(16);
    const mProj = new Float32Array(16);
    return {
      move(rx, ry, z) {
        mView.set([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, z, 1]);
        transforms.rx(mView, rx);
        transforms.ry(mView, ry);
        program.camView(mView);
      },
      projection(fov) {
        const near = 0.001;
        const far = 1000;
        const top = near * Math.tan(fov * Math.PI / 360);
        const right = top * (gl.drawingBufferWidth / gl.drawingBufferHeight);
        const left = -right;
        const bottom = -top;
        mProj[0] = 2 * near / (right - left);
        mProj[5] = 2 * near / (top - bottom);
        mProj[8] = (right + left) / (right - left);
        mProj[9] = (top + bottom) / (top - bottom);
        mProj[10] = -(far + near) / (far - near);
        mProj[11] = -1;
        mProj[14] = -(2 * far * near) / (far - near);
        program.camProj(mProj);
      } };

  };

  // ---- shaders -----

  const program = Shader(`
		precision highp float;
		uniform mat4 camProj, camView;
		attribute vec3 aPosition, aNormal;
		attribute float aBrillance;
		varying vec4 vPosition;
		varying vec3 vNormal, vColor;
		void main() {
			vPosition = camView * vec4(aPosition, 1.0);
			gl_Position = camProj * vPosition;
			vNormal = normalize(vec3(camView * vec4(aNormal, 0.0)));
			vColor = vec3(aBrillance, aBrillance, aBrillance);
		}`, `
		precision highp float;
		uniform vec3 uFog, uFogColor;
		uniform vec3 uLightPosition, uAmbientColor;
		uniform vec3 uSpecularColor, uDiffuseColor;
		varying vec4 vPosition;
		varying vec3 vNormal, vColor;
		float fogDensity = uFog.x;
		float fogPower = uFog.y;
		float shininess = uFog.z;
		void main() {
			float z = gl_FragCoord.z / gl_FragCoord.w;
			float fogFactor = clamp(exp2( - fogDensity * fogDensity * pow(z, fogPower)),.........完整代码请登录后点击上方下载按钮下载查看

网友评论0