Skip to content

Instantly share code, notes, and snippets.

@bshishov
Last active April 28, 2021 09:29
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save bshishov/3eaa056d1560584ff82c1b96ee2f20fd to your computer and use it in GitHub Desktop.
Save bshishov/3eaa056d1560584ff82c1b96ee2f20fd to your computer and use it in GitHub Desktop.
Unity3D simple screen-space decal shader. Does not support lighting. Works with LWRP. Just create a material with this shader and assign it to a cube (also disable shadows and collider). Thats it you've got a working decals.
Shader "Custom/SimpleDecal"
{
Properties {
_MainTex ("Main Texture", 2D) = "white" {}
[HDR]_Color ("Color", Color) = (1, 1, 1, 1)
}
SubShader
{
Tags { "RenderType"= "Transparent" "Queue" = "Transparent" }
Pass
{
ZWrite Off
Lighting Off
Cull Back
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
uniform half4 _Color;
uniform sampler2D _MainTex;
uniform sampler2D _CameraDepthTexture;
float4 _MainTex_ST;
struct VSInput
{
float4 vertex : POSITION;
float3 texcoord : TEXCOORD0;
};
struct VSOut
{
float4 position :SV_POSITION;
float4 screenPos : TEXCOORD0;
float3 ray : TEXCOORD2;
};
VSOut vert (VSInput v)
{
VSOut o ;
o.position = UnityObjectToClipPos(v.vertex);
o.screenPos = ComputeScreenPos(o.position);
o.ray = UnityObjectToViewPos(v.vertex).xyz * float3(-1,-1,1);
// v.texcoord is equal to 0 when we are drawing 3D light shapes and
// contains a ray pointing from the camera to one of near plane's
// corners in camera space when we are drawing a full screen quad.
o.ray = lerp(o.ray, v.texcoord, v.texcoord.z != 0);
return o;
}
fixed4 frag(VSOut i): Color
{
// Get correct view direction
i.ray = i.ray * (_ProjectionParams.z / i.ray.z);
// Get depth in the current pixel
float depth = Linear01Depth (SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, i.screenPos.xy / i.screenPos.w));
// Get new projection coordinates. It is almost like original o.position,
// except that Z axis is using depth information. Such taht we are ignoring our projected object, Z values
float4 prjPos = float4(i.ray * depth,1);
float3 worldPos = mul(unity_CameraToWorld, prjPos).xyz;
float4 objPos = mul(unity_WorldToObject, float4(worldPos, 1));
clip(float3(0.5, 0.5, 0.5) - abs(objPos.xyz));
half2 uv = _MainTex_ST.xy * (objPos.xz + 0.5);
return tex2D(_MainTex, uv) * _Color;
}
ENDCG
}
}
FallBack "Unlit/Transparent"
}
@thunderawesome
Copy link

How would you make this work with an Orthographic camera?

@bshishov
Copy link
Author

bshishov commented Nov 9, 2019

How would you make this work with an Orthographic camera?

@thunderawesome, I haven't test it with orthographic camera, there might be some issues with ProjectionParams, I guess. Probably some macro is missed or a special ifdef for ortho projection, not sure.
I'lll try to check the shader code later, I don't have much time right now.

@Avdbergnmf
Copy link

This seems to have broken in Unity 2020.1.9f1 :/

Any workaround you know about for this? :)

@bshishov
Copy link
Author

bshishov commented Dec 9, 2020

This seems to have broken in Unity 2020.1.9f1 :/

Any workaround you know about for this? :)

Just tested it in 2019.3.10f1 - It works with default rendering settings but it seems like the default scene camera settings does not have depth rendering enabled.

Some workarounds:

  • If it doesnt show up in scene view - enable lighting and postprocessing in scene view. See screenshot
  • If it doesn't work in game view - make sure your camera has depth rendering enabled. You can force enable it from script by executing something like this: Camera.main.depthTextureMode = DepthTextureMode.DepthNormals; see DepthTextureMode docs for moe details
  • or switch camera rendering mode to deffered - it has depth buffer enabled by default.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment