如何复制webgl画布? (我想要小地图)

时间:2017-07-12 23:47:37

标签: javascript html5 opengl-es webgl

我想要结果..

I want results..

我有一个webgl画布 有没有办法复制webgl画布来创建迷你地图?

我调用json并通过ajax在画布上绘制它像第一张图片

原始画布和迷你地图画布想要共享坐标和图片

控制迷你地图的矩形应该使用绘图功能吗?

<div id="glCanvsDiv" style="height: 100%; width: 100%; padding: 0px; margin: 0px; left: 0px; top: 0px; position: absolute;">
<canvas id="glcanvas" class="canvasclass" style="width: 100%; height: 100%; margin: 0; padding: 0;"></canvas>

这是坐标功能

function getWorldPosition(event) {

const pos = getNoPaddingNoBorderCanvasRelativeMousePosition(event, gl.canvas);

const x = pos.x / gl.canvas.width  *  2 - 1;
const y = pos.y / gl.canvas.height * -2 + 1;

const view = mat4.inverse(cameraMatrix);

const viewProjection = mat4.multiply(projectionMatrix, view);

const viewZ = -5;

const clip = transformPoint(projectionMatrix, [0, 0, viewZ]);

const z = clip[2];

const inverseViewProjection = mat4.inverse(viewProjection); 

var world = transformPoint(inverseViewProjection, [x, y, z]);

world[0] = -world[0];
world[1] = -world[1];

return world;

}

我的对话

<div id="aerialViewDlg" style="display:none; padding:0;">

$("#aerialViewDlg").dialog({
    autoOpen: false,
    width: 300,
    height: 260,
    title: "aerialView",
    position: {
        my: "right top",
        at: "right top",
    }
});

我想迷你地图包括全屏, 原始画布仅显示迷你地图中的选定区域

1 个答案:

答案 0 :(得分:1)

我不清楚你在问什么。迷你地图通常显示的信息比迷你地图外显示的信息多得多。换句话说,主显示器可能显示单个建筑物,其中迷你地图显示整个城镇。这意味着这两件事是无关的。要绘制建筑物,只需绘制建筑物。画城镇你画镇。复制画布不会解决此问题

您可以将一个画布绘制到另一个画布中。最简单的方法是,如果目标画布是2D画布,则只需调用其中一个drawImage变体

ctx.drawImage(srcCanvas, dstX, dstY);

ctx.drawImage(srcCanvas, dstX, dstY, dstWidth, dstHeight);

ctx.drawImage(srcCanvas, 
              srcX, srcY, srcWidth, srcHeight,
              dstX, dstY, dstWidth, dstHeight);

如果要在同一画布中绘制小地图,可以启用剪刀测试并将视口设置为

// draw main display
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
gl.disable(gl.SCISSOR_TEST);
compute projection matrix for main display
draw main display

// draw mini-map
gl.viewport(miniMapX, minMapY, miniMapWidth, minMapHeigh);
gl.scissor(miniMapX, minMapY, miniMapWidth, minMapHeigh);
gl.enable(gl.SCISSOR_TEST);
compute projection matrix for mini-map display
draw mini map display

示例:

&#13;
&#13;
"use strict";
const vs = `
attribute vec4 position;
uniform mat4 matrix;
void main() {
  gl_Position = matrix * position;
}
`;
const fs = `
precision mediump float;
uniform vec4 color;
void main() {
  gl_FragColor = color;
}
`;
const m4 = twgl.m4;
const gl = document.querySelector("canvas").getContext("webgl");

// compiles shaders, link program, looks up locations
const programInfo = twgl.createProgramInfo(gl, [vs, fs]);

const arrays = {
  position: {
    numComponents: 2,
    data: [
     -1, -1, 
      1, -1,
     -1,  1,
      1,  1,
    ],
  },
  indices: {
    numComponents: 2,
    data: [
      0, 1,
      1, 3,
      3, 2,
      2, 0,
    ],
  },
};
// calls gl.createBuffer, gl.bindBuffer, gl.bufferData for each array
const bufferInfo = twgl.createBufferInfoFromArrays(gl, arrays);

  // note: a good app would try to only draw what's visible in each
  // view
function drawScene(viewProjection) {  
  gl.useProgram(programInfo.program);
  // calls gl.bindBuffer, gl.enableVertexAttribArray, gl.vertexAttribPointer
  twgl.setBuffersAndAttributes(gl, programInfo, bufferInfo);
  
  for (let y = -5; y <= 5; ++y) {
    for (let x = -5; x <= 5; ++x) {
      const world = m4.translation([x * 2.4, y * 2.4, 0]);
      const mat = m4.multiply(viewProjection, world);
  
      // calls gl.uniformXXX
      twgl.setUniforms(programInfo, {
        color: [(x + 5) / 10, (y + 5) / 10, x / 5 * y / 5 * .5 + 5, 1],
        matrix: mat,
      });
      // calls gl.drawArrays or gl.drawElements
      twgl.drawBufferInfo(gl, bufferInfo, gl.LINES);
    }
  }
}

function render(time) {
  time *= 0.001;
  twgl.resizeCanvasToDisplaySize(gl.canvas);
  
  // draw main scene
  gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
  gl.disable(gl.SCISSOR_TEST);

  gl.clearColor(0,0,0,1);
  gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

  {
    const unitsVertical = 3;
    const half = unitsVertical * .5
    const aspect = gl.canvas.clientWidth / gl.canvas.clientHeight;
    const left = -half * aspect;
    const right = half * aspect;
    const bottom = -half;
    const top = half;
    const zNear = -1;
    const zFar = 1;
    const projection = m4.ortho(left, right, bottom, top, zNear, zFar);

    const camera = m4.rotationZ(time * .1);
    const view = m4.inverse(camera);
    const viewProjection = m4.multiply(projection, view);
  
    drawScene(viewProjection);
  }
  
  // draw mini map
  const miniMapWidth = gl.canvas.width / 3 | 0;
  const miniMapHeight = gl.canvas.height / 3 | 0;
  const miniMapX = gl.canvas.width - miniMapWidth;
  const miniMapY = gl.canvas.height - miniMapHeight;
  gl.viewport(miniMapX, miniMapY, miniMapWidth, miniMapHeight);
  gl.scissor(miniMapX, miniMapY, miniMapWidth, miniMapHeight);
  gl.enable(gl.SCISSOR_TEST);

  gl.clearColor(0.2,0.2,0.2,1);
  gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

  {
    const unitsVertical = 20;
    const half = unitsVertical * .5
    const aspect = miniMapWidth / miniMapHeight;
    const left = -half * aspect;
    const right = half * aspect;
    const bottom = -half;
    const top = half;
    const zNear = -1;
    const zFar = 1;
    const projection = m4.ortho(left, right, bottom, top, zNear, zFar);

    const camera = m4.rotationZ(time * .1);
    const view = m4.inverse(camera);
    const viewProjection = m4.multiply(projection, view);
  
    drawScene(viewProjection);
  }
    
  requestAnimationFrame(render);
}
requestAnimationFrame(render);
&#13;
body { margin: 0; }
canvas { width: 100vw; height: 100vh; display: block; }
&#13;
<canvas></canvas>
<script src="https://twgljs.org/dist/3.x/twgl-full.min.js"></script>
&#13;
&#13;
&#13;

不幸的是,您无法在WebGL中跨画布共享资源(您无法使用相同的缓冲区和纹理)。但是还有其他各种解决方案。请参阅:Display different scenes sharing resources on multiple canvases