繁体   English   中英

WebGL2将Uint16Array渲染为画布作为图像

[英]WebGL2 render Uint16Array to canvas as an image

我试图渲染Uint16Array在图像中使用webgl2纹理浏览器。 我有一个Uint8Array的工作示例提琴,由于webgl的学习曲线很陡,我正在努力升级到16位。

工作8位小提琴(与下面的代码段相同): Uint8Array http://jsfiddle.net/njxvftc9/2/ 非工作16位尝试: Uint16Array http://jsfiddle.net/njxvftc9/3/

 // image data var w = 128; var h = 128; var size = w * h * 4; var img = new Uint8Array(size); // need Uint16Array for (var i = 0; i < img.length; i += 4) { img[i + 0] = 255; // r img[i + 1] = i/64; // g img[i + 2] = 0; // b img[i + 3] = 255; // a } // program var canvas = document.getElementById('cv'); var gl = canvas.getContext('webgl2'); var program = gl.createProgram(); //var color_buffer_float_16ui = gl.getExtension('EXT_color_buffer_float'); // add for 16-bit // texture var tex = gl.createTexture(); // create empty texture gl.bindTexture(gl.TEXTURE_2D, tex); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); gl.texImage2D( gl.TEXTURE_2D, // target 0, // mip level gl.RGBA, // internal format -> gl.RGBA16UI w, h, // width and height 0, // border gl.RGBA, //format -> gm.RGBA_INTEGER gl.UNSIGNED_BYTE, // type -> gl.UNSIGNED_SHORT img // texture data ); // buffer var buffer = gl.createBuffer(); var bufferData = new Float32Array([ -1, -1, 1, -1, 1, 1, 1, 1, -1, 1, -1, -1 ]); gl.bindBuffer(gl.ARRAY_BUFFER, buffer); gl.bufferData(gl.ARRAY_BUFFER, bufferData, gl.STATIC_DRAW); // shaders program.vs = gl.createShader(gl.VERTEX_SHADER); gl.shaderSource(program.vs, "attribute vec4 vertex;\\n" + // incoming pixel input? "varying vec2 pixelCoordinate;\\n" + // variable used to pass position to fragment shader "void main(){\\n" + " gl_Position = vertex;\\n" + // set pixel output position to incoming position (pass through) " pixelCoordinate = vertex.xy*0.5+0.5;\\n" + // set coordinate for fragment shader "}\\n"); program.fs = gl.createShader(gl.FRAGMENT_SHADER); gl.shaderSource(program.fs, "precision highp float;\\n" + // ? "uniform sampler2D tex;\\n" + // ? "varying vec2 pixelCoordinate;\\n" + // receive pixel position from vertex shader "void main(){\\n" + " gl_FragColor = texture2D(tex, pixelCoordinate);\\n" + // lookup color in texture image at coordinate position and set color to "}\\n"); gl.compileShader(program.vs); gl.compileShader(program.fs); gl.attachShader(program,program.vs); gl.attachShader(program,program.fs); gl.deleteShader(program.vs); gl.deleteShader(program.fs); // program gl.bindAttribLocation(program, 0, "vertex"); gl.linkProgram(program); gl.useProgram(program); gl.enableVertexAttribArray(0); gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0); gl.clear(gl.COLOR_BUFFER_BIT); gl.drawArrays(gl.TRIANGLES, 0, 6); // execute program 
 <canvas id="cv" width="100" height="100"></canvas> 

我尝试了许多其他技术,参考了规范,尝试在着色器中转换为浮点,并尝试将此处看到的方法组合在一起: 在WebGL2中渲染为16bits无符号整数2D纹理没有成功。

我更喜欢香草js,但是只要输入是Uint16Array ,着色器就可以输出任何格式(浮动等),但可以使用twgl或three.js之类的库。

任何在webgl2方面有更多经验的人都可以向我指出正确的方向,或者在这里提供有效的样本摆弄吗? 我的代码中是否存在一个简单的错误,我是否错过了一个更大的概念,这是否可能? 任何帮助是极大的赞赏!

如果要将16位数据放入纹理中,则需要选择16位纹理内部格式。 查看内部格式列表,您可以选择RGBA

gl.RGBA16I    // 16bit integers
gl.RGBA16UI   // 16bit unsigned integers
gl.RGBA16F    // 16bit half floats

看起来您选择了gl.RGBA16UI

