Description
Describe the bug
I tried to use libf3d with python and Gtk, but it doesn't render and it crashes
To Reproduce
Steps to reproduce the behavior:
- Run the provided python code
- Open a 3d file
- It won't render and it will crash after resizing the window.
Expected behavior
It should render correctly inside the Gtk.GLArea, if I render it outside it works.
System Information:
- OS: Fedora 40
- GPU and GPU driver: AMD Radeon™ Graphics
F3D Information
The version of f3d library is 2.4.0 installed with pip
Additional context
import gi
import f3d
gi.require_version('Gtk', '4.0')
gi.require_version('Adw', '1')
from gi.repository import Gtk, Adw
class F3Dwindow(Adw.ApplicationWindow):
__gtype_name__ = 'F3Dwindow'
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.set_default_size(300, 300)
self.set_title("F3D")
self.gl_area = Gtk.GLArea(vexpand=True)
self.gl_area.connect("realize", self.on_realize)
self.gl_area.connect("render", self.on_render)
box = Gtk.Box(orientation=1)
button = Gtk.Button(label="open")
button.connect("clicked", self.open_file_chooser)
hb = Adw.HeaderBar()
hb.pack_start(button)
box.append(hb)
box.append(self.gl_area)
self.set_content(box)
f3d.Engine.autoload_plugins()
self.engine = f3d.Engine(f3d.Window.EXTERNAL)
def on_realize(self, area):
ctx = area.get_context()
def on_render(self, area, ctx):
ctx.make_current()
self.engine.window.render()
print(area.get_error())
return True
def open_file_chooser(self, *args):
dialog = Gtk.FileDialog(
title="Open File",
)
dialog.open(self, None, self.on_open_file_response)
def on_open_file_response(self, dialog, response):
file = dialog.open_finish(response)
print(f"Selected File: {file.get_path()}")
if file:
filepath = file.get_path()
self.engine.loader.load_geometry(filepath)
class F3Dapp(Adw.Application):
def __init__(self):
super().__init__()
def do_activate(self):
win = self.props.active_window
if not win:
win = F3Dwindow(application=self)
win.present()
def main():
app = F3Dapp()
return app.run()
main()
This code should show an application window with a button to open a 3d model file and a Gtk.GLArea where to render the 3d model.
Every time it renders it prints this:
Current framebuffer is bind to framebuffer object 85
color attachment 0:
this attachment is a texture with name: 166
its mipmap level is: 0
this is not a cube map texture.
this is not 3D texture.
color attachment 1:
this attachment is empty
color attachment 2:
this attachment is empty
color attachment 3:
this attachment is empty
color attachment 4:
this attachment is empty
color attachment 5:
this attachment is empty
color attachment 6:
this attachment is empty
color attachment 7:
this attachment is empty
depth attachment :
this attachment is a texture with name: 167
its mipmap level is: 0
this is not a cube map texture.
this is not 3D texture.
stencil attachment :
this attachment is empty
there are 8 draw buffers.
draw buffer[0]=GL_COLOR_ATTACHMENT0
draw buffer[1]=GL_NONE
draw buffer[2]=GL_NONE
draw buffer[3]=GL_NONE
draw buffer[4]=GL_NONE
draw buffer[5]=GL_NONE
draw buffer[6]=GL_NONE
draw buffer[7]=GL_NONE
read buffer=GL_COLOR_ATTACHMENT0
And the result of print(area.get_error())
at line 45 before crashing is:
Segmentation fault (core dumped)
Otherwise is None
I can correctly draw using OpenGL like this and it won't crash:
import gi
import f3d
from OpenGL.GL import *
from OpenGL.GLU import *
[...]
def on_render(self, area, ctx):
# self.engine.window.render()
glClearColor(1,0,0,1)
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
print(area.get_error())
return True
[...]
If I do this:
[...]
def on_render(self, area, ctx):
img = self.engine.window.render_to_image()
img.save("/home/user/image.png")
print(area.get_error())
return True
[...]
It will save an image of the same size of the Gtk.GLArea, but all black if no model is loaded or an image like the following one if a geometry is loaded.
With Gtk.GLArea I can set the allowed APIs with:
self.gl_area.set_allowed_apis(Gdk.GLAPI.GL)
self.gl_area.set_allowed_apis(Gdk.GLAPI.GLES)
With only GL it will not crash and it will not print anything, with GLES it will.