Added terrain and basic terrain textures
This commit is contained in:
371
Assets/Filamented/FilamentShadingLit.cginc
Normal file
371
Assets/Filamented/FilamentShadingLit.cginc
Normal file
@ -0,0 +1,371 @@
|
||||
#ifndef FILAMENT_SHADING_LIT
|
||||
#define FILAMENT_SHADING_LIT
|
||||
|
||||
#include "FilamentMaterialInputs.cginc"
|
||||
#include "FilamentCommonMath.cginc"
|
||||
#include "FilamentCommonGraphics.cginc"
|
||||
#include "FilamentCommonLighting.cginc"
|
||||
#include "FilamentCommonMaterial.cginc"
|
||||
#include "FilamentCommonShading.cginc"
|
||||
|
||||
|
||||
#if defined(SHADING_MODEL_SUBSURFACE)
|
||||
#include "FilamentShadingSubsurface.cginc"
|
||||
#elif defined(SHADING_MODEL_CLOTH)
|
||||
#include "FilamentShadingCloth.cginc"
|
||||
#else
|
||||
#include "FilamentShadingStandard.cginc"
|
||||
#endif
|
||||
|
||||
#include "FilamentLightIndirect.cginc"
|
||||
#include "FilamentShadingLit.cginc"
|
||||
#include "FilamentLightDirectional.cginc"
|
||||
#include "FilamentLightPunctual.cginc"
|
||||
#include "FilamentLightLTCGI.cginc"
|
||||
|
||||
#include "UnityStandardInput.cginc"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Lighting
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#if defined(BLEND_MODE_MASKED)
|
||||
half computeMaskedAlpha(half a) {
|
||||
// Use derivatives to smooth alpha tested edges
|
||||
return (a - getMaskThreshold()) / max(fwidth(a), 1e-3) + 0.5;
|
||||
}
|
||||
|
||||
half computeDiffuseAlpha(half a) {
|
||||
// If we reach this point in the code, we already know that the fragment is not discarded due
|
||||
// to the threshold factor. Therefore we can just output 1.0, which prevents a "punch through"
|
||||
// effect from occuring. We do this only for TRANSLUCENT views in order to prevent breakage
|
||||
// of ALPHA_TO_COVERAGE.
|
||||
return (NEEDS_ALPHA_CHANNEL == 1.0) ? 1.0 : a;
|
||||
}
|
||||
|
||||
void applyAlphaMask(inout float4 baseColor) {
|
||||
baseColor.a = computeMaskedAlpha(baseColor.a);
|
||||
if (baseColor.a <= 0.0) {
|
||||
discard;
|
||||
}
|
||||
}
|
||||
|
||||
#else // not masked
|
||||
|
||||
float computeDiffuseAlpha(float a) {
|
||||
#if defined(BLEND_MODE_TRANSPARENT) || defined(BLEND_MODE_FADE)
|
||||
return a;
|
||||
#else
|
||||
return 1.0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void applyAlphaMask(inout float4 baseColor) {}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(GEOMETRIC_SPECULAR_AA)
|
||||
half normalFiltering(half perceptualRoughness, const half3 worldNormal) {
|
||||
// Kaplanyan 2016, "Stable specular highlights"
|
||||
// Tokuyoshi 2017, "Error Reduction and Simplification for Shading Anti-Aliasing"
|
||||
// Tokuyoshi and Kaplanyan 2019, "Improved Geometric Specular Antialiasing"
|
||||
|
||||
// This implementation is meant for deferred rendering in the original paper but
|
||||
// we use it in forward rendering as well (as discussed in Tokuyoshi and Kaplanyan
|
||||
// 2019). The main reason is that the forward version requires an expensive transform
|
||||
// of the half vector by the tangent frame for every light. This is therefore an
|
||||
// approximation but it works well enough for our needs and provides an improvement
|
||||
// over our original implementation based on Vlachos 2015, "Advanced VR Rendering".
|
||||
|
||||
half3 du = ddx(worldNormal);
|
||||
half3 dv = ddy(worldNormal);
|
||||
|
||||
half variance = _specularAntiAliasingVariance * (dot(du, du) + dot(dv, dv));
|
||||
|
||||
half roughness = perceptualRoughnessToRoughness(perceptualRoughness);
|
||||
half kernelRoughness = min(2.0 * variance, _specularAntiAliasingThreshold);
|
||||
half squareRoughness = saturate(roughness * roughness + kernelRoughness);
|
||||
|
||||
return roughnessToPerceptualRoughness(sqrt(squareRoughness));
|
||||
}
|
||||
#endif
|
||||
|
||||
void getCommonPixelParams(const MaterialInputs material, inout PixelParams pixel) {
|
||||
half4 baseColor = material.baseColor;
|
||||
applyAlphaMask(baseColor);
|
||||
|
||||
#if defined(BLEND_MODE_FADE) && !defined(SHADING_MODEL_UNLIT)
|
||||
// Since we work in premultiplied alpha mode, we need to un-premultiply
|
||||
// in fade mode so we can apply alpha to both the specular and diffuse
|
||||
// components at the end
|
||||
unpremultiply(baseColor);
|
||||
#endif
|
||||
|
||||
#if defined(SHADING_MODEL_SPECULAR_GLOSSINESS)
|
||||
// This is from KHR_materials_pbrSpecularGlossiness.
|
||||
half3 specularColor = material.specularColor;
|
||||
half metallic = computeMetallicFromSpecularColor(specularColor);
|
||||
|
||||
pixel.diffuseColor = computeDiffuseColor(baseColor, metallic);
|
||||
pixel.f0 = specularColor;
|
||||
#elif !defined(SHADING_MODEL_CLOTH)
|
||||
pixel.diffuseColor = computeDiffuseColor(baseColor, material.metallic);
|
||||
#if !defined(SHADING_MODEL_SUBSURFACE) && (!defined(MATERIAL_HAS_REFLECTANCE) && defined(MATERIAL_HAS_IOR))
|
||||
half reflectance = iorToF0(max(1.0, material.ior), 1.0);
|
||||
#else
|
||||
// Assumes an interface from air to an IOR of 1.5 for dielectrics
|
||||
half reflectance = computeDielectricF0(material.reflectance);
|
||||
#endif
|
||||
pixel.f0 = computeF0(baseColor, material.metallic, reflectance);
|
||||
#else
|
||||
pixel.diffuseColor = baseColor.rgb;
|
||||
pixel.f0 = material.sheenColor;
|
||||
#if defined(MATERIAL_HAS_SUBSURFACE_COLOR)
|
||||
pixel.subsurfaceColor = material.subsurfaceColor;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(SHADING_MODEL_CLOTH) && !defined(SHADING_MODEL_SUBSURFACE)
|
||||
#if defined(HAS_REFRACTION)
|
||||
// Air's Index of refraction is 1.000277 at STP but everybody uses 1.0
|
||||
const half airIor = 1.0;
|
||||
#if !defined(MATERIAL_HAS_IOR)
|
||||
// [common case] ior is not set in the material, deduce it from F0
|
||||
half materialor = f0ToIor(pixel.f0.g);
|
||||
#else
|
||||
// if ior is set in the material, use it (can lead to unrealistic materials)
|
||||
half materialor = max(1.0, material.ior);
|
||||
#endif
|
||||
pixel.etaIR = airIor / materialor; // air -> material
|
||||
pixel.etaRI = materialor / airIor; // material -> air
|
||||
#if defined(MATERIAL_HAS_TRANSMISSION)
|
||||
pixel.transmission = saturate(material.transmission);
|
||||
#else
|
||||
pixel.transmission = 1.0;
|
||||
#endif
|
||||
#if defined(MATERIAL_HAS_ABSORPTION)
|
||||
#if defined(MATERIAL_HAS_THICKNESS) || defined(MATERIAL_HAS_MICRO_THICKNESS)
|
||||
pixel.absorption = max(0.0, material.absorption);
|
||||
#else
|
||||
pixel.absorption = saturate(material.absorption);
|
||||
#endif
|
||||
#else
|
||||
pixel.absorption = 0.0;
|
||||
#endif
|
||||
#if defined(MATERIAL_HAS_THICKNESS)
|
||||
pixel.thickness = max(0.0, material.thickness);
|
||||
#endif
|
||||
#if defined(MATERIAL_HAS_MICRO_THICKNESS) && (REFRACTION_TYPE == REFRACTION_TYPE_THIN)
|
||||
pixel.uThickness = max(0.0, material.microThickness);
|
||||
#else
|
||||
pixel.uThickness = 0.0;
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void getSheenPixelParams(const ShadingParams shading, const MaterialInputs material, inout PixelParams pixel) {
|
||||
#if defined(MATERIAL_HAS_SHEEN_COLOR) && !defined(SHADING_MODEL_CLOTH) && !defined(SHADING_MODEL_SUBSURFACE)
|
||||
pixel.sheenColor = material.sheenColor;
|
||||
|
||||
half sheenPerceptualRoughness = material.sheenRoughness;
|
||||
sheenPerceptualRoughness = clamp(sheenPerceptualRoughness, MIN_PERCEPTUAL_ROUGHNESS, 1.0);
|
||||
|
||||
#if defined(GEOMETRIC_SPECULAR_AA)
|
||||
sheenPerceptualRoughness =
|
||||
normalFiltering(sheenPerceptualRoughness, shading.geometricNormal);
|
||||
#endif
|
||||
|
||||
pixel.sheenPerceptualRoughness = sheenPerceptualRoughness;
|
||||
pixel.sheenRoughness = perceptualRoughnessToRoughness(sheenPerceptualRoughness);
|
||||
#endif
|
||||
}
|
||||
|
||||
void getClearCoatPixelParams(const ShadingParams shading, const MaterialInputs material, inout PixelParams pixel) {
|
||||
#if defined(MATERIAL_HAS_CLEAR_COAT)
|
||||
pixel.clearCoat = material.clearCoat;
|
||||
|
||||
// Clamp the clear coat roughness to avoid divisions by 0
|
||||
half clearCoatPerceptualRoughness = material.clearCoatRoughness;
|
||||
clearCoatPerceptualRoughness =
|
||||
clamp(clearCoatPerceptualRoughness, MIN_PERCEPTUAL_ROUGHNESS, 1.0);
|
||||
|
||||
#if defined(GEOMETRIC_SPECULAR_AA)
|
||||
clearCoatPerceptualRoughness =
|
||||
normalFiltering(clearCoatPerceptualRoughness, shading.geometricNormal);
|
||||
#endif
|
||||
|
||||
pixel.clearCoatPerceptualRoughness = clearCoatPerceptualRoughness;
|
||||
pixel.clearCoatRoughness = perceptualRoughnessToRoughness(clearCoatPerceptualRoughness);
|
||||
|
||||
#if defined(CLEAR_COAT_IOR_CHANGE)
|
||||
// The base layer's f0 is computed assuming an interface from air to an IOR
|
||||
// of 1.5, but the clear coat layer forms an interface from IOR 1.5 to IOR
|
||||
// 1.5. We recompute f0 by first computing its IOR, then reconverting to f0
|
||||
// by using the correct interface
|
||||
pixel.f0 = lerp(pixel.f0, f0ClearCoatToSurface(pixel.f0), pixel.clearCoat);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void getRoughnessPixelParams(const ShadingParams shading, const MaterialInputs material, inout PixelParams pixel) {
|
||||
#if defined(SHADING_MODEL_SPECULAR_GLOSSINESS)
|
||||
half perceptualRoughness = computeRoughnessFromGlossiness(material.glossiness);
|
||||
#else
|
||||
half perceptualRoughness = material.roughness;
|
||||
#endif
|
||||
|
||||
// This is used by the refraction code and must be saved before we apply specular AA
|
||||
pixel.perceptualRoughnessUnclamped = perceptualRoughness;
|
||||
|
||||
#if defined(GEOMETRIC_SPECULAR_AA)
|
||||
perceptualRoughness = normalFiltering(perceptualRoughness, shading.geometricNormal);
|
||||
#endif
|
||||
|
||||
#if defined(MATERIAL_HAS_CLEAR_COAT) && defined(MATERIAL_HAS_CLEAR_COAT_ROUGHNESS)
|
||||
// This is a hack but it will do: the base layer must be at least as rough
|
||||
// as the clear coat layer to take into account possible diffusion by the
|
||||
// top layer
|
||||
half basePerceptualRoughness = max(perceptualRoughness, pixel.clearCoatPerceptualRoughness);
|
||||
perceptualRoughness = lerp(perceptualRoughness, basePerceptualRoughness, pixel.clearCoat);
|
||||
#endif
|
||||
|
||||
// Clamp the roughness to a minimum value to avoid divisions by 0 during lighting
|
||||
pixel.perceptualRoughness = clamp(perceptualRoughness, MIN_PERCEPTUAL_ROUGHNESS, 1.0);
|
||||
// Remaps the roughness to a perceptually linear roughness (roughness^2)
|
||||
pixel.roughness = perceptualRoughnessToRoughness(pixel.perceptualRoughness);
|
||||
}
|
||||
|
||||
void getSubsurfacePixelParams(const MaterialInputs material, inout PixelParams pixel) {
|
||||
#if defined(SHADING_MODEL_SUBSURFACE)
|
||||
pixel.subsurfacePower = material.subsurfacePower;
|
||||
pixel.subsurfaceColor = material.subsurfaceColor;
|
||||
pixel.thickness = saturate(material.thickness);
|
||||
#endif
|
||||
}
|
||||
|
||||
void getAnisotropyPixelParams(const ShadingParams shading, const MaterialInputs material, inout PixelParams pixel) {
|
||||
#if defined(MATERIAL_HAS_ANISOTROPY)
|
||||
half3 direction = material.anisotropyDirection;
|
||||
pixel.anisotropy = material.anisotropy;
|
||||
pixel.anisotropicT = normalize(mul(shading.tangentToWorld, direction));
|
||||
pixel.anisotropicB = normalize(cross(shading.geometricNormal, pixel.anisotropicT));
|
||||
#endif
|
||||
}
|
||||
|
||||
void getEnergyCompensationPixelParams(const ShadingParams shading, inout PixelParams pixel) {
|
||||
// Pre-filtered DFG term used for image-based lighting
|
||||
pixel.dfg = prefilteredDFG(pixel.perceptualRoughness, shading.NoV);
|
||||
|
||||
#if !defined(SHADING_MODEL_CLOTH)
|
||||
// Energy compensation for multiple scattering in a microfacet model
|
||||
// See "Multiple-Scattering Microfacet BSDFs with the Smith Model"
|
||||
pixel.energyCompensation = 1.0 + pixel.f0 * (1.0 / pixel.dfg.yyy - 1.0);
|
||||
#else
|
||||
pixel.energyCompensation = (1.0);
|
||||
#endif
|
||||
|
||||
#if !defined(SHADING_MODEL_CLOTH)
|
||||
#if defined(MATERIAL_HAS_SHEEN_COLOR)
|
||||
pixel.sheenDFG = prefilteredDFG(pixel.sheenPerceptualRoughness, shading.NoV).z;
|
||||
pixel.sheenScaling = 1.0 - max3(pixel.sheenColor) * pixel.sheenDFG;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void geGlintPixelParams(const ShadingParams shading, const MaterialInputs material, inout PixelParams pixel) {
|
||||
#if defined(MATERIAL_HAS_GLINT)
|
||||
pixel.uv = material.uv;
|
||||
pixel.ddx_uv = ddx(material.uv);
|
||||
pixel.ddy_uv = ddy(material.uv);
|
||||
pixel.glintAlpha = material.glintAlpha;
|
||||
pixel.glintDensity = material.glintDensity;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes all the parameters required to shade the current pixel/fragment.
|
||||
* These parameters are derived from the MaterialInputs structure computed
|
||||
* by the user's material code.
|
||||
*
|
||||
* This function is also responsible for discarding the fragment when alpha
|
||||
* testing fails.
|
||||
*/
|
||||
void getPixelParams(const ShadingParams shading, const MaterialInputs material, out PixelParams pixel) {
|
||||
pixel = (PixelParams)0;
|
||||
getCommonPixelParams(material, pixel);
|
||||
getSheenPixelParams(shading, material, pixel);
|
||||
getClearCoatPixelParams(shading, material, pixel);
|
||||
getRoughnessPixelParams(shading, material, pixel);
|
||||
getSubsurfacePixelParams(material, pixel);
|
||||
getAnisotropyPixelParams(shading, material, pixel);
|
||||
geGlintPixelParams(shading, material, pixel);
|
||||
getEnergyCompensationPixelParams(shading, pixel);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function evaluates all lights one by one:
|
||||
* - Image based lights (IBL)
|
||||
* - Directional lights
|
||||
* - Punctual lights
|
||||
*
|
||||
* Area lights are currently not supported.
|
||||
*
|
||||
* Returns a pre-exposed HDR RGBA color in linear space.
|
||||
*/
|
||||
half4 evaluateLights(const ShadingParams shading, const MaterialInputs material) {
|
||||
PixelParams pixel;
|
||||
getPixelParams(shading, material, pixel);
|
||||
|
||||
// Ideally we would keep the diffuse and specular components separate
|
||||
// until the very end but it costs more ALUs on mobile. The gains are
|
||||
// currently not worth the extra operations
|
||||
half3 color = 0.0;
|
||||
|
||||
// We always evaluate the IBL as not having one is going to be uncommon,
|
||||
// it also saves 1 shader variant
|
||||
#if defined(UNITY_PASS_FORWARDBASE)
|
||||
evaluateIBL(shading, material, pixel, color);
|
||||
#endif
|
||||
|
||||
#if defined(HAS_DIRECTIONAL_LIGHTING)
|
||||
evaluateDirectionalLight(shading, material, pixel, color);
|
||||
#endif
|
||||
|
||||
#if defined(HAS_DYNAMIC_LIGHTING)
|
||||
evaluatePunctualLights(shading, pixel, color);
|
||||
#endif
|
||||
|
||||
#if defined(BLEND_MODE_FADE) && !defined(SHADING_MODEL_UNLIT)
|
||||
// In fade mode we un-premultiply baseColor early on, so we need to
|
||||
// premultiply again at the end (affects diffuse and specular lighting)
|
||||
color *= material.baseColor.a;
|
||||
#endif
|
||||
|
||||
return half4(color, computeDiffuseAlpha(material.baseColor.a));
|
||||
}
|
||||
|
||||
void addEmissive(const MaterialInputs material, inout half4 color) {
|
||||
#if defined(MATERIAL_HAS_EMISSIVE)
|
||||
float4 emissive = material.emissive;
|
||||
//float attenuation = lerp(1.0, frameUniforms.exposure, emissive.w);
|
||||
// Exposure not supported yet
|
||||
float attenuation = emissive.w;
|
||||
color.rgb += emissive.rgb * (attenuation * color.a);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate lit materials. The actual shading model used to do so is defined
|
||||
* by the function surfaceShading() found in shading_model_*.fs.
|
||||
*
|
||||
* Returns a pre-exposed HDR RGBA color in linear space.
|
||||
*/
|
||||
half4 evaluateMaterial(const ShadingParams shading, const MaterialInputs material) {
|
||||
half4 color = evaluateLights(shading, material);
|
||||
addEmissive(material, color);
|
||||
return color;
|
||||
}
|
||||
|
||||
#endif // FILAMENT_SHADING_LIT
|
||||
Reference in New Issue
Block a user