[学习笔记]UnityShader入门精要_第13章_使用深度和法线纹理

本文探讨了在延迟着色渲染中获取深度和法线纹理的方法,包括G-buffer的应用,以及如何使用深度纹理实现运动模糊效果。同时介绍了如何通过C#和Shader进行操作,如偏移相机投影、动态边缘检测和纹理旋转示例。涉及技术包括全局雾效、边缘检测罗伯特算子和相关代码实例。
摘要由CSDN通过智能技术生成

13.1 获取深度和法线纹理

G-buffer

A screen space representation of geometry and material information, generated by an intermediate rendering pass in deferred shading rendering pipelines.

几何体和材质信息的屏幕空间表示,由延迟着色渲染管道中的中间渲染通道生成。


13.1.2 如何获取


13.1.3 查看深度和法线纹理


13.2 再谈运动模糊

用深度纹理重建世界坐标

C# 

Camera

depthTextureMode

previousViewProjectionMatrix

camera.projectionMatrix

// Set an off-center projection, where perspective's vanishing

// point is not necessarily in the center of the screen.

//

// left/right/top/bottom define near plane size, i.e.

// how offset are corners of camera's near plane.

// Tweak the values and you can see camera's frustum change.


using UnityEngine;

using System.Collections;


[ExecuteInEditMode]

public class ExampleClass : MonoBehaviour

{

    public float left = -0.2F;

    public float right = 0.2F;

    public float top = 0.2F;

    public float bottom = -0.2F;

    void LateUpdate()

    {

        Camera cam = Camera.main;

        Matrix4x4 m = PerspectiveOffCenter(left, right, bottom, top, cam.nearClipPlane, cam.farClipPlane);

        cam.projectionMatrix = m;

    }


    static Matrix4x4 PerspectiveOffCenter(float left, float right, float bottom, float top, float near, float far)

    {

        float x = 2.0F * near / (right - left);

        float y = 2.0F * near / (top - bottom);

        float a = (right + left) / (right - left);

        float b = (top + bottom) / (top - bottom);

        float c = -(far + near) / (far - near);

        float d = -(2.0F * far * near) / (far - near);

        float e = -1.0F;

        Matrix4x4 m = new Matrix4x4();

        m[0, 0] = x;

        m[0, 1] = 0;

        m[0, 2] = a;

        m[0, 3] = 0;

        m[1, 0] = 0;

        m[1, 1] = y;

        m[1, 2] = b;

        m[1, 3] = 0;

        m[2, 0] = 0;

        m[2, 1] = 0;

        m[2, 2] = c;

        m[2, 3] = d;

        m[3, 0] = 0;

        m[3, 1] = 0;

        m[3, 2] = e;

        m[3, 3] = 0;

        return m;

    }

}

ExecuteInEditMode

Shader

UNITY_UV_STARTS_AT_TOP


13.3 全局雾效

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

