簡體   English   中英

WebGL iOS渲染到浮點紋理

[英]WebGL iOS render to floating point texture

我正在嘗試渲染到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_floatOES_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報告

gl = document.createElement("canvas").getContext("webgl").getSupportedExtensions()
["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報道

gl = document.createElement("canvas").getContext("webgl").getSupportedExtensions().join("\n")
"ANGLE_instanced_arrays
EXT_blend_minmax
EXT_frag_depth
EXT_sRGB
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
WEBGL_depth_texture
WEBGL_draw_buffers
WEBGL_lose_context
MOZ_WEBGL_lose_context
MOZ_WEBGL_compressed_texture_s3tc
MOZ_WEBGL_depth_texture"

瀏覽器供應商正在忙於實現WebGL 2.0,並且在gl.checkFramebufferStatus方法工作的情況下,沒有時間花費時間使其他擴展字符串出現。

顯然有些iOS設備支持EXT_color_buffer_half_float因此您可以嘗試創建半浮動紋理,將其附加到幀緩沖區並檢查其狀態,然后查看是否有效。

這是檢查支持的示例。 我在我的iPadAir2和我的iPhone5s上運行它

can make floating point textures
can linear filter floating point textures
can make half floating point textures
can linear filter floating point textures
can **NOT** render to FLOAT texture
successfully rendered to HALF_FLOAT_OES texture

這正是我們的預期。

 "use strict"; function log(msg) { var div = document.createElement("div"); div.appendChild(document.createTextNode(msg)); document.body.appendChild(div); } function glEnum(gl, v) { for (var key in gl) { if (gl[key] === v) { return key; } } return "0x" + v.toString(16); } window.onload = function() { // Get A WebGL context var canvas = document.getElementById("c"); var gl = canvas.getContext("webgl"); if (!gl) { return; } function getExt(name, msg) { var ext = gl.getExtension(name); log((ext ? "can " : "can **NOT** ") + msg); return ext; } var testFloat = getExt("OES_texture_float", "make floating point textures"); getExt("OES_texture_float_linear", "linear filter floating point textures"); var testHalfFloat = getExt("OES_texture_half_float", "make half floating point textures"); getExt("OES_texture_half_float_linear", "linear filter half floating point textures"); gl.HALF_FLOAT_OES = 0x8D61; // setup GLSL program var program = webglUtils.createProgramFromScripts(gl, ["2d-vertex-shader", "2d-fragment-shader"]); gl.useProgram(program); // look up where the vertex data needs to go. var positionLocation = gl.getAttribLocation(program, "a_position"); var colorLoc = gl.getUniformLocation(program, "u_color"); // provide texture coordinates for the rectangle. var positionBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0]), gl.STATIC_DRAW); gl.enableVertexAttribArray(positionLocation); gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0); var whiteTex = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, whiteTex); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array([255, 255, 255, 255])); function test(format) { var tex = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, tex); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, format, null); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); var fb = gl.createFramebuffer(); gl.bindFramebuffer(gl.FRAMEBUFFER, fb); gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0); var status = gl.checkFramebufferStatus(gl.FRAMEBUFFER); if (status !== gl.FRAMEBUFFER_COMPLETE) { log("can **NOT** render to " + glEnum(gl, format) + " texture"); return; } // Draw the rectangle. gl.bindTexture(gl.TEXTURE_2D, whiteTex); gl.uniform4fv(colorLoc, [0, 10, 20, 1]); gl.drawArrays(gl.TRIANGLES, 0, 6); gl.bindTexture(gl.TEXTURE_2D, tex); gl.bindFramebuffer(gl.FRAMEBUFFER, null); gl.clearColor(1, 0, 0, 1); gl.clear(gl.COLOR_BUFFER_BIT); gl.uniform4fv(colorLoc, [0, 1/10, 1/20, 1]); gl.drawArrays(gl.TRIANGLES, 0, 6); var pixel = new Uint8Array(4); gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel); if (pixel[0] !== 0 || pixel[1] < 248 || pixel[2] < 248 || pixel[3] < 254) { log("FAIL!!!: Was not able to actually render to " + glEnum(gl, format) + " texture"); } else { log("succesfully rendered to " + glEnum(gl, format) + " texture"); } } if (testFloat) { test(gl.FLOAT); } if (testHalfFloat) { test(gl.HALF_FLOAT_OES); } } 
 canvas { border: 1px solid black; } 
 <script src="//webglfundamentals.org/webgl/resources/webgl-utils.js"></script> <canvas id="c" width="16" height="16"></canvas> <!-- vertex shader --> <script id="2d-vertex-shader" type="x-shader/x-vertex"> attribute vec4 a_position; void main() { gl_Position = a_position; } </script> <!-- fragment shader --> <script id="2d-fragment-shader" type="x-shader/x-fragment"> precision mediump float; uniform vec4 u_color; uniform sampler2D u_texture; void main() { gl_FragColor = texture2D(u_texture, vec2(0.5, 0.5)) * u_color; } </script> 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM