181 lines
4.5 KiB
Plaintext
181 lines
4.5 KiB
Plaintext
Shader "Obi/Particles" {
|
|
|
|
Properties {
|
|
_Color ("Particle color", Color) = (1,1,1,1)
|
|
}
|
|
|
|
SubShader {
|
|
|
|
Pass {
|
|
|
|
Name "ParticleFwdBase"
|
|
Tags {"Queue"="Geometry" "IgnoreProjector"="True" "RenderType"="Opaque" "LightMode" = "ForwardBase"}
|
|
Blend SrcAlpha OneMinusSrcAlpha
|
|
|
|
CGPROGRAM
|
|
#pragma vertex vert
|
|
#pragma fragment frag
|
|
#pragma fragmentoption ARB_precision_hint_fastest
|
|
|
|
#pragma multi_compile_fwdbase
|
|
|
|
#include "ObiParticles.cginc"
|
|
|
|
struct vin{
|
|
float4 vertex : POSITION;
|
|
float3 corner : NORMAL;
|
|
fixed4 color : COLOR;
|
|
float3 texcoord : TEXCOORD0;
|
|
};
|
|
|
|
struct v2f
|
|
{
|
|
float4 pos : SV_POSITION;
|
|
fixed4 color : COLOR;
|
|
float3 texcoord : TEXCOORD0;
|
|
float3 lightDir : TEXCOORD1;
|
|
float4 viewpos : TEXCOORD2;
|
|
LIGHTING_COORDS(3,4)
|
|
};
|
|
|
|
v2f vert(vin v)
|
|
{
|
|
v2f o;
|
|
|
|
// particle positions are passed in world space, no need to use modelview matrix, just view.
|
|
o.viewpos = mul(UNITY_MATRIX_V, v.vertex) + float4(v.corner.x, v.corner.y, 0, 0) * v.corner.z; // multiply by size.
|
|
o.pos = mul(UNITY_MATRIX_P, o.viewpos);
|
|
o.texcoord = float3(v.corner.x*0.5+0.5, v.corner.y*0.5+0.5, v.corner.z);
|
|
o.color = v.color;
|
|
|
|
o.lightDir = mul ((float3x3)UNITY_MATRIX_MV, ObjSpaceLightDir(v.vertex));
|
|
|
|
TRANSFER_VERTEX_TO_FRAGMENT(o);
|
|
|
|
return o;
|
|
}
|
|
|
|
fixed4 _Color;
|
|
fixed4 _LightColor0;
|
|
|
|
fout frag(v2f i)
|
|
{
|
|
fout fo;
|
|
|
|
fo.color = half4(0,0,0,1);
|
|
|
|
// generate sphere normals:
|
|
float3 n = BillboardSphereNormals(i.texcoord);
|
|
|
|
// update fragment position:
|
|
float sphereRadius = i.texcoord.z;
|
|
float4 pixelPos = float4(i.viewpos + n * sphereRadius, 1.0f);
|
|
|
|
// clip space position:
|
|
float4 pos = mul(UNITY_MATRIX_P,pixelPos);
|
|
|
|
// simple lighting: ambient
|
|
half3 amb = SampleSphereAmbient(n,pixelPos);
|
|
|
|
// simple lighting: diffuse
|
|
float ndotl = saturate( dot( n, normalize(i.lightDir) ) );
|
|
UNITY_LIGHT_ATTENUATION(atten,i,0);
|
|
|
|
// final lit color:
|
|
fo.color.rgb = _Color * i.color * (_LightColor0 * ndotl * atten + amb);
|
|
|
|
// normalized device coordinates:
|
|
fo.depth = pos.z/pos.w;
|
|
|
|
// in openGL calculated depth range is <-1,1> map it to <0,1>
|
|
#if SHADER_API_OPENGL || SHADER_API_GLCORE || SHADER_API_GLES || SHADER_API_GLES3
|
|
fo.depth = 0.5*fo.depth + 0.5;
|
|
#endif
|
|
|
|
return fo;
|
|
}
|
|
|
|
ENDCG
|
|
|
|
}
|
|
|
|
Pass {
|
|
Name "ShadowCaster"
|
|
Tags { "LightMode" = "ShadowCaster" }
|
|
Offset 1, 1
|
|
|
|
Fog {Mode Off}
|
|
ZWrite On ZTest LEqual
|
|
|
|
CGPROGRAM
|
|
|
|
#pragma target 3.0
|
|
#pragma vertex vert
|
|
#pragma fragment frag
|
|
#pragma fragmentoption ARB_precision_hint_fastest
|
|
|
|
#pragma multi_compile_shadowcaster
|
|
|
|
#include "ObiParticles.cginc"
|
|
|
|
struct vin{
|
|
float4 vertex : POSITION;
|
|
float3 corner : NORMAL;
|
|
float2 texcoord : TEXCOORD0;
|
|
};
|
|
|
|
struct v2f {
|
|
float3 texcoord : TEXCOORD0;
|
|
float4 viewpos : TEXCOORD1;
|
|
};
|
|
|
|
sampler3D _DitherMaskLOD;
|
|
|
|
v2f vert( vin v , out float4 outpos : SV_POSITION )// clip space position output
|
|
{
|
|
v2f o;
|
|
|
|
o.viewpos = mul(UNITY_MATRIX_V, v.vertex) + float4(v.corner.x, v.corner.y, 0, 0) * v.corner.z;
|
|
outpos = mul(UNITY_MATRIX_P, o.viewpos);
|
|
o.texcoord = float3(v.corner.x*0.5+0.5, v.corner.y*0.5+0.5, v.corner.z);
|
|
return o;
|
|
}
|
|
|
|
fout frag( v2f i , UNITY_VPOS_TYPE vpos : VPOS)
|
|
{
|
|
fout fo;
|
|
|
|
float3 n = BillboardSphereNormals(i.texcoord);
|
|
|
|
// update fragment position:
|
|
float sphereRadius = i.texcoord.z;
|
|
float4 pixelPos = float4(i.viewpos + n * sphereRadius, 1.0f);
|
|
|
|
// project camera space position.
|
|
float4 pos = UnityApplyLinearShadowBias( mul(UNITY_MATRIX_P,pixelPos) );
|
|
|
|
fo.color = pos.z/pos.w; //similar to what SHADOW_CASTER_FRAGMENT does in case there's no depth buffer.
|
|
fo.depth = pos.z/pos.w;
|
|
|
|
// in openGL calculated depth range is <-1,1> map it to <0,1>
|
|
#if SHADER_API_OPENGL || SHADER_API_GLCORE || SHADER_API_GLES || SHADER_API_GLES3
|
|
fo.depth = fo.depth*0.5+0.5;
|
|
#endif
|
|
|
|
// Use dither mask for alpha blended shadows, based on pixel position xy
|
|
// and alpha level. Our dither texture is 4x4x16.
|
|
float alpha = 1.0f; //TODO: give user control over this.
|
|
half alphaRef = tex3D(_DitherMaskLOD, float3(vpos.xy*0.25,alpha*0.9375)).a;
|
|
clip (alphaRef - 0.01);
|
|
|
|
return fo;
|
|
}
|
|
ENDCG
|
|
|
|
}
|
|
|
|
}
|
|
FallBack "Diffuse"
|
|
}
|
|
|