#version 120 varying highp vec3 pos; varying highp vec3 rayDir; uniform highp sampler3D textureSampler; uniform highp vec3 volumeSliceIndices; uniform highp vec4 colorIndex[256]; uniform highp int color8Bit; uniform highp float alphaMultiplier; uniform highp int preserveOpacity; uniform highp vec3 minBounds; uniform highp vec3 maxBounds; const highp vec3 xPlaneNormal = vec3(1.0, 0, 0); const highp vec3 yPlaneNormal = vec3(0, 1.0, 0); const highp vec3 zPlaneNormal = vec3(0, 0, 1.0); void main() { // Find out where ray intersects the slice planes vec3 normRayDir = normalize(rayDir); highp vec3 rayStart = pos; highp float minT = 2.0; if (normRayDir.x != 0.0 && normRayDir.y != 0.0 && normRayDir.z != 0.0) { highp vec3 boxBounds = vec3(1.0, 1.0, 1.0); highp vec3 invRayDir = 1.0 / normRayDir; if (normRayDir.x < 0) boxBounds.x = -1.0; if (normRayDir.y < 0) boxBounds.y = -1.0; if (normRayDir.z < 0) boxBounds.z = -1.0; highp vec3 t = (boxBounds - rayStart) * invRayDir; minT = min(t.x, min(t.y, t.z)); } highp vec3 xPoint = vec3(volumeSliceIndices.x, 0, 0); highp vec3 yPoint = vec3(0, volumeSliceIndices.y, 0); highp vec3 zPoint = vec3(0, 0, volumeSliceIndices.z); highp float firstD = minT + 1.0; highp float secondD = firstD; highp float thirdD = firstD; if (volumeSliceIndices.x >= -1.0) { highp float dx = dot(xPoint - rayStart, xPlaneNormal) / dot(normRayDir, xPlaneNormal); if (dx >= 0.0 && dx <= minT) firstD = min(dx, firstD); } if (volumeSliceIndices.y >= -1.0) { highp float dy = dot(yPoint - rayStart, yPlaneNormal) / dot(normRayDir, yPlaneNormal); if (dy >= 0.0 && dy <= minT) { if (dy < firstD) { secondD = firstD; firstD = dy; } else { secondD = dy; } } } if (volumeSliceIndices.z >= -1.0) { highp float dz = dot(zPoint - rayStart, zPlaneNormal) / dot(normRayDir, zPlaneNormal); if (dz >= 0.0) { if (dz < firstD && dz <= minT) { thirdD = secondD; secondD = firstD; firstD = dz; } else if (dz < secondD){ thirdD = secondD; secondD = dz; } else { thirdD = dz; } } } highp vec4 destColor = vec4(0.0, 0.0, 0.0, 0.0); highp vec4 curColor = vec4(0.0, 0.0, 0.0, 0.0); highp float totalAlpha = 0.0; highp vec3 curRgb = vec3(0, 0, 0); highp float curAlpha = 0.0; // Convert intersection to texture coords if (firstD <= minT) { highp vec3 texelVec = rayStart + normRayDir * firstD; if (clamp(texelVec.x, minBounds.x, maxBounds.x) == texelVec.x && clamp(texelVec.y, maxBounds.y, minBounds.y) == texelVec.y && clamp(texelVec.z, maxBounds.z, minBounds.z) == texelVec.z) { texelVec = 0.5 * (texelVec + 1.0); curColor = texture3D(textureSampler, texelVec); if (color8Bit != 0) curColor = colorIndex[int(curColor.r * 255.0)]; if (curColor.a > 0.0) { curAlpha = curColor.a; if (curColor.a == 1.0 && preserveOpacity != 0) curAlpha = 1.0; else curAlpha = clamp(curColor.a * alphaMultiplier, 0.0, 1.0); destColor.rgb = curColor.rgb * curAlpha; totalAlpha = curAlpha; } } if (secondD <= minT && totalAlpha < 1.0) { texelVec = rayStart + normRayDir * secondD; if (clamp(texelVec.x, minBounds.x, maxBounds.x) == texelVec.x && clamp(texelVec.y, maxBounds.y, minBounds.y) == texelVec.y && clamp(texelVec.z, maxBounds.z, minBounds.z) == texelVec.z) { texelVec = 0.5 * (texelVec + 1.0); curColor = texture3D(textureSampler, texelVec); if (color8Bit != 0) curColor = colorIndex[int(curColor.r * 255.0)]; if (curColor.a > 0.0) { if (curColor.a == 1.0 && preserveOpacity != 0) curAlpha = 1.0; else curAlpha = clamp(curColor.a * alphaMultiplier, 0.0, 1.0); curRgb = curColor.rgb * curAlpha * (1.0 - totalAlpha); destColor.rgb += curRgb; totalAlpha += curAlpha; } } if (thirdD <= minT && totalAlpha < 1.0) { texelVec = rayStart + normRayDir * thirdD; if (clamp(texelVec.x, minBounds.x, maxBounds.x) == texelVec.x && clamp(texelVec.y, maxBounds.y, minBounds.y) == texelVec.y && clamp(texelVec.z, maxBounds.z, minBounds.z) == texelVec.z) { texelVec = 0.5 * (texelVec + 1.0); curColor = texture3D(textureSampler, texelVec); if (curColor.a > 0.0) { if (color8Bit != 0) curColor = colorIndex[int(curColor.r * 255.0)]; if (curColor.a == 1.0 && preserveOpacity != 0) curAlpha = 1.0; else curAlpha = clamp(curColor.a * alphaMultiplier, 0.0, 1.0); curRgb = curColor.rgb * curAlpha * (1.0 - totalAlpha); destColor.rgb += curRgb; totalAlpha += curAlpha; } } } } } if (totalAlpha == 0.0) discard; // Brighten up the final color if there is some transparency left if (totalAlpha > 0.0 && totalAlpha < 1.0) destColor *= 1.0 / totalAlpha; destColor.a = totalAlpha; gl_FragColor = clamp(destColor, 0.0, 1.0); }