DreamWipe

From Unify Community Wiki
(Difference between revisions)
Jump to: navigation, search
(Removing all content from page)
m (Reverted edits by Joseph05408 (Talk); changed back to last version by Casemon)
Line 1: Line 1:
 +
[[Category: Camera]]
 +
[[Category: MonoBehaviour]]
 +
[[Category: JavaScript]]
  
 +
Author: Eric Haines (Eric5h5)
 +
 +
==Description==
 +
Fades from one camera to another, with a wavy distortion effect like those seen in transitions to dream sequences or flashbacks (usually accompanied by cheesy harp music).  Requires Unity Pro.
 +
[[Image:DreamWipe.jpg]]
 +
 +
==Usage==
 +
Make an empty game object, and attach this script to it.  Then drag the two cameras which you want to fade between onto the appropriate slots in the Inspector (the cameras must be in the same scene, of course).
 +
 +
The script has a '''FadeTime''' public variable, which is the time, in seconds, that it will take for the wipe to complete.  '''Resolution''' controls how smooth the effect looks--higher values make for smoother curves, but take more CPU time.  '''WaveScale''' is how large the waves are.  '''WaveFrequency''' is how many waves there are.  '''WaveMotion''' is either Linear or Smooth, the latter of which makes for an ease-in/ease-out effect.
 +
 +
In actual use, you'd want to modify the script slightly: get rid of the Update function, and call DreamWipe() appropriately instead.  See the attached file for an example scene.
 +
 +
Notes:
 +
 +
If you see objects turning transparent or disappearing during the fade when they shouldn't, check the opacity on the color of their materials.  Solid, non-transparent objects should have opacity set to 100%.  This applies to any solid background colors and skyboxes you may be using as well.  They may look fine normally with less opacity, but the rendertexture picks up their alpha and does funky things with it.
 +
 +
Also, doesn't work with "Default-Diffuse" material (created with Unity primitives); replace material with new Diffuse material to work-around.
 +
 +
Any GUIElements (GUITexts and GUITextures) will go wacky during the transition, since they will be picked up by the rendertextures and waved with everything else.  To avoid this, make another camera that only renders GUIElements on top of the other cameras, and nothing else.  If you're using OnGUI, then the GUI won't be affected.
 +
 +
Occasionally the effect doesn't look right in the editor if "Maximize on Play" isn't used for the game window.
 +
 +
<span class="dangerousLink">[[Media:Dreamwipe1.0.zip|Dreamwipe1.0.zip]]</span>‎
 +
<span class="fileInfo"> (151KB, MIME TYPE: <code>application/zip</code>)</span>
 +
 +
==JavaScript - ScreenDreamWipe.js==
 +
<javascript>var cam1 : Camera;
 +
var cam2 : Camera;
 +
 +
var fadeTime : float = 4;
 +
var resolution : int = 60;        // Higher numbers make the effect smoother, but take (a little) more CPU time
 +
var waveScale : float = .07;    // Higher numbers make the effect more exaggerated. Can be negative, .5/-.5 is the max
 +
var waveFrequency : float = 20;    // Higher numbers make more waves in the effect
 +
enum WaveMotion {Linear, Smooth}
 +
var waveMotion = WaveMotion.Smooth;    // Type of motion for waves...Smooth does nice ease-in/out
 +
 +
private var inProgress = false;
 +
private var baseVertices : Vector3[];
 +
private var newVertices : Vector3[];
 +
private var mat : Material;
 +
private var tex1 : RenderTexture;
 +
private var tex2 : RenderTexture;
 +
 +
