Unity Shader實(shí)現(xiàn)動(dòng)態(tài)霧效果
Unity Shader學(xué)習(xí):動(dòng)態(tài)霧,供大家參考,具體內(nèi)容如下
先將相機(jī)近裁面四個(gè)角向量傳給shader,再通過(guò)觀察空間下的深度值和相機(jī)位置算出像素在世界坐標(biāo)系的位置,通過(guò)世界空間高度值來(lái)設(shè)定霧的范圍和濃度,然后通過(guò)噪聲和uv偏移實(shí)現(xiàn)擾動(dòng)效果。得到了類(lèi)似寂靜嶺或惡靈附身1的效果。


C#部分:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[ExecuteInEditMode]
public class RayMarchingCamera : MonoBehaviour {
private Matrix4x4 frustumCorners = Matrix4x4.identity;
public Material material;
public Camera myCamera;
public Transform cameraTransform;
// Use this for initialization
private void Start()
{
myCamera.depthTextureMode = DepthTextureMode.Depth;
}
private void OnRenderImage(RenderTexture source, RenderTexture destination)
{
//field of view
float fov = myCamera.fieldOfView;
//近裁面距離
float near = myCamera.nearClipPlane;
//橫縱比
float aspect = myCamera.aspect;
//近裁面一半的高度
float halfHeight = near * Mathf.Tan(fov * 0.5f * Mathf.Deg2Rad);
//向上和向右的向量
Vector3 toRight = myCamera.transform.right * halfHeight * aspect;
Vector3 toTop = myCamera.transform.up * halfHeight;
//分別得到相機(jī)到近裁面四個(gè)角的向量
//depth/dist=near/|topLeft|
//dist=depth*(|TL|/near)
//scale=|TL|/near
Vector3 topLeft = cameraTransform.forward * near + toTop - toRight;
float scale = topLeft.magnitude / near;
topLeft.Normalize();
topLeft *= scale;
Vector3 topRight = cameraTransform.forward * near + toTop + toRight;
topRight.Normalize();
topRight *= scale;
Vector3 bottomLeft = cameraTransform.forward * near - toTop - toRight;
bottomLeft.Normalize();
bottomLeft *= scale;
Vector3 bottomRight = cameraTransform.forward * near - toTop + toRight;
bottomRight.Normalize();
bottomRight *= scale;
//給矩陣賦值
frustumCorners.SetRow(0, bottomLeft);
frustumCorners.SetRow(1, bottomRight);
frustumCorners.SetRow(2, topRight);
frustumCorners.SetRow(3, topLeft);
//將向量傳給定點(diǎn)著色器,將屏幕畫(huà)面?zhèn)鱾€(gè)shader
material.SetMatrix("_FrustumCornorsRay", frustumCorners);
material.SetTexture("_MainTex", source);
Graphics.Blit(source, destination,material,0);
}
}
shader部分:
Shader "Unlit/Fog"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_NoiseTex("NoiseTex",2D)="white"{}
//霧起始高度
_FogStartHeight("FogStartHeight",float)=0.0
//霧終點(diǎn)高度
_FogEndHeight("FogEndHeight",float)=1.0
//霧x位移速度
_FogXSpeed("FogXSpeed",float)=0.1
//霧y位移速度
_FogYSpeed("FogYSpeed",float)=0.1
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex;
sampler2D _NoiseTex;
sampler2D _CameraDepthTexture;
float _FogStartHeight;
float _FogEndHeight;
float _FogXSpeed;
float _FogYSpeed;
//獲得相機(jī)近裁面四個(gè)角向量
float4x4 _FrustumCornorsRay;
struct a2v{
float4 vertex:POSITION;
float2 uv:TEXCOORD0;
};
struct v2f{
float4 pos:SV_POSITION;
float2 uv:TEXCOORD0;
float4 interpolatedRay:TEXCOORD1;
};
v2f vert(a2v v){
v2f o;
o.pos=UnityObjectToClipPos(v.vertex);
o.uv=v.uv;
int index=0;
if (v.uv.x<0.5&&v.uv.y<0.5)
{
index = 0;
}
else if (v.uv.x>0.5&&v.uv.y<0.5) {
index = 1;
}
else if (v.uv.x>0.5&&v.uv.y>0.5) {
index = 2;
}
else {
index = 3;
}
//安排uv4個(gè)角對(duì)應(yīng)四個(gè)角向量
o.interpolatedRay = _FrustumCornorsRay[index];
return o;
}
float4 frag(v2f i):SV_Target{
//觀察空間下的線性深度值
float linearDepth=LinearEyeDepth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture,i.uv));
//像素世界坐標(biāo)=世界空間相機(jī)位置+像素相對(duì)相機(jī)距離
float3 worldPos=_WorldSpaceCameraPos+linearDepth*i.interpolatedRay.xyz;
float speedX=_Time.y*_FogXSpeed;
float speedY=_Time.y*_FogYSpeed;
float noise=tex2D(_NoiseTex,i.uv+float2(speedX,speedY));
//讓噪聲圖向黑色靠攏,黑白差距不要太大
noise=pow(noise,0.5);
//霧濃度=世界高度/指定范圍
float fogDensity=(_FogEndHeight-worldPos.y)/(_FogEndHeight-_FogStartHeight);
fogDensity=smoothstep(0.0,1.0,fogDensity*noise);
float4 color=tex2D(_MainTex,i.uv);
//根據(jù)霧濃度混合場(chǎng)景和霧顏色
color.rgb=lerp(color.rgb,float3(0.5,0.5,0.5),fogDensity);
return color;
}
ENDCG
}
}
}
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C#中DataTable 轉(zhuǎn)換為 Json的方法匯總(三種方法)
JavaScript Object Notation (Json)是一種輕量級(jí)的數(shù)據(jù)交換格式,下面小編給大家介紹三種方法實(shí)現(xiàn)DataTable轉(zhuǎn)換成 Json 對(duì)象,感興趣的朋友一起看看吧2016-11-11
C#中前臺(tái)線程和后臺(tái)線程的區(qū)別與聯(lián)系
這篇文章主要介紹了C#中前臺(tái)線程和后臺(tái)線程的區(qū)別與聯(lián)系,本文先講解了它們的區(qū)別,然后給出了一個(gè)例子來(lái)驗(yàn)證這些區(qū)別,需要的朋友可以參考下2015-06-06
詳解MongoDB for C#基礎(chǔ)入門(mén)
本篇文章主要介紹了MongoDB for C#基礎(chǔ)入門(mén),具體介紹了c#中關(guān)于對(duì)MongoDB的連接,插入,查詢等,有需要的可以了解一下。2016-12-12
簡(jiǎn)單C#代碼實(shí)現(xiàn)modbus-rtu通訊發(fā)送數(shù)據(jù)方式
這篇文章主要介紹了簡(jiǎn)單C#代碼實(shí)現(xiàn)modbus-rtu通訊發(fā)送數(shù)據(jù)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01

