javascript – WebGL iOS渲染到浮点纹理

前端之家收集整理的这篇文章主要介绍了javascript – WebGL iOS渲染到浮点纹理前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在尝试渲染到iOS Safari上的WebGL中的浮点纹理(不是在本机应用程序中).我已经设法让iOS手动(例如从 JavaScript)读取创建的浮点纹理,但是当我创建浮点类型的帧缓冲并使用GPU渲染到它时,它不起作用.

我已经将问题隔离到渲染到浮点纹理的代码,然后将其传递给另一个要显示的着色器.以下是应用于多维数据集的结果:

纹理渲染绘制绿色正方形,纹理的一半大小,然后应用于立方体的每一侧.

只要绿色方块呈现的纹理类型是标准的无符号字节类型,这在桌面和iOS WebGL上都可以正常工作.但是,将类型更改为浮点会导致iOS设备上的渲染纹理失败(同时继续在桌面浏览器上工作).纹理是空的,就好像没有渲染任何东西一样.

我在这里创建了一个示例项目来演示该问题:https://github.com/felixpalmer/render-2-texture

使用THREE.Renderer.precision设置更改着色器的精度并没有什么区别

解决方法

据我所知,iOS设备不支持渲染浮点纹理(此时此时大多数移动设备也不支持)

我对WebGL规范的理解是

OES_texture_float:允许您创建和读取32位浮点纹理,但渲染到浮点是依赖于设备的.

OES_texture_float_linear:允许线性滤镜浮点纹理.如果这不存在且OES_texture_float那么你只能使用gl.NEAREST来表示浮点纹理.

除半浮点纹理外,OES_texture_half_float和OES_texture_half_float_linear与上面相同.

假设存在OES_texture_float,在WebGL中渲染到浮点纹理的传统方法是创建帧缓冲区,为其附加浮点纹理,然后调用gl.checkFramebufferStatus.如果它返回gl.FRAMEBUFFER_COMPLETE那么你可以,如果不是那么你就不能.注意:无论下一段如何,此方法都应该有效.

规范已更新,因此您还可以检查WebGL扩展,以确定是否可以渲染到浮点纹理.扩展WEBGL_color_buffer_float应该告诉你可以渲染到浮点纹理.半浮点纹理的扩展名EXT_color_buffer_half_float是相同的.我知道没有实际显示这些扩展的浏览器,但如果硬件支持它们,它们支持浮点渲染.

例如我在Chrome 41上的2012 Retina MBP报告

  1. gl = document.createElement("canvas").getContext("webgl").getSupportedExtensions()
  2. ["ANGLE_instanced_arrays","EXT_blend_minmax","EXT_frag_depth","EXT_shader_texture_lod","EXT_sRGB","EXT_texture_filter_anisotropic","WEBKIT_EXT_texture_filter_anisotropic","OES_element_index_uint","OES_standard_derivatives","OES_texture_float","OES_texture_float_linear","OES_texture_half_float","OES_texture_half_float_linear","OES_vertex_array_object","WEBGL_compressed_texture_s3tc","WEBKIT_WEBGL_compressed_texture_s3tc","WEBGL_debug_renderer_info","WEBGL_debug_shaders","WEBGL_depth_texture","WEBKIT_WEBGL_depth_texture","WEBGL_lose_context","WEBKIT_WEBGL_lose_context"]

Firefox 36报道

  1. gl = document.createElement("canvas").getContext("webgl").getSupportedExtensions().join("\n")
  2. "ANGLE_instanced_arrays
  3. EXT_blend_minmax
  4. EXT_frag_depth
  5. EXT_sRGB
  6. EXT_texture_filter_anisotropic
  7. OES_element_index_uint
  8. OES_standard_derivatives
  9. OES_texture_float
  10. OES_texture_float_linear
  11. OES_texture_half_float
  12. OES_texture_half_float_linear
  13. OES_vertex_array_object
  14. WEBGL_compressed_texture_s3tc
  15. WEBGL_depth_texture
  16. WEBGL_draw_buffers
  17. WEBGL_lose_context
  18. MOZ_WEBGL_lose_context
  19. MOZ_WEBGL_compressed_texture_s3tc
  20. MOZ_WEBGL_depth_texture"

浏览器供应商正在忙于实现WebGL 2.0,并且在gl.checkFramebufferStatus方法工作的情况下,没有压力花时间显示其他扩展字符串.

显然有些iOS设备支持EXT_color_buffer_half_float,因此您可以尝试创建半浮动纹理,将其附加到帧缓冲区并检查其状态,然后查看是否有效.

这是检查支持的示例.我在我的iPadAir2和我的iPhone5s上运行它

  1. can make floating point textures
  2. can linear filter floating point textures
  3. can make half floating point textures
  4. can linear filter floating point textures
  5. can **NOT** render to FLOAT texture
  6. successfully rendered to HALF_FLOAT_OES texture

