我有一系列纹理堆叠在一起(使用mip-map风格的分辨率金字塔)以达到最终图像。
由于它们的堆叠方式,当它们没有被有意义的图像数据填充时,有必要将它们初始化为无符号的 int 值 128。 IE, 128 为零,因为渲染着色器将从每个纹理值中减去 .5,这允许后续金字塔层通过正值或负值偏移最终图像。
我似乎无法弄清楚如何将(单通道GL_LUMINANCE)纹理初始化为值!
我尝试将其设置为渲染缓冲区目标并向其渲染多边形,但 FBO 似乎被标记为不完整。 我还尝试将其作为渲染缓冲区目标并使用gl.clear(gl。COLOR_BUFFER_BIT)但它再次被认为是不完整的。
显而易见的事情是使用 gl.texSubImage2D() 复制值,但这似乎真的很慢...... 也许这是唯一的方法? 我希望有更优雅的东西,不需要分配这么多内存(至少是一帧的单个值)和如此慢(因为当所有数据都是单个值时,必须将所有数据写入缓冲区)。
在WebGL中将纹理设置为(默认)值的唯一方法似乎是调整其大小或分配它,将其设置为全零。
此外,似乎没有像gl这样的复制模式。SIGNED_BYTE允许零为零(IE,有符号值进来)...但这也不能解决将纹理初始化为单个值(在本例中为零)的问题。
有什么想法吗? 如何将 WebGL 纹理初始化为一个值,而不仅仅是将值复制到其中?
WebGL所基于的OpenGL ES 2.0规范并不能保证能够渲染到特定类型的纹理。判断它是否有效的唯一方法是创建纹理,将其附加到帧缓冲区,然后调用 checkFramebufferStatus 并查看它是否返回FRAMEBUFFER_COMPLETE。不幸的是,在很多情况下它不会。
仅保证 3 种组合关闭附件有效
- COLOR_ATTACHMENT0 = RGBA/UNSIGNED_BYTE纹理
- COLOR_ATTACHMENT0 = RGBA/UNSIGNED_BYTE纹理 + DEPTH_ATTACHMENT = 渲染缓冲区DEPTH_COMPONENT16
- COLOR_ATTACHMENT0 = RGBA/UNSIGNED_BYTE纹理 + DEPTH_STENCIL_ATTACHMENT = DEPTH_STENCIL渲染缓冲区
所以你的选择是
使用 RGBA 纹理并在 FBO 中渲染 128,128,128,???(或 gl.clear it)
使用亮度纹理并调用texImage2D
- 使用亮度纹理并使用后台缓冲区或清除为所需颜色的正确大小的 fbo 调用 copyTexImage2D(尽管不能保证这是快速的 AFAIK)
根据我的经验(主要是OSX中的Chrome),使用Canvas初始化纹理的速度很快。 我猜这是因为浏览器分配了 Canvas 并在 GPU 上绘制了它,并且它的 WebGL 实现使用与 Canvas 相同的 GL 上下文,因此没有大量的 CPU 到 GPU 内存传输。
// Quickly init texture to (128,128,128)
var canvas = this._canvas = document.createElement("canvas");
canvas.width = wTex;
canvas.height = hTex;
var ctx = this._ctx = canvas.getContext("2d");
ctx.fillStyle = "#808080";
ctx.fillRect(0, 0, wTex, hTex);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, canvas);