Note
Go to the end to download the full example code.
Fine-tuning the OpenGL state using shader callbacks#
Sometimes we need to get more control about how OpenGL will render the actors. This example shows how to change the OpenGL state of one or more actors. This can be useful when we need to create specialized visualization effects.
First, let’s import some functions
import itertools
import numpy as np
import fury
We just proceed as usual: creating the actors and initializing a scene in FURY
centers = np.array([[0, 0, 0], [-0.1, 0, 0], [0.1, 0, 0]])
colors = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]])
actor_no_depth_test = fury.actor.markers(
centers,
marker="s",
colors=colors,
marker_opacity=0.5,
scales=0.2,
)
actor_normal_blending = fury.actor.markers(
centers - np.array([[0, -0.5, 0]]),
marker="s",
colors=colors,
marker_opacity=0.5,
scales=0.2,
)
actor_add_blending = fury.actor.markers(
centers - np.array([[0, -1, 0]]),
marker="s",
colors=colors,
marker_opacity=0.5,
scales=0.2,
)
actor_sub_blending = fury.actor.markers(
centers - np.array([[0, -1.5, 0]]),
marker="s",
colors=colors,
marker_opacity=0.5,
scales=0.2,
)
actor_mul_blending = fury.actor.markers(
centers - np.array([[0, -2, 0]]),
marker="s",
colors=colors,
marker_opacity=0.5,
scales=0.2,
)
scene = fury.window.Scene()
scene.background((0.5, 0.5, 0.5))
showm = fury.window.ShowManager(
scene=scene, size=(900, 768), reset_camera=False, order_transparent=False
)
All actors must be added in the scene
scene.add(actor_no_depth_test)
scene.add(actor_normal_blending)
scene.add(actor_add_blending)
scene.add(actor_sub_blending)
scene.add(actor_mul_blending)
Now, we will enter in the topic of this example. First, we need to create (or use one of the pre-built gl_function of FURY) to change the OpenGL state of a given fury window instance (showm.window).
Here we’re using the pre-build FURY window functions which has already a set of specific behaviors to be applied in the OpenGL context
fury.shaders.shader_apply_effects(
showm.window, actor_normal_blending, effects=fury.window.gl_set_normal_blending
)
# ###############################################################################
# It's also possible use a list of effects. The final opengl state it'll
# be the composition of each effect that each function has in the opengl state
id_observer = fury.shaders.shader_apply_effects(
showm.window,
actor_no_depth_test,
effects=[
fury.window.gl_reset_blend,
fury.window.gl_disable_blend,
fury.window.gl_disable_depth,
],
)
fury.shaders.shader_apply_effects(
showm.window,
actor_add_blending,
effects=[
fury.window.gl_reset_blend,
fury.window.gl_enable_depth,
fury.window.gl_set_additive_blending,
],
)
fury.shaders.shader_apply_effects(
showm.window, actor_sub_blending, effects=fury.window.gl_set_subtractive_blending
)
fury.shaders.shader_apply_effects(
showm.window, actor_mul_blending, effects=fury.window.gl_set_multiplicative_blending
)
Finally, just render and see the results
counter = itertools.count()
# After some steps we will remove the no_depth_test effect
def timer_callback(obj, event):
cnt = next(counter)
showm.render()
# we will rotate the visualization just to help you to see
# the results of each specific opengl-state
showm.scene.azimuth(1)
if cnt == 400:
fury.utils.remove_observer_from_actor(actor_no_depth_test, id_observer)
fury.shaders.shader_apply_effects(
showm.window,
actor_no_depth_test,
effects=fury.window.gl_set_additive_blending,
)
if cnt == 1000:
showm.exit()
interactive = False
showm.add_timer_callback(interactive, 5, timer_callback)
if interactive:
showm.start()
fury.window.record(
scene=scene, out_path="viz_fine_tuning_gl_context.png", size=(600, 600)
)