Friday, September 16, 2011

Reflective water with GLSL, Part I

Being it for physical accuracy or setting mood in game, water and reflections are something that can add lot to your rendering engine. While true reflections can only be done with ray-tracing, one can achieve surprisingly nice approximations by using quite simple scene setup and some GPU programming.

Good water simulation should have at least the following features:
  • True reflection (with correct parallax)
  • Clipping of underwater objects on reflection image
  • View angle dependent transparency/reflectivity of water
  • Ripples and/or waves
  • Water scattering (i.e. water becoming gradually opaque as depth increases)
 Some more things, that can make things nicer but are not as visible, are:
  • Refraction
  • Caustics - i.e. light spots at the bottom of shallow water
  • Reflected light - i.e. light spots reflected to objects near water
At moment I have only implemented features from the first list into Khayyam/Sehle/Shinya code. You can look at my previous post for some in-engine images.
Here I will describe the mathematics behind the scenes and give step-by-step guide to writing your own water system/object/rendering pass.

1.Rendering reflection texture

Water without reflection looks totally uninteresting - just like any other semitransparent surface. Thus we start from implementing reflection and later go on to other effects.

1.1. Parallax
Even if you have until now managed to render you scene in single pass, from this point on you need at least two passes (actually at least N+1, where N is the number of visible reflective surfaces).

The reason is, that unfortunately we cannot recycle our main scene image for reflections. First because it could make view frustum insanely large (for example - if viewing the water surface from high angle we see only ground and water in our main view, but mostly sky in reflection). And second because of parallax. The reflection is unfortunately not the perfect copy of reflected scene, but copy of the view of the same scene from different viewpoint. The following image illustrates this.

A diagram explaining the parallax effect on reflected image

It means that you need to have rendering to texture set up and working. We will render reflection to texture and later use this texture while rendering the water surface in main scene.

Thus, to get reflection texture we first have to render our scene from the reflected camera viewpoint  P' to texture. First we have to find the reflected camera position - or more precisely the reflected view matrix (because we need camera orientation too in addition to the position).
This can be done with the following formula:

M'camera = Mreflection * Mcamera

Where Mreflection is the reflection matrix of mirror surface. It can trivially be calculated from the position of reflection plane:

              | 1-2Nx2   -2NxNy  -2NxNz  -2NxD |
Mreflection = |  -2NxNy 1-2Ny2   -2NyNz  -2NyD |
              |  -2NxNz  -2NyNz 1-2Nz2   -2NzD |
              |    0       0       0       1   |

Where (Nx,Ny,Nz,D) are the coefficients of plane equation (xNx + yNy + zNz + D = 0). Notice, that (Nx,Ny,Nz) is also the normal vector of given plane.

Mcamera is the transformation of camera as if it would be "normal" object in scene. To get ModelView matrix you will need the inverse of it.

1.2. Mirrored geometry
Actually we cheated a little in the previous image. We rotated the mirrored image 180º to make it more similar to the original image, so the effect of parallax can be seen. The actual mirrored image looks like this:
Different winding order on mirrored image
Notice, that the winding order of polygons in image is flipped on mirrored image - i.e. the triangle is oriented CCW on original but CW on reflection.

This may or may not be problem for you. If all your materials are double sided (i.e. you do not do back face culling) or if you can set up rendering pipeline in such a way, that you can change culling direction it is OK. In my case though, I prefer to keep culling always on and have forward-facing always defined as CCW. So something has to be done with the reflected image - or otherwise geometry will not render properly.

We will exploit the feature that camera is always (at least in most applications) rectangular and centered around view direction. Thus we can just flip camera in Y direction and the winding order will be correct again (it flips reflected image so it looks like (3) on the first picture).
This can be done with one more reflection matrix:

M''camera = Mreflection * Mcamera * Mflip

Where Mflip is simply another reflection matrix that does reflection over XZ plane.
Now if we render mirrored image using M''camera as camera matrix, pipeline can be left intact. We, of course, have to save this matrix for later reference, because it is needed to properly map our texture to water object in main render stage.

1.3. Underwater clipping
Take a look at the following picture:
A reflection with underwater object

We have added an underwater object Q to our scene. Now it should not appear on reflection, because it does not block the actual reflection rays PB'B and PA'A. But we are not doing ray-tracing. We are instead moving camera to mirrored viewpoint P' and rendering reflection like normal image. But as you can see, the object Q blocks ray P'A'A and thus would show up in our reflection.

