1
$\begingroup$

As you know, bgl module has been deprecated and will be deleted in the future Blender release. So, I'm tackling to change my old code to use gpu module.

My old code uses bgl.glScissor to clip the target rendered by blf and blf module. However, I could not find the way to implement same function (like bgl.glScissor) with gpu module.

Is there any way to realize bgl.glScissor with gpu module?

$\endgroup$
0

2 Answers 2

1
$\begingroup$

The term "scissor" does not appear in the docs, so I assume a direct equivalent does not exist.

What you could do instead is use a shader that discards fragments outside of the scissor rectangle. The rectangle boundaries would be passed with a uniform.

Here's the second example from the gpu module docs modified to do this. Added lines have been marked with a #.

import bpy
import gpu
from gpu_extras.batch import batch_for_shader


vert_out = gpu.types.GPUStageInterfaceInfo("my_interface")
vert_out.smooth('VEC3', "pos")

shader_info = gpu.types.GPUShaderCreateInfo()
shader_info.push_constant('MAT4', "viewProjectionMatrix")
shader_info.push_constant('FLOAT', "brightness")
shader_info.push_constant('VEC4', "scissorRect")                 #
shader_info.vertex_in(0, 'VEC3', "position")
shader_info.vertex_out(vert_out)
shader_info.fragment_out(0, 'VEC4', "FragColor")

shader_info.vertex_source(
    "void main()"
    "{"
    "  pos = position;"
    "  gl_Position = viewProjectionMatrix * vec4(position, 1.0f);"
    "}"
)

shader_info.fragment_source(
    "void main()"
    "{"
    "  if ("                                                     #
    "    gl_FragCoord.x < scissorRect.x || "                     #
    "    gl_FragCoord.x > scissorRect.z || "                     #
    "    gl_FragCoord.y < scissorRect.y || "                     #
    "    gl_FragCoord.y > scissorRect.w "                        #
    "  ) discard;"                                               #
    "  FragColor = vec4(pos * brightness, 1.0);"
    "}"
)

shader = gpu.shader.create_from_info(shader_info)
del vert_out
del shader_info

coords = [(1, 1, 1), (2, 0, 0), (-2, -1, 3)]
batch = batch_for_shader(shader, 'TRIS', {"position": coords})


def draw():
    matrix = bpy.context.region_data.perspective_matrix
    shader.uniform_float("viewProjectionMatrix", matrix)
    shader.uniform_float("brightness", 0.5)
    shader.uniform_float("scissorRect", [100, 100, 300, 300])    #
    batch.draw(shader)


bpy.types.SpaceView3D.draw_handler_add(draw, (), 'WINDOW', 'POST_VIEW')

Triangle being clipped to the scissor rectangle as the viewport is moved

$\endgroup$
7
  • $\begingroup$ Thanks for the answer. This works well for the target rendered by gpu module. But how do I extend this to the target rendered by blf module. Do I need to make a new shader? $\endgroup$
    – nutti
    Commented Feb 17, 2023 at 3:48
  • 1
    $\begingroup$ Isn't that what blf.clipping does? $\endgroup$
    – scurest
    Commented Feb 17, 2023 at 3:52
  • $\begingroup$ I overlooked blf.clipping, thanks! BTW, all built-in shaders like POLYLINE_SMOOTH_COLOR needs to be re-written to the custom shader in this way? Or any other workarounds? $\endgroup$
    – nutti
    Commented Feb 17, 2023 at 8:15
  • $\begingroup$ Yes. You could try using the stencil buffer I guess. There is some stencil stuff in gpu but I couldn't figure out how to use it. $\endgroup$
    – scurest
    Commented Feb 17, 2023 at 8:44
  • 1
    $\begingroup$ Btw, perhaps you're the one who requested this, but if you're not, you will want to know an issue was just filed for adding the scissor test. $\endgroup$
    – scurest
    Commented Feb 18, 2023 at 8:02
1
$\begingroup$

As of Blender 3.6, the gpu module now has gpu.state.scissor_set and gpu.state.scissor_test_set.

$\endgroup$
1
  • $\begingroup$ Thanks for the sharing. I have also confirmed the new API has already included the latest source code. $\endgroup$
    – nutti
    Commented Feb 22, 2023 at 9:07

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .