Home>

First pass the four corner vectors of the camera's near-plane to the shader, and then calculate the position of the pixel in the world coordinate system by observing the depth value and the camera position in the spaceSet the range and concentration of fog through the world space height value,Then the disturbance effect is achieved by noise and uv shift.Obtained effects similar to Silent Hill or Evil Spirit Possession 1.

c#part:

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;
  //Near cutting distance
  float near=mycamera.nearclipplane;
  //Aspect ratio
  float aspect=mycamera.aspect;
  //Half the height near the cut surface
  float halfheight=near * mathf.tan (fov * 0.5f * mathf.deg2rad);
  //up and right vector
  vector3 toright=mycamera.transform.right * halfheight * aspect;
  vector3 totop=mycamera.transform.up * halfheight;
  //Get the vectors from the camera to the four corners of the near-cut plane respectively
  //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;
  //Assign the matrix
  frustumcorners.setrow (0, bottomleft);
  frustumcorners.setrow (1, bottomright);
  frustumcorners.setrow (2, topright);
  frustumcorners.setrow (3, topleft);
  //pass the vector to the fixed-point shader,Pass the screen to a shader
  material.setmatrix ("_ frustumcornorsray", frustumcorners);
  material.settexture ("_ maintex", source);
  graphics.blit (source, destination, material, 0);
 }
}

Shader part:

shader "unlit/fog"
{
 properties
 {
 _maintex ("texture", 2d)="white" {}
 _noisetex ("noisetex", 2d)="white" {}
 //The starting height of the fog
 _fogstartheight ("fogstartheight", float)=0.0
 //Fog end height
 _fogendheight ("fogendheight", float)=1.0
 //Fog x displacement speed
 _fogxspeed ("fogxspeed", float)=0.1
 //Fog y displacement speed
 _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;
 //Get the four corner vectors of the camera's near-plane
 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;
 }
 //Arrange uv4 corners corresponding to four corner vectors
 o.interpolatedray=_frustumcornorsray [index];
 return o;
 }
 float4 frag (v2f i):sv_target {
 //Observe the linear depth value in space
 float lineardepth=lineareyedepth (sample_depth_texture (_cameradepthtexture, i.uv));
 //Pixel world coordinates=world space camera position + pixel relative camera distance
 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));
 //Let the noise graph move closer to black,Don't make a big gap between black and white
 noise=pow (noise, 0.5);
 //Fog density=world height/specified range
 float fogdensity=(_ fogendheight-worldpos.y)/(_ fogendheight-_fogstartheight);
 fogdensity=smoothstep (0.0,1.0, fogdensity * noise);
 float4 color=tex2d (_maintex, i.uv);
 //mix scene and fog color according to fog density
 color.rgb=lerp (color.rgb, float3 (0.5,0.5,0.5), fogdensity);
 return color;
 }
 endcg
 }
 }
}
  • Previous Unity Shader achieves glass material effect
  • Next Are you ready for vue30