Totally!
Vertex:
#include <defines_fs>
void toTangentFrame(const highp vec4 q, out highp vec3 n) {
n = vec3(0.0, 0.0, 1.0) +
vec3(2.0, -2.0, -2.0) * q.x * q.zwx +
vec3(2.0, 2.0, -2.0) * q.y * q.wzy;
}
void toTangentFrame(const highp vec4 q, out highp vec3 n, out highp vec3 t) {
toTangentFrame(q, n);
t = vec3(1.0, 0.0, 0.0) +
vec3(-2.0, 2.0, -2.0) * q.y * q.yxw +
vec3(-2.0, 2.0, 2.0) * q.z * q.zwx;
}
in vec4 T;
uniform vec3 uNdcOffset;
out Vertex
{
vec4 color;
mat3 tangentToWorld;
vec3 cameraToPixelTangentSpace;
vec3 worldSpacePos;
vec3 worldSpaceNormal;
vec4 worldSpaceTangent;
vec2 texCoord0;
flat int cameraIndex;
} oVert;
void main()
{
{ // Avoid duplicate variable defs
vec3 texcoord = TDInstanceTexCoord(uv[0]);
oVert.texCoord0.st = texcoord.st;
}
// First deform the vertex and normal
// TDDeform always returns values in world space
vec4 worldSpacePos = TDDeform(P);
vec3 uvUnwrapCoord = TDInstanceTexCoord(TDUVUnwrapCoord());
gl_Position = TDWorldToProj(worldSpacePos, uvUnwrapCoord);
gl_Position.xyz -= uNdcOffset;
// This is here to ensure we only execute lighting etc. code
// when we need it. If picking is active we don't need lighting, so
// this entire block of code will be ommited from the compile.
// The TD_PICKING_ACTIVE define will be set automatically when
// picking is active.
#ifndef TD_PICKING_ACTIVE
int cameraIndex = TDCameraIndex();
oVert.cameraIndex = cameraIndex;
oVert.worldSpacePos.xyz = worldSpacePos.xyz;
oVert.color = TDInstanceColor(Cd);
vec3 worldSpaceNorm = normalize(TDDeformNorm(N));
// oVert.worldSpaceNorm.xyz = worldSpaceNorm;
vec3 worldSpaceTangent = TDDeformNorm(T.xyz);
worldSpaceTangent.xyz = normalize(worldSpaceTangent.xyz);
// Create the matrix that will convert vectors and positions from
// tangent space to world space
// T.w contains the handedness of the tangent
// It will be used to flip the bi-normal if needed
mat3 tangentToWorld = TDCreateTBNMatrix(worldSpaceNorm, worldSpaceTangent, T.w);
oVert.tangentToWorld = tangentToWorld;
oVert.worldSpaceNormal = worldSpaceNorm;
oVert.worldSpaceTangent.xyz = worldSpaceTangent.xyz;
oVert.worldSpaceTangent.w = T.w;
#if defined(HEIGHT_LEVEL_MAP) || defined(HEIGHT_LEVEL_TOP)// if height level map is present, do parallax mapping.
vec4 cameraEye = uTDMats[cameraIndex].camInverse[3];
vec3 cameraToPixelTangentSpace = worldSpacePos.xyz - cameraEye.xyz;
oVert.cameraToPixelTangentSpace = inverse(tangentToWorld) * cameraToPixelTangentSpace;
#endif
// vec4 tangentSpaceNorm = worldSpaceNorm;
// vec3 tangentSpaceTangent = worldSpaceTangent;
// toTangentFrame(T, tangentSpaceNorm, tangentSpaceTangent.xyz);
#else // TD_PICKING_ACTIVE
// This will automatically write out the nessessary values
// for this shader to work with picking.
// See the documentation if you want to write custom values for picking.
TDWritePickingValues();
#endif // TD_PICKING_ACTIVE
// int x = gl_VertexID%1024;
// int y = gl_VertexID/1024;
// vec4 vtxDebug = vec4(vec3(worldSpaceTangent.xyz),1);
// imageStore( mTD2DArrayImageOutputs[0] , ivec3(x,y,1) , vtxDebug );
}
Fragment:
// user switches for development
#define DO_FILAMENT_LIGHTING
#define CUBE_SAMPLERS_EXIST
#define DO_CUBE_MIPMAPPING // if turning this off, the old atlas mipmap mode only works correctly with maps generated @ 256 size from cmgen.
// #define LIGHTS_FROM_TEXTURE // turn this on to use texelFetch() from img buffer for punctual lights.. slower though!
// define vertex block
in Vertex
{
vec4 color;
mat3 tangentToWorld;
vec3 cameraToPixelTangentSpace;
vec3 worldSpacePos;
vec3 worldSpaceNormal;
vec4 worldSpaceTangent;
vec2 texCoord0;
flat int cameraIndex;
} iVert;
#include <general_utils>
// define some things early.
vec4 DEBUG2;
vec4 DEBUG3;
vec3 normal;
vec3 clearcoatNormalMap;
vec2 screenCoord;
// make some defines. Filament uses some of these variables internally, so this is our
// way of passing in what it needs from TD variables / functions that already exist and work fine.
#include <defines_fs>
#ifdef CALC_PIXEL_BITANGENT
mat3 recalcualtedTangentToWorld = recalculated_bitangent( iVert.worldSpaceNormal , iVert.worldSpaceTangent );
#define shading_tangentToWorld recalcualtedTangentToWorld
#else
#define shading_tangentToWorld iVert.tangentToWorld
#endif
#define vertex_worldNormal iVert.tangentToWorld[2].xyz
#define vertex_worldPosition iVert.worldSpacePos.xyz
#define light_iblSpecular sLightIblMipMap
#define light_iblDFG sLightIblDFG
// define some Filament specific uniforms.
uniform sampler2D sLightIblMipMap;
uniform sampler2D sLightIblDFG;
uniform samplerCube sIblMip0;
uniform samplerCube sIblMip1;
uniform samplerCube sIblMip2;
uniform samplerCube sIblMip3;
uniform samplerCube sIblMip4;
uniform samplerCube sIblMip5;
uniform samplerCube sIblMip6;
uniform sampler2D sSsaoMap;
uniform sampler2D sPunctualBuffer;
// uniform sampler2D light_ssr;
uniform vec3 uSphericalHarmonics[9];
uniform float uIblRoughnessOneLevel;
uniform float uPunctualsBuffer[ FILA_LIGHT_BUFFER_LEN*NUM_FILA_LIGHTS ];
// define some other more general uniforms.
uniform float uBumpScale;
uniform vec4 uBaseColor;
uniform vec3 uEmission;
uniform float uMetallic;
uniform vec2 uRoughness;
uniform float uSpecularLevel;
uniform float uAmbientOcclusion;
uniform vec4 uParallaxSettings;
uniform bool uApplyCameraFog;
uniform bool uApplyemission;
uniform float uExposure;
uniform float uIblIlluminance;
uniform float uIblRotation;
uniform vec2 uAnisotropy;
uniform vec3 uSheenColor;
uniform float uSheenRoughness;
uniform vec3 uSubSurfaceColor;
uniform vec2 uSubSurfaceThickPower;
uniform vec3 uRefractionThickIor;
uniform vec4 uRefractionTransAbsorp;
// pull in other GLSL code modules from within TD.
#include <mipmap_utils>
#include <parallax_utils>
#include <lighting_utils>
#include <filament_utils>
layout(location = 0) out vec4 oFragColor;
#if TD_NUM_COLOR_BUFFERS > 1
layout(location = 1) out vec4 oFragDebug2;
#endif
#if TD_NUM_COLOR_BUFFERS > 1
layout(location = 2) out vec4 oFragDebug3;
#endif
void main()
{
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////// INITIAL SETUP /////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// This allows things such as order independent transparency
// and Dual-Paraboloid rendering to work properly
TDCheckDiscard();
vec2 texCoord0 = iVert.texCoord0.st;
vec2 texCoord0_parallaxed = iVert.texCoord0.st;
float primary_roughness = uRoughness.x;
float clearcoat_roughness = uRoughness.y;
screenCoord = gl_FragCoord.xy * uTDGeneral.viewport.zw;
DEBUG2 = vec4(0,0,0,1);
DEBUG3 = vec4(0,0,0,1);
vec4 outcol = vec4(0);
// important, this function is something we added to the filament_utils.glsl to manually inject our TD parameters into Filament's
// data structures.
#ifdef DO_FILAMENT_LIGHTING
TD_Filament_INIT();
#endif
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////// PARALLAX RELIEF MAPPING ////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#if defined(HEIGHT_LEVEL_MAP) || defined(HEIGHT_LEVEL_TOP)// if height level map or top is present, do parallax mapping.
vec2 parallaxedUVs = vec2(0);
// only apply the expensive parallax effect if the parallax scale is greater than 0.
if (uParallaxSettings.z > 0.0001){
#ifdef HEIGHT_LEVEL_MAP
parallaxedUVs.st = Parallax(HeightMapSampler, HeightMapSwizzleIndex, uParallaxSettings, iVert.cameraToPixelTangentSpace, texCoord0.st).xy;
#endif
#ifdef HEIGHT_LEVEL_TOP
// assumes swizzle index of 0 for texture streams.
parallaxedUVs.st = Parallax(HeightTopSampler, 0, uParallaxSettings, iVert.cameraToPixelTangentSpace, texCoord0.st).xy;
#endif
}
else{
parallaxedUVs.xy = texCoord0.xy;
}
texCoord0_parallaxed.xy = parallaxedUVs.xy;
#endif
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////// SAMPLE TEXTURE BLOBS /////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// conditionally sample from the blob samplers, if they are defined.
#ifdef BLOB_SAMPLER_0
vec4 blob0 = texture( sBlob0 , texCoord0_parallaxed );
#else
vec4 blob0 = vec4(0);
#endif
#ifdef BLOB_SAMPLER_1
vec4 blob1 = texture( sBlob1 , texCoord0_parallaxed );
#else
vec4 blob1 = vec4(0);
#endif
#ifdef BLOB_SAMPLER_2
vec4 blob2 = texture( sBlob2 , texCoord0_parallaxed );
#else
vec4 blob2 = vec4(0);
#endif
#ifdef BLOB_SAMPLER_3
vec4 blob3 = texture( sBlob3 , texCoord0_parallaxed );
#else
vec4 blob3 = vec4(0);
#endif
#ifdef BLOB_SAMPLER_4
vec4 blob4 = texture( sBlob4 , texCoord0_parallaxed );
#else
vec4 blob4 = vec4(0);
#endif
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////// SAMPLE TEXTURE STREAMS ////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#ifdef SINGLE_CHANNEL_TOPS
vec4 stream_singlechannels = texture( sStream_singlechannels , texCoord0_parallaxed );
#else
vec4 stream_singlechannels = vec4(1,1,1,1); // occlusion,rough,metal,specular
#endif
#ifdef BASE_COLOR_TOP
vec4 stream_basecolor = texture( sStream_basecolor , texCoord0_parallaxed );
#else
vec4 stream_basecolor = vec4(1,1,1,1); // rgb color, a=transparency
#endif
#ifdef EMIT_COLOR_TOP
vec3 stream_emitcolor = texture( sStream_emitcolor , texCoord0_parallaxed ).rgb;
#else
vec3 stream_emitcolor = vec3(0,0,0); // just rgb
#endif
#ifdef NORMAL_TOP
vec3 stream_normalmap = texture( sStream_normalmap , texCoord0_parallaxed ).xyz;
#else
vec3 stream_normalmap = vec3(0,0,1); // just xyz
#endif
#ifdef CLEARCOAT_NORMAL_TOP
vec3 stream_clearcoat_norm = texture( sStream_clearcoatnormalmap , texCoord0 ).xyz; // use unparallaxed coords for clearcoat.
#else
vec3 stream_clearcoat_norm = vec3(0,0,1);
#endif
#ifdef ANISOTROPY_TOP
vec2 stream_anisotropy = texture( sStream_anisotropymap , texCoord0_parallaxed ).xy;
#else
vec2 stream_anisotropy = vec2(0,1);
#endif
#ifdef SUBSURFACE_TOP
vec4 stream_subsurface = texture( sStream_subsurfacemap , texCoord0_parallaxed ).rgba;
#else
vec4 stream_subsurface = vec4(1);
#endif
#ifdef REFRACTTHICK_TOP
float stream_refractionthickness = texture( sStream_refractionthicknessmap , texCoord0_parallaxed ).r;
#else
float stream_refractionthickness = 1.0;
#endif
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////// SURFACE SHADING NORMALS ////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
shading_geometricNormal = iVert.tangentToWorld[2]; // since Filament needs shading_geometricNormal in some cases, setting it here.
#if defined(NORMAL_MAP) || defined(NORMAL_TOP) || defined(BASE_COLOR_TOP)
vec3 normalMap = vec3(0);
#ifdef NORMAL_MAP // this would be the static normals.
normalMap = Normalmaptexture;
#endif
#ifdef NORMAL_TOP // this would be dynamic realtime normals. TODO: give user option to blend this into base normal.
normalMap = stream_normalmap;
#endif
vec3 norm = (2.0 * (normalMap.xyz - 0.5)).xyz;
norm.xy = norm.xy * uBumpScale;
#else
vec3 norm = vec3(0,0,1);
#endif
normal = normalize(norm);
// Flip the normals on backfaces
if (!TDFrontFacing(iVert.worldSpacePos.xyz, shading_geometricNormal.xyz))
{
normal = -normal;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////// CLEAR COAT NORMALS //////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#if defined(MATERIAL_HAS_CLEAR_COAT) && defined(MATERIAL_HAS_CLEAR_COAT_NORMAL)
clearcoatNormalMap = vec3(0,0,1);
#ifdef CLEARCOAT_NORMAL_MAP
clearcoatNormalMap = Clearcoatnormalstexture;
#endif
#ifdef CLEARCOAT_NORMAL_TOP
clearcoatNormalMap = stream_clearcoat_norm;
#endif
clearcoatNormalMap = (2.0 * (clearcoatNormalMap.xyz - 0.5)).xyz; // remap to -1:1
#endif
clearcoatNormalMap = normalize(clearcoatNormalMap);
// Flip the normals on backfaces
if (!TDFrontFacing(iVert.worldSpacePos.xyz, shading_geometricNormal.xyz))
{
clearcoatNormalMap = -clearcoatNormalMap;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////// SPECULAR LEVEL ////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
float specularLevel = uSpecularLevel;
#ifdef SPEC_LEVEL_MAP
specularLevel = uSpecularLevel * Speculartexture;
#endif
#ifdef SPEC_LEVEL_TOP
specularLevel = uSpecularLevel * stream_singlechannels.a;
#endif
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////// METALLIC LEVEL ////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
float metallicLevel = uMetallic;
#ifdef METAL_LEVEL_MAP
metallicLevel = uMetallic * Metaltexture;
#endif
#ifdef METAL_LEVEL_TOP
metallicLevel = uMetallic * stream_singlechannels.b;
#endif
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////// ROUGHNESS LEVEL ///////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
float roughnessLevel = primary_roughness;
#ifdef ROUGH_LEVEL_MAP
roughnessLevel = primary_roughness * Roughnesstexture;
#endif
#ifdef ROUGH_LEVEL_TOP
roughnessLevel = primary_roughness * stream_singlechannels.g;
#endif
roughnessLevel = max(roughnessLevel, 0.0001); // A roughness of exactly 0 is not allowed
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////// AMBIENT OCCLUSION LEVEL ////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
float ambientOcclusionLevel = uAmbientOcclusion;
#ifdef AO_LEVEL_MAP
ambientOcclusionLevel = uAmbientOcclusion * Aomaptexture;
#endif
#ifdef AO_LEVEL_TOP
ambientOcclusionLevel = uAmbientOcclusion * stream_singlechannels.r;
#endif
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////// EMISSION COLOR ////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// always assume emit color from color picker is provided as sRGB
vec3 emitColor = srgb_to_linear(uEmission);
#ifdef EMIT_COLOR_MAP
emitColor = uEmission * Emitcolortexture.rgb;
#endif
#ifdef EMIT_COLOR_TOP
emitColor = uEmission * stream_emitcolor.rgb;
#endif
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////// BASE COLOR //////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// always assume base color from color picker is provided as sRGB
vec3 baseColor = srgb_to_linear(uBaseColor.rgb) * iVert.color.rgb;
#ifdef BASE_COLOR_MAP
baseColor *= Basecolortexture.rgb;
#endif
#ifdef BASE_COLOR_TOP
baseColor *= stream_basecolor.rgb;
#endif
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////// ANISOTROPY //////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
float anisotropy_strength = uAnisotropy.x;
vec2 anisotropy_vector = vec2(1,0);
#ifdef MATERIAL_HAS_ANISOTROPY
#if defined(ANISOTROPY_MAP) || defined(ANISOTROPY_TOP)
#ifdef ANISOTROPY_MAP
anisotropy_strength *= Anisotropytexture.x;
anisotropy_vector.xy = Anisotropytexture.yz;
#endif
#ifdef ANISOTROPY_TOP
anisotropy_strength *= stream_anisotropy.x;
anisotropy_vector.xy = Anisotropytexture.yz;
#endif
#else
float anisotropy_rotation_offset = uAnisotropy.y;
anisotropy_rotation_offset *= PI * 2; // remap 0-1 rotational range to 360 degrees in radians
anisotropy_vector = rotationMatrix2D(anisotropy_rotation_offset) * anisotropy_vector;
#endif
#endif
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////// SHEEN ////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
vec3 SheenColor = vec3(0);
float SheenRoughness = 1.0;
#if defined(MATERIAL_HAS_SHEEN_COLOR) && !defined(SHADING_MODEL_CLOTH)
SheenColor = uSheenColor;
SheenRoughness = uSheenRoughness;
#endif
#ifdef SHADING_MODEL_CLOTH
SheenColor = uSheenColor;
#endif
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////// SUB SURFACE /////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#ifdef SHADING_MODEL_CLOTH
#ifdef MATERIAL_HAS_SUBSURFACE_COLOR
// always assume subsurface from color picker is provided as sRGB
vec3 subSurface = srgb_to_linear(uSubSurfaceColor.rgb);
#endif
#endif
#ifdef SHADING_MODEL_SUBSURFACE
// always assume subsurface from color picker is provided as sRGB
// also multiply against base color, which can contain instance colors.
vec3 subSurface = srgb_to_linear(uSubSurfaceColor.rgb) * baseColor;
float subSurfaceThickness = uSubSurfaceThickPower.x;
float subSurfacePower = uSubSurfaceThickPower.y;
#ifdef SUBSURFACE_MAP
// overwrite subsurface scattering uniforms.
subSurface.rgb = Subsurfacetexture.rgb;
subSurfaceThickness = Subsurfacetexture.a;
#endif
#ifdef SUBSURFACE_TOP
// overwrite subsurface scattering uniforms.
subSurface.rgb = stream_subsurface.rgb;
subSurfaceThickness = stream_subsurface.a;
#endif
#endif
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////// REFRACTION /////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
float RefractionThickness = uRefractionThickIor.x;
float RefractionMicroThickness = uRefractionThickIor.y;
float RefractionIOR = uRefractionThickIor.z;
float RefractionTransmission = uRefractionTransAbsorp.x;
// always assume emit color from color picker is provided as sRGB
vec3 RefractionAbsorption = srgb_to_linear(uRefractionTransAbsorp.yzw);
#ifdef REFRACTTHICK_MAP
RefractionThickness *= Refractionthicknesstexture;
RefractionMicroThickness *= Refractionthicknesstexture;
#endif
#ifdef REFRACTTHICK_TOP
RefractionThickness *= stream_refractionthickness;
RefractionMicroThickness *= stream_refractionthickness;
#endif
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////// GOOGLE FILAMENT /////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#ifdef DO_FILAMENT_LIGHTING
// setting some tangent space normal information.
inputs.normal.xyz = norm;
// pass along the clear coat normals, if the top was plugged in / present.
#if defined(MATERIAL_HAS_CLEAR_COAT) && defined(MATERIAL_HAS_CLEAR_COAT_NORMAL)
inputs.clearCoatNormal.xyz = clearcoatNormalMap;
#endif
#ifdef MATERIAL_HAS_CLEAR_COAT
inputs.clearCoatRoughness = clearcoat_roughness;
#endif
material(inputs);
// overwrite some of the set parameters from our own params, from sampled textures etc.
// eventually need to clean this up so that things happen in a more understandable, modular way.
inputs.baseColor.rgb = vec3(baseColor);
inputs.ambientOcclusion = ambientOcclusionLevel;
inputs.roughness = roughnessLevel;
inputs.emissive.rgb = emitColor;
#if !defined(SHADING_MODEL_CLOTH) && !defined(SHADING_MODEL_SPECULAR_GLOSSINESS)
inputs.metallic = metallicLevel;
inputs.reflectance = specularLevel; // filament calls it reflectance, TD calls it specular level.
#endif
#ifdef MATERIAL_HAS_ANISOTROPY
inputs.anisotropy = anisotropy_strength;
inputs.anisotropyDirection = vec3(anisotropy_vector,0); // third component is always zero since we're defining in tangent space.
#endif
#if defined(MATERIAL_HAS_SHEEN_COLOR) && !defined(SHADING_MODEL_CLOTH) && !defined(SHADING_MODEL_SUBSURFACE)
inputs.sheenColor = SheenColor;
inputs.sheenRoughness = SheenRoughness;
#endif
#ifdef SHADING_MODEL_CLOTH
inputs.sheenColor = SheenColor;
#ifdef MATERIAL_HAS_SUBSURFACE_COLOR
inputs.subsurfaceColor = subSurface;
#endif
#endif
#ifdef SHADING_MODEL_SUBSURFACE
inputs.thickness = subSurfaceThickness;
inputs.subsurfacePower = subSurfacePower;
inputs.subsurfaceColor = subSurface;
#endif
#ifdef HAS_REFRACTION
#ifdef MATERIAL_HAS_ABSORPTION
inputs.absorption = RefractionAbsorption;
#endif
#ifdef MATERIAL_HAS_IOR
inputs.ior = RefractionIOR;
#endif
#ifdef MATERIAL_HAS_TRANSMISSION
inputs.transmission = RefractionTransmission;
#endif
#ifdef MATERIAL_HAS_THICKNESS
inputs.thickness = RefractionThickness;
#endif
#if defined(MATERIAL_HAS_MICRO_THICKNESS) && (REFRACTION_TYPE == REFRACTION_TYPE_THIN)
inputs.microThickness = RefractionMicroThickness;
#endif
#endif
// this call does all of the lighting work.
vec4 FilamentColor = evaluateMaterial(inputs);
outcol = FilamentColor;
#endif
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////// ALPHA CALCULATION ///////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// #if 0
float alpha = uBaseColor.a * iVert.color.a;
#ifdef ALPHA_LEVEL_MAP
alpha *= Basecolortexture.a;
#endif
#ifdef BASE_COLOR_TOP
alpha *= stream_basecolor.a;
#endif
outcol.rgb *= alpha;
// Modern GL removed the implicit alpha test, so we need to apply
// it manually here. This function does nothing if alpha test is disabled.
TDAlphaTest(alpha);
outcol.a = alpha;
// #endif
// DEBUG2.xy = screenCoord;
// DEBUG2.xyz = vertex_worldNormal;
// DEBUG2.xyz = iVert.worldSpaceTangent.xyz;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////// BUFFER OUTPUT /////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
oFragColor = TDOutputSwizzle(outcol);
//////////////////////////// DEBUGGING /////////////////////////////////////
#if TD_NUM_COLOR_BUFFERS > 1
oFragDebug2 = TDOutputSwizzle(vec4(vec3(DEBUG2.xyz),1));
#endif
#if TD_NUM_COLOR_BUFFERS > 2
oFragDebug3 = TDOutputSwizzle(vec4(vec3(DEBUG3.xyz),1));
#endif
}