fragmentShader = glsl(`precision highp float;
precision highp sampler3D;
uniform sampler3D dataTexture;
in vec3 vOrigin;
in vec3 vDirection;
out vec4 frag_color;
vec2 intersectAABB(vec3 rayOrigin, vec3 rayDir, vec3 boxMin, vec3 boxMax) {
vec3 tMin = (boxMin - rayOrigin) / rayDir;
vec3 tMax = (boxMax - rayOrigin) / rayDir;
vec3 t1 = min(tMin, tMax);
vec3 t2 = max(tMin, tMax);
float tNear = max(max(t1.x, t1.y), t1.z);
float tFar = min(min(t2.x, t2.y), t2.z);
return vec2(tNear, tFar);
}
float sampleData(vec3 coord) {
coord.y = 1.0 - coord.y;
return textureLod(dataTexture, coord, 0.0).x;
}
vec4 maximumIntensity(vec4 color, vec3 entryPoint, vec3 rayDir, float samples, float tStart, float tEnd, float tIncr) {
float density = 0.0;
vec3 maxP = vec3(0.0);
for (float i = 0.0; i < samples; i += 1.0) {
float t = tStart + tIncr * i;
vec3 p = entryPoint + rayDir * t;
float value = sampleData(p);
if (value > density) {
density = value;
maxP = p;
}
if (density >= 1.0 || t > tEnd) {
break;
}
}
density *= 2.0;
if (density < ${topLimit}) density = 0.0;
color.rgb = vec3(1.0 - pow(density, ${grayScale.toFixed(2)}));
color.a = pow(density, ${grayScale.toFixed(2)});
return color;
}
void main() {
vec4 color = vec4(0.0);
vec3 rayDir = normalize(vDirection);
vec3 aabbmin = vec3(-0.5);
vec3 aabbmax = vec3(0.5);
vec2 intersection = intersectAABB(vOrigin, rayDir, aabbmin, aabbmax);
float samplingRate = 1.0;
if (intersection.x <= intersection.y) {
intersection.x = max(intersection.x, 0.0); // Clamp if camera is inside box.
vec3 entryPoint = vOrigin + rayDir * intersection.x;
vec3 exitPoint = vOrigin + rayDir * intersection.y;
// Entry Exit Align Corner sampling as described in
// Volume Raycasting Sampling Revisited by Steneteg et al. 2019
vec3 dimensions = vec3(textureSize(dataTexture, 0));
vec3 ray = exitPoint - entryPoint;
float samples = ceil(samplingRate * length(ray * (dimensions - vec3(1.0))));
float tEnd = length(ray);
float tIncr = tEnd / samples;
float tStart = 0.5 * tIncr;
vec3 texEntry = (entryPoint - aabbmin) / (aabbmax - aabbmin);
color = maximumIntensity(color, texEntry, rayDir, samples, tStart, tEnd, tIncr);
}
frag_color = color;
}`)