Simplepbr ‘washing out’ / distorting an orange onScreenImage

Hi all,

Apologies as I’m unable to post my code here. Are there any reasons using simplepbr could cause an orange background image or sky object to become washed out. I’m attempting to create a 3d chess board with an orange background image (behind all other elements). However, all methods I’ve tried have encountered this error.

If anyone has any docs or sample code I could review to try and resolve this issue it would be greatly appreciated!

Thanks,
Jack

Hi, welcome to the community!

It has to do with gamma correction. If you take the texture object you are applying, and call setFormat(Texture.F_srgb) or setFormat(Texture.F_srgb_alpha) on it (depending on whether it has an alpha channel or not) it should show as normal.

Normally, models with a texture applied that are imported with panda3d-gltf should automatically have this set on their textures.

Hi RDB, appreciate the quick response.

I’ve tried this but am unfortunately continue to have the error. I’ve managed to find a slightly different, albeit similar block of code i can post. This time there is no image appearing that can be washed out but instead i’m setting a sky object. Once again, colours outside of orange / orange-y yellows are fine, but the two types i need are washed out. Would you have any advice for this one?

code:

from panda3d.core import *
from direct.showbase.ShowBase import ShowBase
import array
import simplepbr


def create_gradient(sky_color, ground_color):
    vertex_format = GeomVertexFormat()
    
    # Position Format
    array_format = GeomVertexArrayFormat()
    array_format.add_column(InternalName.get_vertex(), 3,
        GeomEnums.NT_float32, GeomEnums.C_point)
    vertex_format.add_array(array_format)

    # Color Format (Switch to Float32 instead of Uint8)
    array_format = GeomVertexArrayFormat()
    array_format.add_column(InternalName.make("color"), 4,
        GeomEnums.NT_float32, GeomEnums.C_color)
    vertex_format.add_array(array_format)

    vertex_format = GeomVertexFormat.register_format(vertex_format)

    vertex_data = GeomVertexData("quad_data", vertex_format, GeomEnums.UH_static)
    vertex_data.unclean_set_num_rows(4)

    # Quad Vertex Positions
    values = array.array("f", [
        -.5, 0., -.5,
        .5, 0., -.5,
        -.5, 0., .5,
        .5, 0., .5
    ])
    pos_array = vertex_data.modify_array(0)
    memview = memoryview(pos_array).cast("B").cast("f")
    memview[:] = values

    # Use Direct Float32 Colors (Avoids Precision Loss)
    values = array.array("f", sky_color * 2 + ground_color * 2)
    color_array = vertex_data.modify_array(1)
    memview = memoryview(color_array).cast("B").cast("f")
    memview[:] = values

    # Triangle Indices
    tris_prim = GeomTriangles(GeomEnums.UH_static)
    indices = array.array("H", [
        0, 1, 2,
        1, 3, 2
    ])
    tris_array = tris_prim.modify_vertices()
    tris_array.unclean_set_num_rows(6)
    memview = memoryview(tris_array).cast("B").cast("H")
    memview[:] = indices

    geom = Geom(vertex_data)
    geom.add_primitive(tris_prim)
    node = GeomNode("quad")
    node.add_geom(geom)
    quad = NodePath(node)

    # Disable Lighting on Background Quad
    quad.set_light_off()
    quad.set_bin("background", 0)
    quad.set_depth_write(False)
    quad.set_depth_test(False)

    return quad


class MyApp(ShowBase):

    def __init__(self, use_pbr=True):
        ShowBase.__init__(self)

        # Disable Gamma Correction in simplepbr
        if use_pbr:
            simplepbr.init(
                )
        # Set Up Light Source (Doesn't Affect Background)
        p_light = PointLight("point_light")
        p_light.set_color((1., 1., 1., 1.))
        self.light = self.camera.attach_new_node(p_light)
        self.light.set_pos(5., -100., 7.)
        self.render.set_light(self.light)

        # Load a Model for Reference
        smiley = self.loader.load_model("smiley")
        smiley.reparent_to(self.render)
        smiley.set_y(10.)

        # Define Colors (Using HEX #fbb842 and #ec7650)
# Adjusted colors to avoid over-brightening
        sky_color = (0.9529, 0.5255, 0.3059, 1.0)  # Orange
        ground_color = (0.9843, 0.7216, 0.2588, 1.0)  # Golden Yellow
        


        # Debug Print
        print("Sky color:", sky_color)
        print("Ground color:", ground_color)

        self.background_gradient = create_gradient(sky_color, ground_color)
        self.background_gradient.reparent_to(self.camera)

        # Prevent Background from Being Lit
        self.background_gradient.set_light_off()

        # Adjust Background Position & Size When Lens Changes
        self.camLens.change_event = "lens-event"
        self.accept("lens-event", self.__handle_lens_event)

        # Force a Clear Background Color to Prevent Overexposure
        self.win.set_clear_color((0, 0, 0, 1))  # Black prevents additional brightening

    def __handle_lens_event(self, lens):
        y = lens.focal_length
        f = (lens.near + 1.) / y if y < lens.near + 1. else 1.
        self.background_gradient.set_y(y * f)
        sx, sz = lens.film_size
        self.background_gradient.set_scale(sx * f, 1., sz * f)


app = MyApp()
app.run()

Anything would be great, thank you for the help already

Your conversion doesn’t account for the gamma curve. It’s not as simple as just dividing by 255.

To convert an sRGB hex color to a linear floating-point colour you can do:

from panda3d.core import *

sky_color = (
    decode_sRGB_float(0xfb),
    decode_sRGB_float(0xb8),
    decode_sRGB_float(0x42),
    1.0)