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/2d081fcc2de734b2faf287349abc5e8b to your computer and use it in GitHub Desktop.
Save hzqst/2d081fcc2de734b2faf287349abc5e8b 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_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