- Home /
Fading in one camera over another as an overlay with RenderTexture and GUI.DrawTexture. Any way to control pixel clearing?
Update: As of now I'm using this script in my project and locking my objects' movement during the transition. This works fine, but solving the original problem would be a more ideal, general solution.
Download example package - RenderTextureQuestionSubmit.unitypackage
I'm trying to use a RenderTexture and GUI.DrawTexture to do a fade-up of a second camera as an overlay. Once the fade is complete, it switches to a live view of both cameras. I have attached screen shots and a unitypackage showing a ghosting problem that I'm getting.
The example fades in a moving foreground over a static background. Once the fade-in is complete, the foreground camera's targetTexture is set to null, causing both background and foreground cameras to be rendered live. The depth-only option for Clear Flags is used on the foreground camera. The Culling mask of the foreground camera is set to a layer called "Foreground" (you'll have to add this yourself as a custom layer if you download the example package) and the gray plane is assigned to that layer. I have included the shader, but I don't think it's the problem here.
The ghosting seems to be caused by a lack of clearing of the RenderTexture between Camera renders. You can see it on the second screen shot: The horizontal ping-pong motion of the gray plane causes the ghosting effect. I tried to fix it by adding a RenderTexture.Release() each frame, but that causes it to appear darker so the ending of the fade doesn't match the live camera when they are swapped, which causes a jump in apparent brightness value. This is easiest to see in the example if you press M to stop moving, and press R to activate Release-each-frame mode. I think the "darkening" is actually fast flicker.
Thanks in advance for any help!
Key script on my "foreground" camera:
public class CameraFadeUpScript: MonoBehaviour {
public Camera thisCamera;
public bool inTransition; public bool releaseEachFrame=false; public float fadeSpeed;
public float alpha = 1.0f;
private RenderTexture renderTex; private Texture tex;
// Use this for initialization void Start () {
}
void OnEnable() {
if (renderTex==null) renderTex = new RenderTexture(Screen.width, Screen.height, 24);
renderTex.Release();
Debug.Log(Time.time + " Enabled");
alpha = 0f;
inTransition = true;
thisCamera.targetTexture = renderTex;
tex = renderTex;
Debug.Log(Time.time + "FG cam enabled");
}
// Update is called once per frame void Update () {
if (Input.GetKeyDown(KeyCode.R))
{
releaseEachFrame = !releaseEachFrame;
}
if (inTransition)
{
alpha = Mathf.MoveTowards(alpha, 1f, Time.deltaTime * fadeSpeed);
alpha = Mathf.Clamp(alpha, 0f, 1f);
Debug.Log(Time.time + "Update: " + alpha);
if (releaseEachFrame)
{
renderTex.Release();
}
tex = renderTex;
if (alpha > 0.99999f)
{
inTransition = false;
thisCamera.targetTexture = null;
renderTex.Release();
Debug.Log(Time.time + "Transition to foreground complete");
}
}
}
void OnGUI() {
if (inTransition && alpha < 1f)
{
GUI.color = new Color(1f, 1f, 1f, alpha);
GUI.DrawTexture(new Rect(0, 1, Screen.width, Screen.height), tex, ScaleMode.StretchToFill, true);
Debug.Log(Time.time + " GUI.DrawTexture");
}
} }
Notes:
- This technique is similar to the CrossFadePro script in the wiki.
- I tried a double-buffering solution with two render textures, where each frame it would alternate between drawing one and Release()-ing one, but this didn't seem to improve upon the darkening observed when you release the rendertexture every frame.
- Side note, I noticed that the transition between GUI.DrawTexture and the live camera looks best if this rectangle is used: Rect(0, 1, Screen.width, Screen.height). Anyone else see a one pixel jump if you use Rect(0, 0, Screen.width, Screen.height)?
Screenshots: