mirror of
https://github.com/muskit/H3VR-TNH-Quality-of-Life-Improvements.git
synced 2026-06-03 04:34:26 -07:00
Initial commit
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
// Alloy Physical Shader Framework
|
||||
// Copyright 2013-2017 RUST LLC.
|
||||
// http://www.alloy.rustltd.com/
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
/// @file Deferred.cginc
|
||||
/// @brief Deferred passes uber-header.
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef ALLOY_SHADERS_FRAMEWORK_DEFERRED_CGINC
|
||||
#define ALLOY_SHADERS_FRAMEWORK_DEFERRED_CGINC
|
||||
|
||||
#define A_DEFERRED_PASS
|
||||
#define A_TANGENT_TO_WORLD_ON
|
||||
#define A_REFLECTION_PROBES_ON
|
||||
|
||||
// Headers both for this file, and for all Definition and Feature modules.
|
||||
#include "Assets/Alloy/Shaders/Config.cginc"
|
||||
#include "Assets/Alloy/Shaders/Framework/LightingImpl.cginc"
|
||||
|
||||
#include "UnityCG.cginc"
|
||||
#include "UnityDeferredLibrary.cginc"
|
||||
#include "UnityGlobalIllumination.cginc"
|
||||
#include "UnityImageBasedLighting.cginc"
|
||||
#include "UnityShaderVariables.cginc"
|
||||
#include "UnityStandardBRDF.cginc"
|
||||
#include "UnityStandardUtils.cginc"
|
||||
|
||||
sampler2D _CameraGBufferTexture0;
|
||||
sampler2D _CameraGBufferTexture1;
|
||||
sampler2D _CameraGBufferTexture2;
|
||||
|
||||
/// Creates a surface description from a Unity G-Buffer.
|
||||
/// @param[in,out] i Unity deferred vertex format.
|
||||
/// @return Material surface data.
|
||||
ASurface aDeferredSurface(
|
||||
inout unity_v2f_deferred i)
|
||||
{
|
||||
ASurface s = aNewSurface();
|
||||
|
||||
// Set vertex data.
|
||||
i.ray = i.ray * (_ProjectionParams.z / i.ray.z);
|
||||
s.screenPosition = i.uv;
|
||||
s.screenUv = s.screenPosition.xy / s.screenPosition.w;
|
||||
|
||||
// Convert G-Buffer to surface.
|
||||
float depth = Linear01Depth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, s.screenUv));
|
||||
half4 gbuffer0 = tex2D(_CameraGBufferTexture0, s.screenUv);
|
||||
half4 gbuffer1 = tex2D(_CameraGBufferTexture1, s.screenUv);
|
||||
half4 gbuffer2 = tex2D(_CameraGBufferTexture2, s.screenUv);
|
||||
float4 vpos = float4(i.ray * depth, 1.0f);
|
||||
|
||||
s.viewDepth = vpos.z;
|
||||
s.positionWorld = mul(unity_CameraToWorld, vpos).xyz;
|
||||
s.viewDirWorld = normalize(UnityWorldSpaceViewDir(s.positionWorld));
|
||||
|
||||
s.albedo = gbuffer0.rgb;
|
||||
s.specularOcclusion = gbuffer0.a;
|
||||
s.f0 = gbuffer1.rgb;
|
||||
s.roughness = 1.0h - gbuffer1.a;
|
||||
s.beckmannRoughness = aLinearToBeckmannRoughness(s.roughness);
|
||||
s.normalWorld = A_NW(s, normalize(gbuffer2.xyz * 2.0h - 1.0h));
|
||||
s.materialType = gbuffer2.w;
|
||||
aPreLighting(s);
|
||||
return s;
|
||||
}
|
||||
|
||||
#endif // ALLOY_SHADERS_FRAMEWORK_DEFERRED_CGINC
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f07a38f558ae0be49aa491fd74692918
|
||||
timeCreated: 1491528345
|
||||
licenseType: Pro
|
||||
ShaderImporter:
|
||||
defaultTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,393 @@
|
||||
// Alloy Physical Shader Framework
|
||||
// Copyright 2013-2017 RUST LLC.
|
||||
// http://www.alloy.rustltd.com/
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
/// @file Feature.cginc
|
||||
/// @brief Features uber-header. Holds methods that rely on uniforms.
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef ALLOY_SHADERS_FRAMEWORK_FEATURE_CGINC
|
||||
#define ALLOY_SHADERS_FRAMEWORK_FEATURE_CGINC
|
||||
|
||||
// Headers both for this file, and for all Definition and Feature modules.
|
||||
#include "Assets/Alloy/Shaders/Config.cginc"
|
||||
#include "Assets/Alloy/Shaders/Framework/Lighting.cginc"
|
||||
#include "Assets/Alloy/Shaders/Framework/Utility.cginc"
|
||||
|
||||
#include "UnityCG.cginc"
|
||||
#include "UnityStandardUtils.cginc"
|
||||
|
||||
/// Picks either UV0 or UV1.
|
||||
#define A_TEX_UV(s, name) (aPickUv(s, name##UV))
|
||||
|
||||
/// Applies Unity texture transforms plus UV0.
|
||||
#define A_TEX_TRANSFORM(s, name) (TRANSFORM_TEX(s.uv01.xy, name))
|
||||
|
||||
/// Applies Unity texture transforms plus UV-switching effect.
|
||||
#define A_TEX_TRANSFORM_UV(s, name) (TRANSFORM_TEX(A_TEX_UV(s, name), name))
|
||||
|
||||
/// Applies Unity texture transforms plus UV-switching and our scrolling effects.
|
||||
#define A_TEX_TRANSFORM_UV_SCROLL(s, name) (A_TEX_TRANSFORM_SCROLL(name, A_TEX_UV(s, name)))
|
||||
|
||||
/// Base UV assignment and update of associated fields.
|
||||
#define A_BV(s, UV) UV; aUpdateBaseUv(s)
|
||||
|
||||
/// Contains accumulated splat material data.
|
||||
struct ASplat {
|
||||
/// Non-TriPlanar transformed base UVs.
|
||||
float2 baseUv;
|
||||
|
||||
/// (RGB) Base Color, (A) Opacity.
|
||||
/// Expects linear-space LDR color values.
|
||||
half4 material0;
|
||||
|
||||
/// (R) Metallic, (G) AO/Specular Tint, (B) Specularity, (A) Roughness.
|
||||
/// Expects values in the range [0,1].
|
||||
half4 material1;
|
||||
|
||||
/// (RGB) Emission, (A) Specular Tint.
|
||||
/// Expects linear-space HDR color values.
|
||||
half4 material2;
|
||||
|
||||
/// World, Object, or Tangent normals.
|
||||
/// Expects a normalized vector.
|
||||
half3 normal;
|
||||
};
|
||||
|
||||
/// Contains shared state for all splat functions, including TriPlanar data.
|
||||
struct ASplatContext {
|
||||
/// Vertex color.
|
||||
/// Expects linear-space LDR color values.
|
||||
half4 vertexColor;
|
||||
|
||||
/// The model's UV0 & UV1 texture coordinate data.
|
||||
/// Be aware that it can have parallax precombined with it.
|
||||
float4 uv01;
|
||||
|
||||
/// X-axis TriPlanar tangent to world matrix.
|
||||
half3x3 xTangentToWorld;
|
||||
|
||||
/// Y-axis TriPlanar tangent to world matrix.
|
||||
half3x3 yTangentToWorld;
|
||||
|
||||
/// Z-axis TriPlanar tangent to world matrix.
|
||||
half3x3 zTangentToWorld;
|
||||
|
||||
/// Blend weights between the top, middle, and bottom TriPlanar axis.
|
||||
half3 blend;
|
||||
|
||||
/// Position in either world or object-space.
|
||||
float3 position;
|
||||
|
||||
/// Binary masks for the positive values in the vertex normals.
|
||||
half3 axisMasks;
|
||||
};
|
||||
|
||||
/// Cutoff value that controls where cutout occurs over opacity.
|
||||
/// Expects values in the range [0,1].
|
||||
half _Cutoff;
|
||||
|
||||
/// Toggles inverting the backface normals.
|
||||
/// Expects the values 0 or 1.
|
||||
float _TransInvertBackNormal;
|
||||
|
||||
/// The base tint color.
|
||||
/// Expects a linear LDR color with alpha.
|
||||
half4 _Color;
|
||||
|
||||
/// Base color map.
|
||||
/// Expects an RGB(A) map with sRGB sampling.
|
||||
A_SAMPLER_2D(_MainTex);
|
||||
|
||||
/// Base packed material map.
|
||||
/// Expects an RGBA data map.
|
||||
A_SAMPLER_2D(_SpecTex);
|
||||
|
||||
/// Metallic map.
|
||||
/// Expects an RGB map with sRGB sampling
|
||||
sampler2D _MetallicMap;
|
||||
|
||||
/// Ambient Occlusion map.
|
||||
/// Expects an RGB map with sRGB sampling
|
||||
sampler2D _AoMap;
|
||||
|
||||
/// Specularity map.
|
||||
/// Expects an RGB map with sRGB sampling
|
||||
sampler2D _SpecularityMap;
|
||||
|
||||
/// Roughness map.
|
||||
/// Expects an RGB map with sRGB sampling
|
||||
sampler2D _RoughnessMap;
|
||||
|
||||
/// Base normal map.
|
||||
/// Expects a compressed normal map.
|
||||
sampler2D _BumpMap;
|
||||
|
||||
/// Height map.
|
||||
/// Expects an RGBA data map.
|
||||
sampler2D _ParallaxMap;
|
||||
|
||||
/// Toggles tinting the base color by the vertex color.
|
||||
/// Expects values in the range [0,1].
|
||||
half _BaseColorVertexTint;
|
||||
|
||||
/// The base metallic scale.
|
||||
/// Expects values in the range [0,1].
|
||||
half _Metal;
|
||||
|
||||
/// The base specularity scale.
|
||||
/// Expects values in the range [0,1].
|
||||
half _Specularity;
|
||||
|
||||
// Amount that f0 is tinted by the base color.
|
||||
/// Expects values in the range [0,1].
|
||||
half _SpecularTint;
|
||||
|
||||
/// The base roughness scale.
|
||||
/// Expects values in the range [0,1].
|
||||
half _Roughness;
|
||||
|
||||
/// Ambient Occlusion strength.
|
||||
/// Expects values in the range [0,1].
|
||||
half _Occlusion;
|
||||
|
||||
/// Normal map XY scale.
|
||||
half _BumpScale;
|
||||
|
||||
/// Height scale of the heightmap.
|
||||
/// Expects values in the range [0,0.08].
|
||||
float _Parallax;
|
||||
|
||||
/// Splat data constructor.
|
||||
ASplat aNewSplat();
|
||||
|
||||
/// Uses surface data to make shared splat data.
|
||||
/// @param s Material surface data.
|
||||
/// @param sharpness Sharpness of the blend between TriPlanar axis.
|
||||
/// @param positionScale Scales the position used for TriPlanar UVs.
|
||||
/// @return Splat context initialized with shared data.
|
||||
ASplatContext aNewSplatContext(ASurface s, half sharpness, float positionScale);
|
||||
|
||||
/// Converts splat to material data and assigns it to a surface.
|
||||
/// @param[in,out] s Material surface data.
|
||||
/// @param[in] sp Combined splat data.
|
||||
void aApplySplat(inout ASurface s, ASplat sp);
|
||||
|
||||
/// Uses mask to blend a splat into surface.
|
||||
/// @param[in,out] s Material surface data.
|
||||
/// @param[in] sp Combined splat data.
|
||||
void aBlendSplat(inout ASurface s, ASplat sp);
|
||||
|
||||
/// Uses splat opacity and mask to blend a splat into surface.
|
||||
/// @param[in,out] s Material surface data.
|
||||
/// @param[in] sp Combined splat data.
|
||||
void aBlendSplatWithOpacity(inout ASurface s, ASplat sp);
|
||||
|
||||
/// Combines two splats into one, accumulating into first splat.
|
||||
/// @param[in,out] sp0 Target for combined splat data ouput.
|
||||
/// @param[in] sp1 Second splat to be combined.
|
||||
void aMergeSplats(inout ASplat sp0, ASplat sp1);
|
||||
|
||||
/// Applies constant material data to a splat.
|
||||
/// @param[in,out] sp Splat being modified.
|
||||
/// @param[in] sc Splat context.
|
||||
/// @param[in] tint Base color tint.
|
||||
/// @param[in] vertexTint Base color vertex color tint weight.
|
||||
/// @param[in] metallic Metallic weight.
|
||||
/// @param[in] specularity Specularity.
|
||||
/// @param[in] specularTint Specular tint weight.
|
||||
/// @param[in] roughness Linear roughness.
|
||||
void aSplatMaterial(inout ASplat sp, ASplatContext sc, half4 tint, half vertexTint, half metallic, half specularity, half specularTint, half roughness);
|
||||
|
||||
/// TriPlanar axis applied to a splat.
|
||||
/// @param[in,out] sp Splat being modified.
|
||||
/// @param[in] mask Masks where the effect is applied.
|
||||
/// @param[in] tbn Local normal tangent to world matrix.
|
||||
/// @param[in] uv Texture coordinates.
|
||||
/// @param[in] occlusion Occlusion map weight.
|
||||
/// @param[in] bumpScale Normal map XY scale.
|
||||
/// @param[in] base Base color map.
|
||||
/// @param[in] material Material map.
|
||||
/// @param[in] normal Normal map.
|
||||
void aTriPlanarAxis(inout ASplat sp, half mask, half3x3 tbn, float2 uv, half occlusion, half bumpScale, sampler2D base, sampler2D material, sampler2D normal);
|
||||
|
||||
/// X-axis triplanar material applied to a splat.
|
||||
/// @param[in,out] sp Splat being modified.
|
||||
/// @param[in] sc Splat context.
|
||||
/// @param[in] base Base color map.
|
||||
/// @param[in] material Material map.
|
||||
/// @param[in] normal Normal map.
|
||||
/// @param[in] occlusion Occlusion map weight.
|
||||
/// @param[in] bumpScale Normal map XY scale.
|
||||
void aTriPlanarX(inout ASplat sp, ASplatContext sc, A_SAMPLER_PARAM(base), sampler2D material, sampler2D normal, half occlusion, half bumpScale);
|
||||
|
||||
/// Y-axis triplanar material applied to a splat.
|
||||
/// @param[in,out] sp Splat being modified.
|
||||
/// @param[in] sc Splat context.
|
||||
/// @param[in] base Base color map.
|
||||
/// @param[in] material Material map.
|
||||
/// @param[in] normal Normal map.
|
||||
/// @param[in] occlusion Occlusion map weight.
|
||||
/// @param[in] bumpScale Normal map XY scale.
|
||||
void aTriPlanarY(inout ASplat sp, ASplatContext sc, A_SAMPLER_PARAM(base), sampler2D material, sampler2D normal, half occlusion, half bumpScale);
|
||||
|
||||
/// Z-axis triplanar material applied to a splat.
|
||||
/// @param[in,out] sp Splat being modified.
|
||||
/// @param[in] sc Splat context.
|
||||
/// @param[in] base Base color map.
|
||||
/// @param[in] material Material map.
|
||||
/// @param[in] normal Normal map.
|
||||
/// @param[in] occlusion Occlusion map weight.
|
||||
/// @param[in] bumpScale Normal map XY scale.
|
||||
void aTriPlanarZ(inout ASplat sp, ASplatContext sc, A_SAMPLER_PARAM(base), sampler2D material, sampler2D normal, half occlusion, half bumpScale);
|
||||
|
||||
/// Positive Y-axis triplanar material applied to a splat.
|
||||
/// @param[in,out] sp Splat being modified.
|
||||
/// @param[in] sc Splat context.
|
||||
/// @param[in] base Base color map.
|
||||
/// @param[in] material Material map.
|
||||
/// @param[in] normal Normal map.
|
||||
/// @param[in] occlusion Occlusion map weight.
|
||||
/// @param[in] bumpScale Normal map XY scale.
|
||||
void aTriPlanarPositiveY(inout ASplat sp, ASplatContext sc, A_SAMPLER_PARAM(base), sampler2D material, sampler2D normal, half occlusion, half bumpScale);
|
||||
|
||||
/// Negative Y-axis triplanar material applied to a splat.
|
||||
/// @param[in,out] sp Splat being modified.
|
||||
/// @param[in] sc Splat context.
|
||||
/// @param[in] base Base color map.
|
||||
/// @param[in] material Material map.
|
||||
/// @param[in] normal Normal map.
|
||||
/// @param[in] occlusion Occlusion map weight.
|
||||
/// @param[in] bumpScale Normal map XY scale.
|
||||
void aTriPlanarNegativeY(inout ASplat sp, ASplatContext sc, A_SAMPLER_PARAM(base), sampler2D material, sampler2D normal, half occlusion, half bumpScale);
|
||||
|
||||
/// Applies constant material data to a splat.
|
||||
/// @param sc Splat context.
|
||||
/// @param base Base color map.
|
||||
/// @param material Material map.
|
||||
/// @param normal Normal map.
|
||||
/// @param tint Base color tint.
|
||||
/// @param vertexTint Base vertex color tint.
|
||||
/// @param metallic Metallic weight.
|
||||
/// @param specularity Specularity.
|
||||
/// @param specularTint Specular tint weight.
|
||||
/// @param roughness Linear roughness.
|
||||
/// @param occlusion Occlusion map weight.
|
||||
/// @param bumpScale Normal map XY scale.
|
||||
/// @return Splat populated with terrain data.
|
||||
ASplat aNewSplat(ASplatContext sc, A_SAMPLER_PARAM(base), sampler2D material, sampler2D normal, half4 tint, half vertexTint, half metallic, half specularity, half specularTint, half roughness, half occlusion, half bumpScale);
|
||||
|
||||
/// Combine splats and convert to material data to assign to a surface.
|
||||
/// @param[in,out] s Material surface data.
|
||||
/// @param[in] weights Weights masking where splats are combined.
|
||||
/// @param[in] sp0 Splat data.
|
||||
/// @param[in] sp1 Splat data.
|
||||
/// @param[in] sp2 Splat data.
|
||||
void aApplyTerrainSplats(inout ASurface s, half3 weights, ASplat sp0, ASplat sp1, ASplat sp2);
|
||||
|
||||
/// Combine splats and convert to material data to assign to a surface.
|
||||
/// @param[in,out] s Material surface data.
|
||||
/// @param[in] weights Weights masking where splats are combined.
|
||||
/// @param[in] sp0 Splat data.
|
||||
/// @param[in] sp1 Splat data.
|
||||
/// @param[in] sp2 Splat data.
|
||||
/// @param[in] sp3 Splat data.
|
||||
void aApplyTerrainSplats(inout ASurface s, half4 weights, ASplat sp0, ASplat sp1, ASplat sp2, ASplat sp3);
|
||||
|
||||
/// Converts AO to linear space and controls the strength of the effect.
|
||||
/// @param ao Gamma-space LDR AO value.
|
||||
/// @param weight Strength of the AO effect.
|
||||
/// @return Weighted, linear-space AO value.
|
||||
half aOcclusionStrength(half ao, half weight);
|
||||
|
||||
/// Sets up base UV for the first time.
|
||||
/// @param[in,out] s Material surface data.
|
||||
void aBaseUvInit(inout ASurface s);
|
||||
|
||||
/// Update values dependent on base UV.
|
||||
void aUpdateBaseUv(inout ASurface s);
|
||||
|
||||
/// Pick between UV0 & UV1.
|
||||
float2 aPickUv(ASurface s, float nameUv);
|
||||
|
||||
/// Pick between UV0 & UV1.
|
||||
float2 aPickUv(ASplatContext sc, float nameUv);
|
||||
|
||||
/// Sets whether backface normals are inverted.
|
||||
/// @param[in,out] s Material surface data.
|
||||
void aTwoSided(inout ASurface s);
|
||||
|
||||
/// Applies cutout effect.
|
||||
/// @param s Material surface data.
|
||||
void aCutout(ASurface s);
|
||||
|
||||
/// Samples the base color map.
|
||||
/// @param s Material surface data.
|
||||
/// @return Base Color with alpha.
|
||||
half4 aSampleBase(ASurface s);
|
||||
|
||||
/// Samples the base material map.
|
||||
/// @param s Material surface data.
|
||||
/// @return Packed material.
|
||||
half4 aSampleMaterial(ASurface s);
|
||||
|
||||
/// Samples and scales the base bump map.
|
||||
/// @param s Material surface data.
|
||||
/// @param scale Normal XY scale factor.
|
||||
/// @return Normalized tangent-space normal.
|
||||
half3 aSampleBumpScale(ASurface s, half scale);
|
||||
|
||||
/// Samples the base bump map.
|
||||
/// @param s Material surface data.
|
||||
/// @return Normalized tangent-space normal.
|
||||
half3 aSampleBump(ASurface s);
|
||||
|
||||
/// Samples the base bump map biasing the mipmap level sampled.
|
||||
/// @param s Material surface data.
|
||||
/// @param bias Mipmap level bias.
|
||||
/// @return Normalized tangent-space normal.
|
||||
half3 aSampleBumpBias(ASurface s, float bias);
|
||||
|
||||
/// Samples the base bump map biasing the mipmap level sampled.
|
||||
/// @param s Material surface data.
|
||||
/// @return Normalized tangent-space normal.
|
||||
half aSampleHeight(ASurface s);
|
||||
|
||||
/// Applies color based on weight parameter.
|
||||
/// @param s Material surface data.
|
||||
/// @param strength Amount to blend in vertex color.
|
||||
/// @return Vertex color tint.
|
||||
half3 aVertexColorTint(ASurface s, half strength);
|
||||
|
||||
/// Applies base vertex color.
|
||||
/// @param s Material surface data.
|
||||
/// @return Vertex color tint.
|
||||
half3 aBaseVertexColorTint(ASurface s);
|
||||
|
||||
/// Gets combined base color tint from uniform and vertex color.
|
||||
/// @param s Material surface data.
|
||||
/// @return Base Color with alpha.
|
||||
half4 aBaseTint(ASurface s);
|
||||
|
||||
/// Gets combined base color from main channels.
|
||||
/// @param s Material surface data.
|
||||
/// @return Base Color with alpha.
|
||||
half4 aBase(ASurface s);
|
||||
|
||||
/// Applies texture coordinate offsets to surface data.
|
||||
/// @param[in,out] s Material surface data.
|
||||
/// @param[in] offset Texture coordinate offset.
|
||||
void aParallaxOffset(inout ASurface s, float2 offset);
|
||||
|
||||
/// Calculates Offset Bump Mapping texture offsets.
|
||||
/// @param[in,out] s Material surface data.
|
||||
void aOffsetBumpMapping(inout ASurface s);
|
||||
|
||||
/// Calculates Parallax Occlusion Mapping texture offsets.
|
||||
/// @param[in,out] s Material surface data.
|
||||
/// @param[in] minSamples Minimum number of samples for POM effect [1,n].
|
||||
/// @param[in] maxSamples Maximum number of samples for POM effect [1,n].
|
||||
void aParallaxOcclusionMapping(inout ASurface s, float minSamples, float maxSamples);
|
||||
|
||||
#endif // ALLOY_SHADERS_FRAMEWORK_FEATURE_CGINC
|
||||
@@ -0,0 +1,6 @@
|
||||
fileFormatVersion: 2
|
||||
guid: aeac9cf700a9bac48bf2bd38f0fcc351
|
||||
ShaderImporter:
|
||||
defaultTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
@@ -0,0 +1,707 @@
|
||||
// Alloy Physical Shader Framework
|
||||
// Copyright 2013-2017 RUST LLC.
|
||||
// http://www.alloy.rustltd.com/
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
/// @file Feature.cginc
|
||||
/// @brief Feature method implementations to allow disabling of features.
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef ALLOY_SHADERS_FRAMEWORK_FEATURE_IMPL_CGINC
|
||||
#define ALLOY_SHADERS_FRAMEWORK_FEATURE_IMPL_CGINC
|
||||
|
||||
#if !defined(A_TEX_UV_OFF) && defined(A_PROJECTIVE_DECAL_SHADER)
|
||||
#define A_TEX_UV_OFF
|
||||
#endif
|
||||
|
||||
#if !defined(A_TRIPLANAR_MAPPING_ON) && defined(_METALLICGLOSSMAP)
|
||||
#define A_TRIPLANAR_MAPPING_ON
|
||||
#endif
|
||||
|
||||
#ifdef A_TRIPLANAR_MAPPING_ON
|
||||
#ifndef _TRIPLANARMODE_WORLD
|
||||
#define A_WORLD_TO_OBJECT_ON
|
||||
#endif
|
||||
|
||||
#ifndef A_NORMAL_WORLD_ON
|
||||
#define A_NORMAL_WORLD_ON
|
||||
#endif
|
||||
|
||||
#ifndef A_POSITION_WORLD_ON
|
||||
#define A_POSITION_WORLD_ON
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "Assets/Alloy/Shaders/Config.cginc"
|
||||
#include "Assets/Alloy/Shaders/Framework/Feature.cginc"
|
||||
#include "Assets/Alloy/Shaders/Framework/LightingImpl.cginc"
|
||||
#include "Assets/Alloy/Shaders/Framework/Utility.cginc"
|
||||
|
||||
#include "HLSLSupport.cginc"
|
||||
#include "UnityCG.cginc"
|
||||
#include "UnityStandardUtils.cginc"
|
||||
|
||||
#define A_BASE_COLOR material0.rgb
|
||||
#define A_OPACITY material0.a
|
||||
|
||||
#define A_METALLIC material1.A_METALLIC_CHANNEL
|
||||
#define A_AMBIENT_OCCLUSION material1.A_AO_CHANNEL
|
||||
#define A_SPECULARITY material1.A_SPECULARITY_CHANNEL
|
||||
#define A_ROUGHNESS material1.A_ROUGHNESS_CHANNEL
|
||||
|
||||
#ifdef A_AMBIENT_OCCLUSION_ON
|
||||
#define A_SPECULAR_TINT material2.a
|
||||
#else
|
||||
#define A_SPECULAR_TINT material1.g
|
||||
#endif
|
||||
|
||||
#define A_EMISSIVE_COLOR material2.rgb
|
||||
|
||||
ASplat aNewSplat()
|
||||
{
|
||||
ASplat sp;
|
||||
|
||||
UNITY_INITIALIZE_OUTPUT(ASplat, sp);
|
||||
sp.material0 = 0.0h;
|
||||
sp.material1 = 0.0h;
|
||||
sp.material2 = 0.0h;
|
||||
sp.normal = 0.0h;
|
||||
return sp;
|
||||
}
|
||||
|
||||
ASplatContext aNewSplatContext(
|
||||
ASurface s,
|
||||
half sharpness,
|
||||
float positionScale)
|
||||
{
|
||||
ASplatContext sc;
|
||||
|
||||
UNITY_INITIALIZE_OUTPUT(ASplatContext, sc);
|
||||
sc.uv01 = s.uv01;
|
||||
sc.vertexColor = s.vertexColor;
|
||||
|
||||
#ifdef A_TRIPLANAR_MAPPING_ON
|
||||
// Triplanar mapping
|
||||
// cf http://www.gamedev.net/blog/979/entry-2250761-triplanar-texturing-and-normal-mapping/
|
||||
#ifdef _TRIPLANARMODE_WORLD
|
||||
half3 geoNormal = s.vertexNormalWorld;
|
||||
sc.position = s.positionWorld;
|
||||
#else
|
||||
half3 geoNormal = UnityWorldToObjectDir(s.vertexNormalWorld);
|
||||
sc.position = mul(unity_WorldToObject, float4(s.positionWorld, 1.0f)).xyz;
|
||||
#endif
|
||||
|
||||
// Unity uses a Left-handed axis, so it requires clumsy remapping.
|
||||
sc.xTangentToWorld = half3x3(A_AXIS_Z, A_AXIS_Y, geoNormal);
|
||||
sc.yTangentToWorld = half3x3(A_AXIS_X, A_AXIS_Z, geoNormal);
|
||||
sc.zTangentToWorld = half3x3(A_AXIS_X, A_AXIS_Y, geoNormal);
|
||||
|
||||
half3 blending = abs(geoNormal);
|
||||
blending = normalize(max(blending, A_EPSILON));
|
||||
blending = pow(blending, sharpness);
|
||||
blending /= dot(blending, A_ONE);
|
||||
sc.blend = blending;
|
||||
|
||||
sc.axisMasks = step(A_ZERO, geoNormal);
|
||||
sc.position *= positionScale;
|
||||
#endif
|
||||
|
||||
return sc;
|
||||
}
|
||||
|
||||
void aApplySplat(
|
||||
inout ASurface s,
|
||||
ASplat sp)
|
||||
{
|
||||
half3 normal = sp.normal;
|
||||
|
||||
s.baseColor = sp.A_BASE_COLOR;
|
||||
s.opacity = sp.A_OPACITY;
|
||||
s.metallic = sp.A_METALLIC;
|
||||
s.specularity = sp.A_SPECULARITY;
|
||||
s.specularTint = sp.A_SPECULAR_TINT;
|
||||
s.roughness = sp.A_ROUGHNESS;
|
||||
|
||||
#ifdef A_AMBIENT_OCCLUSION_ON
|
||||
s.ambientOcclusion = sp.A_AMBIENT_OCCLUSION;
|
||||
#endif
|
||||
|
||||
#ifdef A_EMISSIVE_COLOR_ON
|
||||
s.emissiveColor = sp.A_EMISSIVE_COLOR;
|
||||
#endif
|
||||
|
||||
#ifndef A_TRIPLANAR_MAPPING_ON
|
||||
s.normalTangent = A_NT(s, normalize(normal));
|
||||
#else
|
||||
#ifdef _TRIPLANARMODE_WORLD
|
||||
half3 normalWorld = normalize(normal);
|
||||
#else
|
||||
half3 normalWorld = UnityObjectToWorldNormal(normal);
|
||||
#endif
|
||||
|
||||
s.normalWorld = A_NW(s, normalWorld);
|
||||
#endif
|
||||
}
|
||||
|
||||
void aBlendSplat(
|
||||
inout ASurface s,
|
||||
ASplat sp)
|
||||
{
|
||||
half3 normal = sp.normal;
|
||||
half weight = s.mask;
|
||||
|
||||
s.baseColor = lerp(s.baseColor, sp.A_BASE_COLOR, weight);
|
||||
s.opacity = lerp(s.opacity, sp.A_OPACITY, weight);
|
||||
s.metallic = lerp(s.metallic, sp.A_METALLIC, weight);
|
||||
s.specularity = lerp(s.specularity, sp.A_SPECULARITY, weight);
|
||||
s.specularTint = lerp(s.specularTint, sp.A_SPECULAR_TINT, weight);
|
||||
s.roughness = lerp(s.roughness, sp.A_ROUGHNESS, weight);
|
||||
|
||||
#ifdef A_AMBIENT_OCCLUSION_ON
|
||||
s.ambientOcclusion = lerp(s.ambientOcclusion, sp.A_AMBIENT_OCCLUSION, weight);
|
||||
#endif
|
||||
|
||||
#ifdef A_EMISSIVE_COLOR_ON
|
||||
s.emissiveColor = lerp(s.emissiveColor, sp.A_EMISSIVE_COLOR, weight);
|
||||
#endif
|
||||
|
||||
#ifndef A_TRIPLANAR_MAPPING_ON
|
||||
s.normalTangent = A_NT(s, normalize(lerp(s.normalTangent, normal, weight)));
|
||||
#else
|
||||
#ifdef _TRIPLANARMODE_WORLD
|
||||
half3 normalWorld = normalize(normal);
|
||||
#else
|
||||
half3 normalWorld = UnityObjectToWorldNormal(normal);
|
||||
#endif
|
||||
|
||||
s.normalWorld = A_NW(s, normalize(lerp(s.normalWorld, normalWorld, weight)));
|
||||
#endif
|
||||
}
|
||||
|
||||
void aBlendSplatWithOpacity(
|
||||
inout ASurface s,
|
||||
ASplat sp)
|
||||
{
|
||||
s.mask *= sp.A_OPACITY;
|
||||
sp.A_OPACITY = 1.0h;
|
||||
|
||||
aBlendSplat(s, sp);
|
||||
}
|
||||
|
||||
void aMergeSplats(
|
||||
inout ASplat sp0,
|
||||
ASplat sp1)
|
||||
{
|
||||
sp0.material0 += sp1.material0;
|
||||
sp0.material1 += sp1.material1;
|
||||
sp0.normal += sp1.normal;
|
||||
sp0.material2 += sp1.material2;
|
||||
}
|
||||
|
||||
void aSplatMaterial(
|
||||
inout ASplat sp,
|
||||
ASplatContext sc,
|
||||
half4 tint,
|
||||
half vertexTint,
|
||||
half metallic,
|
||||
half specularity,
|
||||
half specularTint,
|
||||
half roughness)
|
||||
{
|
||||
sp.material0 *= tint;
|
||||
|
||||
#ifndef A_VERTEX_COLOR_IS_DATA
|
||||
sp.A_BASE_COLOR *= aLerpWhiteTo(sc.vertexColor.rgb, vertexTint);
|
||||
#endif
|
||||
|
||||
sp.A_METALLIC *= metallic;
|
||||
sp.A_SPECULARITY *= specularity;
|
||||
sp.A_ROUGHNESS *= roughness;
|
||||
sp.A_SPECULAR_TINT = specularTint;
|
||||
}
|
||||
|
||||
void aTriPlanarAxis(
|
||||
inout ASplat sp,
|
||||
half mask,
|
||||
half3x3 tbn,
|
||||
float2 uv,
|
||||
half occlusion,
|
||||
half bumpScale,
|
||||
sampler2D base,
|
||||
sampler2D material,
|
||||
sampler2D normal)
|
||||
{
|
||||
ASplat sp0 = aNewSplat();
|
||||
|
||||
sp0.material0 = tex2D(base, uv);
|
||||
sp0.normal = mul(UnpackScaleNormal(tex2D(normal, uv), bumpScale), tbn);
|
||||
|
||||
#ifndef A_ROUGHNESS_SOURCE_BASE_COLOR_ALPHA
|
||||
sp0.material1 = tex2D(material, uv);
|
||||
sp0.A_AMBIENT_OCCLUSION = aOcclusionStrength(sp0.A_AMBIENT_OCCLUSION, occlusion);
|
||||
#else
|
||||
sp0.A_METALLIC = 1.0h;
|
||||
sp0.A_AMBIENT_OCCLUSION = 1.0h;
|
||||
sp0.A_SPECULARITY = 1.0h;
|
||||
sp0.A_ROUGHNESS = sp0.A_OPACITY;
|
||||
sp0.A_OPACITY = 1.0h;
|
||||
#endif
|
||||
|
||||
sp.material0 += mask * sp0.material0;
|
||||
sp.material1 += mask * sp0.material1;
|
||||
sp.normal += mask * sp0.normal;
|
||||
}
|
||||
|
||||
void aTriPlanarX(
|
||||
inout ASplat sp,
|
||||
ASplatContext sc,
|
||||
A_SAMPLER_PARAM(base),
|
||||
sampler2D material,
|
||||
sampler2D normal,
|
||||
half occlusion,
|
||||
half bumpScale)
|
||||
{
|
||||
aTriPlanarAxis(sp, sc.blend.x, sc.xTangentToWorld, A_TEX_TRANSFORM_SCROLL(base, sc.position.zy), occlusion, bumpScale, base, material, normal);
|
||||
}
|
||||
|
||||
void aTriPlanarY(
|
||||
inout ASplat sp,
|
||||
ASplatContext sc,
|
||||
A_SAMPLER_PARAM(base),
|
||||
sampler2D material,
|
||||
sampler2D normal,
|
||||
half occlusion,
|
||||
half bumpScale)
|
||||
{
|
||||
aTriPlanarAxis(sp, sc.blend.y, sc.yTangentToWorld, A_TEX_TRANSFORM_SCROLL(base, sc.position.xz), occlusion, bumpScale, base, material, normal);
|
||||
}
|
||||
|
||||
void aTriPlanarZ(
|
||||
inout ASplat sp,
|
||||
ASplatContext sc,
|
||||
A_SAMPLER_PARAM(base),
|
||||
sampler2D material,
|
||||
sampler2D normal,
|
||||
half occlusion,
|
||||
half bumpScale)
|
||||
{
|
||||
aTriPlanarAxis(sp, sc.blend.z, sc.zTangentToWorld, A_TEX_TRANSFORM_SCROLL(base, sc.position.xy), occlusion, bumpScale, base, material, normal);
|
||||
}
|
||||
|
||||
void aTriPlanarPositiveY(
|
||||
inout ASplat sp,
|
||||
ASplatContext sc,
|
||||
A_SAMPLER_PARAM(base),
|
||||
sampler2D material,
|
||||
sampler2D normal,
|
||||
half occlusion,
|
||||
half bumpScale)
|
||||
{
|
||||
aTriPlanarAxis(sp, sc.axisMasks.y * sc.blend.y, sc.yTangentToWorld, A_TEX_TRANSFORM_SCROLL(base, sc.position.xz), occlusion, bumpScale, base, material, normal);
|
||||
}
|
||||
|
||||
void aTriPlanarNegativeY(
|
||||
inout ASplat sp,
|
||||
ASplatContext sc,
|
||||
A_SAMPLER_PARAM(base),
|
||||
sampler2D material,
|
||||
sampler2D normal,
|
||||
half occlusion,
|
||||
half bumpScale)
|
||||
{
|
||||
aTriPlanarAxis(sp, (1.0h - sc.axisMasks.y) * sc.blend.y, sc.yTangentToWorld, A_TEX_TRANSFORM_SCROLL(base, sc.position.xz), occlusion, bumpScale, base, material, normal);
|
||||
}
|
||||
|
||||
ASplat aNewSplat(
|
||||
ASplatContext sc,
|
||||
A_SAMPLER_PARAM(base),
|
||||
sampler2D material,
|
||||
sampler2D normal,
|
||||
half4 tint,
|
||||
half vertexTint,
|
||||
half metallic,
|
||||
half specularity,
|
||||
half specularTint,
|
||||
half roughness,
|
||||
half occlusion,
|
||||
half bumpScale)
|
||||
{
|
||||
ASplat sp = aNewSplat();
|
||||
|
||||
#ifdef A_TRIPLANAR_MAPPING_ON
|
||||
aTriPlanarX(sp, sc, A_SAMPLER_2D_INPUT(base), material, normal, occlusion, bumpScale);
|
||||
aTriPlanarY(sp, sc, A_SAMPLER_2D_INPUT(base), material, normal, occlusion, bumpScale);
|
||||
aTriPlanarZ(sp, sc, A_SAMPLER_2D_INPUT(base), material, normal, occlusion, bumpScale);
|
||||
#else
|
||||
sp.baseUv = A_TEX_TRANSFORM_UV_SCROLL(sc, base);
|
||||
sp.material0 = tex2D(base, sp.baseUv);
|
||||
sp.normal = UnpackScaleNormal(tex2D(normal, sp.baseUv), bumpScale);
|
||||
|
||||
#ifndef A_ROUGHNESS_SOURCE_BASE_COLOR_ALPHA
|
||||
sp.material1 = tex2D(material, sp.baseUv);
|
||||
sp.A_AMBIENT_OCCLUSION = aOcclusionStrength(sp.A_AMBIENT_OCCLUSION, occlusion);
|
||||
#else
|
||||
sp.A_METALLIC = 1.0h;
|
||||
sp.A_AMBIENT_OCCLUSION = 1.0h;
|
||||
sp.A_SPECULARITY = 1.0h;
|
||||
sp.A_ROUGHNESS = sp.A_OPACITY;
|
||||
sp.A_OPACITY = 1.0h;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
aSplatMaterial(sp, sc, tint, vertexTint, metallic, specularity, specularTint, roughness);
|
||||
return sp;
|
||||
}
|
||||
|
||||
void aApplyTerrainSplats(
|
||||
inout ASurface s,
|
||||
half3 weights,
|
||||
ASplat sp0,
|
||||
ASplat sp1,
|
||||
ASplat sp2)
|
||||
{
|
||||
ASplat sp = aNewSplat();
|
||||
sp.material0 = weights.r * sp0.material0 + weights.g * sp1.material0 + weights.b * sp2.material0;
|
||||
sp.material1 = weights.r * sp0.material1 + weights.g * sp1.material1 + weights.b * sp2.material1;
|
||||
sp.material2 = weights.r * sp0.material2 + weights.g * sp1.material2 + weights.b * sp2.material2;
|
||||
sp.normal = weights.r * sp0.normal + weights.g * sp1.normal + weights.b * sp2.normal;
|
||||
aApplySplat(s, sp);
|
||||
}
|
||||
|
||||
void aApplyTerrainSplats(
|
||||
inout ASurface s,
|
||||
half4 weights,
|
||||
ASplat sp0,
|
||||
ASplat sp1,
|
||||
ASplat sp2,
|
||||
ASplat sp3)
|
||||
{
|
||||
ASplat sp = aNewSplat();
|
||||
sp.material0 = weights.r * sp0.material0 + weights.g * sp1.material0 + weights.b * sp2.material0 + weights.a * sp3.material0;
|
||||
sp.material1 = weights.r * sp0.material1 + weights.g * sp1.material1 + weights.b * sp2.material1 + weights.a * sp3.material1;
|
||||
sp.material2 = weights.r * sp0.material2 + weights.g * sp1.material2 + weights.b * sp2.material2 + weights.a * sp3.material2;
|
||||
sp.normal = weights.r * sp0.normal + weights.g * sp1.normal + weights.b * sp2.normal + weights.a * sp3.normal;
|
||||
aApplySplat(s, sp);
|
||||
}
|
||||
|
||||
half aOcclusionStrength(
|
||||
half ao,
|
||||
half weight)
|
||||
{
|
||||
return aLerpOneTo(aGammaToLinear(ao), weight);
|
||||
}
|
||||
|
||||
void aBaseUvInit(
|
||||
inout ASurface s)
|
||||
{
|
||||
s.baseUv = A_TEX_TRANSFORM_UV_SCROLL(s, _MainTex);
|
||||
s.baseTiling = _MainTex_ST.xy;
|
||||
|
||||
// Initialize VirtualCoord here so subsequent calls can be cheaper updates.
|
||||
#ifdef _VIRTUALTEXTURING_ON
|
||||
s.baseVirtualCoord = VTComputeVirtualCoord(s.baseUv);
|
||||
#endif
|
||||
}
|
||||
|
||||
void aUpdateBaseUv(
|
||||
inout ASurface s)
|
||||
{
|
||||
#ifdef _VIRTUALTEXTURING_ON
|
||||
s.baseVirtualCoord = VTUpdateVirtualCoord(s.baseVirtualCoord, s.baseUv);
|
||||
#endif
|
||||
}
|
||||
|
||||
float2 aPickUv(
|
||||
ASurface s,
|
||||
float nameUv)
|
||||
{
|
||||
#ifdef A_TEX_UV_OFF
|
||||
return s.uv01.xy;
|
||||
#else
|
||||
return nameUv < 0.5f ? s.uv01.xy : s.uv01.zw;
|
||||
#endif
|
||||
}
|
||||
|
||||
float2 aPickUv(
|
||||
ASplatContext sc,
|
||||
float nameUv)
|
||||
{
|
||||
#ifdef A_TEX_UV_OFF
|
||||
return sc.uv01.xy;
|
||||
#else
|
||||
return nameUv < 0.5f ? sc.uv01.xy : sc.uv01.zw;
|
||||
#endif
|
||||
}
|
||||
|
||||
void aTwoSided(
|
||||
inout ASurface s)
|
||||
{
|
||||
#ifdef A_TWO_SIDED_SHADER
|
||||
s.normalTangent.xy = A_NT(s, s.facingSign > 0.0h || _TransInvertBackNormal < 0.5f ? s.normalTangent.xy : -s.normalTangent.xy);
|
||||
#endif
|
||||
}
|
||||
|
||||
void aCutout(
|
||||
ASurface s)
|
||||
{
|
||||
#ifdef _ALPHATEST_ON
|
||||
clip(s.opacity - _Cutoff);
|
||||
#endif
|
||||
}
|
||||
|
||||
half4 aSampleBase(
|
||||
ASurface s)
|
||||
{
|
||||
half4 result = 0.0h;
|
||||
|
||||
#ifdef _VIRTUALTEXTURING_ON
|
||||
result = VTSampleBase(s.baseVirtualCoord);
|
||||
#else
|
||||
result = tex2D(_MainTex, s.baseUv);
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
half4 aSampleMaterial(
|
||||
ASurface s)
|
||||
{
|
||||
half4 result = 0.0h;
|
||||
|
||||
#ifndef A_EXPANDED_MATERIAL_MAPS
|
||||
#ifndef _VIRTUALTEXTURING_ON
|
||||
result = tex2D(_SpecTex, s.baseUv);
|
||||
#else
|
||||
result = VTSampleSpecular(s.baseVirtualCoord);
|
||||
#endif
|
||||
|
||||
result.A_AO_CHANNEL = aGammaToLinear(result.A_AO_CHANNEL);
|
||||
#else
|
||||
half3 channels;
|
||||
|
||||
// Assuming sRGB texture sampling, undo it for all but AO.
|
||||
channels.x = tex2D(_MetallicMap, s.baseUv).g;
|
||||
channels.y = tex2D(_SpecularityMap, s.baseUv).g;
|
||||
channels.z = tex2D(_RoughnessMap, s.baseUv).g;
|
||||
channels = LinearToGammaSpace(channels);
|
||||
|
||||
result.A_METALLIC_CHANNEL = channels.x;
|
||||
result.A_AO_CHANNEL = tex2D(_AoMap, s.baseUv).g;
|
||||
result.A_SPECULARITY_CHANNEL = channels.y;
|
||||
result.A_ROUGHNESS_CHANNEL = channels.z;
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
half3 aSampleBumpScale(
|
||||
ASurface s,
|
||||
half scale)
|
||||
{
|
||||
half4 result = 0.0h;
|
||||
|
||||
#ifdef _VIRTUALTEXTURING_ON
|
||||
result = VTSampleNormal(s.baseVirtualCoord);
|
||||
#else
|
||||
result = tex2D(_BumpMap, s.baseUv);
|
||||
#endif
|
||||
|
||||
return UnpackScaleNormal(result, scale);
|
||||
}
|
||||
|
||||
half3 aSampleBump(
|
||||
ASurface s)
|
||||
{
|
||||
return aSampleBumpScale(s, _BumpScale);
|
||||
}
|
||||
|
||||
half3 aSampleBumpBias(
|
||||
ASurface s,
|
||||
float bias)
|
||||
{
|
||||
half4 result = 0.0h;
|
||||
|
||||
#ifdef _VIRTUALTEXTURING_ON
|
||||
result = VTSampleNormal(VTComputeVirtualCoord(s.baseUv, bias));
|
||||
#else
|
||||
result = tex2Dbias(_BumpMap, float4(s.baseUv, 0.0h, bias));
|
||||
#endif
|
||||
|
||||
return UnpackScaleNormal(result, _BumpScale);
|
||||
}
|
||||
|
||||
half aSampleHeight(
|
||||
ASurface s)
|
||||
{
|
||||
half result = 0.0h;
|
||||
|
||||
#ifdef _VIRTUALTEXTURING_ON
|
||||
result = VTSampleNormal(s.baseVirtualCoord).b;
|
||||
#else
|
||||
result = tex2D(_ParallaxMap, s.baseUv).y;
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
half3 aVertexColorTint(
|
||||
ASurface s,
|
||||
half strength)
|
||||
{
|
||||
#ifdef A_VERTEX_COLOR_IS_DATA
|
||||
return A_WHITE;
|
||||
#else
|
||||
return aLerpWhiteTo(s.vertexColor.rgb, strength);
|
||||
#endif
|
||||
}
|
||||
|
||||
half3 aBaseVertexColorTint(
|
||||
ASurface s)
|
||||
{
|
||||
return aVertexColorTint(s, _BaseColorVertexTint);
|
||||
}
|
||||
|
||||
half4 aBaseTint(
|
||||
ASurface s)
|
||||
{
|
||||
half4 result = _Color;
|
||||
|
||||
#ifndef A_VERTEX_COLOR_IS_DATA
|
||||
result.rgb *= aBaseVertexColorTint(s);
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
half4 aBase(
|
||||
ASurface s)
|
||||
{
|
||||
return aBaseTint(s) * aSampleBase(s);
|
||||
}
|
||||
|
||||
void aParallaxOffset(
|
||||
inout ASurface s,
|
||||
float2 offset)
|
||||
{
|
||||
#ifdef A_PARALLAX_MAPPED_PASS
|
||||
offset *= s.mask;
|
||||
|
||||
// To apply the parallax offset to secondary textures without causing swimming,
|
||||
// we must normalize it by removing the implicitly multiplied base map tiling.
|
||||
s.uv01 += (offset / s.baseTiling).xyxy;
|
||||
s.baseUv += A_BV(s, offset);
|
||||
#endif
|
||||
}
|
||||
|
||||
void aOffsetBumpMapping(
|
||||
inout ASurface s)
|
||||
{
|
||||
// NOTE: Prevents NaN compiler errors in DX9 mode for shadow pass.
|
||||
#if defined(A_TANGENT_TO_WORLD_ON) && defined(A_VIEW_DIR_TANGENT_ON)
|
||||
half h = aSampleHeight(s) * _Parallax - _Parallax * 0.5h;
|
||||
half3 v = s.viewDirTangent;
|
||||
|
||||
v.z += 0.42h;
|
||||
aParallaxOffset(s, h * (v.xy / v.z));
|
||||
#endif
|
||||
}
|
||||
|
||||
void aParallaxOcclusionMapping(
|
||||
inout ASurface s,
|
||||
float minSamples,
|
||||
float maxSamples)
|
||||
{
|
||||
// NOTE: Prevents NaN compiler errors in DX9 mode for shadow pass.
|
||||
#if defined(A_TANGENT_TO_WORLD_ON) && defined(A_VIEW_DIR_TANGENT_ON)
|
||||
// Parallax Occlusion Mapping
|
||||
// Subject to GameDev.net Open License
|
||||
// cf http://www.gamedev.net/page/resources/_/technical/graphics-programming-and-theory/a-closer-look-at-parallax-occlusion-mapping-r3262
|
||||
float2 offset = float2(0.0f, 0.0f);
|
||||
|
||||
// Calculate the parallax offset vector max length.
|
||||
// This is equivalent to the tangent of the angle between the
|
||||
// viewer position and the fragment location.
|
||||
float parallaxLimit = -length(s.viewDirTangent.xy) / s.viewDirTangent.z;
|
||||
|
||||
// Scale the parallax limit according to heightmap scale.
|
||||
parallaxLimit *= _Parallax;
|
||||
|
||||
// Calculate the parallax offset vector direction and maximum offset.
|
||||
float2 offsetDirTangent = normalize(s.viewDirTangent.xy);
|
||||
float2 maxOffset = offsetDirTangent * parallaxLimit;
|
||||
|
||||
// Calculate how many samples should be taken along the view ray
|
||||
// to find the surface intersection. This is based on the angle
|
||||
// between the surface normal and the view vector.
|
||||
int numSamples = (int)lerp(maxSamples, minSamples, s.NdotV);
|
||||
int currentSample = 0;
|
||||
|
||||
// Specify the view ray step size. Each sample will shift the current
|
||||
// view ray by this amount.
|
||||
float stepSize = 1.0f / (float)numSamples;
|
||||
|
||||
// Initialize the starting view ray height and the texture offsets.
|
||||
float currentRayHeight = 1.0f;
|
||||
float2 lastOffset = float2(0.0f, 0.0f);
|
||||
|
||||
float lastSampledHeight = 1.0f;
|
||||
float currentSampledHeight = 1.0f;
|
||||
|
||||
#ifdef _VIRTUALTEXTURING_ON
|
||||
VirtualCoord vcoord = s.baseVirtualCoord;
|
||||
#else
|
||||
// Calculate the texture coordinate partial derivatives in screen
|
||||
// space for the tex2Dgrad texture sampling instruction.
|
||||
float2 dx = ddx(s.baseUv);
|
||||
float2 dy = ddy(s.baseUv);
|
||||
#endif
|
||||
|
||||
while (currentSample < numSamples) {
|
||||
#ifdef _VIRTUALTEXTURING_ON
|
||||
vcoord = VTUpdateVirtualCoord(vcoord, s.baseUv + offset);
|
||||
currentSampledHeight = VTSampleNormal(vcoord).b;
|
||||
#else
|
||||
// Sample the heightmap at the current texcoord offset.
|
||||
currentSampledHeight = tex2Dgrad(_ParallaxMap, s.baseUv + offset, dx, dy).y;
|
||||
#endif
|
||||
|
||||
// Test if the view ray has intersected the surface.
|
||||
UNITY_BRANCH
|
||||
if (currentSampledHeight > currentRayHeight) {
|
||||
// Find the relative height delta before and after the intersection.
|
||||
// This provides a measure of how close the intersection is to
|
||||
// the final sample location.
|
||||
float delta1 = currentSampledHeight - currentRayHeight;
|
||||
float delta2 = (currentRayHeight + stepSize) - lastSampledHeight;
|
||||
float ratio = delta1 / (delta1 + delta2);
|
||||
|
||||
// Interpolate between the final two segments to
|
||||
// find the true intersection point offset.
|
||||
offset = lerp(offset, lastOffset, ratio);
|
||||
|
||||
// Force the exit of the while loop
|
||||
currentSample = numSamples + 1;
|
||||
}
|
||||
else {
|
||||
// The intersection was not found. Now set up the loop for the next
|
||||
// iteration by incrementing the sample count,
|
||||
currentSample++;
|
||||
|
||||
// take the next view ray height step,
|
||||
currentRayHeight -= stepSize;
|
||||
|
||||
// save the current texture coordinate offset and increment
|
||||
// to the next sample location,
|
||||
lastOffset = offset;
|
||||
offset += stepSize * maxOffset;
|
||||
|
||||
// and finally save the current heightmap height.
|
||||
lastSampledHeight = currentSampledHeight;
|
||||
}
|
||||
}
|
||||
|
||||
aParallaxOffset(s, offset);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // ALLOY_SHADERS_FRAMEWORK_FEATURE_IMPL_CGINC
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1e933ac91f881374f8971a009670b12c
|
||||
timeCreated: 1473016974
|
||||
licenseType: Pro
|
||||
ShaderImporter:
|
||||
defaultTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,648 @@
|
||||
// Alloy Physical Shader Framework
|
||||
// Copyright 2013-2017 RUST LLC.
|
||||
// http://www.alloy.rustltd.com/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// @file Forward.cginc
|
||||
/// @brief Forward passes uber-header.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef ALLOY_SHADERS_FRAMEWORK_FORWARD_CGINC
|
||||
#define ALLOY_SHADERS_FRAMEWORK_FORWARD_CGINC
|
||||
|
||||
// Headers both for this file, and for all Definition and Feature modules.
|
||||
#include "Assets/Alloy/Shaders/Framework/FeatureImpl.cginc"
|
||||
#include "Assets/Alloy/Shaders/Framework/LightingImpl.cginc"
|
||||
#include "Assets/Alloy/Shaders/Framework/TypeImpl.cginc"
|
||||
#include "Assets/Alloy/Shaders/Framework/Unity.cginc"
|
||||
#include "Assets/Alloy/Shaders/Framework/Utility.cginc"
|
||||
|
||||
#include "AutoLight.cginc"
|
||||
#include "HLSLSupport.cginc"
|
||||
#include "UnityCG.cginc"
|
||||
#include "UnityGlobalIllumination.cginc"
|
||||
#include "UnityImageBasedLighting.cginc"
|
||||
#include "UnityInstancing.cginc"
|
||||
#include "UnityLightingCommon.cginc"
|
||||
#include "UnityShaderUtilities.cginc"
|
||||
#include "UnityShaderVariables.cginc"
|
||||
#include "UnityShadowLibrary.cginc"
|
||||
#include "UnityStandardUtils.cginc"
|
||||
|
||||
// Support for two-sided effects in a single pass.
|
||||
#ifndef A_TWO_SIDED_SHADER
|
||||
#define A_FACING_SIGN_PARAM
|
||||
#define A_FACING_SIGN 1.0h
|
||||
#else
|
||||
#define A_FACING_SIGN_PARAM ,half facingSign : VFACE
|
||||
#define A_FACING_SIGN facingSign
|
||||
#endif
|
||||
|
||||
// Shadows.
|
||||
#if defined(SHADOWS_SCREEN) && !defined(UNITY_NO_SCREENSPACE_SHADOWS)
|
||||
#define A_SCREENSPACE_SHADOWS_ON
|
||||
#endif
|
||||
|
||||
// Lightmaps.
|
||||
#if !defined(A_UV2_ON) && defined(DYNAMICLIGHTMAP_ON) && defined(A_INDIRECT_ON)
|
||||
#define A_UV2_ON
|
||||
#endif
|
||||
|
||||
#if defined(LIGHTMAP_ON) && defined(LIGHTMAP_SHADOW_MIXING) && !defined(SHADOWS_SHADOWMASK) && defined(SHADOWS_SCREEN)
|
||||
#define A_LIGHTMAP_SHADOW_MIXING_ON
|
||||
#endif
|
||||
|
||||
// Lighting vertex data.
|
||||
#if defined(A_INDIRECT_ON) && defined(A_DIRECT_ON)
|
||||
#define A_FORWARD_TEXCOORD0 half4 giData : TEXCOORD0;
|
||||
#define A_FORWARD_TEXCOORD1 UNITY_SHADOW_COORDS(1)
|
||||
#elif defined(A_INDIRECT_ON)
|
||||
#define A_FORWARD_TEXCOORD0 half4 giData : TEXCOORD0;
|
||||
|
||||
#ifdef A_SHADOW_MASKS_BUFFER_ON
|
||||
#define A_FORWARD_TEXCOORD1 UNITY_SHADOW_COORDS(1)
|
||||
#endif
|
||||
#elif defined(A_DIRECT_ON)
|
||||
#define A_FORWARD_TEXCOORD0 UNITY_SHADOW_COORDS(0)
|
||||
|
||||
// Reduce v2f transfer cost for pure directional lights.
|
||||
#if !defined(DIRECTIONAL) && !defined(A_LIGHTMAP_SHADOW_MIXING_ON)
|
||||
#define A_FORWARD_TEXCOORD1 unityShadowCoord4 lightCoord : TEXCOORD1;
|
||||
|
||||
#ifndef USING_DIRECTIONAL_LIGHT
|
||||
#define A_FORWARD_TEXCOORD2 float4 lightVectorRange : TEXCOORD2;
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Handle dependencies between vertex data.
|
||||
#if !defined(A_TANGENT_ON) && defined(A_TANGENT_TO_WORLD_ON)
|
||||
#define A_TANGENT_ON
|
||||
#endif
|
||||
|
||||
#if !defined(A_NORMAL_WORLD_ON) && (defined(A_TANGENT_TO_WORLD_ON) || defined(A_REFLECTION_VECTOR_WORLD_ON))
|
||||
#define A_NORMAL_WORLD_ON
|
||||
#endif
|
||||
|
||||
#if !defined(A_VIEW_DIR_WORLD_ON) && (defined(A_VIEW_DIR_TANGENT_ON) || defined(A_REFLECTION_VECTOR_WORLD_ON))
|
||||
#define A_VIEW_DIR_WORLD_ON
|
||||
#endif
|
||||
|
||||
#if !defined(A_POSITION_WORLD_ON) && defined(A_VIEW_DIR_WORLD_ON)
|
||||
#define A_POSITION_WORLD_ON
|
||||
#endif
|
||||
|
||||
#if !defined(A_SCREEN_UV_ON) && defined(LOD_FADE_CROSSFADE)
|
||||
#define A_SCREEN_UV_ON
|
||||
#endif
|
||||
|
||||
// Enable specific packed texcoord channels.
|
||||
#if !defined(A_POSITION_TEXCOORD_ON) && (defined(A_POSITION_WORLD_ON) || defined(A_VIEW_DEPTH_ON))
|
||||
#define A_POSITION_TEXCOORD_ON
|
||||
#endif
|
||||
|
||||
#if !defined(A_FOG_TEXCOORD_ON) && (defined(A_FOG_ON) || defined(A_SCREEN_UV_ON))
|
||||
#define A_FOG_TEXCOORD_ON
|
||||
#endif
|
||||
|
||||
#if !defined(A_TRANSFER_INSTANCE_ID_ON) && defined(A_WORLD_TO_OBJECT_ON) && defined(A_INSTANCING_PASS)
|
||||
#define A_TRANSFER_INSTANCE_ID_ON
|
||||
#endif
|
||||
|
||||
// Split vertex data conditions to reduce combinations.
|
||||
// UV0-1, TBN, N.
|
||||
#if defined(A_TANGENT_TO_WORLD_ON)
|
||||
#define A_INNER_VERTEX_DATA2(A, B, C, D) \
|
||||
float4 texcoords : TEXCOORD##A; \
|
||||
half3 tangentWorld : TEXCOORD##B; \
|
||||
half3 bitangentWorld : TEXCOORD##C; \
|
||||
half3 normalWorld : TEXCOORD##D;
|
||||
#elif defined(A_NORMAL_WORLD_ON)
|
||||
#define A_INNER_VERTEX_DATA2(A, B, C, D) \
|
||||
float4 texcoords : TEXCOORD##A; \
|
||||
half3 normalWorld : TEXCOORD##B;
|
||||
#else
|
||||
#define A_INNER_VERTEX_DATA2(A, B, C, D) \
|
||||
float4 texcoords : TEXCOORD##A;
|
||||
#endif
|
||||
|
||||
// Vertex Color, Position, View Depth, Fog, and Screen UV.
|
||||
#if defined(A_POSITION_TEXCOORD_ON) && defined(A_FOG_TEXCOORD_ON)
|
||||
#define A_INNER_VERTEX_DATA1(A, B, C, D, E, F, G) \
|
||||
half4 color : TEXCOORD##A; \
|
||||
float4 positionWorldAndViewDepth : TEXCOORD##B; \
|
||||
UNITY_FOG_COORDS_PACKED(C, half4) \
|
||||
A_INNER_VERTEX_DATA2(D, E, F, G)
|
||||
#elif defined(A_POSITION_TEXCOORD_ON)
|
||||
#define A_INNER_VERTEX_DATA1(A, B, C, D, E, F, G) \
|
||||
half4 color : TEXCOORD##A; \
|
||||
float4 positionWorldAndViewDepth : TEXCOORD##B; \
|
||||
A_INNER_VERTEX_DATA2(C, D, E, F)
|
||||
#elif defined(A_FOG_TEXCOORD_ON)
|
||||
#define A_INNER_VERTEX_DATA1(A, B, C, D, E, F, G) \
|
||||
half4 color : TEXCOORD##A; \
|
||||
UNITY_FOG_COORDS_PACKED(C, half4) \
|
||||
A_INNER_VERTEX_DATA2(D, E, F, G)
|
||||
#else
|
||||
#define A_INNER_VERTEX_DATA1(A, B, C, D, E, F, G) \
|
||||
half4 color : TEXCOORD##A; \
|
||||
A_INNER_VERTEX_DATA2(B, C, D, E)
|
||||
#endif
|
||||
|
||||
// Instancing.
|
||||
#if defined(A_TRANSFER_INSTANCE_ID_ON) && defined(A_STEREO_INSTANCING_PASS)
|
||||
#define A_INSTANCING_VERTEX_DATA(A, B, C, D, E, F, G) A_INNER_VERTEX_DATA1(A, B, C, D, E, F, G) UNITY_VERTEX_INPUT_INSTANCE_ID UNITY_VERTEX_OUTPUT_STEREO
|
||||
#elif defined(A_TRANSFER_INSTANCE_ID_ON)
|
||||
#define A_INSTANCING_VERTEX_DATA(A, B, C, D, E, F, G) A_INNER_VERTEX_DATA1(A, B, C, D, E, F, G) UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||
#elif defined(A_STEREO_INSTANCING_PASS)
|
||||
#define A_INSTANCING_VERTEX_DATA(A, B, C, D, E, F, G) A_INNER_VERTEX_DATA1(A, B, C, D, E, F, G) UNITY_VERTEX_OUTPUT_STEREO
|
||||
#else
|
||||
#define A_INSTANCING_VERTEX_DATA(A, B, C, D, E, F, G) A_INNER_VERTEX_DATA1(A, B, C, D, E, F, G)
|
||||
#endif
|
||||
|
||||
// Surface shader off.
|
||||
#if defined(A_SURFACE_SHADER_OFF)
|
||||
#define A_VERTEX_DATA(A, B, C, D, E, F, G)
|
||||
#else
|
||||
#define A_VERTEX_DATA(A, B, C, D, E, F, G) A_INSTANCING_VERTEX_DATA(A, B, C, D, E, F, G)
|
||||
#endif
|
||||
|
||||
/// Configurable vertex input data from the application.
|
||||
struct AVertexInput
|
||||
{
|
||||
float4 vertex : POSITION;
|
||||
float4 uv0 : TEXCOORD0;
|
||||
float4 uv1 : TEXCOORD1;
|
||||
half3 normal : NORMAL;
|
||||
#ifdef A_UV2_ON
|
||||
float4 uv2 : TEXCOORD2;
|
||||
#endif
|
||||
#ifdef A_UV3_ON
|
||||
float4 uv3 : TEXCOORD3;
|
||||
#endif
|
||||
#ifdef A_TANGENT_ON
|
||||
half4 tangent : TANGENT;
|
||||
#endif
|
||||
half4 color : COLOR;
|
||||
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||
};
|
||||
|
||||
/// Extensible fragment input data.
|
||||
struct AFragmentInput {
|
||||
#if defined(A_FORWARD_TEXCOORD0) && defined(A_FORWARD_TEXCOORD1) && defined(A_FORWARD_TEXCOORD2)
|
||||
A_FORWARD_TEXCOORD0
|
||||
A_FORWARD_TEXCOORD1
|
||||
A_FORWARD_TEXCOORD2
|
||||
A_VERTEX_DATA(3, 4, 5, 6, 7, 8, 9)
|
||||
#elif defined(A_FORWARD_TEXCOORD0) && defined(A_FORWARD_TEXCOORD1)
|
||||
A_FORWARD_TEXCOORD0
|
||||
A_FORWARD_TEXCOORD1
|
||||
A_VERTEX_DATA(2, 3, 4, 5, 6, 7, 8)
|
||||
#elif defined(A_FORWARD_TEXCOORD0)
|
||||
A_FORWARD_TEXCOORD0
|
||||
A_VERTEX_DATA(1, 2, 3, 4, 5, 6, 7)
|
||||
#else
|
||||
A_VERTEX_DATA(0, 1, 2, 3, 4, 5, 6)
|
||||
#endif
|
||||
};
|
||||
|
||||
// TODO: Find a way to move this dependency!
|
||||
#include "Assets/Alloy/Shaders/Framework/Tessellation.cginc"
|
||||
|
||||
/// Transfers the per-vertex lightmapping or SH data to the fragment shader.
|
||||
/// @param[in,out] i Vertex to fragment transfer data.
|
||||
/// @param[in] v Vertex input data.
|
||||
void aVertexGi(
|
||||
inout AFragmentInput i,
|
||||
AVertexInput v)
|
||||
{
|
||||
#ifdef A_INDIRECT_ON
|
||||
#ifdef LIGHTMAP_ON
|
||||
i.giData.xy = v.uv1.xy * unity_LightmapST.xy + unity_LightmapST.zw;
|
||||
i.giData.zw = 0.0h;
|
||||
#elif UNITY_SHOULD_SAMPLE_SH
|
||||
// Add approximated illumination from non-important point lights
|
||||
half3 normalWorld = i.normalWorld.xyz;
|
||||
|
||||
#ifdef VERTEXLIGHT_ON
|
||||
i.giData.rgb = aShade4PointLights(i.positionWorldAndViewDepth.xyz, normalWorld);
|
||||
#endif
|
||||
|
||||
i.giData.rgb = ShadeSHPerVertex(normalWorld, i.giData.rgb);
|
||||
#endif
|
||||
|
||||
#ifdef DYNAMICLIGHTMAP_ON
|
||||
i.giData.zw = v.uv2.xy * unity_DynamicLightmapST.xy + unity_DynamicLightmapST.zw;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Populates a UnityGI descriptor in the fragment shader.
|
||||
/// @param i Vertex to fragment transfer data.
|
||||
/// @param s Material surface data.
|
||||
/// @param shadow Forward Base directional light shadow.
|
||||
/// @return Initialized UnityGI descriptor.
|
||||
UnityGI aFragmentGi(
|
||||
AFragmentInput i,
|
||||
ASurface s,
|
||||
half shadow)
|
||||
{
|
||||
UnityGI gi;
|
||||
UNITY_INITIALIZE_OUTPUT(UnityGI, gi);
|
||||
|
||||
#ifdef A_INDIRECT_ON
|
||||
UnityGIInput d;
|
||||
|
||||
UNITY_INITIALIZE_OUTPUT(UnityGIInput, d);
|
||||
d.worldPos = s.positionWorld;
|
||||
d.worldViewDir = s.viewDirWorld; // ???
|
||||
d.atten = shadow;
|
||||
|
||||
#if defined(LIGHTMAP_ON) || defined(DYNAMICLIGHTMAP_ON)
|
||||
d.ambient = 0;
|
||||
d.lightmapUV = i.giData;
|
||||
#else
|
||||
d.ambient = i.giData.rgb;
|
||||
d.lightmapUV = 0;
|
||||
#endif
|
||||
|
||||
d.probeHDR[0] = unity_SpecCube0_HDR;
|
||||
d.probeHDR[1] = unity_SpecCube1_HDR;
|
||||
|
||||
#if defined(UNITY_SPECCUBE_BLENDING) || defined(UNITY_SPECCUBE_BOX_PROJECTION)
|
||||
d.boxMin[0] = unity_SpecCube0_BoxMin; // .w holds lerp value for blending
|
||||
#endif
|
||||
|
||||
#ifdef UNITY_SPECCUBE_BOX_PROJECTION
|
||||
d.boxMax[0] = unity_SpecCube0_BoxMax;
|
||||
d.probePosition[0] = unity_SpecCube0_ProbePosition;
|
||||
d.boxMax[1] = unity_SpecCube1_BoxMax;
|
||||
d.boxMin[1] = unity_SpecCube1_BoxMin;
|
||||
d.probePosition[1] = unity_SpecCube1_ProbePosition;
|
||||
#endif
|
||||
|
||||
// So we can extract shadow with baked occlusion.
|
||||
#ifdef HANDLE_SHADOWS_BLENDING_IN_GI
|
||||
d.light.color = A_WHITE;
|
||||
#endif
|
||||
|
||||
// Pass 1.0 for occlusion so we can apply it later in indirect().
|
||||
gi = UnityGI_Base(d, 1.0h, s.ambientNormalWorld);
|
||||
|
||||
#ifdef A_REFLECTION_PROBES_ON
|
||||
Unity_GlossyEnvironmentData g;
|
||||
|
||||
g.reflUVW = s.reflectionVectorWorld;
|
||||
g.roughness = s.roughness;
|
||||
gi.indirect.specular = UnityGI_IndirectSpecular(d, 1.0h, s.normalWorld, g);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return gi;
|
||||
}
|
||||
|
||||
/// Transforms the vertex data before transferring it to the pixel shader.
|
||||
/// @param[in,out] v Vertex input data.
|
||||
/// @param[out] o Vertex to fragment transfer data.
|
||||
/// @param[out] opos Clip space position.
|
||||
void aForwardVertexShader(
|
||||
inout AVertexInput v,
|
||||
out AFragmentInput o,
|
||||
out float4 opos)
|
||||
{
|
||||
#ifdef A_SURFACE_SHADER_OFF
|
||||
opos = 0.0h;
|
||||
#else
|
||||
UNITY_INITIALIZE_OUTPUT(AFragmentInput, o);
|
||||
|
||||
#ifdef A_INSTANCING_PASS
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
|
||||
#ifdef A_TRANSFER_INSTANCE_ID_ON
|
||||
UNITY_TRANSFER_INSTANCE_ID(v, o);
|
||||
#endif
|
||||
|
||||
#ifdef A_STEREO_INSTANCING_PASS
|
||||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Copy vertex data, and let shader type modify it.
|
||||
AVertex vs = aNewVertex();
|
||||
|
||||
vs.positionObject = v.vertex;
|
||||
vs.uv0 = v.uv0;
|
||||
vs.uv1 = v.uv1;
|
||||
vs.normalObject = v.normal;
|
||||
|
||||
#ifdef A_UV2_ON
|
||||
vs.uv2 = v.uv2;
|
||||
#endif
|
||||
#ifdef A_UV3_ON
|
||||
vs.uv3 = v.uv3;
|
||||
#endif
|
||||
#ifdef A_TANGENT_ON
|
||||
vs.tangentObject = v.tangent;
|
||||
#endif
|
||||
|
||||
vs.color = v.color;
|
||||
|
||||
aVertexShader(vs);
|
||||
|
||||
// Copy data back into original, in case outer shader needs it.
|
||||
v.vertex = vs.positionObject;
|
||||
v.uv0 = vs.uv0;
|
||||
v.uv1 = vs.uv1;
|
||||
v.normal = vs.normalObject;
|
||||
|
||||
#ifdef A_UV2_ON
|
||||
v.uv2 = vs.uv2;
|
||||
#endif
|
||||
#ifdef A_UV3_ON
|
||||
v.uv3 = vs.uv3;
|
||||
#endif
|
||||
#ifdef A_TANGENT_ON
|
||||
v.tangent = vs.tangentObject;
|
||||
#endif
|
||||
|
||||
v.color = vs.color;
|
||||
|
||||
// Fill V2F.
|
||||
o.color = v.color; // Gamma-space vertex color, unless modified.
|
||||
o.texcoords.xy = v.uv0.xy;
|
||||
o.texcoords.zw = v.uv1.xy;
|
||||
opos = UnityObjectToClipPos(v.vertex.xyz);
|
||||
|
||||
#ifdef A_POSITION_TEXCOORD_ON
|
||||
#ifdef A_POSITION_WORLD_ON
|
||||
o.positionWorldAndViewDepth.xyz = mul(unity_ObjectToWorld, v.vertex).xyz;
|
||||
#endif
|
||||
|
||||
#ifdef A_VIEW_DEPTH_ON
|
||||
COMPUTE_EYEDEPTH(o.positionWorldAndViewDepth.w);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef A_NORMAL_WORLD_ON
|
||||
float3 normalWorld = UnityObjectToWorldNormal(v.normal);
|
||||
#endif
|
||||
|
||||
#ifndef A_TANGENT_TO_WORLD_ON
|
||||
#ifdef A_NORMAL_WORLD_ON
|
||||
o.normalWorld = normalWorld;
|
||||
#endif
|
||||
#else
|
||||
float3 tangentWorld = UnityObjectToWorldDir(v.tangent.xyz);
|
||||
float3x3 tangentToWorld = CreateTangentToWorldPerVertex(normalWorld, tangentWorld, v.tangent.w);
|
||||
|
||||
o.tangentWorld = tangentToWorld[0];
|
||||
o.bitangentWorld = tangentToWorld[1];
|
||||
o.normalWorld = tangentToWorld[2];
|
||||
#endif
|
||||
|
||||
#if defined(A_SCREEN_UV_ON) || (defined(A_DIRECT_ON) && defined(A_SCREENSPACE_SHADOWS_ON))
|
||||
float4 screenPos = ComputeScreenPos(opos);
|
||||
#endif
|
||||
|
||||
// Fog and Screen UV.
|
||||
#ifdef A_FOG_TEXCOORD_ON
|
||||
#ifdef A_SCREEN_UV_ON
|
||||
o.fogCoord.yzw = screenPos.xyw;
|
||||
#else
|
||||
o.fogCoord.yzw = A_AXIS_Z;
|
||||
#endif
|
||||
|
||||
#ifdef A_FOG_ON
|
||||
UNITY_TRANSFER_FOG(o, opos);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Lighting data.
|
||||
aVertexGi(o, v);
|
||||
|
||||
#ifdef A_DIRECT_ON
|
||||
// NOTE: Custom macro to skip calculations and remove dependency on o.pos!
|
||||
#ifdef A_SCREENSPACE_SHADOWS_ON
|
||||
o._ShadowCoord = screenPos;
|
||||
#else
|
||||
UNITY_TRANSFER_SHADOW(o, v.uv1);
|
||||
#endif
|
||||
|
||||
#if !defined(DIRECTIONAL) && !defined(A_LIGHTMAP_SHADOW_MIXING_ON)
|
||||
o.lightCoord = mul(unity_WorldToLight, unityShadowCoord4(o.positionWorldAndViewDepth.xyz, 1.0f));
|
||||
|
||||
#ifndef USING_DIRECTIONAL_LIGHT
|
||||
o.lightVectorRange = UnityWorldSpaceLightDir(o.positionWorldAndViewDepth.xyz).xyzz;
|
||||
aLightRange(o.lightVectorRange, o.lightCoord);
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Create a surface populated with material data.
|
||||
/// @param i Vertex to fragment transfer data.
|
||||
/// @param facingSign Sign of front/back facing direction.
|
||||
/// @return Initialized surface data object.
|
||||
ASurface aForwardSurface(
|
||||
AFragmentInput i,
|
||||
half facingSign)
|
||||
{
|
||||
ASurface s = aNewSurface();
|
||||
|
||||
#ifndef A_SURFACE_SHADER_OFF
|
||||
#ifdef A_TRANSFER_INSTANCE_ID_ON
|
||||
UNITY_SETUP_INSTANCE_ID(i);
|
||||
#endif
|
||||
|
||||
s.uv01 = i.texcoords;
|
||||
s.vertexColor = i.color;
|
||||
s.facingSign = facingSign;
|
||||
|
||||
#ifdef A_POSITION_TEXCOORD_ON
|
||||
#ifdef A_POSITION_WORLD_ON
|
||||
s.positionWorld = i.positionWorldAndViewDepth.xyz;
|
||||
#endif
|
||||
|
||||
#ifdef A_VIEW_DEPTH_ON
|
||||
s.viewDepth = i.positionWorldAndViewDepth.w;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef A_NORMAL_WORLD_ON
|
||||
#ifdef A_TWO_SIDED_SHADER
|
||||
i.normalWorld.xyz *= facingSign;
|
||||
#endif
|
||||
|
||||
// Give these sane defaults in case the surface shader doesn't set them.
|
||||
s.vertexNormalWorld = normalize(i.normalWorld);
|
||||
s.normalWorld = s.vertexNormalWorld;
|
||||
s.ambientNormalWorld = s.vertexNormalWorld;
|
||||
#endif
|
||||
|
||||
#ifdef A_VIEW_DIR_WORLD_ON
|
||||
// Cheaper to calculate in PS than to unpack from vertex, while also
|
||||
// preventing distortion in POM and area light specular highlights.
|
||||
s.viewDirWorld = normalize(UnityWorldSpaceViewDir(s.positionWorld));
|
||||
#endif
|
||||
|
||||
#ifdef A_TANGENT_TO_WORLD_ON
|
||||
half3 t = i.tangentWorld;
|
||||
half3 b = i.bitangentWorld;
|
||||
half3 n = i.normalWorld;
|
||||
|
||||
#if UNITY_TANGENT_ORTHONORMALIZE
|
||||
n = normalize(n);
|
||||
|
||||
// ortho-normalize Tangent
|
||||
t = normalize (t - n * dot(t, n));
|
||||
|
||||
// recalculate Binormal
|
||||
half3 newB = cross(n, t);
|
||||
b = newB * sign (dot (newB, b));
|
||||
#endif
|
||||
|
||||
s.tangentToWorld = half3x3(t, b, n);
|
||||
|
||||
#if defined(A_VIEW_DIR_WORLD_ON) && defined(A_VIEW_DIR_TANGENT_ON)
|
||||
s.viewDirTangent = normalize(mul(s.tangentToWorld, s.viewDirWorld));
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef A_FOG_TEXCOORD_ON
|
||||
#ifdef A_FOG_ON
|
||||
s.fogCoord = i.fogCoord;
|
||||
#endif
|
||||
|
||||
#ifdef A_SCREEN_UV_ON
|
||||
s.screenPosition.xyw = i.fogCoord.yzw;
|
||||
s.screenPosition.z = 0.0h;
|
||||
s.screenUv.xy = s.screenPosition.xy / s.screenPosition.w;
|
||||
|
||||
#ifdef LOD_FADE_CROSSFADE
|
||||
half2 projUV = s.screenUv.xy * _ScreenParams.xy * 0.25h;
|
||||
|
||||
projUV.y = frac(projUV.y) * 0.0625h /* 1/16 */ + unity_LODFade.y; // quantized lod fade by 16 levels
|
||||
clip(tex2D(_DitherMaskLOD2D, projUV).a - 0.5f);
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Runs the shader and lighting type's surface code.
|
||||
aBaseUvInit(s);
|
||||
aUpdateViewData(s);
|
||||
aSurfaceShader(s);
|
||||
aPreLighting(s);
|
||||
#endif
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
/// Final processing of the forward color before output.
|
||||
/// @param s Material surface data.
|
||||
/// @param color Lighting + Emission + Fog + etc.
|
||||
/// @return Final HDR output color with alpha opacity.
|
||||
half4 aForwardColor(
|
||||
ASurface s,
|
||||
half3 color)
|
||||
{
|
||||
half4 output;
|
||||
|
||||
#if defined(A_ALPHA_BLENDING_PASS) && defined(A_ALPHA_BLENDING_ON)
|
||||
output.a = s.opacity;
|
||||
#else
|
||||
UNITY_OPAQUE_ALPHA(output.a);
|
||||
#endif
|
||||
|
||||
output.rgb = color;
|
||||
aColorShader(output, s);
|
||||
return aHdrClamp(output);
|
||||
}
|
||||
|
||||
/// Calculates forward lighting from surface and vertex data.
|
||||
/// @param i Vertex to fragment transfer data.
|
||||
/// @param facingSign Sign of front/back facing direction.
|
||||
/// @return Forward direct and indirect lighting.
|
||||
half4 aForwardLitColorShader(
|
||||
AFragmentInput i,
|
||||
half facingSign)
|
||||
{
|
||||
half3 illum = 0.0h;
|
||||
ASurface s = aForwardSurface(i, facingSign);
|
||||
|
||||
#ifdef A_LIGHTING_ON
|
||||
half shadow = UNITY_SHADOW_ATTENUATION(i, s.positionWorld);
|
||||
|
||||
#ifdef A_INDIRECT_ON
|
||||
UnityGI gi = aFragmentGi(i, s, shadow);
|
||||
|
||||
illum = aUnityIndirectLighting(gi, s);
|
||||
|
||||
// Extract shadow with combined baked occlusion.
|
||||
#ifdef HANDLE_SHADOWS_BLENDING_IN_GI
|
||||
shadow = gi.light.color.g;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Do lightmap shadow mixing guard here, since we need direct vertex data.
|
||||
#if defined(A_DIRECT_ON) && !defined(A_LIGHTMAP_SHADOW_MIXING_ON)
|
||||
// Reduce v2f transfer cost for pure directional lights.
|
||||
#if defined(DIRECTIONAL)
|
||||
illum += aUnityDirectLighting(s, shadow, _WorldSpaceLightPos0, A_ZERO4);
|
||||
#elif defined(DIRECTIONAL_COOKIE)
|
||||
illum += aUnityDirectLighting(s, shadow, _WorldSpaceLightPos0, i.lightCoord);
|
||||
#else
|
||||
illum += aUnityDirectLighting(s, shadow, i.lightVectorRange, i.lightCoord);
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(A_BASE_PASS) && defined(A_EMISSIVE_COLOR_ON)
|
||||
illum += s.emissiveColor;
|
||||
#endif
|
||||
|
||||
return aForwardColor(s, illum);
|
||||
}
|
||||
|
||||
/// Creates a G-Buffer from the provided surface data.
|
||||
/// @param i Vertex to fragment transfer data.
|
||||
/// @param facingSign Sign of front/back facing direction.
|
||||
/// @return G-buffer with surface data and ambient illumination.
|
||||
AGbuffer aForwardLitGbufferShader(
|
||||
AFragmentInput i,
|
||||
half facingSign)
|
||||
{
|
||||
half3 illum = 0.0h;
|
||||
AGbuffer gb = aNewGbuffer();
|
||||
ASurface s = aForwardSurface(i, facingSign);
|
||||
|
||||
#ifdef A_INDIRECT_ON
|
||||
illum += aUnityIndirectLighting(aFragmentGi(i, s, 1.0h), s);
|
||||
|
||||
// Baked direct lighting occlusion if any.
|
||||
#ifdef A_SHADOW_MASKS_BUFFER_ON
|
||||
gb.shadowMasks = UnityGetRawBakedOcclusions(i.giData.xy, s.positionWorld);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef A_EMISSIVE_COLOR_ON
|
||||
illum += s.emissiveColor;
|
||||
#endif
|
||||
|
||||
#if defined(A_INDIRECT_ON) || defined(A_EMISSIVE_COLOR_ON)
|
||||
illum = aHdrClamp(illum);
|
||||
#endif
|
||||
|
||||
#ifndef UNITY_HDR_ON
|
||||
illum = exp2(-illum);
|
||||
#endif
|
||||
|
||||
gb.diffuseOcclusion = half4(s.albedo, s.specularOcclusion);
|
||||
gb.specularSmoothness = half4(s.f0, 1.0h - s.roughness);
|
||||
gb.normalType = half4(s.normalWorld * 0.5h + 0.5h, s.materialType);
|
||||
gb.emissionSubsurface = half4(illum, s.subsurface);
|
||||
aGbufferShader(gb, s);
|
||||
return gb;
|
||||
}
|
||||
|
||||
#endif // ALLOY_SHADERS_FRAMEWORK_FORWARD_CGINC
|
||||
@@ -0,0 +1,6 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d38ced127b82dbc4ba0d177f21160d88
|
||||
ShaderImporter:
|
||||
defaultTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
@@ -0,0 +1,531 @@
|
||||
// Alloy Physical Shader Framework
|
||||
// Copyright 2013-2017 RUST LLC.
|
||||
// http://www.alloy.rustltd.com/
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
/// @file Lighting.cginc
|
||||
/// @brief Lighting uber-header.
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef ALLOY_SHADERS_FRAMEWORK_LIGHTING_CGINC
|
||||
#define ALLOY_SHADERS_FRAMEWORK_LIGHTING_CGINC
|
||||
|
||||
// Headers both for this file, and for all Definition and Feature modules.
|
||||
#include "Assets/Alloy/Shaders/Framework/Utility.cginc"
|
||||
|
||||
#include "UnityLightingCommon.cginc"
|
||||
|
||||
#ifndef A_SURFACE_CUSTOM_FIELDS
|
||||
#define A_SURFACE_CUSTOM_FIELDS
|
||||
#endif
|
||||
|
||||
/// Tangent-space normal assignment and update of associated fields.
|
||||
#define A_NT(s, n) n; aUpdateNormalTangent(s)
|
||||
|
||||
/// World-space normal assignment and update of associated fields.
|
||||
#define A_NW(s, n) n; aUpdateNormalWorld(s)
|
||||
|
||||
/// Subsurface assignment and update of associated fields.
|
||||
#define A_SS(s, ss) ss; aUpdateSubsurface(s)
|
||||
|
||||
/// Subsurface color assignment and update of associated fields.
|
||||
#define A_SSC(s, ssc) ssc; aUpdateSubsurfaceColor(s)
|
||||
|
||||
// Use Unity's struct directly to avoid copying since the fields are the same.
|
||||
#define AIndirect UnityIndirect
|
||||
|
||||
/// Collection of direct illumination data.
|
||||
struct ADirect {
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Material lighting.
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Light color, attenuation, and cookies.
|
||||
/// Expects linear-space HDR color values.
|
||||
half3 color;
|
||||
|
||||
/// Shadowing.
|
||||
/// Expects values in the range [0,1].
|
||||
half shadow;
|
||||
|
||||
/// Specular highlight intensity.
|
||||
/// Expects values in the range [0,n].
|
||||
half specularIntensity;
|
||||
|
||||
/// Light direction in world-space.
|
||||
/// Expects normalized vectors.
|
||||
half3 direction;
|
||||
|
||||
/// Direction halfway between the light and view vectors in world space.
|
||||
/// Expects normalized vectors.
|
||||
half3 halfAngleWorld;
|
||||
|
||||
/// Clamped L.H.
|
||||
/// Expects values in the range [0,1].
|
||||
half LdotH;
|
||||
|
||||
/// Clamped N.H.
|
||||
/// Expects values in the range [0,1].
|
||||
half NdotH;
|
||||
|
||||
/// Clamped N.L.
|
||||
/// Expects values in the range [0,1].
|
||||
half NdotL;
|
||||
|
||||
/// Unclamped N.L.
|
||||
/// Expects values in the range [0,1].
|
||||
half NdotLm;
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Internal.
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Diffuse area light vector.
|
||||
/// Expects a non-normalized vector.
|
||||
float3 Ldiff;
|
||||
|
||||
/// Specular area light vector.
|
||||
/// Expects a non-normalized vector.
|
||||
float3 Lspec;
|
||||
|
||||
/// One over the distance to the center of the light volume.
|
||||
/// Expects values in the range [0,n).
|
||||
half centerDistInverse;
|
||||
};
|
||||
|
||||
/// Contains ALL data and state for rendering a surface.
|
||||
/// Can set state to control how features are combined into the surface data.
|
||||
struct ASurface {
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Vertex inputs.
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Screen-space position.
|
||||
float4 screenPosition;
|
||||
|
||||
/// Screen-space texture coordinates.
|
||||
float2 screenUv;
|
||||
|
||||
/// Position in world space.
|
||||
float3 positionWorld;
|
||||
|
||||
/// View direction in world space.
|
||||
/// Expects a normalized vector.
|
||||
half3 viewDirWorld;
|
||||
|
||||
/// Distance from the camera to the given fragement.
|
||||
/// Expects values in the range [0,n].
|
||||
half viewDepth;
|
||||
|
||||
/// Unity's fog data.
|
||||
float fogCoord;
|
||||
|
||||
/// Tangent space to World space rotation matrix.
|
||||
half3x3 tangentToWorld;
|
||||
|
||||
/// View direction in tangent space.
|
||||
/// Expects a normalized vector.
|
||||
half3 viewDirTangent;
|
||||
|
||||
/// Vertex color.
|
||||
/// Expects linear-space LDR color values.
|
||||
half4 vertexColor;
|
||||
|
||||
/// Vertex normal in world space.
|
||||
/// Expects normalized vectors.
|
||||
half3 vertexNormalWorld;
|
||||
|
||||
/// Indicates via sign whether a triangle is front or back facing.
|
||||
/// Positive is front-facing, negative is back-facing.
|
||||
half facingSign;
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Feature layering inputs.
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Masks where the next feature layer will be applied.
|
||||
/// Expects values in the range [0,1].
|
||||
half mask;
|
||||
|
||||
/// The base map's texture transform tiling amount.
|
||||
float2 baseTiling;
|
||||
|
||||
/// Transformed texture coordinates for the base map.
|
||||
float2 baseUv;
|
||||
|
||||
#ifdef _VIRTUALTEXTURING_ON
|
||||
/// Transformed texture coordinates for the virtual base map.
|
||||
VirtualCoord baseVirtualCoord;
|
||||
#endif
|
||||
|
||||
/// The model's UV0 & UV1 texture coordinate data.
|
||||
/// Be aware that it can have parallax precombined with it.
|
||||
float4 uv01;
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Surface inputs.
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Albedo and/or Metallic f0 based on settings. Used by Enlighten.
|
||||
/// Expects linear-space LDR color values.
|
||||
half3 baseColor;
|
||||
|
||||
/// Controls opacity or cutout regions.
|
||||
/// Expects values in the range [0,1].
|
||||
half opacity;
|
||||
|
||||
/// Interpolates material from dielectric to metal.
|
||||
/// Expects values in the range [0,1].
|
||||
half metallic;
|
||||
|
||||
/// Diffuse ambient occlusion.
|
||||
/// Expects values in the range [0,1].
|
||||
half ambientOcclusion;
|
||||
|
||||
/// Linear control of dielectric f0 from [0.00,0.08].
|
||||
/// Expects values in the range [0,1].
|
||||
half specularity;
|
||||
|
||||
/// Tints the dielectric specularity by the base color chromaticity.
|
||||
/// Expects values in the range [0,1].
|
||||
half specularTint;
|
||||
|
||||
/// Linear roughness value, where zero is smooth and one is rough.
|
||||
/// Expects values in the range [0,1].
|
||||
half roughness;
|
||||
|
||||
/// Light emission by the material.
|
||||
/// Expects linear-space HDR color values.
|
||||
half3 emissiveColor;
|
||||
|
||||
/// Color tint for transmission effect.
|
||||
/// Expects linear-space LDR color values.
|
||||
half3 subsurfaceColor;
|
||||
|
||||
/// Monochrome transmission thickness.
|
||||
/// Expects gamma-space LDR values.
|
||||
half subsurface;
|
||||
|
||||
/// Strength of clearcoat layer, used to apply masks.
|
||||
/// Expects values in the range [0,1].
|
||||
half clearCoat;
|
||||
|
||||
/// Roughness of clearcoat layer.
|
||||
/// Expects values in the range [0,1].
|
||||
half clearCoatRoughness;
|
||||
|
||||
/// Normal in world space.
|
||||
/// Expects a normalized vector.
|
||||
half3 normalWorld;
|
||||
|
||||
/// Normal in tangent space.
|
||||
/// Expects a normalized vector.
|
||||
half3 normalTangent;
|
||||
|
||||
/// Blurred normal in tangent space.
|
||||
/// Expects a normalized vector.
|
||||
half3 blurredNormalTangent;
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// BRDF inputs.
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Diffuse albedo.
|
||||
/// Expects linear-space LDR color values.
|
||||
half3 albedo;
|
||||
|
||||
/// Fresnel reflectance at incidence zero.
|
||||
/// Expects linear-space LDR color values.
|
||||
half3 f0;
|
||||
|
||||
/// Beckmann roughness.
|
||||
/// Expects values in the range [0,1].
|
||||
half beckmannRoughness;
|
||||
|
||||
/// Specular occlusion.
|
||||
/// Expects values in the range [0,1].
|
||||
half specularOcclusion;
|
||||
|
||||
/// Ambient diffuse normal in world space.
|
||||
/// Expects normalized vectors.
|
||||
half3 ambientNormalWorld;
|
||||
|
||||
/// View reflection vector in world space.
|
||||
/// Expects a non-normalized vector.
|
||||
half3 reflectionVectorWorld;
|
||||
|
||||
/// Clamped N.V.
|
||||
/// Expects values in the range [0,1].
|
||||
half NdotV;
|
||||
|
||||
/// Fresnel weight of N.V.
|
||||
/// Expects values in the range [0,1].
|
||||
half FV;
|
||||
|
||||
/// Deferred material lighting type.
|
||||
/// Expects the values 0, 1/3, 2/3, or 1.
|
||||
half materialType;
|
||||
|
||||
A_SURFACE_CUSTOM_FIELDS
|
||||
|
||||
half _skinScatteringMask;
|
||||
half _skinScattering;
|
||||
half _subsurfaceShadowWeight;
|
||||
};
|
||||
|
||||
/// Maximum linear-space non-metal specular reflectivity.
|
||||
static const half A_MAX_DIELECTRIC_F0 = 0.08h;
|
||||
|
||||
/// Minimum roughness that won't cause specular artifacts.
|
||||
static const half A_MIN_AREA_ROUGHNESS = 0.05h;
|
||||
|
||||
/// Front-faces cull mode.
|
||||
static const half A_CULL_MODE_FRONT = 1.0h;
|
||||
|
||||
/// Opaque shading type.
|
||||
static const half A_MATERIAL_TYPE_OPAQUE = 1.0h;
|
||||
|
||||
/// Shadowed subsurface transmission shading type.
|
||||
static const half A_MATERIAL_TYPE_SHADOWED_SUBSURFACE = 2.0h / 3.0h;
|
||||
|
||||
/// Unshadowed subsurface transmission shading type.
|
||||
static const half A_MATERIAL_TYPE_UNSHADOWED_SUBSURFACE = 1.0h / 3.0h;
|
||||
|
||||
/// Subsurface scattering shading type.
|
||||
static const half A_MATERIAL_TYPE_SUBSURFACE_SCATTERING = 0.0h;
|
||||
|
||||
#ifdef A_DEFERRED_PASS
|
||||
/// RGB=Blurred normals, A=Subsurface thickness.
|
||||
/// Expects value in the buffer alpha.
|
||||
sampler2D _DeferredPlusBuffer;
|
||||
#endif
|
||||
|
||||
#ifdef A_FORWARD_ONLY_SHADER
|
||||
/// Pre-Integrated scattering LUT.
|
||||
sampler2D _SssBrdfTex;
|
||||
|
||||
/// Weight of the scattering effect.
|
||||
/// Expects values in the range [0,1].
|
||||
half _SssWeight;
|
||||
|
||||
/// Cutoff value used to convert tranmission data to scattering mask.
|
||||
/// Expects values in the range [0.01,1].
|
||||
half _SssMaskCutoff;
|
||||
|
||||
/// Biases the thickness value used to look up in the skin LUT.
|
||||
/// Expects values in the range [0,1].
|
||||
half _SssBias;
|
||||
|
||||
/// Scales the thickness value used to look up in the skin LUT.
|
||||
/// Expects values in the range [0,1].
|
||||
half _SssScale;
|
||||
|
||||
/// Increases the bluriness of the normal map for diffuse lighting.
|
||||
/// Expects values in the range [0,1].
|
||||
half _SssBumpBlur;
|
||||
|
||||
/// Per-channel weights for thickness-based subsurface color absorption.
|
||||
half3 _SssTransmissionAbsorption;
|
||||
|
||||
/// Per-channel RGB gamma weights for colored AO.
|
||||
/// Expects a vector of non-zero values.
|
||||
half3 _SssColorBleedAoWeights;
|
||||
|
||||
/// Weight of the subsurface effect.
|
||||
/// Expects linear-space values in the range [0,1].
|
||||
half _TransWeight;
|
||||
#else
|
||||
/// Pre-Integrated scattering LUT.
|
||||
sampler2D _DeferredSkinLut;
|
||||
|
||||
/// X=Scattering Weight, Y=1/Mask Cutoff, Z=Blur Weight.
|
||||
/// Expects a vector of non-zero values.
|
||||
half3 _DeferredSkinParams;
|
||||
|
||||
/// Per-channel weights for thickness-based subsurface color absorption.
|
||||
/// LUT Bias in alpha.
|
||||
half4 _DeferredSkinTransmissionAbsorption;
|
||||
|
||||
/// Per-channel RGB gamma weights for colored AO. LUT Scale in alpha.
|
||||
/// Expects a vector of non-zero values.
|
||||
half4 _DeferredSkinColorBleedAoWeights;
|
||||
#endif
|
||||
|
||||
/// The current culling mode for transmission shadows.
|
||||
float _ShadowCullMode;
|
||||
|
||||
#ifdef A_FORWARD_ONLY_SHADER
|
||||
/// Shadow influence on the subsurface effect.
|
||||
/// Expects values in the range [0,1].
|
||||
half _TransShadowWeight;
|
||||
|
||||
/// Amount that the subsurface is distorted by surface normals.
|
||||
/// Expects values in the range [0,1].
|
||||
half _TransDistortion;
|
||||
|
||||
/// Falloff of the subsurface effect.
|
||||
/// Expects values in the range [1,n).
|
||||
half _TransPower;
|
||||
#else
|
||||
/// X=Linear Weight, Y=Falloff, Z=Bump Distortion, W=Shadow Weight.
|
||||
/// Expects a vector of non-zero values.
|
||||
half4 _DeferredTransmissionParams;
|
||||
#endif
|
||||
|
||||
/// Abstract declaration for user-defined pre-lighting callback.
|
||||
void aPreLighting(inout ASurface s);
|
||||
|
||||
/// Abstract declaration for user-defined direct lighting callback.
|
||||
half3 aDirectLighting(ADirect d, ASurface s);
|
||||
|
||||
/// Abstract declaration for user-defined indirect lighting callback.
|
||||
half3 aIndirectLighting(AIndirect i, ASurface s);
|
||||
|
||||
/// Indirect lighting data constructor.
|
||||
AIndirect aNewIndirect();
|
||||
|
||||
/// Direct lighting data constructor.
|
||||
ADirect aNewDirect();
|
||||
|
||||
/// Applies light cookie to description.
|
||||
/// @param[in,out] d Direct lighting data.
|
||||
/// @param[in] cookie Cookie map sample.
|
||||
void aLightCookie(inout ADirect d, half4 cookie);
|
||||
|
||||
/// Light range limit falloff.
|
||||
/// @param[in,out] d Direct lighting data.
|
||||
/// @param[in] range Light volume radius.
|
||||
void aSetLightRangeLimit(inout ADirect d, half range);
|
||||
|
||||
/// Populates light with brdf dot products, except N.L.
|
||||
/// @param[in,out] d Direct lighting data.
|
||||
/// @param[in] s Material surface data.
|
||||
void aUpdateLightingInputs(inout ADirect d, ASurface s);
|
||||
|
||||
/// Populates specular lighting data for an area light.
|
||||
/// @param[in,out] d Direct lighting data.
|
||||
/// @param[in] s Material surface data.
|
||||
/// @param[in] radius Area light radius.
|
||||
void aSetAreaSpecularInputs(inout ADirect d, ASurface s, half radius);
|
||||
|
||||
/// Populates material lighting data for an area light.
|
||||
/// @param[in,out] d Direct lighting data.
|
||||
/// @param[in] s Material surface data.
|
||||
/// @param[in] radius Area light radius.
|
||||
/// @return One over area diffuse light vector length.
|
||||
half aSetAreaLightingInputs(inout ADirect d, ASurface s, half radius);
|
||||
|
||||
/// Populates data for a directional light.
|
||||
/// @param[in,out] d Direct lighting data.
|
||||
/// @param[in] s Material surface data.
|
||||
void aDirectionalLight(inout ADirect d, ASurface s);
|
||||
|
||||
/// Populates data for a directional light.
|
||||
/// @param[in,out] d Direct lighting data.
|
||||
/// @param[in] s Material surface data.
|
||||
/// @param[in] direction Light normalized direction.
|
||||
/// @param[in] radius Disc light radius.
|
||||
void aDirectionalDiscLight(inout ADirect d, ASurface s, half3 direction, half radius);
|
||||
|
||||
/// Populates data for a sphere area light.
|
||||
/// @param[in,out] d Direct lighting data.
|
||||
/// @param[in] s Material surface data.
|
||||
/// @param[in] L Vector to light center.
|
||||
/// @param[in] radius Sphere light radius.
|
||||
void aSphereLight(inout ADirect d, ASurface s, float3 L, half radius);
|
||||
|
||||
/// Populates data for a sphere area light.
|
||||
/// @param[in,out] d Direct lighting data.
|
||||
/// @param[in] s Material surface data.
|
||||
/// @param[in] L Vector to light center.
|
||||
/// @param[in] axis Tube light normalized axis direction.
|
||||
/// @param[in] radius Tube light radius.
|
||||
/// @param[in] halfLength Half the length of the tube light.
|
||||
void aTubeLight(inout ADirect d, ASurface s, float3 L, half3 axis, half radius, half halfLength);
|
||||
|
||||
/// Populates data for an area light.
|
||||
/// @param[in,out] d Direct lighting data.
|
||||
/// @param[in] s Material surface data.
|
||||
/// @param[in] color Light color, size weight in alpha. +/- sign.
|
||||
/// @param[in] axis Tube light normalized axis direction.
|
||||
/// @param[in] L Vector to light center.
|
||||
/// @param[in] range Light bounding volume range.
|
||||
void aAreaLight(inout ADirect d, ASurface s, half4 color, half3 axis, float3 L, half range);
|
||||
|
||||
/// Surface data constructor.
|
||||
ASurface aNewSurface();
|
||||
|
||||
/// Sets the feature mask by using a gradient input mask.
|
||||
/// @param[in,out] s Material surface data.
|
||||
/// @param[in] mask Gradient where effect goes from black to white.
|
||||
/// @param[in] weight Weight of the effect.
|
||||
/// @param[in] cutoff Value below which the gradient becomes a mask.
|
||||
/// @param[in] blendRange Range of smooth blend above cutoff.
|
||||
/// @param[in] vertexTint Weight of vertex color alpha cutoff override.
|
||||
void aBlendRangeMask(inout ASurface s, half mask, half weight, half cutoff, half blendRange, half vertexTint);
|
||||
|
||||
/// Transforms a normal from tangent-space to world-space.
|
||||
half3 aTangentToWorld(ASurface s, half3 normalTangent);
|
||||
|
||||
/// Transforms a normal from world-space to tangent-space.
|
||||
half3 aWorldToTangent(ASurface s, half3 normalWorld);
|
||||
|
||||
/// Calculates and sets normal and view-dependent data.
|
||||
void aUpdateViewData(inout ASurface s);
|
||||
|
||||
/// Update values dependent on tangent-space normal.
|
||||
void aUpdateNormalTangent(inout ASurface s);
|
||||
|
||||
/// Update values dependent on world-space normal.
|
||||
void aUpdateNormalWorld(inout ASurface s);
|
||||
|
||||
/// Update values dependent on subsurface.
|
||||
void aUpdateSubsurface(inout ASurface s);
|
||||
|
||||
/// Update values dependent on subsurface color.
|
||||
void aUpdateSubsurfaceColor(inout ASurface s);
|
||||
|
||||
/// Calculates the fresnel at incidence zero from a normalized specularity.
|
||||
/// @param specularity Normalized specularity [0,1].
|
||||
/// @return F0 [0,0.08].
|
||||
half3 aSpecularityToF0(half specularity);
|
||||
|
||||
/// Convert linear roughness to Beckmann roughness.
|
||||
/// @param roughness Linear roughness [0,1].
|
||||
/// @return Beckmann Roughness.
|
||||
half aLinearToBeckmannRoughness(half roughness);
|
||||
|
||||
/// Blend weight portion of Schlick fresnel equation.
|
||||
/// @param w Clamped dot product of two normalized vectors.
|
||||
/// @return Fresnel blend weight.
|
||||
half aFresnel(half w);
|
||||
|
||||
/// Switches off specular lighting per-pixel where surface f0 is black.
|
||||
half3 aSpecularLightingToggle(ASurface s, half3 specular);
|
||||
|
||||
/// Calculates specular occlusion.
|
||||
/// @param ao Linear ambient occlusion.
|
||||
/// @param NdotV Normal and eye vector dot product [0,1].
|
||||
/// @return Specular occlusion.
|
||||
half aSpecularOcclusion(half ao, half NdotV);
|
||||
|
||||
/// Pre-calculate material data shared between direct & indirect lighting.
|
||||
void aStandardPreLighting(inout ASurface s);
|
||||
|
||||
/// Calculate direct illumination from a light and a surface.
|
||||
/// @param d Direct lighting data.
|
||||
/// @param s Material surface data.
|
||||
/// @return Direct illumination.
|
||||
half3 aStandardDirectLighting(ADirect d, ASurface s);
|
||||
|
||||
/// Calculate indirect illumination from a light and a surface.
|
||||
/// @param i Indirect lighting data.
|
||||
/// @param s Material surface data.
|
||||
/// @return Indirect illumination.
|
||||
half3 aStandardIndirectLighting(AIndirect i, ASurface s);
|
||||
|
||||
#endif // ALLOY_SHADERS_FRAMEWORK_LIGHTING_CGINC
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 315a77a44673cd540ad1ecad6d2f47be
|
||||
timeCreated: 1437938893
|
||||
licenseType: Pro
|
||||
ShaderImporter:
|
||||
defaultTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,761 @@
|
||||
// Alloy Physical Shader Framework
|
||||
// Copyright 2013-2017 RUST LLC.
|
||||
// http://www.alloy.rustltd.com/
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
/// @file LightingImpl.cginc
|
||||
/// @brief Lighting method implementations to allow disabling of features.
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef ALLOY_SHADERS_FRAMEWORK_LIGHTING_IMPL_CGINC
|
||||
#define ALLOY_SHADERS_FRAMEWORK_LIGHTING_IMPL_CGINC
|
||||
|
||||
// Headers both for this file, and for all Definition and Feature modules.
|
||||
#include "Assets/Alloy/Shaders/Config.cginc"
|
||||
#include "Assets/Alloy/Shaders/Framework/Lighting.cginc"
|
||||
#include "Assets/Alloy/Shaders/Framework/Utility.cginc"
|
||||
|
||||
#include "HLSLSupport.cginc"
|
||||
#include "UnityCG.cginc"
|
||||
#include "UnityShaderVariables.cginc"
|
||||
|
||||
#if !A_USE_UNITY_ATTENUATION || defined(USING_DIRECTIONAL_LIGHT)
|
||||
#define A_UNITY_ATTENUATION(d, tex, lightCoord, scale)
|
||||
#else
|
||||
#define A_UNITY_ATTENUATION(d, tex, lightCoord, scale) d.color *= tex2D(tex, (dot(lightCoord, lightCoord) * scale).rr).UNITY_ATTEN_CHANNEL;
|
||||
#endif
|
||||
|
||||
#if !defined(A_REFLECTION_PROBES_ON) && (!defined(A_GBUFFER_PASS) || !UNITY_ENABLE_REFLECTION_BUFFERS)
|
||||
#define A_REFLECTION_PROBES_ON
|
||||
#endif
|
||||
|
||||
// Lighting required vertex data flags.
|
||||
#ifndef A_UNLIT_MODE
|
||||
#ifdef A_DIRECT_LIGHTING_PASS
|
||||
#define A_DIRECT_ON
|
||||
#endif
|
||||
|
||||
#ifdef A_INDIRECT_LIGHTING_PASS
|
||||
#define A_INDIRECT_ON
|
||||
#endif
|
||||
|
||||
#if defined(A_DIRECT_ON) || defined(A_INDIRECT_ON)
|
||||
#define A_LIGHTING_ON
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef A_LIGHTING_ON
|
||||
#if !defined(A_NORMAL_WORLD_ON) && defined(A_GBUFFER_PASS)
|
||||
#define A_NORMAL_WORLD_ON
|
||||
#endif
|
||||
#else
|
||||
#ifndef A_NORMAL_WORLD_ON
|
||||
#define A_NORMAL_WORLD_ON
|
||||
#endif
|
||||
|
||||
#ifndef A_VIEW_DIR_WORLD_ON
|
||||
#define A_VIEW_DIR_WORLD_ON
|
||||
#endif
|
||||
|
||||
#ifndef A_POSITION_WORLD_ON
|
||||
#define A_POSITION_WORLD_ON
|
||||
#endif
|
||||
|
||||
#if !defined(A_REFLECTION_VECTOR_WORLD_ON) && (defined(A_DIRECT_ON) || defined(A_REFLECTION_PROBES_ON))
|
||||
#define A_REFLECTION_VECTOR_WORLD_ON
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(A_TANGENT_TO_WORLD_ON) && defined(A_NORMAL_MAPPED_PASS) && (defined(A_VIEW_DIR_TANGENT_ON) || defined(A_NORMAL_MAPPING_ON))
|
||||
#define A_TANGENT_TO_WORLD_ON
|
||||
#endif
|
||||
|
||||
#ifndef A_SCATTERING_ON
|
||||
#define A_SKIN_SUBSURFACE_WEIGHT 1.0h
|
||||
#else
|
||||
#define A_SKIN_SUBSURFACE_WEIGHT _TransWeight
|
||||
|
||||
#ifdef A_FORWARD_ONLY_SHADER
|
||||
#define A_SCATTERING_LUT _SssBrdfTex
|
||||
#define A_SCATTERING_WEIGHT _SssWeight
|
||||
#define A_SCATTERING_INV_MASK_CUTOFF 1.0h / _SssMaskCutoff
|
||||
#define A_SCATTERING_BIAS _SssBias
|
||||
#define A_SCATTERING_SCALE _SssScale
|
||||
#define A_SCATTERING_NORMAL_BLUR _SssBumpBlur
|
||||
#define A_SCATTERING_ABSORPTION _SssTransmissionAbsorption
|
||||
#define A_SCATTERING_AO_COLOR_BLEED _SssColorBleedAoWeights
|
||||
#else
|
||||
#define A_SCATTERING_LUT _DeferredSkinLut
|
||||
#define A_SCATTERING_WEIGHT _DeferredSkinParams.x
|
||||
#define A_SCATTERING_INV_MASK_CUTOFF _DeferredSkinParams.y
|
||||
#define A_SCATTERING_BIAS _DeferredSkinTransmissionAbsorption.w
|
||||
#define A_SCATTERING_SCALE _DeferredSkinColorBleedAoWeights.w
|
||||
#define A_SCATTERING_NORMAL_BLUR _DeferredSkinParams.z
|
||||
#define A_SCATTERING_ABSORPTION _DeferredSkinTransmissionAbsorption.xyz
|
||||
#define A_SCATTERING_AO_COLOR_BLEED _DeferredSkinColorBleedAoWeights.xyz
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef A_SUBSURFACE_ON
|
||||
#ifdef A_FORWARD_ONLY_SHADER
|
||||
#define A_SUBSURFACE_WEIGHT A_SKIN_SUBSURFACE_WEIGHT
|
||||
#define A_SUBSURFACE_FALLOFF _TransPower
|
||||
#define A_SUBSURFACE_DISTORTION _TransDistortion
|
||||
#define A_SUBSURFACE_SHADOW _TransShadowWeight
|
||||
#else
|
||||
#define A_SUBSURFACE_WEIGHT _DeferredTransmissionParams.x
|
||||
#define A_SUBSURFACE_FALLOFF _DeferredTransmissionParams.y
|
||||
#define A_SUBSURFACE_DISTORTION _DeferredTransmissionParams.z
|
||||
#define A_SUBSURFACE_SHADOW _DeferredTransmissionParams.w
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !A_USE_DEFERRED_MATERIAL_TYPE_BRANCHING || !defined(A_DEFERRED_PASS)
|
||||
#define A_DEFERRED_BRANCH(CONDITION)
|
||||
#else
|
||||
#define A_DEFERRED_BRANCH(CONDITION) \
|
||||
UNITY_BRANCH \
|
||||
if (CONDITION)
|
||||
#endif
|
||||
|
||||
AIndirect aNewIndirect() {
|
||||
AIndirect i;
|
||||
|
||||
UNITY_INITIALIZE_OUTPUT(AIndirect, i);
|
||||
i.diffuse = 0.0h;
|
||||
i.specular = 0.0h;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
ADirect aNewDirect()
|
||||
{
|
||||
ADirect d;
|
||||
|
||||
UNITY_INITIALIZE_OUTPUT(ADirect, d);
|
||||
d.color = 0.0h;
|
||||
d.shadow = 1.0h;
|
||||
d.specularIntensity = 1.0h;
|
||||
d.direction = A_AXIS_Y;
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
void aLightCookie(
|
||||
inout ADirect d,
|
||||
half4 cookie)
|
||||
{
|
||||
#if defined(UNITY_PASS_FORWARDBASE) || A_USE_UNITY_LIGHT_COOKIES
|
||||
d.color *= cookie.a;
|
||||
#else
|
||||
d.color *= cookie.rgb * cookie.a;
|
||||
#endif
|
||||
}
|
||||
|
||||
void aSetLightRangeLimit(
|
||||
inout ADirect d,
|
||||
half range)
|
||||
{
|
||||
#if !A_USE_UNITY_ATTENUATION
|
||||
// Light Range Limit Falloff.
|
||||
// cf http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf p12-13
|
||||
half ratio = 1.0h / (range * d.centerDistInverse);
|
||||
half ratio2 = ratio * ratio;
|
||||
half num = saturate(1.0h - (ratio2 * ratio2));
|
||||
|
||||
d.color *= num * num;
|
||||
#endif
|
||||
}
|
||||
|
||||
void aUpdateLightingInputs(
|
||||
inout ADirect d,
|
||||
ASurface s)
|
||||
{
|
||||
d.halfAngleWorld = normalize(d.direction + s.viewDirWorld);
|
||||
d.LdotH = aDotClamp(d.direction, d.halfAngleWorld);
|
||||
d.NdotH = aDotClamp(s.normalWorld, d.halfAngleWorld);
|
||||
}
|
||||
|
||||
void aSetAreaSpecularInputs(
|
||||
inout ADirect d,
|
||||
ASurface s,
|
||||
half radius)
|
||||
{
|
||||
// Representative Point Area Lights.
|
||||
// cf http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf p14-16
|
||||
#ifdef A_AREA_SPECULAR_OFF
|
||||
d.direction = d.Ldiff;
|
||||
#else
|
||||
float3 R = s.reflectionVectorWorld;
|
||||
float3 centerToRay = dot(d.Lspec, R) * R - d.Lspec;
|
||||
float3 closestPoint = d.Lspec + centerToRay * saturate(radius * rsqrt(dot(centerToRay, centerToRay)));
|
||||
half LspecLengthInverse = rsqrt(dot(closestPoint, closestPoint));
|
||||
half a = s.beckmannRoughness;
|
||||
half normalizationFactor = a / saturate(a + (radius * 0.5h * LspecLengthInverse));
|
||||
|
||||
d.direction = closestPoint * LspecLengthInverse;
|
||||
d.specularIntensity = normalizationFactor * normalizationFactor;
|
||||
#endif
|
||||
|
||||
aUpdateLightingInputs(d, s);
|
||||
}
|
||||
|
||||
half aSetAreaLightingInputs(
|
||||
inout ADirect d,
|
||||
ASurface s,
|
||||
half radius)
|
||||
{
|
||||
// Specular.
|
||||
aSetAreaSpecularInputs(d, s, radius);
|
||||
|
||||
// Diffuse.
|
||||
// Set diffuse light direction last to fix transmission & hair.
|
||||
half LdiffLengthSquared = dot(d.Ldiff, d.Ldiff);
|
||||
half LdiffLengthInverse = rsqrt(LdiffLengthSquared);
|
||||
|
||||
d.direction = d.Ldiff * LdiffLengthInverse;
|
||||
d.NdotLm = dot(s.normalWorld, d.direction);
|
||||
d.NdotL = saturate(d.NdotLm);
|
||||
|
||||
#if !A_USE_UNITY_ATTENUATION
|
||||
d.color /= (LdiffLengthSquared + 1.0h); // Attenuation.
|
||||
#endif
|
||||
|
||||
return LdiffLengthInverse;
|
||||
}
|
||||
|
||||
void aDirectionalLight(
|
||||
inout ADirect d,
|
||||
ASurface s)
|
||||
{
|
||||
d.NdotLm = dot(s.normalWorld, d.direction);
|
||||
d.NdotL = saturate(d.NdotLm);
|
||||
aUpdateLightingInputs(d, s);
|
||||
}
|
||||
|
||||
void aDirectionalDiscLight(
|
||||
inout ADirect d,
|
||||
ASurface s,
|
||||
half3 direction,
|
||||
half radius)
|
||||
{
|
||||
d.Ldiff = direction;
|
||||
d.Lspec = direction;
|
||||
|
||||
// Specular.
|
||||
aSetAreaSpecularInputs(d, s, radius);
|
||||
|
||||
// Diffuse.
|
||||
// Set diffuse light direction last to fix transmission & hair.
|
||||
d.direction = d.Ldiff;
|
||||
d.NdotLm = dot(s.normalWorld, d.direction);
|
||||
d.NdotL = saturate(d.NdotLm);
|
||||
}
|
||||
|
||||
void aSphereLight(
|
||||
inout ADirect d,
|
||||
ASurface s,
|
||||
float3 L,
|
||||
half radius)
|
||||
{
|
||||
// Sphere Area Light.
|
||||
// cf http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf p15-16
|
||||
d.Ldiff = L;
|
||||
d.Lspec = L;
|
||||
d.centerDistInverse = aSetAreaLightingInputs(d, s, radius);
|
||||
}
|
||||
|
||||
void aTubeLight(
|
||||
inout ADirect d,
|
||||
ASurface s,
|
||||
float3 L,
|
||||
half3 axis,
|
||||
half radius,
|
||||
half halfLength)
|
||||
{
|
||||
// Tube Area Light.
|
||||
// cf http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf p16-18
|
||||
float3 R = s.reflectionVectorWorld;
|
||||
float3 tubeLightDir = axis * halfLength;
|
||||
float3 L0 = L + tubeLightDir;
|
||||
float3 L1 = L - tubeLightDir;
|
||||
float3 Ld = tubeLightDir * -2.0f;
|
||||
float RdotL0 = dot(R, L0);
|
||||
float RdotLd = dot(R, Ld);
|
||||
float L0dotLd = dot(L0, Ld);
|
||||
float t = (RdotL0 * RdotLd - L0dotLd) / (dot(Ld, Ld) - RdotLd * RdotLd);
|
||||
|
||||
// Modified diffuse term for true tube diffuse lighting.
|
||||
d.Ldiff = L - clamp(dot(L, axis), -halfLength, halfLength) * axis;
|
||||
d.Lspec = L0 + Ld * saturate(t);
|
||||
d.centerDistInverse = rsqrt(dot(L, L));
|
||||
|
||||
// Attentuation normalization.
|
||||
d.color /= 1.0h + (0.25h * halfLength * aSetAreaLightingInputs(d, s, radius));
|
||||
}
|
||||
|
||||
void aAreaLight(
|
||||
inout ADirect d,
|
||||
ASurface s,
|
||||
half4 color,
|
||||
half3 axis,
|
||||
float3 L,
|
||||
half range)
|
||||
{
|
||||
// Packed float light configuration.
|
||||
// +/- llll.rrrr: l=length, r=radius, and sign as specular toggle.
|
||||
// Radius externally clamped to .999 max to simplify math.
|
||||
half lightParams = abs(color.a);
|
||||
|
||||
#ifdef USING_DIRECTIONAL_LIGHT
|
||||
// 0.1 needed to make material inspector look okay.
|
||||
aDirectionalDiscLight(d, s, L, lightParams * 0.1h);
|
||||
#else
|
||||
#if !defined(SPOT) && A_USE_TUBE_LIGHTS
|
||||
// Enable when length is non-zero, and specular is enabled.
|
||||
UNITY_BRANCH
|
||||
if (color.a >= 1) {
|
||||
half dec = frac(lightParams);
|
||||
half radius = dec * range;
|
||||
half halfLength = (lightParams - dec) * 0.001f * range;
|
||||
|
||||
aTubeLight(d, s, L, axis, radius, halfLength);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
aSphereLight(d, s, L, lightParams * range);
|
||||
}
|
||||
|
||||
aSetLightRangeLimit(d, range);
|
||||
#endif
|
||||
|
||||
// Specular highlight toggle.
|
||||
d.specularIntensity = color.a > 0.0h ? d.specularIntensity : 0.0h;
|
||||
}
|
||||
|
||||
ASurface aNewSurface() {
|
||||
ASurface s;
|
||||
|
||||
UNITY_INITIALIZE_OUTPUT(ASurface, s);
|
||||
s.vertexNormalWorld = A_FLAT_NORMAL;
|
||||
s.normalWorld = A_FLAT_NORMAL;
|
||||
s.viewDirWorld = A_AXIS_X;
|
||||
s.viewDirTangent = A_AXIS_X;
|
||||
s.reflectionVectorWorld = A_AXIS_X;
|
||||
s.tangentToWorld = 0.0h;
|
||||
s.normalTangent = A_FLAT_NORMAL;
|
||||
s.blurredNormalTangent = A_FLAT_NORMAL;
|
||||
s.facingSign = 1.0h;
|
||||
s.fogCoord = 0.0f;
|
||||
s.NdotV = 0.0h;
|
||||
s.FV = 0.0h;
|
||||
s.materialType = 1.0h;
|
||||
s.mask = 1.0h;
|
||||
|
||||
s.baseColor = 0.0h;
|
||||
s.opacity = 1.0h;
|
||||
s.metallic = 0.0h;
|
||||
s.ambientOcclusion = 1.0h;
|
||||
s.specularity = 0.5h;
|
||||
s.specularTint = 0.0h;
|
||||
s.roughness = 0.0h;
|
||||
s.emissiveColor = 0.0h;
|
||||
s.subsurfaceColor = 0.0h;
|
||||
s.subsurface = 0.0h;
|
||||
s.clearCoat = 0.0h;
|
||||
s.clearCoatRoughness = 0.0h;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
void aBlendRangeMask(
|
||||
inout ASurface s,
|
||||
half mask,
|
||||
half weight,
|
||||
half cutoff,
|
||||
half blendRange,
|
||||
half vertexTint)
|
||||
{
|
||||
cutoff = lerp(cutoff, 1.0h, s.vertexColor.a * vertexTint);
|
||||
mask = 1.0h - saturate((mask - cutoff) / blendRange);
|
||||
s.mask *= weight * mask;
|
||||
}
|
||||
|
||||
half3 aTangentToWorld(
|
||||
ASurface s,
|
||||
half3 normalTangent)
|
||||
{
|
||||
#ifndef A_TANGENT_TO_WORLD_ON
|
||||
return s.vertexNormalWorld;
|
||||
#else
|
||||
return normalize(mul(normalTangent, s.tangentToWorld));
|
||||
#endif
|
||||
}
|
||||
|
||||
half3 aWorldToTangent(
|
||||
ASurface s,
|
||||
half3 normalWorld)
|
||||
{
|
||||
#ifndef A_TANGENT_TO_WORLD_ON
|
||||
return A_FLAT_NORMAL;
|
||||
#else
|
||||
return normalize(mul(s.tangentToWorld, normalWorld));
|
||||
#endif
|
||||
}
|
||||
|
||||
void aUpdateViewData(
|
||||
inout ASurface s)
|
||||
{
|
||||
#if defined(A_NORMAL_WORLD_ON) && defined(A_VIEW_DIR_WORLD_ON)
|
||||
// Area lights need this to be per-pixel.
|
||||
#ifdef A_REFLECTION_VECTOR_WORLD_ON
|
||||
s.reflectionVectorWorld = reflect(-s.viewDirWorld, s.normalWorld);
|
||||
#endif
|
||||
|
||||
// Skip re-calculating world normals in some cases.
|
||||
#ifndef A_VIEW_DIR_TANGENT_ON
|
||||
s.NdotV = aDotClamp(s.normalWorld, s.viewDirWorld);
|
||||
#else
|
||||
s.NdotV = aDotClamp(s.normalTangent, s.viewDirTangent);
|
||||
#endif
|
||||
|
||||
s.FV = aFresnel(s.NdotV);
|
||||
#endif
|
||||
}
|
||||
|
||||
void aUpdateNormalTangent(
|
||||
inout ASurface s)
|
||||
{
|
||||
#ifndef A_TANGENT_TO_WORLD_ON
|
||||
s.normalTangent = A_FLAT_NORMAL;
|
||||
#else
|
||||
s.normalWorld = aTangentToWorld(s, s.normalTangent);
|
||||
s.ambientNormalWorld = s.normalWorld;
|
||||
aUpdateViewData(s);
|
||||
#endif
|
||||
}
|
||||
|
||||
void aUpdateNormalWorld(
|
||||
inout ASurface s)
|
||||
{
|
||||
#ifndef A_TANGENT_TO_WORLD_ON
|
||||
s.normalWorld = s.vertexNormalWorld;
|
||||
#else
|
||||
s.normalTangent = aWorldToTangent(s, s.normalWorld);
|
||||
s.ambientNormalWorld = s.normalWorld;
|
||||
aUpdateViewData(s);
|
||||
#endif
|
||||
}
|
||||
|
||||
void aUpdateSubsurface(
|
||||
inout ASurface s)
|
||||
{
|
||||
s.subsurfaceColor = aGammaToLinear(s.subsurface).rrr;
|
||||
}
|
||||
|
||||
void aUpdateSubsurfaceColor(
|
||||
inout ASurface s)
|
||||
{
|
||||
s.subsurface = LinearToGammaSpace(s.subsurfaceColor).g;
|
||||
}
|
||||
|
||||
half3 aSpecularityToF0(
|
||||
half specularity)
|
||||
{
|
||||
return (specularity * A_MAX_DIELECTRIC_F0).rrr;
|
||||
}
|
||||
|
||||
half aLinearToBeckmannRoughness(
|
||||
half roughness)
|
||||
{
|
||||
// Remap roughness to prevent specular artifacts.
|
||||
roughness = lerp(A_MIN_AREA_ROUGHNESS, 1.0h, roughness);
|
||||
return roughness * roughness;
|
||||
}
|
||||
|
||||
half aFresnel(
|
||||
half w)
|
||||
{
|
||||
// Sebastien Lagarde's spherical gaussian approximation of Schlick fresnel.
|
||||
// cf http://seblagarde.wordpress.com/2011/08/17/hello-world/
|
||||
return exp2((-5.55473h * w - 6.98316h) * w);
|
||||
}
|
||||
|
||||
half3 aSpecularLightingToggle(
|
||||
ASurface s,
|
||||
half3 specular)
|
||||
{
|
||||
#if !A_USE_BLACK_SPECULAR_COLOR_TOGGLE
|
||||
return specular;
|
||||
#else
|
||||
return any(s.f0) ? specular : A_BLACK;
|
||||
#endif
|
||||
}
|
||||
|
||||
half aSpecularOcclusion(
|
||||
half ao,
|
||||
half NdotV)
|
||||
{
|
||||
// Yoshiharu Gotanda's specular occlusion approximation:
|
||||
// cf http://research.tri-ace.com/Data/cedec2011_RealtimePBR_Implementation_e.pptx pg59
|
||||
half d = NdotV + ao;
|
||||
return saturate((d * d) - 1.0h + ao);
|
||||
}
|
||||
|
||||
void aStandardPreLighting(
|
||||
inout ASurface s)
|
||||
{
|
||||
// In Forward mode, set material type.
|
||||
#ifndef A_DEFERRED_PASS
|
||||
s.baseColor = saturate(s.baseColor);
|
||||
s.albedo = s.baseColor;
|
||||
s.f0 = aSpecularityToF0(s.specularity);
|
||||
|
||||
#ifndef A_SPECULAR_TINT_ON
|
||||
s.specularTint = 0.0h;
|
||||
#else
|
||||
s.f0 *= aLerpWhiteTo(aChromaticity(s.baseColor), s.specularTint);
|
||||
#endif
|
||||
|
||||
#ifndef A_METALLIC_ON
|
||||
s.metallic = 0.0h;
|
||||
#else
|
||||
half metallicInv = 1.0h - s.metallic;
|
||||
|
||||
s.albedo *= metallicInv; // Affects transmission through albedo.
|
||||
s.f0 = lerp(s.f0, s.baseColor, s.metallic);
|
||||
|
||||
#ifdef _ALPHAPREMULTIPLY_ON
|
||||
// Interpolate from a translucent dielectric to an opaque metal.
|
||||
s.opacity = s.metallic + metallicInv * s.opacity;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef A_CLEARCOAT_ON
|
||||
s.clearCoat = 0.0h;
|
||||
s.clearCoatRoughness = 0.0h;
|
||||
#else
|
||||
// f0 of 0.04 gives us a polyurethane-like coating.
|
||||
half clearCoat = s.clearCoat * lerp(0.04h, 1.0h, s.FV);
|
||||
|
||||
s.albedo *= aLerpOneTo(0.0h, clearCoat);
|
||||
s.f0 = lerp(s.f0, A_WHITE, clearCoat);
|
||||
s.roughness = lerp(s.roughness, s.clearCoatRoughness, clearCoat);
|
||||
#endif
|
||||
|
||||
#ifdef _ALPHAPREMULTIPLY_ON
|
||||
// Premultiply opacity with albedo for translucent shaders.
|
||||
s.albedo *= s.opacity;
|
||||
#endif
|
||||
|
||||
s.beckmannRoughness = aLinearToBeckmannRoughness(s.roughness);
|
||||
|
||||
#ifndef A_AMBIENT_OCCLUSION_ON
|
||||
s.ambientOcclusion = 1.0h;
|
||||
s.specularOcclusion = 1.0h;
|
||||
#else
|
||||
s.specularOcclusion = aSpecularOcclusion(s.ambientOcclusion, s.NdotV);
|
||||
#endif
|
||||
|
||||
#if defined(A_SCATTERING_ON)
|
||||
s.materialType = A_MATERIAL_TYPE_SUBSURFACE_SCATTERING;
|
||||
s._subsurfaceShadowWeight = 0.0h;
|
||||
s._skinScatteringMask = 1.0h;
|
||||
s.ambientNormalWorld = aTangentToWorld(s, s.blurredNormalTangent);
|
||||
#elif defined(A_SUBSURFACE_ON)
|
||||
#ifdef A_TWO_SIDED_SHADER
|
||||
s.materialType = A_MATERIAL_TYPE_SHADOWED_SUBSURFACE;
|
||||
s._subsurfaceShadowWeight = A_SUBSURFACE_SHADOW;
|
||||
#else
|
||||
s.materialType = _ShadowCullMode == A_CULL_MODE_FRONT ? A_MATERIAL_TYPE_SHADOWED_SUBSURFACE : A_MATERIAL_TYPE_UNSHADOWED_SUBSURFACE;
|
||||
s._subsurfaceShadowWeight = _ShadowCullMode == A_CULL_MODE_FRONT ? A_SUBSURFACE_SHADOW : 0.0h;
|
||||
#endif
|
||||
#else
|
||||
s.materialType = A_MATERIAL_TYPE_OPAQUE;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(A_SCATTERING_ON) || defined(A_SUBSURFACE_ON)
|
||||
A_DEFERRED_BRANCH(s.materialType != A_MATERIAL_TYPE_OPAQUE)
|
||||
{
|
||||
// In Deferred mode, determine material type and sample extra G-buffer data.
|
||||
#if defined(A_DEFERRED_PASS)
|
||||
half4 buffer = tex2Dlod(_DeferredPlusBuffer, float4(s.screenUv, 0.0f, 0.0f));
|
||||
|
||||
s.subsurface = buffer.a;
|
||||
s._subsurfaceShadowWeight = s.materialType == A_MATERIAL_TYPE_SHADOWED_SUBSURFACE ? A_SUBSURFACE_SHADOW : 0.0h;
|
||||
|
||||
#if defined(A_SCATTERING_ON)
|
||||
s._skinScatteringMask = s.materialType == A_MATERIAL_TYPE_SUBSURFACE_SCATTERING ? 1.0h : 0.0h;
|
||||
s.ambientNormalWorld = normalize(buffer.xyz * 2.0h - 1.0h);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Subsurface color calculation.
|
||||
#ifdef A_SUBSURFACE_ON
|
||||
#ifdef A_FORWARD_ONLY_SHADER
|
||||
s.subsurfaceColor *= s.albedo;
|
||||
#else
|
||||
s.subsurfaceColor = s.albedo * aGammaToLinear(s.subsurface);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Scattering input data.
|
||||
#ifdef A_SCATTERING_ON
|
||||
A_DEFERRED_BRANCH(s.materialType == A_MATERIAL_TYPE_SUBSURFACE_SCATTERING)
|
||||
{
|
||||
// Scattering mask.
|
||||
s._skinScatteringMask *= A_SCATTERING_WEIGHT * saturate(A_SCATTERING_INV_MASK_CUTOFF * s.subsurface);
|
||||
s._skinScattering = saturate(s.subsurface * A_SCATTERING_SCALE + A_SCATTERING_BIAS);
|
||||
|
||||
// Skin subsurface depth absorption tint.
|
||||
// cf http://www.crytek.com/download/2014_03_25_CRYENGINE_GDC_Schultz.pdf pg 35
|
||||
half3 absorption = exp((1.0h - s.subsurface) * A_SCATTERING_ABSORPTION);
|
||||
|
||||
// Albedo scale for absorption assumes ~0.5 luminance for Caucasian skin.
|
||||
absorption *= saturate(s.albedo * unity_ColorSpaceDouble.rgb);
|
||||
s.subsurfaceColor = lerp(s.subsurfaceColor, absorption, s._skinScatteringMask);
|
||||
|
||||
// Blurred normals for indirect diffuse and direct scattering.
|
||||
s.ambientNormalWorld = normalize(lerp(s.normalWorld, s.ambientNormalWorld, A_SCATTERING_NORMAL_BLUR * s._skinScatteringMask));
|
||||
}
|
||||
#endif
|
||||
|
||||
// Subsurface color weight.
|
||||
#ifdef A_SUBSURFACE_ON
|
||||
s.subsurfaceColor *= A_SUBSURFACE_WEIGHT;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
half3 aStandardDirectLighting(
|
||||
ADirect d,
|
||||
ASurface s)
|
||||
{
|
||||
half3 illum = A_BLACK;
|
||||
half3 specular = A_BLACK;
|
||||
|
||||
#if defined(A_SCATTERING_ON) || defined(A_SUBSURFACE_ON)
|
||||
A_DEFERRED_BRANCH(s.materialType != A_MATERIAL_TYPE_OPAQUE)
|
||||
{
|
||||
#ifdef A_SUBSURFACE_ON
|
||||
// Subsurface transmission.
|
||||
// cf http://www.farfarer.com/blog/2012/09/11/translucent-shader-unity3d/
|
||||
half3 transLightDir = d.direction + s.normalWorld * A_SUBSURFACE_DISTORTION;
|
||||
half transLight = pow(aDotClamp(s.viewDirWorld, -transLightDir), A_SUBSURFACE_FALLOFF);
|
||||
half shadow = aLerpOneTo(d.shadow, s._subsurfaceShadowWeight);
|
||||
|
||||
illum += s.subsurfaceColor * (shadow * transLight);
|
||||
#endif
|
||||
|
||||
#ifdef A_SCATTERING_ON
|
||||
A_DEFERRED_BRANCH(s.materialType == A_MATERIAL_TYPE_SUBSURFACE_SCATTERING)
|
||||
{
|
||||
// Pre-Integrated Skin Shading.
|
||||
// cf http://www.farfarer.com/blog/2013/02/11/pre-integrated-skin-shader-unity-3d/
|
||||
float ndlBlur = dot(s.ambientNormalWorld, d.direction) * 0.5h + 0.5h;
|
||||
float4 sssLookupUv = float4(ndlBlur, s._skinScattering * aLuminance(d.color), 0.0f, 0.0f);
|
||||
half3 sss = (s._skinScatteringMask * d.shadow) * tex2Dlod(A_SCATTERING_LUT, sssLookupUv).rgb;
|
||||
|
||||
illum += s.albedo * sss;
|
||||
s.albedo *= 1.0h - s._skinScatteringMask;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
// Cook-Torrance microfacet model.
|
||||
// cf http://graphicrants.blogspot.com/2013/08/specular-brdf-reference.html
|
||||
half LdotH2 = d.LdotH * d.LdotH;
|
||||
|
||||
// Brent Burley diffuse BRDF.
|
||||
// cf https://disney-animation.s3.amazonaws.com/library/s2012_pbs_disney_brdf_notes_v2.pdf pg14
|
||||
half FL = aFresnel(d.NdotL);
|
||||
half Fd90 = 0.5h + (2.0h * LdotH2 * s.roughness);
|
||||
half Fd = aLerpOneTo(Fd90, FL) * aLerpOneTo(Fd90, s.FV);
|
||||
half3 diffuse = s.albedo * Fd;
|
||||
|
||||
#ifndef _SPECULARHIGHLIGHTS_OFF
|
||||
// Schlick's Fresnel approximation.
|
||||
half3 F = lerp(s.f0, A_WHITE, aFresnel(d.LdotH));
|
||||
|
||||
// John Hable's Visibility function.
|
||||
// cf http://www.filmicworlds.com/2014/04/21/optimizing-ggx-shaders-with-dotlh/
|
||||
half a2 = s.beckmannRoughness * s.beckmannRoughness;
|
||||
half k2 = a2 * 0.25h; // k = a/2; k*k = (a*a)/(2*2) = (a^2)/4.
|
||||
half invV = lerp(k2, 1.0h, LdotH2);
|
||||
|
||||
// GGX (Trowbridge-Reitz) NDF.
|
||||
// cf http://graphicrants.blogspot.com/2013/08/specular-brdf-reference.html
|
||||
half denom = aLerpOneTo(a2, d.NdotH * d.NdotH);
|
||||
half mDV = k2 / (invV * denom * denom); // k2 is GGX a^2 and microfacet 1/4.
|
||||
|
||||
specular = aSpecularLightingToggle(s, F * (mDV * s.specularOcclusion * d.specularIntensity));
|
||||
#endif
|
||||
|
||||
// Punctual lighting equation.
|
||||
// cf http://seblagarde.wordpress.com/2012/01/08/pi-or-not-to-pi-in-game-lighting-equation/
|
||||
illum += (d.shadow * d.NdotL) * (diffuse + specular);
|
||||
|
||||
return d.color * illum;
|
||||
}
|
||||
|
||||
half3 aStandardIndirectLighting(
|
||||
AIndirect i,
|
||||
ASurface s)
|
||||
{
|
||||
half3 illum = A_BLACK;
|
||||
|
||||
#if defined(A_DEFERRED_PASS) || defined(A_REFLECTION_PROBES_ON)
|
||||
// Brian Karis' modification of Dimitar Lazarov's Environment BRDF.
|
||||
// cf https://www.unrealengine.com/blog/physically-based-shading-on-mobile
|
||||
const half4 c0 = half4(-1.0h, -0.0275h, -0.572h, 0.022h);
|
||||
const half4 c1 = half4(1.0h, 0.0425h, 1.04h, -0.04h);
|
||||
half4 r = s.roughness * c0 + c1;
|
||||
half a004 = min(r.x * r.x, exp2(-9.28h * s.NdotV)) * r.x + r.y;
|
||||
half2 AB = half2(-1.04h, 1.04h) * a004 + r.zw;
|
||||
half3 specular = i.specular * (s.f0 * AB.x + AB.yyy);
|
||||
#endif
|
||||
|
||||
#ifdef A_DEFERRED_PASS
|
||||
illum = aSpecularLightingToggle(s, specular * s.specularOcclusion);
|
||||
#else
|
||||
#ifndef A_AMBIENT_OCCLUSION_ON
|
||||
half3 diffuse = s.albedo * i.diffuse;
|
||||
|
||||
#ifndef A_REFLECTION_PROBES_ON
|
||||
illum = diffuse;
|
||||
#else
|
||||
illum = diffuse + aSpecularLightingToggle(s, specular);
|
||||
#endif
|
||||
#else
|
||||
#ifndef A_SCATTERING_ON
|
||||
half ao = s.ambientOcclusion;
|
||||
#else
|
||||
// Color Bleed AO.
|
||||
// cf http://www.iryoku.com/downloads/Next-Generation-Character-Rendering-v6.pptx pg113
|
||||
half3 ao = pow(s.ambientOcclusion.rrr, A_ONE - (A_SCATTERING_AO_COLOR_BLEED * s._skinScatteringMask));
|
||||
#endif
|
||||
|
||||
// Yoshiharu Gotanda's fake interreflection for specular occlusion.
|
||||
// Modified to better account for surface f0.
|
||||
// cf http://research.tri-ace.com/Data/cedec2011_RealtimePBR_Implementation_e.pptx pg65
|
||||
half3 ambient = i.diffuse * ao;
|
||||
|
||||
#ifndef A_REFLECTION_PROBES_ON
|
||||
// Diffuse and fake interreflection only.
|
||||
illum = ambient * (s.albedo + aSpecularLightingToggle(s, s.f0 * (1.0h - s.specularOcclusion)));
|
||||
#else
|
||||
// Full equation.
|
||||
illum = ambient * s.albedo
|
||||
+ aSpecularLightingToggle(s, lerp(ambient * s.f0, specular, s.specularOcclusion));
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return illum;
|
||||
}
|
||||
|
||||
#endif // ALLOY_SHADERS_FRAMEWORK_LIGHTING_IMPL_CGINC
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 793f250168f085a4a8ff1459943a8cca
|
||||
timeCreated: 1492114566
|
||||
licenseType: Pro
|
||||
ShaderImporter:
|
||||
defaultTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,247 @@
|
||||
// Alloy Physical Shader Framework
|
||||
// Copyright 2013-2017 RUST LLC.
|
||||
// http://www.alloy.rustltd.com/
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
/// @file Particle.cginc
|
||||
/// @brief Particles uber-header.
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef ALLOY_SHADERS_FRAMEWORK_PARTICLE_CGINC
|
||||
#define ALLOY_SHADERS_FRAMEWORK_PARTICLE_CGINC
|
||||
|
||||
#include "Assets/Alloy/Shaders/Config.cginc"
|
||||
#include "Assets/Alloy/Shaders/Framework/Utility.cginc"
|
||||
|
||||
#include "HLSLSupport.cginc"
|
||||
#include "UnityCG.cginc"
|
||||
#include "UnityInstancing.cginc"
|
||||
#include "UnityLightingCommon.cginc"
|
||||
#include "UnityStandardUtils.cginc"
|
||||
#include "UnityShaderVariables.cginc"
|
||||
|
||||
struct AVertexInput {
|
||||
float4 vertex : POSITION;
|
||||
float4 color : COLOR;
|
||||
float4 texcoords : TEXCOORD0;
|
||||
#ifdef A_PARTICLE_TEXTURE_BLEND_ON
|
||||
float texcoordBlend : TEXCOORD1;
|
||||
#endif
|
||||
#if defined(_RIM_FADE_ON) || defined(A_PARTICLE_LIGHTING_ON)
|
||||
half3 normal : NORMAL;
|
||||
#endif
|
||||
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||
};
|
||||
|
||||
struct AFragmentInput {
|
||||
float4 vertex : SV_POSITION;
|
||||
float4 color : COLOR;
|
||||
float4 texcoords : TEXCOORD0;
|
||||
#ifdef _PARTICLE_EFFECTS_ON
|
||||
float2 uv_ParticleEffectMask1 : TEXCOORD1;
|
||||
float2 uv_ParticleEffectMask2 : TEXCOORD2;
|
||||
#endif
|
||||
UNITY_FOG_COORDS(3)
|
||||
#if defined(SOFTPARTICLES_ON) || defined(_DISTANCE_FADE_ON) || defined(VTRANSPARENCY_ON)
|
||||
float4 projPos : TEXCOORD4;
|
||||
#endif
|
||||
#if defined(_RIM_FADE_ON) || defined(A_PARTICLE_LIGHTING_ON)
|
||||
half3 normalWorld : TEXCOORD5;
|
||||
half4 viewDirWorld : TEXCOORD6;
|
||||
#endif
|
||||
#if defined(A_PARTICLE_LIGHTING_ON) || defined(VAPOR_TRANSLUCENT_FOG_ON)
|
||||
float4 positionWorld : TEXCOORD7;
|
||||
#endif
|
||||
#if defined(A_PARTICLE_LIGHTING_ON)
|
||||
half3 ambient : TEXCOORD8;
|
||||
#endif
|
||||
#ifdef A_PARTICLE_TEXTURE_BLEND_ON
|
||||
float blend : TEXCOORD9;
|
||||
#endif
|
||||
UNITY_VERTEX_INPUT_INSTANCE_ID
|
||||
};
|
||||
|
||||
UNITY_DECLARE_DEPTH_TEXTURE(_CameraDepthTexture);
|
||||
|
||||
half4 _TintColor;
|
||||
A_SAMPLER_2D(_MainTex);
|
||||
half _TintWeight;
|
||||
float _InvFade;
|
||||
|
||||
#ifdef _PARTICLE_EFFECTS_ON
|
||||
A_SAMPLER_2D(_ParticleEffectMask1);
|
||||
A_SAMPLER_2D(_ParticleEffectMask2);
|
||||
#endif
|
||||
|
||||
#ifdef _RIM_FADE_ON
|
||||
half _RimFadeWeight; // Expects linear-space values
|
||||
half _RimFadePower;
|
||||
#endif
|
||||
|
||||
float _DistanceFadeNearFadeCutoff;
|
||||
float _DistanceFadeRange;
|
||||
|
||||
AFragmentInput aMainVertexShader(
|
||||
AVertexInput v)
|
||||
{
|
||||
AFragmentInput o;
|
||||
UNITY_INITIALIZE_OUTPUT(AFragmentInput, o);
|
||||
UNITY_SETUP_INSTANCE_ID(v);
|
||||
UNITY_TRANSFER_INSTANCE_ID(v, o);
|
||||
|
||||
o.vertex = UnityObjectToClipPos(v.vertex.xyz);
|
||||
|
||||
#if defined(SOFTPARTICLES_ON) || defined(_DISTANCE_FADE_ON) || defined(VTRANSPARENCY_ON)
|
||||
o.projPos = ComputeScreenPos (o.vertex);
|
||||
COMPUTE_EYEDEPTH(o.projPos.z);
|
||||
#endif
|
||||
|
||||
o.color = v.color;
|
||||
|
||||
#ifndef A_VERTEX_COLOR_DEGAMMA_OFF
|
||||
o.color.rgb = aGammaToLinear(o.color.rgb);
|
||||
#endif
|
||||
|
||||
o.texcoords.xy = A_TEX_TRANSFORM_SCROLL_SPIN(_MainTex, v.texcoords.xy);
|
||||
|
||||
#ifdef _PARTICLE_EFFECTS_ON
|
||||
o.uv_ParticleEffectMask1 = A_TEX_TRANSFORM_SCROLL_SPIN(_ParticleEffectMask1, v.texcoords.xy);
|
||||
o.uv_ParticleEffectMask2 = A_TEX_TRANSFORM_SCROLL_SPIN(_ParticleEffectMask2, v.texcoords.xy);
|
||||
#endif
|
||||
|
||||
#if defined(_RIM_FADE_ON) || defined(A_PARTICLE_LIGHTING_ON) || defined(VAPOR_TRANSLUCENT_FOG_ON)
|
||||
float4 positionWorld = mul(unity_ObjectToWorld, v.vertex);
|
||||
#endif
|
||||
|
||||
#if defined(_RIM_FADE_ON) || defined(A_PARTICLE_LIGHTING_ON)
|
||||
o.normalWorld = UnityObjectToWorldNormal(v.normal);
|
||||
o.viewDirWorld.xyz = UnityWorldSpaceViewDir(positionWorld.xyz);
|
||||
#endif
|
||||
|
||||
#if defined(A_PARTICLE_LIGHTING_ON) || defined(VAPOR_TRANSLUCENT_FOG_ON)
|
||||
o.positionWorld = positionWorld;
|
||||
#endif
|
||||
#ifdef A_PARTICLE_LIGHTING_ON
|
||||
// 1 Directional, 4 Point lights, and Light probes.
|
||||
o.ambient = _LightColor0.rgb * aDotClamp(_WorldSpaceLightPos0.xyz, o.normalWorld);
|
||||
o.ambient += aShade4PointLights(o.positionWorld.xyz, o.normalWorld);
|
||||
o.ambient += ShadeSHPerVertex(o.normalWorld, o.ambient);
|
||||
#endif
|
||||
|
||||
#ifdef A_PARTICLE_TEXTURE_BLEND_ON
|
||||
o.texcoords.zw = A_TEX_TRANSFORM_SCROLL_SPIN(_MainTex, v.texcoords.zw);
|
||||
o.blend = v.texcoordBlend;
|
||||
#endif
|
||||
|
||||
UNITY_TRANSFER_FOG(o,o.vertex);
|
||||
return o;
|
||||
}
|
||||
|
||||
/// Controls how the particle is faded out based on scene intersection, rim,
|
||||
/// and camera distance.
|
||||
half aFadeParticle(
|
||||
AFragmentInput i)
|
||||
{
|
||||
half fade = 1.0h;
|
||||
|
||||
UNITY_SETUP_INSTANCE_ID(i);
|
||||
|
||||
#ifdef SOFTPARTICLES_ON
|
||||
float sceneZ = DECODE_EYEDEPTH(SAMPLE_DEPTH_TEXTURE_PROJ(_CameraDepthTexture, UNITY_PROJ_COORD(i.projPos)));
|
||||
float partZ = i.projPos.z;
|
||||
|
||||
fade = saturate(_InvFade * (sceneZ - partZ));
|
||||
#endif
|
||||
|
||||
#ifdef _DISTANCE_FADE_ON
|
||||
// Alpha clip.
|
||||
// cf http://wiki.unity3d.com/index.php?title=AlphaClipsafe
|
||||
fade *= saturate((i.projPos.z - _DistanceFadeNearFadeCutoff) / _DistanceFadeRange);
|
||||
#endif
|
||||
|
||||
#ifdef _RIM_FADE_ON
|
||||
half3 normal = normalize(i.normalWorld);
|
||||
half3 viewDir = normalize(i.viewDirWorld.xyz);
|
||||
half NdotV = abs(dot(normal, viewDir));
|
||||
half bias = 1.0h - _RimFadeWeight;
|
||||
|
||||
fade = aRimLight(fade, bias, _RimFadePower, 1.0h - NdotV);
|
||||
#endif
|
||||
|
||||
return fade;
|
||||
}
|
||||
|
||||
/// Applies transforming effects mask textures to the particle.
|
||||
half4 aParticleEffects(
|
||||
AFragmentInput i)
|
||||
{
|
||||
half4 color = tex2D(_MainTex, i.texcoords.xy);
|
||||
|
||||
#ifdef A_PARTICLE_TEXTURE_BLEND_ON
|
||||
half4 color2 = tex2D(_MainTex, i.texcoords.zw);
|
||||
color = lerp(color, color2, i.blend);
|
||||
#endif
|
||||
|
||||
color.rgb *= _TintWeight;
|
||||
|
||||
#ifdef _PARTICLE_EFFECTS_ON
|
||||
color *= tex2D(_ParticleEffectMask1, i.uv_ParticleEffectMask1);
|
||||
color *= tex2D(_ParticleEffectMask2, i.uv_ParticleEffectMask2);
|
||||
#endif
|
||||
|
||||
#ifdef A_PARTICLE_LIGHTING_ON
|
||||
color.rgb *= ShadeSHPerPixel(i.normalWorld, i.ambient, i.positionWorld);
|
||||
#endif
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
half4 aParticleOutputBase(
|
||||
AFragmentInput i,
|
||||
half4 color)
|
||||
{
|
||||
UNITY_APPLY_FOG_COLOR(i.fogCoord, color, unity_FogColor);
|
||||
|
||||
#if defined(VAPOR_TRANSLUCENT_FOG_ON)
|
||||
color = VaporApplyFog(i.positionWorld, color);
|
||||
#elif defined(VTRANSPARENCY_ON)
|
||||
color = VolumetricTransparencyBase(color, i.projPos);
|
||||
#endif
|
||||
|
||||
color.rgb = aHdrClamp(color.rgb);
|
||||
return color;
|
||||
}
|
||||
|
||||
half4 aParticleOutputAdd(
|
||||
AFragmentInput i,
|
||||
half4 color)
|
||||
{
|
||||
UNITY_APPLY_FOG_COLOR(i.fogCoord, color, A_BLACK4);
|
||||
|
||||
#if defined(VAPOR_TRANSLUCENT_FOG_ON)
|
||||
color = VaporApplyFogAdd(i.positionWorld, color);
|
||||
#elif defined(VTRANSPARENCY_ON)
|
||||
color = VolumetricTransparencyAdd(color, i.projPos);
|
||||
#endif
|
||||
|
||||
color.rgb = aHdrClamp(color.rgb);
|
||||
return color;
|
||||
}
|
||||
|
||||
half4 aParticleOutputMultiply(
|
||||
AFragmentInput i,
|
||||
half4 color)
|
||||
{
|
||||
UNITY_APPLY_FOG_COLOR(i.fogCoord, color, A_WHITE4);
|
||||
|
||||
#if defined(VAPOR_TRANSLUCENT_FOG_ON)
|
||||
color = VaporApplyFogFade(i.positionWorld, color, A_WHITE);
|
||||
#elif defined(VTRANSPARENCY_ON)
|
||||
// color = VolumetricTransparencyAdd(color, i.projPos);
|
||||
#endif
|
||||
|
||||
color.rgb = aHdrClamp(color.rgb);
|
||||
return color;
|
||||
}
|
||||
|
||||
#endif // ALLOY_SHADERS_FRAMEWORK_PARTICLE_CGINC
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c51b783c68589c242820eed366e80062
|
||||
timeCreated: 1424470451
|
||||
licenseType: Pro
|
||||
ShaderImporter:
|
||||
defaultTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,256 @@
|
||||
// Alloy Physical Shader Framework
|
||||
// Copyright 2013-2017 RUST LLC.
|
||||
// http://www.alloy.rustltd.com/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// @file Tessellation.cginc
|
||||
/// @brief Callbacks and data structures for tessellation.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef ALLOY_SHADERS_FRAMEWORK_TESSELLATION_CGINC
|
||||
#define ALLOY_SHADERS_FRAMEWORK_TESSELLATION_CGINC
|
||||
|
||||
#include "Assets/Alloy/Shaders/Config.cginc"
|
||||
|
||||
#include "HLSLSupport.cginc"
|
||||
//#include "Lighting.cginc"
|
||||
//#include "Tessellation.cginc"
|
||||
#include "UnityCG.cginc"
|
||||
|
||||
#if defined(A_TESSELLATION_SHADER) && defined(A_TESSELLATION_PASS) && defined(UNITY_CAN_COMPILE_TESSELLATION)
|
||||
struct UnityTessellationFactors {
|
||||
float edge[3] : SV_TessFactor;
|
||||
float inside : SV_InsideTessFactor;
|
||||
};
|
||||
|
||||
#include "UnityShaderVariables.cginc"
|
||||
|
||||
float UnityCalcEdgeTessFactor(float3 wpos0, float3 wpos1, float edgeLen)
|
||||
{
|
||||
// distance to edge center
|
||||
float dist = distance(0.5 * (wpos0 + wpos1), _WorldSpaceCameraPos);
|
||||
// length of the edge
|
||||
float len = distance(wpos0, wpos1);
|
||||
// edgeLen is approximate desired size in pixels
|
||||
float f = max(len * _ScreenParams.y / (edgeLen * dist), 1.0);
|
||||
return f;
|
||||
}
|
||||
|
||||
float UnityDistanceFromPlane(float3 pos, float4 plane)
|
||||
{
|
||||
float d = dot(float4(pos, 1.0f), plane);
|
||||
return d;
|
||||
}
|
||||
|
||||
// Returns true if triangle with given 3 world positions is outside of camera's view frustum.
|
||||
// cullEps is distance outside of frustum that is still considered to be inside (i.e. max displacement)
|
||||
bool UnityWorldViewFrustumCull(float3 wpos0, float3 wpos1, float3 wpos2, float cullEps)
|
||||
{
|
||||
float4 planeTest;
|
||||
|
||||
// left
|
||||
planeTest.x = ((UnityDistanceFromPlane(wpos0, unity_CameraWorldClipPlanes[0]) > -cullEps) ? 1.0f : 0.0f) +
|
||||
((UnityDistanceFromPlane(wpos1, unity_CameraWorldClipPlanes[0]) > -cullEps) ? 1.0f : 0.0f) +
|
||||
((UnityDistanceFromPlane(wpos2, unity_CameraWorldClipPlanes[0]) > -cullEps) ? 1.0f : 0.0f);
|
||||
// right
|
||||
planeTest.y = ((UnityDistanceFromPlane(wpos0, unity_CameraWorldClipPlanes[1]) > -cullEps) ? 1.0f : 0.0f) +
|
||||
((UnityDistanceFromPlane(wpos1, unity_CameraWorldClipPlanes[1]) > -cullEps) ? 1.0f : 0.0f) +
|
||||
((UnityDistanceFromPlane(wpos2, unity_CameraWorldClipPlanes[1]) > -cullEps) ? 1.0f : 0.0f);
|
||||
// top
|
||||
planeTest.z = ((UnityDistanceFromPlane(wpos0, unity_CameraWorldClipPlanes[2]) > -cullEps) ? 1.0f : 0.0f) +
|
||||
((UnityDistanceFromPlane(wpos1, unity_CameraWorldClipPlanes[2]) > -cullEps) ? 1.0f : 0.0f) +
|
||||
((UnityDistanceFromPlane(wpos2, unity_CameraWorldClipPlanes[2]) > -cullEps) ? 1.0f : 0.0f);
|
||||
// bottom
|
||||
planeTest.w = ((UnityDistanceFromPlane(wpos0, unity_CameraWorldClipPlanes[3]) > -cullEps) ? 1.0f : 0.0f) +
|
||||
((UnityDistanceFromPlane(wpos1, unity_CameraWorldClipPlanes[3]) > -cullEps) ? 1.0f : 0.0f) +
|
||||
((UnityDistanceFromPlane(wpos2, unity_CameraWorldClipPlanes[3]) > -cullEps) ? 1.0f : 0.0f);
|
||||
|
||||
// has to pass all 4 plane tests to be visible
|
||||
return !all(planeTest);
|
||||
}
|
||||
|
||||
// Same as UnityEdgeLengthBasedTess, but also does patch frustum culling:
|
||||
// patches outside of camera's view are culled before GPU tessellation. Saves some wasted work.
|
||||
float4 UnityEdgeLengthBasedTessCull(float4 v0, float4 v1, float4 v2, float edgeLength, float maxDisplacement)
|
||||
{
|
||||
float3 pos0 = mul(unity_ObjectToWorld, v0).xyz;
|
||||
float3 pos1 = mul(unity_ObjectToWorld, v1).xyz;
|
||||
float3 pos2 = mul(unity_ObjectToWorld, v2).xyz;
|
||||
float4 tess;
|
||||
|
||||
if (UnityWorldViewFrustumCull(pos0, pos1, pos2, maxDisplacement))
|
||||
{
|
||||
tess = 0.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
tess.x = UnityCalcEdgeTessFactor(pos1, pos2, edgeLength);
|
||||
tess.y = UnityCalcEdgeTessFactor(pos2, pos0, edgeLength);
|
||||
tess.z = UnityCalcEdgeTessFactor(pos0, pos1, edgeLength);
|
||||
tess.w = (tess.x + tess.y + tess.z) / 3.0f;
|
||||
}
|
||||
return tess;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
struct ATessellationInput {
|
||||
float4 vertex : INTERNALTESSPOS;
|
||||
half3 normal : NORMAL;
|
||||
float4 uv0 : TEXCOORD0;
|
||||
float4 uv1 : TEXCOORD1;
|
||||
#ifdef A_UV2_ON
|
||||
float4 uv2 : TEXCOORD2;
|
||||
#endif
|
||||
#ifdef A_TANGENT_ON
|
||||
half4 tangent : TANGENT;
|
||||
#endif
|
||||
half4 color : COLOR;
|
||||
};
|
||||
|
||||
float _EdgeLength;
|
||||
|
||||
#if A_USE_TESSELLATION_MIN_EDGE_LENGTH
|
||||
float _MinEdgeLength;
|
||||
#endif
|
||||
|
||||
#ifdef _TESSELLATIONMODE_DISPLACEMENT
|
||||
A_SAMPLER_2D(_DispTex);
|
||||
float _Displacement;
|
||||
#endif
|
||||
#ifdef _TESSELLATIONMODE_PHONG
|
||||
float _Phong;
|
||||
#endif
|
||||
|
||||
// NOTE: Forward-declared here so we can share Domain shader.
|
||||
void aMainVertexShader(AVertexInput v,
|
||||
#ifndef A_VERTEX_TO_FRAGMENT_OFF
|
||||
out AFragmentInput o,
|
||||
#endif
|
||||
out float4 opos : SV_POSITION);
|
||||
|
||||
// tessellation hull constant shader
|
||||
UnityTessellationFactors aHullConstantTessellation(
|
||||
InputPatch<ATessellationInput, 3> v)
|
||||
{
|
||||
float4 tf = 0.0f;
|
||||
float maxDisplacement = 0.0f;
|
||||
UnityTessellationFactors o;
|
||||
|
||||
#ifdef _TESSELLATIONMODE_DISPLACEMENT
|
||||
maxDisplacement = 1.5f * _Displacement;
|
||||
#endif
|
||||
|
||||
float edgeLength = _EdgeLength;
|
||||
|
||||
#if A_USE_TESSELLATION_MIN_EDGE_LENGTH
|
||||
edgeLength = max(_MinEdgeLength, edgeLength);
|
||||
#endif
|
||||
|
||||
tf = UnityEdgeLengthBasedTessCull(v[0].vertex, v[1].vertex, v[2].vertex, edgeLength, maxDisplacement);
|
||||
|
||||
o.edge[0] = tf.x;
|
||||
o.edge[1] = tf.y;
|
||||
o.edge[2] = tf.z;
|
||||
o.inside = tf.w;
|
||||
return o;
|
||||
}
|
||||
|
||||
ATessellationInput aMainTessellationVertexShader(
|
||||
AVertexInput v)
|
||||
{
|
||||
ATessellationInput o;
|
||||
|
||||
UNITY_INITIALIZE_OUTPUT(ATessellationInput, o);
|
||||
o.vertex = v.vertex;
|
||||
o.normal = v.normal;
|
||||
o.uv0 = v.uv0;
|
||||
o.uv1 = v.uv1;
|
||||
|
||||
#ifdef A_UV2_ON
|
||||
o.uv2 = v.uv2;
|
||||
#endif
|
||||
#ifdef A_TANGENT_ON
|
||||
o.tangent = v.tangent;
|
||||
#endif
|
||||
o.color = v.color;
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
// tessellation hull shader
|
||||
[UNITY_domain("tri")]
|
||||
[UNITY_partitioning("fractional_odd")]
|
||||
[UNITY_outputtopology("triangle_cw")]
|
||||
[UNITY_patchconstantfunc("aHullConstantTessellation")]
|
||||
[UNITY_outputcontrolpoints(3)]
|
||||
ATessellationInput aMainHullShader(
|
||||
InputPatch<ATessellationInput, 3> v,
|
||||
uint id : SV_OutputControlPointID)
|
||||
{
|
||||
return v[id];
|
||||
}
|
||||
|
||||
[UNITY_domain("tri")]
|
||||
void aMainDomainShader(
|
||||
UnityTessellationFactors tessFactors,
|
||||
const OutputPatch<ATessellationInput, 3> vi,
|
||||
float3 bary : SV_DomainLocation,
|
||||
#ifndef A_VERTEX_TO_FRAGMENT_OFF
|
||||
out AFragmentInput o,
|
||||
#endif
|
||||
out float4 opos : SV_POSITION)
|
||||
{
|
||||
AVertexInput v;
|
||||
UNITY_INITIALIZE_OUTPUT(AVertexInput, v);
|
||||
|
||||
v.vertex = vi[0].vertex * bary.x + vi[1].vertex * bary.y + vi[2].vertex * bary.z;
|
||||
v.normal = vi[0].normal * bary.x + vi[1].normal * bary.y + vi[2].normal * bary.z;
|
||||
v.uv0 = vi[0].uv0 * bary.x + vi[1].uv0 * bary.y + vi[2].uv0 * bary.z;
|
||||
v.uv1 = vi[0].uv1 * bary.x + vi[1].uv1 * bary.y + vi[2].uv1 * bary.z;
|
||||
|
||||
#ifdef A_UV2_ON
|
||||
v.uv2 = vi[0].uv2 * bary.x + vi[1].uv2 * bary.y + vi[2].uv2 * bary.z;
|
||||
#endif
|
||||
#ifdef A_TANGENT_ON
|
||||
v.tangent = vi[0].tangent * bary.x + vi[1].tangent * bary.y + vi[2].tangent * bary.z;
|
||||
#endif
|
||||
v.color = vi[0].color * bary.x + vi[1].color * bary.y + vi[2].color * bary.z;
|
||||
|
||||
#ifdef _TESSELLATIONMODE_PHONG
|
||||
float3 pp[3];
|
||||
|
||||
for (int i = 0; i < 3; ++i)
|
||||
pp[i] = v.vertex.xyz - vi[i].normal * (dot(v.vertex.xyz, vi[i].normal) - dot(vi[i].vertex.xyz, vi[i].normal));
|
||||
|
||||
float3 displacedPosition = pp[0] * bary.x + pp[1] * bary.y + pp[2] * bary.z;
|
||||
v.vertex.xyz = lerp(v.vertex.xyz, displacedPosition, _Phong);
|
||||
#endif
|
||||
|
||||
// NOTE: This has to come second, since the Phong mode references the
|
||||
// unmodified vertices in order to work!
|
||||
#ifdef _TESSELLATIONMODE_DISPLACEMENT
|
||||
float d = _Displacement;
|
||||
float oscillation = _Time.y;
|
||||
float2 tessUv = TRANSFORM_TEX(v.uv0.xy, _DispTex) + (_DispTexVelocity * oscillation);
|
||||
|
||||
#ifdef _VIRTUALTEXTURING_ON
|
||||
d *= VTVertexSampleDisplacement(tessUv);
|
||||
#else
|
||||
d *= tex2Dlod(_DispTex, float4(tessUv, 0.0f, 0.0f)).g;
|
||||
#endif
|
||||
|
||||
v.vertex.xyz += v.normal * d;
|
||||
#endif
|
||||
|
||||
aMainVertexShader(
|
||||
v,
|
||||
#ifndef A_VERTEX_TO_FRAGMENT_OFF
|
||||
o,
|
||||
#endif
|
||||
opos);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // ALLOY_SHADERS_FRAMEWORK_TESSELLATION_CGINC
|
||||
@@ -0,0 +1,6 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a789d7820ee8bd8468cb19d1a820a515
|
||||
ShaderImporter:
|
||||
defaultTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
@@ -0,0 +1,147 @@
|
||||
// Alloy Physical Shader Framework
|
||||
// Copyright 2013-2017 RUST LLC.
|
||||
// http://www.alloy.rustltd.com/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// @file Type.cginc
|
||||
/// @brief Shader type uber-header.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef ALLOY_SHADERS_FRAMEWORK_TYPE_CGINC
|
||||
#define ALLOY_SHADERS_FRAMEWORK_TYPE_CGINC
|
||||
|
||||
#define A_VOLUMETRIC_DATA ASurface
|
||||
|
||||
// Headers both for this file, and for all Definition and Feature modules.
|
||||
#include "Assets/Alloy/Shaders/Config.cginc"
|
||||
#include "Assets/Alloy/Shaders/Framework/Feature.cginc"
|
||||
#include "Assets/Alloy/Shaders/Framework/Lighting.cginc"
|
||||
#include "Assets/Alloy/Shaders/Framework/Utility.cginc"
|
||||
#include "Assets/Alloy/Shaders/Framework/Volumetric.cginc"
|
||||
|
||||
#include "UnityCG.cginc"
|
||||
#include "UnityInstancing.cginc"
|
||||
|
||||
#if !defined(A_VERTEX_COLOR_IS_DATA) && defined(A_PROJECTIVE_DECAL_SHADER)
|
||||
#define A_VERTEX_COLOR_IS_DATA
|
||||
#endif
|
||||
|
||||
#if !defined(A_SHADOW_MASKS_BUFFER_ON) && (defined(SHADOWS_SHADOWMASK) && (UNITY_ALLOWED_MRT_COUNT > 4))
|
||||
#define A_SHADOW_MASKS_BUFFER_ON
|
||||
#endif
|
||||
|
||||
#if !defined(A_ALPHA_BLENDING_ON) && (defined(_ALPHABLEND_ON) || defined(_ALPHAPREMULTIPLY_ON))
|
||||
#define A_ALPHA_BLENDING_ON
|
||||
#endif
|
||||
|
||||
#if !defined(A_ROUGHNESS_SOURCE_BASE_COLOR_ALPHA) && defined(_SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A)
|
||||
#define A_ROUGHNESS_SOURCE_BASE_COLOR_ALPHA
|
||||
#endif
|
||||
|
||||
#if !defined(A_NORMAL_MAPPING_ON) && (defined(EFFECT_BUMP) || defined(_TERRAIN_NORMAL_MAP))
|
||||
#define A_NORMAL_MAPPING_ON
|
||||
#endif
|
||||
|
||||
// Features
|
||||
#include "Assets/Alloy/Shaders/Feature/AO2.cginc"
|
||||
#include "Assets/Alloy/Shaders/Feature/CarPaint.cginc"
|
||||
#include "Assets/Alloy/Shaders/Feature/Decal.cginc"
|
||||
#include "Assets/Alloy/Shaders/Feature/Detail.cginc"
|
||||
#include "Assets/Alloy/Shaders/Feature/DirectionalBlend.cginc"
|
||||
#include "Assets/Alloy/Shaders/Feature/Dissolve.cginc"
|
||||
#include "Assets/Alloy/Shaders/Feature/Emission.cginc"
|
||||
#include "Assets/Alloy/Shaders/Feature/Emission2.cginc"
|
||||
#include "Assets/Alloy/Shaders/Feature/Eye.cginc"
|
||||
#include "Assets/Alloy/Shaders/Feature/MainTextures.cginc"
|
||||
#include "Assets/Alloy/Shaders/Feature/OrientedTextures.cginc"
|
||||
#include "Assets/Alloy/Shaders/Feature/Parallax.cginc"
|
||||
#include "Assets/Alloy/Shaders/Feature/Puddles.cginc"
|
||||
#include "Assets/Alloy/Shaders/Feature/Rim.cginc"
|
||||
#include "Assets/Alloy/Shaders/Feature/Rim2.cginc"
|
||||
#include "Assets/Alloy/Shaders/Feature/SecondaryTextures.cginc"
|
||||
#include "Assets/Alloy/Shaders/Feature/SkinTextures.cginc"
|
||||
#include "Assets/Alloy/Shaders/Feature/SpeedTree.cginc"
|
||||
#include "Assets/Alloy/Shaders/Feature/TeamColor.cginc"
|
||||
#include "Assets/Alloy/Shaders/Feature/Terrain.cginc"
|
||||
#include "Assets/Alloy/Shaders/Feature/TransitionBlend.cginc"
|
||||
#include "Assets/Alloy/Shaders/Feature/Transmission.cginc"
|
||||
#include "Assets/Alloy/Shaders/Feature/TriPlanar.cginc"
|
||||
#include "Assets/Alloy/Shaders/Feature/VertexBlend.cginc"
|
||||
#include "Assets/Alloy/Shaders/Feature/WeightedBlend.cginc"
|
||||
#include "Assets/Alloy/Shaders/Feature/Wetness.cginc"
|
||||
|
||||
/// Vertex data to be modified for specific shader type.
|
||||
struct AVertex {
|
||||
/// Vertex position in object space.
|
||||
float4 positionObject;
|
||||
|
||||
/// Vertex normal in object space.
|
||||
/// Expects normalized vectors.
|
||||
half3 normalObject;
|
||||
|
||||
/// Vertex tangent in object space and bitangent sign.
|
||||
/// XYZ: Normalized tangent, W: Bitangent sign.
|
||||
half4 tangentObject;
|
||||
|
||||
/// UV0 texture coordinates.
|
||||
float4 uv0;
|
||||
|
||||
/// UV1 texture coordinates.
|
||||
float4 uv1;
|
||||
|
||||
/// UV2 texture coordinates.
|
||||
float4 uv2;
|
||||
|
||||
/// UV3 texture coordinates.
|
||||
float4 uv3;
|
||||
|
||||
/// Vertex color.
|
||||
/// Expects linear-space LDR color values.
|
||||
half4 color;
|
||||
};
|
||||
|
||||
/// Deferred geometry buffer representation of surface data.
|
||||
struct AGbuffer {
|
||||
/// RGB: Albedo, A: Specular occlusion.
|
||||
half4 diffuseOcclusion : SV_Target0;
|
||||
|
||||
/// RGB: f0, A: 1-Roughness.
|
||||
half4 specularSmoothness : SV_Target1;
|
||||
|
||||
/// RGB: Packed world-space normal, A: Material type.
|
||||
half4 normalType : SV_Target2;
|
||||
|
||||
/// RGB: Emission, A: 1-Subsurface.
|
||||
half4 emissionSubsurface : SV_Target3;
|
||||
|
||||
#ifdef A_SHADOW_MASKS_BUFFER_ON
|
||||
/// RGBA: Shadow Masks.
|
||||
half4 shadowMasks : SV_Target4;
|
||||
#endif
|
||||
};
|
||||
|
||||
/// Abstract declaration for user-defined vertex shader.
|
||||
void aVertexShader(inout AVertex v);
|
||||
|
||||
/// Abstract declaration for user-defined color shader.
|
||||
void aColorShader(inout half4 color, ASurface s);
|
||||
|
||||
/// Abstract declaration for user-defined G-Buffer shader.
|
||||
void aGbufferShader(inout AGbuffer gb, ASurface s);
|
||||
|
||||
/// Abstract declaration for user-defined surface shader.
|
||||
void aSurfaceShader(inout ASurface s);
|
||||
|
||||
/// Vertex output data constructor.
|
||||
AVertex aNewVertex();
|
||||
|
||||
/// Gbuffer output data constructor.
|
||||
AGbuffer aNewGbuffer();
|
||||
|
||||
/// Applies standard vertex transformations.
|
||||
void aStandardVertexShader(inout AVertex v);
|
||||
|
||||
/// Applies standard color transformations.
|
||||
void aStandardColorShader(inout half4 color, ASurface s);
|
||||
|
||||
#endif // ALLOY_SHADERS_FRAMEWORK_TYPE_CGINC
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d0bcdda46674d1746bdd3bee79fa475a
|
||||
timeCreated: 1437771795
|
||||
licenseType: Pro
|
||||
ShaderImporter:
|
||||
defaultTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,63 @@
|
||||
// Alloy Physical Shader Framework
|
||||
// Copyright 2013-2017 RUST LLC.
|
||||
// http://www.alloy.rustltd.com/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// @file Type.cginc
|
||||
/// @brief Shader type method implementations to allow disabling of features.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef ALLOY_SHADERS_FRAMEWORK_TYPE_IMPL_CGINC
|
||||
#define ALLOY_SHADERS_FRAMEWORK_TYPE_IMPL_CGINC
|
||||
|
||||
#if !defined(A_VERTEX_COLOR_IS_DATA) && defined(A_USE_VERTEX_MOTION)
|
||||
#define A_VERTEX_COLOR_IS_DATA
|
||||
#endif
|
||||
|
||||
#include "Assets/Alloy/Shaders/Config.cginc"
|
||||
#include "Assets/Alloy/Shaders/Framework/LightingImpl.cginc"
|
||||
#include "Assets/Alloy/Shaders/Framework/Type.cginc"
|
||||
#include "Assets/Alloy/Shaders/Framework/Utility.cginc"
|
||||
#include "Assets/Alloy/Shaders/Framework/VolumetricImpl.cginc"
|
||||
|
||||
AVertex aNewVertex() {
|
||||
AVertex v;
|
||||
|
||||
UNITY_INITIALIZE_OUTPUT(AVertex, v);
|
||||
return v;
|
||||
}
|
||||
|
||||
AGbuffer aNewGbuffer() {
|
||||
AGbuffer gb;
|
||||
|
||||
UNITY_INITIALIZE_OUTPUT(AGbuffer, gb);
|
||||
|
||||
#ifdef A_SHADOW_MASKS_BUFFER_ON
|
||||
gb.shadowMasks = A_ZERO4;
|
||||
#endif
|
||||
return gb;
|
||||
}
|
||||
|
||||
void aStandardVertexShader(
|
||||
inout AVertex v)
|
||||
{
|
||||
#ifdef A_USE_VERTEX_MOTION
|
||||
v.positionObject = VertExmotion(v.positionObject, v.color);
|
||||
#elif !defined(A_VERTEX_COLOR_IS_DATA)
|
||||
/// Convert in vertex shader to interpolate in linear space.
|
||||
v.color.rgb = aGammaToLinear(v.color.rgb);
|
||||
#endif
|
||||
}
|
||||
|
||||
void aStandardColorShader(
|
||||
inout half4 color,
|
||||
ASurface s)
|
||||
{
|
||||
#ifdef A_BASE_PASS
|
||||
aVolumetricBase(color, s);
|
||||
#else
|
||||
aVolumetricAdd(color, s);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // ALLOY_SHADERS_FRAMEWORK_TYPE_IMPL_CGINC
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 240c6e998db732a4899614464dcba05a
|
||||
timeCreated: 1473016735
|
||||
licenseType: Pro
|
||||
ShaderImporter:
|
||||
defaultTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,193 @@
|
||||
// Alloy Physical Shader Framework
|
||||
// Copyright 2013-2017 RUST LLC.
|
||||
// http://www.alloy.rustltd.com/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// @file Unity.cginc
|
||||
/// @brief Code shared between Alloy shaders and Unity override headers.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef ALLOY_SHADERS_FRAMEWORK_UNITY_CGINC
|
||||
#define ALLOY_SHADERS_FRAMEWORK_UNITY_CGINC
|
||||
|
||||
// Headers both for this file, and for all Definition and Feature modules.
|
||||
#include "Assets/Alloy/Shaders/Config.cginc"
|
||||
#include "Assets/Alloy/Shaders/Framework/LightingImpl.cginc"
|
||||
#include "Assets/Alloy/Shaders/Framework/Utility.cginc"
|
||||
|
||||
#include "AutoLight.cginc"
|
||||
#include "UnityCG.cginc"
|
||||
#include "UnityGlobalIllumination.cginc"
|
||||
#include "UnityLightingCommon.cginc"
|
||||
#include "UnityShaderVariables.cginc"
|
||||
|
||||
/// Sets light range in light vector range ".w" component.
|
||||
/// @param[in,out] lightVectorRange XYZ: Vector to light center, W: Light volume range.
|
||||
/// @param[out] lightCoord Projection coordinates in light space.
|
||||
void aLightRange(
|
||||
inout float4 lightVectorRange,
|
||||
unityShadowCoord4 lightCoord)
|
||||
{
|
||||
// Light range = |light-space light vector| / |world-space light vector|
|
||||
// This works because the light vector's length is the same in both world
|
||||
// and light space, but it's scaled by the light range in light space.
|
||||
// cf http://forum.unity3d.com/threads/get-the-range-of-a-point-light-in-forward-add-mode.213430/#post-1433291
|
||||
lightVectorRange.w = length(lightVectorRange.xyz) * rsqrt(dot(lightCoord.xyz, lightCoord.xyz));
|
||||
}
|
||||
|
||||
/// Calculates forward indirect illumination.
|
||||
/// @param gi UnityGI populated with data.
|
||||
/// @param s Material surface data.
|
||||
/// @return Indirect illumination.
|
||||
half3 aUnityIndirectLighting(
|
||||
UnityGI gi,
|
||||
ASurface s)
|
||||
{
|
||||
return aIndirectLighting(gi.indirect, s);
|
||||
}
|
||||
|
||||
/// Calculates forward direct illumination.
|
||||
/// @param s Material surface data.
|
||||
/// @param shadow Shadow attenuation.
|
||||
/// @param lightVectorRange XYZ: Vector to light center, W: Light volume range.
|
||||
/// @param lightCoord Light projection texture coordinates.
|
||||
/// @return Direct illumination.
|
||||
half3 aUnityDirectLighting(
|
||||
ASurface s,
|
||||
half shadow,
|
||||
float4 lightVectorRange,
|
||||
unityShadowCoord4 lightCoord)
|
||||
{
|
||||
half3 lightAxis = A_ZERO;
|
||||
ADirect d = aNewDirect();
|
||||
|
||||
d.color = _LightColor0.rgb;
|
||||
d.shadow = shadow;
|
||||
|
||||
#if !defined(ALLOY_SUPPORT_REDLIGHTS) && defined(DIRECTIONAL_COOKIE)
|
||||
aLightCookie(d, tex2D(_LightTexture0, lightCoord.xy));
|
||||
#elif defined(POINT) || defined(POINT_COOKIE) || defined(SPOT)
|
||||
lightAxis = normalize(unity_WorldToLight[1].xyz);
|
||||
|
||||
#if defined(POINT)
|
||||
A_UNITY_ATTENUATION(d, _LightTexture0, lightCoord.xyz, 1.0f)
|
||||
#elif defined(POINT_COOKIE)
|
||||
aLightCookie(d, texCUBE(_LightTexture0, lightCoord.xyz));
|
||||
A_UNITY_ATTENUATION(d, _LightTextureB0, lightCoord.xyz, 1.0f)
|
||||
#elif defined(SPOT)
|
||||
half4 cookie = tex2D(_LightTexture0, lightCoord.xy / lightCoord.w + 0.5);
|
||||
|
||||
cookie.a *= (lightCoord.z > 0);
|
||||
aLightCookie(d, cookie);
|
||||
A_UNITY_ATTENUATION(d, _LightTextureB0, lightCoord.xyz, 1.0f)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(ALLOY_SUPPORT_REDLIGHTS) || !defined(DIRECTIONAL_COOKIE)
|
||||
aAreaLight(d, s, _LightColor0, lightAxis, lightVectorRange.xyz, lightVectorRange.w);
|
||||
#else
|
||||
d.direction = lightVectorRange.xyz;
|
||||
d.color *= redLightCalculateForward(_LightTexture0, s.positionWorld, s.normalWorld, s.viewDirWorld, d.direction);
|
||||
aDirectionalLight(d, s);
|
||||
#endif
|
||||
|
||||
return aDirectLighting(d, s);
|
||||
}
|
||||
|
||||
/// Post-processing of Unity surface data into correct format.
|
||||
/// @param[in,out] s Material surface data.
|
||||
void aUnitySurface(
|
||||
inout ASurface s)
|
||||
{
|
||||
s.beckmannRoughness = aLinearToBeckmannRoughness(s.roughness);
|
||||
s.specularOcclusion = aSpecularOcclusion(s.ambientOcclusion, s.NdotV);
|
||||
}
|
||||
|
||||
/// Forward illumination with Unity inputs.
|
||||
/// @param s Material surface data.
|
||||
/// @param gi Unity GI descriptor.
|
||||
/// @param shadow Shadow for the given direct light.
|
||||
/// @return Combined lighting, emission, etc.
|
||||
half4 aUnityLighting(
|
||||
ASurface s,
|
||||
UnityGI gi,
|
||||
half shadow)
|
||||
{
|
||||
half4 c = 0.0h;
|
||||
unityShadowCoord4 lightCoord = 0.0f;
|
||||
float4 lightVectorRange = UnityWorldSpaceLightDir(s.positionWorld).xyzz;
|
||||
|
||||
#ifdef DIRECTIONAL
|
||||
lightCoord = 0.0h;
|
||||
#else
|
||||
lightCoord = mul(unity_WorldToLight, unityShadowCoord4(s.positionWorld, 1.0f));
|
||||
|
||||
#ifndef USING_DIRECTIONAL_LIGHT
|
||||
aLightRange(lightVectorRange, lightCoord);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef UNITY_PASS_FORWARDBASE
|
||||
c.rgb = aUnityIndirectLighting(gi, s);
|
||||
|
||||
// Extract shadow with combined baked occlusion.
|
||||
#ifdef HANDLE_SHADOWS_BLENDING_IN_GI
|
||||
shadow = gi.light.color.g;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
c.rgb += aUnityDirectLighting(s, shadow, lightVectorRange, lightCoord);
|
||||
c.rgb = aHdrClamp(c.rgb);
|
||||
c.a = s.opacity;
|
||||
return c;
|
||||
}
|
||||
|
||||
/// Fills the G-buffer with Unity-compatible material data.
|
||||
/// @param[in] s Material surface data.
|
||||
/// @param[in] gi Unity GI descriptor.
|
||||
/// @param[out] outGBuffer0 RGB: albedo, A: specular occlusion.
|
||||
/// @param[out] outGBuffer1 RGB: f0, A: 1-roughness.
|
||||
/// @param[out] outGBuffer2 RGB: packed normal, A: 1-scattering mask.
|
||||
/// @return RGB: emission, A: 1-transmission.
|
||||
half4 aUnityLightingDeferred(
|
||||
ASurface s,
|
||||
UnityGI gi,
|
||||
out half4 outGBuffer0,
|
||||
out half4 outGBuffer1,
|
||||
out half4 outGBuffer2)
|
||||
{
|
||||
half3 illum = aHdrClamp(s.emissiveColor + aUnityIndirectLighting(gi, s));
|
||||
outGBuffer0 = half4(s.albedo, s.specularOcclusion);
|
||||
outGBuffer1 = half4(s.f0, 1.0h - s.roughness);
|
||||
outGBuffer2 = half4(s.normalWorld * 0.5h + 0.5h, s.materialType);
|
||||
return half4(illum, s.subsurface);
|
||||
}
|
||||
|
||||
/// Forward global illumination with Unity inputs.
|
||||
/// @param[in,out] gi Unity GI descriptor.
|
||||
/// @param[in] data GI input data.
|
||||
/// @param[in] normals World-space normals.
|
||||
/// @param[in] smoothness Surface smoothness.
|
||||
/// @param[in] specular Surface f0.
|
||||
void aUnityLightingGi(
|
||||
inout UnityGI gi,
|
||||
UnityGIInput data,
|
||||
half3 normals,
|
||||
half smoothness,
|
||||
half3 specular)
|
||||
{
|
||||
// So we can extract shadow with baked occlusion.
|
||||
#if defined(UNITY_PASS_FORWARDBASE) && defined(HANDLE_SHADOWS_BLENDING_IN_GI)
|
||||
data.light.color = A_WHITE;
|
||||
#endif
|
||||
|
||||
// Pass 1 for occlusion so we can manage that later.
|
||||
#if defined(UNITY_PASS_DEFERRED) && UNITY_ENABLE_REFLECTION_BUFFERS
|
||||
gi = UnityGlobalIllumination(data, 1.0h, normals);
|
||||
#else
|
||||
Unity_GlossyEnvironmentData g = UnityGlossyEnvironmentSetup(smoothness, data.worldViewDir, normals, specular);
|
||||
gi = UnityGlobalIllumination(data, 1.0h, normals, g);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // ALLOY_SHADERS_FRAMEWORK_UNITY_CGINC
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1bd87f4acb9d203409163c16855b14ae
|
||||
timeCreated: 1448830649
|
||||
licenseType: Pro
|
||||
ShaderImporter:
|
||||
defaultTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,348 @@
|
||||
// Alloy Physical Shader Framework
|
||||
// Copyright 2013-2017 RUST LLC.
|
||||
// http://www.alloy.rustltd.com/
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
/// @file Utility.cginc
|
||||
/// @brief Minimum functions and constants common to surfaces and particles.
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef ALLOY_SHADERS_FRAMEWORK_UTILITY_CGINC
|
||||
#define ALLOY_SHADERS_FRAMEWORK_UTILITY_CGINC
|
||||
|
||||
#include "Assets/Alloy/Shaders/Config.cginc"
|
||||
|
||||
#include "UnityShaderVariables.cginc"
|
||||
|
||||
/// Defines all texture transform uniform variables, inlcuding additional transforms.
|
||||
/// Spin is in radians.
|
||||
#define A_SAMPLER_2D(name) \
|
||||
sampler2D name; \
|
||||
float4 name##_ST; \
|
||||
float2 name##Velocity; \
|
||||
float name##Spin; \
|
||||
float name##UV;
|
||||
|
||||
/// Allows passing all of a texture's transform uniforms into a function.
|
||||
#define A_SAMPLER_2D_INPUT(name) name, name##_ST, name##Velocity, name##UV
|
||||
|
||||
/// Allows accessing all of a texture's transform uniforms inside a function.
|
||||
#define A_SAMPLER_PARAM(name) sampler2D name, float4 name##_ST, float2 name##Velocity, float name##UV
|
||||
|
||||
// NOTE: To make it rotate around a "center" point, the order of operations
|
||||
// needs to be offset, rotate, scale. So that means that we have to apply
|
||||
// offset & scroll first divided by tiling. Then when we apply tiling later
|
||||
// it will cancel.
|
||||
|
||||
/// Applies our scrolling effect.
|
||||
#ifdef A_TEX_SCROLL_OFF
|
||||
#define A_TEX_SCROLL(name, tex) (tex)
|
||||
#else
|
||||
#define A_TEX_SCROLL(name, tex) (tex + ((name##Velocity * _Time.y + name##_ST.zw) / name##_ST.xy))
|
||||
#endif
|
||||
|
||||
/// Applies our spinning effect.
|
||||
#define A_TEX_SPIN(name, tex) (aRotateTextureCoordinates(name##Spin * _Time.y, tex.xy))
|
||||
|
||||
/// Applies Unity texture transforms plus our spinning effect.
|
||||
#define A_TEX_TRANSFORM_SPIN(name, tex) (A_TEX_SPIN(name, tex + (name##_ST.zw / name##_ST.xy)) * name##_ST.xy)
|
||||
|
||||
/// Applies Unity texture transforms plus our spinning and scrolling effects.
|
||||
#define A_TEX_TRANSFORM_SCROLL(name, tex) (A_TEX_SCROLL(name, tex) * name##_ST.xy)
|
||||
|
||||
/// Applies Unity texture transforms plus our spinning and scrolling effects.
|
||||
#define A_TEX_TRANSFORM_SCROLL_SPIN(name, tex) (A_TEX_SPIN(name, A_TEX_SCROLL(name, tex)) * name##_ST.xy)
|
||||
|
||||
/// A value close to zero.
|
||||
/// This is used for preventing NaNs in cases where you can divide by zero.
|
||||
static const float A_EPSILON = 1e-6f;
|
||||
|
||||
/// Multi-component zero.
|
||||
static const half3 A_ZERO = half3(0.0h, 0.0h, 0.0h);
|
||||
|
||||
/// Multi-component zero.
|
||||
static const half4 A_ZERO4 = half4(0.0h, 0.0h, 0.0h, 0.0h);
|
||||
|
||||
/// Multi-component one.
|
||||
static const half3 A_ONE = half3(1.0h, 1.0h, 1.0h);
|
||||
|
||||
/// Multi-component one.
|
||||
static const half4 A_ONE4 = half4(1.0h, 1.0h, 1.0h, 1.0h);
|
||||
|
||||
/// Color Black.
|
||||
static const half3 A_BLACK = A_ZERO;
|
||||
|
||||
/// Multi-component zero.
|
||||
static const half4 A_BLACK4 = A_ZERO4;
|
||||
|
||||
/// Color White.
|
||||
static const half3 A_WHITE = A_ONE;
|
||||
|
||||
/// Multi-component one.
|
||||
static const half4 A_WHITE4 = A_ONE4;
|
||||
|
||||
/// X-Axis normal.
|
||||
static const half3 A_AXIS_X = half3(1.0h, 0.0h, 0.0h);
|
||||
|
||||
/// Y-Axis normal.
|
||||
static const half3 A_AXIS_Y = half3(0.0h, 1.0h, 0.0h);
|
||||
|
||||
/// Z-Axis normal.
|
||||
static const half3 A_AXIS_Z = half3(0.0h, 0.0h, 1.0h);
|
||||
|
||||
/// Flat normal in tangent space.
|
||||
static const half3 A_FLAT_NORMAL = A_AXIS_Z;
|
||||
|
||||
/// Applies 2D texture rotation around the point (0.5,0.5) in UV-space.
|
||||
/// @param rotation Rotation in radians.
|
||||
/// @param texcoords Texture coordinates to be rotated.
|
||||
/// @return Rotated texture coordinates.
|
||||
float2 aRotateTextureCoordinates(
|
||||
float rotation,
|
||||
float2 texcoords)
|
||||
{
|
||||
// Texture Rotation
|
||||
// cf http://forum.unity3d.com/threads/rotation-of-texture-uvs-directly-from-a-shader.150482/#post-1031763
|
||||
float2 centerOffset = float2(0.5f, 0.5f);
|
||||
float sinTheta = sin(rotation);
|
||||
float cosTheta = cos(rotation);
|
||||
float2x2 rotationMatrix = float2x2(cosTheta, -sinTheta, sinTheta, cosTheta);
|
||||
return mul(texcoords - centerOffset, rotationMatrix) + centerOffset;
|
||||
}
|
||||
|
||||
/// Dot product of two vectors, clamped to range [0,1].
|
||||
half aDotClamp(
|
||||
half2 x,
|
||||
half2 y)
|
||||
{
|
||||
return saturate(dot(x, y));
|
||||
}
|
||||
|
||||
/// Dot product of two vectors, clamped to range [0,1].
|
||||
half aDotClamp(
|
||||
half3 x,
|
||||
half3 y)
|
||||
{
|
||||
return saturate(dot(x, y));
|
||||
}
|
||||
|
||||
/// Dot product of two vectors, clamped to range [0,1].
|
||||
half aDotClamp(
|
||||
half4 x,
|
||||
half4 y)
|
||||
{
|
||||
return saturate(dot(x, y));
|
||||
}
|
||||
|
||||
/// Screen Blends two colors.
|
||||
half3 aScreenBlend(
|
||||
half3 a,
|
||||
half3 b)
|
||||
{
|
||||
return A_ONE - ((A_ONE - a) * (A_ONE - b));
|
||||
}
|
||||
|
||||
/// Converts an LDR color from gamma-space to linear-space.
|
||||
half3 aGammaToLinear(
|
||||
half3 sRGB)
|
||||
{
|
||||
// sRGB curve approximation.
|
||||
// cf http://chilliant.blogspot.com.au/2012/08/srgb-approximations-for-hlsl.html?m=1
|
||||
return sRGB * (sRGB * (sRGB * 0.305306011h + 0.682171111h) + 0.012522878h);
|
||||
}
|
||||
|
||||
/// Converts an LDR value from gamma-space to linear-space.
|
||||
half aGammaToLinear(
|
||||
half sRGB)
|
||||
{
|
||||
return aGammaToLinear(sRGB.rrr).r;
|
||||
}
|
||||
|
||||
/// Interpolate from one to another value.
|
||||
half aLerpOneTo(
|
||||
half b,
|
||||
half alpha)
|
||||
{
|
||||
// Use lerp intrinsic for better optimization.
|
||||
return lerp(1.0h, b, alpha);
|
||||
}
|
||||
|
||||
/// Interpolate from the color white to another color.
|
||||
half3 aLerpWhiteTo(
|
||||
half3 b,
|
||||
half alpha)
|
||||
{
|
||||
// Use lerp intrinsic for better optimization.
|
||||
return lerp(A_WHITE, b, alpha);
|
||||
}
|
||||
|
||||
/// Calculates a linear color's luminance.
|
||||
/// @param color Linear LDR color.
|
||||
/// @return Color's chromaticity.
|
||||
half aLuminance(
|
||||
half3 color)
|
||||
{
|
||||
// Linear-space luminance coefficients.
|
||||
// cf https://en.wikipedia.org/wiki/Luma_(video)
|
||||
return dot(color, half3(0.2126h, 0.7152h, 0.0722h));
|
||||
}
|
||||
|
||||
/// Calculates a linear color's chromaticity.
|
||||
/// @param color Linear LDR color.
|
||||
/// @return Color's chromaticity.
|
||||
half3 aChromaticity(
|
||||
half3 color)
|
||||
{
|
||||
return color / max(aLuminance(color), A_EPSILON).rrr;
|
||||
}
|
||||
|
||||
/// Clamp HDR output to avoid excess bloom and blending errors.
|
||||
/// @param value Linear HDR value.
|
||||
/// @return Range-limited HDR color [0,32].
|
||||
half aHdrClamp(
|
||||
half value)
|
||||
{
|
||||
#if A_USE_HDR_CLAMP
|
||||
value = min(value, A_HDR_CLAMP_MAX_INTENSITY);
|
||||
#endif
|
||||
return value;
|
||||
}
|
||||
|
||||
/// Clamp HDR output to avoid excess bloom and blending errors.
|
||||
/// @param color Linear HDR color.
|
||||
/// @return Range-limited HDR color [0,32].
|
||||
half3 aHdrClamp(
|
||||
half3 color)
|
||||
{
|
||||
#if A_USE_HDR_CLAMP
|
||||
color = min(color, (A_HDR_CLAMP_MAX_INTENSITY).rrr);
|
||||
#endif
|
||||
return color;
|
||||
}
|
||||
|
||||
/// Clamp HDR output to avoid excess bloom and blending errors.
|
||||
/// @param color Linear HDR color.
|
||||
/// @return Range-limited HDR color [0,32].
|
||||
half4 aHdrClamp(
|
||||
half4 color)
|
||||
{
|
||||
#if A_USE_HDR_CLAMP
|
||||
color = min(color, (A_HDR_CLAMP_MAX_INTENSITY).rrrr);
|
||||
#endif
|
||||
return color;
|
||||
}
|
||||
|
||||
/// Used to calculate a rim light effect.
|
||||
/// @param weight Scales the intensity of the effect.
|
||||
/// @param bias Bias rim towards constant emission.
|
||||
/// @param power Rim falloff.
|
||||
/// @param NdotV Normal and view vector dot product.
|
||||
/// @return Rim lighting.
|
||||
half aRimLight(
|
||||
half weight,
|
||||
half bias,
|
||||
half power,
|
||||
half NdotV)
|
||||
{
|
||||
return weight * lerp(bias, 1.0h, pow(1.0h - NdotV, power));
|
||||
}
|
||||
|
||||
/// Gets distance from a point to an Axis-Aligned Bounding Box.
|
||||
/// @param p Starting point.
|
||||
/// @param aabbMin AABB min extents.
|
||||
/// @param aabbMax AABB max extents.
|
||||
/// @return Per-axis distance from AABB extents.
|
||||
half3 aDistanceFromAabb(
|
||||
half3 p,
|
||||
half3 aabbMin,
|
||||
half3 aabbMax)
|
||||
{
|
||||
return max(max(p - aabbMax, aabbMin - p), half3(0.0h, 0.0h, 0.0h));
|
||||
}
|
||||
|
||||
/// Applies four closest lights per-vertex using Alloy's attenuation.
|
||||
/// @param lightPosX Four lights' position X in world-space.
|
||||
/// @param lightPosY Four lights' position Y in world-space.
|
||||
/// @param lightPosZ Four lights' position Z in world-space.
|
||||
/// @param lightColor0 First light color.
|
||||
/// @param lightColor1 Second light color.
|
||||
/// @param lightColor2 Third light color.
|
||||
/// @param lightColor3 Fourth light color.
|
||||
/// @param lightAttenSq Four lights' Unity attenuation.
|
||||
/// @param positionWorld Position in world-space.
|
||||
/// @param normalWorld Normal in world-space.
|
||||
/// @return Per-vertex direct lighting.
|
||||
float3 aShade4PointLights(
|
||||
float4 lightPosX,
|
||||
float4 lightPosY,
|
||||
float4 lightPosZ,
|
||||
float3 lightColor0,
|
||||
float3 lightColor1,
|
||||
float3 lightColor2,
|
||||
float3 lightColor3,
|
||||
float4 lightAttenSq,
|
||||
float3 positionWorld,
|
||||
float3 normalWorld)
|
||||
{
|
||||
// to light vectors
|
||||
float4 toLightX = lightPosX - positionWorld.x;
|
||||
float4 toLightY = lightPosY - positionWorld.y;
|
||||
float4 toLightZ = lightPosZ - positionWorld.z;
|
||||
|
||||
// squared lengths
|
||||
float4 lengthSq = 0;
|
||||
lengthSq += toLightX * toLightX;
|
||||
lengthSq += toLightY * toLightY;
|
||||
lengthSq += toLightZ * toLightZ;
|
||||
|
||||
// NdotL
|
||||
float4 ndotl = 0;
|
||||
ndotl += toLightX * normalWorld.x;
|
||||
ndotl += toLightY * normalWorld.y;
|
||||
ndotl += toLightZ * normalWorld.z;
|
||||
|
||||
// correct NdotL
|
||||
float4 corr = rsqrt(lengthSq);
|
||||
ndotl = max (float4(0.0f, 0.0f, 0.0f, 0.0f), ndotl * corr);
|
||||
|
||||
// attenuation
|
||||
#if A_USE_UNITY_ATTENUATION
|
||||
float4 atten = 1.0 / (1.0 + lengthSq * lightAttenSq);
|
||||
#else
|
||||
// NOTE: Get something close to Alloy attenuation by undoing Unity's calculations.
|
||||
// http://forum.unity3d.com/threads/easiest-way-to-change-point-light-attenuation-with-deferred-path.254337/#post-1681835
|
||||
float4 invRangeSqr = lightAttenSq / 25.0f;
|
||||
|
||||
// Inverse Square attenuation, with light range falloff.
|
||||
// cf http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf p12
|
||||
float4 ratio2 = lengthSq * invRangeSqr;
|
||||
float4 num = saturate(float4(1.0f, 1.0f, 1.0f, 1.0f) - (ratio2 * ratio2));
|
||||
float4 atten = (num * num) / (lengthSq + float4(1.0f, 1.0f, 1.0f, 1.0f));
|
||||
#endif
|
||||
|
||||
float4 diff = ndotl * atten;
|
||||
|
||||
// final color
|
||||
float3 col = 0;
|
||||
col += lightColor0 * diff.x;
|
||||
col += lightColor1 * diff.y;
|
||||
col += lightColor2 * diff.z;
|
||||
col += lightColor3 * diff.w;
|
||||
return col;
|
||||
}
|
||||
|
||||
/// Applies four closest lights per-vertex using Alloy's attenuation.
|
||||
/// @param positionWorld Position in world-space.
|
||||
/// @param normalWorld Normal in world-space.
|
||||
/// @return Per-vertex direct lighting.
|
||||
float3 aShade4PointLights(
|
||||
float3 positionWorld,
|
||||
float3 normalWorld)
|
||||
{
|
||||
return aShade4PointLights(
|
||||
unity_4LightPosX0, unity_4LightPosY0, unity_4LightPosZ0,
|
||||
unity_LightColor[0].rgb, unity_LightColor[1].rgb, unity_LightColor[2].rgb, unity_LightColor[3].rgb,
|
||||
unity_4LightAtten0, positionWorld, normalWorld);
|
||||
}
|
||||
|
||||
#endif // ALLOY_SHADERS_FRAMEWORK_UTILITY_CGINC
|
||||
@@ -0,0 +1,6 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9bb275497f031324c95a6fd416e6d726
|
||||
ShaderImporter:
|
||||
defaultTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
@@ -0,0 +1,22 @@
|
||||
// Alloy Physical Shader Framework
|
||||
// Copyright 2013-2017 RUST LLC.
|
||||
// http://www.alloy.rustltd.com/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// @file Volumetric.cginc
|
||||
/// @brief Volumetric fog, light shafts, etc interfaces.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef ALLOY_SHADERS_FRAMEWORK_VOLUMETRIC_CGINC
|
||||
#define ALLOY_SHADERS_FRAMEWORK_VOLUMETRIC_CGINC
|
||||
|
||||
/// Volumetric effects for base passes.
|
||||
void aVolumetricBase(inout half4 color, ASurface s);
|
||||
|
||||
/// Volumetric effects for additive passes.
|
||||
void aVolumetricAdd(inout half4 color, ASurface s);
|
||||
|
||||
/// Volumetric effects for multiplicative passes.
|
||||
void aVolumetricMultiply(inout half4 color, ASurface s);
|
||||
|
||||
#endif // ALLOY_SHADERS_FRAMEWORK_VOLUMETRIC_CGINC
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0a3f6e1010e5ea94b9c9d8852f08fd1f
|
||||
timeCreated: 1496489792
|
||||
licenseType: Pro
|
||||
ShaderImporter:
|
||||
defaultTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,92 @@
|
||||
// Alloy Physical Shader Framework
|
||||
// Copyright 2013-2017 RUST LLC.
|
||||
// http://www.alloy.rustltd.com/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// @file Volumetric.cginc
|
||||
/// @brief Volumetric fog, light shafts, etc implementations.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef ALLOY_SHADERS_FRAMEWORK_VOLUMETRIC_IMPL_CGINC
|
||||
#define ALLOY_SHADERS_FRAMEWORK_VOLUMETRIC_IMPL_CGINC
|
||||
|
||||
#include "Assets/Alloy/Shaders/Config.cginc"
|
||||
#include "Assets/Alloy/Shaders/Framework/Volumetric.cginc"
|
||||
|
||||
#include "UnityShaderVariables.cginc"
|
||||
|
||||
#ifdef A_VOLUMETRIC_PASS
|
||||
#if defined(VAPOR_TRANSLUCENT_FOG_ON)
|
||||
#ifndef A_POSITION_WORLD_ON
|
||||
#define A_POSITION_WORLD_ON
|
||||
#endif
|
||||
#elif defined(VTRANSPARENCY_ON)
|
||||
#ifndef A_SCREEN_UV_ON
|
||||
#define A_SCREEN_UV_ON
|
||||
#endif
|
||||
|
||||
#ifndef A_VIEW_DEPTH_ON
|
||||
#define A_VIEW_DEPTH_ON
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(A_FOG_ON) && (defined(FOG_LINEAR) || defined(FOG_EXP) || defined(FOG_EXP2))
|
||||
#define A_FOG_ON
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void aVolumetricBase(
|
||||
inout half4 color,
|
||||
ASurface s)
|
||||
{
|
||||
#ifdef A_VOLUMETRIC_PASS
|
||||
UNITY_APPLY_FOG_COLOR(s.fogCoord, color, unity_FogColor);
|
||||
|
||||
#if defined(VAPOR_TRANSLUCENT_FOG_ON)
|
||||
color = VaporApplyFog(s.positionWorld, color);
|
||||
#elif defined(VTRANSPARENCY_ON)
|
||||
float4 data = s.screenPosition;
|
||||
|
||||
data.z = s.viewDepth;
|
||||
color = VolumetricTransparencyBase(color, data);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void aVolumetricAdd(
|
||||
inout half4 color,
|
||||
ASurface s)
|
||||
{
|
||||
#ifdef A_VOLUMETRIC_PASS
|
||||
UNITY_APPLY_FOG_COLOR(s.fogCoord, color, A_BLACK4);
|
||||
|
||||
#if defined(VAPOR_TRANSLUCENT_FOG_ON)
|
||||
color = VaporApplyFogAdd(s.positionWorld, color);
|
||||
#elif defined(VTRANSPARENCY_ON)
|
||||
float4 data = s.screenPosition;
|
||||
|
||||
data.z = s.viewDepth;
|
||||
color = VolumetricTransparencyAdd(color, data);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void aVolumetricMultiply(
|
||||
inout half4 color,
|
||||
ASurface s)
|
||||
{
|
||||
#ifdef A_VOLUMETRIC_PASS
|
||||
UNITY_APPLY_FOG_COLOR(s.fogCoord, color, A_WHITE4);
|
||||
|
||||
#if defined(VAPOR_TRANSLUCENT_FOG_ON)
|
||||
color = VaporApplyFogFade(s.positionWorld, color, A_WHITE);
|
||||
#elif defined(VTRANSPARENCY_ON)
|
||||
// float4 data = s.screenPosition;
|
||||
//
|
||||
// data.z = s.viewDepth;
|
||||
// color = VolumetricTransparencyAdd(color, data);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // ALLOY_SHADERS_FRAMEWORK_VOLUMETRIC_IMPL_CGINC
|
||||
@@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 185744146fc75a8458c2dc17f105132c
|
||||
timeCreated: 1496490406
|
||||
licenseType: Pro
|
||||
ShaderImporter:
|
||||
defaultTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user