WebGL-使用网格作为倒置蒙版

时间:2018-09-05 12:12:34

标签: html5 webgl mask mesh masking

除了需要旋转的立方体(必须保持透明以显示位于画布下方的页面的内容)之外,我需要将画布完全涂成黑色。画布应充当页面内容的遮罩。

我认为我的问题可以减少到this one。锡膏解决方案可以将蒙版转换为蒙版,而我需要的是反转蒙版。

是否存在一种解决方案,可以在立方体之外打印所有内容并使立方体区域完全透明?

谢谢。

1 个答案:

答案 0 :(得分:1)

@pleup所说的只是将其清除为不透明的颜色,然后使用透明的颜色绘制

webgl

var geoVS = `
attribute vec4 position;
uniform mat4 matrix;

void main() {
  gl_Position = matrix * position;
}
`;
var geoFS = `
precision mediump float;
void main() {
  gl_FragColor = vec4(0); 
}
`;

const m4 = twgl.m4;
const gl = document.querySelector("canvas").getContext("webgl", {
  powerPreference: 'low-power',
});
const prgInfo = twgl.createProgramInfo(gl, [geoVS, geoFS]);

const bufferInfo = twgl.primitives.createCubeBufferInfo(gl, 1);

function render(time) {
  time *= 0.001;
  
  twgl.resizeCanvasToDisplaySize(gl.canvas);
  gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
  gl.clearColor(0, 0, 0, 1);
  gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
  
  var fov = Math.PI * .25;
  var aspect = gl.canvas.clientWidth / gl.canvas.clientHeight;
  var zNear = 0.1;
  var zFar = 10;
  var mat = m4.perspective(fov, aspect, zNear, zFar);
  mat = m4.translate(mat, [0, 0, -2]);
  mat = m4.rotateX(mat, time * 0.81);
  mat = m4.rotateZ(mat, time * 0.77);
  
  // draw geometry to generate stencil
  gl.useProgram(prgInfo.program);
  
  twgl.setBuffersAndAttributes(gl, prgInfo, bufferInfo);
  twgl.setUniforms(prgInfo, {
    matrix: mat,
  });

  gl.drawElements(gl.TRIANGLES, bufferInfo.numElements, gl.UNSIGNED_SHORT, 0);
  
  requestAnimationFrame(render);
}
requestAnimationFrame(render);
html, body { 
  margin: 0;
  height: 100%;
  font-size: xx-large;
}
canvas { 
  position: fixed;
  left: 0;
  top: 0;
  width: 100vw; 
  height: 100vh; 
  display: block;
  pointer-events: none;
}
<script src="https://twgljs.org/dist/3.x/twgl-full.min.js"></script>


<div>
content goes here

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed consequat nec tellus non suscipit. Proin fermentum ante ut justo pharetra placerat. Nullam imperdiet eros lectus, non scelerisque lectus gravida sit amet. Duis in justo consectetur,  tincidunt mauris vel, tempus augue. Phasellus venenatis, dui in euismod aliquet, ante lorem efficitur arcu, sed lacinia turpis dui eu metus. Cras ut bibendum velit. Integer lobortis lacus porta odio faucibus, non venenatis arcu pharetra. Praesent fringilla nulla sit amet lectus tempus, id lobortis ligula suscipit. ❤️ Donec sapien erat, sagittis a sem non, vulputate molestie lectus. Etiam id maximus tortor. Pellentesque egestas, ligula sed blandit tristique, est sem facilisis elit, accumsan pellentesque est arcu ac nisl. Sed laoreet nisi sit amet scelerisque convallis.

</div>

<canvas></canvas>

不是立方体,而是为了清楚起见,您应该像使用canvas 2D一样容易

const m4 = twgl.m4;
const ctx = document.querySelector("canvas").getContext("2d", {
  powerPreference: 'low-power',
});

function render(time) {
  time *= 0.001;
  
  twgl.resizeCanvasToDisplaySize(ctx.canvas);
  
  ctx.globalCompositeOperation = "source-over";
  ctx.fillStyle = "black";
  ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
  ctx.save();
  {
    ctx.globalCompositeOperation = "destination-out";
    ctx.fillStyle = "rgba(0,0,0,1)";
    ctx.translate(ctx.canvas.width / 2, ctx.canvas.height / 2);
    ctx.rotate(time);
    ctx.fillRect(ctx.canvas.width / -4,
                 ctx.canvas.height / -4,
                 ctx.canvas.width / 2,
                 ctx.canvas.height / 2);
  }
  ctx.restore();
  
  requestAnimationFrame(render);
}
requestAnimationFrame(render);
html, body { 
  margin: 0;
  height: 100%;
  font-size: xx-large;
}
canvas { 
  position: fixed;
  left: 0;
  top: 0;
  width: 100vw; 
  height: 100vh; 
  display: block;
  pointer-events: none;
}
<script src="https://twgljs.org/dist/3.x/twgl.min.js"></script>


<div>
content goes here

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed consequat nec tellus non suscipit. Proin fermentum ante ut justo pharetra placerat. Nullam imperdiet eros lectus, non scelerisque lectus gravida sit amet. Duis in justo consectetur,  tincidunt mauris vel, tempus augue. Phasellus venenatis, dui in euismod aliquet, ante lorem efficitur arcu, sed lacinia turpis dui eu metus. Cras ut bibendum velit. Integer lobortis lacus porta odio faucibus, non venenatis arcu pharetra. Praesent fringilla nulla sit amet lectus tempus, id lobortis ligula suscipit. ❤️ Donec sapien erat, sagittis a sem non, vulputate molestie lectus. Etiam id maximus tortor. Pellentesque egestas, ligula sed blandit tristique, est sem facilisis elit, accumsan pellentesque est arcu ac nisl. Sed laoreet nisi sit amet scelerisque convallis.

</div>

<canvas></canvas>