Hello,
I’ve been working on a project where we want to have shadows. I made 2 objects: a cube and a raptor. These 2 objects should emit the shadow on a plane i put under these objects. The plane has the shadow shader. I want the intensity of the objects shadow to be based on the distance to the light. The issue is: if i move the raptor further away from the light, the cube also decreases in intensity.
(Don’t know why the image doesnt work. link: noMove hosted at ImgBB — ImgBB)
The directional light is in the middle and gives a shadow to both the objects.
Now when i move the directional light, i would want the raptor to have a more intense shadow and the cube a less intense shadow. As you can see in the image below the intensity of the cube is the exact same as the raptor.
(link to image: move hosted at ImgBB — ImgBB)
How do i make seperate intensities per object?
This is the shader:
// Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
Shader "Custom/MatteShadow"
{
Properties
{
_ShadowStrength("Shadow Strength", Range(0, 1)) = 1
_ShadowRange("Shadow Range", Range(1,20)) = 10
}
SubShader
{
Tags
{
"Queue" = "AlphaTest+49"
"IgnoreProjector" = "True"
"RenderType" = "Transparent"
}
Pass
{
Tags{ "LightMode" = "ForwardBase" }
ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fwdbase
float4 shadowObjects[20];
float4 lightPosition;
struct AppDatata {
float4 pos : POSITION;
};
#include "UnityCG.cginc"
#include "AutoLight.cginc"
struct v2f
{
float4 pos : SV_POSITION;
float3 worldPosition : TEXCOORD2;
//float intensity : TEXCOORD3;
//float normalizedDistance : TEXCOORD1;
SHADOW_COORDS(0)
};
fixed _ShadowStrength;
fixed _ShadowRange;
v2f vert(appdata_img v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.worldPosition = mul(unity_ObjectToWorld, v.vertex).xyz;
TRANSFER_SHADOW(o);
return o;
}
fixed4 frag(v2f v) : COLOR
{
fixed shadow = SHADOW_ATTENUATION(v);
fixed shadowalpha = (1.0 - shadow) * _ShadowStrength;
if (shadowalpha == 0) {
return fixed4(0.0, 0.0, 0.0, 0.0);
}
float intensity = 0;
for (int i = 0; i < 2; i++)
{
if (any(shadowObjects[i].xyz != fixed3(0.0, 0.0, 0.0))) { // nullcheck to prevent division by zero
float normalizedIntensity = (length(lightPosition.xyz - shadowObjects[i].xyz)) / _ShadowRange; // _ShadowRange
float saturation = 1 - saturate(normalizedIntensity);
intensity += saturation;
}
}
return fixed4(0.0, 0.0, 0.0, shadowalpha * intensity); // using a light
}
ENDCG
}
Pass
{
Tags{ "LightMode" = "ShadowCaster" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_shadowcaster
#include "UnityCG.cginc"
struct v2f {
V2F_SHADOW_CASTER;
};
v2f vert(appdata_base v)
{
v2f o;
TRANSFER_SHADOW_CASTER_NORMALOFFSET(o)
return o;
}
float4 frag(v2f i) : SV_Target
{
SHADOW_CASTER_FRAGMENT(i)
}
ENDCG
}
}
}
Also i pass the lights position and the objects position to the shader every update:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PassShaderValues : MonoBehaviour {
[SerializeField]
private Material _material;
[SerializeField]
private GameObject[] _shadowObjects;
[SerializeField]
private GameObject _light;
private Vector4[] _shadowPositions = new Vector4[5]; // just temp size
void Start () {
}
// Update is called once per frame
void Update () {
for (int i = 0; i < _shadowObjects.Length; i++) {
Vector3 pos = _shadowObjects[i].transform.position;
_shadowPositions[i] = new Vector4(pos.x, pos.y, pos.z, 1.0f);
}
_material.SetVectorArray("shadowObjects", _shadowPositions);
_material.SetVector("lightPosition", _light.transform.position);
}
}
What am I doing wrong?