You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
KSP-Conformal-Decals/Assets/Shaders/DecalsCommon.cginc

288 lines
8.3 KiB
HLSL

#ifndef DECALS_COMMON_INCLUDED
#define DECALS_COMMON_INCLUDED
struct DecalSurfaceInput
{
float2 uv_decal;
#ifdef DECAL_NORMAL
float2 uv_bump;
#endif //DECAL_NORMAL
#ifdef DECAL_SPECULAR
float2 uv_spec;
#endif //DECAL_SPECULAR
#ifdef DECAL_EMISSIVE
float2 uv_glow;
#endif //DECAL_EMISSIVE
#ifdef DECAL_BASE_NORMAL
float3 normal;
#endif
float3 viewDir;
float3 worldPosition;
};
struct appdata_decal
{
float4 vertex : POSITION;
float3 normal : NORMAL;
#if defined(DECAL_BASE_NORMAL) || defined(DECAL_PREVIEW)
float4 texcoord : TEXCOORD0;
float4 tangent : TANGENT;
#endif
};
struct v2f
{
UNITY_POSITION(pos);
float3 normal : NORMAL;
float4 uv_decal : TEXCOORD0;
#ifdef DECAL_BASE_NORMAL
float2 uv_base : TEXCOORD1;
#endif //DECAL_BASE_NORMAL
float4 tSpace0 : TEXCOORD2;
float4 tSpace1 : TEXCOORD3;
float4 tSpace2 : TEXCOORD4;
#ifdef UNITY_PASS_FORWARDBASE
fixed3 vlight : TEXCOORD5;
UNITY_SHADOW_COORDS(6)
#endif //UNITY_PASS_FORWARDBASE
#ifdef UNITY_PASS_FORWARDADD
UNITY_LIGHTING_COORDS(5,6)
#endif //UNITY_PASS_FORWARDADD
};
// Projection matrix, normal, and tangent vectors
float4x4 _ProjectionMatrix;
float3 _DecalNormal;
float3 _DecalTangent;
#ifdef DECAL_BASE_NORMAL
sampler2D _BumpMap;
float4 _BumpMap_ST;
#endif //DECAL_BASE_NORMAL
float _Cutoff;
float _DecalOpacity;
float _Opacity;
float4 _Background;
inline void decalClipAlpha(float alpha) {
#ifndef DECAL_PREVIEW
clip(alpha - 0.001);
#endif
}
inline float CalcMipLevel(float2 texture_coord) {
float2 dx = ddx(texture_coord);
float2 dy = ddy(texture_coord);
float delta_max_sqr = max(dot(dx, dx), dot(dy, dy));
return 0.5 * log2(delta_max_sqr);
}
// modifed version of the KSP BlinnPhong because it does some weird things
inline fixed4 LightingBlinnPhongDecal(SurfaceOutput s, fixed3 lightDir, half3 viewDir, fixed atten)
{
s.Normal = normalize(s.Normal);
half3 h = normalize(lightDir + viewDir);
fixed diff = max(0, dot(s.Normal, lightDir));
float nh = max(0, dot(s.Normal, h));
float spec = pow(nh, s.Specular*128.0) * s.Gloss;
fixed4 c = 0;
c.rgb = (s.Albedo * _LightColor0.rgb * diff + _LightColor0.rgb * _SpecColor.rgb * spec) * (atten);
return c;
}
// declare surf function,
// this must be defined in any shader using this cginc
void surf (DecalSurfaceInput IN, inout SurfaceOutput o);
v2f vert_forward(appdata_decal v)
{
v2f o;
UNITY_INITIALIZE_OUTPUT(v2f,o);
o.pos = UnityObjectToClipPos(v.vertex);
o.normal = v.normal;
#ifdef DECAL_PREVIEW
o.uv_decal = v.texcoord;
#else
o.uv_decal = mul (_ProjectionMatrix, v.vertex);
#endif //DECAL_PREVIEW
#ifdef DECAL_BASE_NORMAL
o.uv_base = TRANSFORM_TEX(v.texcoord, _BumpMap);
#endif //DECAL_BASE_NORMAL
float3 worldPosition = mul(unity_ObjectToWorld, v.vertex).xyz;
float3 worldNormal = UnityObjectToWorldNormal(v.normal);
#if defined(DECAL_BASE_NORMAL) || defined(DECAL_PREVIEW)
// use tangent of base geometry
fixed3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz);
fixed tangentSign = v.tangent.w * unity_WorldTransformParams.w;
fixed3 worldBinormal = cross(worldNormal, worldTangent) * tangentSign;
#else
// use tangent of projector
fixed3 decalTangent = UnityObjectToWorldDir(_DecalTangent);
fixed3 worldBinormal = cross(decalTangent, worldNormal);
fixed3 worldTangent = cross(worldNormal, worldBinormal);
#endif //defined(DECAL_BASE_NORMAL) || defined(DECAL_PREVIEW)
o.tSpace0 = float4(worldTangent.x, worldBinormal.x, worldNormal.x, worldPosition.x);
o.tSpace1 = float4(worldTangent.y, worldBinormal.y, worldNormal.y, worldPosition.y);
o.tSpace2 = float4(worldTangent.z, worldBinormal.z, worldNormal.z, worldPosition.z);
// forward base pass specific lighting code
#ifdef UNITY_PASS_FORWARDBASE
// SH/ambient light
#if UNITY_SHOULD_SAMPLE_SH
float3 shlight = ShadeSH9 (float4(worldNormal,1.0));
o.vlight = shlight;
#else
o.vlight = 0.0;
#endif // UNITY_SHOULD_SAMPLE_SH
// vertex light
#ifdef VERTEXLIGHT_ON
o.vlight += Shade4PointLights (
unity_4LightPosX0, unity_4LightPosY0, unity_4LightPosZ0,
unity_LightColor[0].rgb, unity_LightColor[1].rgb, unity_LightColor[2].rgb, unity_LightColor[3].rgb,
unity_4LightAtten0, worldPosition, worldNormal );
#endif // VERTEXLIGHT_ON
#endif // UNITY_PASS_FORWARDBASE
// pass shadow and, possibly, light cookie coordinates to pixel shader
UNITY_TRANSFER_LIGHTING(o, 0.0);
return o;
}
fixed4 frag_forward(v2f IN) : SV_Target
{
// declare data
DecalSurfaceInput i;
SurfaceOutput o;
fixed4 c = 0;
// setup world-space TBN vectors
UNITY_EXTRACT_TBN(IN);
float3 worldPosition = float3(IN.tSpace0.w, IN.tSpace1.w, IN.tSpace2.w);
float3 worldTangent = float3(IN.tSpace0.x, IN.tSpace1.x, IN.tSpace2.x);
// setup world-space light and view direction vectors
#ifndef USING_DIRECTIONAL_LIGHT
fixed3 lightDir = normalize(UnityWorldSpaceLightDir(worldPosition));
#else
fixed3 lightDir = _WorldSpaceLightPos0.xyz;
#endif
float3 worldViewDir = normalize(UnityWorldSpaceViewDir(worldPosition));
float3 viewDir = _unity_tbn_0 * worldViewDir.x + _unity_tbn_1 * worldViewDir.y + _unity_tbn_2 * worldViewDir.z;
#ifdef DECAL_PREVIEW
fixed4 uv_projected = IN.uv_decal;
#else
// perform decal projection
fixed4 uv_projected = UNITY_PROJ_COORD(IN.uv_decal);
// clip texture outside of xyz bounds
clip(uv_projected.xyz);
clip(1-uv_projected.xyz);
// clip backsides
clip(dot(_DecalNormal, IN.normal));
#endif //DECAL_PREVIEW
// initialize surface input
UNITY_INITIALIZE_OUTPUT(DecalSurfaceInput, i)
i.uv_decal = TRANSFORM_TEX(uv_projected, _Decal);
#ifdef DECAL_NORMAL
i.uv_bump = TRANSFORM_TEX(uv_projected, _DecalBumpMap);
#endif //DECAL_NORMAL
#ifdef DECAL_SPECULAR
i.uv_spec = TRANSFORM_TEX(uv_projected, _SpecMap);
#endif //DECAL_SPECULAR
#ifdef DECAL_EMISSIVE
i.uv_glow = TRANSFORM_TEX(uv_projected, _GlowMap);
#endif //DECAL_EMISSIVE
#ifdef DECAL_BASE_NORMAL
#ifdef DECAL_PREVIEW
i.normal = fixed3(0,0,1);
#else
i.normal = UnpackNormalDXT5nm(tex2D(_BumpMap, IN.uv_base));
#endif //DECAL_PREVIEW
#endif //DECAL_BASE_NORMAL
//i.normal = IN.normal;
i.viewDir = viewDir;
i.worldPosition = worldPosition;
// initialize surface output
o.Albedo = 0.0;
o.Emission = 0.0;
o.Specular = 0.0;
o.Alpha = 0.0;
o.Gloss = 0.0;
o.Normal = fixed3(0,0,1);
// call surface function
surf(i, o);
#ifdef DECAL_PREVIEW
if (any(IN.uv_decal > 1) || any(IN.uv_decal < 0)) o.Alpha = 0;
o.Albedo = lerp(_Background.rgb, o.Albedo, o.Alpha) * _Color.rgb;
o.Normal = lerp(float3(0,0,1), o.Normal, o.Alpha);
o.Gloss = lerp(_Background.a, o.Gloss, o.Alpha);
o.Emission = lerp(0, o.Emission, o.Alpha);
o.Alpha = _Opacity;
#endif //DECAL_PREVIEW
// compute lighting & shadowing factor
UNITY_LIGHT_ATTENUATION(atten, IN, worldPosition)
// compute world normal
float3 WorldNormal;
WorldNormal.x = dot(_unity_tbn_0, o.Normal);
WorldNormal.y = dot(_unity_tbn_1, o.Normal);
WorldNormal.z = dot(_unity_tbn_2, o.Normal);
WorldNormal = normalize(WorldNormal);
o.Normal = WorldNormal;
//call modified KSP lighting function
c += LightingBlinnPhongDecal(o, lightDir, worldViewDir, atten);
// Forward base emission and ambient/vertex lighting
#ifdef UNITY_PASS_FORWARDBASE
c.rgb += o.Emission;
c.rgb += o.Albedo * IN.vlight;
c.a = o.Alpha;
#endif //UNITY_PASS_FORWARDBASE
// Forward add multiply by alpha
#ifdef UNITY_PASS_FORWARDADD
c.rgb *= o.Alpha;
#endif
return c;
}
#endif