Thus we have to make sure, that nothing that is under the reflection plane (water surface) will show up in mirror rendering. This can be achieved in three different ways:
  1. Use additional clipping plane on GPU. It can be very fast or very slow - depending on card and driver used.
  2. Use oblique projection matrix during reflection rendering. You can read more about it here. This is cool technique, but personally I have never got it to work well enough because it messes up camera far plane.
  3. Clip manually in pixel shaders. It wastes some GPU cycles, but is otherwise easy and foolproof.
I went with option (3) because oblique projection matrix did not seem to play well with wide camera angles (far plane moved through infinity creating all kinds of weird effects). The clipping itself is as easy as adding the following code at the beginning of all pixel shaders (or more precisely the ones that are used for reflectable objects):

uniform vec4 clip_plane;
varying vec3 interpolatedVertexEye;

void main()
    float clipPos = dot (interpolatedVertexEye, + clip_plane.w;
    if (clipPos < 0.0) {

Of course you have to supply your shader with clip_plane and calculate interpolatedVertexEye in vertex shader (it is simply vertex coordinate in view/eye space: VertexEye = Mmodelview * Vertex). If you do not need clipping, simply set clip_plane normal (xyz) to zero and all pixels will be rendered.

1.4. Putting it all together
Before starting the main render pass (being it forward or deferred) do the following:
  1. Create list of all objects that need reflections (and the parameters of all reflection planes). Then for each reflection plane:
  2. Calculate the reflected camera matrix
    M''camera = Mreflection * Mcamera
    * Mflip
  3. Set up camera matrices (you can optimize rendering by using clipped projection matrix, but this will not be discussed here).
  4. Set clipping plane to reflection plane
  5. Render full scene
  6. Save the rendered image as texture to be used with reflective object
If you are using HDR you should not tone-map reflection texture - unless you want to achieve some very specific effect.
2. Rendering reflective object

This is actually quite easy - provided that you have at hand all necessary parameters. You have still to decide at which render stage to do this. I use transparent stage, as water is basically just one semi-transparent surface in scene, but you can add another pass before or after transparency as well.

You will need at hand:
  • Reflected camera matrix M''camera
  • Projection matrix you used to render reflection Mprojectionreflection (normally this is the same projection that you use for main camera)
  • Reflection texture

2.1. Vertex shader

attribute vec3 vertex;

uniform mat4 o2v_projection;

varying vec3 interpolatedVertexObject;

void main()
	gl_Position = o2v_projection * vec4(vertex.xy, 0.0, 1.0);
	interpolatedVertexObject = vertex;

We add another constraint here - water surface will be at XY plane of the object local coordinate system. It is strictly not necessary if you have the proper reflection plane, but I found it easier that way. Just use XY plane as reflection plane and place your object (water body) appropriately.

Actually this allows us to do another cool trick. We can use the bottom of water body (i.e. river, lake..) as our water object. It will be flattened in shader, but we can use the Z data to determine the depth of water at given point. But more about this in next part. 

o2v_projection is simply my name for composite matrix Projection * ModelView. I prefer to name matrices with mnemonic names, describing the coordinate system transformations they do - in given case it is Object To View, multiplied with Projection. 

interpolatedVertexObject is simply vertex coordinate in object local coordinate system - we will need it to do lookup onto reflection texture.

2.2. Fragment shader

uniform mat4 o2v_projection_reflection;
uniform sampler2D reflection_sampler;

varying vec3 interpolatedVertexObject;

void main()
	vec4 vClipReflection = o2v_projection_reflection * vec4(interpolatedVertexObject.xy, 0.0 , 1.0);
	vec2 vDeviceReflection = / vClipReflection.q;
	vec2 vTextureReflection = vec2(0.5, 0.5) + 0.5 * vDeviceReflection;

	vec4 reflectionTextureColor = texture2D (reflection_sampler, vTextureReflection);

	// Framebuffer reflection can have alpha > 1
	reflectionTextureColor.a = 1.0;

	gl_FragColor = reflectionTextureColor;

o2v_projection_reflection is the composite matrix Projection * ModelView as it was used during reflection rendering. I.e:

Mprojectionreflection * (M''camera)-1 * Mobject

Like the name implies, it transforms from the object coordinate system to the clip coordinate system of reflection camera.

In fragment shader we simply repeat the full transform pipeline during reflection rendering and use final 2D coordinates for texture lookup. For this we need initial, untransformed object vertices - thus they are interpolated from vertex shader (interpolatedVertexObject).

I'll set reflection alpha to 1.0 because I use HDR buffers and due to additive blending the final alpha can have some very weird values there.

And the rendered image:

Simple scene from Shinya showing water as perfect mirror

Not very realistic?
Up to now we have implemented water as perfect mirror. This is very far from reality (look at the feature list in the first section).

In the next parts I will show how to add viewing angle based transparency, water color and depth-dependent ripples to your water.

Have fun!


  1. Hello, thanks a lot for this tutorial ! It was clear and it's the most up-to-date I could find :)

    However I've got a remark about this part for the reflected matrix :

    "M'camera = Mreflection * Mcamera"

    Using the GLM lib to handle the matrices, I got more luck using :

    "mat4 reflectedView = camera->viewMatrix * reflectionMat;"

    instead. Also, what about this line :
    "To get ModelView matrix you will need the inverse of it." ? I don't think any inverse was needed.

    Anyway I got my reflection working and I am heading to part ii :)

  2. A big thank you from me as well. This explanation is the most comprehensive I found yet and it's helping me a lot on my own water rendering project.

  3. While true reflections can only be done with ray-tracing, one can achieve surprisingly nice approximations by using quite simple scene setup and some GPU programming. Plumbing Judge

  4. This comment has been removed by the author.

  5. This comment has been removed by the author.

  6. This comment has been removed by the author.

  7. This comment has been removed by the author.

  8. This comment has been removed by the author.

  9. Your website content is fabulous and awesome but I would like to say your website also good. Thanks for sharing... Keep it up..
    Before general look Packers and Movers Chennai gear you ought to assess the manuals of the hardware. It is huge assess the same before #moving, in admiration to #move particular things safely.
    Packers And Movers Chennai

  10. ما تهتم به شركة كشف تسربات المياه بالرياض هو البحث عن كيفة علاج مشاكل تسريبات المياه التي تطرأ علي المكان فجأة بواسطة اجهزة الكشف الحدية التي تستخدمها شركة كشف تسربات بالرياض والتي تسعي للوصول الي افضل النتائج المثالية القادرة علي حل هذه المشكلة بدون تدمير فالاعتماد علي الاساليب الحديثة يساعدكم في الحصول علي نتيجة مثالية في مصلحة العميل فنحن لا نكتفي بتقديم هذه الاعمال في مدينة الرياض فقط بلا لدينا الفنين المتميزة الذي يقدمون شركة كشف تسربات المياه بالدمام التي تعمل علي حل مشكلة البيت بدون الاعتماد علي ا اساليب تقليدية التي تستخدما بعض مقدمي خدمة شركة كشف تسربات بالدمام فلا تتكايل بشأن هذا العمل بالذات لانه يحل لك الكثير من المشاكل

  11. i cannot truly enable but admire your weblog, your weblog is so adorable and great.It has given me courage to try scarier things. I tend to steer clear of them but not anymore.
    Packers And Movers Bangalore
    Packers And Movers Bangalore
    Local Packers and Movers Bangalore list, Cheap Packers Movers Bangalore Charges, Affordable Household Shifting Bangalore.

  12. شركة تتميز بجميع الخبرات في تقديم اعمالها المتميزة في الكشف عن التسريبات من خلال شركة كشف تسربات المياه بجدة التي تعطي كل ما لديها في اصلاح العديد من المشاكل التي تحدث نتيجة كسر او عطل مفاجئ في امدادت المياه لذلك ننصحم ان تعتمد علي شركة كشف تسربات بجدة لديه سباكين وفنين لديهم الخبرة في حل هذه المشكلة بكل سهولة كما نمتلك لديها القدرة علي تنفيذ اعمال العوازل من خلال شركة عزل اسطح بالرياض التي تعالج تسريبات المياه في الاسقف والحوائط كما نقدم خدمة العزل السليمة للخزانات الارضي والعلوي الخرسانية بواسطة فني متميزة لديه القدرة علي معالجة كل ذلك بسهولة من خلال شركة عزل خزانات بالرياض تمتلك مواد ذات جودة متميزة

  13. العاب بنات يحتوي موقعنا على تشكيلة من العاب تلبيس بنات متجددة باستمرار وكل مايتعلق بصنف العاب بنات تلبيس ومكياج والعاب طبخ ومرحبا بكم في العاب تلبيس
    العاب بنات و العاب تلبيس
    العاب طبخ al3ab-banat01


  14. In the name of God the Merciful We in the light of UK companies offer the best services in all cleaning Katenziv in apartments , boards and cabinets and Villas
    شركة نور المملكة
    شركة تنظيف بمكة
    And also we provide insect control for all insects flying and crawling and rat extermination
    شركة مكافحة حشرات بجازان
    We also offer moving furniture needed by everyone because of the expiration of the lease time or travel service
    شركة الصفرات لنقل الاثاث بالرياض
    And safety and God's mercy and blessings
    كما يوجد لدينا ايضا تنظيف المجالس والكنب والسجاد والموكيت باحدث الطرق الموجودة وافضل المواد التى تقضى البقع والاوساخ
    شركة تنظيف مجالس وكنب بحائل
    شركة تنظيف سجاد وموكيت بحائل
    وكل هذا بانسب الاسعار واقل التكلفة ونحن نعمل فى خدماتكم 24ساعه


  15. بسم الله الرحمن الرحيم نحن فى شركة الكمال نقوم بكشف التسربات من خلال امببة هواء مزواده بالعداد هواء كما يوجد لدينا جهاز الكترنى يكشف عن طريق التزبزبات
    شركة كشف تسربات المياه بالطائف
    شركة كشف تسربات بالطائف
    شركة كشف تسربات المياه بجازان
    شركة كشف تسربات بجازان
    شركة كشف تسربات المياه بحائل
    شركة كشف تسربات بحائل
    والسلامة عليكم ورحمة الله وبركاته

  16. There's a lot of interesting info here! I'm very grateful for the post! movers and packers Bangalore is here to make your life simpler
    Packers And Movers Bangalore

  17. An excellent information provided thanks for all the information i must say great efforts made by you. thanks a lot for all the information you provided.
    Packers And Movers Pune

  18. I agree with you. This post is truly inspiring. I like your post and everything you share with us is current and very informative, I want to bookmark the page so I can return here from you that you have done a fantastic job.
    Packers And Movers Bangalore to hyderabad

  19. very good post which I really enjoy reading. It is not every day that I have the possibility to see something like this.
    Packers and Movers Mumbai
    Packers and Movers Mumbai

  20. This blog is so nice to me. I will continue to come here again and again. Visit my link as well. Good luck
    obat aborsi
    cara menggugurkan kandungan
    cara menggugurkan kandungan

  21. Search of movers packers in your city has become very simple now!
    Best Movers Packers Mumbai

  22. Thanks for accepting the comment. And help to publish my site.شركة-تنظيف-بالرياض/
    كافة أعمال النظافة العامة للمنازل تقدمها شركة تنظيف فلل بالرياض من تنظيف للسراميك او البلاط ومجالس أرضية والموكيت والسجاد مع التعطير بافضل المواد التنظيف، باحدث الماكينات مع التنظيف نظافة الوجهات الزجاجية. تلميع أرضيات السيراميك. تنظيف خزانات.رش مبيدات بالرياض .مكافحة الحشرات بكل انواعهاشركة-تنظيف-موكيت-بالرياض/شركة-تنظيف-خزانات-بالرياض/شركة-تنظيف-مساجد-بالرياض/شركة-تسليك-مجارى-بالرياض/

  23. Pipeline construction temporary workers are occupied with work that includes the establishment, repair, or substitution of underground pipes. pipeline service provider

  24. Packers and Movers Chennai Give Safe and Reliable ***Household Shifting Services in Chennai with Reasonable ###Packers and Movers Price Quotation. We Provide Household Shifting, Office Relocation, ✔✔✔Local and Domestic Transportation Services, Affordable and Reliable Shifting Service Charges @
    Packers And Movers In Chennai Local

  25. Very Nice Article to read. Blog articles helped me alot in many ways to find the good solution. Am very happy to comments here. Thanks for sharing this kind of wonderful article in this blog. Lovely ! CCTV Camera Supplier MATRIX dealers

  26. While it is past the extent of this article to talk about each framework, a couple of proposals can be tended to. Each HVAC framework part has expanded in proficiency throughout the years. heating repair somers

  27. This can prompt maltreatment as the expert in your home turns out to be all the more a salesperson rather than a plumber. southbury plumber

  28. Information from this blog is very useful for me, am very happy to read this blog Kindly visit us @ Luxury Watch Box | Shoe Box Manufacturer | Luxury Cosmetics Box

  29. Packers and Movers Indore - Call 09303355424, Local Household Shifting in Indore, Domestic Home Relocation from Indore. International Home Relocation from Indore, Office Shifting within Indore, Car and Bike Transportation from Indore, Safe Packing and Moving Services,
    Packers and Movers Indore
    Packers and Movers Gurgaon
    Packers and Movers Kolkata
    Packers and Movers Mumbai
    Packers and Movers Delhi
    Packers and Movers Jaipur
    Packers and Movers Raipur
    Packers and Movers Pune
    Packers and Movers Ahmedabad
    Packers and Movers Indore Blog

  30. Thanks for sharing this blog, this blog is very helpful information for every one.

  31. The post is written in very a good manner and it contains many useful information for me. Thank you very useful information admin, and pardon me permission to share articles here may help :

    risa herbal
    cara menghilangkan benjolan
    toko obat herbal sapnudin
    sehat dan cantik alami
    khasiat obat herbal
    cara menghilangkan bekas jerawat

  32. This comment has been removed by the author.

  33. The class today has become the happiest person I managed to find a part-time job at home and I really get interesting?
    fine no deposit bonus casinolist you can not thank

  34. Packers and Movers in Delhi-We Have a core expertise of twenty years during this field we have a tendency to worth your merchandise in Transfering your merchandise from one location to a different.

  35. We are a well-reputed and elite independent escort services in Gurgaon, who offers top notch services for esteemed gentlemen who never settle down for just fine, but seek the ultimate
    Gurgaon Escorts Agency
    Independent Female Escorts in Gurgaon

  36. Book Best and Verified packers and movers in Pune, Expert in Home Relocation within or outside Pune. Compare 3 quotes from nearby packers and movers in Pune. Get 100% safe & affordable packing moving from Professional Packers and Movers.

    Packers and Movers Pune

  37. Hiring packers and movers in Gurgaon is not too hard if you take help of the best moving professionals. Best movers and packers Gurgaon assist with their skilled and trained team to pack, load, unload and unpack your belongings.
    So be aware and hire the best mover packer to save your valuables.
    packers and movers Gurgaon
    packers and movers Gurgaon Charges

  38. Nice to be visiting your blog again, it has been months for me. Well this article that i’ve been waited for so long. I need this article to complete my assignment in the college, and it has same topic with your article. Thanks, great share :

    pengobatan cacar alami
    manfaat sari kurma untuk kesehatan
    cara mengobati batu empedu
    obat hidung mimisan disertai sakit kepala
    obat hernia alami
    obat penghilang benjolan di pipi
    pengobatan radang empedu

  39. Your article had provided me with another point of view on this topic. I had absolutely no concept that things can possibly work on this manner as well. Thank you for sharing your opinion

    cara mengatasi sembelit berkepanjangan secara alami
    obat rematik pada kaki alami
    obat nyeri tulang pinggang yang ampuh dan aman
    cara menurunkan trombosit tinggi dengan cepat

  40. I Saw Your Website Carefully. Thanks For Create Such Kind of Informative Website. Your All Content Is Relevant To Your Subject. I Say Keep It Continue, Because Your Website And Subject Is Meaningful For The Users. I Have Recommended Your Website With My Friends Also.
    I Am Ritu Sharma. I Deal In Mumbai Escorts Service . I Am Very Hot And Sexy. I Have Five Years’ Experience. That’s why I Understand the Each Personal Needs of My Every Client. My Service Charge Is Low And Service Is Super. You Can Avail My VIP Escorts Service At Your Home Or In Hotel. I Am Comfortable To Provide Escorts Service In Local And Outside Also.
    Visit Call +91- 9OO4OO9481
    Visit The Links Below And Have A Look At My Various Mumbai Escort Services-
    Mumbai Escorts
    Mumbai Call Girls
    Juhu Escorts
    Andheri Escorts
    Bandra Escorts
    Mumbai Escorts In Vile Parle
    Mumbai Escorts In Colaba

  41. I Am Thankful To You For Create Such Kind Of Informative Website. Really It Is Useful According Your Current Topic. I Suggest To Keep This Continue For Those People, Who Are Looking For Such Kind Of Niche. After See Your Niche I Have Recommended Your Website With My Friends Also.
    My name is Arpita Jain. I run my independent Mumbai Escorts Service. I am an independent Mumbai escort girl. My service charge is low according the current market price. My service is super, because I know very well the personal requirement of my each customer. I am comfortable to provide my Mumbai Escorts Service at your home or in Hotel. Visit- Call- +91 9OO4458359
    Visit The Links Below And Have A Look At My Various Mumbai Escort Services-

    Mumbai Escorts Service

    Juhu Escorts
    Mumbai Call Girls
    Escort Service In Mumbai
    Andheri Escorts
    Bandra Escorts