SuperTuxKart 1.5 upstream source (from official release tarball)
This commit is contained in:
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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>
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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 (α2−1) + 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;
|
||||
}
|
||||
Reference in New Issue
Block a user