798 lines
26 KiB
HLSL
798 lines
26 KiB
HLSL
//////////////////////////////////////////////////////
|
|
// MK Toon Surface //
|
|
// //
|
|
// Created by Michael Kremmel //
|
|
// www.michaelkremmel.de //
|
|
// Copyright © 2021 All rights reserved. //
|
|
//////////////////////////////////////////////////////
|
|
|
|
#ifndef MK_TOON_SURFACE
|
|
#define MK_TOON_SURFACE
|
|
|
|
#include "Core.hlsl"
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
|
// Surface Data
|
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
|
//Dynamic precalc struct
|
|
struct MKSurfaceData
|
|
{
|
|
#ifdef MK_NORMAL
|
|
half3 vertexNormalWorld;
|
|
#endif
|
|
#ifdef MK_LIT
|
|
#ifdef MK_ENVIRONMENT_REFLECTIONS
|
|
float4 lightmapUV;
|
|
#endif
|
|
#ifdef MK_VERTEX_LIGHTING
|
|
half3 vertexLighting;
|
|
#endif
|
|
half3 normalWorld;
|
|
#ifdef MK_TBN
|
|
half3 tangentWorld;
|
|
half3 bitangentWorld;
|
|
#endif
|
|
#ifdef MK_PARALLAX
|
|
half height;
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef MK_VD
|
|
half3 viewWorld;
|
|
#endif
|
|
#ifdef MK_VD_O
|
|
half3 viewTangent;
|
|
#endif
|
|
|
|
#ifdef MK_POS_WORLD
|
|
float3 positionWorld;
|
|
#endif
|
|
#ifdef MK_FOG
|
|
float fogFactor;
|
|
#endif
|
|
|
|
#if defined(MK_VERTCLR) || defined(MK_PARTICLES) || defined(MK_POLYBRUSH)
|
|
autoLP4 vertexColor;
|
|
#endif
|
|
|
|
#if defined(MK_TCM) || defined(MK_TCD)
|
|
float4 baseUV;
|
|
#endif
|
|
#ifdef MK_THRESHOLD_MAP
|
|
float2 thresholdUV;
|
|
#endif
|
|
#if defined(MK_SCREEN_UV)
|
|
float4 screenUV;
|
|
#endif
|
|
#if defined(MK_REFRACTION)
|
|
float2 refractionUV;
|
|
#endif
|
|
#ifdef MK_ARTISTIC
|
|
float2 artisticUV;
|
|
#endif
|
|
#ifdef MK_FLIPBOOK
|
|
float3 flipbookUV;
|
|
#endif
|
|
#ifdef MK_DISSOLVE
|
|
half dissolveClip;
|
|
#endif
|
|
|
|
#ifdef MK_V_DOT_N
|
|
half VoN;
|
|
half OneMinusVoN;
|
|
#endif
|
|
#ifdef MK_MV_REF_N
|
|
half3 MVrN;
|
|
#endif
|
|
};
|
|
|
|
struct MKPBSData
|
|
{
|
|
half reflectivity;
|
|
half oneMinusReflectivity;
|
|
half roughness;
|
|
#if defined(MK_ENVIRONMENT_REFLECTIONS) || defined(MK_SPECULAR) || defined(MK_DIFFUSE_OREN_NAYAR) || defined(MK_DIFFUSE_MINNAERT)
|
|
half roughnessPow2;
|
|
#endif
|
|
#if defined(MK_ENVIRONMENT_REFLECTIONS) || defined(MK_SPECULAR)
|
|
half roughnessPow4;
|
|
#endif
|
|
half smoothness;
|
|
half3 diffuseRadiance;
|
|
half3 specularRadiance;
|
|
#ifdef MK_FRESNEL_HIGHLIGHTS
|
|
half3 fresnel;
|
|
#endif
|
|
};
|
|
|
|
//dynamic surface struct
|
|
struct Surface
|
|
{
|
|
half4 final;
|
|
half3 albedo;
|
|
half alpha;
|
|
#ifdef MK_REFRACTION
|
|
half3 refraction;
|
|
#endif
|
|
|
|
// RGB - RAW
|
|
#if defined(MK_LIT)
|
|
#ifdef MK_THRESHOLD_MAP
|
|
half thresholdOffset;
|
|
#endif
|
|
half4 goochBright;
|
|
half4 goochDark;
|
|
half2 occlusion;
|
|
#ifdef MK_EMISSION
|
|
half3 emission;
|
|
#endif
|
|
|
|
#ifdef MK_INDIRECT
|
|
half3 indirect;
|
|
#endif
|
|
half4 direct;
|
|
|
|
#ifdef MK_ARTISTIC
|
|
#if defined(MK_ARTISTIC_DRAWN) || defined(MK_ARTISTIC_SKETCH)
|
|
half artistic0;
|
|
#elif defined(MK_ARTISTIC_HATCHING)
|
|
half3 artistic0;
|
|
half3 artistic1;
|
|
#endif
|
|
#endif
|
|
#ifdef MK_THICKNESS_MAP
|
|
half thickness;
|
|
#endif
|
|
#if defined(MK_RIM)
|
|
half4 rim;
|
|
#endif
|
|
#ifdef MK_IRIDESCENCE
|
|
half4 iridescence;
|
|
#endif
|
|
#endif
|
|
};
|
|
|
|
half3 FresnelSchlickGGXIBL(half oneMinusVoN, half3 f0, half smoothness)
|
|
{
|
|
return FastPow5(oneMinusVoN) * (max(smoothness, f0) - f0) + f0;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
|
// Header macros
|
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
|
#ifdef MK_PBS
|
|
#define PASS_BLENDING_ARG(surface, surfaceData, pbsData) surface, surfaceData, pbsData
|
|
#else
|
|
#define PASS_BLENDING_ARG(surface, surfaceData, pbsData) surface, surfaceData
|
|
#endif
|
|
|
|
#ifdef MK_FLIPBOOK
|
|
#define SURFACE_FLIPBOOK_UV surfaceData.flipbookUV
|
|
#else
|
|
#define SURFACE_FLIPBOOK_UV 0
|
|
#endif
|
|
|
|
#ifdef MK_POS_WORLD
|
|
#define PASS_POSITION_WORLD_ARG(positionWorld) positionWorld
|
|
#else
|
|
#define PASS_POSITION_WORLD_ARG(positionWorld) 0
|
|
#endif
|
|
|
|
#ifdef MK_FOG
|
|
#define PASS_FOG_FACTOR_WORLD_ARG(fogFacor) ,fogFacor
|
|
#else
|
|
#define PASS_FOG_FACTOR_WORLD_ARG(fogFacor)
|
|
#endif
|
|
|
|
#if defined(MK_TCM) || defined(MK_TCD)
|
|
#define PASS_BASE_UV_ARG(baseUV) ,baseUV
|
|
#else
|
|
#define PASS_BASE_UV_ARG(baseUV)
|
|
#endif
|
|
|
|
#if defined(MK_VERTCLR) || defined(MK_PARTICLES) || defined(MK_POLYBRUSH)
|
|
#define PASS_VERTEX_COLOR_ARG(vertexColor) ,vertexColor
|
|
#else
|
|
#define PASS_VERTEX_COLOR_ARG(vertexColor)
|
|
#endif
|
|
|
|
#if defined(MK_NORMAL)
|
|
#define PASS_NORMAL_WORLD_ARG(normalWorld) ,normalWorld
|
|
#else
|
|
#define PASS_NORMAL_WORLD_ARG(normalWorld)
|
|
#endif
|
|
|
|
#if defined(MK_VERTEX_LIGHTING)
|
|
#define PASS_VERTEX_LIGHTING_ARG(vertexLighting) ,vertexLighting
|
|
#else
|
|
#define PASS_VERTEX_LIGHTING_ARG(vertexLighting)
|
|
#endif
|
|
|
|
#if defined(MK_TBN)
|
|
#define PASS_TANGENT_WORLD_ARG(tangentWorld) ,tangentWorld
|
|
#define PASS_BITANGENT_WORLD_ARG(bitangentWorld) ,bitangentWorld
|
|
#else
|
|
#define PASS_TANGENT_WORLD_ARG(bitangentWorld)
|
|
#define PASS_BITANGENT_WORLD_ARG(bitangentWorld)
|
|
#endif
|
|
|
|
#ifdef MK_ENVIRONMENT_REFLECTIONS
|
|
#define PASS_LIGHTMAP_UV_ARG(lightmapUV) ,lightmapUV
|
|
#else
|
|
#define PASS_LIGHTMAP_UV_ARG(lightmapUV)
|
|
#endif
|
|
|
|
#if defined(MK_PARALLAX)
|
|
#define PASS_VIEW_TANGENT_ARG(viewTangent) ,viewTangent
|
|
#else
|
|
#define PASS_VIEW_TANGENT_ARG(viewTangent)
|
|
#endif
|
|
|
|
#ifdef MK_POS_CLIP
|
|
#define PASS_POSITION_CLIP_ARG(positionClip) ,positionClip
|
|
#else
|
|
#define PASS_POSITION_CLIP_ARG(positionClip)
|
|
#endif
|
|
|
|
#ifdef MK_POS_NULL_CLIP
|
|
#define PASS_NULL_CLIP_ARG(nullClip) ,nullClip
|
|
#else
|
|
#define PASS_NULL_CLIP_ARG(nullClip)
|
|
#endif
|
|
|
|
#ifdef MK_FLIPBOOK
|
|
#define PASS_FLIPBOOK_UV_ARG(flipbookUV) ,flipbookUV
|
|
#else
|
|
#define PASS_FLIPBOOK_UV_ARG(flipbookUV)
|
|
#endif
|
|
|
|
//Texture color
|
|
inline void SurfaceColor(out half3 albedo, out half alpha, DECLARE_TEXTURE_2D_ARGS(albedoMap, samplerTex), float2 uv, float3 blendUV, autoLP4 color)
|
|
{
|
|
half4 c;
|
|
#ifdef MK_OUTLINE_PASS
|
|
c = half4(color.rgb, SAMPLE_TEX2D_FLIPBOOK(albedoMap, SAMPLER_REPEAT_MAIN, uv, blendUV).a * color.a);
|
|
#else
|
|
c = SAMPLE_TEX2D_FLIPBOOK(albedoMap, SAMPLER_REPEAT_MAIN, uv, blendUV) * color;
|
|
#endif
|
|
albedo = c.rgb;
|
|
#if defined(MK_ALPHA_LOOKUP)
|
|
alpha = c.a;
|
|
#else
|
|
alpha = 1.0h;
|
|
#endif
|
|
}
|
|
|
|
inline void SurfaceColor(out half3 albedo, out half alpha, DECLARE_TEXTURE_2D_ARGS(albedoMap, samplerTex), DECLARE_TEXTURE_2D_ARGS(albedoMap1, samplerTex1), DECLARE_TEXTURE_2D_ARGS(albedoMap2, samplerTex2), DECLARE_TEXTURE_2D_ARGS(albedoMap3, samplerTex3), float2 uv, autoLP4 blendColor, float3 blendUV, autoLP4 color)
|
|
{
|
|
half4 c0, c1, c2, c3;
|
|
#ifdef MK_OUTLINE_PASS
|
|
c0 = half4(color.rgb, SAMPLE_TEX2D_FLIPBOOK(albedoMap, SAMPLER_REPEAT_MAIN, uv, blendUV).a * color.a);
|
|
c1 = half4(color.rgb, SAMPLE_TEX2D_FLIPBOOK(albedoMap1, SAMPLER_REPEAT_MAIN, uv, blendUV).a) * blendColor.g;
|
|
c2 = half4(color.rgb, SAMPLE_TEX2D_FLIPBOOK(albedoMap2, SAMPLER_REPEAT_MAIN, uv, blendUV).a) * blendColor.b;
|
|
c3 = half4(color.rgb, SAMPLE_TEX2D_FLIPBOOK(albedoMap3, SAMPLER_REPEAT_MAIN, uv, blendUV).a) * blendColor.a;
|
|
#else
|
|
c0 = SAMPLE_TEX2D_FLIPBOOK(albedoMap, SAMPLER_REPEAT_MAIN, uv, blendUV) * color;
|
|
c1 = SAMPLE_TEX2D_FLIPBOOK(albedoMap1, SAMPLER_REPEAT_MAIN, uv, blendUV) * blendColor.y;
|
|
c2 = SAMPLE_TEX2D_FLIPBOOK(albedoMap2, SAMPLER_REPEAT_MAIN, uv, blendUV) * blendColor.z;
|
|
c3 = SAMPLE_TEX2D_FLIPBOOK(albedoMap3, SAMPLER_REPEAT_MAIN, uv, blendUV) * blendColor.w;
|
|
#endif
|
|
|
|
half4 mixedColor = lerp(lerp(lerp(c0, c1, blendColor.g), c2, blendColor.b), c3, blendColor.a);
|
|
|
|
albedo = mixedColor.rgb;
|
|
#if defined(MK_ALPHA_LOOKUP)
|
|
alpha = mixedColor.a;
|
|
#else
|
|
alpha = 1.0h;
|
|
#endif
|
|
}
|
|
|
|
//Non texture color
|
|
inline void SurfaceColor(out half3 albedo, out half alpha, autoLP4 vertexColor, autoLP4 color)
|
|
{
|
|
half4 c = vertexColor * color;
|
|
albedo = c.rgb;
|
|
#if defined(MK_ALPHA_LOOKUP)
|
|
alpha = c.a;
|
|
#else
|
|
alpha = 1.0h;
|
|
#endif
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
|
// Initialize
|
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
|
inline MKSurfaceData ComputeSurfaceData
|
|
(
|
|
//#ifdef MK_POS_WORLD
|
|
in float3 positionWorld
|
|
//#endif
|
|
#ifdef MK_FOG
|
|
, in float fogFactor
|
|
#endif
|
|
#if defined(MK_TCM) || defined(MK_TCD)
|
|
, in float4 baseUV
|
|
#endif
|
|
#ifdef MK_ENVIRONMENT_REFLECTIONS
|
|
, in float4 lightmapUV
|
|
#endif
|
|
#if defined(MK_VERTCLR) || defined(MK_PARTICLES) || defined(MK_POLYBRUSH)
|
|
, in autoLP4 vertexColor
|
|
#endif
|
|
#ifdef MK_NORMAL
|
|
, in half3 normalWorld
|
|
#endif
|
|
#ifdef MK_VERTEX_LIGHTING
|
|
, in autoLP3 vertexLighting
|
|
#endif
|
|
#if defined(MK_TBN)
|
|
, in half3 tangentWorld
|
|
#endif
|
|
#if defined(MK_PARALLAX)
|
|
, in half3 viewTangent
|
|
#endif
|
|
#if defined(MK_TBN)
|
|
, in half3 bitangentWorld
|
|
#endif
|
|
#ifdef MK_POS_CLIP
|
|
, in float4 positionClip
|
|
#endif
|
|
#ifdef MK_POS_NULL_CLIP
|
|
, in float4 nullClip
|
|
#endif
|
|
#ifdef MK_FLIPBOOK
|
|
, in float3 flipbookUV
|
|
#endif
|
|
)
|
|
{
|
|
MKSurfaceData surfaceData;
|
|
INITIALIZE_STRUCT(MKSurfaceData, surfaceData);
|
|
|
|
#ifdef MK_POS_WORLD
|
|
surfaceData.positionWorld = positionWorld;
|
|
#endif
|
|
#ifdef MK_FOG
|
|
surfaceData.fogFactor = fogFactor;
|
|
#endif
|
|
|
|
#if defined(MK_VERTCLR) || defined(MK_PARTICLES) || defined(MK_POLYBRUSH)
|
|
surfaceData.vertexColor = vertexColor;
|
|
#endif
|
|
|
|
#if defined(MK_TCM) || defined(MK_TCD)
|
|
surfaceData.baseUV = 0;
|
|
#endif
|
|
#if defined(MK_TCM)
|
|
surfaceData.baseUV.xy = baseUV.xy * _AlbedoMap_ST.xy + _AlbedoMap_ST.zw;
|
|
#endif
|
|
#if defined(MK_TCD)
|
|
surfaceData.baseUV.zw = baseUV.zw;
|
|
#endif
|
|
|
|
#ifdef MK_FLIPBOOK
|
|
SURFACE_FLIPBOOK_UV = flipbookUV;
|
|
#endif
|
|
|
|
#ifdef MK_VD
|
|
surfaceData.viewWorld = SafeNormalize(CAMERA_POSITION_WORLD - surfaceData.positionWorld);
|
|
#endif
|
|
|
|
#ifdef MK_VD_O
|
|
surfaceData.viewTangent = SafeNormalize(viewTangent);
|
|
#endif
|
|
|
|
#ifdef MK_PARALLAX
|
|
surfaceData.height = SAMPLE_TEX2D_FLIPBOOK(_HeightMap, SAMPLER_REPEAT_MAIN, surfaceData.baseUV.xy, SURFACE_FLIPBOOK_UV).r;
|
|
float2 parallaxUVOffset = Parallax(surfaceData.viewTangent, surfaceData.height, _Parallax, 0.42);
|
|
|
|
#if defined(MK_TCM)
|
|
surfaceData.baseUV.xy += parallaxUVOffset;
|
|
#endif
|
|
#if defined(MK_TCD)
|
|
surfaceData.baseUV.zw += parallaxUVOffset;
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef MK_THRESHOLD_MAP
|
|
surfaceData.thresholdUV = surfaceData.baseUV.xy * _ThresholdMapScale;
|
|
#endif
|
|
|
|
#if defined(MK_SCREEN_UV)
|
|
surfaceData.screenUV = ComputeNDC(positionClip);
|
|
#endif
|
|
|
|
#if defined(MK_ARTISTIC)
|
|
#if defined(MK_ARTISTIC_DRAWN)
|
|
#if defined(MK_ARTISTIC_PROJECTION_SCREEN_SPACE)
|
|
surfaceData.artisticUV = ComputeNormalizedScreenUV(surfaceData.screenUV, ComputeNDC(nullClip), _DrawnMapScale);
|
|
#else
|
|
surfaceData.artisticUV = surfaceData.baseUV.xy * _DrawnMapScale;
|
|
#endif
|
|
#elif defined(MK_ARTISTIC_HATCHING)
|
|
#if defined(MK_ARTISTIC_PROJECTION_SCREEN_SPACE)
|
|
surfaceData.artisticUV = ComputeNormalizedScreenUV(surfaceData.screenUV, ComputeNDC(nullClip), _HatchingMapScale);
|
|
#else
|
|
surfaceData.artisticUV = surfaceData.baseUV.xy * _HatchingMapScale;
|
|
#endif
|
|
#elif defined(MK_ARTISTIC_SKETCH)
|
|
#if defined(MK_ARTISTIC_PROJECTION_SCREEN_SPACE)
|
|
surfaceData.artisticUV = ComputeNormalizedScreenUV(surfaceData.screenUV, ComputeNDC(nullClip), _SketchMapScale);
|
|
#else
|
|
surfaceData.artisticUV = surfaceData.baseUV.xy * _SketchMapScale;
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef MK_ARTISTIC_ANIMATION_STUTTER
|
|
surfaceData.artisticUV.xy += Stutter(_Time.y, _ArtisticFrequency);
|
|
#endif
|
|
#endif
|
|
|
|
//dissolve could be moved above the screen uv to safe some instructions while clipping
|
|
#ifdef MK_DISSOLVE
|
|
float2 dissolveUV;
|
|
#ifdef MK_DISSOLVE_PROJECTION_SCREEN_SPACE
|
|
dissolveUV = ComputeNormalizedScreenUV(surfaceData.screenUV, ComputeNDC(nullClip), _DissolveMapScale);
|
|
#else
|
|
dissolveUV = surfaceData.baseUV.xy;
|
|
#endif
|
|
surfaceData.dissolveClip = SAMPLE_TEX2D_FLIPBOOK(_DissolveMap, SAMPLER_REPEAT_MAIN, dissolveUV, SURFACE_FLIPBOOK_UV).r - _DissolveAmount;
|
|
Clip0(surfaceData.dissolveClip);
|
|
#endif
|
|
|
|
#ifdef MK_NORMAL
|
|
surfaceData.vertexNormalWorld = SafeNormalize(normalWorld);
|
|
#endif
|
|
#ifdef MK_TBN
|
|
surfaceData.tangentWorld = SafeNormalize(tangentWorld);
|
|
surfaceData.bitangentWorld = SafeNormalize(bitangentWorld);
|
|
#endif
|
|
#if defined(MK_LIT)
|
|
//get normal direction
|
|
#ifdef MK_TBN
|
|
//Normalmap extraction
|
|
#if defined(MK_NORMAL_MAP) && !defined(MK_DETAIL_NORMAL_MAP)
|
|
surfaceData.normalWorld = NormalMappingWorld(PASS_TEXTURE_2D(_NormalMap, SAMPLER_REPEAT_MAIN), surfaceData.baseUV.xy, SURFACE_FLIPBOOK_UV, _NormalMapIntensity, half3x3(surfaceData.tangentWorld, surfaceData.bitangentWorld, surfaceData.vertexNormalWorld));
|
|
#elif defined(MK_NORMAL_MAP) && defined(MK_DETAIL_NORMAL_MAP)
|
|
surfaceData.normalWorld = NormalMappingWorld(PASS_TEXTURE_2D(_NormalMap, SAMPLER_REPEAT_MAIN), surfaceData.baseUV.xy, SURFACE_FLIPBOOK_UV, _NormalMapIntensity, PASS_TEXTURE_2D(_DetailNormalMap, SAMPLER_REPEAT_MAIN), surfaceData.baseUV.zw, _DetailNormalMapIntensity, half3x3(surfaceData.tangentWorld, surfaceData.bitangentWorld, surfaceData.vertexNormalWorld));
|
|
#elif !defined(MK_NORMAL_MAP) && defined(MK_DETAIL_NORMAL_MAP)
|
|
surfaceData.normalWorld = NormalMappingWorld(PASS_TEXTURE_2D(_DetailNormalMap, SAMPLER_REPEAT_MAIN), surfaceData.baseUV.xy, SURFACE_FLIPBOOK_UV, _DetailNormalMapIntensity, half3x3(surfaceData.tangentWorld, surfaceData.bitangentWorld, surfaceData.vertexNormalWorld));
|
|
#else
|
|
surfaceData.normalWorld = surfaceData.vertexNormalWorld;
|
|
#endif
|
|
|
|
#ifdef MK_SPECULAR_ANISOTROPIC
|
|
//rebuild tangent and bitangent
|
|
surfaceData.tangentWorld = SafeNormalize(cross(surfaceData.normalWorld, half3(0.0, 1.0, 0.0)));
|
|
surfaceData.bitangentWorld = SafeNormalize(cross(surfaceData.normalWorld, surfaceData.tangentWorld));
|
|
#endif
|
|
#else
|
|
surfaceData.normalWorld = surfaceData.vertexNormalWorld;
|
|
#endif
|
|
|
|
#ifdef MK_VERTEX_LIGHTING
|
|
surfaceData.vertexLighting = vertexLighting;
|
|
#endif
|
|
#ifdef MK_ENVIRONMENT_REFLECTIONS
|
|
surfaceData.lightmapUV = lightmapUV;
|
|
#endif
|
|
#endif
|
|
|
|
#if defined(MK_REFRACTION)
|
|
#ifdef MK_INDEX_OF_REFRACTION
|
|
float3 ssY = float3(UNITY_MATRIX_V[1][0], UNITY_MATRIX_V[1][1], UNITY_MATRIX_V[1][2]);
|
|
float3 ssX = normalize( cross(surfaceData.viewWorld, ssY));
|
|
|
|
float4x4 ssView = float4x4
|
|
(
|
|
ssX.x, ssX.y, ssX.z, 0,
|
|
ssY.x, ssY.y, ssY.z, 0,
|
|
surfaceData.viewWorld, 0,
|
|
0,0,0,1
|
|
);
|
|
|
|
float2 ssIOR = mul(ssView, float4(surfaceData.vertexNormalWorld, 0.0)).xy;
|
|
ssIOR.x *= SafeDivide(_ScreenParams.y, _ScreenParams.x);
|
|
ssIOR *= (1.0 - saturate(dot(surfaceData.vertexNormalWorld, surfaceData.viewWorld))) * _IndexOfRefraction;
|
|
surfaceData.refractionUV = surfaceData.screenUV.xy - ssIOR;
|
|
#else
|
|
surfaceData.refractionUV = surfaceData.screenUV.xy;
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef MK_V_DOT_N
|
|
surfaceData.VoN = saturate(dot(surfaceData.viewWorld, surfaceData.normalWorld));
|
|
surfaceData.OneMinusVoN = 1.0 - surfaceData.VoN;
|
|
#endif
|
|
#ifdef MK_MV_REF_N
|
|
surfaceData.MVrN = reflect(-surfaceData.viewWorld, surfaceData.normalWorld);
|
|
#endif
|
|
return surfaceData;
|
|
}
|
|
|
|
inline void ComputeBlending
|
|
(
|
|
inout Surface surface
|
|
, in MKSurfaceData surfaceData
|
|
#ifdef MK_PBS
|
|
, inout MKPBSData pbsData
|
|
#endif
|
|
)
|
|
{
|
|
#if defined(MK_BLEND_PREMULTIPLY) || defined(MK_BLEND_ADDITIVE)
|
|
#if defined(MK_PBS)
|
|
pbsData.diffuseRadiance *= surface.alpha;
|
|
half premulGISpec;
|
|
#ifdef MK_FRESNEL_HIGHLIGHTS
|
|
premulGISpec = dot(pbsData.fresnel, REL_LUMA);
|
|
#else
|
|
premulGISpec = pbsData.specularRadiance;
|
|
#endif
|
|
surface.alpha = surface.alpha * pbsData.oneMinusReflectivity + premulGISpec;
|
|
#else
|
|
surface.albedo *= surface.alpha;
|
|
#endif
|
|
#elif defined(MK_BLEND_MULTIPLY)
|
|
#if defined(MK_PBS)
|
|
surface.albedo = lerp(HALF3_ONE, surface.albedo, surface.alpha);
|
|
pbsData.diffuseRadiance = lerp(HALF3_ONE, pbsData.diffuseRadiance, surface.alpha * pbsData.oneMinusReflectivity + pbsData.reflectivity);
|
|
#else
|
|
surface.albedo = lerp(HALF3_ONE, surface.albedo, surface.alpha);
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef MK_SOFT_FADE
|
|
#if defined(MK_BLEND_PREMULTIPLY) || defined(MK_BLEND_ADDITIVE)
|
|
surface.albedo *= SoftFade(_SoftFadeNearDistance, _SoftFadeFarDistance, surfaceData.screenUV);
|
|
#else
|
|
surface.alpha *= SoftFade(_SoftFadeNearDistance, _SoftFadeFarDistance, surfaceData.screenUV);
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef MK_CAMERA_FADE
|
|
#if defined(MK_BLEND_PREMULTIPLY) || defined(MK_BLEND_ADDITIVE)
|
|
surface.albedo *= CameraFade(_CameraFadeNearDistance, _CameraFadeFarDistance, surfaceData.screenUV);
|
|
#else
|
|
surface.alpha *= CameraFade(_CameraFadeNearDistance, _CameraFadeFarDistance, surfaceData.screenUV);
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef MK_LIT
|
|
#if defined(MK_ALPHA_LOOKUP)
|
|
surface.goochBright.a *= surface.alpha;
|
|
surface.goochDark.a *= surface.alpha;
|
|
#endif
|
|
#endif
|
|
}
|
|
|
|
inline MKPBSData ComputePBSData(inout Surface surface, in MKSurfaceData surfaceData)
|
|
{
|
|
MKPBSData pbsData;
|
|
INITIALIZE_STRUCT(MKPBSData, pbsData);
|
|
|
|
half4 pbsInput;
|
|
|
|
#if defined(MK_WORKFLOW_METALLIC)
|
|
#ifdef MK_PBS_MAP_0
|
|
pbsInput = SAMPLE_TEX2D_FLIPBOOK(_MetallicMap, SAMPLER_REPEAT_MAIN, surfaceData.baseUV.xy, SURFACE_FLIPBOOK_UV).rrra;
|
|
pbsInput.a *= _Smoothness;
|
|
#else
|
|
pbsInput.rgb = _Metallic;
|
|
pbsInput.a = _Smoothness;
|
|
#endif
|
|
#elif defined(MK_WORKFLOW_ROUGHNESS)
|
|
#ifdef MK_PBS_MAP_0
|
|
pbsInput.rgb = SAMPLE_TEX2D_FLIPBOOK(_MetallicMap, SAMPLER_REPEAT_MAIN, surfaceData.baseUV.xy, SURFACE_FLIPBOOK_UV).rrr;
|
|
#else
|
|
pbsInput.rgb = _Metallic;
|
|
#endif
|
|
#ifdef MK_PBS_MAP_1
|
|
pbsInput.a = 1.0 - SAMPLE_TEX2D_FLIPBOOK(_RoughnessMap, SAMPLER_REPEAT_MAIN, surfaceData.baseUV.xy, SURFACE_FLIPBOOK_UV).r;
|
|
#else
|
|
pbsInput.a = 1.0 - _Roughness;
|
|
#endif
|
|
#else //MK_WORKFLOW_SPECULAR / Simple
|
|
#ifdef MK_PBS_MAP_0
|
|
pbsInput = SAMPLE_TEX2D_FLIPBOOK(_SpecularMap, SAMPLER_REPEAT_MAIN, surfaceData.baseUV.xy, SURFACE_FLIPBOOK_UV);
|
|
pbsInput.a *= _Smoothness;
|
|
#else
|
|
pbsInput.rgb = _SpecularColor.rgb;
|
|
pbsInput.a = _Smoothness;
|
|
#endif
|
|
#endif
|
|
|
|
#if defined(MK_WORKFLOW_METALLIC)
|
|
pbsData.smoothness = pbsInput.a;
|
|
pbsData.oneMinusReflectivity = K_SPEC_DIELECTRIC_MAX - pbsInput.r * K_SPEC_DIELECTRIC_MAX;
|
|
pbsData.reflectivity = 1.0 - pbsData.oneMinusReflectivity;
|
|
pbsData.specularRadiance = lerp(K_SPEC_DIELECTRIC_MIN, surface.albedo, pbsInput.r);
|
|
pbsData.diffuseRadiance = surface.albedo * (pbsData.oneMinusReflectivity * (1.0 - pbsData.specularRadiance));//surface.albedo * pbsData.oneMinusReflectivity;
|
|
#elif defined(MK_WORKFLOW_ROUGHNESS)
|
|
pbsData.smoothness = pbsInput.a;
|
|
pbsData.oneMinusReflectivity = K_SPEC_DIELECTRIC_MAX - pbsInput.r * K_SPEC_DIELECTRIC_MAX;
|
|
pbsData.reflectivity = 1.0 - pbsData.oneMinusReflectivity;
|
|
pbsData.specularRadiance = lerp(K_SPEC_DIELECTRIC_MIN, surface.albedo, pbsInput.r);
|
|
pbsData.diffuseRadiance = surface.albedo * ((1.0 - pbsData.specularRadiance) * pbsData.oneMinusReflectivity);
|
|
#elif defined(MK_WORKFLOW_SPECULAR)
|
|
pbsData.reflectivity = max(max(pbsInput.r, pbsInput.g), pbsInput.b);
|
|
pbsData.smoothness = pbsInput.a;
|
|
pbsData.oneMinusReflectivity = 1.0 - pbsData.reflectivity;
|
|
pbsData.specularRadiance = pbsInput.rgb;
|
|
pbsData.diffuseRadiance = surface.albedo * (half3(1.0, 1.0, 1.0) - pbsInput.rgb);
|
|
#else //Simple
|
|
pbsData.reflectivity = 0;
|
|
pbsData.smoothness = pbsInput.a;
|
|
pbsData.oneMinusReflectivity = 1.0 - pbsData.reflectivity;
|
|
pbsData.diffuseRadiance = surface.albedo;
|
|
pbsData.specularRadiance = pbsInput.rgb;
|
|
#endif
|
|
|
|
pbsData.roughness = 1.0 - pbsData.smoothness;
|
|
#if defined(MK_ENVIRONMENT_REFLECTIONS) || defined(MK_SPECULAR) || defined(MK_DIFFUSE_OREN_NAYAR) || defined(MK_DIFFUSE_MINNAERT)
|
|
pbsData.roughnessPow2 = FastPow2(pbsData.roughness);
|
|
#endif
|
|
#if defined(MK_ENVIRONMENT_REFLECTIONS) || defined(MK_SPECULAR)
|
|
pbsData.roughnessPow4 = FastPow2(pbsData.roughnessPow2);
|
|
#endif
|
|
|
|
#ifdef MK_FRESNEL_HIGHLIGHTS
|
|
pbsData.fresnel = FresnelSchlickGGXIBL(surfaceData.OneMinusVoN, pbsData.specularRadiance, pbsData.smoothness);
|
|
#endif
|
|
|
|
#ifdef MK_PBS
|
|
ComputeBlending(PASS_BLENDING_ARG(surface, surfaceData, pbsData));
|
|
#endif
|
|
|
|
return pbsData;
|
|
}
|
|
|
|
inline Surface InitSurface(in MKSurfaceData surfaceData, DECLARE_TEXTURE_2D_ARGS(albedoMap, samplerTex), inout half4 albedoTint)
|
|
{
|
|
//Init Surface
|
|
Surface surface;
|
|
INITIALIZE_STRUCT(Surface, surface);
|
|
|
|
#ifdef MK_ARTISTIC
|
|
#if defined(MK_ARTISTIC_DRAWN)
|
|
surface.artistic0 = 1.0 - SampleTex2D(PASS_TEXTURE_2D(_DrawnMap, SAMPLER_REPEAT_MAIN), surfaceData.artisticUV).r;
|
|
#elif defined(MK_ARTISTIC_SKETCH)
|
|
surface.artistic0 = SampleTex2D(PASS_TEXTURE_2D(_SketchMap, SAMPLER_REPEAT_MAIN), surfaceData.artisticUV).r;
|
|
#elif defined(MK_ARTISTIC_HATCHING)
|
|
surface.artistic0 = SampleTex2D(PASS_TEXTURE_2D(_HatchingDarkMap, SAMPLER_REPEAT_MAIN), surfaceData.artisticUV).rgb;
|
|
surface.artistic1 = SampleTex2D(PASS_TEXTURE_2D(_HatchingBrightMap, SAMPLER_REPEAT_MAIN), surfaceData.artisticUV).rgb;
|
|
#endif
|
|
#endif
|
|
|
|
//init surface color
|
|
#if defined(MK_TEXCLR)
|
|
#if defined(MK_PARTICLES) || defined(MK_COMBINE_VERTEX_COLOR_WITH_ALBEDO_MAP)
|
|
albedoTint *= surfaceData.vertexColor;
|
|
#endif
|
|
SurfaceColor(surface.albedo, surface.alpha, PASS_TEXTURE_2D(albedoMap, samplerTex), surfaceData.baseUV.xy, SURFACE_FLIPBOOK_UV, albedoTint);
|
|
#elif defined(MK_POLYBRUSH)
|
|
SurfaceColor(surface.albedo, surface.alpha, PASS_TEXTURE_2D(albedoMap, samplerTex), PASS_TEXTURE_2D(_AlbedoMap1, samplerTex), PASS_TEXTURE_2D(_AlbedoMap2, samplerTex), PASS_TEXTURE_2D(_AlbedoMap3, samplerTex), surfaceData.baseUV.xy, surfaceData.vertexColor, SURFACE_FLIPBOOK_UV, albedoTint);
|
|
#else
|
|
SurfaceColor(surface.albedo, surface.alpha, surfaceData.vertexColor, albedoTint);
|
|
#endif
|
|
|
|
//add detail
|
|
#ifdef MK_DETAIL_MAP
|
|
MixAlbedoDetail(surface.albedo, PASS_TEXTURE_2D(_DetailMap, SAMPLER_REPEAT_MAIN), surfaceData.baseUV.zw, SURFACE_FLIPBOOK_UV);
|
|
#endif
|
|
|
|
#if defined(MK_ALPHA_CLIPPING)
|
|
Clip0(surface.alpha - _AlphaCutoff);
|
|
#endif
|
|
|
|
#ifdef MK_REFRACTION
|
|
half2 refractionDir;
|
|
|
|
#ifdef MK_REFRACTION_DISTORTION_MAP
|
|
refractionDir = (_RefractionDistortion * REFRACTION_DISTORTION_SCALE * surface.alpha) * UnpackDudv(PASS_TEXTURE_2D(_RefractionDistortionMap, SAMPLER_REPEAT_MAIN), surfaceData.baseUV.xy * _RefractionDistortionMapScale, SURFACE_FLIPBOOK_UV);
|
|
#else
|
|
//currently disabled if no normal mapping is set, could be optimized using a procedural noise
|
|
refractionDir = 0;
|
|
#endif
|
|
|
|
surface.refraction = SampleRefraction(surfaceData.refractionUV + refractionDir);
|
|
surface.albedo.rgb = lerp(surface.refraction.rgb, surface.albedo.rgb, saturate(surface.alpha - _RefractionDistortionFade));
|
|
#endif
|
|
|
|
#ifdef MK_COLOR_GRADING_ALBEDO
|
|
surface.albedo = ColorGrading(surface.albedo, _Brightness, _Saturation, _Contrast);
|
|
#endif
|
|
|
|
#ifdef MK_LIT
|
|
#ifdef MK_THRESHOLD_MAP
|
|
surface.thresholdOffset = SAMPLE_TEX2D_FLIPBOOK(_ThresholdMap, SAMPLER_REPEAT_MAIN, surfaceData.thresholdUV, SURFACE_FLIPBOOK_UV).r;
|
|
#endif
|
|
surface.direct = 0;
|
|
|
|
surface.goochBright = _GoochBrightColor;
|
|
#ifdef MK_LEGACY_RP
|
|
#ifdef USING_DIRECTIONAL_LIGHT
|
|
surface.goochDark = _GoochDarkColor;
|
|
#else
|
|
surface.goochDark = 0;
|
|
#endif
|
|
#else
|
|
surface.goochDark = _GoochDarkColor;
|
|
#endif
|
|
|
|
#if defined(MK_GOOCH_BRIGHT_MAP)
|
|
surface.goochBright *= SAMPLE_TEX2D_FLIPBOOK(_GoochBrightMap, SAMPLER_REPEAT_MAIN, surfaceData.baseUV.xy, SURFACE_FLIPBOOK_UV);
|
|
#endif
|
|
#if defined(MK_GOOCH_DARK_MAP)
|
|
#ifdef MK_LEGACY_RP
|
|
#ifdef USING_DIRECTIONAL_LIGHT
|
|
surface.goochDark *= SAMPLE_TEX2D_FLIPBOOK(_GoochDarkMap, SAMPLER_REPEAT_MAIN, surfaceData.baseUV.xy, SURFACE_FLIPBOOK_UV);
|
|
#endif
|
|
#else
|
|
surface.goochDark *= SAMPLE_TEX2D_FLIPBOOK(_GoochDarkMap, SAMPLER_REPEAT_MAIN, surfaceData.baseUV.xy, SURFACE_FLIPBOOK_UV);
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef MK_INDIRECT
|
|
surface.indirect = 0;
|
|
#endif
|
|
#ifdef MK_THICKNESS_MAP
|
|
surface.thickness = SAMPLE_TEX2D_FLIPBOOK(_ThicknessMap, SAMPLER_REPEAT_MAIN, surfaceData.baseUV.xy, SURFACE_FLIPBOOK_UV).r;
|
|
#endif
|
|
#if defined(MK_RIM)
|
|
surface.rim = 0;
|
|
#endif
|
|
|
|
#ifdef MK_IRIDESCENCE
|
|
surface.iridescence = 0;
|
|
#endif
|
|
|
|
#ifdef MK_OCCLUSION_MAP
|
|
surface.occlusion = (1.0 - _OcclusionMapIntensity) + SAMPLE_TEX2D_FLIPBOOK(_OcclusionMap, SAMPLER_REPEAT_MAIN, surfaceData.baseUV.xy, SURFACE_FLIPBOOK_UV).rg * _OcclusionMapIntensity;
|
|
#else
|
|
surface.occlusion = 1.0;
|
|
#endif
|
|
|
|
#ifdef MK_EMISSION
|
|
#if defined(MK_EMISSION_MAP)
|
|
surface.emission = _EmissionColor * SAMPLE_TEX2D_FLIPBOOK(_EmissionMap, SAMPLER_REPEAT_MAIN, surfaceData.baseUV.xy, SURFACE_FLIPBOOK_UV).rgb;
|
|
#else
|
|
surface.emission = _EmissionColor;
|
|
#endif
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef MK_COLOR
|
|
#if defined(MK_COLOR_BLEND_ADDITIVE)
|
|
surface.albedo = surface.albedo + surfaceData.vertexColor;
|
|
surface.alpha *= surfaceData.vertexColor.a;
|
|
#elif defined(MK_COLOR_BLEND_SUBTRACTIVE)
|
|
surface.albedo = surface.albedo + surfaceData.vertexColor * (-1.0h);
|
|
surface.alpha *= surfaceData.vertexColor.a;
|
|
#elif defined(MK_COLOR_BLEND_OVERLAY)
|
|
surface.albedo = lerp(1 - 2 * (1 - surface.albedo) * (1 - surface.albedo), 2 * surface.albedo * surfaceData.vertexColor.rgb, step(surface.albedo, 0.5));
|
|
surface.alpha *= surfaceData.vertexColor.a;
|
|
#elif defined(MK_COLOR_BLEND_COLOR)
|
|
half3 aHSL = RGBToHSV(surface.albedo);
|
|
half3 bHSL = RGBToHSV(surfaceData.vertexColor.rgb);
|
|
half3 rHSL = half3(bHSL.x, bHSL.y, aHSL.z);
|
|
surface.albedo = HSVToRGB(rHSL);
|
|
surface.alpha = surface.alpha * surfaceData.vertexColor.a;
|
|
#elif defined(MK_COLOR_BLEND_DIFFERENCE)
|
|
surface.albedo = abs(surface.albedo + surfaceData.vertexColor * (-1.0h));
|
|
surface.alpha *= surfaceData.vertexColor.a;
|
|
#else
|
|
surface.albedo *= surfaceData.vertexColor.rgb;
|
|
surface.alpha *= surfaceData.vertexColor.a;
|
|
#endif
|
|
#endif
|
|
|
|
//avoid not initialized value
|
|
surface.final = 0;
|
|
|
|
#ifndef MK_PBS
|
|
ComputeBlending(PASS_BLENDING_ARG(surface, surfaceData, 0));
|
|
#endif
|
|
|
|
return surface;
|
|
}
|
|
#endif |