这正是我们的预期.

  1. "use strict";
  2.  
  3. function log(msg) {
  4. var div = document.createElement("div");
  5. div.appendChild(document.createTextNode(msg));
  6. document.body.appendChild(div);
  7. }
  8.  
  9. function glEnum(gl,v) {
  10. for (var key in gl) {
  11. if (gl[key] === v) {
  12. return key;
  13. }
  14. }
  15. return "0x" + v.toString(16);
  16. }
  17.  
  18. window.onload = function() {
  19. // Get A WebGL context
  20. var canvas = document.getElementById("c");
  21. var gl = canvas.getContext("webgl");
  22. if (!gl) {
  23. return;
  24. }
  25. function getExt(name,msg) {
  26. var ext = gl.getExtension(name);
  27. log((ext ? "can " : "can **NOT** ") + msg);
  28. return ext;
  29. }
  30. var testFloat = getExt("OES_texture_float","make floating point textures");
  31. getExt("OES_texture_float_linear","linear filter floating point textures");
  32. var testHalfFloat = getExt("OES_texture_half_float","make half floating point textures");
  33. getExt("OES_texture_half_float_linear","linear filter half floating point textures");
  34. gl.HALF_FLOAT_OES = 0x8D61;
  35. // setup GLSL program
  36. var program = webglUtils.createProgramFromScripts(gl,["2d-vertex-shader","2d-fragment-shader"]);
  37. gl.useProgram(program);
  38.  
  39. // look up where the vertex data needs to go.
  40. var positionLocation = gl.getAttribLocation(program,"a_position");
  41. var colorLoc = gl.getUniformLocation(program,"u_color");
  42.  
  43. // provide texture coordinates for the rectangle.
  44. var positionBuffer = gl.createBuffer();
  45. gl.bindBuffer(gl.ARRAY_BUFFER,positionBuffer);
  46. gl.bufferData(gl.ARRAY_BUFFER,new Float32Array([
  47. -1.0,-1.0,1.0,1.0]),gl.STATIC_DRAW);
  48. gl.enableVertexAttribArray(positionLocation);
  49. gl.vertexAttribPointer(positionLocation,2,gl.FLOAT,false,0);
  50. var whiteTex = gl.createTexture();
  51. gl.bindTexture(gl.TEXTURE_2D,whiteTex);
  52. gl.texImage2D(gl.TEXTURE_2D,gl.RGBA,1,gl.UNSIGNED_BYTE,new Uint8Array([255,255,255]));
  53. function test(format) {
  54. var tex = gl.createTexture();
  55. gl.bindTexture(gl.TEXTURE_2D,tex);
  56. gl.texImage2D(gl.TEXTURE_2D,format,null);
  57. gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.NEAREST);
  58. gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MAG_FILTER,gl.NEAREST);
  59. var fb = gl.createFramebuffer();
  60. gl.bindFramebuffer(gl.FRAMEBUFFER,fb);
  61. gl.framebufferTexture2D(gl.FRAMEBUFFER,gl.COLOR_ATTACHMENT0,gl.TEXTURE_2D,tex,0);
  62. var status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
  63. if (status !== gl.FRAMEBUFFER_COMPLETE) {
  64. log("can **NOT** render to " + glEnum(gl,format) + " texture");
  65. return;
  66. }
  67. // Draw the rectangle.
  68. gl.bindTexture(gl.TEXTURE_2D,whiteTex);
  69. gl.uniform4fv(colorLoc,[0,10,20,1]);
  70. gl.drawArrays(gl.TRIANGLES,6);
  71. gl.bindTexture(gl.TEXTURE_2D,tex);
  72. gl.bindFramebuffer(gl.FRAMEBUFFER,null);
  73. gl.clearColor(1,1);
  74. gl.clear(gl.COLOR_BUFFER_BIT);
  75. gl.uniform4fv(colorLoc,1/10,1/20,6);
  76. var pixel = new Uint8Array(4);
  77. gl.readPixels(0,pixel);
  78. if (pixel[0] !== 0 ||
  79. pixel[1] < 248 ||
  80. pixel[2] < 248 ||
  81. pixel[3] < 254) {
  82. log("FAIL!!!: Was not able to actually render to " + glEnum(gl,format) + " texture");
  83. } else {
  84. log("succesfully rendered to " + glEnum(gl,format) + " texture");
  85. }
  86. }
  87. if (testFloat) {
  88. test(gl.FLOAT);
  89. }
  90. if (testHalfFloat) {
  91. test(gl.HALF_FLOAT_OES);
  92. }
  93. }
  1. canvas {
  2. border: 1px solid black;
  3. }
  1. <script src="//webglfundamentals.org/webgl/resources/webgl-utils.js"></script>
  2. <canvas id="c" width="16" height="16"></canvas>
  3. <!-- vertex shader -->
  4. <script id="2d-vertex-shader" type="x-shader/x-vertex">
  5. attribute vec4 a_position;
  6.  
  7. void main() {
  8. gl_Position = a_position;
  9. }
  10. </script>
  11. <!-- fragment shader -->
  12. <script id="2d-fragment-shader" type="x-shader/x-fragment">
  13. precision mediump float;
  14. uniform vec4 u_color;
  15. uniform sampler2D u_texture;
  16.  
  17. void main() {
  18. gl_FragColor = texture2D(u_texture,vec2(0.5,0.5)) * u_color;
  19. }
  20. </script>

猜你在找的JavaScript相关文章