Skip to content

Commit 233cd80

Browse files
author
operel
committed
vertex array object fix for gl 3.3
Signed-off-by: operel <operel@nvidia.com>
1 parent 1f4203a commit 233cd80

File tree

2 files changed

+28
-12
lines changed

2 files changed

+28
-12
lines changed

wisp/framework/state.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ class InteractiveRendererState:
114114
'none' - No inherent antialising mode will be activated.
115115
"""
116116

117-
gl_version: str = "GL 3.3"
117+
gl_version: str = "GL 3.3 core"
118118
""" Wisp applications rely on glumpy + OpenGL to render specific features and blit content to the window.
119119
This setting configures glumpy to load with a specific OpenGL backend.
120120
OpenGL 3.3 is widely supported and is therefore assumed to be the default.

wisp/renderer/app/wisp_app.py

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,8 @@ def __init__(self, wisp_state, window_name="wisp app"):
111111
# There we generate a simple billboard GL program (normally with a shared CUDA resource)
112112
# Canvas content will be blitted onto it
113113
self.canvas_program: Optional[gloo.Program] = None # GL program used to paint a single billboard
114-
self.cugl_rgb_handle = None # CUDA buffer, as a shared resource with OpenGL
114+
self.vao: Optional[gloo.VertexArray] = None # Vertex array object to hold GL buffers
115+
self.cugl_rgb_handle = None # CUDA buffer, as a shared resource with OpenGL
115116
self.cugl_depth_handle = None
116117

117118
try:
@@ -133,7 +134,7 @@ def __init__(self, wisp_state, window_name="wisp app"):
133134
self.change_user_mode(self.default_user_mode())
134135

135136
self.redraw() # Refresh RendererCore
136-
137+
137138
def add_pipeline(self, name, pipeline, transform=None):
138139
"""Register a neural fields pipeline into the scene graph.
139140
@@ -143,7 +144,7 @@ def add_pipeline(self, name, pipeline, transform=None):
143144
transform (wisp.core.ObjectTransform): The transform for the pipeline.
144145
"""
145146
add_pipeline_to_scene_graph(self.wisp_state, name, pipeline, transform=transform)
146-
147+
147148
def add_widget(self, widget):
148149
""" Adds a widget to the list of widgets.
149150
@@ -242,10 +243,10 @@ def run(self):
242243
"""
243244
app.run() # App clock should always run as frequently as possible (background tasks should not be limited)
244245

245-
def _create_window(self, width, height, window_name, gl_version):
246+
def _create_window(self, width, height, window_name, gl_version) -> app.Window:
246247
# Currently assume glfw backend due to integration with imgui
247248
app.use(f"glfw_imgui ({gl_version})")
248-
win_config = app.configuration.Configuration()
249+
win_config = app.configuration.get_default()
249250
if self.wisp_state.renderer.antialiasing == 'msaa_4x':
250251
win_config.samples = 4
251252

@@ -267,7 +268,7 @@ def _create_window(self, width, height, window_name, gl_version):
267268
return window
268269

