首页 > 解决方案 > WebGL - 使用网格作为倒置蒙版

问题描述

我需要将我的画布完全涂成黑色,除了必须保持透明以显示位于画布下方的页面内容的旋转立方体。画布应作为页面内容的掩码。

我认为我的问题可以归结为这个问题。stancil 解决方案将立方体转换为蒙版,我需要的是一个倒置蒙版。

有没有办法打印立方体外的所有东西并使立方体区域完全透明?

提前致谢。

标签: htmlwebglmaskmeshmasking

解决方案


正如@pleup 所说,只需清除不透明的颜色,然后用透明的颜色绘制

网页浏览器

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>


推荐阅读