From cac09110d89fb3facf66253a7f87f904aa698030 Mon Sep 17 00:00:00 2001 From: mclarsen Date: Tue, 23 Feb 2021 14:36:58 -0800 Subject: [PATCH] fix rendering depths and divide by zero --- vtkm/rendering/Camera.cxx | 2 +- vtkm/rendering/CanvasRayTracer.cxx | 20 ++++++++++++++++--- vtkm/rendering/LineRenderer.cxx | 18 ++++++++++++++++- .../raytracing/CylinderIntersector.cxx | 2 +- vtkm/rendering/raytracing/QuadIntersector.cxx | 2 +- vtkm/rendering/raytracing/RayOperations.cxx | 2 +- vtkm/rendering/raytracing/RayOperations.h | 8 +++++--- vtkm/rendering/raytracing/RayTracer.cxx | 1 + .../raytracing/SphereIntersector.cxx | 2 +- .../raytracing/TriangleIntersector.cxx | 4 ++-- 10 files changed, 47 insertions(+), 14 deletions(-) diff --git a/vtkm/rendering/Camera.cxx b/vtkm/rendering/Camera.cxx index c1ac84c1c..30d0faedd 100644 --- a/vtkm/rendering/Camera.cxx +++ b/vtkm/rendering/Camera.cxx @@ -286,7 +286,7 @@ void Camera::ResetToBounds(const vtkm::Bounds& dataBounds, vtkm::Float32 diagonalLength = vtkm::Magnitude(totalExtent); this->SetPosition(center + directionOfProjection * diagonalLength * 1.0f); this->SetFieldOfView(60.0f); - this->SetClippingRange(0.1f * diagonalLength, diagonalLength * 10.0f); + this->SetClippingRange(0.1f * diagonalLength, diagonalLength * 5.0f); // Reset for 2D camera this->SetViewRange2D(db); diff --git a/vtkm/rendering/CanvasRayTracer.cxx b/vtkm/rendering/CanvasRayTracer.cxx index ad57f280e..da6a4a0ef 100644 --- a/vtkm/rendering/CanvasRayTracer.cxx +++ b/vtkm/rendering/CanvasRayTracer.cxx @@ -27,11 +27,13 @@ namespace internal class SurfaceConverter : public vtkm::worklet::WorkletMapField { vtkm::Matrix ViewProjMat; + bool Is3d; public: VTKM_CONT - SurfaceConverter(const vtkm::Matrix viewProjMat) + SurfaceConverter(const vtkm::Matrix viewProjMat, bool is3d) : ViewProjMat(viewProjMat) + , Is3d(is3d) { } @@ -51,7 +53,18 @@ public: ColorBufferPortalType& colorBuffer, const vtkm::Id& index) const { - vtkm::Vec intersection = origin + inDepth * dir; + vtkm::Vec intersection; + // For reasons I can't explain atm, the view direction + // is different for for 2d and 3d so that it matches the + // gl depth buffer values for annotations + if (Is3d) + { + intersection = origin + inDepth * dir; + } + else + { + intersection = origin + inDepth * (-dir); + } vtkm::Vec4f_32 point; point[0] = static_cast(intersection[0]); point[1] = static_cast(intersection[1]); @@ -105,7 +118,8 @@ VTKM_CONT void WriteToCanvas(const vtkm::rendering::raytracing::Ray& vtkm::MatrixMultiply(camera.CreateProjectionMatrix(canvas->GetWidth(), canvas->GetHeight()), camera.CreateViewMatrix()); - vtkm::worklet::DispatcherMapField(SurfaceConverter(viewProjMat)) + bool is3d = camera.GetMode() == vtkm::rendering::Camera::MODE_3D; + vtkm::worklet::DispatcherMapField(SurfaceConverter(viewProjMat, is3d)) .Invoke(rays.PixelIdx, colors, rays.Distance, diff --git a/vtkm/rendering/LineRenderer.cxx b/vtkm/rendering/LineRenderer.cxx index 1660319f8..3914c151c 100644 --- a/vtkm/rendering/LineRenderer.cxx +++ b/vtkm/rendering/LineRenderer.cxx @@ -55,6 +55,11 @@ void LineRenderer::RenderLine(const vtkm::Vec3f_64& point0, vtkm::Id dx = vtkm::Abs(x1 - x0), sx = x0 < x1 ? 1 : -1; vtkm::Id dy = -vtkm::Abs(y1 - y0), sy = y0 < y1 ? 1 : -1; vtkm::Id err = dx + dy, err2 = 0; + + const vtkm::Id xStart = x0; + const vtkm::Id yStart = y0; + const vtkm::Float32 pdist = vtkm::Sqrt(vtkm::Float32(dx * dx) + vtkm::Float32(dy * dy)); + auto colorPortal = vtkm::rendering::Canvas::ColorBufferType(Canvas->GetColorBuffer()).WritePortal(); auto depthPortal = @@ -63,9 +68,19 @@ void LineRenderer::RenderLine(const vtkm::Vec3f_64& point0, while (x0 >= 0 && x0 < Canvas->GetWidth() && y0 >= 0 && y0 < Canvas->GetHeight()) { - vtkm::Float32 t = (dx == 0) ? 1.0f : (static_cast(x0) - p0[0]) / (p1[0] - p0[0]); + vtkm::Float32 deltaX = static_cast(x0 - xStart); + vtkm::Float32 deltaY = static_cast(y0 - yStart); + // Depth is wrong, but its far less wrong that it used to be. + // These depth values are in screen space, which have been + // potentially tranformed by a perspective correction. + // To interpolated the depth correctly, there must be a perspective correction. + // I haven't looked, but the wireframmer probably suffers from this too. + // Additionally, this should not happen on the CPU. Annotations take + // far longer than the the geometry. + vtkm::Float32 t = pdist == 0.f ? 1.0 : vtkm::Sqrt(deltaX * deltaX + deltaY * deltaY) / pdist; t = vtkm::Min(1.f, vtkm::Max(0.f, t)); vtkm::Float32 z = vtkm::Lerp(z0, z1, t); + vtkm::Id index = y0 * Canvas->GetWidth() + x0; vtkm::Vec4f_32 currentColor = colorPortal.Get(index); vtkm::Float32 currentZ = depthPortal.Get(index); @@ -85,6 +100,7 @@ void LineRenderer::RenderLine(const vtkm::Vec3f_64& point0, writeColor[2] = currentColor[2] + colorC[2] * alpha; writeColor[3] = 1.f * alpha + currentColor[3]; // we are always drawing opaque lines // keep the current z. Line z interpolation is not accurate + // Matt: this is correct. Interpolation is wrong depth = currentZ; } diff --git a/vtkm/rendering/raytracing/CylinderIntersector.cxx b/vtkm/rendering/raytracing/CylinderIntersector.cxx index 0e73026b3..06c973d87 100644 --- a/vtkm/rendering/raytracing/CylinderIntersector.cxx +++ b/vtkm/rendering/raytracing/CylinderIntersector.cxx @@ -379,7 +379,7 @@ public: : MinScalar(minScalar) { Normalize = true; - if (minScalar > maxScalar) + if (minScalar >= maxScalar) { // support the scalar renderer Normalize = false; diff --git a/vtkm/rendering/raytracing/QuadIntersector.cxx b/vtkm/rendering/raytracing/QuadIntersector.cxx index 6590c76d7..ad74812c2 100644 --- a/vtkm/rendering/raytracing/QuadIntersector.cxx +++ b/vtkm/rendering/raytracing/QuadIntersector.cxx @@ -366,7 +366,7 @@ public: : MinScalar(minScalar) { Normalize = true; - if (minScalar > maxScalar) + if (minScalar >= maxScalar) { // support the scalar renderer Normalize = false; diff --git a/vtkm/rendering/raytracing/RayOperations.cxx b/vtkm/rendering/raytracing/RayOperations.cxx index 1d819eead..a3d5ff087 100644 --- a/vtkm/rendering/raytracing/RayOperations.cxx +++ b/vtkm/rendering/raytracing/RayOperations.cxx @@ -28,7 +28,7 @@ void RayOperations::MapCanvasToRays(Ray& rays, (void)valid; // this can be a false negative for really tiny spatial domains. vtkm::worklet::DispatcherMapField( detail::RayMapCanvas(inverse, width, height, camera.GetPosition())) - .Invoke(rays.PixelIdx, rays.MaxDistance, canvas.GetDepthBuffer()); + .Invoke(rays.PixelIdx, rays.MaxDistance, rays.Origin, canvas.GetDepthBuffer()); } } } diff --git a/vtkm/rendering/raytracing/RayOperations.h b/vtkm/rendering/raytracing/RayOperations.h index dd63c3c4f..5275b441d 100644 --- a/vtkm/rendering/raytracing/RayOperations.h +++ b/vtkm/rendering/raytracing/RayOperations.h @@ -70,12 +70,13 @@ public: DoubleInvWidth = 2.f / static_cast(width); } - using ControlSignature = void(FieldIn, FieldInOut, WholeArrayIn); - using ExecutionSignature = void(_1, _2, _3); + using ControlSignature = void(FieldIn, FieldInOut, FieldIn, WholeArrayIn); + using ExecutionSignature = void(_1, _2, _3, _4); template VTKM_EXEC void operator()(const vtkm::Id& pixelId, Precision& maxDistance, + const Vec& origin, const DepthPortalType& depths) const { vtkm::Vec4f_32 position; @@ -94,7 +95,8 @@ public: p[0] = position[0] / position[3]; p[1] = position[1] / position[3]; p[2] = position[2] / position[3]; - p = p - Origin; + p = p - origin; + maxDistance = vtkm::Magnitude(p); } diff --git a/vtkm/rendering/raytracing/RayTracer.cxx b/vtkm/rendering/raytracing/RayTracer.cxx index 0c12ef888..49b512892 100644 --- a/vtkm/rendering/raytracing/RayTracer.cxx +++ b/vtkm/rendering/raytracing/RayTracer.cxx @@ -277,6 +277,7 @@ void RayTracer::RenderOnDevice(Ray& rays) logger->AddLogData("shapes", NumberOfShapes); logger->AddLogData("num_rays", rays.NumRays); + size_t numShapes = Intersectors.size(); if (NumberOfShapes > 0) { diff --git a/vtkm/rendering/raytracing/SphereIntersector.cxx b/vtkm/rendering/raytracing/SphereIntersector.cxx index 91dd69737..e2274cd6d 100644 --- a/vtkm/rendering/raytracing/SphereIntersector.cxx +++ b/vtkm/rendering/raytracing/SphereIntersector.cxx @@ -257,7 +257,7 @@ public: : MinScalar(minScalar) { Normalize = true; - if (minScalar > maxScalar) + if (minScalar >= maxScalar) { // support the scalar renderer Normalize = false; diff --git a/vtkm/rendering/raytracing/TriangleIntersector.cxx b/vtkm/rendering/raytracing/TriangleIntersector.cxx index 27b3bf05c..62d795359 100644 --- a/vtkm/rendering/raytracing/TriangleIntersector.cxx +++ b/vtkm/rendering/raytracing/TriangleIntersector.cxx @@ -251,7 +251,7 @@ public: : MinScalar(minScalar) { Normalize = true; - if (minScalar > maxScalar) + if (minScalar >= maxScalar) { // support the scalar renderer Normalize = false; @@ -315,7 +315,7 @@ public: : MinScalar(minScalar) { Normalize = true; - if (minScalar > maxScalar) + if (minScalar >= maxScalar) { // support the scalar renderer Normalize = false;