WebGL2 texelFetch'ing 纹理意外结果
WebGL2 texelFetch'ing a texture unexpected results
我用参数 gl.R8、gl.RED、gl.UNSIGNED_BYTE 到 gl.texImage2D 创建了一个 1x1 纹理。
我想这基本上只会创建一个 1 字节的缓冲区。
现在我想在我的片段着色器中访问这个 1 字节缓冲区,使用 texelFetch,但是我没有得到我上传的 1 字节。
我创建了一个简单的示例来说明我的问题:https://jsfiddle.net/w5hp18e0/7/
//Absolutely no error checking for clarity
var canvas=document.getElementById('canvas');
var gl=canvas.getContext('webgl2');
gl.clearColor(0,0,0,1);
gl.clear(gl.COLOR_BUFFER_BIT);
//Vertex shader
var vtx_so=gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vtx_so,`#version 300 es
in vec4 a_pos;
void main(){
gl_Position=a_pos;
}`);
gl.compileShader(vtx_so);
//Fragment shader
var frg_so=gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(frg_so,`#version 300 es
precision mediump float;
precision mediump usampler2D;
uniform usampler2D u_samp;
out vec4 o_color;
void main(){
// README
uint val=texelFetch(u_samp,ivec2(0,0),0).x;
// replace false with true in desired location
if(false){
// set to red IF val != 0
if(val!=0u)
{o_color=vec4(1.,0.,0.,1.);}
}else if(false){
// set to red IF val == 1
if(val==1u)
{o_color=vec4(1.,0.,0.,1.);}
}else if(false){
// set to red IF val & 0x01000000
if((val&0x01000000u)!=0u)
{o_color=vec4(1.,0.,0.,1.);}
}else if(false){
// set to red IF val == 0x01000000
if(val==0x01000000u)
{o_color=vec4(1.,0.,0.,1.);}
}
}`);
gl.compileShader(frg_so);
console.log(gl.getShaderInfoLog(frg_so));
//Program
var prog=gl.createProgram();
gl.attachShader(prog,vtx_so);
gl.attachShader(prog,frg_so);
gl.linkProgram(prog);
gl.useProgram(prog);
//Verticies
var vao=gl.createVertexArray();
gl.bindVertexArray(vao);
var vbo=gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER,vbo);
gl.bufferData(gl.ARRAY_BUFFER,new Float32Array([
0,0,0,1,1,1,1,1,1,0,0,0,
]),gl.STATIC_DRAW);
var loc=gl.getAttribLocation(prog,'a_pos');
gl.vertexAttribPointer(loc,2,gl.FLOAT,false,0,0);
gl.enableVertexAttribArray(loc);
//Texture
var tex=gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D,tex);
gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MAX_LEVEL,0);
var tex_buf=new Uint8Array(1);
// README
tex_buf[0]=1; // set me to some 8-bit value
gl.texImage2D(gl.TEXTURE_2D,0,gl.R8,1,1,0,gl.RED,gl.UNSIGNED_BYTE,tex_buf);
//Sampler
loc=gl.getUniformLocation(prog,'u_samp');
gl.uniform1i(loc,0);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D,tex);
gl.drawArrays(gl.TRIANGLES,0,6);
本质上,当我 texelFetch 我将值“1”上传到的纹理时,它 returns 一些不为 1 的非零数字。我可以推断出的唯一 属性这个返回值的一部分是 val&0x01000000 returns true。但是,甚至 val==0x01000000 returns 都不是真的,这有点令人困惑。
我做错了什么?
您使用的内部格式有误。 GL_R8
代表 float
而 GL_R8UI
代表 unsigned int
。您同样也使用了错误的格式。这里同样需要使用GL_RED_INTEGER
(同理)。
gl.texImage2D(gl.TEXTURE_2D, 0, gl.R8UI, 1, 1, 0, gl.RED_INTEGER, gl.UNSIGNED_BYTE, tex_buf);
您还必须将过滤设置为 GL_NEAREST
。
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
我用参数 gl.R8、gl.RED、gl.UNSIGNED_BYTE 到 gl.texImage2D 创建了一个 1x1 纹理。
我想这基本上只会创建一个 1 字节的缓冲区。
现在我想在我的片段着色器中访问这个 1 字节缓冲区,使用 texelFetch,但是我没有得到我上传的 1 字节。
我创建了一个简单的示例来说明我的问题:https://jsfiddle.net/w5hp18e0/7/
//Absolutely no error checking for clarity
var canvas=document.getElementById('canvas');
var gl=canvas.getContext('webgl2');
gl.clearColor(0,0,0,1);
gl.clear(gl.COLOR_BUFFER_BIT);
//Vertex shader
var vtx_so=gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vtx_so,`#version 300 es
in vec4 a_pos;
void main(){
gl_Position=a_pos;
}`);
gl.compileShader(vtx_so);
//Fragment shader
var frg_so=gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(frg_so,`#version 300 es
precision mediump float;
precision mediump usampler2D;
uniform usampler2D u_samp;
out vec4 o_color;
void main(){
// README
uint val=texelFetch(u_samp,ivec2(0,0),0).x;
// replace false with true in desired location
if(false){
// set to red IF val != 0
if(val!=0u)
{o_color=vec4(1.,0.,0.,1.);}
}else if(false){
// set to red IF val == 1
if(val==1u)
{o_color=vec4(1.,0.,0.,1.);}
}else if(false){
// set to red IF val & 0x01000000
if((val&0x01000000u)!=0u)
{o_color=vec4(1.,0.,0.,1.);}
}else if(false){
// set to red IF val == 0x01000000
if(val==0x01000000u)
{o_color=vec4(1.,0.,0.,1.);}
}
}`);
gl.compileShader(frg_so);
console.log(gl.getShaderInfoLog(frg_so));
//Program
var prog=gl.createProgram();
gl.attachShader(prog,vtx_so);
gl.attachShader(prog,frg_so);
gl.linkProgram(prog);
gl.useProgram(prog);
//Verticies
var vao=gl.createVertexArray();
gl.bindVertexArray(vao);
var vbo=gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER,vbo);
gl.bufferData(gl.ARRAY_BUFFER,new Float32Array([
0,0,0,1,1,1,1,1,1,0,0,0,
]),gl.STATIC_DRAW);
var loc=gl.getAttribLocation(prog,'a_pos');
gl.vertexAttribPointer(loc,2,gl.FLOAT,false,0,0);
gl.enableVertexAttribArray(loc);
//Texture
var tex=gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D,tex);
gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MAX_LEVEL,0);
var tex_buf=new Uint8Array(1);
// README
tex_buf[0]=1; // set me to some 8-bit value
gl.texImage2D(gl.TEXTURE_2D,0,gl.R8,1,1,0,gl.RED,gl.UNSIGNED_BYTE,tex_buf);
//Sampler
loc=gl.getUniformLocation(prog,'u_samp');
gl.uniform1i(loc,0);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D,tex);
gl.drawArrays(gl.TRIANGLES,0,6);
本质上,当我 texelFetch 我将值“1”上传到的纹理时,它 returns 一些不为 1 的非零数字。我可以推断出的唯一 属性这个返回值的一部分是 val&0x01000000 returns true。但是,甚至 val==0x01000000 returns 都不是真的,这有点令人困惑。
我做错了什么?
您使用的内部格式有误。 GL_R8
代表 float
而 GL_R8UI
代表 unsigned int
。您同样也使用了错误的格式。这里同样需要使用GL_RED_INTEGER
(同理)。
gl.texImage2D(gl.TEXTURE_2D, 0, gl.R8UI, 1, 1, 0, gl.RED_INTEGER, gl.UNSIGNED_BYTE, tex_buf);
您还必须将过滤设置为 GL_NEAREST
。
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);