function Start () {
 +
    mat = new Material (
 +
        "Shader \"Unlit2Pass\" {" +
 +
        "Properties {" +
 +
        "    _Color (\"Main Color\", Color) = (1,1,1,1)" +
 +
        "    _Tex1 (\"Base\", Rect) = \"white\" {}" +
 +
        "    _Tex2 (\"Base\", Rect) = \"white\" {}" +
 +
        "}" +
 +
        "Category {" +
 +
        "    ZWrite Off Alphatest Greater 0 ColorMask RGB Lighting Off" +
 +
        "    Tags {\"Queue\"=\"Transparent\" \"IgnoreProjector\"=\"True\" \"RenderType\"=\"Transparent\"}" +
 +
        "    Blend SrcAlpha OneMinusSrcAlpha" +
 +
        "    SubShader {" +
 +
        "        Material {Diffuse [_Color]}" +
 +
        "        Pass {SetTexture [_Tex2] {constantColor [_Color]}}" +
 +
        "        Pass {SetTexture [_Tex1] {" +
 +
        "            constantColor [_Color]" +
 +
        "            Combine texture * constant, texture * constant" +
 +
        "        }}" +
 +
        "    }" +
 +
        "}}"
 +
    );
 +
   
 +
    // Set up renderer
 +
    gameObject.AddComponent(MeshFilter);
 +
    gameObject.AddComponent(MeshRenderer);
 +
    renderer.material = mat;
 +
 +
    // Create the mesh used for the distortion effect
 +
    var myMesh = new Mesh();
 +
    GetComponent(MeshFilter).mesh = myMesh;
 +
   
 +
    resolution = Mathf.Clamp(resolution, 1, 16380);
 +
    waveScale = Mathf.Clamp(waveScale, -.5, .5);
 +
    waveFrequency = .25/(resolution/waveFrequency);
 +
    baseVertices = new Vector3[4*resolution + 4];
 +
    newVertices = new Vector3[baseVertices.Length];
 +
    var newUV = new Vector2[4*resolution + 4];
 +
    var newTriangles = new int[18*resolution];
 +
   
 +
    var idx = 0;
 +
    for (i = 0; i <= resolution; i++) {
 +
        var add : float = 1.0/resolution*i;
 +
        newUV[idx] = Vector2(0.0, 1.0-add);
 +
        baseVertices[idx++] = Vector3(-1.0, .5-add, 0.0);
 +
        newUV[idx] = Vector2(0.0, 1.0-add);
 +
        baseVertices[idx++] = Vector3(-.5, .5-add, 0.0);
 +
        newUV[idx] = Vector2(1.0, 1.0-add);
 +
        baseVertices[idx++] = Vector3(.5, .5-add, 0.0);
 +
        newUV[idx] = Vector2(1.0, 1.0-add);
 +
        baseVertices[idx++] = Vector3(1.0, .5-add, 0.0);
 +
    }
 +
   
 +
    idx = 0;
 +
    for (y = 0; y < resolution; y++) {
 +
        for (x = 0; x < 3; x++) {
 +
            newTriangles[idx++] = (y*4    )+x;
 +
            newTriangles[idx++] = (y*4    )+x+1;
 +
            newTriangles[idx++] = ((y+1)*4)+x;
 +
 +
            newTriangles[idx++] = ((y+1)*4)+x;
 +
            newTriangles[idx++] = (y    *4)+x+1;
 +
            newTriangles[idx++] = ((y+1)*4)+x+1;
 +
        }
 +
    }
 +
   
 +
    myMesh.vertices = baseVertices;
 +
    myMesh.uv = newUV;
 +
    myMesh.triangles = newTriangles;
 +
    renderer.enabled = false;
 +
       
 +
    // Set up rendertextures
 +
    tex1 = new RenderTexture(Screen.width, Screen.height, 24);
 +
    tex2 = new RenderTexture(Screen.width, Screen.height, 24);
 +
    tex1.isPowerOfTwo = tex2.isPowerOfTwo = false;
 +
    tex1.filterMode = tex2.filterMode = FilterMode.Point;
 +
    tex1.Create();
 +
    tex2.Create();
 +
    mat.SetTexture("_Tex1", tex1);
 +
    mat.SetTexture("_Tex2", tex2);
 +
}
 +
 +
function Update () {
 +
    if (Input.GetKeyDown("space")) {DreamWipe(fadeTime);}
 +
}
 +
 +
