2
\$\begingroup\$

When I get the depthnormals with the shaderreplace script, it just replaces all the shaders in the scene and uses the meshes geometry to calculate the normals, ignoring the normalmap textures applied on them.

How can I get the final rendered scene normals to a rendertexture like it appears in the editor windows normal debug mode that is used for deferred light calculations and ambient occlusion and such ?

enter image description here

\$\endgroup\$
  • \$\begingroup\$ please explain more! why do you need get the final rendered scene normals.do you need shader? \$\endgroup\$ – Seyed Morteza Kamali Dec 31 '17 at 14:40
  • \$\begingroup\$ I'll use it in a shader for post-processing. \$\endgroup\$ – Cactus on Fire Dec 31 '17 at 15:06
  • \$\begingroup\$ first write shader for debugging normals then use ShaderReplacement for replacing normal map shader then Render it toTexture by RenderTexture .now you can use final result in RenderTexture. \$\endgroup\$ – Seyed Morteza Kamali Dec 31 '17 at 15:51
  • \$\begingroup\$ Hmm.. depthnormals shouldn't ignore normal maps. Are you using custom shaders from which Unity might not be able to infer the normal maps itself? Is it an option for your project to switch to deferred rendering so the normals are already present in the GBuffer? \$\endgroup\$ – DMGregory Dec 31 '17 at 16:33
  • \$\begingroup\$ I'm using shader forge, there is an option for deferred or forward. Let me try getting everything rendered with deferred. \$\endgroup\$ – Cactus on Fire Dec 31 '17 at 16:43
2
\$\begingroup\$

DisplayNormal

you can use Replacement Shader to Displaying Mesh Normals

First attach this script to camera:

using UnityEngine;
using System.Collections;

[ExecuteInEditMode]
public class ReplacementShaderEffect : MonoBehaviour
{
    public Shader ReplacementShader;


    void OnEnable()
    {
        if (ReplacementShader != null)
            GetComponent<Camera>().SetReplacementShader(ReplacementShader, "");
    }

    void OnDisable()
    {
        GetComponent<Camera>().ResetReplacementShader();
    }
}

then use this shader in above script for Replacing shaders

Shader "Tutorial/Display Normals" {
    SubShader {
        Pass {
    CGPROGRAM
    #pragma vertex vert
    #pragma fragment frag
    #include "UnityCG.cginc"

    struct v2f {
        float4 pos : SV_POSITION;
        float3 color : COLOR0;
    };

    v2f vert (appdata_base v)
    {
        v2f o;
        o.pos = UnityObjectToClipPos (v.vertex);
        o.color = v.normal * 0.5 + 0.5;
        return o;
    }

    half4 frag (v2f i) : COLOR
    {
        return half4 (i.color, 1);
    }
    ENDCG

        }
    }
    Fallback "VertexLit"
    } 

In your comments you mentioned that you need store result to Rendertexture and use it in shader for post-processing

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CaptureMe : MonoBehaviour {
    public RenderTexture RT;
    public Camera SecondCamera;//Second Camera Renders Normal that store to RenderTexture
    public Shader shader;//shader that you want pass result to it

    void Update(){
    }

    void OnRenderImage(RenderTexture source,RenderTexture target){

        int resWidth = Screen.width;
        int resHeight = Screen.height;

        RT = new RenderTexture(resWidth, resHeight, 24);
        SecondCamera.targetTexture = RT; //Create new renderTexture and assign to camera
        Texture2D screenShot = new Texture2D(resWidth, resHeight, TextureFormat.RGB24, false); //Create new texture

        SecondCamera.Render();

        RenderTexture.active = RT;
        screenShot.ReadPixels(new Rect(0, 0, resWidth, resHeight), 0, 0); //Apply pixels from camera onto Texture2D

        SecondCamera.targetTexture = null;
        RenderTexture.active = null; //Clean


        Material mat = new Material(shader);

        mat.SetTexture ("_NormalScene", RT);

        Graphics.Blit (source, target,mat);


        Destroy(RT); //Free memory



    }
}

Update

DisplayNormal

If you need better result you should be calculating the world normals.

Shader "Tutorial/DisplayNormal2"
{
    SubShader

    {
        Tags { "RenderType" = "Opaque" }
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct v2f

            {
                float4 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;

            };
            v2f vert(appdata_base v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv.xyz = UnityObjectToWorldNormal(v.normal);
                return o;
            }
            fixed4 frag (v2f i) : SV_Target
            {
                float3 c = i.uv.xyz;
                return float4(c, 1);
            }
            ENDCG
        }
    }
}
\$\endgroup\$
  • \$\begingroup\$ Thanks for the reply, but as I said, that's not what I'm looking for. That method only displays the mesh normals, wheres I want to get the surface pixel normals. \$\endgroup\$ – Cactus on Fire Dec 31 '17 at 16:32
  • \$\begingroup\$ i.imgur.com/ZW9v3O6.jpg \$\endgroup\$ – Cactus on Fire Dec 31 '17 at 16:33
  • \$\begingroup\$ Like the image above is what replaceshader does. But instead I need the final rendered normals like below. \$\endgroup\$ – Cactus on Fire Dec 31 '17 at 16:34
  • \$\begingroup\$ @CactusonFire here there is normal shader do you test it? docs.unity3d.com/Manual/SL-VertexFragmentShaderExamples.html \$\endgroup\$ – Seyed Morteza Kamali Dec 31 '17 at 16:42
  • \$\begingroup\$ Yup, that's still the mesh normals. \$\endgroup\$ – Cactus on Fire Dec 31 '17 at 16:53
1
\$\begingroup\$

I'm assuming you're talking about the gbuffers of the deferred rendering path

According to this tutorial.

You need to declare the samplers in your shaders:

sampler2D _CameraGBufferTexture0;
sampler2D _CameraGBufferTexture1;
sampler2D _CameraGBufferTexture2;

Then you can read from them like so

float3 albedo = tex2D(_CameraGBufferTexture0, uv).rgb;
float3 specularTint = tex2D(_CameraGBufferTexture1, uv).rgb;
float3 smoothness = tex2D(_CameraGBufferTexture1, uv).a;
float3 normal = tex2D(_CameraGBufferTexture2, uv).rgb * 2 - 1;

You're interested in _CameraGBufferTexture2

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.