Shader "Unity Shaders Book/Chapter 13/Edge Detection Normals And Depth" {
	Properties {
		_MainTex ("Base (RGB)", 2D) = "white" {}
		_EdgeOnly ("Edge Only", Float) = 1.0
		_EdgeColor ("Edge Color", Color) = (0, 0, 0, 1)
		_BackgroundColor ("Background Color", Color) = (1, 1, 1, 1)
		_SampleDistance ("Sample Distance", Float) = 1.0
		_Sensitivity ("Sensitivity", Vector) = (1, 1, 1, 1)
	}
	SubShader {
		CGINCLUDE
		
		#include "UnityCG.cginc"
		
		sampler2D _MainTex;
		half4 _MainTex_TexelSize;
		fixed _EdgeOnly;
		fixed4 _EdgeColor;
		fixed4 _BackgroundColor;
		float _SampleDistance;
		half4 _Sensitivity;
		
		sampler2D _CameraDepthNormalsTexture;
		
		struct v2f {
			float4 pos : SV_POSITION;
			half2 uv[5]: TEXCOORD0;
		};
		  
		v2f vert(appdata_img v) {
			v2f o;
			o.pos = UnityObjectToClipPos(v.vertex);
			
			half2 uv = v.texcoord;
			o.uv[0] = uv;
			
			#if UNITY_UV_STARTS_AT_TOP
			if (_MainTex_TexelSize.y < 0)
				uv.y = 1 - uv.y;
			#endif
			
			o.uv[1] = uv + _MainTex_TexelSize.xy * half2(1,1) * _SampleDistance;
			o.uv[2] = uv + _MainTex_TexelSize.xy * half2(-1,-1) * _SampleDistance;
			o.uv[3] = uv + _MainTex_TexelSize.xy * half2(-1,1) * _SampleDistance;
			o.uv[4] = uv + _MainTex_TexelSize.xy * half2(1,-1) * _SampleDistance;
					 
			return o;
		}
		
		half CheckSame(half4 center, half4 sample) {
			half2 centerNormal = center.xy;
			float centerDepth = DecodeFloatRG(center.zw);
			half2 sampleNormal = sample.xy;
			float sampleDepth = DecodeFloatRG(sample.zw);
			
			// difference in normals
			// do not bother decoding normals - there's no need here
			half2 diffNormal = abs(centerNormal - sampleNormal) * _Sensitivity.x;
			int isSameNormal = (diffNormal.x + diffNormal.y) < 0.1;
			// difference in depth
			float diffDepth = abs(centerDepth - sampleDepth) * _Sensitivity.y;
			// scale the required threshold by the distance
			int isSameDepth = diffDepth < 0.1 * centerDepth;
			
			// return:
			// 1 - if normals and depth are similar enough
			// 0 - otherwise
			return isSameNormal * isSameDepth ? 1.0 : 0.0;
		}
		
		fixed4 fragRobertsCrossDepthAndNormal(v2f i) : SV_Target {
			half4 sample1 = tex2D(_CameraDepthNormalsTexture, i.uv[1]);
			half4 sample2 = tex2D(_CameraDepthNormalsTexture, i.uv[2]);
			half4 sample3 = tex2D(_CameraDepthNormalsTexture, i.uv[3]);
			half4 sample4 = tex2D(_CameraDepthNormalsTexture, i.uv[4]);
			
			half edge = 1.0;
			
			edge *= CheckSame(sample1, sample2);
			edge *= CheckSame(sample3, sample4);
			
			fixed4 withEdgeColor = lerp(_EdgeColor, tex2D(_MainTex, i.uv[0]), edge);
			fixed4 onlyEdgeColor = lerp(_EdgeColor, _BackgroundColor, edge);
			
			return lerp(withEdgeColor, onlyEdgeColor, _EdgeOnly);
		}
		
		ENDCG
		
		Pass { 
			ZTest Always Cull Off ZWrite Off
			
			CGPROGRAM      
			
			#pragma vertex vert  
			#pragma fragment fragRobertsCrossDepthAndNormal
			
			ENDCG  
		}
	} 
	FallBack Off
}

13.3.3 实现

C# 

GetComponent

Component.GetComponent

GameObject.GetComponent

OnEnable

SetRow

material.SetMatrix

// Use this shader on an object together with the above example script.

// The shader transforms texture coordinates with a matrix set from a script.

Shader "RotatingTexture"

{

    Properties

    {

        _MainTex ("Base (RGB)", 2D) = "white" {}

    }

    SubShader

    {

        Pass

        {

            CGPROGRAM

            #pragma vertex vert

            #pragma fragment frag


            struct v2f

            {

                float2 uv : TEXCOORD0;

                float4 pos : SV_POSITION;

            };


            float4x4 _TextureRotation;


            v2f vert (float4 pos : POSITION, float2 uv : TEXCOORD0)

            {

                v2f o;

                o.pos = UnityObjectToClipPos(pos);

                o.uv = mul(_TextureRotation, float4(uv,0,1)).xy;

                return o;

            }


            sampler2D _MainTex;

            fixed4 frag (v2f i) : SV_Target

            {

                return tex2D(_MainTex, i.uv);

            }

            ENDCG

        }

    }

}

Normalize


13.4 再谈边缘检测

罗伯特算子


13.5 扩展阅读

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值