function DreamWipe (fadeTime : float) {
 +
    if (inProgress) {return;}
 +
    inProgress = true;
 +
 +
    // Set up cameras
 +
    if (cam1.gameObject.active) {
 +
        var cam = cam1;
 +
        var otherCam = cam2;
 +
    }
 +
    else {
 +
        cam = cam2;
 +
        otherCam = cam1;
 +
    }
 +
    var camera2 = Instantiate(otherCam, otherCam.transform.position, otherCam.transform.rotation);
 +
    if (camera2.GetComponent(AudioListener)) {
 +
        DestroyImmediate(camera2.GetComponent(AudioListener));
 +
    }
 +
   
 +
    // Move camera back a bit so the rendertexture camera won't see the renderPlane
 +
    otherCam.transform.Translate(Vector3.forward * -1.0);
 +
    // Get screen coodinates of 0,0 in local spatial coordinates, so we know how big to scale the plane
 +
    var p = otherCam.transform.InverseTransformPoint(otherCam.ScreenToWorldPoint(Vector3(0.0, 0.0, otherCam.nearClipPlane)));
 +
    transform.localScale = Vector3(-p.x*2.0, -p.y*2.0, 1.0);
 +
    transform.position = otherCam.transform.position;
 +
    transform.rotation = otherCam.transform.rotation;
 +
    // Must be a tiny bit beyond the nearClipPlane, or it might not show up
 +
    transform.Translate(Vector3.forward * (otherCam.nearClipPlane+.000001));
 +
   
 +
    // Initialize some stuff
 +
    renderer.enabled = true;
 +
    var scale : float = 0.0;
 +
    var myMesh = GetComponent(MeshFilter).mesh;
 +
   
 +
    // Switch second camera on and turn on rendertextures
 +
    otherCam.gameObject.active = true;
 +
    cam.targetTexture = tex1;
 +
    camera2.targetTexture = tex2;
 +
 +
    // Do the cross-fade
 +
    for (i = 1.0; i > 0.0; i -= Time.deltaTime / fadeTime) {
 +
        var t = Mathf.Lerp(1.0, 0.0, Mathf.InverseLerp(.75, .15, i));
 +
        mat.color.a = Mathf.SmoothStep(0.0, 1.0, t);
 +
        // Make plane undulate
 +
        for (var j = 0; j < newVertices.Length; j++) {
 +
            newVertices[j] = baseVertices[j];
 +
            newVertices[j].x += Mathf.Sin(j*waveFrequency + (1.0-i)*fadeTime) * scale;
 +
        }
 +
        myMesh.vertices = newVertices;
 +
        if (waveMotion == WaveMotion.Smooth) {
 +
            scale = Mathf.Sin(Mathf.PI * Mathf.SmoothStep(1.0, 0.0, i)) * waveScale;
 +
        }
 +
        else {
 +
            scale = Mathf.Sin(Mathf.PI * i) * waveScale;
 +
        }
 +
        yield;
 +
    }
 +
   
 +
    // Clean up
 +
    otherCam.transform.Translate(Vector3.forward * 1.0);
 +
    renderer.enabled = inProgress = cam.gameObject.active = false;
 +
    Destroy(camera2.gameObject);
 +
    cam.targetTexture = null;
 +
    tex1.Release();
 +
    tex2.Release();
 +
}</javascript>
 +
 +
'''Note''': There is a more flexible and self-contained version of this script in the History circ. July 27th 2008. Original author decided he wanted only his version as the main document (despite this being a wiki), but if you want to check it out the refined version, click History at the top of the page, and the date, then Compare. More specific details in the Discussion page.

Revision as of 19:12, 19 October 2009


Author: Eric Haines (Eric5h5)

Description

Fades from one camera to another, with a wavy distortion effect like those seen in transitions to dream sequences or flashbacks (usually accompanied by cheesy harp music). Requires Unity Pro. DreamWipe.jpg

Usage

Make an empty game object, and attach this script to it. Then drag the two cameras which you want to fade between onto the appropriate slots in the Inspector (the cameras must be in the same scene, of course).

The script has a FadeTime public variable, which is the time, in seconds, that it will take for the wipe to complete. Resolution controls how smooth the effect looks--higher values make for smoother curves, but take more CPU time. WaveScale is how large the waves are. WaveFrequency is how many waves there are. WaveMotion is either Linear or Smooth, the latter of which makes for an ease-in/ease-out effect.

In actual use, you'd want to modify the script slightly: get rid of the Update function, and call DreamWipe() appropriately instead. See the attached file for an example scene.

Notes:

