- Home /
Post-processing shader using 3D pixel coordinates to dictate colour
Dear All,
I am trying to make a post-processor shader which I cannot quite crack.
Essentially I want to make a post processing shader that finds the 3D world coordinate of its associated pixels, based upon these locations I want to calculate the distance from a game object and then "tint" the pixels based upon this distance.
The end result would be a postprocessor shader that will change colour based upon what you are looking at and how close that is to a specific game object.
So far I have been trying a variety of shaders myself and based also upon those found online however am stuck and starting to question if this is even possible.
Has anyone got any ideas or code that could help me on my way?
Thanks in advance for your help!
Answer by BastianUrbach · Dec 25, 2018 at 12:32 PM
This is how it was done in the old GlobalFog image effect:
Camera cam = GetComponent<Camera>();
Transform camtr = cam.transform;
cam.depthTextureMode = DepthTextureMode.Depth;
Vector3[] frustumCorners = new Vector3[4];
cam.CalculateFrustumCorners(new Rect(0, 0, 1, 1), cam.farClipPlane, cam.stereoActiveEye, frustumCorners);
var bottomLeft = camtr.TransformVector(frustumCorners[0]);
var topLeft = camtr.TransformVector(frustumCorners[1]);
var topRight = camtr.TransformVector(frustumCorners[2]);
var bottomRight = camtr.TransformVector(frustumCorners[3]);
Matrix4x4 frustumCornersArray = Matrix4x4.identity;
frustumCornersArray.SetRow(0, bottomLeft);
frustumCornersArray.SetRow(1, bottomRight);
frustumCornersArray.SetRow(2, topLeft);
frustumCornersArray.SetRow(3, topRight);
material.SetMatrix("_FrustumCornersWS", frustumCornersArray);
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float2 uv_depth : TEXCOORD1;
float4 interpolatedRay : TEXCOORD2;
float4 vertex : SV_POSITION;
};
float4x4 _FrustumCornersWS;
float4 _MainTex_TexelSize;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv.xy;
o.uv_depth = v.uv.xy;
#if UNITY_UV_STARTS_AT_TOP
if (_MainTex_TexelSize.y < 0)
o.uv.y = 1-o.uv.y;
#endif
int frustumIndex = v.uv.x + (2 * o.uv.y);
o.interpolatedRay = _FrustumCornersWS[frustumIndex];
o.interpolatedRay.w = frustumIndex;
return o;
}
sampler2D _MainTex;
sampler2D _CameraDepthTexture;
fixed4 frag (v2f i) : SV_Target
{
float rawDepth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, UnityStereoTransformScreenSpaceTex(i.uv_depth));
float dpth = Linear01Depth(rawDepth);
float3 wsDir = dpth * i.interpolatedRay.xyz;
float3 wsPos = _WorldSpaceCameraPos + wsDir;
return float4(frac(wsPos.xyz), 1);
}