【问题标题】:Render Depth to texture & samplerCubeShadow WebGL 2.0将深度渲染到纹理和采样器CubeShadow WebGL 2.0
【发布时间】:2018-03-11 12:54:08
【问题描述】:

我正在尝试使用 samplerCubeShadow 使 OpenGL 阴影映射代码适应 WebGL,但由于有效的数据格式和存储在第一个和第二个之间显然不一样,我拼命系统地陷入了死胡同。

我知道我可以使用除sampler*Shadow 之外的其他采样器并通过以其他方式渲染到纹理来实现阴影映射,但是,如果可能的话,我希望实现与我在 OpenGL 中相同的方式。

我的问题是找到(如果存在的话!)格式、内部格式以及 WebGL/GLSL 对 samplerCubeShadow 采样器的期望的良好组合......

1。问题:目标深度纹理格式。

在 OpenGL 中,我使用以下格式作为深度纹理:

GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_FLOAT

但对于DEPTH_ATTACHEMENT,WebGL 唯一可接受的组合似乎是

gl.DEPTH_COMPONENT16, gl.DEPTH_COMPONENT, gl.UNSIGNED_SHORT

我尝试了gl.FLOAT 和gl.HALF_FLOAT,但texImage2D 拒绝gl.UNSIGNED_SHORT 以外的其他类型。

它是 WebGL 中深度纹理的好格式吗?如果是,那么 WebGL 将深度数据存储在 16 位整数而不是浮点数中,这听起来很奇怪,但不是真正的问题,因为 16 位就是 16 位。它真的是 WebGL 中唯一可接受的深度纹理格式吗?

2。问题:纹理不可渲染

我可以毫无错误地绘制此纹理,但是,当将纹理绑定到我的 samplerCubeShadow 时,WebGL 向我抛出了我一生中从未见过的错误:

texture bound to texture unit # is not renderable. It maybe non-power-of-2 and have incompatible texture filtering.

从这里开始

要么我找到了一个“可渲染”的格式,但它不能用作DEPTH_ATTACHEMENT,或者我找到了一个适合DEPTH_ATTACHEMENT 的格式,它不是“可渲染”的......那么,解决方案是什么?

伪代码:

 gl.bindTexture(gl.TEXTURE_CUBE_MAP, shadow_cube);
 gl.texParameteri(gl.TEXTURE_CUBE_MAP, 0x2800, gl.LINEAR);
 gl.texParameteri(gl.TEXTURE_CUBE_MAP, 0x2800, gl.LINEAR);
 gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
 gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
 gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_R, gl.CLAMP_TO_EDGE);
 gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_COMPARE_MODE, gl.COMPARE_R_TO_TEXTURE);
 gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_COMPARE_FUNC, gl.GREATER);
 for(var c = 0; c < 6; c++) {
    gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X+c, 0, gl.DEPTH_COMPONENT16, 512, 512, 0, gl.DEPTH_COMPONENT, gl.UNSIGNED_SHORT, null);
 }

gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, offscreen_fbo);
gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, null, 0);
for(var c = 0; c < 6; c++) {
   gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.TEXTURE_CUBE_MAP_POSITIVE_X+c, shadow_cube, 0);
   // draw things...
}

gl.activeTexture(gl.TEXTURE#);
gl.bindTexture(gl.TEXTURE_CUBE_MAP, shadow_cube);

编辑:在 OpenGL 代码中,目标深度纹理有一个额外的参数:

glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_DEPTH_TEXTURE_MODE, GL_LUMINANCE);

但是,DEPTH_TEXTURE_MODE 在 WebGL 中不存在...也许这是在 WebGL 中工作所缺少的?

【问题讨论】:

    标签: webgl render-to-texture webgl2


    【解决方案1】:

    我终于找到了解决方案...至少有一个错误。

    1。使用 texStorage2D 而不是带有 null 的 texImage2D

    虽然使用NULL 数据调用texImage2D 可用于OpenGL,但似乎WebGL 更喜欢使用gl.DEPTH_COMPONENT16 调用texStorage2D

    我替换了这个:

    for(var c = 0; c < 6; c++) {
      gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X+c, 0, gl.DEPTH_COMPONENT16, 512, 512, 0, gl.DEPTH_COMPONENT, gl.UNSIGNED_SHORT, null);
     }
    

    通过这个:

    gl.texStorage2D(gl.TEXTURE_CUBE_MAP, 1, gl.DEPTH_COMPONENT16, this._smap_res, this._smap_res);
    

    2。 COMPARE_R_TO_TEXTURE 枚举在 WebGL 中无效

    目前适用于 WebGL 的好的枚举实际上是 COMPARE_REF_TO_TEXTURE,枚举 GL_COMPARE_R_TO_TEXTURE 是特定于 OpenGL 的。这很棘手,因为如果您通过 gl.COMPARE_R_TO_TEXTURE 枚举,WebGL 不会出错!

    所以,我改变了:

    gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_COMPARE_MODE, gl.COMPARE_R_TO_TEXTURE);
    

    收件人:

    gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_COMPARE_MODE, gl.COMPARE_REF_TO_TEXTURE);
    

    现在,一切正常!

    【讨论】:

    • texStorage2D 在texImage2D 工作的事实不仅仅意味着代码做错了其他事情。任何可以用texStorage2D 完成的事情也可以用texImage2D 完成。对于texParameteri,它没有产生错误的原因是因为COMPARE_R_TO_TEXTURE 是undefined。对于数字,undefined 被强制为 0,这与 NONE 相同,这是 TEXTURE_COMPARE_MODE 的有效值
    • 我同意理论上,texStorage2D 是 texImage2D 的一种别名,但在这种情况下,texImage2D 和 gl.DEPTH_COMPONENT16, gl.DEPTH_COMPONENT, gl.UNSIGNED_SHORT 组合在 @987654344 时不起作用@ 只需要 gl.DEPTH_COMPONENT16 格式作为参数,所以 WebGL 用它来做它的内部厨师...... texImage2D 的问题可能是格式组合的问题,但哪个组合是好的组合?这对我来说仍然是一个谜......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多