imagination XD

realizing dream

[Research] Unity Underwater Caustic Effect


I can't see the caustic effect clearly. That's why this is still just a research.

I can’t see the caustic effect clearly. That’s why this is still just a research.

Hello everybody, yeah I’m a bit late. I was promised that I’ll give Underwater Caustic Effect on this thread. So yeah, it was simple enough to create this Caustic Effect. It only use Directional Light’s cookie or Projector. For the water, I use Reflective>Bumped Specular. You can create double-sided by adding ” Cull Off ” on Reflective>Bumped Specular shader, but if you are lazy to add it, you can duplicate the water mesh and mirror it (Original(Quad) : 90,0,0, doubleSided : -90,0,0).

1. Go make a new JavaScript and then attach it to your water mesh. Your player also need to be tagged as “Player”. You’ll need this

#pragma strict

var scrollSpeed = 0.25;
var waterCausticSpeed = 2;
var isWater = true; // Just set it true.

var cubeMap : Cubemap;
var causticTextures : Texture;
var causticSize = 10.0;

private var entered = false;
private var awakeFogCol : Color;
private var awakeFogDense : float;
private var defSky : Material;
private var lungColor =;
private var causticator : GameObject;

function Awake () {

        awakeFogCol = RenderSettings.fogColor;
        awakeFogDense = RenderSettings.fogDensity;
        defSky = RenderSettings.skybox;



function FixedUpdate(){
    var offset = Time.time * scrollSpeed;
    renderer.material.mainTextureOffset = Vector2(0,-offset);
    renderer.material.SetTextureOffset("_BumpMap", Vector2(0,-offset));

    if(isWater && entered){
        /*lungCapacity -= 0.5;
        if(lungCapacity < 125) lungColor = Color.yellow;
        if(lungCapacity < 50) lungColor =;
        if(lungCapacity <= 0)player.ApplyDamage(1);*/


function OnTriggerEnter(col : Collider){    
    if(col.gameObject.tag == "Player" && isWater){
        entered = true;
        RenderSettings.fogColor = Color(0,0.4,0.7,0.6);
        RenderSettings.fogDensity = 0.1;


function OnTriggerExit(col : Collider){
    if(col.gameObject.tag == "Player" && isWater){
        entered = false;
        RenderSettings.fogColor = awakeFogCol;
        RenderSettings.fogDensity = awakeFogDense;


function CreateCaustic(){
    causticator = new GameObject("Causticator");
    causticator.light.type = LightType.Directional;
    causticator.light.intensity = 0.5;
    causticator.light.color = Color(0.5,0.5,0.5);
    causticator.light.cookie = causticTextures;
    causticator.light.cookieSize = causticSize;
    causticator.transform.rotation.eulerAngles = Vector3(90,0,0);

2. After that, You’ll need Loopable Caustic Texture, you can find it on Google.

3. And then import that texture to Unity, remember to enable Alpha from Grayscale.

4. Also, remember to add Triggered BoxCollider on water mesh. Make sure that Box Collider Size covered all ground, but you also need to adjust the center of Y Axis because You don’t want an obvious transition, do you ?

As you can see, the Box Collider was offset-ed from water mesh. So it'll give you a nice transition.

As you can see, the Box Collider was offset-ed from water mesh. So it’ll give you a nice transition.

5. Finally, you just have to adjust all those thing until you fully satisfied.

6. So, you want to use Projection Method ? Well… Create empty Game Object, Add Projector to it, set it to Orthographic projection, set the rotation to 90,0,0. After that adjust the size until you happy. But you’ll need a Light Projection Shader (You can obtain it on Assets > Import Package > Projector). Create new material with Light Projection Shader, insert Caustic Texture to Cookie and Falloff Texture to Falloff. Use the script to rotate it.

So what’s the best ? What should i choose ?
Here’s the comparison between Directional Light Method and Projector Method

Directional Light

  • Quick, fast, and easy to use.
  • All area included.
  • Sometimes causes Obvious Transition.
  • My eyes! Too bright! The intensity must be high, if low, you wouldn’t be able to see the caustic.


  • OK transition (No screen brightening)
  • You don’t need to adjust the intensity, you’ll always be able to see the caustic.
  • Difficult, Requires High patience, and High Accuracy.
  • You have to adjust the projection area.


Started making games since 13 year old. 3D CGI Weeaboo | VFX Otaku | Anime Researcher | Indie Game Dev | VR Chuunibyou

3 thoughts on “[Research] Unity Underwater Caustic Effect

  1. Pingback: [Shader] Reflective Transparent / Water-like Unity Indie | imagination XD

  2. Please help, i understand this post is old but i keep getting this error…Unknown identifier error for:

    • ah yes, i forgot, just delete this two line ply = GameObject.FindWithTag(“Player”).GetComponent(HeroCtrl);
      player = GameObject.FindWithTag(“Player”).GetComponent(PlayerCore);

      and add isWater = true; below #pragma strict

      thanks for reminding


Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s