mirror of
https://github.com/muskit/H3VR-TNH-Quality-of-Life-Improvements.git
synced 2026-06-02 20:24:26 -07:00
Initial commit
This commit is contained in:
@@ -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
|
||||
Reference in New Issue
Block a user