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