要在着色器中访问该纹理,请在此行

uniform sampler2D tex;

必须改变这个

uniform usampler2D tex;

该语法仅在GLSL 3.00 es中可用,因此您需要在两个着色器的顶部添加#version 300 es

切换到#version 300 es也意味着其他语法更改 attribute变得invaryingout在顶点着色器和in在片段着色器。 gl_FragColor消失了,您必须声明自己的输出,例如out vec4 fooColor; 同样texture2D变成了texture

您不能对整数纹理使用过滤,因此这两行

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_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);

当您从纹理中获取数据时,它将是无符号整数,因此此行

gl_FragColor = texture2D(tex, pixelCoordinate);

最终会变成类似

out vec4 fooColor;  // named this fooColor to make it clear you pick the name

void main() {
  uvec4 unsignedIntValues = texture(tex, pixelCoordinate);
  vec4 floatValues0To65535 = vec4(unsignedIntValues);  
  vec4 colorValues0To1 = floatValues0To65535 / 65535.0;
  fooColor = colorValues0To1;
}

当然,您可以将数学缩短为一行

  fooColor = vec4(texture(tex, pixelCoordinate)) / 65535.0;

例:

 // image data var w = 128; var h = 128; var size = w * h * 4; var img = new Uint16Array(size); // need Uint16Array for (var i = 0; i < img.length; i += 4) { img[i + 0] = 65535; // r img[i + 1] = i/64 * 256; // g img[i + 2] = 0; // b img[i + 3] = 65535; // a } // program var canvas = document.getElementById('cv'); var gl = canvas.getContext('webgl2'); var program = gl.createProgram(); //var color_buffer_float_16ui = gl.getExtension('EXT_color_buffer_float'); // add for 16-bit // texture var tex = gl.createTexture(); // create empty texture gl.bindTexture(gl.TEXTURE_2D, tex); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); gl.texImage2D( gl.TEXTURE_2D, // target 0, // mip level gl.RGBA16UI, // internal format -> gl.RGBA16UI w, h, // width and height 0, // border gl.RGBA_INTEGER, //format -> gm.RGBA_INTEGER gl.UNSIGNED_SHORT, // type -> gl.UNSIGNED_SHORT img // texture data ); // buffer var buffer = gl.createBuffer(); var bufferData = new Float32Array([ -1, -1, 1, -1, 1, 1, 1, 1, -1, 1, -1, -1 ]); gl.bindBuffer(gl.ARRAY_BUFFER, buffer); gl.bufferData(gl.ARRAY_BUFFER, bufferData, gl.STATIC_DRAW); // shaders program.vs = gl.createShader(gl.VERTEX_SHADER); gl.shaderSource(program.vs, `#version 300 es in vec4 vertex; // incoming pixel input? out vec2 pixelCoordinate; // variable used to pass position to fragment shader void main(){ gl_Position = vertex; // set pixel output position to incoming position (pass through) pixelCoordinate = vertex.xy*0.5+0.5; // set coordinate for fragment shader } `); program.fs = gl.createShader(gl.FRAGMENT_SHADER); gl.shaderSource(program.fs, `#version 300 es precision highp float; // ? uniform highp usampler2D tex; // ? in vec2 pixelCoordinate; // receive pixel position from vertex shader out vec4 fooColor; void main() { uvec4 unsignedIntValues = texture(tex, pixelCoordinate); vec4 floatValues0To65535 = vec4(unsignedIntValues); vec4 colorValues0To1 = floatValues0To65535 / 65535.0; fooColor = colorValues0To1; } `); gl.compileShader(program.vs); checkCompileError(program.vs); gl.compileShader(program.fs); checkCompileError(program.fs); function checkCompileError(s) { if (!gl.getShaderParameter(s, gl.COMPILE_STATUS)) { console.error(gl.getShaderInfoLog(s)); } } gl.attachShader(program,program.vs); gl.attachShader(program,program.fs); gl.deleteShader(program.vs); gl.deleteShader(program.fs); // program gl.bindAttribLocation(program, 0, "vertex"); gl.linkProgram(program); gl.useProgram(program); gl.enableVertexAttribArray(0); gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0); gl.clear(gl.COLOR_BUFFER_BIT); gl.drawArrays(gl.TRIANGLES, 0, 6); // execute program 
 <canvas id="cv" width="100" height="100"></canvas> 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM