我试图弄清楚如何使用gl.copyTexImage2D函数。
我有以下代码(虽然笨拙):



//--------- SETUP (not important) ---------------

//I use budo package to easily run browserify
var createContext = require('webgl-context');
var createShader = require('gl-shader');

//↓ here is webgl setup usual routine, using floats and simple one-triangle vertex shader
var gl = createContext({width: 2, height: 2});
gl.getExtension('OES_texture_float');
gl.getExtension('OES_texture_float_linear');

var shader = createShader(gl, `
precision mediump float;
attribute vec2 position;
varying vec2 uv;
void main (void) {
	gl_Position = vec4(position, 0, 1);
	uv = vec2(position.x * 0.5 + 0.5, position.y * 0.5 + 0.5);
}
`, `
precision mediump float;
uniform sampler2D image;
varying vec2 uv;
void main (void) {
	gl_FragColor = texture2D(image, uv);
}
`);

//fullscreen triangle
var buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, -1, -1, 3, 3, -1]), gl.STATIC_DRAW);
shader.attributes.position.pointer();

//textures
var outTexture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, outTexture);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_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);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 2, 2, 0, gl.RGBA, gl.FLOAT, new Float32Array([1,1,1,1, 0,0,0,1, 0,0,0,1, 0,0,0,1]));

var sourceTexture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, sourceTexture);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_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);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 2, 2, 0, gl.RGBA, gl.FLOAT, new Float32Array([0,0,0,1, 1,1,1,1, 0,0,0,1, 0,0,0,1]));


//--------------- MAIN PART (important) ---------------

//then I setup custom framebuffer ↓
var framebuffer = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, outTexture, 0);

gl.bindTexture(gl.TEXTURE_2D, sourceTexture);
gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
gl.drawArrays(gl.TRIANGLES, 0, 3);

//here ↓ I am expecting to copy framebuffer’s output, which is `outTexture`, to `sourceTexture`
gl.bindTexture(gl.TEXTURE_2D, sourceTexture);
gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0, 0, w, h, 0);

//then I try to render shader again, with it’s own output as input
gl.drawArrays(gl.TRIANGLES, 0, 3);

//when I try to read pixels here ↓ I get the error below
gl.readPixels(0, 0, w, h, gl.RGBA, gl.FLOAT, pixels);





错误:[.CommandBufferContext]GL ERROR :GL_INVALID_OPERATION : glCopyTexImage2D:

无法弄清楚我该怎么做。

最佳答案

错误是来自gl.copyTexImage2D而不是gl.readPixels。在调用gl.readPixels之前看不到它的原因是因为WebGL是命令驱动的语言。除非出于各种原因必须执行命令,否则不执行命令。 gl.flush将强制命令在某个时刻执行。 gl.readPixels还强制执行命令,因为命令的结果需要用于读取像素。

至于错误,您需要提供更多代码。照原样通过gl.copyTexImage2D运行代码,这意味着您从中得到的错误与一些未显示的代码有关。您创建的纹理错误,w和h或时髦的值等

在它下面自己尝试一下,但是指出了另一个错误。您无法在WebGL中使用gl.readPixels读取浮点数。切换到UNSIGNED_BYTE的作品



var gl = document.getElementById("c").getContext("webgl");
var w = 300;
var h = 150;

var programInfo = twgl.createProgramInfo(gl, ["vs", "fs"]);
gl.useProgram(programInfo.program);

var arrays = {
  position: [-1, -1, 0, 1, -1, 0, -1, 1, 0, -1, 1, 0, 1, -1, 0, 1, 1, 0],
};
var bufferInfo = twgl.createBufferInfoFromArrays(gl, arrays);
twgl.setBuffersAndAttributes(gl, programInfo, bufferInfo);

// make a renderable npot texture
function createRenderableTexture(gl, w, h) {
 var tex = gl.createTexture();
 gl.bindTexture(gl.TEXTURE_2D, tex);
 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, w, h, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
 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_MIN_FILTER, gl.LINEAR);
 return tex;
}

var outTexture = createRenderableTexture(gl, w, h);
var framebuffer = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, outTexture, 0);

// render something to it
gl.clearColor(0,1,0,1);  // green
gl.clear(gl.COLOR_BUFFER_BIT);

// copy the framebuffer to the texture
var sourceTexture = createRenderableTexture(gl, w, h)
gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0, 0, w, h, 0);

// draw to canvas
gl.bindFramebuffer(gl.FRAMEBUFFER, null);

// clear to red
gl.clearColor(1,0,0,1);
gl.clear(gl.COLOR_BUFFER_BIT);

// Since we cleared to red and the texture is filled with green
// the result should be green
gl.drawArrays(gl.TRIANGLES, 0, 6);

var pixels = new Uint8Array(w * h * 4);
gl.readPixels(0, 0, w, h, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
log("pixel 0: "
        + pixels[0] + ","
        + pixels[1] + ","
        + pixels[2] + ","
        + pixels[3]);

function log(msg) {
  var div = document.createElement("pre");
  div.appendChild(document.createTextNode(msg));
  document.body.appendChild(div);
}

<script src="https://twgljs.org/dist/twgl.min.js"></script>
<script id="vs" type="notjs">
attribute vec4 position;
varying vec2 v_uv;

void main() {
  gl_Position = position;
  v_uv = position.xy * 0.5 + 0.5;
}
</script>
<script id="fs" type="notjs">
precision mediump float;

varying vec2 v_uv;
uniform sampler2D u_texture;

void main() {
  gl_FragColor = texture2D(u_texture, v_uv);
}
  </script>
<canvas id="c"></canvas>





另一方面,FLOAT纹理不起作用。他们为我工作,但据我所知这是我系统上的错误,而不是您的系统。

具体而言,默认情况下,WebGL中不允许使用FLOAT纹理。您可以通过启用OES_texture_float扩展名将其打开,但将that extension specifically says


  
  具有半浮点和浮点通道的纹理是否应支持CopyTexImage2D,CopyTexSubImage {2D | 3D}?
  
  解决方法:不。
  


I filed a bug for Chrome

您可以尝试自己实施copyTexImage2D来解决该问题。基本上,将要复制的纹理作为源纹理附加到某些着色器和四边形。将要复制的纹理附加到帧缓冲区对象。由于它是FLOAT纹理,因此您需要调用checkFramebufferStatus并检查它是否返回FRAMEBUFFER_COMPLETE以确保您的GPU /驱动程序实际上支持浮点纹理作为附件。然后使用简单的着色器绘制四边形,从而有效地将纹理从src复制到dst。

关于javascript - copyTexImage2D — GL错误:GL_INVALID_OPERATION:glCopyTexImage2D:,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/36539955/

10-12 12:38