summaryrefslogtreecommitdiffstats
path: root/src/datavisualization/engine/shaders
diff options
context:
space:
mode:
authorMiikka Heikkinen <miikka.heikkinen@digia.com>2014-08-13 15:09:36 +0300
committerMiikka Heikkinen <miikka.heikkinen@digia.com>2014-08-18 09:11:30 +0300
commit169a4d638c6c1b6634ffcfd19c4fe3cb94cf27d5 (patch)
tree454810f2e9cc418bae9f1c6716c51c3fae38a968 /src/datavisualization/engine/shaders
parentbe7bdaa8930caf15fcc58a480d223e0c2b8af6ed (diff)
Implement volume rendering support
New subclass of QCustom3DItem, QCustom3DVolume is provided. The documentation for the example will be done in a separate commit. Change-Id: Idb3fdb0654c6bec7606ca012b75852a5a8412397 Reviewed-by: Tomi Korpipää <tomi.korpipaa@digia.com>
Diffstat (limited to 'src/datavisualization/engine/shaders')
-rw-r--r--src/datavisualization/engine/shaders/default.frag1
-rw-r--r--src/datavisualization/engine/shaders/texture3d.frag70
-rw-r--r--src/datavisualization/engine/shaders/texture3d.vert12
-rw-r--r--src/datavisualization/engine/shaders/texture3dslice.frag119
4 files changed, 202 insertions, 0 deletions
diff --git a/src/datavisualization/engine/shaders/default.frag b/src/datavisualization/engine/shaders/default.frag
index c03b1054..0276ed95 100644
--- a/src/datavisualization/engine/shaders/default.frag
+++ b/src/datavisualization/engine/shaders/default.frag
@@ -33,5 +33,6 @@ void main() {
materialDiffuseColor * lightStrength * pow(cosTheta, 2) / distance +
materialSpecularColor * lightStrength * pow(cosAlpha, 5) / distance;
gl_FragColor.a = color_mdl.a;
+ gl_FragColor = clamp(gl_FragColor, 0.0, 1.0);
}
diff --git a/src/datavisualization/engine/shaders/texture3d.frag b/src/datavisualization/engine/shaders/texture3d.frag
new file mode 100644
index 00000000..054b59cb
--- /dev/null
+++ b/src/datavisualization/engine/shaders/texture3d.frag
@@ -0,0 +1,70 @@
+#version 120
+
+varying highp vec3 pos;
+
+uniform highp sampler3D textureSampler;
+uniform highp vec3 cameraPositionRelativeToModel;
+uniform highp vec4 colorIndex[256];
+uniform highp int color8Bit;
+
+const float maxDist = sqrt(2.0);
+const int sampleCount = 1024;
+const float alphaThreshold = 0.001;
+void main() {
+ // Raytrace into volume, need to sample pixels along the eye ray until we hit opacity 1
+
+ // Find out where ray intersects the object
+ highp vec3 rayDir = -(cameraPositionRelativeToModel - pos);
+ highp vec3 invRayDir = 1.0 / rayDir;
+ highp vec3 minCorner = vec3(-1.0);
+ highp vec3 maxCorner = vec3(1.0);
+ highp vec3 t1 = invRayDir * (minCorner - pos);
+ highp vec3 t2 = invRayDir * (maxCorner - pos);
+ highp vec3 tmin = min(t1, t2);
+ highp vec3 tmax = max(t1, t2);
+ highp vec2 t = max(tmin.xx, tmin.yz);
+ t = min(tmax.xx, tmax.yz);
+ float tFar = min(t.x, t.y);
+ highp vec3 rayStart = pos;
+ // Flip Y and Z so QImage bits work directly for texture and first image is in the front
+ rayStart.yz = -rayStart.yz;
+ highp vec3 rayStop = pos + rayDir * tFar;
+ rayStop.yz = -rayStop.yz;
+
+ // Convert intersections to texture coords
+ rayStart = 0.5 * (rayStart + 1.0);
+ rayStop = 0.5 * (rayStop + 1.0);
+
+ highp vec3 curPos = rayStart;
+ highp float fullDist = distance(rayStop, rayStart);
+ highp float stepSize = maxDist / float(sampleCount); // TODO: Stepsize needs to be improved
+ highp vec3 step = normalize(rayStop - rayStart) * stepSize;
+ highp float totalDist = 0.0;
+ highp float totalAlpha = 0.0;
+ highp vec4 destColor = vec4(0, 0, 0, 0);
+ highp vec4 curColor = vec4(0, 0, 0, 0);
+ highp vec3 curRgb = vec3(0, 0, 0);
+ highp float curAlpha = 0.0;
+
+ for (int i = 0; i < sampleCount; i++) {
+ curColor = texture3D(textureSampler, curPos);
+ if (color8Bit != 0)
+ curColor = colorIndex[int(curColor.r * 255.0)];
+
+ curAlpha = curColor.a;
+ if (curAlpha > alphaThreshold) {
+ curRgb = curColor.rgb * curAlpha * (1.0 - totalAlpha);
+ destColor.rgb += curRgb;
+ totalAlpha += curAlpha;
+ }
+ curPos += step;
+ totalDist += stepSize;
+ if (totalDist > fullDist || totalAlpha >= 1.0) {
+ break;
+ }
+ }
+
+ destColor.a = totalAlpha;
+ gl_FragColor = clamp(destColor, 0.0, 1.0);
+}
+
diff --git a/src/datavisualization/engine/shaders/texture3d.vert b/src/datavisualization/engine/shaders/texture3d.vert
new file mode 100644
index 00000000..cad1ce06
--- /dev/null
+++ b/src/datavisualization/engine/shaders/texture3d.vert
@@ -0,0 +1,12 @@
+uniform highp mat4 MVP;
+
+attribute highp vec3 vertexPosition_mdl;
+attribute highp vec2 vertexUV;
+attribute highp vec3 vertexNormal_mdl;
+
+varying highp vec3 pos;
+
+void main() {
+ gl_Position = MVP * vec4(vertexPosition_mdl, 1.0);
+ pos = vertexPosition_mdl;
+}
diff --git a/src/datavisualization/engine/shaders/texture3dslice.frag b/src/datavisualization/engine/shaders/texture3dslice.frag
new file mode 100644
index 00000000..641b32a5
--- /dev/null
+++ b/src/datavisualization/engine/shaders/texture3dslice.frag
@@ -0,0 +1,119 @@
+#version 120
+
+varying highp vec3 pos;
+
+uniform highp sampler3D textureSampler;
+uniform highp vec3 cameraPositionRelativeToModel;
+uniform highp vec3 volumeSliceIndices;
+uniform highp vec4 colorIndex[256];
+uniform highp int color8Bit;
+
+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);
+
+const float alphaThreshold = 0.001;
+void main() {
+ // Raytrace into volume, need to sample pixels along the eye ray until we hit opacity 1
+
+ // Find out where ray intersects the slice planes
+ highp vec3 rayDir = -(cameraPositionRelativeToModel - pos);
+ highp vec3 rayStart = pos;
+ // Flip Y and Z so QImage bits work directly for texture and first image is in the front
+ rayStart.yz = -rayStart.yz;
+ rayDir.yz = -rayDir.yz;
+ highp vec3 invRayDir = 1.0 / rayDir;
+ highp vec3 minCorner = vec3(-1.0);
+ highp vec3 maxCorner = vec3(1.0);
+ highp vec3 t1 = invRayDir * (minCorner - rayStart);
+ highp vec3 t2 = invRayDir * (maxCorner - rayStart);
+ highp vec3 tmin = min(t1, t2);
+ highp vec3 tmax = max(t1, t2);
+ highp vec2 t = max(tmin.xx, tmin.yz);
+ t = min(tmax.xx, tmax.yz);
+ float tFar = min(t.x, t.y);
+
+ 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 = tFar + 1.0;
+ highp float secondD = firstD;
+ highp float thirdD = firstD;
+ if (volumeSliceIndices.x >= -1.0) {
+ highp float dx = dot(xPoint - rayStart, xPlaneNormal) / dot(rayDir, xPlaneNormal);
+ if (dx >= 0.0 && dx <= tFar)
+ firstD = min(dx, firstD);
+ }
+ if (volumeSliceIndices.y >= -1.0) {
+ highp float dy = dot(yPoint - rayStart, yPlaneNormal) / dot(rayDir, yPlaneNormal);
+ if (dy >= 0.0 && dy <= tFar) {
+ if (dy < firstD) {
+ secondD = firstD;
+ firstD = dy;
+ } else {
+ secondD = dy;
+ }
+ }
+ }
+ if (volumeSliceIndices.z >= -1.0) {
+ highp float dz = dot(zPoint - rayStart, zPlaneNormal) / dot(rayDir, zPlaneNormal);
+ if (dz >= 0.0) {
+ if (dz < firstD && dz <= tFar) {
+ 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 float totalAlpha = 0.0;
+ highp vec3 curRgb = vec3(0, 0, 0);
+
+ // Convert intersection to texture coords
+
+ if (firstD <= tFar) {
+ highp vec3 firstTex = rayStart + rayDir * firstD;
+ firstTex = 0.5 * (firstTex + 1.0);
+ highp vec4 firstColor = texture3D(textureSampler, firstTex);
+ if (color8Bit != 0)
+ firstColor = colorIndex[int(firstColor.r * 255.0)];
+
+ if (firstColor.a > alphaThreshold) {
+ destColor.rgb = firstColor.rgb * firstColor.a;
+ totalAlpha = firstColor.a;
+ }
+ if (secondD <= tFar && totalAlpha < 1.0) {
+ highp vec3 secondTex = rayStart + rayDir * secondD;
+ secondTex = 0.5 * (secondTex + 1.0);
+ highp vec4 secondColor = texture3D(textureSampler, secondTex);
+ if (color8Bit != 0)
+ secondColor = colorIndex[int(secondColor.r * 255.0)];
+ if (secondColor.a > alphaThreshold) {
+ curRgb = secondColor.rgb * secondColor.a * (1.0 - totalAlpha);
+ destColor.rgb += curRgb;
+ totalAlpha += secondColor.a;
+ }
+ if (thirdD <= tFar && totalAlpha < 1.0) {
+ highp vec3 thirdTex = rayStart + rayDir * thirdD;
+ thirdTex = 0.5 * (thirdTex + 1.0);
+ highp vec4 thirdColor = texture3D(textureSampler, thirdTex);
+ if (color8Bit != 0)
+ thirdColor = colorIndex[int(thirdColor.r * 255.0)];
+ if (thirdColor.a > alphaThreshold) {
+ curRgb = thirdColor.rgb * thirdColor.a * (1.0 - totalAlpha);
+ destColor.rgb += curRgb;
+ totalAlpha += thirdColor.a;
+ }
+ }
+ }
+ }
+ destColor.a = totalAlpha;
+ gl_FragColor = clamp(destColor, 0.0, 1.0);
+}
+