Configuring the Texture class

Practicing with creating textures at a low level, I came to the conclusion that I was using the Texture class incorrectly. I used the read() method which overrides the previously set parameters. This is not what I want, I switched to the set_ram_image() method, however, I had difficulties.

from direct.showbase.ShowBase import ShowBase
from panda3d.core import Texture, PTAUchar, CPTAUchar

class MyApp(ShowBase):

    def __init__(self):
        ShowBase.__init__(self)

        file = open('fon.png', mode = 'rb')
        image = CPTAUchar(file.read())
        #image = PTAUchar(file.read())
        file.close()

        tex = Texture("Texture")
        tex.setup_2d_texture(256, 256, Texture.T_unsigned_byte, Texture.F_rgba)
        tex.set_ram_image(image)

app = MyApp()
app.run()

I get such an error, which is completely not informative.

D:\Code\Blank>D:\Panda3D-1.10.13-x64\python\python.exe main.py
Known pipe types:
  wglGraphicsPipe
(all display modules loaded.)
Assertion failed: compression != CM_off || image.size() == do_get_expected_ram_image_size(cdata) at line 5652 of c:\buildslave\sdk-windows-amd64\build\panda\src\gobj\texture.cxx
Traceback (most recent call last):
  File "main.py", line 18, in <module>
    app = MyApp()
  File "main.py", line 16, in __init__
    tex.set_ram_image(image)
AssertionError: compression != CM_off || image.size() == do_get_expected_ram_image_size(cdata) at line 5652 of c:\buildslave\sdk-windows-amd64\build\panda\src\gobj\texture.cxx

fon

Hmm… Okay, the error seems to indicate that either the problem is the compression-mode, or the size of the image.

The former seems to be the easier to test–“set_ram_image” takes a “compression” parameter.

And indeed, it looks like–on my machine at least–setting that parameter to “Texture.CM_on” removes the assertion-error!

Like so:

from direct.showbase.ShowBase import ShowBase
from panda3d.core import Texture, PTAUchar, CPTAUchar

class MyApp(ShowBase):

    def __init__(self):
        ShowBase.__init__(self)

        file = open('fon.png', mode = 'rb')
        image = CPTAUchar(file.read())
        #image = PTAUchar(file.read())
        file.close()

        tex = Texture("Texture")
        tex.setup_2d_texture(256, 256, Texture.T_unsigned_byte, Texture.F_rgba)
        tex.set_ram_image(image, Texture.CM_on) # <-----

app = MyApp()
app.run()

This is not the solution. Passing a compression mode just disables the size check. But it will crash later on, because the RAM image is not compressed in a way that the GPU will understand. GPUs do not understand PNG-compressed data, the only compression they understand is block compression (DXT et al) or uncompressed, raw image data.

So, you need to decode the .png data first. This can be done via PNMImage, or with Texture.read (passing in a StringStream). set_ram_image will not handle decoding/decompressing for you, it is for raw data only.

2 Likes

Ah, I stand corrected then, with my apologies!