I've been attempting to write a custom RenderEngine for Blender, but have stumbled on a fundamental problem which is preventing me from going any further.
To illustrate the issue I will include an example from the official docs as a small repro:
"""
3D Image
--------
Similar to the 2D Image shader, but works with 3D positions for the image vertices.
To use this example you have to provide an image that should be displayed.
"""
import bpy
import gpu
from gpu_extras.batch import batch_for_shader
IMAGE_NAME = "Untitled"
image = bpy.data.images[IMAGE_NAME]
texture = gpu.texture.from_image(image)
shader = gpu.shader.from_builtin('IMAGE')
batch = batch_for_shader(
shader, 'TRIS',
{
"pos": ((0, 0, 0), (0, 1, 1), (1, 1, 1), (1, 1, 1), (1, 0, 0), (0, 0, 0)),
"texCoord": ((0, 0), (0, 1), (1, 1), (1, 1), (1, 0), (0, 0)),
},
)
def draw():
shader.uniform_sampler("image", texture)
batch.draw(shader)
bpy.types.SpaceView3D.draw_handler_add(draw, (), 'WINDOW', 'POST_VIEW')
When the example is run, a simple textured plane will show up in the 3D viewport.
However, when I adapt the example and add an extra batch of polygons to the script, this happens:
When the viewport is rotated, the second batch (furthest away) appears in front of the first batch (nearest). It seems they are drawn on top of each other in the order I specified in the script.
How can I resolve this issue?
Complete code:
import bpy
import gpu
from gpu_extras.batch import batch_for_shader
IMAGE_NAME = "Untitled"
image = bpy.data.images[IMAGE_NAME]
texture = gpu.texture.from_image(image)
shader = gpu.shader.from_builtin('IMAGE')
batch1 = batch_for_shader(
shader, 'TRIS',
{
"pos": ((0, 0, 0), (0, 1, 1), (1, 1, 1), (1, 1, 1), (1, 0, 0), (0, 0, 0)),
"texCoord": ((0, 0), (0, 1), (1, 1), (1, 1), (1, 0), (0, 0)),
},
)
batch2 = batch_for_shader(
shader, 'TRIS',
{
"pos": ((2, 2, 0), (2, 3, 1), (3, 3, 1), (3, 3, 1), (3, 2, 0), (2, 2, 0)),
"texCoord": ((0, 0), (0, 1), (1, 1), (1, 1), (1, 0), (0, 0)),
},
)
def draw():
fb = gpu.state.active_framebuffer_get()
fb.clear(color=(0, 0, 0, 1))
shader.uniform_sampler("image", texture)
batch1.draw(shader)
batch2.draw(shader)
bpy.types.SpaceView3D.draw_handler_add(draw, (), 'WINDOW', 'POST_VIEW')
gpu.state.depth_test_set(mode='ALWAYS')
docs.blender.org/api/current/… $\endgroup$gpu.state.face_culling_set()
, but I'm still getting artefacts. I wanted to try this with the example RenderEngine from here, but I can't even get the example to run. I even installed Lubuntu on VirtualBox with a fresh install of Blender, thinking it was a problem with my installation, but still nothing happens when I run the script from the text editor. So I wonder if it works for you? $\endgroup$