Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve default near/far #3293

Merged
merged 2 commits into from
Oct 16, 2023
Merged

Improve default near/far #3293

merged 2 commits into from
Oct 16, 2023

Conversation

ffreyer
Copy link
Collaborator

@ffreyer ffreyer commented Oct 13, 2023

Description

In the original camera3d pr I changed near/far to be multiplied by norm(eyeposition - lookat) and set the default far to be very large to avoid clipping issues. This is problematic for OIT where depth is used to mix colors because without zooming plots occupy a very small depth range.

To summarize the issues with clipping:

  • when zooming in (i.e. looking at details) a static near value will eventually become large relative to the limits one looks at. This will cause data to be clipped starting from the camera
  • when zooming out a static far value will eventually clip the far side of the plot. This usually starts with the axis frame/grid disappearing

This pr makes static near/far values available again and adds a new (default) scaling mode which scales far so that far = 1 always ends up behind the scene bounding sphere, and calculates near to be just in front of it, but no closer than norm(lookat - eyeposition) * near (to avoid negative near). This continues to solve the clipping issues as near effectively scales with zooming, far is always outside/behind the region containing data, and it should improve OIT again by keeping the depth scale close to the minimum necessary.

Camera setup from the OIT refimg test (scene area not matched exactly)

Code
begin
    using GLMakie
    using GeometryBasics, LinearAlgebra

    function frustum_snapshot(cam)
        r = Rect3f(Point3f(-1, -1, -1), Vec3f(2, 2, 2))
        rect_ps = coordinates(r) .|> Point3f
        insert!(rect_ps, 13, Point3f(1, -1, 1)) # fix bad line

        inv_pv = inv(cam.projectionview[])
        return map(rect_ps) do p
            p = inv_pv * to_ndim(Point4f, p, 1)
            return p[Vec(1,2,3)] / p[4]
        end
    end


    ex = Point3f(1,0,0)
    ey = Point3f(0,1,0)
    ez = Point3f(0,0,1)
end

begin
    fig = Figure()
    ax = LScene(fig[1, 1])
    cam3d!(ax.scene)
    r = Rect2f(-1, -1, 2, 2)
    for x in (0, 1)
        for (i, a) in enumerate((0.25, 0.5, 0.75, 1.0))
            ps = [Point3f(a, (0.15 + 0.01y)*(2x-1) , 0.2y) for y in 1:8]
            if x == 0
                cs = [RGBAf(1, 0, 0, 0.75), RGBAf(0, 1, 0, 0.5), RGBAf(0, 0, 1, 0.25)]
            elseif x == 1
                cs = [RGBAf(1, x, 0, a), RGBAf(0, 1, x, a), RGBAf(x, 0, 1, a)]
            end
            idxs = [1, 2, 3, 2, 1, 3, 1, 2, 1, 2, 3][i:7+i]
            meshscatter!(
                ax, ps, marker = r,
                color = cs[idxs], transparency = true
            )
        end
    end
    cc = cameracontrols(ax.scene)
    cc.fov[] = 22f0
    update_cam!(ax.scene, cc, Vec3f(0.625, 0, 3.5), Vec3f(0.625, 0, 0), Vec3f(0, 1, 0))

    scene = ax.scene
    cam = scene.camera
    eyeposition = cc.eyeposition
    lookat = cc.lookat
    frustum = map(pv -> frustum_snapshot(cam), cam.projectionview)

    scene2 = LScene(fig[1, 2])
    _cc = Makie.Camera3D(scene2.scene, projectiontype = Makie.Orthographic)
    lines!(scene2, frustum, color = :blue, linestyle = :dot)
    scatter!(scene2, eyeposition, color = :black)
    scatter!(scene2, lookat, color = :black)

    r = Rect2f(-1, -1, 2, 2)
    for x in (0, 1)
        for (i, a) in enumerate((0.25, 0.5, 0.75, 1.0))
            ps = [Point3f(a, (0.15 + 0.01y)*(2x-1) , 0.2y) for y in 1:8]
            if x == 0
                cs = [RGBAf(1, 0, 0, 0.75), RGBAf(0, 1, 0, 0.5), RGBAf(0, 0, 1, 0.25)]
            elseif x == 1
                cs = [RGBAf(1, x, 0, a), RGBAf(0, 1, x, a), RGBAf(x, 0, 1, a)]
            end
            idxs = [1, 2, 3, 2, 1, 3, 1, 2, 1, 2, 3][i:7+i]
            meshscatter!(
                scene2, ps, marker = r,
                color = cs[idxs], transparency = true
            )
        end
    end
    linesegments!(scene2, data_limits(scene), color = :black)

    r = map(frustum) do frustum
        r = Rect3f(frustum)
        Rect2f(origin(r)[Vec(1,2)], widths(r)[Vec(1,2)])
        # Rect3f(frustum)
    end
    m = mesh!(scene2, r, color = :lightblue)
    on(frustum) do frustum
        x, y, z = minimum(Rect3f(frustum))
        translate!(m, Vec3f(0, 0, z))
    end
    notify(frustum)

    fig
