How to Render 3D Models with Transparent Surfaces


GeeXLab - 3D Models with Transparent Surfaces



Downloads

How to run the demo?
Download and unzip GeeXLab and the demopack where you want, launch GeeXLab and drop the demo (main.xml) in GeeXLab. This demo requires OpenGL 2.1+.

 
New functions have been added in GeeXLab 0.48 to help the rendering of meshes and 3D models with transparent surfaces.

The rendering of objects with opaque and transparent surfaces is usually done as follows:
1/ sort opaque and transparent surfaces in two lists.
2/ render opaque surfaces
3/ disable depth test writes and enable color blending
4/ render transparent surfaces

When the 3D model is designed with rendering in mind, transparent surfaces are transparent meshes and the material attached to a particular mesh should have the opacity property: 1.0 for opaque surface or less than 1.0 for transparent surface.

If you have such a 3D model, here is how to load and initialize it with GeeXLab. Let’s load a glTF object:

init.lua

...

num_opaque_meshes = 0
num_transparent_meshes = 0

model_directory = demo_dir .. "/data/old_lantern/"
resource_directory = demo_dir .. "/data/old_lantern/"
gltf_file ="scene.gltf"

model = gh_model.create_from_file_loader_gltf(gltf_file, model_directory, resource_directory, "")

opacity_threshold = 1.0
gh_model.update_meshes_lists(model, opacity_threshold)
  
num_opaque_meshes = gh_model.get_num_opaque_meshes(model)
num_transparent_meshes = gh_model.get_num_transparent_meshes(model)
print(string.format("num_opaque_meshes: %d - num_transparent_meshes: %d", 
                     num_opaque_meshes, num_transparent_meshes))

...

 
In the init script you can also change by yourself the opacity of a material using the gh_material.set_opacity() function. This function takes two parameters: the ID of the material (from the material name –artists: don’t be lazy and give proper names to your materials!) and the opacity value (between 0.0 and 1.0). In the demo, the old lantern has a material for the glass: lambert2SG:

lambert2SG_mat = gh_material.getid("lambert2SG")
gh_material.set_opacity(lambert2SG_mat, 0.5)

 
Now the model is ready to be rendered:

frame.lua

...
gh_renderer.clear_color_depth_buffers(0, 0, 0, 1, 1)

gh_gpu_program.bind(lighting_prog)

gh_model.render_opaque_meshes(model)

if (num_transparent_meshes > 0) then
  gh_renderer.set_depth_mask(0)
  gh_renderer.set_blending_state(1)
  gh_renderer.set_blending_factors(BLEND_FACTOR_SRC_ALPHA, BLEND_FACTOR_ONE)

  gh_model.render_transparent_meshes(model)

  gh_renderer.set_blending_state(0)
  gh_renderer.set_depth_mask(1)
end

...

 
You can play with these functions in the following demo of the OpenGL 2.1 demopack:
geexlab-demopack-gl21/d64-loader-object-gltf/demo-02/main.xml

 
If you’re unlucky, the 3D model has one mesh, one material (with a random name of course) and the opacity is stored in the alpha channel of the unique texture! In that situation, there is a way to render opaque and transparent faces. The technique works but is far from perfect.

The technique is based on the following multipass algorithm:
1/ first pass: z-pass. Disable writes in the color buffer and render the model in the depth buffer only.
2/ second pass: opaque pass. Enable writes in the color buffer, set depth test to LESS_OR_EQUAL, enable color blending
and render the opaque meshes.
3/ third pass: transparent pass. Keep the same render states and render the transparent meshes.

A demo that shows this technique is available in the GL 2.1 demopack here:
geexlab-demopack-gl21/d64-loader-object-gltf/demo-03/main.xml





Leave a Comment

Your email address will not be published. Required fields are marked *