Files
Hasebe/Assets/MK/MKToon/Shader/Lib/Forward/ProgramForward.hlsl
T
2026-10-09 17:25:14 +03:00

338 lines
14 KiB
HLSL

//////////////////////////////////////////////////////
// MK Toon Forward Program //
// //
// Created by Michael Kremmel //
// www.michaelkremmel.de //
// Copyright © 2020 All rights reserved. //
//////////////////////////////////////////////////////
#ifndef MK_TOON_FORWARD
#define MK_TOON_FORWARD
#include "../Forward/Data.hlsl"
#include "../Surface.hlsl"
#include "../Lighting.hlsl"
#include "../Composite.hlsl"
/////////////////////////////////////////////////////////////////////////////////////////////
// VERTEX SHADER
/////////////////////////////////////////////////////////////////////////////////////////////
void ForwardVert (VertexInputForward VERTEX_INPUT, out VertexOutputLight vertexOutputLight, out VertexOutputForward vertexOutput)
{
UNITY_SETUP_INSTANCE_ID(VERTEX_INPUT);
INITIALIZE_STRUCT(VertexOutputForward, vertexOutput);
INITIALIZE_STRUCT(VertexOutputLight, vertexOutputLight);
UNITY_TRANSFER_INSTANCE_ID(VERTEX_INPUT, vertexOutput);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(vertexOutput);
#ifdef MK_VERTEX_ANIMATION
VERTEX_INPUT.vertex.xyz = VertexAnimation(PASS_VERTEX_ANIMATION_ARG(_VertexAnimationMap, PASS_VERTEX_ANIMATION_UV(VERTEX_INPUT.texcoord0.xy), _VertexAnimationIntensity, _VertexAnimationFrequency.xyz, VERTEX_INPUT.vertex.xyz, VERTEX_INPUT.normal));
#endif
//CurvedWorldSupport
//CurvedWorldVertexTransformations
/*
Replace on the Vertex Transformation code the following:
- v.vertex => VERTEX_INPUT.vertex
- v.normal => VERTEX_INPUT.normal
- v.tangent => VERTEX_INPUT.tangent
*/
//
//Clip Pos
#ifdef MK_POS_WORLD
vertexOutput.positionWorld.xyz = ComputeObjectToWorldSpace(VERTEX_INPUT.vertex.xyz);
#else
vertexOutput.positionWorld.xyz = 0;
#endif
vertexOutputLight.SV_CLIP_POS = ComputeObjectToClipSpace(VERTEX_INPUT.vertex.xyz);
//vertex positions
#ifdef MK_NORMAL
vertexOutput.normalWorld.xyz = ComputeNormalWorld(VERTEX_INPUT.normal);
#endif
#ifdef MK_LIT
#if defined(MK_TBN)
vertexOutput.tangentWorld.xyz = ComputeTangentWorld(VERTEX_INPUT.tangent.xyz);
vertexOutput.bitangentWorld.xyz = ComputeBitangentWorld(vertexOutput.normalWorld.xyz, vertexOutput.tangentWorld.xyz, VERTEX_INPUT.tangent.w * unity_WorldTransformParams.w);
#endif
#endif
//texcoords
#if defined(MK_TCM) || defined(MK_TCD)
//XY always RAW Coords
vertexOutput.uv = VERTEX_INPUT.texcoord0.xyxy;
#if defined(MK_SECONDARY_UV_SET)
vertexOutput.uv.zw = _DetailUVSet > 0.5 ? VERTEX_INPUT.texcoord7.xy : VERTEX_INPUT.texcoord0.xy;
#endif
#endif
#ifdef MK_PARALLAX
half3 viewTangent = ComputeViewTangent(ComputeViewWorld(vertexOutput.positionWorld.xyz), vertexOutput.normalWorld.xyz, vertexOutput.tangentWorld.xyz, vertexOutput.bitangentWorld.xyz);
vertexOutput.normalWorld.w = viewTangent.x;
vertexOutput.tangentWorld.w = viewTangent.y;
vertexOutput.bitangentWorld.w = viewTangent.z;
#endif
#ifdef MK_VERTEX_COLOR_REQUIRED
vertexOutput.color = VERTEX_INPUT.color;
#endif
#ifdef MK_LIT
#ifdef MK_FORWARD_BASE_PASS
#ifdef MK_VERTEX_LIGHTING
// Approximated illumination from non-important point lights
vertexOutputLight.vertexLighting = ComputeVertexLighting(vertexOutput.positionWorld.xyz, vertexOutput.normalWorld.xyz);
#endif
#ifdef MK_LIGHTMAP_UV
vertexOutputLight.lightmapUV = 0;
#if defined(MK_URP) || defined(MK_LWRP)
#if UNITY_VERSION >= 60000009
OUTPUT_LIGHTMAP_UV(VERTEX_INPUT.staticLightmapUV.xy, unity_LightmapST, vertexOutputLight.lightmapUV.xy);
OUTPUT_SH4(vertexOutput.positionWorld.xyz, vertexOutput.normalWorld.xyz, GetWorldSpaceNormalizeViewDir(vertexOutput.positionWorld.xyz), vertexOutputLight.lightmapUV, vertexOutput.probeOcclusion);
#ifdef DYNAMICLIGHTMAP_ON
vertexOutputLight.lightmapUV.zw = ComputeDynamicLightmapUV(VERTEX_INPUT.dynamicLightmapUV.xy);
#endif
#elif UNITY_VERSION >= 60000000
OUTPUT_LIGHTMAP_UV(VERTEX_INPUT.staticLightmapUV.xy, unity_LightmapST, vertexOutputLight.lightmapUV.xy);
OUTPUT_SH4(vertexOutput.positionWorld.xyz, vertexOutput.normalWorld.xyz, GetWorldSpaceNormalizeViewDir(vertexOutput.positionWorld.xyz), vertexOutputLight.lightmapUV);
#ifdef DYNAMICLIGHTMAP_ON
vertexOutputLight.lightmapUV.zw = ComputeDynamicLightmapUV(VERTEX_INPUT.dynamicLightmapUV.xy);
#endif
#else
#if defined(LIGHTMAP_ON)
vertexOutputLight.lightmapUV.xy = ComputeStaticLightmapUV(VERTEX_INPUT.staticLightmapUV.xy);
#else
vertexOutputLight.lightmapUV.rgb = ComputeSHVertex(vertexOutput.positionWorld.xyz, vertexOutput.normalWorld.xyz, ComputeViewWorld(vertexOutput.positionWorld.xyz));
#endif
#ifdef DYNAMICLIGHTMAP_ON
vertexOutputLight.lightmapUV.zw = ComputeDynamicLightmapUV(VERTEX_INPUT.dynamicLightmapUV.xy);
#endif
#endif
#else
//lightmaps and ambient
//Static lightmaps
#if defined(LIGHTMAP_ON)
vertexOutputLight.lightmapUV.xy = ComputeStaticLightmapUV(VERTEX_INPUT.staticLightmapUV.xy);
//If no lightmaps used, do vertex lit if enabled
#elif defined(UNITY_SHOULD_SAMPLE_SH)
vertexOutputLight.lightmapUV.rgb = ComputeSHVertex(vertexOutput.positionWorld.xyz, vertexOutput.normalWorld.xyz, ComputeViewWorld(vertexOutput.positionWorld.xyz));
#endif
#ifdef DYNAMICLIGHTMAP_ON
vertexOutputLight.lightmapUV.zw = ComputeDynamicLightmapUV(VERTEX_INPUT.dynamicLightmapUV.xy);
#endif
#endif
#endif
#endif
//transform lighting coords
TRANSFORM_WORLD_TO_SHADOW_COORDS(vertexOutput, VERTEX_INPUT, vertexOutputLight)
#endif
#ifdef MK_BARYCENTRIC_POS_CLIP
vertexOutput.positionClip = vertexOutputLight.SV_CLIP_POS;
#endif
#ifdef MK_POS_NULL_CLIP
vertexOutput.nullClip = ComputeObjectToClipSpace(0);
#endif
//vertex fog
#ifdef MK_FOG
vertexOutput.positionWorld.w = FogFactorVertex(vertexOutputLight.SV_CLIP_POS.z);
#endif
#ifdef MK_FLIPBOOK
vertexOutput.flipbookUV.xy = VERTEX_INPUT.texcoord0.zw;
vertexOutput.flipbookUV.z = VERTEX_INPUT.texcoordBlend;
#endif
}
/////////////////////////////////////////////////////////////////////////////////////////////
// FRAGMENT SHADER
/////////////////////////////////////////////////////////////////////////////////////////////
MKFragmentOutput ForwardFrag(in VertexOutputLight vertexOutputLight, in VertexOutputForward vertexOutput MK_DECLARE_V_FACE)
{
UNITY_SETUP_INSTANCE_ID(vertexOutput);
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(vertexOutput);
MKFragmentOutput mkFragmentOutput;
INITIALIZE_STRUCT(MKFragmentOutput, mkFragmentOutput);
#ifdef MK_LOD_FADE_CROSSFADE
LODFadeCrossFade(vertexOutputLight.SV_CLIP_POS);
#endif
MKSurfaceData surfaceData = ComputeSurfaceData
(
vertexOutputLight.SV_CLIP_POS,
PASS_POSITION_WORLD_ARG(vertexOutput.positionWorld.xyz)
PASS_FOG_FACTOR_WORLD_ARG(vertexOutput.positionWorld.w)
PASS_BASE_UV_ARG(vertexOutput.uv)
PASS_LIGHTMAP_UV_ARG(vertexOutputLight.lightmapUV)
PASS_VERTEX_COLOR_ARG(vertexOutput.color)
PASS_NORMAL_WORLD_ARG(vertexOutput.normalWorld.xyz)
PASS_VERTEX_LIGHTING_ARG(vertexOutputLight.vertexLighting)
PASS_TANGENT_WORLD_ARG(vertexOutput.tangentWorld.xyz)
PASS_VIEW_TANGENT_ARG(half3(vertexOutput.normalWorld.w, vertexOutput.tangentWorld.w, vertexOutput.bitangentWorld.w))
PASS_BITANGENT_WORLD_ARG(vertexOutput.bitangentWorld.xyz)
PASS_BARYCENTRIC_POSITION_CLIP_ARG(vertexOutput.positionClip)
PASS_NULL_CLIP_ARG(vertexOutput.nullClip)
PASS_FLIPBOOK_UV_ARG(vertexOutput.flipbookUV)
PASS_PROBE_OCCLUSION_ARG(vertexOutput.probeOcclusion)
#ifdef MK_VFACE
, vFace
#endif
);
Surface surface = InitSurface(surfaceData, PASS_SAMPLER_2D(_AlbedoMap), _AlbedoColor, vertexOutputLight.SV_CLIP_POS);
MKPBSData pbsData = ComputePBSData(surface, surfaceData);
#ifdef MK_LIT
//Init per mainLight
MKLight mainLight = ComputeMainLight(surfaceData, vertexOutputLight);
//Init mainLight data
MKLightData lightData = ComputeLightData(mainLight, surfaceData);
//Do per pass light
LightingIndirect(surface, surfaceData, pbsData, mainLight, lightData);
#if defined(MK_URP) || defined(MK_LWRP)
#if UNITY_VERSION >= 202220
uint meshRenderingLayers = GetMeshRenderingLayer();
#ifdef _LIGHT_LAYERS
if (IsMatchingLightLayer(mainLight.layerMask, meshRenderingLayers))
#endif
{
LightingDirect(surface, surfaceData, pbsData, mainLight, lightData, surface.direct);
}
#if defined(_ADDITIONAL_LIGHTS)
half4 gD = surface.goochDark;
surface.goochDark = 0;
uint additionalLightCount = GetAdditionalLightsCount();
half4 additionalDirect = 0;
MKLight additionalLight;
MKLightData additionalLightData;
#if USE_FORWARD_PLUS || USE_CLUSTER_LIGHT_LOOP
MKInputDataWrapper inputData;
INITIALIZE_STRUCT(MKInputDataWrapper, inputData);
inputData.normalizedScreenSpaceUV = surfaceData.screenUV.xy;
inputData.positionWS = surfaceData.positionWorld;
[loop] for (uint lightIndex = 0; lightIndex < min(URP_FP_DIRECTIONAL_LIGHTS_COUNT, MAX_VISIBLE_LIGHTS); lightIndex++)
{
#if UNITY_VERSION >= 60010000
CLUSTER_LIGHT_LOOP_SUBTRACTIVE_LIGHT_CHECK
#else
FORWARD_PLUS_SUBTRACTIVE_LIGHT_CHECK
#endif
additionalLight = ComputeAdditionalLight(lightIndex, surfaceData, vertexOutputLight);
additionalLightData = ComputeLightData(additionalLight, surfaceData);
#ifdef _LIGHT_LAYERS
if (IsMatchingLightLayer(additionalLight.layerMask, meshRenderingLayers))
#endif
{
LightingDirectAdditional(surface, surfaceData, pbsData, additionalLight, additionalLightData, additionalDirect);
surface.direct += additionalDirect;
}
}
#endif
LIGHT_LOOP_BEGIN(additionalLightCount)
additionalLight = ComputeAdditionalLight(lightIndex, surfaceData, vertexOutputLight);
additionalLightData = ComputeLightData(additionalLight, surfaceData);
#ifdef _LIGHT_LAYERS
if (IsMatchingLightLayer(additionalLight.layerMask, meshRenderingLayers))
#endif
{
LightingDirectAdditional(surface, surfaceData, pbsData, additionalLight, additionalLightData, additionalDirect);
surface.direct += additionalDirect;
}
LIGHT_LOOP_END
surface.goochDark = gD;
#endif
#elif UNITY_VERSION >= 202120
uint meshRenderingLayers = GetMeshRenderingLightLayer();
if (IsMatchingLightLayer(mainLight.layerMask, meshRenderingLayers))
{
LightingDirect(surface, surfaceData, pbsData, mainLight, lightData, surface.direct);
}
#ifdef _ADDITIONAL_LIGHTS
half4 gD = surface.goochDark;
surface.goochDark = 0;
uint additionalLightCount = GetAdditionalLightsCount();
half4 additionalDirect = 0;
MKLight additionalLight;
MKLightData additionalLightData;
#if USE_CLUSTERED_LIGHTING
MKInputDataWrapper inputData;
INITIALIZE_STRUCT(MKInputDataWrapper, inputData);
inputData.normalizedScreenSpaceUV = surfaceData.screenUV.xy;
inputData.positionWS = surfaceData.positionWorld;
for (uint lightIndex = 0; lightIndex < min(_AdditionalLightsDirectionalCount, MAX_VISIBLE_LIGHTS); ++lightIndex)
{
additionalLight = ComputeAdditionalLight(lightIndex, surfaceData, vertexOutputLight);
additionalLightData = ComputeLightData(additionalLight, surfaceData);
if (IsMatchingLightLayer(additionalLight.layerMask, meshRenderingLayers))
{
LightingDirectAdditional(surface, surfaceData, pbsData, additionalLight, additionalLightData, additionalDirect);
surface.direct += additionalDirect;
}
}
#endif
LIGHT_LOOP_BEGIN(additionalLightCount)
additionalLight = ComputeAdditionalLight(lightIndex, surfaceData, vertexOutputLight);
additionalLightData = ComputeLightData(additionalLight, surfaceData);
if (IsMatchingLightLayer(additionalLight.layerMask, meshRenderingLayers))
{
LightingDirectAdditional(surface, surfaceData, pbsData, additionalLight, additionalLightData, additionalDirect);
surface.direct += additionalDirect;
}
LIGHT_LOOP_END
surface.goochDark = gD;
#endif
#else
LightingDirect(surface, surfaceData, pbsData, mainLight, lightData, surface.direct);
#ifdef _ADDITIONAL_LIGHTS
half4 gD = surface.goochDark;
surface.goochDark = 0;
uint additionalLightCount = GetAdditionalLightsCount();
half4 additionalDirect = 0;
for (uint lightIndex = 0u; lightIndex < additionalLightCount; ++lightIndex)
{
MKLight additionalLight = ComputeAdditionalLight(lightIndex, surfaceData, vertexOutputLight);
MKLightData additionalLightData = ComputeLightData(additionalLight, surfaceData);
LightingDirectAdditional(surface, surfaceData, pbsData, additionalLight, additionalLightData, additionalDirect);
surface.direct += additionalDirect;
}
surface.goochDark = gD;
#endif
#endif
#else
LightingDirect(surface, surfaceData, pbsData, mainLight, lightData, surface.direct);
#endif
#endif
//Finalize the output
Composite(surface, surfaceData, pbsData);
mkFragmentOutput.svTarget0 = surface.final;
#ifdef MK_WRITE_RENDERING_LAYERS
#if UNITY_VERSION >= 60020000
mkFragmentOutput.svTarget1 = EncodeMeshRenderingLayer();
#else //UNITY_VERSION >= 202220
uint renderingLayers = GetMeshRenderingLayer();
mkFragmentOutput.svTarget1 = float4(EncodeMeshRenderingLayer(renderingLayers), 0, 0, 0);
#endif
#endif
return mkFragmentOutput;
}
#endif