Skip to content

Instantly share code, notes, and snippets.

@hzqst
Created October 22, 2022 03:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hzqst/a0b0a6e5de86e41a596cba4d47a435dc to your computer and use it in GitHub Desktop.
Save hzqst/a0b0a6e5de86e41a596cba4d47a435dc to your computer and use it in GitHub Desktop.
#version 430
#define DIFFUSE_ENABLED
#define LIGHTMAP_ENABLED
#define GBUFFER_ENABLED
#define BINDLESS_ENABLED
#define SHADOW_TEXTURE_OFFSET (1.0 / 4096.0)
#define IS_FRAGMENT_SHADER
#extension GL_EXT_texture_array : require
#extension GL_EXT_gpu_shader4 : require
#ifdef BINDLESS_ENABLED
#extension GL_ARB_shader_draw_parameters : require
#endif
#ifdef BINDLESS_ENABLED
#ifdef UINT64_ENABLED
#extension GL_NV_bindless_texture : require
#extension GL_NV_gpu_shader5 : require
#else
#extension GL_ARB_bindless_texture : require
#endif
#endif
#if defined(OIT_ALPHA_BLEND_ENABLED) || defined(OIT_ADDITIVE_BLEND_ENABLED)
#ifdef IS_FRAGMENT_SHADER
// See https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_shader_image_load_store.txt
#extension GL_ARB_shader_image_load_store : require
// See https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_fragment_shader_interlock.txt
#extension GL_ARB_fragment_shader_interlock : require
// Use early z-test to cull transparent fragments occluded by opaque fragments.
// Additionaly, use fragment interlock.
layout(early_fragment_tests) in;
// gl_FragCoord will be used for pixel centers at integer coordinates.
// See https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/gl_FragCoord.xhtml
layout(pixel_center_integer) in vec4 gl_FragCoord;
#define MAX_NUM_NODES 16
#endif
#endif
#if defined(UINT64_ENABLED)
#define texture_handle_t uint64_t
#else
#define texture_handle_t uvec2
#endif
#define TEXTURE_SSBO_DIFFUSE 0
#define TEXTURE_SSBO_REPLACE 1
#define TEXTURE_SSBO_DETAIL 2
#define TEXTURE_SSBO_NORMAL 3
#define TEXTURE_SSBO_PARALLAX 4
#define TEXTURE_SSBO_SPECULAR 5
#define TEXTURE_SSBO_MAX 6
#define TEXTURE_SSBO_WATER_BASE 0
#define TEXTURE_SSBO_WATER_NORMAL 1
#define TEXTURE_SSBO_WATER_REFLECT 2
#define TEXTURE_SSBO_WATER_REFRACT 3
#define TEXTURE_SSBO_WATER_DEPTH 4
#define BINDING_POINT_SCENE_UBO 0
#define BINDING_POINT_SKYBOX_SSBO 1
#define BINDING_POINT_DECAL_SSBO 1
#define BINDING_POINT_TEXTURE_SSBO 1
#define BINDING_POINT_ENTITY_UBO 2
#define BINDING_POINT_STUDIO_UBO 2
#define BINDING_POINT_OIT_FRAGMENT_SSBO 3
#define BINDING_POINT_OIT_NUMFRAGMENT_SSBO 4
#define BINDING_POINT_OIT_COUNTER_SSBO 5
#define WSURF_DIFFUSE_TEXTURE 0
#define WSURF_REPLACE_TEXTURE 1
#define WSURF_DETAIL_TEXTURE 2
#define WSURF_NORMAL_TEXTURE 3
#define WSURF_PARALLAX_TEXTURE 4
#define WSURF_SPECULAR_TEXTURE 5
#define WSURF_MAX_TEXTURE 6
#define SPR_VP_PARALLEL_UPRIGHT 0
#define SPR_FACING_UPRIGHT 1
#define SPR_VP_PARALLEL 2
#define SPR_ORIENTED 3
#define SPR_VP_PARALLEL_ORIENTED 4
struct scene_ubo_t{
mat4 viewMatrix;
mat4 projMatrix;
mat4 invViewMatrix;
mat4 invProjMatrix;
mat4 shadowMatrix[3];
uvec4 viewport;
vec4 frustumpos[4];
vec4 viewpos;
vec4 vpn;
vec4 vright;
vec4 vup;
vec4 shadowDirection;
vec4 shadowColor;
vec4 shadowFade;
vec4 clipPlane;
vec4 fogColor;
float fogStart;
float fogEnd;
float fogDensity;
float time;
float r_g;
float r_g3;
float v_brightness;
float v_lightgamma;
float v_lambert;
float v_gamma;
float v_texgamma;
float z_near;
float z_far;
float r_alpha_shift;
float r_additive_shift;
float padding;
};
struct entity_ubo_t{
mat4 entityMatrix;
vec4 color;
float scrollSpeed;
};
struct studio_ubo_t{
float r_ambientlight;
float r_shadelight;
float r_blend;
float r_scale;
vec4 r_plightvec;
vec4 r_colormix;
vec4 r_origin;
vec4 entity_origin;
mat3x4 bonematrix[128];
};
//Scene level
layout (std140, binding = BINDING_POINT_SCENE_UBO) uniform SceneBlock
{
scene_ubo_t SceneUBO;
};
#if defined(BINDLESS_ENABLED)
layout (std430, binding = BINDING_POINT_DECAL_SSBO) coherent buffer DecalBlock
{
texture_handle_t DecalSSBO[];
};
layout (std430, binding = BINDING_POINT_SKYBOX_SSBO) coherent buffer SkyboxBlock
{
texture_handle_t SkyboxSSBO[];
};
#endif
//Entity level
layout (std140, binding = BINDING_POINT_ENTITY_UBO) uniform EntityBlock
{
entity_ubo_t EntityUBO;
};
#if defined(BINDLESS_ENABLED)
layout (std430, binding = BINDING_POINT_TEXTURE_SSBO) coherent buffer TextureBlock
{
texture_handle_t TextureSSBO[];
};
#endif
layout (std140, binding = BINDING_POINT_STUDIO_UBO) uniform StudioBlock
{
studio_ubo_t StudioUBO;
};
#if defined(OIT_ALPHA_BLEND_ENABLED) || defined(OIT_ADDITIVE_BLEND_ENABLED)
// A fragment node stores rendering information about one specific fragment
struct FragmentNode
{
// RGBA color of the node
uint color;
// Depth value of the fragment (in view space)
float depth;
// The index of the next node in "nodes" array
uint next;
};
// Fragment-and-link buffer (linked list). Stores "nodesPerPixel" number of fragments.
layout (std430, binding = BINDING_POINT_OIT_FRAGMENT_SSBO) coherent buffer FragmentNodes
{
FragmentNode nodes[];
};
// Start-offset buffer (mapping pixels to first pixel in the buffer) of size viewportW*viewportH.
layout (std430, binding = BINDING_POINT_OIT_NUMFRAGMENT_SSBO) coherent buffer NumFragmentsBuffer
{
uint numFragments[];
};
layout(binding = BINDING_POINT_OIT_COUNTER_SSBO, offset = 0) uniform atomic_uint fragCounter;
#ifdef IS_FRAGMENT_SHADER
void GatherFragment(inout vec4 color)
{
uint x = uint(gl_FragCoord.x);
uint y = uint(gl_FragCoord.y);
uint viewportW = SceneUBO.viewport.x;
uint linkedListSize = SceneUBO.viewport.z;
uint pixelIndex = viewportW*y + x;
FragmentNode frag;
frag.color = packUnorm4x8(color);
#ifdef OIT_ADDITIVE_BLEND_ENABLED
frag.depth = -gl_FragCoord.z;
#else
frag.depth = gl_FragCoord.z;
#endif
frag.next = -1;
uint insertIndex = atomicCounterIncrement(fragCounter);
if (insertIndex < linkedListSize) {
// Insert the fragment into the linked list
frag.next = atomicExchange(numFragments[pixelIndex], insertIndex);
nodes[insertIndex] = frag;
}
discard;
}
#endif
#endif
vec2 UnitVectorToHemiOctahedron(vec3 dir) {
dir.y = max(dir.y, 0.0001);
dir.xz /= dot(abs(dir), vec3(1.0));
return clamp(0.5 * vec2(dir.x + dir.z, dir.x - dir.z) + 0.5, 0.0, 1.0);
}
vec3 HemiOctahedronToUnitVector(vec2 coord) {
coord = 2.0 * coord - 1.0;
coord = 0.5 * vec2(coord.x + coord.y, coord.x - coord.y);
float y = 1.0 - dot(vec2(1.0), abs(coord));
return normalize(vec3(coord.x, y + 0.0001, coord.y));
}
vec2 UnitVectorToOctahedron(vec3 dir) {
dir.xz /= dot(abs(dir), vec3(1.0));
// Lower hemisphere
if (dir.y < 0.0) {
vec2 orig = dir.xz;
dir.x = (orig.x >= 0.0 ? 1.0 : -1.0) * (1.0 - abs(orig.y));
dir.z = (orig.y >= 0.0 ? 1.0 : -1.0) * (1.0 - abs(orig.x));
}
return clamp(0.5 * vec2(dir.x, dir.z) + 0.5, 0.0, 1.0);
}
vec3 OctahedronToUnitVector(vec2 coord) {
coord = 2.0 * coord - 1.0;
float y = 1.0 - dot(abs(coord), vec2(1.0));
// Lower hemisphere
if (y < 0.0) {
vec2 orig = coord;
coord.x = (orig.x >= 0.0 ? 1.0 : -1.0) * (1.0 - abs(orig.y));
coord.y = (orig.y >= 0.0 ? 1.0 : -1.0) * (1.0 - abs(orig.x));
}
return normalize(vec3(coord.x, y + 0.0001, coord.y));
}
#if defined(LINEAR_FOG_ENABLED) && defined(IS_FRAGMENT_SHADER)
vec4 CalcFogWithDistance(vec4 color, float z)
{
float fogFactor = ( SceneUBO.fogEnd - z ) / ( SceneUBO.fogEnd - SceneUBO.fogStart );
fogFactor = clamp(fogFactor, 0.0, 1.0);
color.xyz = mix(SceneUBO.fogColor.xyz, color.xyz, fogFactor );
return color;
}
vec4 CalcFog(vec4 color)
{
return CalcFogWithDistance(color, gl_FragCoord.z / gl_FragCoord.w);
}
#elif defined(EXP_FOG_ENABLED) && defined(IS_FRAGMENT_SHADER)
vec4 CalcFogWithDistance(vec4 color, float z)
{
float f = SceneUBO.fogDensity * z;
float fogFactor = exp( -f );
fogFactor = clamp(fogFactor, 0.0, 1.0);
color.xyz = mix(SceneUBO.fogColor.xyz, color.xyz, fogFactor );
return color;
}
vec4 CalcFog(vec4 color)
{
return CalcFogWithDistance(color, gl_FragCoord.z / gl_FragCoord.w);
}
#elif defined(EXP2_FOG_ENABLED) && defined(IS_FRAGMENT_SHADER)
vec4 CalcFogWithDistance(vec4 color, float z)
{
//const float LOG2 = 1.442695;
//float fogFactor = exp2( -SceneUBO.fogDensity * SceneUBO.fogDensity * z * z * LOG2 );
float f = SceneUBO.fogDensity * z / 1.8;
float fogFactor = exp(-f*f);
fogFactor = clamp(fogFactor, 0.0, 1.0);
color.xyz = mix(SceneUBO.fogColor.xyz, color.xyz, fogFactor );
return color;
}
vec4 CalcFog(vec4 color)
{
return CalcFogWithDistance(color, gl_FragCoord.z / gl_FragCoord.w);
}
#else
vec4 CalcFog(vec4 color)
{
return color;
}
vec4 CalcFogWithDistance(vec4 color, float z)
{
return color;
}
#endif
vec4 GammaToLinear(vec4 color)
{
color.rgb = pow(color.rgb, vec3(SceneUBO.v_gamma));
return color;
}
vec4 TexGammaToLinear(vec4 color)
{
color.rgb = pow(color.rgb, vec3(SceneUBO.v_texgamma));
return color;
}
//This was being applied for GL_Upload16
vec4 TexGammaToGamma(vec4 color)
{
color.rgb = pow(color.rgb, vec3(SceneUBO.v_texgamma * SceneUBO.r_g));//r_g = 1.0 / v_gamma
return color;
}
vec4 LinearToGamma(vec4 color)
{
color.rgb = pow(color.rgb, vec3(SceneUBO.r_g));//r_g = 1.0 / v_gamma
return color;
}
vec3 LinearToGamma3(vec3 color)
{
color.rgb = pow(color.rgb, vec3(SceneUBO.r_g));//r_g = 1.0 / v_gamma
return color;
}
//This was being applied for R_BuildLightMap and R_StudioLighting
float LightGammaToGammaInternal(float color)
{
float fv = pow(color, SceneUBO.v_lightgamma);
fv = fv * max(SceneUBO.v_brightness, 1.0);
//if (fv > SceneUBO.r_g3)
float fv1 = 0.125 + ((fv - SceneUBO.r_g3) / (1.0 - SceneUBO.r_g3)) * 0.875;
//else
float fv2 = (fv / SceneUBO.r_g3) * 0.125;
fv = clamp(fv1, fv2, step(fv, SceneUBO.r_g3));
return clamp(pow( fv, SceneUBO.r_g ), 0.0, 1.0);
}
vec4 LightGammaToGamma(vec4 color)
{
return vec4(LightGammaToGammaInternal(color.r), LightGammaToGammaInternal(color.g), LightGammaToGammaInternal(color.b), color.a);
}
float LightGammaToLinearInternal(float color)
{
float fv = pow(color, SceneUBO.v_lightgamma);
fv = fv * max(SceneUBO.v_brightness, 1.0);
fv = mix(
0.125 + ((fv - SceneUBO.r_g3) / (1.0 - SceneUBO.r_g3)) * 0.875,
(fv / SceneUBO.r_g3) * 0.125,
step(fv, SceneUBO.r_g3));
/*if (fv > SceneUBO.r_g3)
fv = 0.125 + ((fv - SceneUBO.r_g3) / (1.0 - SceneUBO.r_g3)) * 0.875;
else
fv = (fv / SceneUBO.r_g3) * 0.125;*/
return clamp(fv, 0.0, 1.0);
}
vec4 LightGammaToLinear(vec4 color)
{
return vec4(LightGammaToLinearInternal(color.r), LightGammaToLinearInternal(color.g), LightGammaToLinearInternal(color.b), color.a);
}
#if defined(IS_FRAGMENT_SHADER)
void ClipPlaneTest(vec3 worldpos, vec3 normal)
{
#if defined(CLIP_WATER_ENABLED)
vec4 clipVec = vec4(worldpos.xyz, 1.0);
vec4 clipPlane = SceneUBO.clipPlane;
if(dot(clipVec, clipPlane) < 0)
discard;
clipPlane.w += 32.0;
if(dot(clipVec, clipPlane) < 0 && dot(normalize(normal.xyz), -clipPlane.xyz) > 0.866)
discard;
#elif defined(CLIP_ENABLED)
vec4 clipVec = vec4(worldpos.xyz - SceneUBO.clipPlane.xyz * 4.0, -1.0);
vec4 clipPlane = SceneUBO.clipPlane;
if(dot(clipVec, clipPlane) > 0)
discard;
#endif
}
#else
void ClipPlaneTest(vec3 worldpos, vec3 normal)
{
}
#endif
uniform float u_parallaxScale;
#ifndef BINDLESS_ENABLED
layout(binding = 0) uniform sampler2D diffuseTex;
layout(binding = 1) uniform sampler2DArray lightmapTexArray;
layout(binding = 2) uniform sampler2D detailTex;
layout(binding = 3) uniform sampler2D normalTex;
layout(binding = 4) uniform sampler2D parallaxTex;
layout(binding = 5) uniform sampler2D specularTex;
layout(binding = 6) uniform sampler2DArray shadowmapTexArray;
#else
layout(binding = 1) uniform sampler2DArray lightmapTexArray;
layout(binding = 6) uniform sampler2DArray shadowmapTexArray;
#endif
in vec3 v_worldpos;
in vec3 v_normal;
in vec3 v_tangent;
in vec3 v_bitangent;
in vec2 v_diffusetexcoord;
in vec3 v_lightmaptexcoord;
in vec2 v_replacetexcoord;
in vec2 v_detailtexcoord;
in vec2 v_normaltexcoord;
in vec2 v_parallaxtexcoord;
in vec2 v_speculartexcoord;
in vec4 v_shadowcoord[3];
#ifdef BINDLESS_ENABLED
#if defined(SKYBOX_ENABLED)
flat in int v_drawid;
#elif defined(DECAL_ENABLED)
flat in int v_decalindex;
#else
flat in int v_texindex;
#endif
#endif
#ifdef GBUFFER_ENABLED
#if defined(DECAL_ENABLED)
//Decal only affects diffuse and worldnorm channel
layout(location = 0) out vec4 out_Diffuse;
layout(location = 1) out vec4 out_WorldNorm;
#else
layout(location = 0) out vec4 out_Diffuse;
layout(location = 1) out vec4 out_Lightmap;
layout(location = 2) out vec4 out_WorldNorm;
layout(location = 3) out vec4 out_Specular;
layout(location = 4) out vec4 out_Additive;
#endif
#else
layout(location = 0) out vec4 out_Diffuse;
#endif
#ifdef BINDLESS_ENABLED
texture_handle_t GetCurrentTextureHandle(int type)
{
#if defined(SKYBOX_ENABLED)
return SkyboxSSBO[v_drawid];
#elif defined(DECAL_ENABLED)
return DecalSSBO[v_decalindex * TEXTURE_SSBO_MAX + type];
#else
return TextureSSBO[v_texindex * TEXTURE_SSBO_MAX + type];
#endif
}
#endif
#ifdef NORMALTEXTURE_ENABLED
vec3 NormalMapping(vec3 T, vec3 B, vec3 N, vec2 baseTexcoord)
{
#ifdef BINDLESS_ENABLED
sampler2D normalTex = sampler2D(GetCurrentTextureHandle(TEXTURE_SSBO_NORMAL));
#endif
// Create TBN matrix. from tangent to world space
mat3 TBN = mat3(normalize(T), normalize(B), normalize(N));
vec2 vNormTexcoord = vec2(baseTexcoord.x * v_normaltexcoord.x, baseTexcoord.y * v_normaltexcoord.y);
// Sample tangent space normal vector from normal map and remap it from [0, 1] to [-1, 1] range.
vec3 n = texture2D(normalTex, vNormTexcoord).xyz;
n = normalize(n * 2.0 - 1.0);
// Multiple normal by the TBN matrix to transform the normal from tangent space to world space.
n = normalize(TBN * n);
return n;
}
#endif
#ifdef PARALLAXTEXTURE_ENABLED
vec2 ParallaxMapping(vec3 T, vec3 B, vec3 N, vec3 viewDirWorld, vec2 baseTexcoord)
{
#ifdef BINDLESS_ENABLED
sampler2D parallaxTex = sampler2D(GetCurrentTextureHandle(TEXTURE_SSBO_PARALLAX));
#endif
// Create TBN matrix.
mat3 TBN = mat3(normalize(T), normalize(B), normalize(N));
//Multiple viewDir by the TBN matrix to transform the normal from tangent space to world space.
vec3 viewDir = normalize(transpose(TBN) * viewDirWorld);
const float minLayers = 20;
const float maxLayers = 40;
float numLayers = mix(maxLayers, minLayers, abs(dot(vec3(0.0f, 0.0f, 1.0f), viewDir)));
float layerDepth = 1.0 / numLayers;
float currentLayerDepth = 0.0;
vec2 p = viewDir.xy / viewDir.z * u_parallaxScale;
vec2 deltaTexCoords = p / numLayers;
vec2 mainTexCoods = baseTexcoord;
vec2 currentTexCoords = mainTexCoods;
vec2 ddx = dFdx(mainTexCoods);
vec2 ddy = dFdy(mainTexCoods);
float currentDepthMapValue = 1.0 - textureGrad(parallaxTex, vec2(currentTexCoords.x * v_parallaxtexcoord.x, currentTexCoords.y * v_parallaxtexcoord.y), ddx, ddy ).r;
while(currentLayerDepth < currentDepthMapValue)
{
currentTexCoords -= deltaTexCoords;
currentDepthMapValue = 1.0 - textureGrad(parallaxTex, vec2(currentTexCoords.x * v_parallaxtexcoord.x, currentTexCoords.y * v_parallaxtexcoord.y), ddx, ddy ).r;
currentLayerDepth += layerDepth;
}
vec2 prevTexCoords = currentTexCoords + deltaTexCoords;
// get depth after and before collision for linear interpolation
float afterDepth = currentDepthMapValue - currentLayerDepth;
float beforeDepth = 1.0 - textureGrad(parallaxTex, vec2(prevTexCoords.x * v_parallaxtexcoord.x, prevTexCoords.y * v_parallaxtexcoord.y), ddx, ddy ).r - currentLayerDepth + layerDepth;
// interpolation of texture coordinates
float weight = afterDepth / (afterDepth - beforeDepth);
vec2 finalTexCoords = mix(currentTexCoords, prevTexCoords, weight);
return finalTexCoords;
}
#endif
float ShadowCompareDepth(vec4 coord, vec2 off, float layer)
{
vec4 newcoord = coord + vec4(off.x * SHADOW_TEXTURE_OFFSET, off.y * SHADOW_TEXTURE_OFFSET, 0.0, 0.0);
float depth0 = texture2DArray(shadowmapTexArray, vec3(newcoord.xy / newcoord.w, layer) ).a;
float depth1 = newcoord.z / newcoord.w;
return depth0 < depth1 ? 0.0 : 1.0;
}
vec3 ShadowGetWorldPosition(vec4 coord, float layer)
{
return texture2DArray(shadowmapTexArray, vec3(coord.xy / coord.w, layer) ).xyz;
}
float CalcShadowIntensityInternal(vec3 worldpos, int ilayer, float layer, float shadow_high, float shadow_medium, float shadow_low)
{
float shadow_intensity = 1.0;
vec3 scene = worldpos.xyz;
vec3 caster = ShadowGetWorldPosition(v_shadowcoord[ilayer], layer);
float dist = abs(caster.z - scene.z);
float distlerp = (dist - SceneUBO.shadowFade.x) / SceneUBO.shadowFade.y;
shadow_intensity *= 1.0 - clamp(distlerp, 0.0, 1.0);
shadow_high = 1.0 - shadow_high;
shadow_medium = 1.0 - shadow_medium;
shadow_low = 1.0 - shadow_low;
float shadow_final = shadow_high + shadow_medium + shadow_low;
shadow_final = clamp(shadow_final, 0.0, 1.0) * shadow_intensity;
return shadow_final;//0 = shadow, 1 = no shadow
}
float CalcShadowIntensity(vec3 worldpos, vec3 norm, vec3 lightdir)
{
float shadow_final = 0.0;
if(dot(norm.xyz, lightdir.xyz) < 0.0)
{
float shadow_high = 1.0;
#ifdef SHADOWMAP_HIGH_ENABLED
shadow_high = 0.0;
shadow_high += ShadowCompareDepth(v_shadowcoord[0], vec2(0.0,0.0), 0.0) * 0.25;
shadow_high += ShadowCompareDepth(v_shadowcoord[0], vec2( -1.0, -1.0), 0.0) * 0.0625;
shadow_high += ShadowCompareDepth(v_shadowcoord[0], vec2( -1.0, 0.0), 0.0) * 0.125;
shadow_high += ShadowCompareDepth(v_shadowcoord[0], vec2( -1.0, 1.0), 0.0) * 0.0625;
shadow_high += ShadowCompareDepth(v_shadowcoord[0], vec2( 0.0, -1.0), 0.0) * 0.125;
shadow_high += ShadowCompareDepth(v_shadowcoord[0], vec2( 0.0, 1.0), 0.0) * 0.125;
shadow_high += ShadowCompareDepth(v_shadowcoord[0], vec2( 1.0, -1.0), 0.0) * 0.0625;
shadow_high += ShadowCompareDepth(v_shadowcoord[0], vec2( 1.0, 0.0), 0.0) * 0.125;
shadow_high += ShadowCompareDepth(v_shadowcoord[0], vec2( 1.0, 1.0), 0.0) * 0.0625;
#endif
float shadow_medium = 1.0;
#ifdef SHADOWMAP_MEDIUM_ENABLED
shadow_medium = 0.0;
shadow_medium += ShadowCompareDepth(v_shadowcoord[1], vec2(0.0,0.0), 1.0);
shadow_medium += ShadowCompareDepth(v_shadowcoord[1], vec2(0.035,0.0), 1.0);
shadow_medium += ShadowCompareDepth(v_shadowcoord[1], vec2(-0.035,0.0), 1.0);
shadow_medium += ShadowCompareDepth(v_shadowcoord[1], vec2(0.0,0.035), 1.0);
shadow_medium += ShadowCompareDepth(v_shadowcoord[1], vec2(0.0,-0.035), 1.0);
shadow_medium *= 0.2;
#endif
float shadow_low = 1.0;
#ifdef SHADOWMAP_LOW_ENABLED
shadow_low = 0.0;
shadow_low += ShadowCompareDepth(v_shadowcoord[2], vec2(0.0,0.0), 2.0);
shadow_low += ShadowCompareDepth(v_shadowcoord[2], vec2(0.035,0.0), 2.0);
shadow_low += ShadowCompareDepth(v_shadowcoord[2], vec2(-0.035,0.0), 2.0);
shadow_low += ShadowCompareDepth(v_shadowcoord[2], vec2(0.0,0.035), 2.0);
shadow_low += ShadowCompareDepth(v_shadowcoord[2], vec2(0.0,-0.035), 2.0);
shadow_low *= 0.2;
#endif
if(false)
{
//nothing here
}
#ifdef SHADOWMAP_HIGH_ENABLED
else if(shadow_high < 0.95)
{
shadow_final = CalcShadowIntensityInternal(worldpos, 0, 0.0, shadow_high, shadow_medium, shadow_low);
}
#endif
#ifdef SHADOWMAP_MEDIUM_ENABLED
else if(shadow_medium < 0.95)
{
shadow_final = CalcShadowIntensityInternal(worldpos, 1, 1.0, shadow_high, shadow_medium, shadow_low);
}
#endif
#ifdef SHADOWMAP_LOW_ENABLED
else if(shadow_low < 0.95)
{
shadow_final = CalcShadowIntensityInternal(worldpos, 2, 2.0, shadow_high, shadow_medium, shadow_low);
}
#endif
}
return shadow_final;
}
float CalcShadowIntensityLumFadeout(vec4 lightmapColor, float intensity)
{
float lightmapLum = 0.299 * lightmapColor.x + 0.587 * lightmapColor.y + 0.114 * lightmapColor.z;
float shadowLerp = (lightmapLum - SceneUBO.shadowFade.w) / (SceneUBO.shadowFade.z - SceneUBO.shadowFade.w);
float shadowIntensity = intensity * clamp(shadowLerp, 0.0, 1.0);
shadowIntensity *= SceneUBO.shadowColor.a;
return shadowIntensity;
}
void main()
{
#ifndef SKYBOX_ENABLED
ClipPlaneTest(v_worldpos.xyz, v_normal.xyz);
#endif
vec2 baseTexcoord = vec2(0.0, 0.0);
#ifdef DIFFUSE_ENABLED
#ifdef REPLACETEXTURE_ENABLED
#ifdef BINDLESS_ENABLED
sampler2D diffuseTex = sampler2D(GetCurrentTextureHandle(TEXTURE_SSBO_REPLACE));
#endif
baseTexcoord = vec2(v_diffusetexcoord.x * v_replacetexcoord.x, v_diffusetexcoord.y * v_replacetexcoord.y);
#else
#ifdef BINDLESS_ENABLED
sampler2D diffuseTex = sampler2D(GetCurrentTextureHandle(TEXTURE_SSBO_DIFFUSE));
#endif
baseTexcoord = v_diffusetexcoord.xy;
#endif
#ifdef PARALLAXTEXTURE_ENABLED
vec3 viewDir = normalize(v_worldpos.xyz - SceneUBO.viewpos.xyz);
vec4 diffuseColor = texture(diffuseTex, ParallaxMapping(v_tangent, v_bitangent, v_normal, viewDir, baseTexcoord));
#else
vec4 diffuseColor = texture(diffuseTex, baseTexcoord);
#endif
//dynamic gamma correction will corrupt the alpha-blend routine that decal rendering was using when there was pre-applied texgamma correction.
#if !defined(DECAL_ENABLED)
diffuseColor = TexGammaToLinear(diffuseColor);
#else
diffuseColor = TexGammaToLinear(diffuseColor);
//so we have to shift the alpha a little bit up...
#ifndef TRANSPARENT_ENABLED
diffuseColor.a = pow(diffuseColor.a, SceneUBO.r_alpha_shift);
#else
//Don't do alpha adjustment for decals on transparent surfaces.
#endif
#endif
#else
vec4 diffuseColor = vec4(1.0, 1.0, 1.0, 1.0);
#endif
#ifdef LIGHTMAP_ENABLED
vec4 lightmapColor = texture2DArray(lightmapTexArray, v_lightmaptexcoord.xyz);
lightmapColor = LightGammaToLinear(lightmapColor);
//lightmapColor.x = max(lightmapColor.x, 0.03);
//lightmapColor.y = max(lightmapColor.y, 0.03);
//lightmapColor.z = max(lightmapColor.z, 0.03);
#else
vec4 lightmapColor = vec4(1.0, 1.0, 1.0, 1.0);
#endif
#ifdef NORMALTEXTURE_ENABLED
vec3 vNormal = NormalMapping(v_tangent, v_bitangent, v_normal, baseTexcoord);
#else
vec3 vNormal = normalize(v_normal.xyz);
#endif
#ifdef DETAILTEXTURE_ENABLED
#ifdef BINDLESS_ENABLED
sampler2D detailTex = sampler2D(GetCurrentTextureHandle(TEXTURE_SSBO_DETAIL));
#endif
vec2 detailTexCoord = vec2(baseTexcoord.x * v_detailtexcoord.x, baseTexcoord.y * v_detailtexcoord.y);
vec4 detailColor = texture(detailTex, detailTexCoord);
detailColor.xyz *= 2.0;
detailColor.a = 1.0;
detailColor = TexGammaToLinear(detailColor);
#else
vec4 detailColor = vec4(1.0, 1.0, 1.0, 1.0);
#endif
#ifdef SHADOW_CASTER_ENABLED
out_Diffuse.xyz = v_worldpos.xyz;
out_Diffuse.w = gl_FragCoord.z;
#else
#ifdef SHADOWMAP_ENABLED
float shadowIntensity = CalcShadowIntensity(v_worldpos, vNormal, SceneUBO.shadowDirection.xyz);
#endif
#ifdef GBUFFER_ENABLED
vec4 specularColor = vec4(0.0);
vec2 vOctNormal = UnitVectorToOctahedron(vNormal);
float flDistanceToFragment = distance(v_worldpos.xyz, SceneUBO.viewpos.xyz);
#ifdef SPECULARTEXTURE_ENABLED
#ifdef BINDLESS_ENABLED
sampler2D specularTex = sampler2D(GetCurrentTextureHandle(TEXTURE_SSBO_SPECULAR));
#endif
vec2 specularTexCoord = vec2(baseTexcoord.x * v_speculartexcoord.x, baseTexcoord.y * v_speculartexcoord.y);
specularColor.xy = texture2D(specularTex, specularTexCoord).xy;
#endif
#ifdef SHADOWMAP_ENABLED
specularColor.z = shadowIntensity;
#endif
#ifdef DECAL_ENABLED
out_Diffuse = diffuseColor * detailColor;
out_WorldNorm = vec4(vOctNormal.x, vOctNormal.y, flDistanceToFragment, 0.0);
#else
out_Diffuse = diffuseColor * detailColor;
out_Lightmap = lightmapColor;
out_WorldNorm = vec4(vOctNormal.x, vOctNormal.y, flDistanceToFragment, 0.0);
out_Specular = specularColor;
out_Additive = vec4(0.0);
#endif
#else
#ifdef SHADOWMAP_ENABLED
shadowIntensity = CalcShadowIntensityLumFadeout(lightmapColor, shadowIntensity);
lightmapColor.xyz *= (1.0 - shadowIntensity);
#endif
#ifdef TRANSPARENT_ENABLED
vec4 color = CalcFog(diffuseColor * lightmapColor * detailColor * EntityUBO.color);
#else
vec4 color = CalcFog(diffuseColor * lightmapColor * detailColor);
#endif
#if defined(OIT_ALPHA_BLEND_ENABLED) || defined(OIT_ADDITIVE_BLEND_ENABLED)
GatherFragment(color);
#endif
out_Diffuse = color;
#endif
#endif
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment