SuperTuxKart 1.5 upstream source (from official release tarball)

This commit is contained in:
Benjamin
2026-06-11 20:04:02 +02:00
commit 2957e51aaa
8551 changed files with 1801800 additions and 0 deletions
+21
View File
@@ -0,0 +1,21 @@
layout(location = 0) in vec4 f_color;
layout(location = 1) in vec2 f_uv;
layout(location = 2) flat in int f_sampler_index;
#ifdef BIND_TEXTURES_AT_ONCE
layout(binding = 0) uniform sampler2D f_tex[SAMPLER_SIZE];
#else
layout(binding = 0) uniform sampler2D f_tex;
#endif
layout(location = 0) out vec4 o_color;
void main()
{
#ifdef BIND_TEXTURES_AT_ONCE
vec4 tex_color = texture(f_tex[GE_SAMPLE_TEX_INDEX(f_sampler_index)], f_uv);
#else
vec4 tex_color = texture(f_tex, f_uv);
#endif
o_color = tex_color * f_color;
}
+16
View File
@@ -0,0 +1,16 @@
layout(location = 0) in vec2 v_position;
layout(location = 1) in vec4 v_color;
layout(location = 2) in vec2 v_uv;
layout(location = 3) in int v_sampler_index;
layout(location = 0) out vec4 f_color;
layout(location = 1) out vec2 f_uv;
layout(location = 2) flat out int f_sampler_index;
void main()
{
gl_Position = vec4(v_position, 0.0, 1.0);
f_color = v_color.zyxw;
f_uv = v_uv;
f_sampler_index = v_sampler_index;
}
+52
View File
@@ -0,0 +1,52 @@
layout(location = 0) in vec4 f_vertex_color;
layout(location = 1) in vec2 f_uv;
layout(location = 3) flat in int f_material_id;
layout(location = 4) in float f_hue_change;
#ifdef PBR_ENABLED
layout(location = 5) in vec3 f_normal;
layout(location = 8) in vec4 f_world_position;
#endif
layout(location = 0) out vec4 o_color;
#include "utils/sample_mesh_texture.glsl"
#include "../utils/rgb_conversion.frag"
#ifdef PBR_ENABLED
#include "utils/handle_pbr.glsl"
#include "../utils/encode_normal.frag"
layout(location = 1) out vec4 o_normal;
#endif
void main()
{
vec4 tex_color = sampleMeshTexture0(f_material_id, f_uv);
if (tex_color.a * f_vertex_color.a < 0.5)
discard;
if (f_hue_change > 0.0)
{
vec3 old_hsv = rgbToHsv(tex_color.rgb);
vec2 new_xy = vec2(f_hue_change, old_hsv.y);
vec3 new_color = hsvToRgb(vec3(new_xy.x, new_xy.y, old_hsv.z));
tex_color = vec4(new_color.r, new_color.g, new_color.b, tex_color.a);
}
#ifndef PBR_ENABLED
vec3 mixed_color = tex_color.xyz * f_vertex_color.xyz;
o_color = vec4(mixed_color, 1.0);
#else
vec3 diffuse_color = tex_color.xyz * f_vertex_color.xyz;
vec3 normal = normalize(f_normal.xyz);
vec3 pbr = sampleMeshTexture2(f_material_id, f_uv).xyz;
if (u_deferred)
{
o_color = vec4(diffuse_color, pbr.z);
o_normal.xy = EncodeNormal(normal);
o_normal.zw = pbr.xy;
}
else
{
o_color = vec4(handlePBR(diffuse_color, pbr, f_world_position, normal),
1.0);
}
#endif
}
@@ -0,0 +1,12 @@
layout(location = 0) in vec4 f_vertex_color;
layout(location = 1) in vec2 f_uv;
layout(location = 3) flat in int f_material_id;
#include "utils/sample_mesh_texture.glsl"
void main()
{
vec4 tex_color = sampleMeshTexture0(f_material_id, f_uv);
if (tex_color.a * f_vertex_color.a < 0.5)
discard;
}
+41
View File
@@ -0,0 +1,41 @@
layout(location = 1) in vec2 f_uv;
layout(location = 2) in vec2 f_uv_two;
layout(location = 3) flat in int f_material_id;
#ifdef PBR_ENABLED
layout(location = 5) in vec3 f_normal;
layout(location = 8) in vec4 f_world_position;
#endif
layout(location = 0) out vec4 o_color;
#include "utils/sample_mesh_texture.glsl"
#ifdef PBR_ENABLED
#include "utils/handle_pbr.glsl"
#include "../utils/encode_normal.frag"
layout(location = 1) out vec4 o_normal;
#endif
void main()
{
vec4 color = sampleMeshTexture0(f_material_id, f_uv);
vec4 layer_two_tex = sampleMeshTexture1(f_material_id, f_uv_two);
layer_two_tex.rgb = layer_two_tex.a * layer_two_tex.rgb;
vec3 final_color = layer_two_tex.rgb + color.rgb * (1.0 - layer_two_tex.a);
#ifndef PBR_ENABLED
o_color = vec4(final_color, 1.0);
#else
vec3 normal = normalize(f_normal.xyz);
vec3 pbr = sampleMeshTexture2(f_material_id, f_uv).xyz;
if (u_deferred)
{
o_color = vec4(final_color, pbr.z);
o_normal.xy = EncodeNormal(normal);
o_normal.zw = pbr.xy;
}
else
{
o_color = vec4(handlePBR(final_color, pbr, f_world_position, normal),
1.0);
}
#endif
}
@@ -0,0 +1,10 @@
layout (input_attachment_index = 0, binding = 0) uniform subpassInput u_hdr;
layout(location = 0) out vec4 o_color;
#include "utils/constants_utils.glsl"
void main()
{
o_color = vec4(convertColor(subpassLoad(u_hdr).xyz), 1.0);
}
+33
View File
@@ -0,0 +1,33 @@
layout (input_attachment_index = 0, binding = 0) uniform subpassInput u_color;
layout (input_attachment_index = 1, binding = 1) uniform subpassInput u_normal;
layout (input_attachment_index = 2, binding = 2) uniform subpassInput u_depth;
layout(location = 0) out vec4 o_color;
layout(push_constant) uniform Constants
{
int m_fullscreen_light_count;
} u_push_constants;
#include "utils/unproject_position.glsl"
#include "utils/handle_pbr.glsl"
#include "../utils/decodeNormal.frag"
void main()
{
float depth = subpassLoad(u_depth).x;
if (!u_has_skybox && depth == 1.0)
discard;
vec3 diffuse_color = subpassLoad(u_color).xyz;
vec3 pbr = vec3(subpassLoad(u_normal).zw, subpassLoad(u_color).w);
vec3 world_normal = DecodeNormal(subpassLoad(u_normal).xy);
vec3 xpos = getPosFromUVDepth(vec3(gl_FragCoord.xy, depth),
u_camera.m_viewport, u_camera.m_inverse_projection_matrix);
vec3 eyedir = -normalize(xpos);
vec3 normal = (u_camera.m_view_matrix * vec4(world_normal, 0.0)).xyz;
vec3 hdr = handlePBRDeferred(diffuse_color, pbr, world_normal, eyedir,
normal, 1.0 - pbr.x);
hdr += accumulateLights(u_push_constants.m_fullscreen_light_count,
diffuse_color, normal, xpos, eyedir, 1.0 - pbr.x, pbr.y);
o_color = vec4(hdr, 1.0);
}
@@ -0,0 +1,31 @@
layout (input_attachment_index = 0, binding = 0) uniform subpassInput u_color;
layout (input_attachment_index = 1, binding = 1) uniform subpassInput u_normal;
layout (input_attachment_index = 2, binding = 2) uniform subpassInput u_depth;
layout(location = 0) flat in int light_idx;
layout(location = 0) out vec4 o_color;
#include "utils/unproject_position.glsl"
#include "utils/handle_pbr.glsl"
#include "../utils/decodeNormal.frag"
void main()
{
float depth = subpassLoad(u_depth).x;
if (depth == 1.0)
{
o_color = vec4(0.0, 0.0, 0.0, 1.0);
return;
}
vec3 diffuse_color = subpassLoad(u_color).xyz;
vec3 pbr = vec3(subpassLoad(u_normal).zw, subpassLoad(u_color).w);
vec3 world_normal = DecodeNormal(subpassLoad(u_normal).xy);
vec3 xpos = getPosFromUVDepth(vec3(gl_FragCoord.xy, depth),
u_camera.m_viewport, u_camera.m_inverse_projection_matrix);
vec3 eyedir = -normalize(xpos);
vec3 normal = (u_camera.m_view_matrix * vec4(world_normal, 0.0)).xyz;
vec3 light = calculateLight(light_idx, diffuse_color, normal, xpos,
eyedir, 1.0 - pbr.x, pbr.y);
o_color = vec4(light, 1.0);
}
@@ -0,0 +1,59 @@
#include "utils/camera.glsl"
#include "utils/global_light_data.glsl"
#include "utils/spm_data.glsl"
#include "../utils/get_world_location.vert"
layout(push_constant) uniform Constants
{
vec4 m_billboard_rotation;
int m_fullscreen_light;
} u_push_constants;
layout(location = 0) flat out int light_idx;
const vec3 g_vertices[4] =
vec3[]
(
vec3( 1.0, 1.0, 0.0),
vec3( 1.0, -1.0, 0.0),
vec3(-1.0, 1.0, 0.0),
vec3(-1.0, -1.0, 0.0)
);
void main()
{
// Get the light index from the instance ID
light_idx = gl_InstanceIndex + u_push_constants.m_fullscreen_light;
LightData light = u_global_light.m_lights[light_idx];
vec4 pos_radius = light.m_position_radius;
// Get camera position from inverse view matrix
vec3 camera_pos = vec3(u_camera.m_inverse_view_matrix[3]);
// Calculate vector from light to camera
vec3 light_to_camera = normalize(camera_pos - pos_radius.xyz);
/* The lights which cover the whole screen have been rendered already
// Calculate distance from light to camera
float dist_to_camera = distance(camera_pos, pos_radius.xyz);
// If camera is within light radius, move the billboard quad towards the
// near plane
if (dist_to_camera < pos_radius.w)
{
gl_Position = vec4(g_vertices[gl_VertexIndex], 1.0);
return;
}
*/
// Move the billboard towards camera by one radius unit
vec4 world_pos = getWorldPosition(
pos_radius.xyz + light_to_camera * pos_radius.w,
u_push_constants.m_billboard_rotation,
vec3(pos_radius.w), g_vertices[gl_VertexIndex]);
vec4 pv = u_camera.m_projection_view_matrix * world_pos;
if (pv.z < 0.0)
gl_Position = vec4(pv.xy, 0.0, 1.0);
else
gl_Position = pv;
}
+3
View File
@@ -0,0 +1,3 @@
void main()
{
}
@@ -0,0 +1,53 @@
layout (local_size_x = 16, local_size_y = 16, local_size_z = 1) in;
// Binding for the input skybox cubemap.
layout(set = 0, binding = 0) uniform samplerCube uSkybox;
// Binding for the output irradiance (diffuse) cube map stored as a 2D array (each layer is one face).
#ifdef SHADER_STORAGE_IMAGE_EXTENDED_FORMATS
layout(set = 0, binding = 1, rgb10_a2) uniform restrict writeonly image2DArray uIrradianceMap;
#else
layout(set = 0, binding = 1, rgba8) uniform restrict writeonly image2DArray uIrradianceMap;
#endif
#include "utils/environment_map.glsl"
void main()
{
ivec2 pix = ivec2(gl_GlobalInvocationID.xy);
if (pix.x >= pc.size || pix.y >= pc.size) return;
// Get normalized UV for current pixel.
vec2 uv = (vec2(pix) + 0.5) / vec2(pc.size, pc.size);
int face = int(gl_GlobalInvocationID.z);
vec3 normal = FaceUVtoDir(face, uv);
// Establish a tangent space basis.
vec3 up = abs(normal.y) < 0.999 ? vec3(0.0, 1.0, 0.0) : vec3(1.0, 0.0, 0.0);
vec3 right = normalize(cross(up, normal));
vec3 tangent = cross(normal, right);
vec3 irradiance = vec3(0.0);
float weight = 0.0;
uint sampleCount = uint(pc.sampleCount);
for (uint i = 0u; i < sampleCount; i++)
{
vec2 xi = Hammersley(i, sampleCount);
// Cosine-weighted hemisphere sampling.
float phi = 2.0 * PI * xi.x;
float cosTheta = sqrt(1.0 - xi.y); // weight factor equals cos(theta)
float sinTheta = sqrt(xi.y);
vec3 sampleDir = vec3(cos(phi) * sinTheta, sin(phi) * sinTheta, cosTheta);
// Transform sample direction from tangent space to world space.
vec3 sampleVec = normalize(right * sampleDir.x + tangent * sampleDir.y + normal * sampleDir.z);
vec3 sampleColor = texture(uSkybox, sampleVec).rgb;
irradiance += sampleColor * cosTheta;
weight += cosTheta;
}
irradiance /= weight;
imageStore(uIrradianceMap, ivec3(pix, face), vec4(irradiance, 1.0));
}
@@ -0,0 +1,31 @@
layout(binding = 0) uniform sampler2D u_displace_mask;
layout(binding = 2) uniform sampler2D u_displace_color;
layout(location = 0) in vec2 f_uv;
layout(location = 0) out vec4 o_color;
layout(push_constant) uniform Constants
{
bool m_has_displace;
} u_push_constants;
#include "utils/camera.glsl"
#include "../utils/displace_utils.frag"
void main()
{
#ifdef PBR_ENABLED
ivec2 uv = ivec2(gl_FragCoord.xy);
if (u_push_constants.m_has_displace)
{
vec2 mask = texelFetch(u_displace_mask, uv, 0).xy;
if (!(mask.x == 0.0 && mask.y == 0.0))
{
vec2 shift = 2.0 * mask - 1.0;
uv = getDisplaceUV(shift, u_camera.m_viewport, u_displace_mask);
}
}
o_color = texelFetch(u_displace_color, uv, 0);
#endif
}
+288
View File
@@ -0,0 +1,288 @@
layout(location = 1) in vec2 f_uv;
layout(location = 5) in vec3 f_normal;
layout(location = 8) in vec4 f_world_position;
layout(location = 3) flat in int f_material_id;
layout(location = 0) out vec2 o_displace_mask;
layout(location = 1) out vec4 o_displace_ssr;
layout(push_constant) uniform Constants
{
vec4 m_displace_direction;
} u_push_constants;
#include "utils/camera.glsl"
#include "utils/constants_utils.glsl"
#include "utils/sample_mesh_texture.glsl"
#include "../utils/displace_utils.frag"
#include "../utils/screen_space_reflection.frag"
layout (set = 2, binding = 2) uniform samplerCube u_skybox_texture;
layout (set = 3, binding = 0) uniform sampler2D u_displace_color;
layout (set = 3, binding = 1) uniform sampler2DShadow u_depth;
layout (set = 3, binding = 2) uniform sampler2D u_hiz_depth;
#ifdef PBR_ENABLED
// Start tracing in this level.
#define HIZ_START_LEVEL 0
// Stop tracing if current level is higher than this. (higher level means lower value)
#define HIZ_STOP_LEVEL 0
#define HIZ_MAX_LEVEL 6
// Set to 1 to disable HiZ and perform naive linear search.
#define DEBUG_LINEAR_SEARCH 0
#define MAX_THICKNESS 0.001
vec3 intersectDepthPlane(vec3 o, vec3 d, float z)
{
return o + d * z;
}
// Index of the cell that contains the given 2D position.
ivec2 getCell(vec2 screenUV, ivec2 cellCount)
{
return ivec2(screenUV * cellCount);
}
// The number of cells in the quad tree at the given level.
ivec2 getCellCount(int level)
{
return textureSize(u_hiz_depth, level);
}
// Returns screen space position of the intersection
// between o + d*t and the closest cell boundary at current HiZ level.
vec3 intersectCellBoundary(
vec3 pos, vec3 dir,
ivec2 cell, ivec2 cellCount,
vec2 crossStep, vec2 crossOffset)
{
vec3 intersection = vec3(0.0);
vec2 index = cell + crossStep;
vec2 boundary = index / vec2(cellCount); // Screen space position of the boundary
boundary += crossOffset;
vec2 delta = boundary - pos.xy;
delta /= dir.xy;
float t = min(delta.x, delta.y);
intersection = intersectDepthPlane(pos, dir, t);
return intersection;
}
bool crossedCellBoundary(ivec2 oldCellIx, ivec2 newCellIx)
{
return any(notEqual(oldCellIx, newCellIx));
}
// Minimum depth of the current cell in the current HiZ level.
float getMinDepthPlane(ivec2 cellIx, int level)
{
return texelFetch(u_hiz_depth, cellIx, level).x;
}
float getMaxTraceDistance(vec3 p, vec3 v)
{
vec3 traceDistances;
if (v.x < 0.0)
traceDistances.x = p.x / (-v.x);
else
traceDistances.x = (1.0 - p.x) / v.x;
if (v.y < 0.0)
traceDistances.y = p.y / (-v.y);
else
traceDistances.y = (1.0 - p.y) / v.y;
if (v.z < 0.0)
traceDistances.z = p.z / (-v.z);
else
traceDistances.z = (1.0 - p.z) / v.z;
return min(traceDistances.x, min(traceDistances.y, traceDistances.z));
}
// p : Screen space position
// v : Screen space reflection direction
// hitPointSS : Returns screen space hit point
// Return value : Whether RT actually hit a surface
bool traceHiZ(vec3 p, vec3 v, out vec2 hitPointSS)
{
const int maxLevel = min(HIZ_MAX_LEVEL, textureQueryLevels(u_hiz_depth) - 1); // Last mip level
float maxTraceDistance = getMaxTraceDistance(p, v);
// Get the cell cross direction and a small offset to enter
// the next cell when doing cell crossing.
vec2 crossStep = vec2(v.x >= 0 ? 1 : -1, v.y >= 0 ? 1 : -1);
vec2 crossOffset = crossStep / u_camera.m_viewport.zw / 128.;
crossStep = clamp(crossStep, 0.0, 1.0);
// Set current ray to the original screen coordinate and depth.
vec3 ray = p;
float minZ = ray.z;
float maxZ = ray.z + v.z * maxTraceDistance;
float deltaZ = maxZ - minZ;
vec3 o = ray;
vec3 d = v * maxTraceDistance;
int level = HIZ_START_LEVEL;
int deepestLevel = level;
#if DEBUG_LINEAR_SEARCH
level = 0;
#endif
uint iterations = 0;
bool isBackwardRay = v.z < 0;
float rayDir = isBackwardRay ? -1.0 : 1.0;
// Cross to next cell s.t. we don't get a self-intersection immediately.
ivec2 startCellCount = getCellCount(level);
ivec2 rayCell = getCell(ray.xy, startCellCount);
ray = intersectCellBoundary(o, d, rayCell, startCellCount, crossStep, crossOffset * 64.);
while (level >= HIZ_STOP_LEVEL && ray.z * rayDir <= maxZ * rayDir &&
iterations < u_hiz_iterations)
{
// Get the cell number of our current ray.
ivec2 cellCount = getCellCount(level);
ivec2 oldCellIx = getCell(ray.xy, cellCount);
// Get the minimum depth plane in which the current ray resides.
float cellMinZ = getMinDepthPlane(oldCellIx, level);
// Intersect only if ray depth is below the minimum depth plane.
vec3 tempRay;
if (cellMinZ > ray.z && !isBackwardRay)
tempRay = intersectDepthPlane(o, d, (cellMinZ - minZ) / deltaZ);
else
tempRay = ray;
ivec2 newCellIx = getCell(tempRay.xy, cellCount);
float thickness = level == 0 ? (ray.z - cellMinZ) : 0;
bool crossed = (isBackwardRay && (cellMinZ > ray.z))
|| (thickness > MAX_THICKNESS) || crossedCellBoundary(oldCellIx, newCellIx);
if (crossed)
{
ray = intersectCellBoundary(o, d, oldCellIx, cellCount, crossStep, crossOffset);
level = min(maxLevel, level + 1);
deepestLevel = max(deepestLevel, level);
#if DEBUG_LINEAR_SEARCH
level = 0;
#endif
}
else
{
ray = tempRay;
level = level - 1;
}
iterations += 1;
}
// Results
//debugDeepestLevel = deepestLevel;
//debugIterations = iterations;
hitPointSS = ray.xy;
return level < HIZ_STOP_LEVEL && iterations < u_hiz_iterations;
}
#endif
void main()
{
#ifdef PBR_ENABLED
float horiz = sampleMeshTexture2(f_material_id, f_uv + u_push_constants.m_displace_direction.xy * 150.).x;
float vert = sampleMeshTexture2(f_material_id, (f_uv.yx + u_push_constants.m_displace_direction.zw * 150.) * vec2(0.9)).x;
vec2 mask = getDisplaceShift(horiz, vert);
mask = (mask + 1.0) * 0.5;
o_displace_mask = mask;
if (u_ssr)
{
float alpha = sampleMeshTexture0(f_material_id, f_uv).a;
if (alpha == 0.0)
{
o_displace_ssr = vec4(0.0);
return;
}
// eye-space position
vec3 xpos = (u_camera.m_view_matrix * f_world_position).xyz;
// eye-space view direction (points from surface toward eye at origin)
vec3 eyedir = -normalize(xpos);
// eye-space normal
vec3 normal = (u_camera.m_view_matrix * vec4(normalize(f_normal), 0)).xyz;
// bail out immediately if normal is facing away from the camera,
// dot(normal, eyedir) <= 0 means back-facing
float NdotV = dot(normal, eyedir);
if (NdotV <= 0.0)
{
o_displace_ssr = vec4(0.0);
return;
}
// compute reflection in eye-space
vec3 reflected = reflect(-eyedir, normal);
// bring it back into world-space
vec3 world_reflection = (u_camera.m_inverse_view_matrix *
vec4(reflected, 0.0)).xyz;
// fallback to skybox
vec4 fallback = texture(u_skybox_texture, world_reflection);
// early exit if normal is facing camera too directly (no meaningful reflection)
if (normal.z < -0.75)
{
o_displace_ssr = fallback;
return;
}
vec4 result;
vec2 viewport_scale = u_camera.m_viewport.zw / u_camera.m_screensize;
vec2 viewport_offset = u_camera.m_viewport.xy / u_camera.m_screensize;
bool hit = true;
vec2 coords;
if (u_hiz_iterations == 0)
{
coords = RayCast(reflected, xpos, u_camera.m_projection_matrix,
viewport_scale, viewport_offset, u_depth);
}
else
{
vec3 positionSS = CalcCoordFromPosition(xpos,
u_camera.m_projection_matrix, vec2(1.0), vec2(0.0));
vec3 positionCS = positionSS;
positionCS.xy = 2.0 * positionCS.xy - 1.0;
vec3 position2VS = xpos + 1000.0 * reflected;
vec4 position2CS = u_camera.m_projection_matrix * vec4(position2VS, 1.0);
position2CS /= position2CS.w;
vec3 position2SS = position2CS.xyz;
position2SS.xy = vec2(0.5) + 0.5 * position2SS.xy;
vec3 reflectionDirSS = normalize(position2SS - positionSS);
// Trace HiZ to find the hit point.
hit = traceHiZ(positionSS, reflectionDirSS, coords);
coords = coords * viewport_scale + viewport_offset;
}
vec2 viewport_coords = (coords - viewport_offset) / viewport_scale;
if (!hit || viewport_coords.x < 0. || viewport_coords.x > 1. ||
viewport_coords.y < 0. || viewport_coords.y > 1.)
{
result = fallback;
}
else
{
result = texture(u_displace_color, coords);
float edge = GetEdgeFade(coords, viewport_scale, viewport_offset);
//float fresnel = pow(1.0 - NdotV, 2.0);
float fresnel = (1.0 - NdotV) * (1.0 - NdotV);
float blend_weight = edge * fresnel;
result = mix(fallback, result, blend_weight);
}
o_displace_ssr = result;
}
#endif
}
@@ -0,0 +1,48 @@
layout(location = 0) in vec4 f_vertex_color;
layout(location = 1) in vec2 f_uv;
layout(location = 3) flat in int f_material_id;
layout(location = 0) out vec4 o_color;
layout(push_constant) uniform Constants
{
vec4 m_displace_direction;
} u_push_constants;
#include "utils/camera.glsl"
#include "utils/constants_utils.glsl"
#include "utils/sample_mesh_texture.glsl"
#include "../utils/displace_utils.frag"
layout (set = 3, binding = 0) uniform sampler2D u_displace_mask;
layout (set = 3, binding = 1) uniform sampler2D u_displace_ssr;
void main()
{
#ifdef PBR_ENABLED
vec4 color = sampleMeshTexture0(f_material_id, f_uv) * f_vertex_color;
vec3 mixed_color = color.xyz;
float alpha = color.w;
mixed_color = convertColor(mixed_color);
if (u_ssr)
{
float alpha = sampleMeshTexture0(f_material_id, f_uv).a;
if (alpha == 0.0)
{
o_color = vec4(mixed_color * alpha, alpha);
return;
}
float horiz = sampleMeshTexture2(f_material_id, f_uv + u_push_constants.m_displace_direction.xy * 150.).x;
float vert = sampleMeshTexture2(f_material_id, (f_uv.yx + u_push_constants.m_displace_direction.zw * 150.) * vec2(0.9)).x;
vec2 shift = getDisplaceShift(horiz, vert);
ivec2 uv = getDisplaceUV(shift, u_camera.m_viewport, u_displace_mask);
vec3 reflection = texelFetch(u_displace_ssr, uv, 0).xyz;
o_color = vec4(mixed_color * alpha * 0.5 + reflection * alpha * 0.5 ,
alpha);
}
else
{
o_color = vec4(mixed_color * alpha, alpha);
}
#endif
}
@@ -0,0 +1,7 @@
layout (location = 0) out vec2 f_uv;
void main()
{
f_uv = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2);
gl_Position = vec4(f_uv * 2.0 - 1.0, 1.0, 1.0);
}
+38
View File
@@ -0,0 +1,38 @@
layout(location = 0) in vec4 f_vertex_color;
layout(location = 1) in vec2 f_uv;
layout(location = 3) flat in int f_material_id;
layout(location = 4) in float f_hue_change;
layout(location = 0) out vec4 o_color;
#include "utils/constants_utils.glsl"
#include "utils/sample_mesh_texture.glsl"
#include "../utils/rgb_conversion.frag"
void main()
{
vec4 tex_color = sampleMeshTexture0(f_material_id, f_uv);
if (f_hue_change > 0.0)
{
float mask = tex_color.a;
vec3 old_hsv = rgbToHsv(tex_color.rgb);
float mask_step = step(mask, 0.5);
#ifndef PBR_ENABLED
// For similar color
float saturation = mask * 1.825; // 2.5 * 0.5 ^ (1. / 2.2)
#else
float saturation = mask * 2.5;
#endif
vec2 new_xy = mix(vec2(old_hsv.x, old_hsv.y), vec2(f_hue_change,
max(old_hsv.y, saturation)), vec2(mask_step, mask_step));
vec3 new_color = hsvToRgb(vec3(new_xy.x, new_xy.y, old_hsv.z));
tex_color = vec4(new_color.r, new_color.g, new_color.b, 1.0);
}
vec3 mixed_color = tex_color.xyz * f_vertex_color.xyz;
#ifdef PBR_ENABLED
mixed_color = convertColor(mixed_color);
#endif
o_color = vec4(mixed_color * 0.5, 0.5);
}
+35
View File
@@ -0,0 +1,35 @@
#include "utils/camera.glsl"
#include "utils/spm_data.glsl"
#include "utils/spm_layout.vert"
#include "../utils/get_world_location.vert"
layout(push_constant) uniform Constants
{
vec3 m_wind_direction;
} u_push_constants;
void main()
{
vec3 offset = sin(u_push_constants.m_wind_direction * (v_position.y * 0.1));
offset += vec3(cos(u_push_constants.m_wind_direction) * 0.7);
vec4 v_world_position = getWorldPosition(
u_object_buffer.m_objects[gl_InstanceIndex].m_translation + offset *
v_color.r,
u_object_buffer.m_objects[gl_InstanceIndex].m_rotation,
u_object_buffer.m_objects[gl_InstanceIndex].m_scale, v_position);
f_world_position = v_world_position;
gl_Position = u_camera.m_projection_view_matrix * v_world_position;
f_vertex_color = vec4(1.0);
f_uv = v_uv;
f_uv_two = v_uv_two;
f_material_id = u_object_buffer.m_objects[gl_InstanceIndex].m_material_id;
#ifdef BIND_MESH_TEXTURES_AT_ONCE
if (f_material_id < 0)
f_material_id = u_material_ids.m_material_id[gl_DrawIDARB];
#endif
f_hue_change = u_object_buffer.m_objects[gl_InstanceIndex].m_hue_change;
#ifdef PBR_ENABLED
f_normal = rotateVector(u_object_buffer.m_objects[gl_InstanceIndex].m_rotation, v_normal.xyz);
#endif
}
+62
View File
@@ -0,0 +1,62 @@
layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in;
layout(binding = 0) uniform sampler2D u_depth;
layout(binding = 1, r32f) uniform writeonly image2D u_hiz_depth;
layout(push_constant) uniform PushConstants
{
ivec3 u_offset_miplevel;
} pc;
void main()
{
ivec2 dst = ivec2(gl_GlobalInvocationID.xy);
ivec2 current_size = imageSize(u_hiz_depth);
if (dst.x >= current_size.x || dst.y >= current_size.y)
return;
if (pc.u_offset_miplevel.z == 0)
{
// at level 0, do a 1:1 copy
float d = texelFetch(u_depth, dst + pc.u_offset_miplevel.xy, 0).r;
imageStore(u_hiz_depth, dst, vec4(d));
}
else
{
// at higher mip levels, read a 2×2 block from previous level
ivec2 src = dst * 2;
int prev_level = pc.u_offset_miplevel.z - 1;
ivec2 prev_size = textureSize(u_depth, prev_level);
float d0 = texelFetch(u_depth, src + ivec2(0, 0), prev_level).r;
float d1 = texelFetch(u_depth, src + ivec2(1, 0), prev_level).r;
float d2 = texelFetch(u_depth, src + ivec2(0, 1), prev_level).r;
float d3 = texelFetch(u_depth, src + ivec2(1, 1), prev_level).r;
float min_depth = min(min(d0, d1), min(d2, d3));
//float max_depth = max(max(d0, d1), max(d2, d3));
bool extra_sample_x = (current_size.x * 2) < prev_size.x;
bool extra_sample_y = (current_size.y * 2) < prev_size.y;
if (extra_sample_x)
{
float d4 = texelFetch(u_depth, src + ivec2(2, 0), prev_level).r;
float d5 = texelFetch(u_depth, src + ivec2(2, 1), prev_level).r;
min_depth = min(min_depth, min(d4, d5));
//max_depth = max(max_depth, max(d4, d5));
}
if (extra_sample_y)
{
float d6 = texelFetch(u_depth, src + ivec2(0, 2), prev_level).r;
float d7 = texelFetch(u_depth, src + ivec2(1, 2), prev_level).r;
min_depth = min(min_depth, min(d6, d7));
//max_depth = max(max_depth, max(d6, d7));
}
if (extra_sample_x && extra_sample_y)
{
float d8 = texelFetch(u_depth, src + ivec2(2, 2), prev_level).r;
min_depth = min(min_depth, d8);
//max_depth = max(max_depth, d8);
}
imageStore(u_hiz_depth, dst, vec4(min_depth));
//imageStore(u_hiz_depth, dst, vec4(min_depth, max_depth, 0.0, 0.0));
}
}
+69
View File
@@ -0,0 +1,69 @@
layout(location = 0) in vec4 f_vertex_color;
layout(location = 1) in vec2 f_uv;
layout(location = 3) flat in int f_material_id;
layout(location = 4) in float f_hue_change;
#ifdef PBR_ENABLED
layout(location = 5) in vec3 f_normal;
layout(location = 6) in vec3 f_tangent;
layout(location = 7) in vec3 f_bitangent;
layout(location = 8) in vec4 f_world_position;
#endif
layout(location = 0) out vec4 o_color;
#include "utils/sample_mesh_texture.glsl"
#include "../utils/rgb_conversion.frag"
#ifdef PBR_ENABLED
#include "utils/handle_pbr.glsl"
#include "../utils/encode_normal.frag"
layout(location = 1) out vec4 o_normal;
#endif
void main()
{
vec4 tex_color = sampleMeshTexture0(f_material_id, f_uv);
if (f_hue_change > 0.0)
{
float mask = tex_color.a;
vec3 old_hsv = rgbToHsv(tex_color.rgb);
float mask_step = step(mask, 0.5);
#ifndef PBR_ENABLED
// For similar color
float saturation = mask * 1.825; // 2.5 * 0.5 ^ (1. / 2.2)
#else
float saturation = mask * 2.5;
#endif
vec2 new_xy = mix(vec2(old_hsv.x, old_hsv.y), vec2(f_hue_change,
max(old_hsv.y, saturation)), vec2(mask_step, mask_step));
vec3 new_color = hsvToRgb(vec3(new_xy.x, new_xy.y, old_hsv.z));
tex_color = vec4(new_color.r, new_color.g, new_color.b, 1.0);
}
#ifndef PBR_ENABLED
vec3 mixed_color = tex_color.xyz * f_vertex_color.xyz;
o_color = vec4(mixed_color, 1.0);
#else
vec3 diffuse_color = tex_color.xyz * f_vertex_color.xyz;
vec4 layer_3 = sampleMeshTexture3(f_material_id, f_uv);
vec3 tangent_space_normal = 2.0 * layer_3.xyz - 1.0;
vec3 frag_tangent = normalize(f_tangent);
vec3 frag_bitangent = normalize(f_bitangent);
vec3 frag_normal = normalize(f_normal);
mat3 t_b_n = mat3(frag_tangent, frag_bitangent, frag_normal);
vec3 normal = normalize(t_b_n * tangent_space_normal);
vec3 pbr = sampleMeshTexture2(f_material_id, f_uv).xyz;
if (u_deferred)
{
o_color = vec4(diffuse_color, pbr.z);
o_normal.xy = EncodeNormal(normal);
o_normal.zw = pbr.xy;
}
else
{
o_color = vec4(handlePBR(diffuse_color, pbr, f_world_position, normal),
1.0);
}
#endif
}
+113
View File
@@ -0,0 +1,113 @@
<?xml version="1.0" encoding="UTF-8"?>
<shader-settings>
<setting name="solid">
<shaders>
<vertex>spm.vert</vertex>
<fragment>solid.frag</fragment>
<depth>depth_only.frag</depth>
<skinning-vertex>spm_skinning.vert</skinning-vertex>
</shaders>
</setting>
<setting name="normalmap">
<properties>
<nonpbr-fallback>solid</nonpbr-fallback>
</properties>
<shaders>
<vertex>spm.vert</vertex>
<fragment>normalmap.frag</fragment>
<depth>depth_only.frag</depth>
<skinning-vertex>spm_skinning.vert</skinning-vertex>
</shaders>
</setting>
<setting name="decal">
<shaders>
<vertex>spm.vert</vertex>
<fragment>decal.frag</fragment>
<depth>depth_only.frag</depth>
<skinning-vertex>spm_skinning.vert</skinning-vertex>
</shaders>
</setting>
<setting name="splatting">
<properties>
<nonpbr-fallback>solid</nonpbr-fallback>
<srgb-settings>YNYYYY</srgb-settings>
</properties>
<shaders>
<vertex>spm.vert</vertex>
<fragment>splatting.frag</fragment>
<depth>depth_only.frag</depth>
</shaders>
</setting>
<setting name="alphatest">
<shaders>
<vertex>spm.vert</vertex>
<fragment>alphatest.frag</fragment>
<depth>alphatest_depth.frag</depth>
<skinning-vertex>spm_skinning.vert</skinning-vertex>
</shaders>
</setting>
<setting name="unlit">
<properties>
<nonpbr-fallback>alphatest</nonpbr-fallback>
</properties>
<shaders>
<vertex>spm.vert</vertex>
<fragment>unlit.frag</fragment>
<depth>alphatest_depth.frag</depth>
<skinning-vertex>spm_skinning.vert</skinning-vertex>
</shaders>
</setting>
<setting name="grass">
<shaders>
<vertex>grass.vert</vertex>
<fragment>alphatest.frag</fragment>
<depth>alphatest_depth.frag</depth>
</shaders>
</setting>
<setting name="alphablend">
<properties>
<alphablend>true</alphablend>
<depth-write>false</depth-write>
<backface-culling>false</backface-culling>
</properties>
<shaders>
<vertex>spm.vert</vertex>
<fragment>transparent.frag</fragment>
<skinning-vertex>spm_skinning.vert</skinning-vertex>
</shaders>
</setting>
<setting name="additive">
<properties>
<additive>true</additive>
<depth-write>false</depth-write>
<backface-culling>false</backface-culling>
</properties>
<shaders>
<vertex>spm.vert</vertex>
<fragment>transparent.frag</fragment>
<skinning-vertex>spm_skinning.vert</skinning-vertex>
</shaders>
</setting>
<setting name="displace">
<properties>
<alphablend>true</alphablend>
<depth-write>false</depth-write>
<backface-culling>false</backface-culling>
<nonpbr-fallback>alphablend</nonpbr-fallback>
</properties>
<shaders>
<vertex>spm.vert</vertex>
<fragment>displace_transparent.frag</fragment>
</shaders>
</setting>
</shader-settings>
+20
View File
@@ -0,0 +1,20 @@
layout(location = 0) in vec2 f_uv;
layout(binding = 2) uniform samplerCube f_skybox_texture;
layout(binding = 3) uniform samplerCube f_skybox_texture_srgb;
layout(location = 0) out vec4 o_color;
#include "utils/camera.glsl"
#include "utils/constants_utils.glsl"
void main()
{
vec2 uv = 2.0f * f_uv - 1.0f;
vec4 front = u_camera.m_inverse_projection_view_matrix * vec4(uv, -1.0, 1.0);
vec4 back = u_camera.m_inverse_projection_view_matrix * vec4(uv, 1.0, 1.0);
vec3 dir = back.xyz / back.w - front.xyz / front.w;
if (u_deferred)
o_color = texture(f_skybox_texture_srgb, dir);
else
o_color = texture(f_skybox_texture, dir);
}
+59
View File
@@ -0,0 +1,59 @@
layout(location = 0) in vec4 f_vertex_color;
layout(location = 1) in vec2 f_uv;
layout(location = 3) flat in int f_material_id;
layout(location = 4) in float f_hue_change;
#ifdef PBR_ENABLED
layout(location = 5) in vec3 f_normal;
layout(location = 8) in vec4 f_world_position;
#endif
layout(location = 0) out vec4 o_color;
#include "utils/sample_mesh_texture.glsl"
#include "../utils/rgb_conversion.frag"
#ifdef PBR_ENABLED
#include "utils/handle_pbr.glsl"
#include "../utils/encode_normal.frag"
layout(location = 1) out vec4 o_normal;
#endif
void main()
{
vec4 tex_color = sampleMeshTexture0(f_material_id, f_uv);
if (f_hue_change > 0.0)
{
float mask = tex_color.a;
vec3 old_hsv = rgbToHsv(tex_color.rgb);
float mask_step = step(mask, 0.5);
#ifndef PBR_ENABLED
// For similar color
float saturation = mask * 1.825; // 2.5 * 0.5 ^ (1. / 2.2)
#else
float saturation = mask * 2.5;
#endif
vec2 new_xy = mix(vec2(old_hsv.x, old_hsv.y), vec2(f_hue_change,
max(old_hsv.y, saturation)), vec2(mask_step, mask_step));
vec3 new_color = hsvToRgb(vec3(new_xy.x, new_xy.y, old_hsv.z));
tex_color = vec4(new_color.r, new_color.g, new_color.b, 1.0);
}
#ifndef PBR_ENABLED
vec3 mixed_color = tex_color.xyz * f_vertex_color.xyz;
o_color = vec4(mixed_color, 1.0);
#else
vec3 diffuse_color = tex_color.xyz * f_vertex_color.xyz;
vec3 normal = normalize(f_normal.xyz);
vec3 pbr = sampleMeshTexture2(f_material_id, f_uv).xyz;
if (u_deferred)
{
o_color = vec4(diffuse_color, pbr.z);
o_normal.xy = EncodeNormal(normal);
o_normal.zw = pbr.xy;
}
else
{
o_color = vec4(handlePBR(diffuse_color, pbr, f_world_position, normal),
1.0);
}
#endif
}
@@ -0,0 +1,82 @@
layout (local_size_x = 16, local_size_y = 16, local_size_z = 1) in;
// Binding for the input skybox cubemap.
layout(set = 0, binding = 0) uniform samplerCube uSkybox;
// Output prefiltered environment specular map (stored as a 2D array for cube faces).
#ifdef SHADER_STORAGE_IMAGE_EXTENDED_FORMATS
layout(set = 0, binding = 1, rgb10_a2) uniform restrict writeonly image2DArray uPrefilterMap;
#else
layout(set = 0, binding = 1, rgba8) uniform restrict writeonly image2DArray uPrefilterMap;
#endif
#include "utils/environment_map.glsl"
#include "utils/pbr_utils.glsl"
void main()
{
ivec2 pix = ivec2(gl_GlobalInvocationID.xy);
if (pix.x >= pc.size || pix.y >= pc.size) return;
// Get normalized UV for current pixel.
vec2 uv = (vec2(pix) + 0.5) / vec2(pc.size, pc.size);
int face = int(gl_GlobalInvocationID.z);
float roughness = float(pc.mipmapLevel) / float(pc.mipmapCount - 1);
vec3 R = FaceUVtoDir(face, uv);
vec3 V = normalize(R);
// Don't need to sample skybox when roughness is 0.
// Since it's a perfect reflector.
if (roughness == 0.0)
{
vec4 color = textureLod(uSkybox, V, 0);
imageStore(uPrefilterMap, ivec3(pix, face), color);
return;
}
vec3 prefilteredColor = vec3(0.0);
float totalWeight = 0.0;
uint sampleCount = uint(pc.sampleCount);
for (uint i = 0u; i < sampleCount; ++i)
{
vec2 xi = Hammersley(i, sampleCount);
// Importance sampling with a GGX distribution.
float a = roughness * roughness;
float phi = 2.0 * PI * xi.x;
// GGX importance sampling for the cosine of the angle.
float cosTheta = sqrt((1.0 - xi.y) / (1.0 + (a * a - 1.0) * xi.y));
float sinTheta = sqrt(1.0 - cosTheta * cosTheta);
vec3 H = vec3(cos(phi) * sinTheta, sin(phi) * sinTheta, cosTheta);
// Construct TBN basis from view direction V.
vec3 up = abs(V.y) < 0.999 ? vec3(0.0, 1.0, 0.0) : vec3(1.0, 0.0, 0.0);
vec3 tangent = normalize(cross(up, V));
vec3 bitangent = cross(V, tangent);
mat3 TBN = mat3(tangent, bitangent, V);
H = normalize(TBN * H);
// Compute reflection vector L.
vec3 L = normalize(reflect(-V, H));
float NdotL = max(dot(V, L), 0.0);
if (NdotL > 0.0)
{
// Calculate the mip level based on the PDF.
// In a skybox/environment map scenario, N = V.
float NoH = max(dot(V, H), 0.0);
float VoH = max(dot(V, H), 0.0);
float D = D_GGX(roughness, NoH);
float pdf = D * NoH / (4.0 * VoH);
float omegaS = 1.0 / (float(sampleCount) * pdf);
float omegaP = 4.0 * PI / (6.0 * float(pc.size * pc.size));
float mipLevel = 0.5 * log2(omegaS / omegaP);
vec3 sampleColor = textureLod(uSkybox, L, mipLevel).rgb;
prefilteredColor += sampleColor * NdotL;
totalWeight += NdotL;
}
}
prefilteredColor = prefilteredColor / totalWeight;
imageStore(uPrefilterMap, ivec3(pix, face), vec4(prefilteredColor, 1.0));
}
+71
View File
@@ -0,0 +1,71 @@
layout(location = 1) in vec2 f_uv;
layout(location = 2) in vec2 f_uv_two;
layout(location = 3) flat in int f_material_id;
layout(location = 5) in vec3 f_normal;
layout(location = 8) in vec4 f_world_position;
layout(location = 0) out vec4 o_color;
layout(location = 1) out vec4 o_normal;
#include "utils/sample_mesh_texture.glsl"
#include "utils/handle_pbr.glsl"
#include "../utils/encode_normal.frag"
#define HIGH_RES_SAMPLER 1.0f
#define LOW_RES_SAMPLER 0.5f
#ifdef PBR_ENABLED
vec4 sampleMultiResTextureLayer2(float factor, int material_id, vec2 uv)
{
return mix(sampleMeshTexture2(material_id, uv * HIGH_RES_SAMPLER), sampleMeshTexture2(material_id, uv * LOW_RES_SAMPLER), factor);
}
vec4 sampleMultiResTextureLayer3(float factor, int material_id, vec2 uv)
{
return mix(sampleMeshTexture3(material_id, uv * HIGH_RES_SAMPLER), sampleMeshTexture3(material_id, uv * LOW_RES_SAMPLER), factor);
}
vec4 sampleMultiResTextureLayer4(float factor, int material_id, vec2 uv)
{
return mix(sampleMeshTexture4(material_id, uv * HIGH_RES_SAMPLER), sampleMeshTexture4(material_id, uv * LOW_RES_SAMPLER), factor);
}
vec4 sampleMultiResTextureLayer5(float factor, int material_id, vec2 uv)
{
return mix(sampleMeshTexture5(material_id, uv * HIGH_RES_SAMPLER), sampleMeshTexture5(material_id, uv * LOW_RES_SAMPLER), factor);
}
#endif
void main()
{
#ifdef PBR_ENABLED
// mitigate repetitive patterns
float cam_dist = length(u_camera.m_view_matrix * f_world_position);
float mitigation = clamp(pow(cam_dist * 0.01, 2.0) - 0., 0., 1.);
// Splatting part
vec4 splatting = sampleMeshTexture1(f_material_id, f_uv_two);
vec4 detail0 = sampleMultiResTextureLayer2(mitigation, f_material_id, f_uv);
vec4 detail1 = sampleMultiResTextureLayer3(mitigation, f_material_id, f_uv);
vec4 detail2 = sampleMultiResTextureLayer4(mitigation, f_material_id, f_uv);
vec4 detail3 = sampleMultiResTextureLayer5(mitigation, f_material_id, f_uv);
vec4 splatted = splatting.r * detail0 +
splatting.g * detail1 +
splatting.b * detail2 +
max(0.0, (1.0 - splatting.r - splatting.g - splatting.b)) * detail3;
vec3 normal = normalize(f_normal.xyz);
if (u_deferred)
{
o_color = vec4(splatted.xyz, 0.0);
o_normal.xy = EncodeNormal(normal);
o_normal.zw = vec2(0.0);
}
else
{
o_color = vec4(handlePBR(splatted.xyz, vec3(0.0), f_world_position,
normal), 1.0);
}
#endif
}
+32
View File
@@ -0,0 +1,32 @@
#include "utils/camera.glsl"
#include "utils/get_vertex_color.glsl"
#include "utils/spm_data.glsl"
#include "utils/spm_layout.vert"
#include "../utils/get_world_location.vert"
void main()
{
vec4 v_world_position = getWorldPosition(
u_object_buffer.m_objects[gl_InstanceIndex].m_translation,
u_object_buffer.m_objects[gl_InstanceIndex].m_rotation,
u_object_buffer.m_objects[gl_InstanceIndex].m_scale, v_position);
f_world_position = v_world_position;
gl_Position = u_camera.m_projection_view_matrix * v_world_position;
f_vertex_color = v_color.zyxw * getVertexColor(
u_object_buffer.m_objects[gl_InstanceIndex].m_custom_vertex_color);
f_uv = v_uv + u_object_buffer.m_objects[gl_InstanceIndex].m_texture_trans;
f_uv_two = v_uv_two;
f_material_id = u_object_buffer.m_objects[gl_InstanceIndex].m_material_id;
#ifdef BIND_MESH_TEXTURES_AT_ONCE
if (f_material_id < 0)
f_material_id = u_material_ids.m_material_id[gl_DrawIDARB];
#endif
f_hue_change = u_object_buffer.m_objects[gl_InstanceIndex].m_hue_change;
#ifdef PBR_ENABLED
vec3 world_normal = rotateVector(u_object_buffer.m_objects[gl_InstanceIndex].m_rotation, v_normal.xyz);
vec3 world_tangent = rotateVector(u_object_buffer.m_objects[gl_InstanceIndex].m_rotation, v_tangent.xyz);
f_bitangent = cross(world_normal, world_tangent) * v_tangent.w;
f_tangent = world_tangent;
f_normal = world_normal;
#endif
}
+42
View File
@@ -0,0 +1,42 @@
#include "utils/camera.glsl"
#include "utils/get_vertex_color.glsl"
#include "utils/spm_data.glsl"
#include "utils/spm_layout.vert"
#include "../utils/get_world_location.vert"
void main()
{
int offset = u_object_buffer.m_objects[gl_InstanceIndex].m_skinning_offset;
mat4 joint_matrix =
v_weight[0] * u_skinning_matrices.m_mat[max(v_joint[0] + offset, 0)] +
v_weight[1] * u_skinning_matrices.m_mat[max(v_joint[1] + offset, 0)] +
v_weight[2] * u_skinning_matrices.m_mat[max(v_joint[2] + offset, 0)] +
v_weight[3] * u_skinning_matrices.m_mat[max(v_joint[3] + offset, 0)];
vec4 v_skinning_position = joint_matrix * vec4(v_position, 1.0);
vec4 v_world_position = getWorldPosition(
u_object_buffer.m_objects[gl_InstanceIndex].m_translation,
u_object_buffer.m_objects[gl_InstanceIndex].m_rotation,
u_object_buffer.m_objects[gl_InstanceIndex].m_scale,
v_skinning_position.xyz);
f_world_position = v_world_position;
gl_Position = u_camera.m_projection_view_matrix * v_world_position;
f_vertex_color = v_color.zyxw * getVertexColor(
u_object_buffer.m_objects[gl_InstanceIndex].m_custom_vertex_color);
f_uv = v_uv + u_object_buffer.m_objects[gl_InstanceIndex].m_texture_trans;
f_uv_two = v_uv_two;
f_material_id = u_object_buffer.m_objects[gl_InstanceIndex].m_material_id;
#ifdef BIND_MESH_TEXTURES_AT_ONCE
if (f_material_id < 0)
f_material_id = u_material_ids.m_material_id[gl_DrawIDARB];
#endif
f_hue_change = u_object_buffer.m_objects[gl_InstanceIndex].m_hue_change;
#ifdef PBR_ENABLED
vec4 skinned_normal = joint_matrix * v_normal;
vec4 skinned_tangent = joint_matrix * vec4(v_tangent.xyz, 0.0);
vec3 world_normal = rotateVector(u_object_buffer.m_objects[gl_InstanceIndex].m_rotation, skinned_normal.xyz);
vec3 world_tangent = rotateVector(u_object_buffer.m_objects[gl_InstanceIndex].m_rotation, skinned_tangent.xyz);
f_bitangent = cross(world_normal, world_tangent) * v_tangent.w;
f_tangent = world_tangent;
f_normal = world_normal;
#endif
}
+19
View File
@@ -0,0 +1,19 @@
layout(location = 0) in vec4 f_vertex_color;
layout(location = 1) in vec2 f_uv;
layout(location = 3) flat in int f_material_id;
layout(location = 0) out vec4 o_color;
#include "utils/constants_utils.glsl"
#include "utils/sample_mesh_texture.glsl"
void main()
{
vec4 color = sampleMeshTexture0(f_material_id, f_uv) * f_vertex_color;
vec3 mixed_color = color.xyz;
float alpha = color.w;
#ifdef PBR_ENABLED
mixed_color = convertColor(mixed_color);
#endif
o_color = vec4(mixed_color * alpha, alpha);
}
+45
View File
@@ -0,0 +1,45 @@
layout(location = 0) in vec4 f_vertex_color;
layout(location = 1) in vec2 f_uv;
layout(location = 3) flat in int f_material_id;
layout(location = 4) in float f_hue_change;
layout(location = 5) in vec3 f_normal;
layout(location = 8) in vec4 f_world_position;
layout(location = 0) out vec4 o_color;
layout(location = 1) out vec4 o_normal;
#include "utils/sample_mesh_texture.glsl"
#include "../utils/rgb_conversion.frag"
#include "utils/handle_pbr.glsl"
#include "../utils/encode_normal.frag"
void main()
{
#ifdef PBR_ENABLED
vec4 tex_color = sampleMeshTexture0(f_material_id, f_uv);
if (tex_color.a * f_vertex_color.a < 0.5)
discard;
if (f_hue_change > 0.0)
{
vec3 old_hsv = rgbToHsv(tex_color.rgb);
vec2 new_xy = vec2(f_hue_change, old_hsv.y);
vec3 new_color = hsvToRgb(vec3(new_xy.x, new_xy.y, old_hsv.z));
tex_color = vec4(new_color.r, new_color.g, new_color.b, tex_color.a);
}
vec3 diffuse_color = tex_color.xyz * f_vertex_color.xyz;
vec3 normal = normalize(f_normal.xyz);
if (u_deferred)
{
o_color = vec4(diffuse_color, 0.4);
o_normal.xy = EncodeNormal(normal);
o_normal.zw = vec2(0.0);
}
else
{
vec3 pbr = vec3(0.0, 0.0, 0.4);
o_color = vec4(handlePBR(diffuse_color, pbr, f_world_position, normal),
1.0);
}
#endif
}
+12
View File
@@ -0,0 +1,12 @@
layout(std140, set = 1, binding = 0) uniform CameraBuffer
{
mat4 m_view_matrix;
mat4 m_projection_matrix;
mat4 m_inverse_view_matrix;
mat4 m_inverse_projection_matrix;
mat4 m_projection_view_matrix;
mat4 m_inverse_projection_view_matrix;
vec4 m_viewport;
vec2 m_screensize;
vec2 m_padding;
} u_camera;
@@ -0,0 +1,20 @@
layout (constant_id = 0) const bool u_ibl = true;
layout (constant_id = 1) const float u_specular_levels_minus_one = 0.0;
layout (constant_id = 2) const bool u_deferred = false;
layout (constant_id = 3) const bool u_has_skybox = true;
layout (constant_id = 4) const bool u_ssr = false;
layout (constant_id = 5) const uint u_hiz_iterations = 0;
vec3 convertColor(vec3 input_color)
{
if (u_ibl)
{
return (input_color * (6.5 * input_color + 0.45)) /
(input_color * (5.0 * input_color + 1.75) + 0.05);
}
else
{
return (input_color * (7.0 * input_color + 0.75)) /
(input_color * (5.0 * input_color + 1.75) + 0.05);
}
}
@@ -0,0 +1,47 @@
// Push constants to pass face index, dimensions, and sample count.
layout(push_constant) uniform PushConstants {
int size; // width and height for current mipmap level
int sampleCount; // number of samples for integration
int mipmapLevel; // current mipmap level
int mipmapCount; // total mipmap levels
} pc;
// Returns the radical inverse of "bits" with base 2.
float RadicalInverse_VdC(uint bits)
{
bits = (bits << 16u) | (bits >> 16u);
bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
return float(bits) * 2.3283064365386963e-10;
}
// Generate a 2D Hammersley sequence value.
vec2 Hammersley(uint i, uint N)
{
return vec2(float(i) / float(N), RadicalInverse_VdC(i));
}
// Converts face index and UV coordinates in [0,1] to a normalized direction vector.
vec3 FaceUVtoDir(int face, vec2 uv)
{
// Map UV from [0, 1] to [-1, 1]
uv = uv * 2.0 - 1.0;
vec3 dir;
if (face == 0) // +X
dir = vec3(1.0, -uv.y, -uv.x);
else if (face == 1) // -X
dir = vec3(-1.0, -uv.y, uv.x);
else if (face == 2) // +Y
dir = vec3(uv.x, 1.0, uv.y);
else if (face == 3) // -Y
dir = vec3(uv.x, -1.0, -uv.y);
else if (face == 4) // +Z
dir = vec3(uv.x, -uv.y, 1.0);
else if (face == 5) // -Z
dir = vec3(-uv.x, -uv.y, -1.0);
return normalize(dir);
}
const float PI = 3.14159265359;
@@ -0,0 +1,9 @@
vec4 getVertexColor(uint packed)
{
vec4 vertex_color;
vertex_color.a = float(packed >> 24) / 255.0;
vertex_color.r = float((packed >> 16) & 0xff) / 255.0;
vertex_color.g = float((packed >> 8) & 0xff) / 255.0;
vertex_color.b = float(packed & 0xff) / 255.0;
return vertex_color;
}
@@ -0,0 +1,21 @@
struct LightData
{
vec4 m_position_radius;
vec4 m_color_inverse_square_range;
vec4 m_direction_scale_offset; // Spotlight only
};
const int MAX_LIGHT = 32;
layout(std140, set = 1, binding = 3) uniform GlobalLightBuffer
{
vec3 m_ambient_color;
float m_sun_scatter;
vec3 m_sun_color;
float m_sun_angle_tan_half;
vec3 m_sun_direction;
float m_fog_density;
vec4 m_fog_color;
vec3 m_skytop_color;
int m_light_count;
LightData m_lights[MAX_LIGHT];
} u_global_light;
@@ -0,0 +1,60 @@
layout (set = 2, binding = 0) uniform samplerCube u_diffuse;
layout (set = 2, binding = 1) uniform samplerCube u_specular;
#include "camera.glsl"
#include "constants_utils.glsl"
#include "spm_data.glsl"
#include "pbr_utils.glsl"
#include "global_light_data.glsl"
#include "pbr_light.glsl"
#include "sun_direction.glsl"
vec3 handlePBRDeferred(vec3 diffuse_color, vec3 pbr, vec3 world_normal,
vec3 eyedir, vec3 normal, float perceptual_roughness)
{
float radiance_level = perceptual_roughness * u_specular_levels_minus_one;
vec3 reflection = reflect(-eyedir, normal);
vec3 irradiance = vec3(0.0);
vec3 radiance = vec3(0.0);
if (u_ibl)
{
vec3 world_reflection = (u_camera.m_inverse_view_matrix *
vec4(reflection, 0.0)).xyz;
irradiance = texture(u_diffuse, world_normal).rgb;
radiance = textureLod(u_specular, world_reflection, radiance_level).rgb;
}
vec3 lightdir = sunDirection(reflection,
u_global_light.m_sun_direction, u_global_light.m_sun_angle_tan_half,
u_camera.m_inverse_view_matrix);
vec3 mixed_color = PBRSunAmbientEmitLight(
normal, eyedir, lightdir, diffuse_color,
irradiance, radiance,
u_global_light.m_sun_color,
u_global_light.m_ambient_color,
perceptual_roughness, pbr.y, pbr.z);
return mixed_color;
}
vec3 handlePBR(vec3 diffuse_color, vec3 pbr, vec4 world_position,
vec3 world_normal)
{
vec3 xpos = (u_camera.m_view_matrix * world_position).xyz;
vec3 eyedir = -normalize(xpos);
vec3 normal = (u_camera.m_view_matrix * vec4(world_normal, 0.0)).xyz;
float perceptual_roughness = 1.0 - pbr.x;
vec3 mixed_color = handlePBRDeferred(diffuse_color, pbr, world_normal,
eyedir, normal, perceptual_roughness);
mixed_color += accumulateLights(u_global_light.m_light_count,
diffuse_color, normal, xpos, eyedir, perceptual_roughness, pbr.y);
//Disable for deferred shading
//float factor = (1.0 - exp(length(xpos) * -0.0001));
//mixed_color = mixed_color + vec3(0.5) * factor;
return convertColor(mixed_color);
}
@@ -0,0 +1,189 @@
vec3 PBRLight(
vec3 normal,
vec3 eyedir,
vec3 lightdir,
vec3 color,
float perceptual_roughness,
float metallic)
{
float NdotV = max(dot(normal, eyedir), 0.0001);
float NdotL = clamp(dot(normal, lightdir), 0.0, 1.0);
vec2 F_ab = F_AB(perceptual_roughness, NdotV);
vec3 H = normalize(eyedir + lightdir);
float NdotH = clamp(dot(normal, H), 0.0, 1.0);
float LdotH = clamp(dot(lightdir, H), 0.0, 1.0);
vec3 diffuse_color = color * (1.0 - metallic);
vec3 F0 = mix(vec3(0.04), color, metallic);
// No real world material has specular values under 0.02, so we use this range as a
// "pre-baked specular occlusion" that extinguishes the fresnel term, for artistic control.
// See: https://google.github.io/filament/Filament.html#specularocclusion
float F90 = clamp(dot(F0, vec3(50.0 * 0.33)), 0.0, 1.0);
float roughness = perceptualRoughnessToRoughness(perceptual_roughness);
vec3 diffuse = diffuse_color * Fd_Burley(roughness, NdotV, NdotL, NdotH);
float D = D_GGX(roughness, NdotH);
float V = V_Smith_GGX_Correlated(roughness, NdotV, NdotL);
vec3 F = fresnel(F0, F90, LdotH);
vec3 specular = D * V * F * (1.0 + F0 * (1.0 / F_ab.x - 1.0));
return NdotL * (diffuse + specular);
}
vec3 PBRSunAmbientEmitLight(
vec3 normal,
vec3 eyedir,
vec3 sundir,
vec3 color,
vec3 irradiance,
vec3 radiance,
vec3 sun_color,
vec3 ambient_color,
float perceptual_roughness,
float metallic,
float emissive)
{
// Copied from PBRLight to use F_ab and F90 again
float NdotV = max(dot(normal, eyedir), 0.0001);
float NdotL = clamp(dot(normal, sundir), 0.0, 1.0);
vec2 F_ab = F_AB(perceptual_roughness, NdotV);
vec3 H = normalize(eyedir + sundir);
float NdotH = clamp(dot(normal, H), 0.0, 1.0);
float LdotH = clamp(dot(sundir, H), 0.0, 1.0);
vec3 diffuse_color = color * (1.0 - metallic);
vec3 F0 = mix(vec3(0.04), color, metallic);
// No real world material has specular values under 0.02, so we use this range as a
// "pre-baked specular occlusion" that extinguishes the fresnel term, for artistic control.
// See: https://google.github.io/filament/Filament.html#specularocclusion
float F90 = clamp(dot(F0, vec3(50.0 * 0.33)), 0.0, 1.0);
float roughness = perceptualRoughnessToRoughness(perceptual_roughness);
vec3 diffuse = diffuse_color * Fd_Burley(roughness, NdotV, NdotL, NdotH);
float D = D_GGX(roughness, NdotH);
float V = V_Smith_GGX_Correlated(roughness, NdotV, NdotL);
vec3 F = fresnel(F0, F90, LdotH);
vec3 specular = D * V * F * (1.0 + F0 * (1.0 / F_ab.x - 1.0));
vec3 sunlight = NdotL * (diffuse + specular);
vec3 diffuse_ambient = envBRDFApprox(diffuse_color, F_AB(1.0, NdotV));
vec3 specular_ambient = F90 * envBRDFApprox(F0, F_ab);
// Other 0.6 comes from skybox
ambient_color *= 0.4;
vec3 environment;
if (u_ibl)
{
environment = environmentLight(irradiance, radiance, roughness,
diffuse_color, F_ab, F0, F90, NdotV);
}
else
{
environment = u_global_light.m_skytop_color * ambient_color *
diffuse_color;
}
vec3 emit = emissive * color * 4.0;
return sun_color * sunlight
+ environment + emit
+ (diffuse_ambient + specular_ambient) * ambient_color;
}
vec3 accumulateLights(int light_count, vec3 diffuse_color, vec3 normal,
vec3 xpos, vec3 eyedir, float perceptual_roughness,
float metallic)
{
vec3 accumulated_color = vec3(0.0);
for (int i = 0; i < light_count; i++)
{
vec3 light_to_frag = (u_camera.m_view_matrix *
vec4(u_global_light.m_lights[i].m_position_radius.xyz,
1.0)).xyz - xpos;
float invrange = u_global_light.m_lights[i].m_color_inverse_square_range.w;
float distance_sq = dot(light_to_frag, light_to_frag);
if (distance_sq * invrange > 1.)
continue;
// SpotLight
float sattenuation = 1.;
float sscale = u_global_light.m_lights[i].m_direction_scale_offset.z;
float distance = sqrt(distance_sq);
float distance_inverse = 1. / distance;
vec3 L = light_to_frag * distance_inverse;
if (sscale != 0.)
{
vec3 sdir =
vec3(u_global_light.m_lights[i].m_direction_scale_offset.xy, 0.);
sdir.z = sqrt(1. - dot(sdir, sdir)) * sign(sscale);
sdir = (u_camera.m_view_matrix * vec4(sdir, 0.0)).xyz;
sattenuation = clamp(dot(-sdir, L) *
abs(sscale) +
u_global_light.m_lights[i].m_direction_scale_offset.w, 0.0, 1.0);
#ifndef TILED_GPU
// Reduce branching in tiled GPU
if (sattenuation == 0.)
continue;
#endif
}
vec3 diffuse_specular = PBRLight(normal, eyedir, L, diffuse_color,
perceptual_roughness, metallic);
float attenuation = 20. / (1. + distance_sq);
float radius = u_global_light.m_lights[i].m_position_radius.w;
attenuation *= (radius - distance) / radius;
attenuation *= sattenuation * sattenuation;
vec3 light_color =
u_global_light.m_lights[i].m_color_inverse_square_range.xyz;
accumulated_color += light_color * attenuation * diffuse_specular;
}
return accumulated_color;
}
// Copied because reusing in a loop will be slower
vec3 calculateLight(int i, vec3 diffuse_color, vec3 normal, vec3 xpos,
vec3 eyedir, float perceptual_roughness, float metallic)
{
vec3 light_to_frag = (u_camera.m_view_matrix *
vec4(u_global_light.m_lights[i].m_position_radius.xyz,
1.0)).xyz - xpos;
float invrange = u_global_light.m_lights[i].m_color_inverse_square_range.w;
float distance_sq = dot(light_to_frag, light_to_frag);
if (distance_sq * invrange > 1.)
return vec3(0.0);
// SpotLight
float sattenuation = 1.;
float sscale = u_global_light.m_lights[i].m_direction_scale_offset.z;
float distance = sqrt(distance_sq);
float distance_inverse = 1. / distance;
vec3 L = light_to_frag * distance_inverse;
if (sscale != 0.)
{
vec3 sdir =
vec3(u_global_light.m_lights[i].m_direction_scale_offset.xy, 0.);
sdir.z = sqrt(1. - dot(sdir, sdir)) * sign(sscale);
sdir = (u_camera.m_view_matrix * vec4(sdir, 0.0)).xyz;
sattenuation = clamp(dot(-sdir, L) *
abs(sscale) +
u_global_light.m_lights[i].m_direction_scale_offset.w, 0.0, 1.0);
if (sattenuation == 0.)
return vec3(0.0);
}
vec3 diffuse_specular = PBRLight(normal, eyedir, L, diffuse_color,
perceptual_roughness, metallic);
float attenuation = 20. / (1. + distance_sq);
float radius = u_global_light.m_lights[i].m_position_radius.w;
attenuation *= (radius - distance) / radius;
attenuation *= sattenuation * sattenuation;
vec3 light_color =
u_global_light.m_lights[i].m_color_inverse_square_range.xyz;
return light_color * attenuation * diffuse_specular;
}
@@ -0,0 +1,91 @@
vec2 F_AB(float perceptual_roughness, float NdotV)
{
vec4 c0 = vec4(-1.0, -0.0275, -0.572, 0.022);
vec4 c1 = vec4(1.0, 0.0425, 1.04, -0.04);
vec4 r = perceptual_roughness * c0 + c1;
float a004 = min(r.x * r.x, pow(2.0, -9.28 * NdotV)) * r.x + r.y;
return vec2(-1.04, 1.04) * a004 + r.zw;
}
// Lambert model
float F_Schlick(float f0, float f90, float VdotH)
{
return mix(f0, f90, pow(1.0 - VdotH, 5.0));
}
float Fd_Burley(float roughness, float NdotV, float NdotL, float LdotH)
{
// Don't divide by Pi to avoid light being too dim.
float f90 = 0.5 + 2.0 * roughness * LdotH * LdotH;
float lightScatter = F_Schlick(1.0, f90, NdotL);
float viewScatter = F_Schlick(1.0, f90, NdotV);
return lightScatter * viewScatter;
}
// Calculate distribution.
// Based on https://google.github.io/filament/Filament.html#citation-walter07
// D_GGX(h,α) = α^2 / { π ((n⋅h)^2 (α21) + 1)^2 }
// Simple implementation, has precision problems when using fp16 instead of fp32
// see https://google.github.io/filament/Filament.html#listing_speculardfp16
float D_GGX(float roughness, float NdotH)
{
float oneMinusNdotHSquared = 1.0 - NdotH * NdotH;
float a = NdotH * roughness;
float k = roughness / (oneMinusNdotHSquared + a * a);
return k * k * (1.0 / 3.14159265359);
}
// Calculate visibility.
// Hammon 2017, "PBR Diffuse Lighting for GGX+Smith Microsurfaces"
// see https://google.github.io/filament/Filament.html#listing_approximatedspecularv
float V_Smith_GGX_Correlated(float roughness, float NdotV, float NdotL)
{
return 0.5 / mix(2.0 * NdotL * NdotV, NdotL + NdotV, roughness);
}
// Fresnel function
// see https://google.github.io/filament/Filament.html#citation-schlick94
// F_Schlick(v,h,f_0,f_90) = f_0 + (f_90 f_0) (1 v⋅h)^5
vec3 fresnel(vec3 f0, float f90, float VdotH)
{
return f0 + (f90 - f0) * pow(1.0 - VdotH, 5.0);
}
vec3 envBRDFApprox(vec3 F0, vec2 F_ab)
{
return F0 * F_ab.x + F_ab.y;
}
float perceptualRoughnessToRoughness(float perceptual_roughness)
{
float roughness = clamp(perceptual_roughness, 0.089, 1.0);
return roughness * roughness;
}
vec3 environmentLight(
vec3 irradiance,
vec3 radiance,
float roughness,
vec3 diffuse_color,
vec2 F_ab,
vec3 F0,
float F90,
float NdotV)
{
// Multiscattering approximation: https://www.jcgt.org/published/0008/01/03/paper.pdf
// Useful reference: https://bruop.github.io/ibl
vec3 Fr = max(vec3(1.0 - roughness), F0) - F0;
vec3 kS = F0 + Fr * pow(1.0 - NdotV, 5.0);
float Ess = F_ab.x + F_ab.y;
vec3 FssEss = kS * Ess * F90;
float Ems = 1.0 - Ess;
vec3 Favg = F0 + (1.0 - F0) / 21.0;
vec3 Fms = FssEss * Favg / (1.0 - Ems * Favg);
vec3 FmsEms = Fms * Ems;
vec3 Edss = 1.0 - (FssEss + FmsEms);
vec3 kD = diffuse_color * Edss;
vec3 diffuse = (FmsEms + kD) * irradiance;
vec3 specular = FssEss * radiance;
return diffuse + specular;
}
@@ -0,0 +1,104 @@
#ifdef BIND_MESH_TEXTURES_AT_ONCE
layout(binding = 0) uniform sampler2D f_mesh_textures[SAMPLER_SIZE * TOTAL_MESH_TEXTURE_LAYER];
vec4 sampleMeshTexture0(int material_id, vec2 uv)
{
int id = (TOTAL_MESH_TEXTURE_LAYER * material_id) + 0;
return texture(f_mesh_textures[GE_SAMPLE_TEX_INDEX(id)], uv);
}
vec4 sampleMeshTexture1(int material_id, vec2 uv)
{
int id = (TOTAL_MESH_TEXTURE_LAYER * material_id) + 1;
return texture(f_mesh_textures[GE_SAMPLE_TEX_INDEX(id)], uv);
}
vec4 sampleMeshTexture2(int material_id, vec2 uv)
{
int id = (TOTAL_MESH_TEXTURE_LAYER * material_id) + 2;
return texture(f_mesh_textures[GE_SAMPLE_TEX_INDEX(id)], uv);
}
vec4 sampleMeshTexture3(int material_id, vec2 uv)
{
int id = (TOTAL_MESH_TEXTURE_LAYER * material_id) + 3;
return texture(f_mesh_textures[GE_SAMPLE_TEX_INDEX(id)], uv);
}
vec4 sampleMeshTexture4(int material_id, vec2 uv)
{
int id = (TOTAL_MESH_TEXTURE_LAYER * material_id) + 4;
return texture(f_mesh_textures[GE_SAMPLE_TEX_INDEX(id)], uv);
}
vec4 sampleMeshTexture5(int material_id, vec2 uv)
{
int id = (TOTAL_MESH_TEXTURE_LAYER * material_id) + 5;
return texture(f_mesh_textures[GE_SAMPLE_TEX_INDEX(id)], uv);
}
vec4 sampleMeshTexture6(int material_id, vec2 uv)
{
int id = (TOTAL_MESH_TEXTURE_LAYER * material_id) + 6;
return texture(f_mesh_textures[GE_SAMPLE_TEX_INDEX(id)], uv);
}
vec4 sampleMeshTexture7(int material_id, vec2 uv)
{
int id = (TOTAL_MESH_TEXTURE_LAYER * material_id) + 7;
return texture(f_mesh_textures[GE_SAMPLE_TEX_INDEX(id)], uv);
}
#else
layout(binding = 0) uniform sampler2D f_mesh_texture_0;
layout(binding = 1) uniform sampler2D f_mesh_texture_1;
#ifdef PBR_ENABLED
layout(binding = 2) uniform sampler2D f_mesh_texture_2;
layout(binding = 3) uniform sampler2D f_mesh_texture_3;
layout(binding = 4) uniform sampler2D f_mesh_texture_4;
layout(binding = 5) uniform sampler2D f_mesh_texture_5;
layout(binding = 6) uniform sampler2D f_mesh_texture_6;
layout(binding = 7) uniform sampler2D f_mesh_texture_7;
#endif
vec4 sampleMeshTexture0(int material_id, vec2 uv)
{
return texture(f_mesh_texture_0, uv);
}
vec4 sampleMeshTexture1(int material_id, vec2 uv)
{
return texture(f_mesh_texture_1, uv);
}
#ifdef PBR_ENABLED
vec4 sampleMeshTexture2(int material_id, vec2 uv)
{
return texture(f_mesh_texture_2, uv);
}
vec4 sampleMeshTexture3(int material_id, vec2 uv)
{
return texture(f_mesh_texture_3, uv);
}
vec4 sampleMeshTexture4(int material_id, vec2 uv)
{
return texture(f_mesh_texture_4, uv);
}
vec4 sampleMeshTexture5(int material_id, vec2 uv)
{
return texture(f_mesh_texture_5, uv);
}
vec4 sampleMeshTexture6(int material_id, vec2 uv)
{
return texture(f_mesh_texture_6, uv);
}
vec4 sampleMeshTexture7(int material_id, vec2 uv)
{
return texture(f_mesh_texture_7, uv);
}
#endif
#endif
@@ -0,0 +1,31 @@
#ifdef BIND_MESH_TEXTURES_AT_ONCE
#extension GL_ARB_shader_draw_parameters : enable
#endif
struct ObjectData
{
vec3 m_translation;
float m_hue_change;
vec4 m_rotation;
vec3 m_scale;
uint m_custom_vertex_color;
int m_skinning_offset;
int m_material_id;
vec2 m_texture_trans;
};
layout(std140, set = 1, binding = 1) readonly buffer ObjectBuffer
{
ObjectData m_objects[];
} u_object_buffer;
layout(std140, set = 1, binding = 2) readonly buffer SkinningMatrices
{
mat4 m_mat[];
} u_skinning_matrices;
#ifdef BIND_MESH_TEXTURES_AT_ONCE
layout(std430, set = 1, binding = 4) readonly buffer MaterialIDs
{
int m_material_id[];
} u_material_ids;
#endif
@@ -0,0 +1,18 @@
layout(location = 0) in vec3 v_position;
layout(location = 1) in vec4 v_normal;
layout(location = 2) in vec4 v_color;
layout(location = 3) in vec2 v_uv;
layout(location = 4) in vec2 v_uv_two;
layout(location = 5) in vec4 v_tangent;
layout(location = 6) in ivec4 v_joint;
layout(location = 7) in vec4 v_weight;
layout(location = 0) out vec4 f_vertex_color;
layout(location = 1) out vec2 f_uv;
layout(location = 2) out vec2 f_uv_two;
layout(location = 3) flat out int f_material_id;
layout(location = 4) out float f_hue_change;
layout(location = 5) out vec3 f_normal;
layout(location = 6) out vec3 f_tangent;
layout(location = 7) out vec3 f_bitangent;
layout(location = 8) out vec4 f_world_position;
@@ -0,0 +1,14 @@
// Sun Most Representative Point (used for MRP area lighting method)
// From "Frostbite going PBR" paper
vec3 sunDirection(vec3 R, vec3 sun_direction, float sun_angle_tan_half, mat4 inverse_view_matrix)
{
sun_direction = normalize((transpose(inverse_view_matrix) * vec4(sun_direction, 0.)).xyz);
float DdotR = dot(sun_direction, R);
vec3 S = normalize(R - DdotR * sun_direction);
float sun_angle_tan_half2 = 1 + sun_angle_tan_half * sun_angle_tan_half;
vec2 sun_angle_sin_cos = vec2(2 * sun_angle_tan_half, 2 - sun_angle_tan_half2) / sun_angle_tan_half2;
// Equivalent to DdotR < cos(sun_angle)
float factor = step(DdotR, sun_angle_sin_cos.y);
return mix(R, normalize(sun_direction * sun_angle_sin_cos.y + S * sun_angle_sin_cos.x), factor);
}
@@ -0,0 +1,17 @@
vec3 getPosFromFragCoord(vec4 frag_coord, vec4 viewport, mat4 inverse_projection_matrix)
{
vec2 ndc = vec2((frag_coord.x - viewport.x) / viewport.z * 2.0 - 1.0,
(frag_coord.y - viewport.y) / viewport.w * 2.0 - 1.0);
vec4 clip = vec4(ndc, 1.0, 1.0);
vec4 view_space = inverse_projection_matrix * clip;
return view_space.xyz / frag_coord.w;
}
vec3 getPosFromUVDepth(vec3 uv_depth, vec4 viewport, mat4 inverse_projection_matrix)
{
vec2 ndc = vec2((uv_depth.x - viewport.x) / viewport.z * 2.0 - 1.0,
(uv_depth.y - viewport.y) / viewport.w * 2.0 - 1.0);
vec4 clip = vec4(ndc, uv_depth.z, 1.0);
vec4 view_space = inverse_projection_matrix * clip;
return view_space.xyz / view_space.w;
}