end

Screenshot from 2023-10-13 20-30-59

For reference, this is from master:

Screenshot from 2023-10-13 16-28-16

And this from beta-20:

Screenshot from 2023-10-13 16-33-23

Type of change

  • Bug fix (non-breaking change which fixes an issue)

@MakieBot
Copy link
Collaborator

MakieBot commented Oct 13, 2023

Compile Times benchmark

Note, that these numbers may fluctuate on the CI servers, so take them with a grain of salt. All benchmark results are based on the mean time and negative percent mean faster than the base branch. Note, that GLMakie + WGLMakie run on an emulated GPU, so the runtime benchmark is much slower. Results are from running:

using_time = @ctime using Backend
# Compile time
create_time = @ctime fig = scatter(1:4; color=1:4, colormap=:turbo, markersize=20, visible=true)
display_time = @ctime Makie.colorbuffer(display(fig))
# Runtime
create_time = @benchmark fig = scatter(1:4; color=1:4, colormap=:turbo, markersize=20, visible=true)
display_time = @benchmark Makie.colorbuffer(display(fig))
using create display create display
GLMakie 10.51s (10.48, 10.54) 0.02+- 805.13ms (796.68, 812.92) 6.13+- 1.22s (1.20, 1.28) 0.03+- 9.11ms (8.99, 9.15) 0.06+- 153.50ms (151.45, 154.94) 1.15+-
sd/beta-20 10.49s (10.47, 10.51) 0.01+- 797.37ms (790.73, 805.23) 4.40+- 1.21s (1.21, 1.22) 0.01+- 9.10ms (9.02, 9.17) 0.05+- 152.44ms (150.42, 153.52) 1.09+-
evaluation +0.21%, 0.02s slower X (1.39d, 0.02p, 0.02std) +0.96%, 7.76ms slower X (1.45d, 0.02p, 5.27std) +0.51%, 0.01s invariant (0.33d, 0.56p, 0.02std) +0.11%, 0.01ms invariant (0.19d, 0.72p, 0.05std) +0.69%, 1.07ms invariant (0.95d, 0.10p, 1.12std)
CairoMakie 14.45s (14.04, 15.03) 0.37+- 1.22s (1.16, 1.28) 0.04+- 840.38ms (788.51, 902.56) 44.47+- 17.22ms (16.09, 19.13) 0.98+- 9.40ms (9.00, 9.97) 0.32+-
sd/beta-20 14.56s (14.09, 14.90) 0.31+- 1.26s (1.15, 1.33) 0.06+- 829.25ms (787.06, 868.22) 24.94+- 17.31ms (16.10, 17.97) 0.83+- 9.33ms (8.99, 9.67) 0.23+-
evaluation -0.73%, -0.11s invariant (-0.31d, 0.57p, 0.34std) -3.04%, -0.04s invariant (-0.77d, 0.18p, 0.05std) +1.32%, 11.13ms invariant (0.31d, 0.58p, 34.70std) -0.56%, -0.1ms invariant (-0.11d, 0.85p, 0.91std) +0.67%, 0.06ms invariant (0.23d, 0.68p, 0.27std)
WGLMakie 15.25s (14.72, 16.84) 0.74+- 1007.66ms (949.30, 1165.20) 75.48+- 13.75s (13.38, 14.40) 0.42+- 17.76ms (14.80, 26.60) 3.98+- 1.06s (0.96, 1.10) 0.05+-
sd/beta-20 14.99s (14.71, 15.93) 0.45+- 978.98ms (932.32, 1072.10) 55.18+- 13.90s (13.38, 14.57) 0.44+- 16.77ms (15.48, 17.51) 0.79+- 1.08s (1.04, 1.21) 0.06+-
evaluation +1.71%, 0.26s invariant (0.42d, 0.45p, 0.60std) +2.85%, 28.68ms invariant (0.43d, 0.43p, 65.33std) -1.09%, -0.15s invariant (-0.35d, 0.53p, 0.43std) +5.59%, 0.99ms noisy🤷‍♀️ (0.35d, 0.54p, 2.38std) -2.70%, -0.03s invariant (-0.53d, 0.34p, 0.05std)

@ffreyer
Copy link
Collaborator Author

ffreyer commented Oct 16, 2023

@SimonDanisch This should be ready to merge. If we want to get OIT closer to what it was we can tweak the weight factor after this.

@SimonDanisch SimonDanisch merged commit 722c659 into sd/beta-20 Oct 16, 2023
13 of 15 checks passed
@SimonDanisch SimonDanisch deleted the ff/cam_depth branch October 16, 2023 12:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants