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
}
}
}
Related questions
- Unity Shader achieves cutting effect
- Unity Shader realizes the fog of 2D games
- Unity Shader realizes the sketch effect
- Unity Shader implements sketch-style rendering
- Unity Shader achieves graphics drawing (blue sky, white clouds and sea)
- Unity shader realizes the effect of vertex animation wave
- Unity shader to achieve glass refraction effect
- Unity Shader achieves glass material effect
- Unity Shader intersection algorithm realizes simple anti-energy shield