为什么 gl.clear(gl.COLOR_BUFFER_BIT) 和 requestAnimationFrame 会清除我之前绘制的所有图元
why is that gl.clear(gl.COLOR_BUFFER_BIT) and requestAnimationFrame will clear all the primitives I drew before
大家好,我一直在学习 WebGL 并试图用它制作俄罗斯方块游戏。
我有几个问题想请教:
- 对于这个游戏,我想先绘制网格作为背景。但是我注意到,在我画线之后,如果我在之后使用
gl.clear(gl.COLOR_BUFFER_BIT );
,它会清除我之前画的所有线。我知道 gl.clear(gl.COLOR_BUFFER_BIT );
是关于清除颜色缓冲区的(您可能会问我为什么要这样做。请耐心等待。)。然后我尝试使用 gl.uniform4f( uColor, 0, 0, 0, 1);
将颜色再次发送到片段着色器,但它没有帮助。
片段是这样的
window.onload = function(){
getGLContext();
initShaders();
drawLines( 0, 0, 400,400 );
gl.clear(gl.COLOR_BUFFER_BIT );
gl.uniform4f( uColor, 0, 0, 0, 1);
}
对于游戏,我需要网格作为背景,我需要 requestAnimationFrame
作为游戏循环,并将在循环内渲染 Tetrominos。因此,在画完这条线后,我用这个 draw()
画了其他的 Tetrominos。但是它删除了我之前画的线。当我在 draw()
中注释掉 gl.clear(gl.COLOR_BUFFER_BIT );
时,它会删除该行以及背景颜色。
function draw() {
gl.clear(gl.COLOR_BUFFER_BIT );
gl.drawArrays(gl.TRIANGLES, 0, index*6);
requestAnimationFrame(draw);
}
这是演示:https://codepen.io/zhenghaohe/pen/LqxpjB
希望你能回答这两个问题。谢谢!
这通常是 WebGL 的工作方式。
WebGL 只是绘制成一个像素矩形。没有原始人的记忆。没有结构。只有代码和生成的 canvas 这是一个像素矩形。
大多数 WebGL programs/pages 清除整个 canvas 每一帧,并在每次绘制时重绘他们想要显示的 100% 的内容。对于俄罗斯方块,一般代码可能类似于
function render() {
clear the canvas
draw the grid
draw all the stable pieces
draw the current piece
draw the next piece
draw the effects
draw the score
}
基元或其他结构的任何知识完全取决于您的代码。
如果您希望网格线是静态的,请使用 CSS 设置静态背景或使用另一个 canvas
使用背景:
const gl = document.querySelector('#c').getContext('webgl');
function render(time) {
time *= 0.001;
gl.clearColor(0, 0, 0, 0);
gl.clear(gl.COLOR_BUFFER_BIT);
drawBlocks(gl, time);
requestAnimationFrame(render);
}
requestAnimationFrame(render);
// --- below this line not important to the answer
function drawBlocks(gl, time) {
gl.enable(gl.SCISSOR_TEST);
const numBlocks = 5;
for (let i = 0; i < numBlocks; ++i) {
const u = i / numBlocks;
gl.clearColor(i / 5, i / 2 % 1, i / 3 % 1, 1);
const x = 150 + Math.sin(time + u * Math.PI * 2) * 130;
const y = 75 + Math.cos(time + u * Math.PI * 2) * 55;
gl.scissor(x, y, 20, 20);
gl.clear(gl.COLOR_BUFFER_BIT);
}
gl.disable(gl.SCISSOR_TEST);
}
#c {
background-image: url(https://i.imgur.com/ZCfccZh.png);
}
<canvas id="c"></canvas>
使用 2 canvases
// this is the context for the back canvas. It could also be webgl
// using a 2D context just to make the sample simpler
const ctx = document.querySelector('#back').getContext('2d');
drawGrid(ctx);
// this is the context for the front canvas
const gl = document.querySelector('#front').getContext('webgl');
function render(time) {
time *= 0.001;
gl.clearColor(0, 0, 0, 0);
gl.clear(gl.COLOR_BUFFER_BIT);
drawBlocks(gl, time);
requestAnimationFrame(render);
}
requestAnimationFrame(render);
// --- below this line not important to the answer
function drawBlocks(gl, time) {
gl.enable(gl.SCISSOR_TEST);
const numBlocks = 5;
for (let i = 0; i < numBlocks; ++i) {
const u = i / numBlocks;
gl.clearColor(i / 5, i / 2 % 1, i / 3 % 1, 1);
const x = 150 + Math.sin(time + u * Math.PI * 2) * 130;
const y = 75 + Math.cos(time + u * Math.PI * 2) * 55;
gl.scissor(x, y, 20, 20);
gl.clear(gl.COLOR_BUFFER_BIT);
}
gl.disable(gl.SCISSOR_TEST);
}
function drawGrid(ctx) {
// draw grid
ctx.translate(-10.5, -5.5);
ctx.beginPath();
for (let i = 0; i < 330; i += 20) {
ctx.moveTo(0, i);
ctx.lineTo(330, i);
ctx.moveTo(i, 0);
ctx.lineTo(i, 300);
}
ctx.strokeStyle = "blue";
ctx.stroke();
}
#container {
position: relative; /* required so we can position child elements */
}
#front {
position: absolute;
left: 0;
top: 0;
}
<div id="container">
<canvas id="back"></canvas>
<canvas id="front"></canvas>
</div>
至于为什么即使您没有调用 clear 也会清除,那是因为规范说它应该这样做
参见:
大家好,我一直在学习 WebGL 并试图用它制作俄罗斯方块游戏。
我有几个问题想请教:
- 对于这个游戏,我想先绘制网格作为背景。但是我注意到,在我画线之后,如果我在之后使用
gl.clear(gl.COLOR_BUFFER_BIT );
,它会清除我之前画的所有线。我知道gl.clear(gl.COLOR_BUFFER_BIT );
是关于清除颜色缓冲区的(您可能会问我为什么要这样做。请耐心等待。)。然后我尝试使用gl.uniform4f( uColor, 0, 0, 0, 1);
将颜色再次发送到片段着色器,但它没有帮助。
片段是这样的
window.onload = function(){
getGLContext();
initShaders();
drawLines( 0, 0, 400,400 );
gl.clear(gl.COLOR_BUFFER_BIT );
gl.uniform4f( uColor, 0, 0, 0, 1);
}
对于游戏,我需要网格作为背景,我需要
requestAnimationFrame
作为游戏循环,并将在循环内渲染 Tetrominos。因此,在画完这条线后,我用这个draw()
画了其他的 Tetrominos。但是它删除了我之前画的线。当我在draw()
中注释掉gl.clear(gl.COLOR_BUFFER_BIT );
时,它会删除该行以及背景颜色。function draw() { gl.clear(gl.COLOR_BUFFER_BIT ); gl.drawArrays(gl.TRIANGLES, 0, index*6); requestAnimationFrame(draw); }
这是演示:https://codepen.io/zhenghaohe/pen/LqxpjB
希望你能回答这两个问题。谢谢!
这通常是 WebGL 的工作方式。
WebGL 只是绘制成一个像素矩形。没有原始人的记忆。没有结构。只有代码和生成的 canvas 这是一个像素矩形。
大多数 WebGL programs/pages 清除整个 canvas 每一帧,并在每次绘制时重绘他们想要显示的 100% 的内容。对于俄罗斯方块,一般代码可能类似于
function render() {
clear the canvas
draw the grid
draw all the stable pieces
draw the current piece
draw the next piece
draw the effects
draw the score
}
基元或其他结构的任何知识完全取决于您的代码。
如果您希望网格线是静态的,请使用 CSS 设置静态背景或使用另一个 canvas
使用背景:
const gl = document.querySelector('#c').getContext('webgl');
function render(time) {
time *= 0.001;
gl.clearColor(0, 0, 0, 0);
gl.clear(gl.COLOR_BUFFER_BIT);
drawBlocks(gl, time);
requestAnimationFrame(render);
}
requestAnimationFrame(render);
// --- below this line not important to the answer
function drawBlocks(gl, time) {
gl.enable(gl.SCISSOR_TEST);
const numBlocks = 5;
for (let i = 0; i < numBlocks; ++i) {
const u = i / numBlocks;
gl.clearColor(i / 5, i / 2 % 1, i / 3 % 1, 1);
const x = 150 + Math.sin(time + u * Math.PI * 2) * 130;
const y = 75 + Math.cos(time + u * Math.PI * 2) * 55;
gl.scissor(x, y, 20, 20);
gl.clear(gl.COLOR_BUFFER_BIT);
}
gl.disable(gl.SCISSOR_TEST);
}
#c {
background-image: url(https://i.imgur.com/ZCfccZh.png);
}
<canvas id="c"></canvas>
使用 2 canvases
// this is the context for the back canvas. It could also be webgl
// using a 2D context just to make the sample simpler
const ctx = document.querySelector('#back').getContext('2d');
drawGrid(ctx);
// this is the context for the front canvas
const gl = document.querySelector('#front').getContext('webgl');
function render(time) {
time *= 0.001;
gl.clearColor(0, 0, 0, 0);
gl.clear(gl.COLOR_BUFFER_BIT);
drawBlocks(gl, time);
requestAnimationFrame(render);
}
requestAnimationFrame(render);
// --- below this line not important to the answer
function drawBlocks(gl, time) {
gl.enable(gl.SCISSOR_TEST);
const numBlocks = 5;
for (let i = 0; i < numBlocks; ++i) {
const u = i / numBlocks;
gl.clearColor(i / 5, i / 2 % 1, i / 3 % 1, 1);
const x = 150 + Math.sin(time + u * Math.PI * 2) * 130;
const y = 75 + Math.cos(time + u * Math.PI * 2) * 55;
gl.scissor(x, y, 20, 20);
gl.clear(gl.COLOR_BUFFER_BIT);
}
gl.disable(gl.SCISSOR_TEST);
}
function drawGrid(ctx) {
// draw grid
ctx.translate(-10.5, -5.5);
ctx.beginPath();
for (let i = 0; i < 330; i += 20) {
ctx.moveTo(0, i);
ctx.lineTo(330, i);
ctx.moveTo(i, 0);
ctx.lineTo(i, 300);
}
ctx.strokeStyle = "blue";
ctx.stroke();
}
#container {
position: relative; /* required so we can position child elements */
}
#front {
position: absolute;
left: 0;
top: 0;
}
<div id="container">
<canvas id="back"></canvas>
<canvas id="front"></canvas>
</div>
至于为什么即使您没有调用 clear 也会清除,那是因为规范说它应该这样做
参见: