我正在尝试使用OpenGL阴影映射代码将samplerCubeShadow调整为WebGL,并且我极其系统地陷入死胡同,因为有效的数据格式和存储在第一个和第二个之间明显不同。
我知道我可以使用除sampler*Shadow
之外的其他采样器实现阴影映射,并以其他方式渲染到纹理中,但是,如果可能的话,我希望以与在OpenGL中相同的方式实现。
我的问题是找到(如果它存在!)格式,内部格式以及WebGL / GLSL对samplerCubeShadow采样器所期望的良好组合......
在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中唯一可接受的深度纹理格式吗?
我可以毫无错误地绘制这个纹理,然而,当将纹理绑定到我的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中工作的缺失?
答案 0 :(得分:0)
我最终找到了解决方案......至少有一个错误。
虽然texImage2D
对NULL
数据的调用与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);
目前,WebGL的良好枚举实际上是COMPARE_ REF _TO_TEXTURE,枚举GL_COMPARE_ R _TO_TEXTURE是特定于OpenGL的。这很棘手,因为如果你传递gl.COMPARE_R_TO_TEXTURE
enum!
所以,我改变了:
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);
现在,一切正常!