269270
@staticmethod
270-
def _create_gl_depth_billboard_program(texture: np.ndarray, depth_texture: np.ndarray):
271+
def _create_gl_depth_billboard_program(texture: np.ndarray, depth_texture: np.ndarray) -> gloo.Program:
271272
vertex = """
272273
uniform float scale;
273274
attribute vec2 position;
@@ -301,8 +302,22 @@ def _create_gl_depth_billboard_program(texture: np.ndarray, depth_texture: np.nd
301302
canvas['depth_tex'] = depth_texture
302303
return canvas
303304

305+
def _create_vao(self, gl_config: app.Configuration) -> gloo.VertexArray:
306+
""" Creates a "default" VertexBufferObject to be used by the GL Programs. """
307+
# OpenGL 3.3+ requires that a VertexArrayObject is always bound.
308+
# Since glumpy's glfw_imgui backend doesn't guarantee one, and imgui expects a GL context with OpenGL >= 3.3,
309+
# we create a default one here for all programs and buffers which gloo will bind its buffers to.
310+
# This isn't how VAOs are meant to be used: it is more correct to keep a VAO per group of buffers (in Wisp's
311+
# case, at least once per gizmo). However, the following glumpy issue needs to be sorted out first, see:
312+
# https://github.com/glumpy/glumpy/issues/310
313+
vao = None
314+
if gl_config.major_version >= 3:
315+
vao = np.zeros(0, np.float32).view(gloo.VertexArray) # Keep GL happy by binding with some VAO handle
316+
vao.activate() # Actual vao created here
317+
return vao
318+
304319
@staticmethod
305-
def _create_screen_texture(res_h, res_w, channel_depth, dtype=np.uint8):
320+
def _create_screen_texture(res_h, res_w, channel_depth, dtype=np.uint8) -> gloo.Texture2D:
306321
""" Create and return a Texture2D with gloo and a cuda handle. """
307322
if issubclass(dtype, np.integer):
308323
tex = np.zeros((res_h, res_w, channel_depth), dtype).view(gloo.Texture2D)
@@ -385,7 +400,7 @@ def render_canvas(self, render_core, time_delta, force_render):
385400

386401
return img, depth_img
387402

388-
def _blit_to_gl_renderbuffer(self, img, depth_img, canvas_program, cugl_rgb_handle, cugl_depth_handle, height):
403+
def _blit_to_gl_renderbuffer(self, img, depth_img, canvas_program, vao, cugl_rgb_handle, cugl_depth_handle, height):
389404
if self.blitdevice2device:
390405
# Device to device copy: Copy CUDA buffer to GL Texture mem
391406
shared_tex = canvas_program['tex']
@@ -402,6 +417,8 @@ def _blit_to_gl_renderbuffer(self, img, depth_img, canvas_program, cugl_rgb_hand
402417
canvas_program['tex'] = img.cpu().numpy()
403418
canvas_program['depth_tex'] = depth_img.cpu().numpy()
404419

420+
if vao is not None:
421+
vao.activate()
405422
canvas_program.draw(gl.GL_TRIANGLE_STRIP)
406423

407424
def update_renderer_state(self, wisp_state, dt):
@@ -487,7 +504,7 @@ def render(self):
487504

488505
# glumpy code injected within the pyimgui render loop to blit the renderer core output to the actual canvas
489506
# The torch buffers are copied by with cuda, connected as shared resources as 2d GL textures
490-
self._blit_to_gl_renderbuffer(img, depth_img, self.canvas_program, self.cugl_rgb_handle,
507+
self._blit_to_gl_renderbuffer(img, depth_img, self.canvas_program, self.vao, self.cugl_rgb_handle,
491508
self.cugl_depth_handle, self.height)
492509

493510
# Finally, render OpenGL gizmos on the canvas.
@@ -544,6 +561,7 @@ def on_resize(self, width, height):
544561
self.cugl_depth_handle = self._register_cugl_shared_texture(depth_tex)
545562
if self.canvas_program is None:
546563
self.canvas_program = self._create_gl_depth_billboard_program(texture=tex, depth_texture=depth_tex)
564+
self.vao = self._create_vao(self.window.config)
547565
else:
548566
if self.canvas_program['tex'] is not None:
549567
self.canvas_program['tex'].delete()
@@ -708,7 +726,6 @@ def dump_framebuffer(self, path='./framebuffer'):
708726
framebuffer = np.flip(framebuffer, 0)
709727
ext.png.from_array(framebuffer, 'L').save(path + '_depth.png')
710728

711-
712729
def register_io_mappings(self):
713730
WispMouseButton.register_symbol(WispMouseButton.LEFT_BUTTON, app.window.mouse.LEFT)
714731
WispMouseButton.register_symbol(WispMouseButton.MIDDLE_BUTTON, app.window.mouse.MIDDLE)
@@ -720,4 +737,3 @@ def register_io_mappings(self):
720737
WispKey.register_symbol(WispKey.DOWN, app.window.key.DOWN)
721738

722739
# TODO: Take care of remaining mappings, and verify the event handlers of glumpy were not overriden
723-

0 commit comments

Comments
 (0)