レイキャスティング

raycasting.png
top.jpg

レイキャスティングとは?

raycasting.png

視線とスクリーン上のピクセルを結ぶ線をレイとする。
そのレイに沿って、ボリュームデータをサンプリングして、
データ値を加算して、レンダリングする手法。
1ピクセルごとの計算なので、フラグメントシェーダと相性ばっちりなのである。

関連事項

List of pages tagged with raycasting:

現在のモデルビュー行列からカメラからの位置を取得するには?

手順

  1. volume entry positionを決める立方体と直線の交わる点を見つけるには?
  2. レイの方向を計算する
  3. while(レイの位置がボリューム内にある限りは)
    1. 現在のレイの位置のデータにアクセス
    2. 色と透明度を加算する
    3. レイに沿って位置を進める。
  4. end while
ファイル名ファイルタイプサイズ
20plate-raycasting.pngPNG image data187.94 kBInfo
bonsai.jpgJPEG image data6.14 kBInfo
glass.jpgJPEG image data8.26 kBInfo
plate10-raycasting.pngPNG image data150.03 kBInfo
raycasting.pngPNG image data115.29 kBInfo
stamp.jpgJPEG image data9.19 kBInfo
top.jpgJPEG image data6.14 kBInfo
wall.jpgJPEG image data8.91 kBInfo

頂点シェーダ

varying vec3 v_lightvec;
varying vec3 v_cam;
varying vec3 vpos;//0.0-1.0に正規化された3Dテクスチャ座標
//uniform float uMaxPtSize;//ウィンドウサイズによりけり。
void main(){
    gl_ClipVertex=gl_ModelViewMatrix*gl_Vertex;
    gl_Position =gl_ProjectionMatrix * gl_ClipVertex;
    v_cam =normalize(gl_ClipVertex.xyz/gl_ClipVertex.w);          // 視線ベクトル
    v_lightvec=normalize(gl_LightSource[0].position.xyz - gl_ClipVertex);
    vpos=(gl_Vertex.xyz+1.0)/2.0;
}

フラグメントシェーダ

フルソースコード
raycasting.png
// フラグメントシェーダ
    uniform sampler3D voltexture;
    uniform sampler1D trans_func;
    varying vec3 vpos;//0.0-1.0に正規化された3Dテクスチャ座標
    uniform vec3 camera;
    vec3 volExtentMin=vec3(0,0,0);
    vec3 volExtentMax=vec3(1.0,1.0,1.0);
    void main() {  
        vec4 dst=vec4(0,0,0,0);
        vec3 position=vpos;
        int samplenum=800;
        vec3 direction=normalize(position-camera)*pow(3.0,0.5)/float(samplenum);//111=0.009 10=0.17
        vec4 value;
        float scalar=0;
        for(int i=0;i<samplenum;i++){//64*√3より
            if(dst.a>0.9)break;
            value=texture3D(voltexture,position);
            scalar=value.x;
            ///if(scalar>0.3){
            //vec4 src=vec4(scalar,scalar,scalar,scalar*0.01);
            vec4 src=texture1D(trans_func,scalar);
            //    dst=(1.0-dst.a)*src+dst;
            //}
            //front-to-back
            dst.xyz = (1.0-dst.a) * src.a * src.xyz + dst.xyz;//薄いとこが暗くなるのが嫌。
            dst.a   = (1.0-dst.a)  * src.a   + dst.a;
 
            position=position+direction;//1/110
            vec3 temp1=sign(position-volExtentMin);
            vec3 temp2=sign(volExtentMax-position);
            float inside=dot(temp1,temp2);
            if(inside<3.0)
            break;
        }
          gl_FragColor =dst;  
}

display関数上でやること
立方体を描くのだ。
void DrawVolume(){    
    glUseProgram(gProgram);
    // 透視変換行列の設定
 
    glUniformMatrix4fv(projectionUniform, 1, 0, gProj.m);
    glUniformMatrix4fv(modelviewUniform, 1, 0, gModelView.m);
    glUniform3f(gCamUniLoc,gLocalCoordCam.x,gLocalCoordCam.y,gLocalCoordCam.z);
 
    //glEnable(GL_DEPTH_TEST);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    // Bind the texture
    glActiveTexture ( GL_TEXTURE0 );
    glBindTexture ( GL_TEXTURE_3D, texId[0] );
    glEnable ( GL_TEXTURE_3D );
    glUniform1i ( gTexSamplerLoc, 0);// texId[0]);
    glActiveTexture(GL_TEXTURE1);
    glBindTexture ( GL_TEXTURE_1D, texId[1] );
    glEnable(GL_TEXTURE_1D);
    glUniform1i(gTFTexSamplerLoc, 1);//texId[1]);
    //頂点の設定
    glEnableVertexAttribArray(ATTRIB_VERTEX);
    glDrawArrays(GL_QUADS,0,24);
    glDisable(GL_TEXTURE_1D);
    glDisable(GL_TEXTURE_3D);
    glDisable(GL_BLEND);
    //glDisable(GL_DEPTH_TEST);
    glUseProgram(0);
 
}

レイキャスティングに向いているテクスチャパラメータの設定

    glTexParameteri ( GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
    glTexParameteri ( GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
    glTexParameteri ( GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
    glTexParameteri ( GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
    glTexParameteri ( GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE );

レイキャスティングギャラリー


ray raycast shader

サポートサイト Wikidot.com rayraycastshader