【发布时间】:2020-10-28 18:02:37
【问题描述】:
我有一个画布,通过在上面应用一些 WebGL 过滤器来呈现给定的图像。显示的画布必须重复使用。那就是我不断得到不同的图像(程序的其他部分),我应该在这个画布上绘制这些图像,并应用相同的过滤器(片段着色器)。
我在这里创建了一个function drawoncanvas(gl, img, img.width, img.height),gl 是画布的 webglrenderingcontext,img 是带有要使用的图像的 html 元素。该函数具有所有 WebGL 处理部分。
因此,每当我获得要处理并显示在画布上的新图像时。我用同一画布的新 img 元素和 webglrenderingcontext 调用此函数。
我面临的问题是我可以在当前内容后面的画布上看到先前绘制的内容(无论当前内容是透明的)。如果我通过两次相同的图像,画布显示的内容是颠倒的。
我想知道如何在开始使用新图像之前清除画布和/或 WebGL 渲染上下文。这样它就不会显示下面的旧内容或给出这些问题。
编辑:我的代码 sn-p 如下
/* img1, img2 are img elements I get from other part of the program according to user selections.
As per user input more than 2 images can also be received. Demonstrating issue using two */
const canvas = document.getElementB("canvas"); //the canvas on which I am rendering.
const gl = canvas.getContext("webgl");
drawfilter(gl,img1,img1.width, img1.height); // first displaying image one
drawfilter(gl,img2,img2.width, img2.height); // when second image is received the function is called again
function drawfilter(gl,img,width,height){
gl.clearColor(1, 1, 1, 1);
gl.clear(gl.COLOR_BUFFER_BIT||gl.DEPTH_BUFFER_BIT||gl.STENCIL_BUFFER_BIT);
function createShader(gl, type, shaderSource) {
const shader = gl.createShader(type);
gl.shaderSource(shader, shaderSource);
gl.compileShader(shader);
const success = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
if (!success) {
console.warn(gl.getShaderInfoLog(shader));
gl.deleteShader(shader);
}
return shader;
}
//the shaderssources cannot be displayed here
const vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexShaderSource); //simple vertex shader
const fragmentShaderA = createShader(gl, gl.FRAGMENT_SHADER, fragmentShaderSourceA);//simple fragment shader
const fragmentShaderB = createShader(gl, gl.FRAGMENT_SHADER, fragmentShaderSourceB);//simple fragment shader
/* this shader takes two texture inputs. 1- original image,
2- ShadersourceA applied on original image then on output shadersouceB is applied and the result is passed as second texture to this fragment shader */
const fragmentShaderC = createShader(gl, gl.FRAGMENT_SHADER, fragmentShaderSourceC);
function createProgram(gl, vertexShader, fragmentShader) {
const program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
const success = gl.getProgramParameter(program, gl.LINK_STATUS);
if (!success) {
console.log(gl.getProgramInfoLog(program));
gl.deleteProgram(program);
}
return program;
}
const programA = createProgram(gl, vertexShader, fragmentShaderA);
const programB = createProgram(gl, vertexShader, fragmentShaderB);
const programC = createProgram(gl, vertexShader, fragmentShaderC);
const texFbPair1 = createTextureAndFramebuffer(gl);
const texFbPair2 = createTextureAndFramebuffer(gl);
function setAttributes(program) {
const positionLocation = gl.getAttribLocation(program, 'position');
const positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
-1, -1, -1, 1, 1, -1,
1, 1, 1, -1, -1, 1,
]), gl.STATIC_DRAW);
gl.enableVertexAttribArray(positionLocation);
gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);
const texCoordLocation = gl.getAttribLocation(program, "a_texCoord");
const texCoordBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, texCoordBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
0.0, 1.0,
0.0, 0.0,
1.0, 1.0,
1.0, 0.0,
1.0, 1.0,
0.0, 0.0]), gl.STATIC_DRAW);
gl.enableVertexAttribArray(texCoordLocation);
gl.vertexAttribPointer(texCoordLocation, 2, gl.FLOAT, false, 0, 0);
}
const texture = gl.createTexture();
texture.image = new Image();
texture.image.onload = function () {
handleLoadedTexture(gl, texture);
};
texture.image.crossOrigin = '';
texture.image.src = img.getAttribute('src');
function handleLoadedTexture(gl, texture, callback) {
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.image);
setAttributes(programA);
gl.useProgram(programA);
gl.bindFramebuffer(gl.FRAMEBUFFER, texFbPair1.fb);
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.clearColor(0, 0, 1, 1);
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
gl.drawArrays(gl.TRIANGLES, 0, 6);
setAttributes(programB);
gl.useProgram(programB);
gl.bindFramebuffer(gl.FRAMEBUFFER, texFbPair2.fb);
gl.bindTexture(gl.TEXTURE_2D, texFbPair1.tex);
gl.clearColor(0, 0, 0, 1);
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
gl.drawArrays(gl.TRIANGLES, 0, 6)
setAttributes(programC);
gl.useProgram(programC);
var uTextureLocation = gl.getUniformLocation(programC, "uTexture");
var originalTextureLocation = gl.getUniformLocation(programC, "originalTexture");
// set which texture units to render with.
gl.uniform1i(uTextureLocation, 0); // texture unit 0
gl.uniform1i(originalTextureLocation, 1); // texture unit 1
// Set each texture unit to use a particular texture.
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, texFbPair2.tex);
gl.activeTexture(gl.TEXTURE1);
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
gl.clearColor(0, 0, 0, 1);
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
gl.drawArrays(gl.TRIANGLES, 0, 6)
}
function createTextureAndFramebuffer(gl) {
const tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
const fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
return { tex: tex, fb: fb };
}
}
【问题讨论】:
-
这能回答你的问题吗? How to clear the canvas for redrawing
-
我无法获取 2d 上下文并使用 clearrect。 canvas.getContext(“2d”) 给出 null
-
如果您尝试
var gl = canvas.getContext("webgl"); gl.clearColor(1, 1, 1, 1); gl.clear(gl.COLOR_BUFFER_BIT);会怎样? Some MDN Docs -
@blex 我已经试过了,但没用
-
没有代码问题本身我们无法调试您的代码。 WebGL clears itself by default 所以你必须做一些特别的事情来防止这种情况发生。投票结束与 S.O. 一样的话题。如果你想调试帮助,需要一个 repo。请在snippet 中添加minimal 存储库。您可以使用来自imgur的图片
标签: javascript html5-canvas webgl