diff options
author | Norbert Preining <norbert@preining.info> | 2020-07-08 03:01:45 +0000 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2020-07-08 03:01:45 +0000 |
commit | 8c3fedd243b69349b426144e5e2b94ef4aea6a4c (patch) | |
tree | f5842753f11a90141f3cc2e356c3a04766e8d81e /graphics/asymptote/webgl | |
parent | ef87f13c4503a2aa4a9098cbf33e0bfcad19008e (diff) |
CTAN sync 202007080301
Diffstat (limited to 'graphics/asymptote/webgl')
-rw-r--r-- | graphics/asymptote/webgl/gl.js | 145 |
1 files changed, 89 insertions, 56 deletions
diff --git a/graphics/asymptote/webgl/gl.js b/graphics/asymptote/webgl/gl.js index e2053f3161..a7cf6a5862 100644 --- a/graphics/asymptote/webgl/gl.js +++ b/graphics/asymptote/webgl/gl.js @@ -79,11 +79,6 @@ let viewParam = { zmin:0,zmax:0 }; -let positionBuffer; -let materialBuffer; -let colorBuffer; -let indexBuffer; - let remesh=true; let wireframe=0; let mouseDownOrTouchActive=false; @@ -158,15 +153,6 @@ function deleteShaders() gl.deleteProgram(pixelShader); } -// Create buffers for the patch and its subdivisions. -function setBuffers() -{ - positionBuffer=gl.createBuffer(); - materialBuffer=gl.createBuffer(); - colorBuffer=gl.createBuffer(); - indexBuffer=gl.createBuffer(); -} - function noGL() { if (!gl) alert("Could not initialize WebGL"); @@ -241,7 +227,6 @@ function initGL() initShaders(); } - setBuffers(); indexExt=gl.getExtension("OES_element_index_uint"); TRIANGLES=gl.TRIANGLES; @@ -280,6 +265,20 @@ function getShader(gl,shaderScript,type,options=[]) return shader; } +function registerBuffer(buffervector,bufferIndex,copy,type=gl.ARRAY_BUFFER) +{ + if(buffervector.length > 0) { + if(bufferIndex == 0) { + bufferIndex=gl.createBuffer(); + copy=true; + } + gl.bindBuffer(type,bufferIndex); + if(copy) + gl.bufferData(type,buffervector,gl.STATIC_DRAW); + } + return bufferIndex; +} + function drawBuffer(data,shader,indices=data.indices) { if(data.indices.length == 0) return; @@ -288,9 +287,9 @@ function drawBuffer(data,shader,indices=data.indices) setUniforms(data,shader); - gl.bindBuffer(gl.ARRAY_BUFFER,positionBuffer); - gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(data.vertices), - gl.STATIC_DRAW); + let copy=remesh || data.partial || !data.rendered; + data.verticesBuffer=registerBuffer(new Float32Array(data.vertices), + data.verticesBuffer,copy); gl.vertexAttribPointer(positionAttribute,3,gl.FLOAT,false, normal ? 24 : 16,0); if(normal && Lights.length > 0) @@ -298,22 +297,22 @@ function drawBuffer(data,shader,indices=data.indices) else if(pixel) gl.vertexAttribPointer(widthAttribute,1,gl.FLOAT,false,16,12); - gl.bindBuffer(gl.ARRAY_BUFFER,materialBuffer); - gl.bufferData(gl.ARRAY_BUFFER,new Int16Array(data.materialIndices), - gl.STATIC_DRAW); + data.materialsBuffer=registerBuffer(new Int16Array(data.materialIndices), + data.materialsBuffer,copy); gl.vertexAttribPointer(materialAttribute,1,gl.SHORT,false,2,0); + if(shader == colorShader || shader == transparentShader) { - gl.bindBuffer(gl.ARRAY_BUFFER,colorBuffer); - gl.bufferData(gl.ARRAY_BUFFER,new Uint8Array(data.colors), - gl.STATIC_DRAW); + data.colorsBuffer=registerBuffer(new Uint8Array(data.colors), + data.colorsBuffer,copy); gl.vertexAttribPointer(colorAttribute,4,gl.UNSIGNED_BYTE,true,0,0); } - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, - indexExt ? new Uint32Array(indices) : - new Uint16Array(indices),gl.STATIC_DRAW); + data.indicesBuffer=registerBuffer(indexExt ? new Uint32Array(indices) : + new Uint16Array(indices), + data.indicesBuffer,copy, + gl.ELEMENT_ARRAY_BUFFER); + data.rendered=true; gl.drawElements(normal ? (wireframe ? gl.LINES : data.type) : gl.POINTS, indices.length, @@ -325,15 +324,24 @@ let TRIANGLES; class vertexBuffer { constructor(type) { this.type=type ? type : TRIANGLES; + + this.verticesBuffer=0; + this.materialsBuffer=0; + this.colorsBuffer=0; + this.indicesBuffer=0; + + this.rendered=false; // Are all patches in this buffer fully rendered? + this.partial=false; // Does buffer contain incomplete data? + this.clear(); } + clear() { this.vertices=[]; this.materialIndices=[]; this.colors=[]; this.indices=[]; this.nvertices=0; - this.materials=[]; this.materialTable=[]; } @@ -422,7 +430,7 @@ function append(a,b) a[n+i]=b[i]; } -// efficiently append array b onto array a +// efficiently append array b onto array a with offset function appendOffset(a,b,o) { let n=a.length; @@ -488,8 +496,10 @@ class Geometry { setMaterial(data,draw) { if(data.materialTable[this.MaterialIndex] == null) { - if(data.materials.length >= Nmaterials) + if(data.materials.length >= Nmaterials) { + data.partial=true; draw(); + } data.materialTable[this.MaterialIndex]=data.materials.length; data.materials.push(Materials[this.MaterialIndex]); } @@ -510,6 +520,7 @@ class Geometry { if(this.offscreen(v)) { // Fully offscreen this.data.clear(); + this.notRendered(); return; } @@ -517,8 +528,7 @@ class Geometry { let P; if(this.CenterIndex == 0) { - if(!remesh && this.Onscreen) { - // Fully onscreen; no need to re-render + if(!remesh && this.Onscreen) { // Fully onscreen; no need to re-render this.append(); return; } @@ -537,6 +547,7 @@ class Geometry { this.Epsilon=FillFactor*res; this.data.clear(); + this.notRendered(); this.Onscreen=true; this.process(P); } @@ -765,6 +776,15 @@ class BezierPatch extends Geometry { materialData.append(this.data); } + notRendered() { + if(this.transparent) + transparentData.rendered=false; + else if(this.color) + colorData.rendered=false; + else + materialData.rendered=false; + } + Render(p,I0,I1,I2,I3,P0,P1,P2,P3,flat0,flat1,flat2,flat3,C0,C1,C2,C3) { let d=this.Distance(p); if(d[0] < this.res2 && d[1] < this.res2) { // Bezier patch is flat @@ -1683,6 +1703,10 @@ class BezierCurve extends Geometry { material1Data.append(this.data); } + notRendered() { + material1Data.rendered=false; + } + Render(p,I0,I1) { let p0=p[0]; let p1=p[1]; @@ -1747,6 +1771,10 @@ class Pixel extends Geometry { append() { material0Data.append(this.data); } + + notRendered() { + material0Data.rendered=false; + } } class Triangles extends Geometry { @@ -1833,6 +1861,14 @@ class Triangles extends Geometry { else triangleData.append(this.data); } + + notRendered() { + if(this.transparent) + transparentData.rendered=false; + else + triangleData.rendered=false; + } + } function home() @@ -2435,6 +2471,7 @@ function drawColor() function drawTriangle() { drawBuffer(triangleData,transparentShader); + triangleData.rendered=false; // Force copying of sorted triangles to GPU. triangleData.clear(); } @@ -2479,6 +2516,8 @@ function drawTransparent() gl.depthMask(false); // Enable transparency drawBuffer(transparentData,transparentShader,Indices); + // Force copying of sorted triangles to GPU. + transparentData.rendered=false; gl.depthMask(true); // Disable transparency } transparentData.clear(); @@ -2497,8 +2536,8 @@ function drawBuffers() function draw() { if(embedded) { - offscreen.width=canvas.width; - offscreen.height=canvas.height; + offscreen.width=canvasWidth; + offscreen.height=canvasHeight; setViewport(); } @@ -2511,7 +2550,7 @@ function draw() drawBuffers(); if(embedded) { - context.clearRect(0,0,canvas.width,canvas.height); + context.clearRect(0,0,canvasWidth,canvasHeight); context.drawImage(offscreen,0,0); } @@ -2585,21 +2624,20 @@ function setViewport() { gl.viewportWidth=canvasWidth; gl.viewportHeight=canvasHeight; - gl.viewport(0,0,gl.viewportWidth,gl.viewportHeight); - gl.scissor(0,0,gl.viewportWidth,gl.viewportHeight); + gl.viewport(0.5*(canvas.width-canvasWidth),0.5*(canvas.height-canvasHeight), + canvasWidth,canvasHeight); + gl.scissor(0,0,canvas.width,canvas.height); } function setCanvas() { - canvas.width=canvasWidth; - canvas.height=canvasHeight; if(embedded) { - offscreen.width=canvasWidth; - offscreen.height=canvasHeight; + canvas.width=offscreen.width=canvasWidth; + canvas.height=offscreen.height=canvasHeight; } size2=Math.hypot(canvasWidth,canvasHeight); - halfCanvasWidth=0.5*canvasWidth; - halfCanvasHeight=0.5*canvasHeight; + halfCanvasWidth=0.5*canvas.width; + halfCanvasHeight=0.5*canvas.height; } function setsize(w,h) @@ -2644,22 +2682,17 @@ function webGLInit() canvasWidth *= window.devicePixelRatio; canvasHeight *= window.devicePixelRatio; } else { - canvas.width=Math.max(window.innerWidth-windowTrim,windowTrim); - canvas.height=Math.max(window.innerHeight-windowTrim,windowTrim); - let Aspect=canvasWidth/canvasHeight; - if(canvas.width > canvas.height*Aspect) - canvas.width=Math.min(canvas.height*Aspect,canvas.width); - else - canvas.height=Math.min(canvas.width/Aspect,canvas.height); - - if(canvas.width > 0) - canvasWidth=canvas.width; + canvasWidth=Math.max(window.innerWidth-windowTrim,windowTrim); + canvasHeight=Math.max(window.innerHeight-windowTrim,windowTrim); - if(canvas.height > 0) - canvasHeight=canvas.height; + if(!orthographic && canvasWidth < canvasHeight*Aspect) + Zoom0 *= canvasWidth/(canvasHeight*Aspect); } + canvas.width=canvasWidth; + canvas.height=canvasHeight; + setCanvas(); ArcballFactor=1+8*Math.hypot(viewportmargin[0],viewportmargin[1])/size2; |