Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create Depth Fade effect in OpenGL?

I would like to create a translucent sphere, which is highlighted where it intersects other objects (for example the ground).

Like the white line in this picture:

image

I've found an Unreal Engine 4 tutorial about how to create something like that.

It uses "depth fade" in the shader. Unfortunately I haven't found any OpenGL tutorial about Depth Fades.

How is it possible to create an effect like this?

like image 636
U Ack Fin Avatar asked Mar 09 '23 03:03

U Ack Fin


1 Answers

Sure. I don't know exactly what Unreal means by it, but the general idea is as follows.

First, you need a readable depth buffer. This means either do a depth-prepass, or just render this special effect after you've rendered the opaque objects in the scene (the ones against which you want this sphere to intersect). I will assume that you know or can figure out how to create and use your own depth buffer so that you can read it back in the later steps. You will not be able to use GL's default depth buffer for this (so you will require a framebuffer object, color attachment, depth attachment).

Now, let's talk about rendering the sphere. In your vertex shader, you will need to:

  • Transform your vertex as usual
  • After transformation, write the depth value of the vertex to a varying (you'll need it in the fragment shader)

So the purpose of your vertex shader is to compute your sphere's scene depth and pass it to the fragment shader.

In the fragment shader, this is where you do the meat of the technique. You need to bind your readable depth buffer to a uniform sampler2D. Then:

  • Sample the depth buffer at the current screen position
  • Compute the sceneDepth - currDepth, where currDepth is the varying that you passed in from your vert shader, and sceneDepth is the value that you sampled from the depth buffer
  • Apply some math however you like to obtain an effect from this difference. For a very rough example, float effectAlpha = exp(-k * max(0.0, sceneDepth - currDepth)); k here controls how quickly it fades out. You can then add some color, for example, and multiply it by effectAlpha.

The point, ultimately, is that you're computing the effect based on a difference between the rendered geometry's depth and the occluding scene's depth. Hence 'depth fade.' Similar techniques are used, for example, to make water appear to smoothly fade into a coastline.

EDIT: I just glossed over the tutorial and noticed he also uses a Fresnel effect. That's giving some highlight at glancing angles. If you do a search for Fresnel effect GLSL, it should be easy to find sources -- Fresnel is ubiquitous in rendering, especially in physically-based rendering. Basic idea is that you'll be computing a value that is 0 where your object 'faces' the camera ('faces' meaning has a normal vector aligned with the direction to the camera), and 1 where your object faces a direction orthogonal to the camera.

It actually doesn't appear that the fresnel is very visible in the screenshot you posted (fresnel is a very slight effect as it fades roughly like a 5th-degree polynomial), so you can probably achieve most of what you want with the depth fade alone.

like image 134
Josh Parnell Avatar answered Mar 21 '23 10:03

Josh Parnell