我有来自threejs示例[http://threejs.org/examples/#webgl_animation_cloth]的代码示例,其中浮点值转换为vec4。我在其他几个论坛上看到了这个逻辑,但没有解释。
我也见过这个链接Packing float into vec4 - how does this code work?
它说vec4最终将存储在32位RGBA8缓冲区中 由于我们将深度值传递给颜色缓冲区,opengl将如何知道如何处理?
此外,由于vec4有4个组件,每个4个字节使其为16个字节,使其为16 * 8位,这如何适合32位RGBA8?
vec4 pack_depth( const in float depth ) {
const vec4 bit_shift = vec4( 256.0 * 256.0 * 256.0, 256.0 *
256.0,256.0,1.0);
const vec4 bit_mask = vec4( 0.0, 1.0 / 256.0, 1.0 / 256.0, 1.0 /
256.0);
vec4 res = fract( depth * bit_shift );
res -= res.xxyz * bit_mask;
return res;
}
void main() {
vec4 pixel = texture2D( texture, vUV );
if ( pixel.a < 0.5 ) discard;
gl_FragData[ 0 ] = pack_depth( gl_FragCoord.z );
}
答案 0 :(得分:2)
除了@ WaclawJasper的答案之外,这段代码将浮点值(32位)打包成4个8位值。
gl_FragData[ 0 ]
在纹理中呈现单个像素,在这种情况下是每个通道8位(总共32位)的纹理。如果我写
gl_FragData[0] = vec4(0.25, 0.5, 0.75, 1.0);
正在写入的纹理(假设它是一个8位纹理)实际上会得到值
r = Math.floor(0.25 * 255) = 63;
g = Math.floor(0.5 * 255) = 127;
b = Math.floor(0.75 * 255) = 191;
a = Math.floor(1.0 * 255) = 255;
规范中的实际公式实际上是
unsignedIntValue = floor(clamp(floatValue, 0., 1.) * (pow(2., numberOfBits) - 1.));
因此即使pack_depth
返回一个vec4,它是浮点数,gl_FragData
被定义为vec4
,它最终会在写入当前正在写入的WebGL时被转换(画布,a renderbuffer,纹理)。
如果写入浮点纹理pack_depth
则不必要。由于pack_depth
正在做什么,我们可以推断它是否写入8位RGBA纹理。
为什么这需要呢?因为在WebGL中支持浮点纹理是可选的。因此,如果用户的机器不支持浮点纹理,并且您需要浮点数据(如阴影贴图的深度缓冲区),那么将数据打包成8位纹理就是一种解决方案。
答案 1 :(得分:1)
256是8位数据可以表示的不同值的数量。让我们停止二进制工作一秒钟,然后使用熟悉的十进制数。如果我们有2个频道,每个频道只能存储1个数字(0-9),我们如何打包45个?显然,我们将5个打包成一个数字,将40/10或4打包成另一个数字。然后在我们的解包函数中我们反过来:4 * 10 + 5 = 45. 256与我们的十进制示例中的10类似。
Opengl没有,但你自己的应用程序代码可以理解它。
我不确定我是否正确理解这部分内容。但是你所显示的代码是将一个浮点数打包成8 * 4位RGBA。