UnityShader实现动态雾效果
Unity Shader学习:动态雾,供⼤家参考,具体内容如下
先将相机近裁⾯四个⾓向量传给shader,再通过观察空间下的深度值和相机位置算出像素在世界坐标系的位置,通过世界空间⾼度值来设定雾的范围和浓度,然后通过噪声和uv偏移实现扰动效果。得到了类似寂静岭或恶灵附⾝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 = arClipPlane;
//横纵⽐
float aspect = myCamera.aspect;
//近裁⾯⼀半的⾼度
float halfHeight = near * Mathf.Tan(fov * 0.5f * Mathf.Deg2Rad);
//向上和向右的向量
Vector3 toRight = ansform.right * halfHeight * aspect;
Vector3 toTop = ansform.up * halfHeight;
//分别得到相机到近裁⾯四个⾓的向量
/
/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);
//将向量传给定点着⾊器,将屏幕画⾯传个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
float up/
/雾终点⾼度
_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 "inc"
sampler2D _MainTex;
sampler2D _NoiseTex;
sampler2D _CameraDepthTexture;
float _FogStartHeight;
float _FogEndHeight;
float _FogXSpeed;
float _FogYSpeed;
//获得相机近裁⾯四个⾓向量
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个⾓对应四个⾓向量
o.interpolatedRay = _FrustumCornorsRay[index];
return o;
}
float4 frag(v2f i):SV_Target{
//观察空间下的线性深度值
float linearDepth=LinearEyeDepth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture,i.uv)); //像素世界坐标=世界空间相机位置+像素相对相机距离
float3 worldPos=_WorldSpaceCameraPos+linearDepth*;
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);
//根据雾浓度混合场景和雾颜⾊
return color;
}
ENDCG
}
}
}
以上就是本⽂的全部内容,希望对⼤家的学习有所帮助,也希望⼤家多多⽀持。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论