Glsl 在WebGL中将数据放到不同的纹理上并将其取出
我试图从着色器输出多个缓冲区-一般目标是将其用于GPGPU目的。我已经看到了这一点,并通过这一点更接近目标:Glsl 在WebGL中将数据放到不同的纹理上并将其取出,glsl,webgl,Glsl,Webgl,我试图从着色器输出多个缓冲区-一般目标是将其用于GPGPU目的。我已经看到了这一点,并通过这一点更接近目标: document.addEventListener("DOMContentLoaded", function() { function main() { const gl = document.querySelector('canvas').getContext('webgl2'); if (!gl) {
document.addEventListener("DOMContentLoaded", function() {
function main() {
const gl = document.querySelector('canvas').getContext('webgl2');
if (!gl) {
return alert("need WebGL2");
}
gl.canvas.width = 2;
gl.canvas.height = 2;
const vs = `
#version 300 es
in vec2 position;
void main(void) {
gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
}
`;
const fs = `
#version 300 es
precision mediump float;
layout(location = 0) out vec4 outColor0;
layout(location = 1) out vec4 outColor1;
layout(location = 2) out vec4 outColor2;
layout(location = 3) out vec4 outColor3;
layout(location = 4) out vec4 outColor4;
layout(location = 5) out vec4 outColor5;
void main() {
// simplified for question purposes
outColor0 = vec4(1, 0, 0, 1);
outColor1 = vec4(0, 1, 0, 1);
outColor2 = vec4(0, 0, 1, 1);
outColor3 = vec4(1, 1, 0, 1);
outColor4 = vec4(1, 0, 1, 1);
outColor5 = vec4(0, 1, 1, 1);
}
`
const program = twgl.createProgram(gl, [vs, fs]);
const textures = [];
const fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
for (let i = 0; i < 6; ++i) {
const tex = gl.createTexture();
textures.push(tex);
gl.bindTexture(gl.TEXTURE_2D, tex);
const width = 2;
const height = 2;
const level = 0;
gl.texImage2D(gl.TEXTURE_2D, level, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
// attach texture to framebuffer
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + i, gl.TEXTURE_2D, tex, level);
}
gl.viewport(0, 0, 2, 2);
// tell it we want to draw to all 4 attachments
gl.drawBuffers([
gl.COLOR_ATTACHMENT0,
gl.COLOR_ATTACHMENT1,
gl.COLOR_ATTACHMENT2,
gl.COLOR_ATTACHMENT3,
gl.COLOR_ATTACHMENT4,
gl.COLOR_ATTACHMENT5,
]);
// draw a single point
gl.useProgram(program);
{
const offset = 0;
const count = 1
gl.drawArrays(gl.TRIANGLE, 0, 4);
}
for (var l = 0; l < 6; l++) {
var pixels = new Uint8Array(gl.canvas.width * gl.canvas.height * 4);
gl.readBuffer(gl.COLOR_ATTACHMENT0 + l);
gl.readPixels(0, 0, gl.canvas.width, gl.canvas.height, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
console.log(pixels.join(' '));
}
}
main();
})
而不是我所希望/期望的:
255 0 0 255 255 0 0 255 255 0 0 255 255 0 0 255
etc.
我早就料到了
outColor0 = vec4(1, 0, 0, 1);
相当于
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
但显然我错了
那么,我如何才能得到期望的结果——能够在每个缓冲区上设置每个像素?代码不提供任何顶点数据,即使它要求它绘制4个顶点。此外,它正在传入不存在的
gl.TRIANGLE
。它是gl.三角形
,末尾是s
<代码>总图三角形将被未定义,强制为0,与总图点匹配
在JavaScript控制台中
> const gl = document.createElement('canvas').getContext('webgl2');
< undefined
> gl.TRIANGLE
< undefined
> gl.TRIANGLES
< 4
> gl.POINTS
< 0
你可以这么做
gl.drawArrays(4, offset, count)
因为gl.三角形
=4
但是你没有使用gl.TRIANGLES
你使用了gl.TRIANGLE
(没有S
),所以你有效地做到了这一点
gl.drawArrays(undefined, offset, count)
这被解释为
gl.drawArrays(0, offset, count)
0=gl.POINTS,这与
gl.drawArrays(gl.POINTS, offset, count)
然后,代码在同一位置绘制单个1像素点4次,因为您使用计数4调用它
gl.drawArrays(gl.POINTS, 0, 4)
顶点着色器中的任何内容都不会更改每次迭代,因此每次迭代都将执行完全相同的操作。在本例中,它将在剪辑空间位置0,0,0,1处绘制一个1x1像素点,该点将最终成为2x2像素的左下像素
在任何情况下,您可能希望提供顶点,但作为一个简单的测试,如果我添加
gl_PointSize = 2.0;
到顶点着色器,并将绘制调用更改为
gl.drawArrays(gl.POINTS, 0, 1); // draw 1 point
然后它会产生您期望的结果。它在剪辑空间位置0,0,0,1处绘制单个2x2像素点
函数main(){
const gl=document.querySelector('canvas').getContext('webgl2');
如果(!gl){
返回警报(“需要WebGL2”);
}
gl.canvas.width=2;
gl.canvas.height=2;
常数vs=`
#300版es
在vec2位置;
真空总管(真空){
gl_位置=vec4(0.0,0.0,0.0,1.0);
gl_PointSize=2.0;
}
`;
常数fs=`
#300版es
精密中泵浮子;
布局(位置=0)输出vec4输出颜色0;
布局(位置=1)输出向量4输出颜色1;
布局(位置=2)输出向量4输出颜色2;
布局(位置=3)输出向量4输出颜色3;
布局(位置=4)输出向量4输出颜色4;
布局(位置=5)输出向量4输出颜色5;
void main(){
//为提问而简化
outColor0=vec4(1,0,0,1);
outColor1=vec4(0,1,0,1);
outColor2=vec4(0,0,1,1);
outColor3=vec4(1,1,0,1);
outColor4=vec4(1,0,1,1);
outColor5=vec4(0,1,1,1);
}
`
const program=twgl.createProgram(gl[vs,fs]);
常量纹理=[];
const fb=gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER,fb);
for(设i=0;i<6;++i){
常量tex=gl.createTexture();
纹理。推送(tex);
gl.bindTexture(gl.TEXTURE_2D,tex);
常数宽度=2;
常数高度=2;
常数级=0;
gl.texImage2D(gl.TEXTURE_2D,level,gl.RGBA,宽度,高度,0,gl.RGBA,gl.UNSIGNED_字节,null);
//将纹理附加到帧缓冲区
gl.framebufferTexture2D(gl.FRAMEBUFFER、gl.COLOR_ATTACHMENT0+i、gl.TEXTURE_2D、tex、level);
}
总图视口(0,0,2,2);
//告诉它我们要绘制所有4个附件
德国劳埃德船级社([
gl.COLOR_附件0,
gl.COLOR_附件1,
gl.COLOR_附件2,
gl.COLOR_附件3,
gl.COLOR_附件4,
gl.COLOR_附件5,
]);
//画一个点
gl.useProgram(程序){
常数偏移=0;
常数计数=1
总图绘制阵列(总图点,0,1);
}
对于(var l=0;l<6;l++){
var像素=新的Uint8Array(gl.canvas.width*gl.canvas.height*4);
gl.readBuffer(gl.COLOR_附件0+l);
gl.readPixels(0,0,gl.canvas.width,gl.canvas.height,gl.RGBA,gl.UNSIGNED_字节,像素);
console.log(像素连接(“”));
}
}
main()代码>
我可能会在某个时候提出一些澄清性的问题,但首先,我会仔细研究,直到完全理解答案。我希望有一种方法能够以某种方式总结这些以GPGPU为重点的问题和答案,并反馈给社区。还是除了我,他们太明显了?还是太利基了?你觉得怎么样?如果我的回答不容易理解,我很抱歉。更新了答案。我不确定您对WebGL的理解程度,但可能会有所帮助
gl_PointSize = 2.0;
gl.drawArrays(gl.POINTS, 0, 1); // draw 1 point