If you see objects turning transparent or disappearing during the fade when they shouldn't, check the opacity on the color of their materials. Solid, non-transparent objects should have opacity set to 100%. This applies to any solid background colors and skyboxes you may be using as well. They may look fine normally with less opacity, but the rendertexture picks up their alpha and does funky things with it.

Also, doesn't work with "Default-Diffuse" material (created with Unity primitives); replace material with new Diffuse material to work-around.

Any GUIElements (GUITexts and GUITextures) will go wacky during the transition, since they will be picked up by the rendertextures and waved with everything else. To avoid this, make another camera that only renders GUIElements on top of the other cameras, and nothing else. If you're using OnGUI, then the GUI won't be affected.

Occasionally the effect doesn't look right in the editor if "Maximize on Play" isn't used for the game window.

Dreamwipe1.0.zip (151KB, MIME TYPE: application/zip)

JavaScript - ScreenDreamWipe.js

<javascript>var cam1 : Camera; var cam2 : Camera;

var fadeTime : float = 4; var resolution : int = 60; // Higher numbers make the effect smoother, but take (a little) more CPU time var waveScale : float = .07; // Higher numbers make the effect more exaggerated. Can be negative, .5/-.5 is the max var waveFrequency : float = 20; // Higher numbers make more waves in the effect enum WaveMotion {Linear, Smooth} var waveMotion = WaveMotion.Smooth; // Type of motion for waves...Smooth does nice ease-in/out

private var inProgress = false; private var baseVertices : Vector3[]; private var newVertices : Vector3[]; private var mat : Material; private var tex1 : RenderTexture; private var tex2 : RenderTexture;

function Start () {

   mat = new Material (
       "Shader \"Unlit2Pass\" {" +
       "Properties {" +
       "    _Color (\"Main Color\", Color) = (1,1,1,1)" +
       "    _Tex1 (\"Base\", Rect) = \"white\" {}" +
       "    _Tex2 (\"Base\", Rect) = \"white\" {}" +
       "}" +
       "Category {" +
       "    ZWrite Off Alphatest Greater 0 ColorMask RGB Lighting Off" +
       "    Tags {\"Queue\"=\"Transparent\" \"IgnoreProjector\"=\"True\" \"RenderType\"=\"Transparent\"}" +
       "    Blend SrcAlpha OneMinusSrcAlpha" +
       "    SubShader {" +
       "        Material {Diffuse [_Color]}" +
       "        Pass {SetTexture [_Tex2] {constantColor [_Color]}}" +
       "        Pass {SetTexture [_Tex1] {" +
       "            constantColor [_Color]" +
       "            Combine texture * constant, texture * constant" +
       "        }}" +
       "    }" +
       "}}"
   );
   
   // Set up renderer
   gameObject.AddComponent(MeshFilter);
   gameObject.AddComponent(MeshRenderer);
   renderer.material = mat;
   // Create the mesh used for the distortion effect
   var myMesh = new Mesh();
   GetComponent(MeshFilter).mesh = myMesh;
   
   resolution = Mathf.Clamp(resolution, 1, 16380);
   waveScale = Mathf.Clamp(waveScale, -.5, .5);
   waveFrequency = .25/(resolution/waveFrequency);
   baseVertices = new Vector3[4*resolution + 4];
   newVertices = new Vector3[baseVertices.Length];
   var newUV = new Vector2[4*resolution + 4];
   var newTriangles = new int[18*resolution];
   
   var idx = 0;
   for (i = 0; i <= resolution; i++) {
       var add : float = 1.0/resolution*i;
       newUV[idx] = Vector2(0.0, 1.0-add);
       baseVertices[idx++] = Vector3(-1.0, .5-add, 0.0);
       newUV[idx] = Vector2(0.0, 1.0-add);
       baseVertices[idx++] = Vector3(-.5, .5-add, 0.0);
       newUV[idx] = Vector2(1.0, 1.0-add);
       baseVertices[idx++] = Vector3(.5, .5-add, 0.0);
       newUV[idx] = Vector2(1.0, 1.0-add);
       baseVertices[idx++] = Vector3(1.0, .5-add, 0.0);
   }
   
   idx = 0;
   for (y = 0; y < resolution; y++) {
       for (x = 0; x < 3; x++) {
           newTriangles[idx++] = (y*4    )+x;
           newTriangles[idx++] = (y*4    )+x+1;
           newTriangles[idx++] = ((y+1)*4)+x;
           newTriangles[idx++] = ((y+1)*4)+x;
           newTriangles[idx++] = (y    *4)+x+1;
           newTriangles[idx++] = ((y+1)*4)+x+1;
       }
   }
   
   myMesh.vertices = baseVertices;
   myMesh.uv = newUV;
   myMesh.triangles = newTriangles;
   renderer.enabled = false;
       
   // Set up rendertextures
   tex1 = new RenderTexture(Screen.width, Screen.height, 24);
   tex2 = new RenderTexture(Screen.width, Screen.height, 24);
   tex1.isPowerOfTwo = tex2.isPowerOfTwo = false;
   tex1.filterMode = tex2.filterMode = FilterMode.Point;
   tex1.Create();
   tex2.Create();
   mat.SetTexture("_Tex1", tex1);
   mat.SetTexture("_Tex2", tex2);

}

