Offscreen rendering with bgl.glEnable(bgl.GL_DEPTH_TEST) results in black images (affects Windows only) #85709

Closed
opened 2021-02-16 19:29:36 +01:00 by Sebastian · 21 comments

System Information
System 1:
Operating system: Windows-10-10.0.18362-SP0 64 Bits
Graphics card: GeForce GTX TITAN X/PCIe/SSE2 NVIDIA Corporation 4.5.0 NVIDIA 451.48

System 2:
Operating system: Windows-10-10.0.19041-SP0 64 Bits
Graphics card: GeForce 840M/PCIe/SSE2 NVIDIA Corporation 4.5.0 NVIDIA 452.41

Blender Version
Broken: version: 2.92.0 Beta, branch: master, commit date: 2021-02-15 19:10, hash: 3e55d7d605
Broken: version: 2.93.0 Alpha, branch: master, commit date: 2021-02-16 01:44, hash: 4a784f32fe
Worked: never (on Windows)

Short description of error
Using offscreen rendering with bgl.glEnable(bgl.GL_DEPTH_TEST) results in black images. The problem does not appear under Linux.

Exact steps for others to reproduce the error
Use the attached python file to reproduce this issue.
test_opengl_rendering.py
Set the variable ofp to a valid output file path.
If use_bgl_dl_depth_test is set to False the following image should be rendered.
bgl_test.jpeg
If use_bgl_dl_depth_test is set to True only a black image appears.

The workaround proposed in https://developer.blender.org/T83482 does not fix the issue.

