0

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

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

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

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

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

GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_FLOAT

但似乎 WebGL 唯一被接受的组合DEPTH_ATTACHEMENT

gl.DEPTH_COMPONENT16, gl.DEPTH_COMPONENT, gl.UNSIGNED_SHORT

我试过了gl.FLOATgl.HALF_FLOATtexImage2D拒绝了另一种类型gl.UNSIGNED_SHORT

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

2.问题:纹理不可渲染

我可以毫无错误地绘制此纹理,但是,当将纹理绑定到我samplerCubeShadow的 .

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_MODEWebGL 中不存在 ......也许这是在 WebGL 中工作所缺少的?

4

1 回答 1

0

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

1. 使用 texStorage2D 而不是 texImage2D with null

虽然对数据的调用texImage2D适用NULL于 OpenGL,但似乎 WebGL 更喜欢调用texStorage2Dwithgl.DEPTH_COMPONENT16

我替换了这个:

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 的。这很棘手,因为如果您通过枚举,WebGL 不会出错gl.COMPARE_R_TO_TEXTURE

所以,我改变了:

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);

现在,一切正常!

于 2017-09-29T16:20:14.090 回答