【问题标题】:Volume rendering from inside volume从内部体积进行体积渲染
【发布时间】:2015-07-25 23:36:31
【问题描述】:

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

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

我们真的不知道从哪里开始!

提前致谢

【问题讨论】:

    标签: glsl webgl shader raytracing volume-rendering


    【解决方案1】:

    只渲染一次。

    在该通道中,您仅渲染背面。摄像机位置需要从世界坐标转换成一个坐标系,该坐标系由 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) 框的体积。

    创建该体积盒矩阵的逆矩阵,并将 cam 作为 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...
    }
    

    编码愉快!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多