レイキャスティング+シェーディング

本物のページはこちら→shading

Included page "raycasting:shading" does not exist (create it now)

注意事項は

  • フラグメントシェーダ内で法線を計算する
  • 光のベクトルもフラグメントシェーダ内
  • 視線ベクトルもフラグメントシェーダ内

なぜなら、レイキャスティング方では、フラグメントシェーダの中ではじめて本当の位置がわかるから。

レンダリングプリミティブ

glutSolidCube(1.0);

頂点シェーダ

varying vec3 v_lightvec;
varying vec3 v_cam_local;//オブジェクト中心から見た時のカメラの座標・位置
varying vec3 uvw;//0.0-1.0に正規化された3Dテクスチャ座標
//uniform float uMaxPtSize;//ウィンドウサイズによりけり。
void main(){
    gl_ClipVertex=gl_ModelViewMatrix*gl_Vertex;
    gl_Position =gl_ProjectionMatrix * gl_ClipVertex;
    v_lightvec=normalize(gl_LightSource[0].position.xyz - gl_ClipVertex);
    uvw=(gl_Vertex.xyz+0.5);
    v_cam_local=vec4(gl_ModelViewMatrixInverse*vec4(0.0,0.0,0.0,1.0)).xyz;
    v_cam_local+=0.5;
 
}

フラグメントシェーダ

//Bling-Phong shading
vec3 shading(vec3 _normal,vec3 _viewvec,vec3 _lightpos){
 
    float diffuse_intensity=max(dot(_lightpos,_normal),0);//光源の拡散反射強度
    vec3 diffuse=gl_FrontLightProduct[0].diffuse*diffuse_intensity;
 
    if(diffuse_intensity<=0){//もし光の方向ベクトル・法線の内積が0以下だったら鏡面反射は発生しない。
        return gl_FrontLightProduct[0].ambient+diffuse;
    }else{//光の方向ベクトル・法線の内積が0より大きい場合だけ鏡面反射が発生する
        vec3 reflection = normalize(_lightpos-_viewvec);
        float specular_intensity=pow(max(dot(reflection,_normal),0.3),gl_FrontMaterial.shininess);
        vec3 specular=gl_FrontLightProduct[0].specular*specular_intensity;
        return gl_FrontLightProduct[0].ambient+diffuse+specular;
    }
}
#define DELTA (0.01)
#define THRESHOLD (0.25)
// フラグメントシェーダ
uniform sampler3D voltexture;
varying vec3 uvw;//0.0-1.0に正規化された3Dテクスチャ座標
vec3 volExtentMin=vec3(0,0,0);
vec3 volExtentMax=vec3(1.0,1.0,1.0);
//光関係
varying vec3 v_lightvec;
varying vec3 v_cam_local;
 
void main() {  
    vec4 dst=vec4(0,0,0,0);
    int samplenum=800;
    vec3 direction=normalize(uvw-v_cam_local)*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;
        vec4 src=texture3D(voltexture,uvw);
        //src.a=src.x;//なんとなくうまくいかないからこうした。
        scalar=src.x;//GL_LUMINANCEで渡すとxに強度が入る
        if(scalar<THRESHOLD){
            src=vec4(0.0,0.0,0.0,0.0);
        }else{
            vec3 sample1,sample2;
            sample1.x=texture3D(voltexture,uvw-vec3(DELTA,0.0,0.0)).x;
            sample2.x=texture3D(voltexture,uvw+vec3(DELTA,0.0,0.0)).x;
            sample1.y=texture3D(voltexture,uvw-vec3(0.0,DELTA,0.0)).x;
            sample2.y=texture3D(voltexture,uvw+vec3(0.0,DELTA,0.0)).x;
            sample1.z=texture3D(voltexture,uvw-vec3(0.0,0.0,DELTA)).x;
            sample2.z=texture3D(voltexture,uvw+vec3(0.0,0.0,DELTA)).x;
            vec3 normal = normalize(sample2-sample1);
            normal=normalize(gl_NormalMatrix*normal);//
            float3 lightvec = normalize(gl_LightSource[0].position.xyz  - uvw);
            float3 viewvec = normalize(v_cam_local - uvw);
 
            src=vec4(shading(normal,viewvec,lightvec),scalar);
        }
        //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;
 
        uvw=uvw+direction;//1/110 レイに沿って進める
        vec3 temp1=sign(uvw-volExtentMin);
        vec3 temp2=sign(volExtentMax-uvw);
        float inside=dot(temp1,temp2);
        if(inside<3.0)
            break;
    }
    gl_FragColor =dst;  
 
}

サポートサイト Wikidot.com