**System Information** System 1: Operating system: Windows-10-10.0.18362-SP0 64 Bits Graphics card: GeForce GTX TITAN X/PCIe/SSE2 NVIDIA Corporation 4.5.0 NVIDIA 451.48 System 2: Operating system: Windows-10-10.0.19041-SP0 64 Bits Graphics card: GeForce 840M/PCIe/SSE2 NVIDIA Corporation 4.5.0 NVIDIA 452.41 **Blender Version** Broken: version: 2.92.0 Beta, branch: master, commit date: 2021-02-15 19:10, hash: `3e55d7d605` Broken: version: 2.93.0 Alpha, branch: master, commit date: 2021-02-16 01:44, hash: `4a784f32fe` Worked: never (on Windows) **Short description of error** Using offscreen rendering with bgl.glEnable(bgl.GL_DEPTH_TEST) results in black images. The problem does not appear under Linux. **Exact steps for others to reproduce the error** Use the attached python file to reproduce this issue. [test_opengl_rendering.py](https://archive.blender.org/developer/F9809187/test_opengl_rendering.py) Set the variable `ofp` to a valid output file path. If `use_bgl_dl_depth_test` is set to `False` the following image should be rendered. ![bgl_test.jpeg](https://archive.blender.org/developer/F9809159/bgl_test.jpeg) If `use_bgl_dl_depth_test` is set to `True` only a black image appears. The workaround proposed in https://developer.blender.org/T83482 does not fix the issue.
Author

Added subscriber: @sbcv

Added subscriber: @sbcv

Added subscribers: @fclem, @rjg

Added subscribers: @fclem, @rjg

The behavior is platform independent for me. Unfortunately, I currently don't have time to look further into this. @fclem Perhaps this is something for you.

The behavior is platform independent for me. Unfortunately, I currently don't have time to look further into this. @fclem Perhaps this is something for you.
Author

Strange, the system I mentioned above, i.e.

Operating system: Windows-10-10.0.18362-SP0 64 Bits
Graphics card: GeForce GTX TITAN X/PCIe/SSE2 NVIDIA Corporation 4.5.0 NVIDIA 451.48

has a dualboot installation (Windows + Linux). And for Linux it worked as expected.

I tested it also on another Linux system without problems, see specs below:

  Operating system: Linux-5.4.0-65-generic-x86_64-with-debian-buster-sid 64 Bits
  Graphics card: Quadro RTX 6000/PCIe/SSE2 NVIDIA Corporation 4.5.0 NVIDIA 450.102.04
Strange, the system I mentioned above, i.e. ``` Operating system: Windows-10-10.0.18362-SP0 64 Bits Graphics card: GeForce GTX TITAN X/PCIe/SSE2 NVIDIA Corporation 4.5.0 NVIDIA 451.48 ``` has a dualboot installation (Windows + Linux). And for Linux it worked as expected. I tested it also on another Linux system without problems, see specs below: ``` Operating system: Linux-5.4.0-65-generic-x86_64-with-debian-buster-sid 64 Bits Graphics card: Quadro RTX 6000/PCIe/SSE2 NVIDIA Corporation 4.5.0 NVIDIA 450.102.04 ```

Added subscriber: @2046411367

Added subscriber: @2046411367

Added subscriber: @mano-wii

Added subscriber: @mano-wii

Changed status from 'Needs Triage' to: 'Archived'

Changed status from 'Needs Triage' to: 'Archived'

Revisiting some older reports I found this one:
Apparently you also need to enable bgl.glDepthMask(True) to get the intended result.
I'm not sure why the problem only occurs on Windows. But since the bgl module is deprecated in favor of the gpu, I don't think this issue is worth investigating.
Try using these functions instead:

gpu.state.depth_mask_set(True)
gpu.state.depth_test_set('LESS_EQUAL')
Revisiting some older reports I found this one: Apparently you also need to enable `bgl.glDepthMask(True)` to get the intended result. I'm not sure why the problem only occurs on Windows. But since the `bgl` module is deprecated in favor of the `gpu`, I don't think this issue is worth investigating. Try using these functions instead: ``` gpu.state.depth_mask_set(True) gpu.state.depth_test_set('LESS_EQUAL') ```
Author

Unfortunately, both proposed solutions do not fix the bug on my Windows system - I still get a black image when the depth test is enabled (tested with Blender 3.0).
So, I'm afraid that the bug also affects the gpu module.
Even worse: I've realized that the bug is not deterministic - a few times, I've actually obtained the desired result with the depth test enabled (maybe 1 out of 10 while changing different parts of the script).

I've attached the adjusted test script with your latest instructions. Maybe you could have a look at it, so we can make sure that I understood you correctly. test_opengl_rendering_v2.py

Unfortunately, **both** proposed solutions do not fix the bug on my Windows system - I still get a black image when the depth test is enabled (tested with Blender 3.0). So, I'm afraid that the bug **also affects the gpu module**. Even worse: I've realized that the bug is not deterministic - a few times, I've actually obtained the desired result with the depth test enabled (maybe 1 out of 10 while changing different parts of the script). I've attached the adjusted test script with your latest instructions. Maybe you could have a look at it, so we can make sure that I understood you correctly. [test_opengl_rendering_v2.py](https://archive.blender.org/developer/F12870377/test_opengl_rendering_v2.py)

@sbcv do not mix gpu and bgl usage. This is asking for trouble

Moreover, you never clear the framebuffer so the content of the depth buffer is undefined.

Try using offscreen.clear() or the bgl equivalent should fix the issue.

@sbcv do not mix gpu and bgl usage. This is asking for trouble Moreover, you never clear the framebuffer so the content of the depth buffer is undefined. Try using `offscreen.clear()` or the bgl equivalent should fix the issue.
Author

Thank you for your advice, I've integrated the points mentioned above - unfortunately with no success.

@ Sebastian (SBCV) do not mix gpu and bgl usage. This is asking for trouble

I was not aware of that (since previously a lot of the examples on https:*docs.blender.org/api/current/gpu.html used the GPL and the GPU module simultaneously). I've now replaced all bgl related commands with their gpu counterparts.

Moreover, you never clear the framebuffer so the content of the depth buffer is undefined.
Try using offscreen.clear() or the bgl equivalent should fix the issue.

I'm afraid that this instruction is a bit unclear to me. According to https:*docs.blender.org/api/current/gpu.types.html, only gpu.types.GPUFrameBuffer has a clear() method - gpu.types.GPUOffScreen has only a free() method.

Since the offscreen.free() method has already been used in the example script, I've added also

    fb = gpu.state.active_framebuffer_get()
    fb.clear(color=(0.0, 0.0, 0.0, 0.0))

However, the current version of the script works (still) only for linux but not for windows. I've added another version of the example script with the latest changes. I would highly appreciate, if you could have another look.

test_opengl_rendering_v3.py

Thank you for your advice, I've integrated the points mentioned above - unfortunately with no success. > @ Sebastian (SBCV) do not mix gpu and bgl usage. This is asking for trouble I was not aware of that (since previously a lot of the examples on [https:*docs.blender.org/api/current/gpu.html](https:*docs.blender.org/api/current/gpu.html) used the GPL and the GPU module simultaneously). I've now replaced all `bgl` related commands with their `gpu` counterparts. > Moreover, you never clear the framebuffer so the content of the depth buffer is undefined. > Try using `offscreen.clear()` or the bgl equivalent should fix the issue. I'm afraid that this instruction is a bit unclear to me. According to [https:*docs.blender.org/api/current/gpu.types.html](https:*docs.blender.org/api/current/gpu.types.html), only `gpu.types.GPUFrameBuffer` has a `clear()` method - `gpu.types.GPUOffScreen` has only a `free()` method. Since the `offscreen.free()` method has already been used in the example script, I've added also ``` fb = gpu.state.active_framebuffer_get() fb.clear(color=(0.0, 0.0, 0.0, 0.0)) ``` However, the current version of the script works (still) only for linux but not for windows. I've added another version of the example script with the latest changes. I would highly appreciate, if you could have another look. [test_opengl_rendering_v3.py](https://archive.blender.org/developer/F12871369/test_opengl_rendering_v3.py)

Try clearing the depth too:

    fb.clear(color=(0.0, 0.0, 0.0, 1.0), depth=1.0)
Try clearing the depth too: ``` fb.clear(color=(0.0, 0.0, 0.0, 1.0), depth=1.0) ```

However the value 1.0 is the default value for depth in fb.clear(color=(0.0, 0.0, 0.0, 0.0)). Strange it still doesn't work. EDIT: My mistake, it is mandatory to set a value for the depth if you want to clear the depth too

I tested the new script and it works here on Windows.
The problem may also be in the point size.

Try adding the line gpu.state.program_point_size_set(False)

~~However the value 1.0 is the default value for depth in `fb.clear(color=(0.0, 0.0, 0.0, 0.0))`. Strange it still doesn't work.~~ **EDIT: My mistake, it is mandatory to set a value for the depth if you want to clear the depth too** I tested the new script and it works here on Windows. The problem may also be in the point size. Try adding the line `gpu.state.program_point_size_set(False)`
Author

Replacing fb.clear(color=(0.0, 0.0, 0.0, 0.0)) with fb.clear(color=(0.0, 0.0, 0.0, 1.0), depth=1.0) did the trick - thank you!

However, I've noticed that the replacement of

bgl.glEnable(bgl.GL_DEPTH_TEST)

with

gpu.state.depth_mask_set(True)
gpu.state.depth_test_set('LESS_EQUAL')

causes my Blender gui to freeze (at least partly). For example, I'm not able to close Blender or to change the editor type (like the 3D view). When I change the size of the 3D view or the outliner I observe strange drawing artifacts - see the attached image. freeze.JPG

But I guess that is a different bug?

I've attached the latest version of the script which draws the points but also causes this partly Blender freeze.
test_opengl_rendering_v4.py

If you want, I can open another bug report.

Replacing `fb.clear(color=(0.0, 0.0, 0.0, 0.0))` with `fb.clear(color=(0.0, 0.0, 0.0, 1.0), depth=1.0)` did the trick - thank you! However, I've noticed that the replacement of ``` bgl.glEnable(bgl.GL_DEPTH_TEST) ``` with ``` gpu.state.depth_mask_set(True) gpu.state.depth_test_set('LESS_EQUAL') ``` causes my Blender gui to freeze (at least partly). For example, I'm not able to close Blender or to change the editor type (like the `3D view`). When I change the size of the `3D view` or the `outliner` I observe strange drawing artifacts - see the attached image. ![freeze.JPG](https://archive.blender.org/developer/F12871518/freeze.JPG) But I guess that is a different bug? I've attached the latest version of the script which draws the points but also causes this partly Blender freeze. [test_opengl_rendering_v4.py](https://archive.blender.org/developer/F12871503/test_opengl_rendering_v4.py) If you want, I can open another bug report.
Author

Btw: When I tried to add gpu.state.program_point_size_set(False), I received gpu.state has no attribute use_program_point_size.

My Blender Version is: version: 3.0.1, branch: master, commit date: 2022-01-25 17:19, hash: dc2d180181

Btw: When I tried to add `gpu.state.program_point_size_set(False)`, I received `gpu.state has no attribute use_program_point_size`. My Blender Version is: version: 3.0.1, branch: master, commit date: 2022-01-25 17:19, hash: `dc2d180181`
Author

Even more strange:
I've written a Blender addon that allows to import reconstructions of several Structure-from-Motion-based libraries.
The addon also allows to render the corresponding point clouds using a function similar to the one contained in the example script.
Today, I've updated the offscreen rendering of the addon according to your suggestions. If I run the offscreen rendering with the latest changes from within the GUI of the Blender Addon, I do not see the freezing behavior and I can perform multiple renderings and close Blender without any issues.

Even more strange: I've written a [Blender addon](https://github.com/SBCV/Blender-Addon-Photogrammetry-Importer) that allows to import reconstructions of several Structure-from-Motion-based libraries. The addon also allows to render the corresponding point clouds using a function similar to the one contained in the example script. Today, I've updated the offscreen rendering of the addon according to your suggestions. If I run the offscreen rendering with the latest changes from within the GUI of the Blender Addon, I do not see the freezing behavior and I can perform multiple renderings and close Blender without any issues.

Fixed issue with documentation -> 59aaf2036e
The other issues may be related to state changes that are not restored.

Fixed issue with documentation -> 59aaf2036e The other issues may be related to state changes that are not restored.
Author

The other issues may be related to state changes that are not restored.

Could you be a bit more specific here?

> The other issues may be related to state changes that are not restored. Could you be a bit more specific here?
Author

The other issues may be related to state changes that are not restored.

Indeed, I fixed with

previous_depth_test_value = gpu.state.depth_test_get()
gpu.state.depth_test_set('LESS_EQUAL')
...
gpu.state.depth_test_set(previous_depth_test_value)

I've attached the working script for future references: test_opengl_rendering_working.py

While debugging, I found the following inconsistencies between the actual python API and the API documentation .

Documentation: gpu.state.blend_depth_test_get()
API: gpu.state.depth_test_get()

Documentation: gpu.state.depth_mask_set_get()
API: gpu.state.depth_mask_get()

Besides that: do you think it makes sense to add a simplified version of the working script to the offscreen rendering examples in the gpu module documentation ? Currently, the documentation contains only an example for the 2D case.

> The other issues may be related to state changes that are not restored. Indeed, I fixed with ``` previous_depth_test_value = gpu.state.depth_test_get() gpu.state.depth_test_set('LESS_EQUAL') ... gpu.state.depth_test_set(previous_depth_test_value) ``` I've attached the working script for future references: [test_opengl_rendering_working.py](https://archive.blender.org/developer/F12876428/test_opengl_rendering_working.py) While debugging, I found the following inconsistencies between the actual python API and the [API documentation ](https://docs.blender.org/api/current/gpu.state.html). Documentation: `gpu.state.blend_depth_test_get()` API: `gpu.state.depth_test_get()` Documentation: `gpu.state.depth_mask_set_get()` API: `gpu.state.depth_mask_get()` Besides that: do you think it makes sense to add a simplified version of the working script to the offscreen rendering examples in the [gpu module documentation ](https://docs.blender.org/api/current/gpu.html#copy-offscreen-rendering-result-back-to-ram)? Currently, the documentation contains only an example for the 2D case.

Good to see you found the state changes that were causing the problem :)
(Maybe Blender should internally restore at the end of each draw callback and make it safer).
For the depth test, I don't think it's really necessary to check the previous state, just set it to False at the end of the callback (this should be the default depth test for these functions).


Thanks for the heads up on the documentation inconsistencies. I will fix this.


In #85709#1310566, @sbcv wrote:
(...)
Besides that: do you think it makes sense to add a simplified version of the working script to the offscreen rendering examples in the gpu module documentation ? Currently, the documentation contains only an example for the 2D case.

I'm not sure what's missing. There are already 3 examples using GPOUffScreen. (Two of them for 3D View).
If a new example is important, feel free to contact the developers through one of the channels listed at: https://wiki.blender.org/wiki/Communication/Contact

Good to see you found the state changes that were causing the problem :) (Maybe Blender should internally restore at the end of each draw callback and make it safer). For the depth test, I don't think it's really necessary to check the previous state, just set it to False at the end of the callback (this should be the default depth test for these functions). --- Thanks for the heads up on the documentation inconsistencies. I will fix this. --- > In #85709#1310566, @sbcv wrote: > (...) > Besides that: do you think it makes sense to add a simplified version of the working script to the offscreen rendering examples in the [gpu module documentation ](https://docs.blender.org/api/current/gpu.html#copy-offscreen-rendering-result-back-to-ram)? Currently, the documentation contains only an example for the 2D case. I'm not sure what's missing. There are already 3 examples using `GPOUffScreen`. (Two of them for 3D View). If a new example is important, feel free to contact the developers through one of the channels listed at: https://wiki.blender.org/wiki/Communication/Contact
Author

(Maybe Blender should internally restore at the end of each draw callback and make it safer).

That would definitively improve the robustness of the api

I'm not sure what's missing. There are already 3 examples using GPOUffScreen. (Two of them for 3D View).

That is correct, but the current examples do not show how to

  • correctly initialize the depth buffer, i.e.
fb.clear(depth=1.0)
  • properly load the matrices for offscreen rendering in 3D, i.e.
    view_matrix = camera_object.matrix_world.inverted()
    projection_matrix = camera_object.calc_matrix_camera(
        bpy.context.evaluated_depsgraph_get(), x=width, y=height
    )
    perspective_matrix = projection_matrix @ view_matrix
    gpu.matrix.load_matrix(perspective_matrix)
    gpu.matrix.load_projection_matrix(Matrix.Identity(4))

  • restore a correct depth state after computation, i.e.
gpu.state.depth_mask_set(False)
gpu.state.depth_test_set('NONE')

I don't know, but considering the fact that I needed several times the help from you and Clément, I feel that the current examples are a bit limited w.r.t. the rendering of 3D opengl elements to the offscreen buffer (from an arbitrary perspective).
Side note: When I observed the black images (under windows only) and the freeze like behavior, I would have never guessed that I could fix these with setting specific states.

> (Maybe Blender should internally restore at the end of each draw callback and make it safer). That would definitively improve the robustness of the api > I'm not sure what's missing. There are already 3 examples using GPOUffScreen. (Two of them for 3D View). That is correct, but the current examples do not show how to - correctly initialize the depth buffer, i.e. ``` fb.clear(depth=1.0) ``` - properly load the matrices for offscreen rendering in 3D, i.e. ``` view_matrix = camera_object.matrix_world.inverted() projection_matrix = camera_object.calc_matrix_camera( bpy.context.evaluated_depsgraph_get(), x=width, y=height ) perspective_matrix = projection_matrix @ view_matrix gpu.matrix.load_matrix(perspective_matrix) gpu.matrix.load_projection_matrix(Matrix.Identity(4)) ``` - restore a correct depth state after computation, i.e. ``` gpu.state.depth_mask_set(False) gpu.state.depth_test_set('NONE') ``` I don't know, but considering the fact that I needed several times the help from you and Clément, I feel that the current examples are a bit limited w.r.t. the rendering of 3D opengl elements to the offscreen buffer (from an arbitrary perspective). Side note: When I observed the black images (under windows only) and the freeze like behavior, I would have never guessed that I could fix these with setting specific states.
Sign in to join this conversation.
No Label
Interest
Alembic
Interest
Animation & Rigging
Interest
Asset Browser Project (Legacy)
Interest
Asset System
Interest
Audio
Interest
Automated Testing
Interest
Blender Asset Bundle
Interest
BlendFile
Interest
Collada
Interest
Compatibility
Interest
Compositing
Interest
Core
Interest
Cycles
Interest
Dependency Graph
Interest
Development Management
Interest
EEVEE
Interest
EEVEE & Viewport
Interest
Freestyle
Interest
Geometry Nodes
Interest
Grease Pencil
Interest
ID Management
Interest
Images & Movies
Interest
Import Export
Interest
Line Art
Interest
Masking
Interest
Metal
Interest
Modeling
Interest
Modifiers
Interest
Motion Tracking
Interest
Nodes & Physics
Interest
OpenGL
Interest
Overlay
Interest
Overrides
Interest
Performance
Interest
Physics
Interest
Pipeline, Assets & IO
Interest
Platforms, Builds & Tests
Interest
Python API
Interest
Render & Cycles
Interest
Render Pipeline
Interest
Sculpt, Paint & Texture
Interest
Text Editor
Interest
Translations
Interest
Triaging
Interest
Undo
Interest
USD
Interest
User Interface
Interest
UV Editing
Interest
VFX & Video
Interest
Video Sequencer
Interest
Virtual Reality
Interest
Vulkan
Interest
Wayland
Interest
Workbench
Interest: X11
Legacy
Blender 2.8 Project
Legacy
Milestone 1: Basic, Local Asset Browser
Legacy
OpenGL Error
Meta
Good First Issue
Meta
Papercut
Meta
Retrospective
Meta
Security
Module
Animation & Rigging
Module
Core
Module
Development Management
Module
EEVEE & Viewport
Module
Grease Pencil
Module
Modeling
Module
Nodes & Physics
Module
Pipeline, Assets & IO
Module
Platforms, Builds & Tests
Module
Python API
Module
Render & Cycles
Module
Sculpt, Paint & Texture
Module
Triaging
Module
User Interface
Module
VFX & Video
Platform
FreeBSD
Platform
Linux
Platform
macOS
Platform
Windows
Priority
High
Priority
Low
Priority
Normal
Priority
Unbreak Now!
Status
Archived
Status
Confirmed
Status
Duplicate
Status
Needs Info from Developers
Status
Needs Information from User
Status
Needs Triage
Status
Resolved
Type
Bug
Type
Design
Type
Known Issue
Type
Patch
Type
Report
Type
To Do
No Milestone
No project
No Assignees
5 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: blender/blender#85709
No description provided.