mosra / magnum

Lightweight and modular C++11 graphics middleware for games and data visualization
https://magnum.graphics/
Other
4.74k stars 439 forks source link

Some trouble with LineGL3D shader when camera is close #634

Open bz-next opened 5 months ago

bz-next commented 5 months ago

I toyed around with the LineGL3D shader to render a simple debug grid:

image

The trouble is, when I zoom in close to the grid, the window gets filled with some artifacts:

image

image

I am just using the default LineGL3D shader with no special config.

Below is the code that generates the line objects and attaches the drawables:

{
        debugLine = new GL::Mesh{
            MeshTools::compileLines(
                MeshTools::generateLines(
                    WorldPrimitiveGenerator::debugLine(
                        {-1.0f, 0.0f, 0.0f},
                        {1.0f, 0.0f, 0.0f})))};
        Object3D *debugLines = new Object3D{};
        debugLines->setParent(worldParent);
        debugLines->scale(Vector3{100.0, 100.0, 100.0});
        // Create debug grid
        int numLines = 20;
        float start = -1.0f;
        float step = 2.0f/numLines;

        // xy grid
        for (int i = 0; i <= numLines; ++i) {
            Object3D *xline = new Object3D{};
            xline->setParent(debugLines);
            xline->translate({0.0f, start+i*step, 0.0f});
            new DebugLineDrawable{*xline, _lineShader, 0.5*Color3{1.0f, 0.0f, 0.0f}, *debugLine, *worldDebugDrawables};
            Object3D *yline = new Object3D{};
            yline->setParent(debugLines);
            yline->rotateZ(Deg(90.0f));
            yline->translate({start+i*step, 0.0f, 0.0f});
            new DebugLineDrawable{*yline, _lineShader, 0.5*Color3{0.0f, 1.0f, 0.0f}, *debugLine, *worldDebugDrawables};
        }
        Object3D *zline = new Object3D{};
        zline->setParent(debugLines);
        zline->rotateY(Deg(90.0));
        new DebugLineDrawable{*zline, _lineShader, 0.5*Color3{0.0f, 0.0f, 1.0f}, *debugLine, *worldDebugDrawables};
    }

And the drawable itself:

void DebugLineDrawable::draw(const Matrix4& transformationMatrix, SceneGraph::Camera3D& camera) {
    _shader
        .setColor(_color)
        .setViewportSize(Vector2{GL::defaultFramebuffer.viewport().size()})
        .setTransformationProjectionMatrix(camera.projectionMatrix()*transformationMatrix)
        .setWidth(2.0f)
        .draw(_mesh);
}

Generator for the debug line mesh:

Trade::MeshData WorldPrimitiveGenerator::debugLine(Magnum::Math::Vector3<float> a, Magnum::Math::Vector3<float> b) {
    constexpr Trade::MeshAttributeData AttributeData3DWireframe[]{
        Trade::MeshAttributeData{Trade::MeshAttribute::Position, VertexFormat::Vector3,
            0, 0, sizeof(Vector3)}
    };
    constexpr UnsignedInt points = 11;

    Containers::Array<char> vertexData{points*sizeof(Vector3)};
    auto positions = Containers::arrayCast<Vector3>(vertexData);
    Vector3 delta = b-a;
    delta /= float(points)-1;

    Vector3 pos = a;
    for (int i = 0; i < points; ++i) {
        positions[i] = pos+delta*i;
    }

    return MeshTools::copy(Trade::MeshData{MeshPrimitive::LineStrip, Utility::move(vertexData),
        Trade::meshAttributeDataNonOwningArray(AttributeData3DWireframe), UnsignedInt(positions.size())});
}

In terms of scale: The lines themselves are 2 units long (-1.0 to 1.0 on their respective axes). They are parented to an Object3D that has a scale factor of 100 in all dimensions. That Object3D is parented to another object that has a scale factor of 0.05. The overall hierarchy is:

[scene manipulator] <- [world object (0.05x)] <- [debug lines object (100x)] <- [the lines]

The camera projection matrix is defined by .setProjectionMatrix(Matrix4::perspectiveProjection(35.0_degf, 1.0f, 0.1f, 1000.0f))

I tried increasing my near plane from 0.1f to 1.0f since I read this helps with z-buffer artifacts, and it doesn't eliminate the issue, just changes it:

image

Is there something I'm doing wrong with using the shader? I've tried changing the number of points / line (ideally I'd just use 2, but I tried varying it in case it made a difference. Here I'm using 11 points.)

mosra commented 5 months ago

Hello -- I already replied on Gitter, but replying here as well to not make it look like I'm ignoring this.

Artifacts with the near clip plane are a problem I'm aware of and on my list of things to fix. Enabling GL::Renderer::Feature::DepthClamp should help with that, at least in most cases. I looked around and discovered that it's now also available on WebGL, so with bb4064beda78259b7e050558971abe8c7d8f727a you should be able to use it there as well.

I'll comment here once I get back to investigating this.