Created
October 22, 2022 03:58
-
-
Save hzqst/2d081fcc2de734b2faf287349abc5e8b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#version 430 | |
#define DIFFUSE_ENABLED | |
#define LIGHTMAP_ENABLED | |
#define GBUFFER_ENABLED | |
#define BINDLESS_ENABLED | |
#define SHADOW_TEXTURE_OFFSET (1.0 / 4096.0) | |
#define IS_VERTEX_SHADER | |
#extension GL_EXT_texture_array : require | |
#extension GL_ARB_shader_draw_parameters : require | |
#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; | |
layout(location = 0) in vec3 in_vertex; | |
layout(location = 1) in vec3 in_normal; | |
layout(location = 2) in vec3 in_tangent; | |
layout(location = 3) in vec3 in_bitangent; | |
layout(location = 4) in vec3 in_diffusetexcoord; | |
layout(location = 5) in vec3 in_lightmaptexcoord; | |
layout(location = 6) in vec2 in_replacetexcoord; | |
layout(location = 7) in vec2 in_detailtexcoord; | |
layout(location = 8) in vec2 in_normaltexcoord; | |
layout(location = 9) in vec2 in_parallaxtexcoord; | |
layout(location = 10) in vec2 in_speculartexcoord; | |
#if defined(SKYBOX_ENABLED) | |
#elif defined(DECAL_ENABLED) | |
layout(location = 11) in int in_decalindex; | |
#else | |
layout(location = 11) in int in_texindex; | |
#endif | |
out vec3 v_worldpos; | |
out vec3 v_normal; | |
out vec3 v_tangent; | |
out vec3 v_bitangent; | |
out vec2 v_diffusetexcoord; | |
out vec3 v_lightmaptexcoord; | |
out vec2 v_replacetexcoord; | |
out vec2 v_detailtexcoord; | |
out vec2 v_normaltexcoord; | |
out vec2 v_parallaxtexcoord; | |
out vec2 v_speculartexcoord; | |
out vec4 v_shadowcoord[3]; | |
#ifdef BINDLESS_ENABLED | |
#if defined(SKYBOX_ENABLED) | |
flat out int v_drawid; | |
#elif defined(DECAL_ENABLED) | |
flat out int v_decalindex; | |
#else | |
flat out int v_texindex; | |
#endif | |
#endif | |
#ifdef SKYBOX_ENABLED | |
void MakeSkyVec(float s, float t, int axis, float zFar, out vec3 position, out vec2 texCoord) | |
{ | |
const float flScale = 0.57735; | |
const ivec3 st_to_vec[6] = | |
{ | |
ivec3( 3, -1, 2 ), | |
ivec3( -3, 1, 2 ), | |
ivec3( 1, 3, 2 ), | |
ivec3( -1, -3, 2 ), | |
ivec3( -2, -1, 3 ), | |
ivec3( 2, -1, -3 ) | |
}; | |
float width = zFar * flScale; | |
vec3 b = vec3(s * width, t * width, width); | |
vec3 v = SceneUBO.viewpos.xyz; | |
for (int j = 0; j < 3; j++) | |
{ | |
int k = st_to_vec[axis][j]; | |
float v_negetive = -b[-k - 1]; | |
float v_positive = b[k - 1]; | |
v[j] += mix(v_negetive, v_positive, float(step(0, k)) ); | |
} | |
// avoid bilerp seam | |
s = (s + 1)*0.5; | |
t = (t + 1)*0.5; | |
// AV - I'm commenting this out since our skyboxes aren't 512x512 and we don't | |
// modify the textures to deal with the border seam fixup correctly. | |
// The code below was causing seams in the skyboxes. | |
s = clamp(s, 1.0 / 512.0, 511.0 / 512.0); | |
t = clamp(t, 1.0 / 512.0, 511.0 / 512.0); | |
t = 1.0 - t; | |
position = v; | |
texCoord = vec2(s, t); | |
} | |
#endif | |
void main(void) | |
{ | |
#ifdef SKYBOX_ENABLED | |
int vertidx = gl_VertexID % 4; | |
int quadidx = gl_VertexID / 4; | |
const vec4 s_array = vec4(-1.0, -1.0, 1.0, 1.0); | |
const vec4 t_array = vec4(-1.0, 1.0, 1.0, -1.0); | |
vec3 vertex = vec3(0.0); | |
vec2 texcoord = vec2(0.0); | |
MakeSkyVec(s_array[vertidx], t_array[vertidx], quadidx, SceneUBO.z_far, vertex, texcoord); | |
vec4 worldpos4 = vec4(vertex, 1.0); | |
v_worldpos = worldpos4.xyz; | |
vec4 normal4 = vec4(in_normal.xyz, 0.0); | |
v_normal = normalize((normal4).xyz); | |
v_diffusetexcoord = texcoord; | |
#else | |
vec4 worldpos4 = EntityUBO.entityMatrix * vec4(in_vertex.xyz, 1.0); | |
v_worldpos = worldpos4.xyz; | |
vec4 normal4 = vec4(in_normal.xyz, 0.0); | |
v_normal = normalize((EntityUBO.entityMatrix * normal4).xyz); | |
#ifdef DIFFUSE_ENABLED | |
v_diffusetexcoord = vec2(in_diffusetexcoord.x + in_diffusetexcoord.z * EntityUBO.scrollSpeed, in_diffusetexcoord.y); | |
#endif | |
#endif | |
#ifdef LIGHTMAP_ENABLED | |
v_lightmaptexcoord = in_lightmaptexcoord; | |
#endif | |
#ifdef REPLACETEXTURE_ENABLED | |
v_replacetexcoord = in_replacetexcoord; | |
#endif | |
#ifdef DETAILTEXTURE_ENABLED | |
v_detailtexcoord = in_detailtexcoord; | |
#endif | |
#if defined(NORMALTEXTURE_ENABLED) || defined(PARALLAXTEXTURE_ENABLED) | |
vec4 tangent4 = vec4(in_tangent, 0.0); | |
v_tangent = normalize((EntityUBO.entityMatrix * tangent4).xyz); | |
vec4 bitangent4 = vec4(in_bitangent, 0.0); | |
v_bitangent = normalize((EntityUBO.entityMatrix * bitangent4).xyz); | |
#endif | |
#ifdef NORMALTEXTURE_ENABLED | |
v_normaltexcoord = in_normaltexcoord; | |
#endif | |
#ifdef PARALLAXTEXTURE_ENABLED | |
v_parallaxtexcoord = in_parallaxtexcoord; | |
#endif | |
#ifdef SPECULARTEXTURE_ENABLED | |
v_speculartexcoord = in_speculartexcoord; | |
#endif | |
#ifdef SHADOWMAP_ENABLED | |
#ifdef SHADOWMAP_HIGH_ENABLED | |
v_shadowcoord[0] = SceneUBO.shadowMatrix[0] * vec4(v_worldpos, 1.0); | |
#endif | |
#ifdef SHADOWMAP_MEDIUM_ENABLED | |
v_shadowcoord[1] = SceneUBO.shadowMatrix[1] * vec4(v_worldpos, 1.0); | |
#endif | |
#ifdef SHADOWMAP_LOW_ENABLED | |
v_shadowcoord[2] = SceneUBO.shadowMatrix[2] * vec4(v_worldpos, 1.0); | |
#endif | |
#endif | |
#ifdef BINDLESS_ENABLED | |
#if defined(SKYBOX_ENABLED) | |
v_drawid = quadidx; | |
#elif defined(DECAL_ENABLED) | |
v_decalindex = in_decalindex; | |
#else | |
v_texindex = in_texindex; | |
#endif | |
#endif | |
gl_Position = SceneUBO.projMatrix * SceneUBO.viewMatrix * worldpos4; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment