2

我们一直在做大量工作,试图在 WebGL 中对 3D 云场进行体积渲染。我们到目前为止所采用的方法在这里概述- 每条射线的开始位置是体积立方体正面的当前位置,结束位置是从前一次通过计算的,它将 xyx 值编码为背面质地。

当相机在体积内时,我们如何扩展它来工作?我们是否需要即时创建体积更小的立方体?我们是否可以只更改着色器以从相机而不是正面开始行进,然后投影到立方体的背面?

我们真的不确定从哪里开始!

提前致谢

4

1 回答 1

0

只渲染一次。

在该通道中,您仅渲染背面。摄像机位置需要从世界坐标转换为由 3 个轴及其渲染的体积框大小构建的坐标系。您的目标是创建一个 4x4 矩阵,其中所有列向量都是 vec4(...,0) 并且这些向量的 x,y,z 由 x,y,z 轴方向和体积框的长度定义。如果框平行于 x 轴,则该向量为 (1,0,0)。如果它被拉伸到 (2,0,0),那么它就是它自己的 x 轴,这将是矩阵中第 0 列的列向量。使用 y 和 z 轴及其长度来执行此操作。矩阵中的最后一列向量是框的位置,为 vec4(tx,ty,tz,1),因为该矩阵定义了一个坐标系,您可以使用它将相机位置转换为统一的 (0,0,0 )-(1,1,1) 框的体积。

创建该体积盒矩阵的逆矩阵并将凸轮作为 vec4(campos, 1) 从右侧乘以 invVolMatrix。将生成的 vec3 作为 UNIFORM 发送到着色器。

仅在其各自的 volBox 角上渲染具有 (0,0,0) 到 (1,1,1) 坐标的背面 - 正如您已经做过的那样。现在你的着色器中有

  1. 统一坎波斯
  2. 背面涡坐标
  3. 您知道您的 volbox 是局部坐标系中的单位立方体,对角线从 (0,0,0) 到 (1,1,1)

在着色器中执行:

varying vec3 vLocalUnitTexCoord;   // backface interpolated coordinate
uniform vec3 LOCAL_CAM_POS;        // localised camPos

struct AABB {
    vec3 min; // (0,0,0) 
    vec3 max; // (1,1,1)
};

struct Ray {
    vec3 origin; vec3 dir;
};

float getUnitAABBEntry( in Ray r ) {
   AABB b;
   b.min = vec3( 0 ); 
   b.max = vec3( 1 );

   // compute clipping for box.min and box.max corner
   vec3 rInvDir = vec3( 1.0 ) / r.dir;
   vec3 tMinima = ( b.min - r.origin ) * rInvDir; 
   vec3 tMaxima = ( b.max - r.origin ) * rInvDir;

   // sort for nearest corner
   vec3 tEntries = min( tMinima, tMaxima );

    // find first real entry value of 3 t-distance values in vec3 container
    vec2 tMaxEntryCandidates = max( vec2( tEntries.st ), vec2( tEntries.pp ) ); 
   float tMaxEntry = max( tMaxEntryCandidates.s, tMaxEntryCandidates.t );
}

vec3 getCloserPos( in vec3 camera, in vec3 frontFaceIntersection, in float t ) {
    float useFrontCoord = 0.5 + 0.5 * sign( t );
    vec3 startPos = mix( camera, frontFaceIntersection, useFrontCoord );   
    return startPos;
}

vec4 main(void)
{
    Ray r;
    r.origin = LOCAL_CAM_POS;
    r.dir = normalize( vLocalUnitTexCoord - LOCAL_CAM_POS );

    float t = getUnitAABBEntry( r );
    vec3 frontFaceLocalUnitTexCoord = r.origin + r.dir * t;
    vec3 startPos = getCloserPos( LOCAL_CAM_POS, frontFaceLocalUnitTexCoord, t );

    // loop for integration follows here
    vec3 start = startpos;
    vec3 end = vLocalUnitTexCoord;
    ...for loop..etc...
}

快乐编码!

于 2018-01-15T00:54:39.430 回答