diff options
Diffstat (limited to 'src/datavisualization/engine/shaders')
4 files changed, 135 insertions, 116 deletions
diff --git a/src/datavisualization/engine/shaders/texture3d.frag b/src/datavisualization/engine/shaders/texture3d.frag index 460cbcc6..3f9c42ff 100644 --- a/src/datavisualization/engine/shaders/texture3d.frag +++ b/src/datavisualization/engine/shaders/texture3d.frag @@ -1,15 +1,17 @@ #version 120 varying highp vec3 pos; +varying highp vec3 rayDir; uniform highp sampler3D textureSampler; -uniform highp vec3 cameraPositionRelativeToModel; uniform highp vec4 colorIndex[256]; uniform highp int color8Bit; uniform highp vec3 textureDimensions; uniform highp int sampleCount; // This is the maximum sample count uniform highp float alphaMultiplier; uniform highp int preserveOpacity; +uniform highp vec3 minBounds; +uniform highp vec3 maxBounds; // Ray traveling straight through a single 'alpha thickness' applies 100% of the encountered alpha. // Rays traveling shorter distances apply a fraction. This is used to normalize the alpha over @@ -17,51 +19,38 @@ uniform highp int preserveOpacity; const highp float alphaThicknesses = 32.0; void main() { - highp vec3 rayDir = -(cameraPositionRelativeToModel - pos); vec3 rayStart = pos; - // Flip Y and Z so QImage bits work directly for texture and first image is in the front - rayDir.yz = -rayDir.yz; - rayStart.yz = -rayStart.yz; - // Calculate ray intersection endpoint - vec3 rayStop; - if (rayDir.x == 0.0) { - rayStop.yz = rayStart.yz; - rayStop.x = -rayStart.x; - } else if (rayDir.y == 0.0) { - rayStop.xz = rayStart.xz; - rayStop.y = -rayStart.y; - } else if (rayDir.z == 0.0) { - rayStop.xy = rayStart.xy; - rayStop.z = -rayStart.z; - } else { - highp vec3 boxBounds = vec3(1.0, 1.0, 1.0); - highp vec3 invRayDir = 1.0 / rayDir; - if (rayDir.x < 0) - boxBounds.x = -1.0; - if (rayDir.y < 0) - boxBounds.y = -1.0; - if (rayDir.z < 0) - boxBounds.z = -1.0; - highp vec3 t = (boxBounds - rayStart) * invRayDir; - highp float minT = min(t.x, min(t.y, t.z)); - rayStop = rayStart + minT * rayDir; + highp vec3 startBounds = minBounds; + highp vec3 endBounds = maxBounds; + if (rayDir.x < 0.0) { + startBounds.x = maxBounds.x; + endBounds.x = minBounds.x; + } + if (rayDir.y > 0.0) { + startBounds.y = maxBounds.y; + endBounds.y = minBounds.y; + } + if (rayDir.z > 0.0) { + startBounds.z = maxBounds.z; + endBounds.z = minBounds.z; } + // Calculate ray intersection endpoint + highp vec3 rayStop; + highp vec3 invRayDir = 1.0 / rayDir; + highp vec3 t = (endBounds - rayStart) * invRayDir; + highp float endT = min(t.x, min(t.y, t.z)); + rayStop = rayStart + endT * rayDir; + if (endT <= 0.0) + discard; + // Convert intersections to texture coords rayStart = 0.5 * (rayStart + 1.0); rayStop = 0.5 * (rayStop + 1.0); highp vec3 ray = rayStop - rayStart; - // Avoid artifacts from divisions by zero - if (ray.x == 0) - ray.x = 0.000000001; - if (ray.y == 0) - ray.y = 0.000000001; - if (ray.z == 0) - ray.z = 0.000000001; - highp vec3 absRay = abs(ray); highp vec3 invAbsRay = 1.0 / absRay; highp float fullDist = length(ray); @@ -154,6 +143,9 @@ void main() { break; } + if (totalOpacity == 1.0) + discard; + // Brighten up the final color if there is some transparency left if (totalOpacity >= 0.0 && totalOpacity < 1.0) destColor *= (1.0 - (totalOpacity * 0.5)) / (1.0 - totalOpacity); diff --git a/src/datavisualization/engine/shaders/texture3d.vert b/src/datavisualization/engine/shaders/texture3d.vert index cad1ce06..ef3f1b25 100644 --- a/src/datavisualization/engine/shaders/texture3d.vert +++ b/src/datavisualization/engine/shaders/texture3d.vert @@ -1,12 +1,36 @@ uniform highp mat4 MVP; +uniform highp vec3 minBounds; +uniform highp vec3 maxBounds; +uniform highp vec3 cameraPositionRelativeToModel; attribute highp vec3 vertexPosition_mdl; attribute highp vec2 vertexUV; attribute highp vec3 vertexNormal_mdl; varying highp vec3 pos; +varying highp vec3 rayDir; void main() { gl_Position = MVP * vec4(vertexPosition_mdl, 1.0); - pos = vertexPosition_mdl; + + highp vec3 minBoundsNorm = minBounds; + highp vec3 maxBoundsNorm = maxBounds; + + // Y and Z are flipped in bounds to be directly usable in texture calculations, + // so flip them back to normal for position calculations + minBoundsNorm.yz = -minBoundsNorm.yz; + maxBoundsNorm.yz = -maxBoundsNorm.yz; + + minBoundsNorm = 0.5 * (minBoundsNorm + 1.0); + maxBoundsNorm = 0.5 * (maxBoundsNorm + 1.0); + + pos = vertexPosition_mdl + + ((1.0 - vertexPosition_mdl) * minBoundsNorm) + - ((1.0 + vertexPosition_mdl) * (1.0 - maxBoundsNorm)); + + rayDir = -(cameraPositionRelativeToModel - pos); + + // Flip Y and Z so QImage bits work directly for texture and first image is in the front + rayDir.yz = -rayDir.yz; + pos.yz = -pos.yz; } diff --git a/src/datavisualization/engine/shaders/texture3dlowdef.frag b/src/datavisualization/engine/shaders/texture3dlowdef.frag index 72b959fc..ed0d41ce 100644 --- a/src/datavisualization/engine/shaders/texture3dlowdef.frag +++ b/src/datavisualization/engine/shaders/texture3dlowdef.frag @@ -1,15 +1,17 @@ #version 120 varying highp vec3 pos; +varying highp vec3 rayDir; uniform highp sampler3D textureSampler; -uniform highp vec3 cameraPositionRelativeToModel; uniform highp vec4 colorIndex[256]; uniform highp int color8Bit; uniform highp vec3 textureDimensions; uniform highp int sampleCount; // This is the maximum sample count uniform highp float alphaMultiplier; uniform highp int preserveOpacity; +uniform highp vec3 minBounds; +uniform highp vec3 maxBounds; // Ray traveling straight through a single 'alpha thickness' applies 100% of the encountered alpha. // Rays traveling shorter distances apply a fraction. This is used to normalize the alpha over @@ -18,36 +20,30 @@ const highp float alphaThicknesses = 32.0; const highp float SQRT3 = 1.73205081; void main() { - highp vec3 rayDir = -(cameraPositionRelativeToModel - pos); vec3 rayStart = pos; - // Flip Y and Z so QImage bits work directly for texture and first image is in the front - rayDir.yz = -rayDir.yz; - rayStart.yz = -rayStart.yz; + highp vec3 startBounds = minBounds; + highp vec3 endBounds = maxBounds; + if (rayDir.x < 0.0) { + startBounds.x = maxBounds.x; + endBounds.x = minBounds.x; + } + if (rayDir.y > 0.0) { + startBounds.y = maxBounds.y; + endBounds.y = minBounds.y; + } + if (rayDir.z > 0.0) { + startBounds.z = maxBounds.z; + endBounds.z = minBounds.z; + } // Calculate ray intersection endpoint - vec3 rayStop; - if (rayDir.x == 0.0) { - rayStop.yz = rayStart.yz; - rayStop.x = -rayStart.x; - } else if (rayDir.y == 0.0) { - rayStop.xz = rayStart.xz; - rayStop.y = -rayStart.y; - } else if (rayDir.z == 0.0) { - rayStop.xy = rayStart.xy; - rayStop.z = -rayStart.z; - } else { - highp vec3 boxBounds = vec3(1.0, 1.0, 1.0); - highp vec3 invRayDir = 1.0 / rayDir; - if (rayDir.x < 0) - boxBounds.x = -1.0; - if (rayDir.y < 0) - boxBounds.y = -1.0; - if (rayDir.z < 0) - boxBounds.z = -1.0; - highp vec3 t = (boxBounds - rayStart) * invRayDir; - highp float minT = min(t.x, min(t.y, t.z)); - rayStop = rayStart + minT * rayDir; - } + highp vec3 rayStop; + highp vec3 invRayDir = 1.0 / rayDir; + highp vec3 t = (endBounds - rayStart) * invRayDir; + highp float endT = min(t.x, min(t.y, t.z)); + if (endT <= 0.0) + discard; + rayStop = rayStart + endT * rayDir; // Convert intersections to texture coords rayStart = 0.5 * (rayStart + 1.0); @@ -55,15 +51,6 @@ void main() { highp vec3 ray = rayStop - rayStart; - // Avoid artifacts from divisions by zero - if (ray.x == 0) - ray.x = 0.000000001; - if (ray.y == 0) - ray.y = 0.000000001; - if (ray.z == 0) - ray.z = 0.000000001; - - highp float fullDist = length(ray); highp float stepSize = SQRT3 / sampleCount; highp vec3 step = (SQRT3 * normalize(ray)) / sampleCount; @@ -110,6 +97,9 @@ void main() { break; } + if (totalOpacity == 1.0) + discard; + // Brighten up the final color if there is some transparency left if (totalOpacity >= 0.0 && totalOpacity < 1.0) destColor *= (1.0 - (totalOpacity * 0.5)) / (1.0 - totalOpacity); diff --git a/src/datavisualization/engine/shaders/texture3dslice.frag b/src/datavisualization/engine/shaders/texture3dslice.frag index 00584744..c555af98 100644 --- a/src/datavisualization/engine/shaders/texture3dslice.frag +++ b/src/datavisualization/engine/shaders/texture3dslice.frag @@ -1,14 +1,16 @@ #version 120 varying highp vec3 pos; +varying highp vec3 rayDir; uniform highp sampler3D textureSampler; -uniform highp vec3 cameraPositionRelativeToModel; 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); @@ -16,21 +18,17 @@ const highp vec3 zPlaneNormal = vec3(0, 0, 1.0); void main() { // Find out where ray intersects the slice planes - highp vec3 rayDir = -(cameraPositionRelativeToModel - pos); - rayDir = normalize(rayDir); + vec3 normRayDir = normalize(rayDir); 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 float minT = 2.0f; - if (rayDir.x != 0.0 && rayDir.y != 0.0 && rayDir.z != 0.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 / rayDir; - if (rayDir.x < 0) + highp vec3 invRayDir = 1.0 / normRayDir; + if (normRayDir.x < 0) boxBounds.x = -1.0; - if (rayDir.y < 0) + if (normRayDir.y < 0) boxBounds.y = -1.0; - if (rayDir.z < 0) + if (normRayDir.z < 0) boxBounds.z = -1.0; highp vec3 t = (boxBounds - rayStart) * invRayDir; minT = min(t.x, min(t.y, t.z)); @@ -43,12 +41,12 @@ void main() { highp float secondD = firstD; highp float thirdD = firstD; if (volumeSliceIndices.x >= -1.0) { - highp float dx = dot(xPoint - rayStart, xPlaneNormal) / dot(rayDir, xPlaneNormal); + 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(rayDir, yPlaneNormal); + highp float dy = dot(yPoint - rayStart, yPlaneNormal) / dot(normRayDir, yPlaneNormal); if (dy >= 0.0 && dy <= minT) { if (dy < firstD) { secondD = firstD; @@ -59,7 +57,7 @@ void main() { } } if (volumeSliceIndices.z >= -1.0) { - highp float dz = dot(zPoint - rayStart, zPlaneNormal) / dot(rayDir, zPlaneNormal); + highp float dz = dot(zPoint - rayStart, zPlaneNormal) / dot(normRayDir, zPlaneNormal); if (dz >= 0.0) { if (dz < firstD && dz <= minT) { thirdD = secondD; @@ -83,43 +81,35 @@ void main() { // Convert intersection to texture coords if (firstD <= minT) { - highp vec3 firstTex = rayStart + rayDir * firstD; - firstTex = 0.5 * (firstTex + 1.0); - curColor = texture3D(textureSampler, firstTex); - 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) { - highp vec3 secondTex = rayStart + rayDir * secondD; - secondTex = 0.5 * (secondTex + 1.0); - curColor = texture3D(textureSampler, secondTex); + 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); - curRgb = curColor.rgb * curAlpha * (1.0 - totalAlpha); - destColor.rgb += curRgb; - totalAlpha += curAlpha; + destColor.rgb = curColor.rgb * curAlpha; + totalAlpha = curAlpha; } - if (thirdD <= minT && totalAlpha < 1.0) { - highp vec3 thirdTex = rayStart + rayDir * thirdD; - thirdTex = 0.5 * (thirdTex + 1.0); - curColor = texture3D(textureSampler, thirdTex); + } + 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 (color8Bit != 0) - curColor = colorIndex[int(curColor.r * 255.0)]; if (curColor.a == 1.0 && preserveOpacity != 0) curAlpha = 1.0; else @@ -129,9 +119,32 @@ void main() { 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; |