function Update () {

   if (Input.GetKeyDown("space")) {DreamWipe(fadeTime);}

}

function DreamWipe (fadeTime : float) {

   if (inProgress) {return;}
   inProgress = true;
   // Set up cameras
   if (cam1.gameObject.active) {
       var cam = cam1;
       var otherCam = cam2;
   }
   else {
       cam = cam2;
       otherCam = cam1;
   }
   var camera2 = Instantiate(otherCam, otherCam.transform.position, otherCam.transform.rotation);
   if (camera2.GetComponent(AudioListener)) {
       DestroyImmediate(camera2.GetComponent(AudioListener));
   }
   
   // Move camera back a bit so the rendertexture camera won't see the renderPlane
   otherCam.transform.Translate(Vector3.forward * -1.0);
   // Get screen coodinates of 0,0 in local spatial coordinates, so we know how big to scale the plane
   var p = otherCam.transform.InverseTransformPoint(otherCam.ScreenToWorldPoint(Vector3(0.0, 0.0, otherCam.nearClipPlane)));
   transform.localScale = Vector3(-p.x*2.0, -p.y*2.0, 1.0);
   transform.position = otherCam.transform.position;
   transform.rotation = otherCam.transform.rotation;
   // Must be a tiny bit beyond the nearClipPlane, or it might not show up
   transform.Translate(Vector3.forward * (otherCam.nearClipPlane+.000001));
   
   // Initialize some stuff
   renderer.enabled = true;
   var scale : float = 0.0;
   var myMesh = GetComponent(MeshFilter).mesh;
   
   // Switch second camera on and turn on rendertextures
   otherCam.gameObject.active = true;
   cam.targetTexture = tex1;
   camera2.targetTexture = tex2;
   // Do the cross-fade
   for (i = 1.0; i > 0.0; i -= Time.deltaTime / fadeTime) {
       var t = Mathf.Lerp(1.0, 0.0, Mathf.InverseLerp(.75, .15, i));
       mat.color.a = Mathf.SmoothStep(0.0, 1.0, t);
       // Make plane undulate
       for (var j = 0; j < newVertices.Length; j++) {
           newVertices[j] = baseVertices[j];
           newVertices[j].x += Mathf.Sin(j*waveFrequency + (1.0-i)*fadeTime) * scale;
       }
       myMesh.vertices = newVertices;
       if (waveMotion == WaveMotion.Smooth) {
           scale = Mathf.Sin(Mathf.PI * Mathf.SmoothStep(1.0, 0.0, i)) * waveScale;
       }
       else {
           scale = Mathf.Sin(Mathf.PI * i) * waveScale;
       }
       yield;
   }
   
   // Clean up
   otherCam.transform.Translate(Vector3.forward * 1.0);
   renderer.enabled = inProgress = cam.gameObject.active = false;
   Destroy(camera2.gameObject);
   cam.targetTexture = null;
   tex1.Release();
   tex2.Release();

}</javascript>

Note: There is a more flexible and self-contained version of this script in the History circ. July 27th 2008. Original author decided he wanted only his version as the main document (despite this being a wiki), but if you want to check it out the refined version, click History at the top of the page, and the date, then Compare. More specific details in the Discussion page.

Personal tools
Namespaces

Variants
Actions
Navigation
Extras
Toolbox