.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "_gallery/feature_demo/blending_weighted_plus.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr__gallery_feature_demo_blending_weighted_plus.py: Blending weighted_plus ====================== The 'weighted_plus' was a previously supported blend mode (when blending as defined on the renderer). This example mimics it's behaviour. This scene is particularly difficult to blend correctly, because the planes cannot be sorted by depth, causing classing blending to produce incorrect results. Dither works great although it's noisy. Weighted blending also works, but you don't see where the planes intersect. The idea of weighted_plus is to render transparent objects with weighted blending, except the frontmost layer is actually blended correctly. A bit like depth-peeling but with one layer and using OIT for the rest. .. GENERATED FROM PYTHON SOURCE LINES 19-121 .. image-sg:: /_gallery/feature_demo/images/sphx_glr_blending_weighted_plus_001.webp :alt: blending weighted plus :srcset: /_gallery/feature_demo/images/sphx_glr_blending_weighted_plus_001.webp :class: sphx-glr-single-img .. code-block:: Python from rendercanvas.auto import RenderCanvas, loop import pygfx as gfx import pylinalg as la canvas = RenderCanvas() renderer = gfx.renderers.WgpuRenderer(canvas) scene = gfx.Scene() background = gfx.Background.from_color("#000") sphere = gfx.Mesh(gfx.sphere_geometry(10), gfx.MeshPhongMaterial()) geometry = gfx.plane_geometry(50, 50) plane1 = gfx.Mesh(geometry, gfx.MeshBasicMaterial(color="r", opacity=0.2)) plane2 = gfx.Mesh(geometry, gfx.MeshBasicMaterial(color="g", opacity=0.5)) plane3 = gfx.Mesh(geometry, gfx.MeshBasicMaterial(color="b", opacity=0.7)) plane1.local.rotation = la.quat_from_axis_angle((1, 0, 0), 1.571) plane2.local.rotation = la.quat_from_axis_angle((0, 1, 0), 1.571) plane3.local.rotation = la.quat_from_axis_angle((0, 0, 1), 1.571) scene.add(background, plane1, plane2, plane3, sphere) camera = gfx.PerspectiveCamera(70, 16 / 9) camera.show_object(scene, view_dir=(-1, -2, -3)) controller = gfx.OrbitController(camera, register_events=renderer) scene.add(camera.add(gfx.DirectionalLight())) scene_overlay = gfx.Scene() blend_text = gfx.Text( text="weighted_plus blending", anchor="bottom-left", material=gfx.TextMaterial(outline_thickness=0.3), ) scene_overlay.add(blend_text) screen_camera = gfx.ScreenCoordsCamera() # Give the objects some special treatment ... opaque_objects = [background, sphere] transparent_objects = [plane1, plane2, plane3] objects = opaque_objects + transparent_objects for ob in opaque_objects: ob.material.alpha_mode = "solid" ob.material.depth_compare = "<=" for ob in transparent_objects: ob.material.alpha_mode = "weighted_blend" for ob in transparent_objects: # Clone the material ob.material1 = ob.material ob.material2 = type(ob.material)( color=ob.material.color, opacity=ob.material.opacity ) ob.material1.depth_write = True ob.material1.depth_test = True ob.material1.depth_compare = "<=" ob.material1.alpha_mode = "blend" ob.material2.depth_write = False ob.material2.depth_test = True ob.material2.depth_compare = ">" def animate(): # Render the scene with material 1, to prime the depth buffer renderer.render(scene, camera, flush=False) # Clear the color (not the depth) renderer.clear(color=True) renderer.render(scene, camera, flush=False) # Now render again with material 2, to render fragments behind the first layer, blended. # Note that because of the weird depth test, opaque objects are not rendered very well :( for ob in transparent_objects: ob.material = ob.material2 renderer.render(scene, camera, flush=False) # And now again with material 1, to bring back that first layer. for ob in transparent_objects: ob.material = ob.material1 renderer.render(scene, camera, flush=False) # The overlay renderer.render(scene_overlay, screen_camera, flush=False) renderer.flush() if __name__ == "__main__": print(__doc__) canvas.request_draw(animate) loop.run() .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 0.508 seconds) .. _sphx_glr_download__gallery_feature_demo_blending_weighted_plus.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: blending_weighted_plus.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: blending_weighted_plus.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: blending_weighted_plus.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_ .. only:: html Interactive example ------------------- Try this example in your browser using Pyodide. Might not work with all examples and all devices. Check the output and your browser's console for details. .. raw:: html