Genesis
Genesis copied to clipboard
Visualization Bug - AttributeError: function 'glGetUniformLocation' not found
Visualizing the elastic dragon example on Windows:
(venv) PS S:\Tools\genesis> py .\elastic_dragon.py --vis
[Genesis] [21:41:21] [INFO] Running on [NVIDIA GeForce RTX 3090 Ti] with backend gs.cuda. Device memory: 23.99 GB.
[Genesis] [21:41:22] [DEBUG] [Taichi] version 1.7.2, llvm 15.0.1, commit 0131dce9, win, python 3.10.5
[Genesis] [21:41:22] [DEBUG] [Taichi] Starting on arch=cuda
[Genesis] [21:41:22] [INFO] ๐ Genesis initialized. ๐ version: 0.2.0, ๐ฑ seed: None, ๐ precision: '32', ๐ debug: False, ๐จ theme: 'dark'.
[Genesis] [21:41:22] [INFO] Scene <2463c84> created.
[Genesis] [21:41:22] [INFO] Adding <gs.PBD3DEntity>. idx: 0, uid: <e6ec9b0>, morph: <gs.morphs.Mesh(file='S:\Tools\genesis\venv\lib\site-packages\genesis\assets\meshes/dragon/dragon.obj')>, material: <gs.PBD.Elastic>.
[Genesis] [21:41:22] [DEBUG] Remeshed file (`.rm`) found in cache.
[Genesis] [21:41:23] [INFO] Building scene <2463c84>...
[Genesis] [21:41:25] [INFO] Compiling simulation kernels...
[Genesis] [21:41:30] [INFO] Building visualizer...
Traceback (most recent call last):
File "S:\Tools\genesis\elastic_dragon.py", line 58, in <module>
main()
File "S:\Tools\genesis\elastic_dragon.py", line 49, in main
scene.build()
File "S:\Tools\genesis\venv\lib\site-packages\genesis\utils\misc.py", line 38, in wrapper
return method(self, *args, **kwargs)
File "S:\Tools\genesis\venv\lib\site-packages\genesis\engine\scene.py", line 556, in build
self._visualizer.build()
File "S:\Tools\genesis\venv\lib\site-packages\genesis\vis\visualizer.py", line 101, in build
self._context.build(self._scene)
File "S:\Tools\genesis\venv\lib\site-packages\genesis\vis\rasterizer_context.py", line 70, in build
self.jit = JITRenderer(self._scene, [], [])
File "S:\Tools\genesis\venv\lib\site-packages\genesis\ext\pyrender\jit_render.py", line 201, in __init__
self.gen_func_ptr()
File "S:\Tools\genesis\venv\lib\site-packages\genesis\ext\pyrender\jit_render.py", line 354, in gen_func_ptr
self.gl = GLWrapper()
File "S:\Tools\genesis\venv\lib\site-packages\genesis\ext\pyrender\numba_gl_wrapper.py", line 24, in __init__
load_func("glGetUniformLocation", GLint, GLuint, GLvoidp)
File "S:\Tools\genesis\venv\lib\site-packages\genesis\ext\pyrender\numba_gl_wrapper.py", line 52, in load_func
func_ptr = GL.platform.ctypesloader.buildFunction(
File "S:\Tools\genesis\venv\lib\site-packages\OpenGL\platform\ctypesloader.py", line 96, in buildFunction
return functionType( (name, dll), )
AttributeError: function 'glGetUniformLocation' not found
[Genesis] [21:41:30] [INFO] ๐ค Exiting Genesis and caching compiled kernels...
causes an AttributeError. Works fine without the --vis flag.
I met the same problem
same problem here
Is everyone here using Windows?
Is everyone here using Windows?
Here is win11
same problem using win11
Same problem here as well. I use win 11 and made sure all the dependencies are installed.
Following the topic.
https://genesis-world.readthedocs.io/en/latest/user_guide/overview/installation.html Based on our test, rendering is not supported on Windows due to OpenGL issues. It would be super appreciated if someone could find a solution. Otherwise, Linux or macOS are the only platforms supporting rasterization.
https://genesis-world.readthedocs.io/en/latest/user_guide/overview/installation.html Based on our test, rendering is not supported on Windows due to OpenGL issues. It would be super appreciated if someone could find a solution. Otherwise, Linux or macOS are the only platforms supporting rasterization.
I added a small try/except feature in the 'load_func()' function in numba_gl_wrapper.py. Here is the list of libraries that can be loaded successfully or not.
Failed to load glGetUniformLocation: function 'glGetUniformLocation' not found
Failed to load glUniformMatrix4fv: function 'glUniformMatrix4fv' not found
Failed to load glUniform1i: function 'glUniform1i' not found
Failed to load glUniform1f: function 'glUniform1f' not found
Failed to load glUniform2f: function 'glUniform2f' not found
Failed to load glUniform3fv: function 'glUniform3fv' not found
Failed to load glUniform4fv: function 'glUniform4fv' not found
Failed to load glBindVertexArray: function 'glBindVertexArray' not found
Failed to load glActiveTexture: function 'glActiveTexture' not found
Loaded glBindTexture successfully.
Loaded glEnable successfully.
Loaded glDisable successfully.
Loaded glBlendFunc successfully.
Loaded glPolygonMode successfully.
Loaded glCullFace successfully.
Failed to load glDrawElementsInstanced: function 'glDrawElementsInstanced' not found
Failed to load glDrawArraysInstanced: function 'glDrawArraysInstanced' not found
Failed to load glUseProgram: function 'glUseProgram' not found
Loaded glFlush successfully.
Loaded glReadPixels successfully.
Failed to load glBindBuffer: function 'glBindBuffer' not found
Failed to load glBufferData: function 'glBufferData' not found
Failed to load glBufferSubData: function 'glBufferSubData' not found
Another thing I noticed is the way of the definition of the functions(or objects).
glFlush: an example of the function that loads successfully
<OpenGL.platform.baseplatform.glFlush object at 0x000001AF92DDEB90>
glGetUniformLocation: an example of the function cannot load
OpenGL.lazywrapper.lazy( 'glGetUniformLocation' )
I hope it helps.
I met the same problem in Win10.
I found that in pyrender/numba_gl_wrapper.py/load_func, the variable dll pointed at 'C:\WINDOWS\system32\opengl32.dll', which we know that windows only support OpenGL until version 1.1, but what we need is OpenGL2.0 or later. so is there anyone know, how to change the default OpenGL version that dll = GL.platform.PLATFORM.GL pointed at?
Another interesting thing is, the following code can work:
python
>>> from OpenGL.GL import glGetUniformLocation as a
>>> from OpenGL.GL import glActiveTexture as b
>>> a
OpenGL.lazywrapper.lazy( 'glGetUniformLocation' )
>>> b
<OpenGL.platform.baseplatform.glActiveTexture object at 0x000002845FD4C550>
So I wonder if there's a way that we just import those function directly instead of load them from load_func?
Same Problem.
Based on our test, rendering is not supported on Windows due to OpenGL issues.
Hope someone can solve it!!!!
Lame. I spent a while trying to get this to run. This is the blocking error.
Should put a warning on the repo that it doesn't work on windows 11 currently
We can make a workaround, but simpler and slower, for Windows visualization by modifying elastic_dragon.py --vis to render a GIF using matplotlib instead of OpenGL.
- Add imports at top:
import matplotlib.pyplot as plt, imageio, io
- Disable OpenGL viewer:
show_viewer=False
- Replace simulation loop visualization:
for i in range(horizon):
scene.step()
with
if args.vis:
# Pre-create figure once
fig = plt.figure(figsize=(8, 8), dpi=100)
ax = fig.add_subplot(111, projection='3d')
frames = []
for i in range(horizon):
scene.step()
if i % 20 == 0:
# Get positions and update scatter plot
pos = scene.get_state()._solvers_state[5]._pos.cpu().numpy()
ax.clear() # Clear previous frame
ax.scatter(pos[:, 0], pos[:, 1], pos[:, 2], c='red', s=1)
# Capture frame directly to memory
buf = io.BytesIO()
fig.savefig(buf, format='png')
buf.seek(0)
frames.append(imageio.imread(buf))
buf.close()
plt.close()
imageio.mimsave('simulation.gif', frames, fps=10)
Lame. I spent a while trying to get this to run. This is the blocking error.
Should put a warning on the repo that it doesn't work on windows 11 currently
the compatibility matrix here on the docs does say that windows viewer is not supported. however adding camera is not supported also
I met the same problem in Win10.
I found that in pyrender/numba_gl_wrapper.py/load_func, the variable
dllpointed at 'C:\WINDOWS\system32\opengl32.dll', which we know that windows only support OpenGL until version 1.1, but what we need is OpenGL2.0 or later. so is there anyone know, how to change the default OpenGL version thatdll = GL.platform.PLATFORM.GLpointed at?Another interesting thing is, the following code can work:
python >>> from OpenGL.GL import glGetUniformLocation as a >>> from OpenGL.GL import glActiveTexture as b >>> a OpenGL.lazywrapper.lazy( 'glGetUniformLocation' ) >>> b <OpenGL.platform.baseplatform.glActiveTexture object at 0x000002845FD4C550>So I wonder if there's a way that we just import those function directly instead of load them from
load_func?
the OpenGL.lazywrapper.lazy( 'glGetUniformLocation' ) upon calling raises NullFunctionError: Attempt to call an undefined function glGetUniformLocation, check for bool(glGetUniformLocation) before calling, seems like the lazy wrapper can't find the symbol during runtime
same problem, GPU:nvidiaRTX3070ti
C:\Users\32653\PycharmProjects\PythonProject.venv\Scripts\python.exe C:\Users\32653\PycharmProjects\PythonProject\main.py
[Genesis] [19:00:39] [INFO] โญโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎ
[Genesis] [19:00:39] [INFO] โโโโโโโโโโโโโโโโโโโโ Genesis โโโโโโโโโโโโโโโโโโโโ
[Genesis] [19:00:39] [INFO] โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ
[Genesis] [19:00:39] [INFO] Running on [Intel64 Family 6 Model 154 Stepping 3, GenuineIntel] with backend gs.cpu. Device memory: 31.68 GB.
[Genesis] [19:00:39] [INFO] ๐ Genesis initialized. ๐ version: 0.2.0, ๐ฑ seed: None, ๐ precision: '32', ๐ debug: False, ๐จ theme: 'dark'.
[Genesis] [19:00:39] [INFO] Scene <1c2da54> created.
[Genesis] [19:00:39] [INFO] Adding <gs.RigidEntity>. idx: 0, uid:
I have made some attempts, personally think it should be the problem of PyOpenGL library, PyOpenGL installed directly on 64-bit windows by pip will lack dll files, this problem can be solved, so that PyOpenGL can run normally in other programs. However, the source code seems to use ctypes to load 32-bit dll files, 64-bit python will not find the file, but install 32-bit python will not be able to use "pip install genesis-world", perhaps on linux to solve these problems.
https://genesis-world.readthedocs.io/en/latest/user_guide/overview/installation.html Based on our test, rendering is not supported on Windows due to OpenGL issues. It would be super appreciated if someone could find a solution. Otherwise, Linux or macOS are the only platforms supporting rasterization.
I added a small try/except feature in the 'load_func()' function in numba_gl_wrapper.py. Here is the list of libraries that can be loaded successfully or not.
Failed to load glGetUniformLocation: function 'glGetUniformLocation' not found Failed to load glUniformMatrix4fv: function 'glUniformMatrix4fv' not found Failed to load glUniform1i: function 'glUniform1i' not found Failed to load glUniform1f: function 'glUniform1f' not found Failed to load glUniform2f: function 'glUniform2f' not found Failed to load glUniform3fv: function 'glUniform3fv' not found Failed to load glUniform4fv: function 'glUniform4fv' not found Failed to load glBindVertexArray: function 'glBindVertexArray' not found Failed to load glActiveTexture: function 'glActiveTexture' not found Loaded glBindTexture successfully. Loaded glEnable successfully. Loaded glDisable successfully. Loaded glBlendFunc successfully. Loaded glPolygonMode successfully. Loaded glCullFace successfully. Failed to load glDrawElementsInstanced: function 'glDrawElementsInstanced' not found Failed to load glDrawArraysInstanced: function 'glDrawArraysInstanced' not found Failed to load glUseProgram: function 'glUseProgram' not found Loaded glFlush successfully. Loaded glReadPixels successfully. Failed to load glBindBuffer: function 'glBindBuffer' not found Failed to load glBufferData: function 'glBufferData' not found Failed to load glBufferSubData: function 'glBufferSubData' not foundAnother thing I noticed is the way of the definition of the functions(or objects).
glFlush: an example of the function that loads successfully
<OpenGL.platform.baseplatform.glFlush object at 0x000001AF92DDEB90>glGetUniformLocation: an example of the function cannot loadOpenGL.lazywrapper.lazy( 'glGetUniformLocation' )I hope it helps.
The reason you're unable to find certain OpenGL functions, such as glGetUniformLocation, in the opengl32.dll export table on Windows is that the opengl32.dll provided by Microsoft is typically outdated and only supports basic functionality. Microsoft doesn't actively maintain or update OpenGL, as they focus more on DirectX for graphics programming.
As is shown below, opengl32.dll at C:\Windows\System32 on Windows 11 24H2 only has limited api sets. glGetUniformLocation is not found.
Instead, modern OpenGL functionality is provided through GPU drivers from vendors like Nvidia or AMD. These drivers include their own implementations of OpenGL, often providing support for newer versions and extensions.
same problem using win11
same problem using win11
same problem using win11
same problem using win11 so which example in here can we run on windows 11 ?
maybe should try wglGetProcAddress to get the opengl func ptr
Using glfw making it works now...
Using glfw making it works now...
Hello. It stops there. Or the viewer Or the viewer doesn't show up if I'm not using the camera.
Using glfw making it works now...
In this way, although the image cannot be obtained directly at present, the particle position of some routines has actually been generated and can be visualized by plt
Test program code:
`import torch import matplotlib.pyplot as plt import genesis as gs
all_particles = []
def main(): ########################## init ########################## gs.init()
########################## create a scene ##########################
scene = gs.Scene(
sim_options=gs.options.SimOptions(
dt=4e-3,
substeps=10,
),
sph_options=gs.options.SPHOptions(
lower_bound=(-0.5, -0.5, 0.0),
upper_bound=(0.5, 0.5, 1),
particle_size=0.01,
),
vis_options=gs.options.VisOptions(
visualize_sph_boundary=True,
),
show_viewer=True,
)
########################## entities ##########################
plane = scene.add_entity(
morph=gs.morphs.Plane(),
)
liquid = scene.add_entity(
# viscous liquid
# material=gs.materials.SPH.Liquid(mu=0.02, gamma=0.02),
material=gs.materials.SPH.Liquid(),
morph=gs.morphs.Box(
pos=(0.0, 0.0, 0.65),
size=(0.4, 0.4, 0.4),
),
surface=gs.surfaces.Default(
color=(0.4, 0.8, 1.0),
vis_mode='particle',
),
)
########################## build ##########################
scene.build()
gs.tools.run_in_another_thread(fn=run_sim, args=(scene, False, liquid))
#scene.viewer.start()
def run_sim(scene, enable_vis, liquid): global all_particles i = 0 while True: i += 1
scene.step()
particles = liquid.get_particles()
# print(particles)
'''
[-4.8954931e-01 3.9647943e-01 2.0921452e-02]
[-2.9889485e-01 -3.5985804e-01 2.3578152e-03]
[-3.0421656e-01 5.0000000e-01 9.5947198e-06]
'''
all_particles.append(particles)
if i > 10:
break
if enable_vis:
scene.viewer.stop()
main() while True: if len(all_particles) == 10: for particles in all_particles: fig = plt.figure() ax = fig.add_subplot(111, projection='3d') ax.scatter(particles[:, 0], particles[:, 1], particles[:, 2]) ax.set_xlabel('x') ax.set_ylabel('y') ax.set_zlabel('z') plt.show()
plt.show()`
same problem here
same problem here
Can be workarounded using MESA.
Short answer
- Download Mesa OpenGL32.dll from here: https://github.com/lightningterror/mesa3D-Windows/releases (not the official source, but avoid compiling it by yourself).
- Put it so that it is found before Windows/System32/openGL32.dll. If you use python venv, you can put it in venv/script.
- Comment the
gs.raise_exceptioninvenv\Lib\site-packages\genesis\vis\viewer.py line 67
Long answer
OpenGL is not strickly speaking a library. It is a spec which is implemented by some other parties, especially by GPU vendors in the driver. Historically, Windows has implemented this library at the begining, but stopped at OpenGL 1.2. That's why glGetUniformLocation symbole is not present in windows's OpenGL.dll as glGetUniformLocation has been introducedd in OpenGL 2.x
MESA is a CPU implementation of OpenGL spec. Meaning, it defines and implement all the symboles but the code will be executed on CPU, instead of GPU. Meaning performences will lower.
Real fix would be to load OpenGL symboles from the GPU driver instead of Windows OpenGL32.dll. In C/C++ this is done typically using GLEW. However, I don't know how to proceed in python.
same issue with win 11, cuda 12.4, rtx4090 - if the camera/viewer is the part unsupported on windows, how can I run a simulation using genesis and access the data (via spout lookup to the same gpu memory address, ideally) so that I can render it in a separate process? all the example code for simulations (SPH, etc) includes the scene.build() line, which is what triggers the aforementioned issue. how should we run a simulation without using scene.build()?
Could we rely on PyOpenGLโs Automatic Loading? Based on an earlier comment A straightforward โfixโ in Python is to rely on PyOpenGL to load extensions for you. Once youโve created a modern OpenGL context (for example, using GLFW and specifying a minimum core profile version like 3.3), you can:
import glfw from OpenGL.GL import glGetUniformLocation, glUseProgram, ...
Create a window and context
glfw.init() glfw.window_hint(glfw.CONTEXT_VERSION_MAJOR, 3) glfw.window_hint(glfw.CONTEXT_VERSION_MINOR, 3) glfw.window_hint(glfw.OPENGL_PROFILE, glfw.OPENGL_CORE_PROFILE) window = glfw.create_window(800, 600, "OpenGL Window", None, None) glfw.make_context_current(window)
Now PyOpenGL will be able to load modern functions
location = glGetUniformLocation(some_program, b"uniformName")
Under the hood, PyOpenGL uses the current context and calls wglGetProcAddress to load entry points for functions not found in opengl32.dll. This typically means you donโt have to do any manual symbol loading yourself, as PyOpenGL mimics what GLEW does in C/C++.
Another option is to get the pointers manually Using wglGetProcAddress with ctypes If you really want to replicate GLEW-like behavior manually:
First, ensure you have a valid, current OpenGL context created by something like GLFW or any other windowing toolkit that can provide a modern context.
Import the necessary functions and DLLs:
import ctypes
Load the system OpenGL library
opengl32 = ctypes.windll.opengl32
Get the wglGetProcAddress function
wglGetProcAddress = opengl32.wglGetProcAddress wglGetProcAddress.restype = ctypes.c_void_p wglGetProcAddress.argtypes = [ctypes.c_char_p]
After making the context current:
func_ptr = wglGetProcAddress(b"glGetUniformLocation") if not func_ptr: raise RuntimeError("Failed to load glGetUniformLocation!")
Once you have the function pointer, you convert it into a callable Python function using ctypes.CFUNCTYPE. For example:
Define a Python signature for glGetUniformLocation
GLGetUniformLocationType = ctypes.CFUNCTYPE( ctypes.c_int, # return type GLint ctypes.c_uint, # GLuint program ctypes.c_char_p # const GLchar *name )
glGetUniformLocation = GLGetUniformLocationType(func_ptr)
Now you can call glGetUniformLocation just like a normal Python function
location = glGetUniformLocation(program, b"myUniform")
This mimics what GLEW does in C/C++: querying the driver for a function pointer and then wrapping it for convenient use.
A valid context is needed because wglGetProcAddress only works when thereโs a current OpenGL context that supports the requested function. If you call it before making the context current or if you have an incompatible context (e.g., too old), it will return None.
Maybe I'm misunderstanding the implementation here but why can't we just use a more modern method to load PyOpenGL. PyOpenGLโs extension loading process is very similar to what GLEW does, but itโs done automatically after you create a modern context and import from OpenGL.GL. Thatโs why the real fix is usually just to create a proper modern OpenGL context, then rely on PyOpenGLโs from OpenGL.GL import ... approach instead of manually loading symbols.
Can anyone clarify why we can't just do something like: import OpenGL.GL as GL from OpenGL.GL import glGetUniformLocation
Instead of manually loading?

