1、頂點著色器代碼
#version 110
/* GLSL 1.10需要顯式聲明精度 (OpenGL ES要求) */
#ifdef GL_ES
precision highp float;
#endif
// 體數據采樣步長
uniform float xStepSize,yStepSize,zStepSize;
// 體數據紋理和顏色紋理
uniform sampler3D baseTexture;
uniform sampler1D tfTexture;
// 體數據包圍盒邊界
uniform vec3 minBound,maxBound;
varying vec3 vDirection;//模型空間下的光線方向
varying vec3 vCameraModelPosition;//模型空間下的相機位置
void main(void)
{// 計算裁剪空間的位置gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;vec4 cameraPos = (gl_ModelViewMatrixInverse * vec4(0, 0, 0, 1));vCameraModelPosition = cameraPos.xyz/cameraPos.w;vDirection = gl_Vertex.xyz/gl_Vertex.w- vCameraModelPosition;}
2、片元著色器代碼
#version 110
/* GLSL 1.10需要顯式聲明精度 (OpenGL ES要求) */
#ifdef GL_ES
precision highp float;
precision highp sampler3D;
precision highp sampler1D;
#endif
#define EPSILON 1e-3// 體數據紋理和顏色紋理
uniform sampler3D baseTexture;
uniform sampler1D tfTexture;uniform int steps;//采樣步長,值越大,采樣次數越多,效果越小,但性能越差
uniform float densityFactor;//值越大,顏色變化劇烈,細節邊界變得銳利,可能出現不平滑的鋸齒狀過渡;值越小,顏色變化緩慢,疊加的顏色較多,導致整體視覺上更加柔和、模糊,增強了霧氣感
// 體數據包圍盒邊界
uniform vec3 minBound,maxBound;varying vec3 vDirection;//模型空間下的光線方向
varying vec3 vCameraModelPosition;//模型空間下的相機位置const int maxSamples = 256;
vec2 hitBox(vec3 orig, vec3 dir) {vec3 inv_dir = 1.0 / dir;// 光線方向倒數(處理正負方向)vec3 tmin_tmp = (minBound - orig) * inv_dir;// 沿光線方向到達包圍盒各軸最小邊界的距離vec3 tmax_tmp = (maxBound - orig) * inv_dir; // 沿光線方向到達包圍盒各軸最大邊界的距離vec3 tmin = min(tmin_tmp, tmax_tmp);// 各軸向的最近交點vec3 tmax = max(tmin_tmp, tmax_tmp);// 各軸向的最遠交點float near = max(max(tmin.x, max(tmin.y, tmin.z)),0.0);// 光線最終進入包圍盒的距離float far = min(tmax.x, min( tmax.y, tmax.z)); // 光線最終離開包圍盒的距離return vec2( near, far );
}void main(void)
{vec3 rayDir = normalize(vDirection);vec2 bounds = hitBox( vCameraModelPosition, rayDir );bounds.x -= 0.000001;if ( bounds.x >= bounds.y) discard;//光線與包圍盒無交點。vec3 sampleStart = vCameraModelPosition + bounds.x * rayDir;// 初始化顏色累積vec4 finalColor = vec4(0.0);const float opacityThreshold = 0.99; // 不透明度閾值float T = 1.0;// 光線步進采樣float delta = sqrt(3.0) / float(steps); // 均勻步長vec3 voxelSizeInv = 1.0 / (maxBound - minBound); for (float t = bounds.x; t < bounds.y; t += delta) {sampleStart = vCameraModelPosition + t * rayDir;vec3 texCoord = (sampleStart - minBound) * voxelSizeInv;float density = texture3D(baseTexture, texCoord).r;vec4 color = texture1D(tfTexture, density);color.rbg = pow(color.rbg, vec3(2.2));//從gamma空間轉換到線性空間color *= densityFactor * delta;finalColor += T*color;T*=1.0-color.a;if (T<0.01) break;}// 丟棄完全透明的片元if (finalColor.a < EPSILON) discard;finalColor.rgb = pow(finalColor.rgb, vec3(1.0/2.2));gl_FragColor = finalColor;}