wtc-math+webgl实现三维立体空间向前推进摄像机视角效果代码
代码语言:html
所属分类:三维
代码描述:wtc-math+webgl实现三维立体空间向前推进摄像机视角效果代码
代码标签: wtc-math webgl 三维 立体 空间 摄像机 视角
下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开
<!DOCTYPE html> <html lang="en" > <head> <meta charset="UTF-8"> <style> body { background: #666; margin: 0; overflow: hidden; } canvas { height: 100vh; width: 100vw; touch-action: none; cursor: pointer; } .osc { left: 0px; position: fixed; top: 0px; } .button { position: fixed; z-index: 10; right: 0; bottom: 0; } .controls { position: fixed; z-index: 10; left: 0; bottom: 0; } .playpause { background: #AAB; padding: 10px; } .playpause label { display: block; box-sizing: border-box; width: 0; height: 20px; cursor: pointer; border-color: transparent transparent transparent #202020; transition: 100ms all ease; will-change: border-width; border-style: double; border-width: 0px 0 0px 20px; } .playpause input[type='checkbox'] { visibility: hidden; } .playpause.checked label { border-style: double; border-width: 0px 0 0px 20px; } .playpause label { border-style: solid; border-width: 10px 0 10px 20px; } /* } */ </style> </head> <body > <script id="vertexShader_buffer" type="x-shader/x-vertex">attribute vec4 a_position; uniform mat4 u_modelViewMatrix; uniform mat4 u_projectionMatrix; void main() { gl_Position = a_position; } </script> <script id="fragmentShader_AA" type="x-shader/x-vertex"> precision highp float; #extension GL_EXT_shader_texture_lod : enable #extension GL_OES_standard_derivatives : enable uniform vec2 u_resolution; uniform vec2 u_mouse; uniform float u_time; uniform sampler2D b_render; #define FXAA_REDUCE_MIN (1.0/ 128.0) #define FXAA_REDUCE_MUL (1.0 / 8.0) #define FXAA_SPAN_MAX 8.0 void texcoords(vec2 fragCoord, vec2 resolution, out vec2 v_rgbNW, out vec2 v_rgbNE, out vec2 v_rgbSW, out vec2 v_rgbSE, out vec2 v_rgbM) { vec2 inverseVP = 1.0 / resolution.xy; v_rgbNW = (fragCoord + vec2(-1.0, -1.0)) * inverseVP; v_rgbNE = (fragCoord + vec2(1.0, -1.0)) * inverseVP; v_rgbSW = (fragCoord + vec2(-1.0, 1.0)) * inverseVP; v_rgbSE = (fragCoord + vec2(1.0, 1.0)) * inverseVP; v_rgbM = vec2(fragCoord * inverseVP); } //optimized version for mobile, where dependent //texture reads can be a bottleneck vec4 fxaa(sampler2D tex, vec2 fragCoord, vec2 resolution, vec2 v_rgbNW, vec2 v_rgbNE, vec2 v_rgbSW, vec2 v_rgbSE, vec2 v_rgbM) { vec4 color; mediump vec2 inverseVP = vec2(1.0 / resolution.x, 1.0 / resolution.y); vec3 rgbNW = texture2D(tex, v_rgbNW).xyz; vec3 rgbNE = texture2D(tex, v_rgbNE).xyz; vec3 rgbSW = texture2D(tex, v_rgbSW).xyz; vec3 rgbSE = texture2D(tex, v_rgbSE).xyz; vec4 texColor = texture2D(tex, v_rgbM); vec3 rgbM = texColor.xyz; vec3 luma = vec3(0.299, 0.587, 0.114); float lumaNW = dot(rgbNW, luma); float lumaNE = dot(rgbNE, luma); float lumaSW = dot(rgbSW, luma); float lumaSE = dot(rgbSE, luma); float lumaM = dot(rgbM, luma); float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE))); float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE))); mediump vec2 dir; dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE)); dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE)); float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) * (0.25 * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN); float rcpDirMin = 1.0 / (min(abs(dir.x), abs(dir.y)) + dirReduce); dir = min(vec2(FXAA_SPAN_MAX, FXAA_SPAN_MAX), max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX), dir * rcpDirMin)) * inverseVP; vec3 rgbA = 0.5 * ( texture2D(tex, fragCoord * inverseVP + dir * (1.0 / 3.0 - 0.5)).xyz + texture2D(tex, fragCoord * inverseVP + dir * (2.0 / 3.0 - 0.5)).xyz); vec3 rgbB = rgbA * 0.5 + 0.25 * ( texture2D(tex, fragCoord * inverseVP + dir * -0.5).xyz + texture2D(tex, fragCoord * inverseVP + dir * 0.5).xyz); float lumaB = dot(rgbB, luma); if ((lumaB < lumaMin) || (lumaB > lumaMax)) color = vec4(rgbA, texColor.a); else color = vec4(rgbB, texColor.a); return color; } void main() { vec2 rcpFrame = 1./u_resolution.xy; vec2 uv2 = gl_FragCoord.xy / u_resolution.xy; vec3 col; mediump vec2 v_rgbNW; mediump vec2 v_rgbNE; mediump vec2 v_rgbSW; mediump vec2 v_rgbSE; mediump vec2 v_rgbM; texcoords(gl_FragCoord.xy, u_resolution.xy, v_rgbNW, v_rgbNE, v_rgbSW, v_rgbSE, v_rgbM); col = fxaa( b_render, gl_FragCoord.xy, u_resolution.xy, v_rgbNW, v_rgbNE, v_rgbSW, v_rgbSE, v_rgbM).rgb; gl_FragColor = vec4( col, 1. ); // vec3 colour = FxaaPixelShader( uv, b_render, rcpFrame); // gl_FragColor = vec4(colour, 1.); } </script> <script id="fragmentShader_under" type="x-shader/x-vertex"> precision highp float; precision highp int; uniform vec2 u_resolution; uniform vec2 u_mouse; uniform float u_time; uniform sampler2D u_noise; uniform float u_fov; uniform sampler2D b_render; const float vSize = .4; // this is the voxel size const int maxIterations = 256; const int maxIterationsShad = 16; const float stopThreshold = 0.001; const float stepScale = .7; const float eps = 0.005; const vec3 clipColour = vec3(1.); const vec3 fogColour = vec3(.0,.1,.3); const vec3 light1_position = vec3(0, 1., 1.); const vec3 light1_colour = vec3(.8, .8, .85)*1.5; const float light1_strength = .9; const float light1_attenuation = 0.15; const float fogStrength = 0.03; struct Surface { int object_id; float distance; vec3 position; vec3 colour; float ambient; float spec; vec3 norm; vec3 vPos; vec3 mask; vec3 rd; }; vec3 path(float z) { // return vec3( // cos(z*.1 + sin(z*-1.)*.05)*10.+sin(z * .35)*2.,sin(cos(z*.4)*1.5)*2.+cos(z*.143) * 3.,z); return vec3(0,0,z); } float opExtrusion( in vec3 p, in float d, in float h ) { vec2 w = vec2( d, abs(p.z) - h ); return min(max(w.x,w.y),0.0) + length(max(w,0.0)); } float sdBox( in vec2 p, in vec2 b ) { vec2 d = abs(p)-b; return length(max(d,0.0)) + min(max(d.x,d.y),0.0); } vec3 hash33(vec3 p3) { p3 = fract(p3 * vec3(.1031, .1030, .0973)); p3 += dot(p3, p3.yxz+33.33); return fract((p3.xxy + p3.yxx)*p3.zyx); } mat2 rot(float a) { float s = sin(a); float c = cos(a); return mat2(c, -s, s, c); } float world(in vec3 p, inout int object_id) { p.xy -= path(p.z+.2).xy; p.y -= 2.; // p.xy *= rot(p.z * .005); float f = mix(max(p.y, -step(abs(p.x) - 1., 0.)), 100., step(1., float(object_id))); float l = abs(p.x); vec3 id = floor(p/2.); vec3 r = hash33(id); p = mod(p, 4.) - 2.; return max(length(p.xz)-r.x*1.*length(p.yz)-r.y*1., -l+.5); } float world(in vec3 position) { int dummy = 0; return world(position, dummy); } float world(in vec3 position, in float voxelSize) { int dummy = 1; return world(position*voxelSize, dummy); } Surface getSurface(int object_id, float rayDepth, vec3 sp, vec3 norm, vec3 vPos, vec3 mask, vec3 rd) { return Surface( object_id, rayDepth, sp, vec3(.5, 0.3, 0.), .3, 2., norm, vPos, mask, rd); } vec3 voxelTrace( vec3 ro, vec3 rd, out bool hit, inout vec3 norm, out float rayDepth, out float steps, out vec2 center, out vec3 mask, out vec3 vPos) { ro /= vSize; rd /= vSize; vec3 vRay = floor(ro) + .5; vec3 inRay = 1./abs(rd); vec3 signRay = sign(rd); rd = signRay; vec3 side = (inRay*(rd * (vRay - ro) + 0.5)); // vec3 mask = vec3(0); for (int i = 0; i < maxIterations; i++) { if (world(vRay*vSize)<0.) { hit = true; break; } mask = (step(side, side.yzx)*(1.-step(side.zxy, side))); side += (mask*inRay); vRay = (vRay + mask * rd); } norm = normalize((-mask * signRay)); rayDepth = length(ro - vRay); return vRay; } float voxelToDistance(vec3 ro, vec3 rd, vec3 voxelPos) { ro /= vSize; rd /= vSize; vec3 c = (voxelPos-ro - .5*sign(rd))/rd; return max(max(c.x, c.y), c.z); } float voxShadow(vec3 ro, vec3 rd, float end){ ro /= vSize; rd /= vSize; float shade = 1.0; vec3 p = floor(ro) + .5; vec3 dRd = 1./abs(rd);//1./max(abs(rd), vec3(.0001)); rd = sign(rd); vec3 side = dRd*(rd * (p - ro) + 0.5); vec3 mask = vec3(0); float d = 1.; for (int i = 0; i < maxIterationsShad; i++) { d = world(p*vSize); if (d<0. || length(p-ro)>end) break; mask = step(side, side.yzx)*(1.-step(side.zxy, side)); side += mask*dRd; p += mask * rd; } // Shadow value. If in shadow, return a dark value. return shade = step(0., d)*.7 + .3; } vec4 voxelAO(vec3 p, vec3 d1, vec3 d2) { // Take the four side and corner readings... at the correct positions... // That's the annoying bit that I'm glad others have worked out. :) vec4 side = vec4(world(p + d1, vSize), world(p + d2, vSize), world(p - d1, vSize), world(p - d2, vSize)); vec4 corner = vec4(world(p + d1 + d2, vSize), world(p - d1 + d2, vSize), world(p - d1 - d2, vSize), world(p + d1 - d2, vSize)); // Quantize them. It's either occluded, or it's not, so to speak. side = step(side, vec4(0)); corner = step(corner, vec4(0)); // Use the side and corner values to produce a more honed in value... kind of. return 1. - (side + side.yzwx + max(corner, side*side.yzwx))/3.; } float calcVoxAO(vec3 ro, vec3 rd, Surface surfaceObject) { ro /= vSize; // rd /= vSize; vec3 vp = surfaceObject.vPos; vec3 sp = ro + rd * surfaceObject.distance; sp = surfaceObject.position/vSize; vec3 mask = surfaceObject.mask; // Obtain four AO values at the appropriate quantized positions. vec4 vAO = voxelAO(vp - sign(rd)*mask, mask.zxy, mask.yzx); // Use the fractional voxel postion and and the proximate AO values // to return the interpolated AO value for the surface position. sp = fract(sp); vec2 uv = sp.yz*mask.x + sp.zx*mask.y + sp.xy*mask.z; return mix(mix(vAO.z, vAO.w, uv.x), mix(vAO.y, vAO.x, uv.x), uv.y); } vec3 lighting(Surface surface_object, vec3 cam, vec3 lp) { // start with black vec3 sceneColour = vec3(0); // Surface normal vec3 normal = surface_object.norm; // Light position // vec3 lp = cam + vec3(0., -1., 0.); // lp.xy = path(lp.z).xy + light1_position.xy; // Light direction vec3 ld = lp - surface_object.position; vec3 ldo = (lp - surface_object.position); // light attenuation // For brightly lit scenes or global illumination (like sunlit), this can be limited to just normalizing the ld float len = length( ld ); ld = normalize(ld); float lightAtten = min( 1.0 / ( light1_attenuation*len ), 1.0 ); // float lightAtten = 1.; // Scene values, mainly for fog float sceneLength = length(cam - surface_object.position); float sceneAttenuation = min( 1. / ( fogStrength * sceneLength * sceneLength ), 1. ); // The surface's light reflection normal vec3 reflection_normal = reflect(-ld, normal); // Ambient Occlusion float ao = 1.; ao = calcVoxAO(cam, surface_object.rd, surface_object); // Object surface properties float diffuse = clamp(dot(normal, ld), 0., 1.); float specular = clamp(dot( reflection_normal, normalize(cam - surface_object.position) ), 0., 1.); // specular = .5; // shadows float shadows = 1.; shadows = voxShadow((surface_object.position + surface_object.norm*.001), ld, len); // Bringing all of the lighting components together sceneColour += ( surface_object.colour * mix(surface_object.ambient, shadows, diffuse) + specular ) * light1_colour * lightAtten * light1_strength; // adding fog sceneColour = clamp(mix( sceneColour, mix(fogColour, vec3(0.), clamp(1.-sceneAttenuation*16., 0., 1.)), 1. - sceneAttenuation ), 0., 1.); return sceneColour*min(ao+.3, 1.); } void main() { vec2 uv = (gl_FragCoord.xy - 0.5 * u_resolution.xy) / min(u_resolution.y, u_resolution.x); vec2 m = (u_mouse.xy - 0.5 * u_resolution.xy) / min(u_resolution.y, u_resolution.x); float ptime = u_time * 5.; // movement vec3 movement = path(ptime); // Camera and look-at vec3 cam = vec3(0,-1.5,-1); vec3 lookAt = vec3(.2,-1.,0); // add movement lookAt += path(ptime+5.); cam += movement; vec3 light = lookAt; lookAt += vec3(m*vec2(20., -20.), 0.); // Unit vectors vec3 forward = normalize(lookAt - cam); vec3 right = normalize(vec3(forward.z, 0., -forward.x)); vec3 up = normalize(cross(forward, right)); // FOV float FOV = u_fov; // Ray origin and ray direction vec3 ro = cam; vec3 rd = normalize(forward + FOV * uv.x * right + FOV * uv.y * up); vec3 pt = path(lookAt.z); float t = pt.x*.02; float s = sin(t); float c = cos(t); rd.xy *= mat2(c, -s, s, c); // t = pt.y*.2; // s = sin(t); // c = cos(t); // rd.yz *= mat2(c, -s, s, c); bool hit = false; vec3 norm = vec3(0.); float rayDepth = 0.; float steps = 0.; vec2 center = vec2(0); const float clipNear = 0.; const float clipFar = 32.; vec3 mask; vec3 vPos; vec3 surfacePos = voxelTrace(ro, rd, hit, norm, rayDepth, steps, center, mask, vPos); Surface objectSurface = getSurface(1, rayDepth, cam + rd * voxelToDistance(ro, rd, surfacePos), norm, surfacePos, mask, rd); // gl_FragColor = vec4(vec3(hp/20.), 1.); // return; // if(length(center) > 0.) { // objectSurface.colour = vec3(smoothstep(.9,.92,length(center))); // objectSurface.colour = vec3(length((center))); // } vec3 sceneColour = vec3(0); if(hit) { sceneColour = lighting(objectSurface, cam, light); } float bright = smoothstep(2.9, 4.,sceneColour.r + sceneColour.g + sceneColour.b); // sceneColour = vec3(bright); float additive = smoothstep(12., 1., u_fov); gl_FragColor = vec4(sceneColour*(additive*.8+.2) + texture2D(b_render, gl_FragCoord.xy/u_resolution.xy).rgb*((1.-additive)*.8+.2), 1.); // gl_FragColor *= gl_FragColor; // gl_FragColor *= vec4(vec3(rayDepth*.02), 1.); } </script> <script type="module"> import { Vec2, Vec3, Mat2, Mat3, Mat4, Quat } from '//repo.bfw.wiki/bfwrepo/js/module/wtc-math/wtc-math.1.0.14.js'; console.clear(); const setup = function() { const dimensions = [window.innerWidth, window.innerHeight]; const canvas = document.createElement('canvas'); document.body.appendChild(canvas); const renderer = new Renderer(canvas, { width: dimensions[0], height: dimensions[1], alpha: false, premultipliedAlpha: true, preserveDrawingBuffer: true }); const ctx = renderer.ctx; let drawing = new Float32Array([ -1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0]); const drawBuffer = new Buffer(ctx, drawing); const vertexShader_buffer = document.getElementById('vertexShader_buffer').innerText; const programMain = new Program(ctx, vertexShader_buffer, document.getElementById('fragmentShader_under').innerText, { clearColour: [.15, .15, 0.25, 1.], renderType: Program.RENDER_STRIP }); const programAA = new Program(ctx, vertexShader_buffer, document.getElementById('fragmentShader_AA').innerText, { renderType: Program.RENDER_STRIP }); const renderBuffer = new FrameBuffer(renderer, 'render', { width: dimensions[0], height: dimensions[1], tiling: Texture.IMAGETYPE_REGULAR, texdepth: FrameBuffer.TEXTYPE_FLOAT, pxRatio: Math.min(window.devicePixelRatio, 2) }); const time = new Uniform(ctx, 'time', Uniform.TYPE_FLOAT, 100); const uDelta = new Uniform(ctx, 'delta', Uniform.TYPE_FLOAT, 100); const fov = new Uniform(ctx, 'fov', Uniform.TYPE_FLOAT, .9); let timedilation = 1.; const mouse = new Uniform(ctx, 'mouse', Uniform.TYPE_V2, [window.innerWidth/2,window.innerHeight/2]); const noise = new Texture(ctx, 'noise', { textureType: Texture.IMAGETYPE_TILE, url: '//repo.bfw.wiki/bfwrepo/image/5dfd8574f13f0.png' }); noise.preload().then((n) => { requestAnimationFrame(run); }); let pointerdown = false; let lastPos = new Vec2(); window.addEventListener('pointerdown', (e) => { pointerdown = true; lastPos = new Vec2(e.x, e.y); }); window.addEventListener('pointerup', (e) => { pointerdown = false; }); window.addEventListener('pointermove', (e) => { // if(pointerdown) { let newPos = new Vec2(e.x, e.y); mouse.value = newPos.array; // } }); let playing = true; const setPlaying = (value) => { playing = value; } let autoTransitionTimer = 0; let timeToTransition = 0; const setupValues = (i) => { dimensions[0] = window.innerWidth; dimensions[1] = window.innerHeight; time.value = -100; } setupValues(0); let timeout; window.addEventListener('resize', () => { clearTimeout(timeout); timeout = setTimeout(() => { dimensions[0] = window.innerWidth; dimensions[1] = window.innerHeight; renderer.resize(dimensions[0], dimensions[1]); renderBuffer.resize(dimensions[0], dimensions[1]); }, 100); }); const opx = renderer.pxRatio; let then = 0; let gifDone = false; const run = (delta) => { let now = Date.now() / 1000; let _delta = now - then; then = now; if(_delta > 1000) { requestAnimationFrame(run); return; } if(pointerdown) { timedilation += (10. - timedilation) * .002; fov.value += (10 - fov.value) * .002; } else { if(timedilation > 1.01) { timedilation += (1. - timedilation) * .02; } if(fov.value > .91) { fov.value += (.9 - fov.value) * .05; } } if(playing) { uDelta.value = Math.min(_delta, 0.5); time.value += _delta * .15 * timedilation; renderer.setViewport(); renderer.setupProgram(programMain, [drawBuffer], [], [time, mouse, fov]); renderBuffer.render(4); renderer.setupProgram(programAA, [drawBuffer], [], [time, mouse, renderBuffer]); renderer.render(4); requestAnimationFrame(run); } } } // Determine whether a number is a power of 2 function powerOf2(v) { return v && !(v & (v - 1)); } // Return the next greatest power of 2 function nextPow2( v ) { v--; v |= v >> 1; v |= v >> 2; v |= v >> 4; v |= v >> 8; v |= v >> 16; v++; return v; } // Update a provided image to the nearest power of 2 in size. const pow2Image = (c) => { const newWidth = powerOf2(c.width) ? c.width : nextPow2(c.width); const newHeight = powerOf2(c.height) ? c.height : nextPow2(c.height); const _c = document.createElement('canvas'); const ctx = _c.getContext('2d'); _c.width = newWidth; _c.height = newHeight; ctx.drawImage(c, 0, 0, newWidth, newHeight); return _c; } const asyncImageLoad = function(img, src) { return new Promise((resolve, reject) => { img.onload = () => resolve(img); img.onerror = reject; img.src = src; }) } const glEnumToString = (function() { const haveEnumsForType = {}; const enums = {}; function addEnums(gl) { const type = gl.constructor.name; if (!haveEnumsForType[type]) { for (const key in gl) { if (typeof gl[key] === 'number') { const existing = enums[gl[key]]; enums[gl[key]] = existing ? `${existing} | ${key}` : key; } } haveEnumsForType[type] = true; } } return function glEnumToString(gl, value) { addEnums(gl); return enums[value] || (typeof value === 'number' ? `0x${value.toString(16)}` : value); }; }()); const addExtensions = (ctx) => { // Set up the extensions ctx.getExtension('OES_standard_derivatives'); ctx.getExtension('EXT_shader_texture_lod'); ctx.getExtension('OES_texture_float'); ctx.getExtension('WEBGL_color_buffer_float'); ctx.getExtension('OES_texture_float_linear'); ctx.getExtension('EXT_color_buffer_float'); } function createContext(c, opt_attribs, params) { const ctx = c.getContext("webgl", params) || this._el.getContext("experimental-webgl", params); addExtensions(ctx); return ctx; } const quatToMat4 = (q) => { if(q.array) q = q.array; // This just transforms a provided vector into to an array. if(q instanceof Array && q.length >= 4) { const [x, y, z, w] = q; const [x2, y2, z2] = q.map(x => x * 2.); const xx = x * x2, yx = y * x2, yy = y * y2, zx = z * x2, zy = z * y2, zz = z * z2, wx = w * x2, wy = w * y2, wz = w * z2; return new Mat4( 1 - yy -zz, yx -wz, zx + wy, 0, yx + wz, 1 - xx - zz, zy - wx, 0, zx - wy, zy + wx, 1 - xx - yy, 0, 0, 0, 0, 1 ); } } class Renderer { static #defaultOptions = { width: 512, height: 512, pxRatio: Math.min(window.devicePixelRatio, 2), clearing: true, depthTesting: true, premultipliedAlpha: true } static BLENDING_DEBUG = -1; static BLENDING_NORMAL = 1; static BLENDING_ADDITIVE = 2; static BLENDING_SUBTRACTIVE = 4; static BLENDING_MULTIPLY = 8; static BLENDING_OFF = 16; isWebgl2 = false; #blending; #blendingEnabled = false; #buffers = []; constructor(canvas, options) { options = Object.assign({}, Renderer.#defaultOptions, options); this.width = options.width; this.height = options.height; this.pxRatio = options.pxRatio; this.clearing = options.clearing; this.depthTesting = options.depthTesting; this.canvas = canvas || document.createElement('canvas'); this.canvas.width = this.width * this.pxRatio; this.canvas.height = this.height * this.pxRatio; this.premultipliedAlpha = options.premultipliedAlpha; this.ctx = this.canvas.getContext("webgl", options) || this.canvas.getContext("experimental-webgl", options); this.ctx.viewportWidth = this.canvas.width; this.ctx.viewportHeight = this.canvas.height; this.uniformResolution = new Uniform(this.ctx, 'resolution', Uniform.TYPE_V2, [this.canvas.width, this.canvas.height]); this.addExtensions(); } resize(w, h, ratio) { this.width = w; this.height = h; this.pxRatio = ratio || this.pxRatio; this.canvas.width = this.width * this.pxRatio; this.canvas.height = this.height * this.pxRatio; this.ctx.viewportWidth = this.canvas.width; this.ctx.viewportHeight = this.canvas.height; this.uniformResolution = new Uniform(this.ctx, 'resolution', Uniform.TYPE_V2, [this.canvas.width, this.canvas.height]); } setViewport(dimensions) { let w = this.width*this.pxRatio; let h = this.height*this.pxRatio; if(dimensions) { w = dimensions[0]; h = dimensions[1]; } this.ctx.viewport(0, 0, w, h); this.uniformResolution = new Uniform(this.ctx, 'resolution', Uniform.TYPE_V2, [w, h]); } addExtensions() { this.ctx.getExtension('OES_standard_derivatives'); this.ctx.getExtension('EXT_shader_texture_lod'); this.ctx.getExtension('OES_texture_float'); this.ctx.getExtension('WEBGL_color_buffer_float'); this.ctx.getExtension.........完整代码请登录后点击上方下载按钮下载查看
网友评论0