内部卷

时间:2015-05-14 11:11:26

标签: glsl webgl shader raytracing volume-rendering

我们一直在尝试在WebGL中渲染3D云场。到目前为止我们采用的方法是here - 每条光线的起始位置是体积立方体正面的当前位置,结束位置是从前一个通道计算的,该通道编码xyx vales作为背面纹理。

当相机在卷内时,我们如何将其扩展?我们是否需要动态创建体积较小的立方体?我们可以只更改着色器以开始从相机而不是正面行进,并投影到立方体的背面吗?

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

提前致谢

1 个答案:

答案 0 :(得分: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)
  4. 在着色器中执行:

    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...
    }
    

    快乐的编码!