diff options
author | Miikka Heikkinen <miikka.heikkinen@digia.com> | 2014-09-09 11:30:15 +0300 |
---|---|---|
committer | Miikka Heikkinen <miikka.heikkinen@digia.com> | 2014-09-10 12:30:54 +0300 |
commit | ddb9be979d93b7e17f1067dc6056de54d9828b29 (patch) | |
tree | df612c56e4a804481297ae55b29f0ee379c5f8ab /src/datavisualization/engine/shaders | |
parent | bb30ea555c71604de9a2bc5096fa35c9532b26bd (diff) |
Limit volume to axis ranges
The volume object that would go partially outside axis ranges
is scale and repositioned so that it only renders the portion
that is inside the axis ranges.
Change-Id: I792494e437998ba6276f58fab645767276c1476d
Reviewed-by: Mika Salmela <mika.salmela@digia.com>
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; |