0
\$\begingroup\$

I'm new to Unity and game programming, so I apologize in advance for any embarrassingly bad stupidities.

I'm not having any luck trying to reproduce the RenderTexture example at the bottom of this page: https://docs.unity3d.com/2022.2/Documentation/Manual/class-RenderTexture.html

The only difference is that I'm trying to recreate it in a 2D project, so instead of a 3D cube, I'm trying to apply the RenderTexture to a flat square. The issue is that nothing is appearing in the square once I set everything up.

The setup is (not everything, but hopefully enough):

  1. I've created a PNG file my sprite graphic, which is just a single color (white) object on a transparent background. I put that in my Assets directory.

  2. I went into Unity and dragged that sprite from the Project window into my scene in the Hierarchy window. I moved the sprite out of the main camera area.

  3. I created an auxiliary camera and pointed it at the sprite.

  4. I created a RenderTexture and assigned it to the TargetTexture of the auxiliary camera. I set it up to be Orthographic and sized it appropriately so that the sprite is appearing in the aux camera's preview window. It's just a white image on a black background.

  5. The instructions say to create a cube, but since I'm working in 2D, I've created a Square sprite.

  6. The instructions say to drag the RenderTexture onto the cube to create a material for it, but that doesn't work for me. It doesn't do anything to drag the RenderTexture onto the Square.

I guess this is point where I should stop. I went further, creating a material and stuff, but it didn't get me anywhere.

I just want to know why this doesn't work. What am I not understanding about this?

\$\endgroup\$
8
  • 1
    \$\begingroup\$ Did you try using a quad MeshRenderer instead of a SpriteRenderer? \$\endgroup\$
    – DMGregory
    Jun 15 at 13:36
  • 2
    \$\begingroup\$ You can create a 3D Quad instead of 2D Square. There is no real 2D in unity, you can mix them. \$\endgroup\$
    – Mangata
    Jun 15 at 13:48
  • \$\begingroup\$ Oh, I see. But why do I need to do that? I don't understand. Sprites have a material property, but it just doesn't work? \$\endgroup\$ Jun 15 at 13:51
  • \$\begingroup\$ And it doesn't doesn't render properly on the quad. It's too dark. \$\endgroup\$ Jun 15 at 14:05
  • 2
    \$\begingroup\$ If you've solved your problem, post your solution as an Answer below. The reason the Editor does not support the shortcut of making a material from a texture when dragging it onto a SpriteRenderer is that SpriteRenderers are made to render Sprites, not textures. A sprite can be a subset of a texture, and many sprites from the same texture can be rendered together in a batch. So the workflow to support that is to create a Sprite first. Providing the shortcut would make it easy to skip this step and break batching, gaining no benefits from the SpriteRenderer over a quad. \$\endgroup\$
    – DMGregory
    Jun 15 at 14:14

1 Answer 1

2
\$\begingroup\$

enter image description here

In the upper right corner is a 3D Quad (MeshRenderer) and in the lower right corner is a 2D Square (SpriteRenderer). Now let me explain the difference and how to create them.

Using the shortcut to create a mesh(dragging the Render Texture onto the mesh) will automatically create a material with a standard shader, and set the albedo as the dragged texture. So naturally this mesh will be affected by lighting.(I added a yellow direct light there). And creating a sprite renderer(creating a new material with a custom shader) directly displays the color of the texture, which depends on the shader and can be further extended.

Why can't you drag the texture to the spriteRenderer for shortcut operations? spriteRenderer requires a material to have a _MainTex parameter, the default shader(Sprites/Default) has only one texture channel (and is already used by spriteRenderer), so it is unreasonable to attach an extra material to SpriteRenderer's material. This is why the new version of unity sets _MainTex is inoperable. The sprite is designed to display an image only, and such a setup is reasonable.

Anyway, we can create a custom shader, provide a _MainTex parameter but not use it, and create a new texture channel to place the RenderTexture, and use its color.

Create a new material, select the shader as the custom shader below, and set it as the material of the SpriteRenderer. set the RenderTexture to _SubTex.

Shader "Custom/NewShader"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _SubTex ("Texture", 2D) = "white" {}
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            
            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;

            sampler2D _SubTex;
            float4 _SubTex_ST;
            
            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                return o;
            }
            
            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 col = tex2D(_SubTex, i.uv);
                return col;
            }
            ENDCG
        }
    }
}

Some extra notes to clarify:

There are two ways to achieve Displaying a RenderTexture:

  1. Plan A: Use a 3D Quad (MeshRenderer)

    1. Drag the renderTexuture onto this mesh according to the tutorial instructions.
    2. And add a light to your scene. Because this texture is used as an albedo for the mesh. Its final color is affected by lighting, if there is no lighting it is black.
  2. Plan B: Use a 2D Square (SpriteRenderer)

    1. Create a .shader file in your Assets dir. And copy the code above into it.
    2. Create a new material and select the shader for it.(Custom/NewShader)
    3. Drag the renderTexuture file to the material(_SubTex).
    4. Drag the material to the 2D Square.

the preview window displays my sprite fine, but my square is still white in the end.

Because the spriteRenderer is used to display a sprite, it will overwrite the texture of the sprite to the material at runtime. so _MainTex is already used by spriteRenderer. You can not use that.

So we could create a new shader with extra texture paramater(_SubTex) and just ignore _MainTex. It will be fine.

\$\endgroup\$
7
  • \$\begingroup\$ Thanks! I appreciate the effort you put into that answer, but I'm left throughly confused by it. Let me ask the question by giving my impressions about what is happening: When I right-click on my scene > 3D Object > Quad, and scale it up to (x,y) = (50,50), I get a dark square. I guess it's transparent because I can see everything I drag it over. Anyway, I have my RenderTexture ready to go and I can drag it onto the quad and see my sprite. I look in the quad properties and I see a Materials section, Element 0 = my RenderTexture. \$\endgroup\$ Jun 16 at 2:00
  • \$\begingroup\$ Now I right-click on my scene again > 2D Object > Sprites > Square, scale it up to 50x50, and this time I get a white square. I drag the RenderTexture onto it and of course it doesn't work. But in the Square properties, I see a Material field in there. I can set it to my RenderTexture and it accepts it no problem. Except for nothing happens to the display of the square. It's still a white square. My question is why doesn't it do anything? What is the point of that material property if it doesn't show you the texture you put in the material you assign to it? \$\endgroup\$ Jun 16 at 2:13
  • 1
    \$\begingroup\$ 1. You get a black square not because it is transparent, but because it is affected by lighting, you need to add light to the scene. 2. You're getting a white square because it's using the default material, which doesn't have an extra texture channel to put your renderTexture on, because it's a spriteRenderer, and it's forcing to use that only texture channel to show the sprite. \$\endgroup\$
    – Mangata
    Jun 16 at 5:57
  • 1
    \$\begingroup\$ The old version of unity allows you to use this unique texture channel in Sprites/Default, but it will not have any effect, this field has been disabled in the new version of unity. \$\endgroup\$
    – Mangata
    Jun 16 at 6:00
  • \$\begingroup\$ No, I changed it to my material, the one I made with my RenderTexture. Sorry, I left that part out. I manually created a material and I set....well, I actually had to hack it and change the shader to Standard before it would let me put my texture in the Albedo property. This makes the preview window go a little dark, but I can change the shader back to Sprites/Default and that fixes the preview window colors. So the preview window displays my sprite fine, but my square is still white in the end. I don't know, I guess I'm getting confused by a design gap in the Unity editor. \$\endgroup\$ Jun 16 at 13:21

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .