x


When does RenderTexture.active = myRT work?

Hello!

I've been trying again and again to make use of RenderTexture.active and it has never worked once so far.

I tried everything I could think of, using Pro assets and mainly ImageEffects as an example as well.

I tried using different ways to draw a quad to the render texture: Graphics.DrawTexture, Graphics.DrawMeshNow, GL (GL.QUADS), Graphics.Blit. Not once has there been anything drawn into the render texture, which remained completely black and transparent at all times.

This is the most stripped down version I've been trying to make work, in a scene bereft of all but the camera and this script attached to it:

using UnityEngine;
using System.Collections;

public class rdnTxtTst : MonoBehaviour
{
    private RenderTexture rndTxt = null;
    private Material mat = null;

    void Start( )
    {
        rndTxt = Resources.Load( "Textures/RenderTextures/RTtest" ) as RenderTexture;
        mat = new Material( Shader.Find( "DrawPinkAllOver" ) );
    }

    void OnPostRender( )
    {
        RenderTexture oldRndT = RenderTexture.active;
        RenderTexture.active = rndTxt;

        GL.PushMatrix( );
        GL.LoadOrtho( );
        for( int i = 0 ; i < mat.passCount ; i++ )
        {
            mat.SetPass( i );
            GL.Begin( GL.QUADS );

            GL.Vertex3( 0.0f, 0.0f, 0.1f );
            GL.Vertex3( 1.0f, 0.0f, 0.1f );
            GL.Vertex3( 1.0f, 1.0f, 0.1f );
            GL.Vertex3( 0.0f, 1.0f, 0.1f );

            GL.End( );
        }
        GL.PopMatrix( );

        RenderTexture.active = oldRndT;

        Graphics.DrawTexture( new Rect( 0.0f, 0.0f, Screen.width, Screen.height ), rndTxt );
    }
}

And the shader:

Shader "DrawPinkAllOver"
{
    Properties
    {
        _MainTex ("", 2D) = "white" {}
    }

    SubShader
    {
      Cull Off Lighting Off Fog { Color (0,0,0,0) }
   ColorMask RGBA

        Pass
        {
            Blend One Zero
CGPROGRAM
#pragma vertex vert_img
#pragma fragment frag
#pragma fragmentoption ARB_precision_hint_fastest
#include "UnityCG.cginc"

uniform sampler2D _MainTex;

half4 frag (v2f_img i) : COLOR
{
   half4 res = float4( 1.0, 0.0, 1.0, 1.0 );

   return res;
}
ENDCG
        }
    }
}

This version uses GL, but as I said, I won't get any better results using other ways to render a quad on the screen such as Graphics.DrawTexture

Whyyyyyyyyyyy? I'm desperate! Please help!

Thanks in advance.

more ▼

asked Apr 27 '10 at 03:04 PM

taoa gravatar image

taoa
1.6k 8 13 34

(comments are locked)
10|3000 characters needed characters left

2 answers: sort voted first

I found out what the problem was:

RenderTexture.active = rndTxt;

this will apparently clean up matrix information (amongst other things).

So, instead of:

GL.PushMatrix( );
    GL.LoadOrtho( );
    for( int i = 0 ; i < mat.passCount ; i++ )
    {
        mat.SetPass( i );
        GL.Begin( GL.QUADS );

        GL.Vertex3( 0.0f, 0.0f, 0.1f );
        GL.Vertex3( 1.0f, 0.0f, 0.1f );
        GL.Vertex3( 1.0f, 1.0f, 0.1f );
        GL.Vertex3( 0.0f, 1.0f, 0.1f );

        GL.End( );
    }

you do

Graphics.DrawTexture(new Rect(-1.0f,-1.0f,2.0f,2.0f), some_texture);

that will render over the entire RT (the viewport's coordinates go from -1 to 1).

Also, bear in mind that DrawTexture expects pixel positions, so all parameters will be cast into ints internally. As a consequence, you can't give it things like

Graphics.DrawTexture(new Rect(-0.74984f,0.3494854.0f,0.16549f,0.23165f), some_texture);

as it all will be floored down to the nearest integer.

If like me you'd like to keep DrawTexture to use 'screen' coordinates (here, pixel positions) you'll have to rebuild a projection matrix yourself, something like that:

        Matrix4x4 pm = Matrix4x4.identity;
    pm[0, 0] = 2.0f / RT.width;
    pm[1, 1] = -2.0f / RT.height;
    pm[0, 3] = -1.0f;
    pm[1, 3] = 1.0f;

and pass it on to the vertex shader and multiply your vertices positions with it. And then you can use pixel positions in the Rect you pass to DrawTexture instead of -1,-1,2,2 .

more ▼

answered May 07 '10 at 07:56 AM

taoa gravatar image

taoa
1.6k 8 13 34

Yeah... in retrospect, it is probably best to go with the engine-native draw commands rather than implementing your own :) It does seem very odd that the DrawTexture Rect would simultaneously expect "screen coordinates" in the documentation (and floor the input) and operate on a -1 to 1 coordinate space. I currently use camera ViewportToWorld functions for fitting a quad to screen, and there the viewport seems to index (0,0) to (width,height)... Are you sure you haven't shot yourself in the foot with some manual viewport matrix transform elsewhere?

May 07 '10 at 02:33 PM sean

Nah, the only place I've fiddled with hand made transformation matrices was when I did this projection matrix described above, but I don't even do that anymore as it gives dirty results. I went back on using GL stuff, got rid of GL.LoadOrtho( ); and use viewport coordinates (from -1 to 1) and it's satisfactory... What is indeed odd is that in other places, it does expects screen/pixel coordinates for this to work, mostly when my RT is of the screen size exactly. Honestly, I've stopped trying to understand (I even tried debugging it in PIX, nothing), as long as I can have what I need working...

May 21 '10 at 10:00 AM taoa

GL.LoadPixelMatrix ! Yeah boyo!

May 25 '10 at 03:21 PM taoa
(comments are locked)
10|3000 characters needed characters left

First, you'll need to be using Pro. Render textures are one of the goodies explicitly left out of the freebie version. Second, check out the cubemapping scripts in the manual for examples of how to create a real-time cube texture. I believe there are very similar functions for rendering to traditional textures instead.

Now, if you're looking for a way to hack into the final ~screen buffer~ texture (what gets drawn to the window)... I'm still chewing on that one myself. Best solution I've found is to render a regular texture and slap it on a simple plane fit to the window. Wastes some VRAM, but meh.

more ▼

answered May 06 '10 at 09:54 PM

sean gravatar image

sean
296 11 12 19

To get the final screen buffer texture, perform a Grab pass in a shader, which does just that. :) You can then get the result into a render texture... and we're back on the same issue! Yeehaaa!

May 07 '10 at 07:42 AM taoa
(comments are locked)
10|3000 characters needed characters left
Your answer
toggle preview:

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this question

By Email:

Once you sign in you will be able to subscribe for any updates here

By RSS:

Answers

Answers and Comments

Topics:

x194
x116

asked: Apr 27 '10 at 03:04 PM

Seen: 3626 times

Last Updated: Apr 27 '10 at 03:04 PM