渲染深度到纹理& samplerCubeShadow WebGL 2.0

时间:2017-09-29 15:10:45

标签: webgl render-to-texture webgl2

我正在尝试使用OpenGL阴影映射代码将samplerCubeShadow调整为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.FLOATgl.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);

然而,WebGL中不存在DEPTH_TEXTURE_MODE ...也许这是在WebGL中工作的缺失?

1 个答案:

答案 0 :(得分:0)

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

1。使用texStorage2D而不是texImage2D with null

虽然texImage2DNULL数据的调用与OpenGL有效,但似乎WebGL更喜欢使用texStorage2D调用gl.DEPTH_COMPONENT16

Il取代了这个:

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 enum!

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

现在,一切正常!