Sign in to follow this  
h_iben

Need opinions on glass refraction shader

Recommended Posts

h_iben    100
Hi everyone - first post in this community...

I have some experience with OpenGL's fixed pipeline and now I'm playing around with GLSL. One effect that I really like from games is the simulated distortion when looking through thick glass (like security glass in Doom 3, the offices in Portal, etc.).

So I spent some time trying to recreate the effect. There are many tutorials out there that show you how to do refraction based on cubemaps but this is not useable as you simply want to modify what you are seeing.
I would like to get some feedback on my approach. I would really like some hints on performance or if am totally running in the wrong direction.

I will describe what I am doing. After that I'll insert a screenshot to make things more clear.
The basic idea is to render the scene without the window-effect into a texture. Then - into a second texture - the window geometry is rendered where the vertex colors represent the texture coordinates for the displacement (normal) map.
Finally the sceneTexture, the texCoordTexture and the normal map are bound to individual texture units and a full screen quad is drawn that would render the sceneTexture.
At this point a shader creates the window-effect: the vertex shader only does the fixed pipeline stuff (transform vertex, set texture coords). The important step happens in the fragment shader:
The texture coordinate is used to lookup the color in the texCoordTexture. This color encodes two things: a) if the pixel belongs to the window (z/b part) and b) the location of the normal. So if it is part of the window, look up the normal and scale it down to limit the displacement. Final color is then determined by adding the scaled normal to the original texCoord and looking up the color in the sceneTexture.

This is the fragment shader:
[code]
uniform sampler2D tex;
uniform sampler2D disptc;
uniform sampler2D disp;

void main(void) {
vec3 dispnormal;
vec3 displace;
vec2 tcfragment = gl_TexCoord[0].st;
vec3 disptc = texture2D(disptc, tcfragment).xyz;

if(disptc.z == 0.0) {
discard;
} else {
dispnormal = normalize(texture2D(disp, disptc.xy).xyz);
dispnormal = dispnormal * 2.0 - 1.0;
displace = dispnormal * 0.035;

vec4 color = texture2D(tex, tcfragment + displace.xy);
gl_FragColor = color;
}
}
[/code]

Here is a screenshot of the shader in action:

[img]http://imageshack.us/m/691/9586/glassshader.png[/img]

The upper part is the scene, below you see the sceneTexture (without window) and the texCoordTexture. The scene consists of a hollow cube (wall thickness 1.0) and the window has a small border (not on floor level). Inside is a 'poster' (quad with a texture) and a Teapot.

One thing that bothers me: The shader acts on an image that is drawn on a full-screen quad. This makes including highlights a bit difficult as it seems. Currently I think this can be solved with even more textures that store the needed info but maybe someone knows a better way ?

I would really like some feedback on this. Maybe there even is a guide for this kind of effect that I could not find...

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this