在OpenGL ES / WebGL中将子数据复制到空纹理中

时间:2015-11-01 23:36:11

标签: opengl-es textures webgl

我用这种方式创建了一个纹理:

var tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.texParameteri(...
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, w, h, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);

然后我尝试将当前帧缓冲区中的子数据复制到其中:

gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, ox, oy, sx, sy, w, h);

它不会第一次复制任何内容。纹理仍为空(包含零)。

当我第二次调用copyTexSubImage2D时,它可以正常工作。如果子区域的大小对应于纹理的大小,它也是第一次起作用。

我想避免在开始时发送实际数据(花费太长时间)并且复制比我需要的更大的区域也需要太长时间。

是预期的行为,还是Chromes WebGL中的错误?还有其他解决方案吗?

1 个答案:

答案 0 :(得分:0)

让我们进行测试



var gl = twgl.getWebGLContext(document.getElementById("c"));
var programInfo = twgl.createProgramInfo(gl, ["vs", "fs"]);
var greenProgramInfo = twgl.createProgramInfo(gl, ["vs", "green-fs"]);

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 texture for a framebuffer
var fbtex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, fbtex);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 256, 256, 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.NEAREST);

// create a framebuffer and attach the texture
var fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, fbtex, 0);

// clear texture to green
//gl.clearColor(0, 1, 0, 1);
//gl.clear(gl.COLOR_BUFFER_BIT);
// Just to make sure let's render green instead of clear to green. (both work for me though)
gl.useProgram(greenProgramInfo.program);
twgl.drawBufferInfo(gl, gl.TRIANGLES, bufferInfo);

// now make a texture
var tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 256, 256, 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.NEAREST);

// copy part of the fbtexture to it
// target, level, xoffset, yoffset, x, y, width, height
gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 10, 20, 30, 40, 50, 60);

gl.bindFramebuffer(gl.FRAMEBUFFER, null);

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

// Now render with the texture
gl.useProgram(programInfo.program);
var uniforms = {
  u_texture: tex,
};
twgl.setUniforms(programInfo, uniforms);
twgl.drawBufferInfo(gl, gl.TRIANGLES, bufferInfo);

canvas { border: 1px solid black; }

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

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

uniform sampler2D u_texture;
varying vec2 v_texcoord;

void main() {
  gl_FragColor = texture2D(u_texture, v_texcoord);
}
</script>
<script id="green-fs" type="notjs">
precision mediump float;

varying vec2 v_texcoord;

void main() {
  gl_FragColor = vec4(0,1,0,1);
}
</script>
<div>If this works there should be a white (transparent) canvas with a green rectangle inside.</div>
<canvas id="c"></canvas>
&#13;
&#13;
&#13;

似乎适合我。它不适合你吗?