HDR in panda

Thank you for your answer. I have no problem to implement tone mapping in the shader myself. Unfortunately, it seems to me that this HDR just doesn’t work for me.

Let’s take an example.

Here is the Panda3D Python code:

from direct.filter.FilterManager import FilterManager
from direct.showbase.ShowBase import ShowBase
from panda3d.core import (
    LightRampAttrib,
    ColorBlendAttrib,
    Texture,
    Shader,
    loadPrcFileData,
)

loadPrcFileData("", "gl-version 4 1")
base = ShowBase()
base.setBackgroundColor(0.75, 0.75, 0.75)
# noinspection PyArgumentList
base.render.setAttrib(LightRampAttrib.makeHdr0())
# noinspection PyArgumentList
base.render.setAttrib(ColorBlendAttrib.make(ColorBlendAttrib.MAdd))
model = base.loader.loadModel("ripple")
model.reparentTo(base.render)
model.setPos(0, 2, 0)
manager = FilterManager(base.win, base.cam)
tex = Texture()
quad = manager.renderSceneInto(colortex=tex)
# noinspection PyArgumentList
quad.setShader(
    Shader.load(
        Shader.SL_GLSL,
        vertex="basic.vert",
        fragment="basic.frag",
    )
)
quad.setShaderInput("tex", tex)
base.run()

Here is the vertex shader code in GLSL:

#version 410
uniform mat4 p3d_ModelViewProjectionMatrix;
in vec4 p3d_Vertex;
void main() {
    gl_Position = p3d_ModelViewProjectionMatrix * p3d_Vertex;
}

Here is the shader fragment code in GLSL:

#version 410
uniform sampler2D tex;
out vec4 p3d_FragColor;
void main() {
    p3d_FragColor = texture(tex, gl_FragCoord.xy / textureSize(tex, 0));
    p3d_FragColor.rgb -= 0.75;
}

Now let me explain what’s going on here.

I’m loading one of the standard Panda3D objects, “ripple”. I place the object on a fairly light background: (0.75, 0.75, 0.75). Normally it would look like this:

But this time, what’s more, I render the object in additive mode, i.e. the pixel brightness of the “ripple” itself is added to the already bright background. Naturally, a large part of the pixels are overexposed and looks like this:

Well, yes, but we supposedly have HDR turned on, i.e. we have inactive upper clamping, which means that pixels can take values with > 1.0 components. So if I then add a full-screen quad, which will act as a filter, and in this filter I subtract 0.75 from each component, I would expect the background to become black (because 0.75 - 0.75 = 0.0), and the object “ripple” will have the original colors. However, this is not quite what happens:

Yes, the background becomes black (with HDR not needed here, of course, because we were within the scale), but the colors of the object are distorted. So clearly, somewhere along the way, there was an upper clamping at the value of 1.0, despite the HDR mode being enabled for the entire scene (for base.render).

Where am I making a mistake?