mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-10-30 09:40:29 +01:00
Vulkan: scene rendering (D1–D7) on a scene walk shared with GL (N6a, N6b)
This commit is contained in:
@@ -41,3 +41,25 @@ source, compile the binaries again (or delete them): a binary older than its sou
|
||||
* The constants of the game (bindings, sizes) are written in `ogl46/common.glsl` and `vk14/common.glsl` for the binaries; the
|
||||
game puts its own values before the sources and checks at the start that the files have the same ones (the shader
|
||||
validator in `ci_shadervalidator` checks them too).
|
||||
|
||||
## vk14
|
||||
|
||||
The shaders of `vk14/` are those of `ogl46/` made for the descriptor sets of the Vulkan renderer
|
||||
(`rendering/vulkan14/vulkan14bindings.h`), drawn with the same matrices and the same conventions as the OpenGL renderer
|
||||
(nothing is turned upside down but the picture shown in the window, `present.frag`).
|
||||
|
||||
* A stage file includes `common.glsl` right after its stage define. The pipeline layout it is drawn with is picked by a
|
||||
define before that include: none for the passes of the scene, `LAYOUT_POST` for the post-processing (with `quad.vert`),
|
||||
`LAYOUT_CLUSTER` for the compute passes of the light clusters, `LAYOUT_UI` for the user interface.
|
||||
* The scene: set `PASS_SET` holds the blocks of the scene, of the draws (`model_draws[]`, the one of a draw picked by the push
|
||||
constant `pc.draw`), of the instances and of the lights and clusters, and the shadow, environment and headlight maps;
|
||||
set `MATERIAL_SET` the textures of the material at `MATERIAL_TEXTURE_FIRST + unit` of their `#pragma texture`. The names of
|
||||
the model block (`modelview`, `param`, `opacity` ...) stand for the fields of the draw, as in the `MODEL_DRAWS` variant of
|
||||
`ogl46/`.
|
||||
* The push constants (`pc`, `PUSH_CONSTANTS_SIZE` bytes) carry the draw and the parameters of the special shaders in
|
||||
`pc.data[]`; each of those says at the top what it takes from them. In the post-processing `param` stands for `pc.data`.
|
||||
* The settings are specialization constants with the ids `SPEC_*` (`vk14/settings.glsl`).
|
||||
* The features of the later stages of the renderer (the shadows of the lamps and the headlights, the contact shadows, the
|
||||
weather and its fog, the sky ambient light, the prefiltered environment map, the automatic exposure, soft and gpu
|
||||
particles) aren't in `vk14/` yet; the code paths are the ones `ogl46/` takes with them off, the fog is an analytic one
|
||||
(`vk14/apply_fog.glsl`).
|
||||
|
||||
@@ -23,9 +23,10 @@ import sys
|
||||
|
||||
STAGES = ('.vert', '.frag', '.geom', '.comp')
|
||||
TREES = {
|
||||
# source directory, binary directory, target environment, variants of the vertex and fragment shaders
|
||||
'ogl46': ('ogl46', 'ogl46bin', 'opengl4.5', ['MODEL_DRAWS']),
|
||||
'vk14': ('vk14', 'vk14bin', 'vulkan1.4', []),
|
||||
# source directory, binary directory, target environment, variants of the vertex and fragment shaders, whether a variant is
|
||||
# made only for the files which use its name (opengl links a program from the binaries of all of its stages or from none)
|
||||
'ogl46': ('ogl46', 'ogl46bin', 'opengl4.5', ['MODEL_DRAWS'], False),
|
||||
'vk14': ('vk14', 'vk14bin', 'vulkan1.4', ['NO_MOTION_OUTPUT'], True),
|
||||
}
|
||||
INCLUDE = re.compile(r'^[ \t]*#include[ \t]*[<"]([^>"]+)[>"]', re.M)
|
||||
|
||||
@@ -84,7 +85,7 @@ def main():
|
||||
|
||||
failed = []
|
||||
count = 0
|
||||
for key, (sourcedir, binarydir, env, variants) in TREES.items():
|
||||
for key, (sourcedir, binarydir, env, variants, onlyused) in TREES.items():
|
||||
if args.only and args.only != key:
|
||||
continue
|
||||
sources = os.path.join(args.shaders, sourcedir)
|
||||
@@ -96,13 +97,17 @@ def main():
|
||||
names = sorted(n for n in os.listdir(sources) if os.path.splitext(n)[1] in STAGES)
|
||||
for name in names:
|
||||
jobs = [('', [])]
|
||||
if os.path.splitext(name)[1] in ('.vert', '.frag'):
|
||||
jobs += [(v, ['-D%s=1' % v]) for v in variants]
|
||||
try:
|
||||
deps = dependencies(sources, name)
|
||||
except OSError as e:
|
||||
failed.append('%s/%s (%s)' % (sourcedir, name, e))
|
||||
continue
|
||||
if os.path.splitext(name)[1] in ('.vert', '.frag'):
|
||||
text = ''
|
||||
for dep in deps:
|
||||
with open(os.path.join(sources, dep), 'r', encoding='utf-8', errors='replace') as f:
|
||||
text += f.read()
|
||||
jobs += [(v, ['-D%s=1' % v]) for v in variants if (not onlyused) or (v in text)]
|
||||
for variant, defines in jobs:
|
||||
binary = name + ('.' + variant if variant else '') + '.spv'
|
||||
command = [glslc, '--target-env=' + env] + defines + [os.path.join(sources, name), '-o', os.path.join(binaries, binary)]
|
||||
|
||||
13
shaders/vk14/alphashadowmap.frag
Normal file
13
shaders/vk14/alphashadowmap.frag
Normal file
@@ -0,0 +1,13 @@
|
||||
#version 460 core
|
||||
#define STAGE_FRAGMENT 1
|
||||
#include "common.glsl"
|
||||
layout(location = 2) in vec2 f_coord;
|
||||
|
||||
#pragma texture(tex1, 0, sRGB_A)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 0) uniform sampler2D tex1;
|
||||
|
||||
void main()
|
||||
{
|
||||
if (texture(tex1, f_coord).a < 0.5f)
|
||||
discard;
|
||||
}
|
||||
40
shaders/vk14/apply_fog.glsl
Normal file
40
shaders/vk14/apply_fog.glsl
Normal file
@@ -0,0 +1,40 @@
|
||||
// fog between the camera and a fragment, the api of shaders/ogl46/apply_fog.glsl. the fog volume and the weather of the opengl
|
||||
// renderer come with the stage P2 of the plan; until then the fog is analytic: exponential with the distance, of the density of
|
||||
// the draw (fog_density of the model block, a draw with 0 is not fogged), of the colour fog_color of the light buffer, turned
|
||||
// towards the colour of the sun around its direction
|
||||
// rgb: light the fog adds, a: what it lets through
|
||||
vec4 fog_at_fragment()
|
||||
{
|
||||
if (fog_density <= 0.0)
|
||||
return vec4(0.0, 0.0, 0.0, 1.0);
|
||||
float amount = 1.0 - clamp(exp(-length(f_pos.xyz) * fog_density), 0.0, 1.0);
|
||||
vec3 color = fog_color;
|
||||
if ((lights_count >= 1U) && (lights[0].type == LIGHT_DIR))
|
||||
{
|
||||
float sunward = pow(max(dot(normalize(f_pos.xyz), normalize(-lights[0].dir)), 0.0), 30.0);
|
||||
color = mix(color, lights[0].color, sunward);
|
||||
}
|
||||
return vec4(color * amount, 1.0 - amount);
|
||||
}
|
||||
|
||||
vec3 get_fog_color()
|
||||
{
|
||||
vec4 fog = fog_at_fragment();
|
||||
return fog.rgb / max(1.0 - fog.a, 1e-4);
|
||||
}
|
||||
|
||||
float get_fog_amount()
|
||||
{
|
||||
return 1.0 - fog_at_fragment().a;
|
||||
}
|
||||
|
||||
vec3 apply_fog(vec3 color)
|
||||
{
|
||||
vec4 fog = fog_at_fragment();
|
||||
return color * fog.a + fog.rgb;
|
||||
}
|
||||
|
||||
vec3 add_fog(vec3 color, float amount)
|
||||
{
|
||||
return color + fog_at_fragment().rgb * amount;
|
||||
}
|
||||
34
shaders/vk14/billboard.frag
Normal file
34
shaders/vk14/billboard.frag
Normal file
@@ -0,0 +1,34 @@
|
||||
#version 460 core
|
||||
#define STAGE_FRAGMENT 1
|
||||
#include "common.glsl"
|
||||
layout(location = 2) in vec2 f_coord;
|
||||
|
||||
#pragma texture(tex1, 0, sRGB_A)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 0) uniform sampler2D tex1;
|
||||
|
||||
#include "tonemapping.glsl"
|
||||
|
||||
layout(location = 0) out vec4 out_color;
|
||||
#ifdef NO_MOTION_OUTPUT
|
||||
// a pass without the velocity target: the writes go nowhere
|
||||
vec4 out_motion;
|
||||
#else
|
||||
layout(location = 1) out vec4 out_motion;
|
||||
#endif
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 tex_color = texture(tex1, f_coord);
|
||||
if (POSTFX_ENABLED)
|
||||
{
|
||||
out_color = tex_color * param[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
out_color = tonemap(tex_color * param[0]);
|
||||
}
|
||||
if (MOTIONBLUR_ENABLED)
|
||||
{
|
||||
out_motion = vec4(0.0f);
|
||||
}
|
||||
}
|
||||
93
shaders/vk14/celestial.frag
Normal file
93
shaders/vk14/celestial.frag
Normal file
@@ -0,0 +1,93 @@
|
||||
#version 460 core
|
||||
#define STAGE_FRAGMENT 1
|
||||
#include "common.glsl"
|
||||
// the sun, the moon and the textured sprite of the easter egg, drawn over the sky on a quad around the direction of the body
|
||||
// (celestial.vert). param[0]: colour (rgb) and alpha, param[1]: position in view space and half the size of the quad,
|
||||
// param[2].xy: corner (sprite) or centre (moon) of the picture in the texture, param[2].z: its size (sprite) or the radius of
|
||||
// the disc in it (moon), in texture units, param[2].w: kind of body, 0: textured sprite, 1: sun, 2: moon.
|
||||
// the colour goes out premultiplied, the alpha is how much of the sky behind the body it hides (blending ONE, ONE_MINUS_SRC_ALPHA)
|
||||
|
||||
layout(location = 2) in vec2 f_coord;
|
||||
layout(location = 15) in vec2 f_local;
|
||||
|
||||
#pragma texture(tex1, 0, sRGB_A)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 0) uniform sampler2D tex1;
|
||||
|
||||
#include "tonemapping.glsl"
|
||||
|
||||
// shape and light of the sun and the moon, pc.data[0..2] of the push constants (a loose uniform vec4 body[3] in the opengl
|
||||
// renderer, set by opengl46_renderer::Render(world_environment *)):
|
||||
// [0].xy: direction to the zenith on the quad, [0].z: height over width of the disc (flattened by the refraction near the
|
||||
// horizon), [0].w: radius of the disc in units of half the quad
|
||||
// [1].xyz: direction to the sun in view space, [1].w: light of the earth on the dark part of the moon, against the light of
|
||||
// the sun on the lit part
|
||||
// [2].rgb: limb darkening of the sun per channel (linear law)
|
||||
#define body pc.data
|
||||
|
||||
layout(location = 0) out vec4 out_color;
|
||||
#ifdef NO_MOTION_OUTPUT
|
||||
// a pass without the velocity target: the writes go nowhere
|
||||
vec4 out_motion;
|
||||
#else
|
||||
layout(location = 1) out vec4 out_motion;
|
||||
#endif
|
||||
|
||||
void main()
|
||||
{
|
||||
int kind = int(param[2].w + 0.5);
|
||||
vec4 color = vec4(0.0);
|
||||
if (kind == 0)
|
||||
{
|
||||
vec4 tex_color = texture(tex1, f_coord) * param[0];
|
||||
color = vec4(tex_color.rgb * tex_color.a, 0.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// the point on the disc in its radii, x along the horizon, y to the zenith, with the flattening undone
|
||||
vec2 zenith = body[0].xy;
|
||||
vec2 across = vec2(zenith.y, -zenith.x);
|
||||
vec2 p = vec2(dot(f_local, across), dot(f_local, zenith)) / body[0].w;
|
||||
p.y /= body[0].z;
|
||||
float r = length(p);
|
||||
float coverage = clamp((1.0 - r) / max(fwidth(r), 1e-4) + 0.5, 0.0, 1.0);
|
||||
// the horizon hides what is under it
|
||||
vec3 direction = normalize(param[1].xyz + vec3(f_local * param[1].w, 0.0));
|
||||
float height = (mat3(inv_view) * direction).y;
|
||||
coverage *= clamp(height / max(fwidth(height), 1e-7) + 0.5, 0.0, 1.0);
|
||||
// cosine of the angle between the line of sight and the surface of the sphere
|
||||
float mu = sqrt(max(1.0 - r * r, 0.0));
|
||||
if (kind == 1)
|
||||
{
|
||||
// limb darkening, kept to the average brightness of the disc
|
||||
vec3 limb = (vec3(1.0) - body[2].rgb * (1.0 - mu)) / (vec3(1.0) - body[2].rgb / 3.0);
|
||||
color = vec4(param[0].rgb * limb * coverage, 0.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// the moon as a sphere lit from the direction of the sun. the frame of the disc in view space, z to the viewer
|
||||
vec3 z = -normalize(param[1].xyz);
|
||||
vec3 x = vec3(across, 0.0);
|
||||
x = normalize(x - z * dot(x, z));
|
||||
vec3 y = cross(z, x);
|
||||
vec2 q = p / max(r, 1.0);
|
||||
vec3 normal = q.x * x + q.y * y + mu * z;
|
||||
float mu0 = max(dot(normal, normalize(body[1].xyz)), 0.0);
|
||||
// Lommel-Seeliger law: an even disc at the full moon, as the real one, no darkening towards the limb
|
||||
float lit = 2.0 * mu0 / (mu0 + max(mu, 1e-3));
|
||||
vec3 albedo = texture(tex1, param[2].xy + p * param[2].z).rgb;
|
||||
color = vec4(albedo * param[0].rgb * ((lit + body[1].w) * coverage), coverage * param[0].a);
|
||||
}
|
||||
}
|
||||
if (POSTFX_ENABLED)
|
||||
{
|
||||
out_color = color;
|
||||
}
|
||||
else
|
||||
{
|
||||
out_color = vec4(tonemap(vec4(color.rgb, 1.0)).rgb, color.a);
|
||||
}
|
||||
if (MOTIONBLUR_ENABLED)
|
||||
{
|
||||
out_motion = vec4(0.0f);
|
||||
}
|
||||
}
|
||||
34
shaders/vk14/celestial.vert
Normal file
34
shaders/vk14/celestial.vert
Normal file
@@ -0,0 +1,34 @@
|
||||
#version 460 core
|
||||
#define STAGE_VERTEX 1
|
||||
#include "common.glsl"
|
||||
const vec2 vert[4] = vec2[]
|
||||
(
|
||||
vec2(-1.0, 1.0),
|
||||
vec2(-1.0, -1.0),
|
||||
vec2( 1.0, 1.0),
|
||||
vec2( 1.0, -1.0)
|
||||
);
|
||||
|
||||
layout(location = 2) out vec2 f_coord;
|
||||
// the corner of the quad, -1...1 across it
|
||||
layout(location = 15) out vec2 f_local;
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = projection * (vec4(param[1].xyz, 1.0) + vec4(vert[gl_VertexIndex] * param[1].w, 0.0, 0.0));
|
||||
|
||||
f_local = vert[gl_VertexIndex];
|
||||
|
||||
vec2 coord = param[2].xy;
|
||||
float size = param[2].z;
|
||||
|
||||
if (gl_VertexIndex == 0)
|
||||
f_coord = vec2(coord.x, coord.y);
|
||||
if (gl_VertexIndex == 1)
|
||||
f_coord = vec2(coord.x, coord.y - size);
|
||||
if (gl_VertexIndex == 2)
|
||||
f_coord = vec2(coord.x + size, coord.y);
|
||||
if (gl_VertexIndex == 3)
|
||||
f_coord = vec2(coord.x + size, coord.y - size);
|
||||
}
|
||||
59
shaders/vk14/cluster_build.comp
Normal file
59
shaders/vk14/cluster_build.comp
Normal file
@@ -0,0 +1,59 @@
|
||||
#version 460 core
|
||||
#define STAGE_COMPUTE 1
|
||||
#define LAYOUT_CLUSTER 1
|
||||
#include "common.glsl"
|
||||
// bounding boxes of the light clusters in view space, see gl/cluster_grid.h
|
||||
// one invocation per cluster, run when the projection or the depth range of the pass changes
|
||||
|
||||
layout(local_size_x = CLUSTER_BUILD_GROUP_SIZE) in;
|
||||
|
||||
// clip space w at the lower boundary of slice k: the inverse of the slice formula used when shading
|
||||
float slice_depth(uint k)
|
||||
{
|
||||
return exp((float(k) - cluster_slice_bias) / cluster_slice_scale);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
uint index = gl_GlobalInvocationID.x;
|
||||
if (index >= uint(CLUSTER_COUNT))
|
||||
return;
|
||||
|
||||
uvec3 cell = uvec3(
|
||||
index % uint(CLUSTER_GRID_X),
|
||||
(index / uint(CLUSTER_GRID_X)) % uint(CLUSTER_GRID_Y),
|
||||
index / uint(CLUSTER_GRID_X * CLUSTER_GRID_Y));
|
||||
|
||||
// clip x, y and w are affine functions of the view space position, while clip z is constant (reverse z with
|
||||
// the far plane at infinity), which makes the projection matrix singular. the position is recovered from
|
||||
// those three alone, so off-axis and rotated screens of custom viewports and vr eyes work too
|
||||
mat3 linear = mat3(
|
||||
vec3(cluster_projection[0][0], cluster_projection[0][1], cluster_projection[0][3]),
|
||||
vec3(cluster_projection[1][0], cluster_projection[1][1], cluster_projection[1][3]),
|
||||
vec3(cluster_projection[2][0], cluster_projection[2][1], cluster_projection[2][3]));
|
||||
vec3 translation = vec3(cluster_projection[3][0], cluster_projection[3][1], cluster_projection[3][3]);
|
||||
mat3 unproject = inverse(linear);
|
||||
|
||||
// the tile in clip space xy, the slice in clip space w
|
||||
vec2 tiles = vec2(CLUSTER_GRID_X, CLUSTER_GRID_Y);
|
||||
vec2 ndc_min = vec2(cell.xy) / tiles * 2.0 - 1.0;
|
||||
vec2 ndc_max = vec2(cell.xy + 1U) / tiles * 2.0 - 1.0;
|
||||
float w_near = slice_depth(cell.z);
|
||||
float w_far = slice_depth(cell.z + 1U);
|
||||
|
||||
vec3 lower = vec3(3.402823e38);
|
||||
vec3 upper = vec3(-3.402823e38);
|
||||
for (int corner = 0; corner < 8; ++corner)
|
||||
{
|
||||
vec2 ndc = vec2(
|
||||
(corner & 1) != 0 ? ndc_max.x : ndc_min.x,
|
||||
(corner & 2) != 0 ? ndc_max.y : ndc_min.y);
|
||||
float w = (corner & 4) != 0 ? w_far : w_near;
|
||||
vec3 position = unproject * (vec3(ndc * w, w) - translation);
|
||||
lower = min(lower, position);
|
||||
upper = max(upper, position);
|
||||
}
|
||||
|
||||
cluster_aabbs[index].lower = vec4(lower, 0.0);
|
||||
cluster_aabbs[index].upper = vec4(upper, 0.0);
|
||||
}
|
||||
157
shaders/vk14/cluster_cull.comp
Normal file
157
shaders/vk14/cluster_cull.comp
Normal file
@@ -0,0 +1,157 @@
|
||||
#version 460 core
|
||||
#define STAGE_COMPUTE 1
|
||||
#define LAYOUT_CLUSTER 1
|
||||
#include "common.glsl"
|
||||
// assigns the lights to the light clusters, see gl/cluster_grid.h
|
||||
// one invocation per cluster: tests every light of light_ssbo (the sun, slot 0, is handled apart from the clusters)
|
||||
// against the bounding box of the cluster in view space, and writes the indices of the lights which reach it.
|
||||
// run every frame after the lights were updated, for the grid of the pass about to be drawn
|
||||
|
||||
layout(local_size_x = CLUSTER_CULL_GROUP_SIZE) in;
|
||||
|
||||
// a light is taken to end where its brightest possible contribution drops under this, a fraction of
|
||||
// what the display can tell apart. there is no other limit: the 1 km filter on the cpu side is about the distance of a light
|
||||
// from the camera, not about how far it reaches, and the shading lights a surface at any distance
|
||||
const float MIN_CONTRIBUTION = 1.0 / 1024.0;
|
||||
// reach of a light whose contribution does not fall off with the distance; its square still fits in a float
|
||||
const float UNLIMITED_RANGE = 1.0e18;
|
||||
// the boxes and the light data are floats: planes of the headlight projection let this much (in meters) of a box through
|
||||
const float PLANE_MARGIN = 0.05;
|
||||
|
||||
// brightest value the light adds to a surface it hits, as the shading computes it
|
||||
float light_peak(light_s light)
|
||||
{
|
||||
float peak = max(light.color.r, max(light.color.g, light.color.b)) * light.intensity;
|
||||
if (light.type == LIGHT_HEADLIGHTS)
|
||||
// weights are the state of the individual lamps and the beam texture, which is not brighter than 1, picks from them
|
||||
return peak * max(light.headlight_weights.r, max(light.headlight_weights.g, light.headlight_weights.b));
|
||||
return peak * (1.0 + light.ambient);
|
||||
}
|
||||
|
||||
// distance from the light at which its contribution falls under MIN_CONTRIBUTION, 0 for a light which has none
|
||||
float light_range(light_s light)
|
||||
{
|
||||
float peak = light_peak(light);
|
||||
if (!(peak > MIN_CONTRIBUTION))
|
||||
return 0.0;
|
||||
// attenuation which the contribution can drop to without being lost: 1 / k
|
||||
float k = peak / MIN_CONTRIBUTION;
|
||||
|
||||
if (light.type == LIGHT_HEADLIGHTS)
|
||||
{
|
||||
// 1 + linear * d + quadratic * d^2 <= k, the positive root written the way which has no cancellation for a small quadratic
|
||||
float a = light.quadratic;
|
||||
float b = light.linear;
|
||||
float c = 1.0 - k;
|
||||
float denominator = b + sqrt(b * b - 4.0 * a * c);
|
||||
return (denominator > 1e-12) ? min(-2.0 * c / denominator, UNLIMITED_RANGE) : UNLIMITED_RANGE;
|
||||
}
|
||||
// point and spot lights fall off with the square of the distance; the shading ends them at 1 / sqrt(quadratic) where it is set
|
||||
float range = sqrt(k);
|
||||
return (light.quadratic > 0.0) ? min(range, inversesqrt(light.quadratic)) : range;
|
||||
}
|
||||
|
||||
bool sphere_touches_box(vec3 center, float radius, vec3 lower, vec3 upper)
|
||||
{
|
||||
vec3 offset = center - clamp(center, lower, upper);
|
||||
return dot(offset, offset) <= radius * radius;
|
||||
}
|
||||
|
||||
// whether any part of the box, given by its center and half extents, is on the positive side of the plane
|
||||
bool box_reaches_plane(vec4 plane, vec3 center, vec3 extent)
|
||||
{
|
||||
return dot(plane.xyz, center) + plane.w + dot(abs(plane.xyz), extent) + PLANE_MARGIN * length(plane.xyz) >= 0.0;
|
||||
}
|
||||
|
||||
// planes bounding the beam of a headlight: the projection takes a view space position to the texture coordinates
|
||||
// of the beam, and the beam is where those fall in 0..1 and the position is in front of the projector. clip z of that
|
||||
// projection is a constant (reverse z, no far plane), so only the four sides and the near plane are real planes
|
||||
bool box_in_headlight_beam(mat4 projection, vec3 center, vec3 extent)
|
||||
{
|
||||
vec4 row_x = vec4(projection[0][0], projection[1][0], projection[2][0], projection[3][0]);
|
||||
vec4 row_y = vec4(projection[0][1], projection[1][1], projection[2][1], projection[3][1]);
|
||||
vec4 row_z = vec4(projection[0][2], projection[1][2], projection[2][2], projection[3][2]);
|
||||
vec4 row_w = vec4(projection[0][3], projection[1][3], projection[2][3], projection[3][3]);
|
||||
|
||||
return box_reaches_plane(row_x, center, extent)
|
||||
&& box_reaches_plane(row_w - row_x, center, extent)
|
||||
&& box_reaches_plane(row_y, center, extent)
|
||||
&& box_reaches_plane(row_w - row_y, center, extent)
|
||||
&& box_reaches_plane(row_z, center, extent)
|
||||
&& box_reaches_plane(row_w - row_z, center, extent);
|
||||
}
|
||||
|
||||
// whether the sphere touches the infinite cone with the apex at the origin, the unit axis and the cosine of the half angle
|
||||
bool sphere_touches_cone(vec3 center, float radius, vec3 axis, float cosine)
|
||||
{
|
||||
float sine = max(sqrt(max(1.0 - cosine * cosine, 0.0)), 1e-4);
|
||||
float along = dot(center, axis);
|
||||
float across = sqrt(max(dot(center, center) - along * along, 0.0));
|
||||
// distance to the boundary ray if the closest point of the cone is on it, and to the apex otherwise
|
||||
float distance_to_cone = (along * cosine + across * sine > 0.0) ? across * cosine - along * sine : length(center);
|
||||
return distance_to_cone <= radius;
|
||||
}
|
||||
|
||||
bool light_reaches_box(light_s light, float range, vec3 lower, vec3 upper)
|
||||
{
|
||||
vec3 center = 0.5 * (lower + upper);
|
||||
vec3 extent = 0.5 * (upper - lower);
|
||||
|
||||
if (light.type == LIGHT_DIR)
|
||||
return true;
|
||||
|
||||
if (!sphere_touches_box(light.pos, range, lower, upper))
|
||||
return false;
|
||||
|
||||
if (light.type == LIGHT_HEADLIGHTS)
|
||||
return box_in_headlight_beam(light.headlight_projection, center, extent);
|
||||
|
||||
if ((light.type == LIGHT_SPOT) && (light.out_cutoff > 0.0))
|
||||
// the cone is tested against the sphere around the box, which lets some of the corners through. a cone wider than
|
||||
// a half of the space is taken as the whole sphere
|
||||
return sphere_touches_cone(center - light.pos, length(extent), normalize(light.dir), light.out_cutoff);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
uint index = gl_GlobalInvocationID.x;
|
||||
if (index >= uint(CLUSTER_COUNT))
|
||||
return;
|
||||
|
||||
vec3 lower = cluster_aabbs[index].lower.xyz;
|
||||
vec3 upper = cluster_aabbs[index].upper.xyz;
|
||||
|
||||
// the lights are in the order of their importance, so when a cluster is full the least important are the ones left out
|
||||
uint found[MAX_LIGHTS_PER_CLUSTER];
|
||||
uint found_count = 0U;
|
||||
uint dropped = 0U;
|
||||
|
||||
uint lights_end = min(lights_total, uint(lights.length()));
|
||||
for (uint i = 1U; i < lights_end; ++i)
|
||||
{
|
||||
float range = light_range(lights[i]);
|
||||
if (range <= 0.0 && lights[i].type != LIGHT_DIR)
|
||||
continue;
|
||||
if (!light_reaches_box(lights[i], range, lower, upper))
|
||||
continue;
|
||||
|
||||
if (found_count < uint(MAX_LIGHTS_PER_CLUSTER))
|
||||
found[found_count++] = i;
|
||||
else
|
||||
++dropped;
|
||||
}
|
||||
|
||||
uint offset = 0U;
|
||||
if (found_count > 0U)
|
||||
{
|
||||
offset = atomicAdd(cluster_index_count, found_count);
|
||||
for (uint k = 0U; k < found_count; ++k)
|
||||
cluster_light_indices[offset + k] = found[k];
|
||||
}
|
||||
if (dropped > 0U)
|
||||
atomicAdd(cluster_overflow_count, dropped);
|
||||
|
||||
cluster_ranges[index] = cluster_range_s(offset, found_count);
|
||||
}
|
||||
35
shaders/vk14/color.frag
Normal file
35
shaders/vk14/color.frag
Normal file
@@ -0,0 +1,35 @@
|
||||
#version 460 core
|
||||
#define STAGE_FRAGMENT 1
|
||||
#include "common.glsl"
|
||||
layout(location = 13) in vec3 f_color;
|
||||
layout(location = 3) in vec4 f_pos;
|
||||
|
||||
#include "apply_fog.glsl"
|
||||
#include "tonemapping.glsl"
|
||||
|
||||
layout(location = 0) out vec4 out_color;
|
||||
#ifdef NO_MOTION_OUTPUT
|
||||
// a pass without the velocity target: the writes go nowhere
|
||||
vec4 out_motion;
|
||||
#else
|
||||
layout(location = 1) out vec4 out_motion;
|
||||
#endif
|
||||
|
||||
#include "sky_shoulder.glsl"
|
||||
|
||||
void main()
|
||||
{
|
||||
vec3 col = sky_shoulder(pow(max(f_color.rgb, vec3(0.0)), vec3(2.2)));
|
||||
if (POSTFX_ENABLED)
|
||||
{
|
||||
out_color = vec4(apply_fog(col), 1.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
out_color = tonemap(vec4(apply_fog(col), 1.0f));
|
||||
}
|
||||
if (MOTIONBLUR_ENABLED)
|
||||
{
|
||||
out_motion = vec4(0.0f);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,22 @@
|
||||
// what the shaders of the vulkan 1.4 renderer share: the bindings of rendering/vulkan14/vulkan14bindings.h and the settings.
|
||||
// what the shaders of the vulkan 1.4 renderer share: the bindings of rendering/vulkan14/vulkan14bindings.h, the constants of the
|
||||
// game, the settings, the push constants and the resources of the pipeline layout a shader is drawn with.
|
||||
// compiled by the game, the bindings come from the renderer (vk14::binding_preamble()) and are taken instead of these; the
|
||||
// SPIR-V binaries (shaders/vk14bin) are compiled with the values written here, so they have to stay the same as in the game,
|
||||
// which checks them when it starts (and doesn't load the binaries when they differ)
|
||||
//
|
||||
// the pipeline layout is picked by a define before the include of this file:
|
||||
// (none) the passes of the scene (materials, shadows, picking, lines, sprites, sky, particles): set PASS_SET with
|
||||
// the blocks of the scene, of the draws, of the instances, the lights, the clusters and the shadow,
|
||||
// environment and headlight maps; set MATERIAL_SET with the textures of the material
|
||||
// LAYOUT_POST the post-processing and the copies of whole images: set POST_SET pushed with the images read, the
|
||||
// parameters in the push constants (param stands for pc.data)
|
||||
// LAYOUT_CLUSTER the compute passes of the light clusters: set 0 pushed at the CL_* bindings
|
||||
// LAYOUT_UI the user interface: none of the above, its own push constants
|
||||
//
|
||||
// the locations of the inputs and outputs between the stages are the table of shaders/ogl46/common.glsl, the same for a name
|
||||
// in every shader: 0 f_normal, 1 f_normal_raw, 2 f_coord, 3 f_pos, 4 f_clip_pos, 5 f_clip_future_pos, 6 TangentFragPos,
|
||||
// 7 UserData, 8-10 f_tbn, 12 f_albedo, 13 f_color, 14 f_coords, 15 f_local, 16 f_soft, 17 f_streak (11 f_model_draw is not
|
||||
// used: the draw is in the push constants)
|
||||
#ifndef COMMON_GLSL
|
||||
#define COMMON_GLSL
|
||||
|
||||
@@ -15,18 +30,276 @@
|
||||
#define UI_TEXTURE 0
|
||||
#define PASS_SET 0
|
||||
#define MATERIAL_SET 1
|
||||
#define SCENE_UBO 0
|
||||
#define DRAW_SSBO 1
|
||||
#define INSTANCE_SSBO 2
|
||||
#define LIGHT_SSBO 3
|
||||
#define CLUSTER_UBO 4
|
||||
#define CLUSTER_RANGE_SSBO 5
|
||||
#define CLUSTER_INDEX_SSBO 6
|
||||
#define SHADOW_TEX 7
|
||||
#define ENV_TEX 8
|
||||
#define HEADLIGHT_TEX 9
|
||||
#define PASS_BINDING_COUNT 10
|
||||
#define MATERIAL_TEXTURE_FIRST 0
|
||||
#define CL_CLUSTER_UBO 0
|
||||
#define CL_AABB_SSBO 1
|
||||
#define CL_RANGE_SSBO 2
|
||||
#define CL_INDEX_SSBO 3
|
||||
#define CL_COUNTER_SSBO 4
|
||||
#define CL_LIGHT_SSBO 5
|
||||
#define POST_SET 0
|
||||
#define POST_TEXTURE_FIRST 0
|
||||
#define PUSH_CONSTANTS_SIZE 112
|
||||
#define SPEC_OUTPUT_GAMMA 0
|
||||
#define SPEC_SHADOWMAP_ENABLED 1
|
||||
#define SPEC_ENVMAP_ENABLED 2
|
||||
#define SPEC_MOTIONBLUR_ENABLED 3
|
||||
#define SPEC_POSTFX_ENABLED 4
|
||||
#define SPEC_EXTRAEFFECTS_ENABLED 5
|
||||
#define SPEC_COUNT 6
|
||||
#define MAX_LIGHTS 1024U
|
||||
#define MAX_CASCADES 3U
|
||||
#define MAX_PARAMS 3U
|
||||
#define MAX_HEADLIGHT_SHADOWS 4U
|
||||
#define CLUSTER_GRID_X 16
|
||||
#define CLUSTER_GRID_Y 9
|
||||
#define CLUSTER_GRID_Z 24
|
||||
#define CLUSTER_COUNT 3456
|
||||
#define MAX_LIGHTS_PER_CLUSTER 64
|
||||
#define CLUSTER_BUILD_GROUP_SIZE 64
|
||||
#define CLUSTER_CULL_GROUP_SIZE 64
|
||||
#endif
|
||||
|
||||
// whether the colour written to the window is encoded by the shader (FBOUT): the window has no srgb format (gfx.shadergamma yes).
|
||||
// a specialization constant, set by the renderer when it makes the pipeline
|
||||
layout(constant_id = SPEC_OUTPUT_GAMMA) const bool OUTPUT_GAMMA = false;
|
||||
#include "settings.glsl"
|
||||
|
||||
// the colour written to the window
|
||||
vec4 FBOUT(vec4 x)
|
||||
#ifndef LAYOUT_UI
|
||||
// vk14::draw_constants, PUSH_CONSTANTS_SIZE bytes, visible in every stage. draw: the element of model_draws[] the draw reads
|
||||
// (the passes of the scene); flags and data: the parameters of the special shaders, each says what it takes from them
|
||||
layout(push_constant) uniform draw_constants_block
|
||||
{
|
||||
return (OUTPUT_GAMMA ? vec4(pow(x.rgb, vec3(1.0 / 2.2)), x.a) : x);
|
||||
uint draw;
|
||||
uint flags;
|
||||
uint pad0;
|
||||
uint pad1;
|
||||
vec4 data[6];
|
||||
} pc;
|
||||
#endif
|
||||
|
||||
const uint LIGHT_SPOT = 0U;
|
||||
const uint LIGHT_POINT = 1U;
|
||||
const uint LIGHT_DIR = 2U;
|
||||
const uint LIGHT_HEADLIGHTS = 3U;
|
||||
|
||||
// gl::light_element
|
||||
struct light_s
|
||||
{
|
||||
vec3 pos;
|
||||
uint type;
|
||||
|
||||
vec3 dir;
|
||||
float in_cutoff;
|
||||
|
||||
vec3 color;
|
||||
float out_cutoff;
|
||||
|
||||
float linear;
|
||||
float quadratic;
|
||||
|
||||
float intensity;
|
||||
float ambient;
|
||||
|
||||
mat4 headlight_projection;
|
||||
vec4 headlight_weights;
|
||||
};
|
||||
|
||||
// light clusters, see gl/cluster_grid.h
|
||||
struct cluster_aabb_s
|
||||
{
|
||||
vec4 lower;
|
||||
vec4 upper;
|
||||
};
|
||||
|
||||
struct cluster_range_s
|
||||
{
|
||||
uint offset;
|
||||
uint count;
|
||||
};
|
||||
|
||||
#if defined(LAYOUT_CLUSTER)
|
||||
|
||||
layout(std140, set = 0, binding = CL_CLUSTER_UBO) uniform cluster_ubo
|
||||
{
|
||||
mat4 cluster_projection;
|
||||
float cluster_znear;
|
||||
float cluster_zfar;
|
||||
float cluster_slice_scale;
|
||||
float cluster_slice_bias;
|
||||
vec2 cluster_viewport_size;
|
||||
uint cluster_valid;
|
||||
};
|
||||
|
||||
layout(std430, set = 0, binding = CL_AABB_SSBO) buffer cluster_aabb_ssbo
|
||||
{
|
||||
cluster_aabb_s cluster_aabbs[];
|
||||
};
|
||||
|
||||
layout(std430, set = 0, binding = CL_RANGE_SSBO) buffer cluster_range_ssbo
|
||||
{
|
||||
cluster_range_s cluster_ranges[];
|
||||
};
|
||||
|
||||
layout(std430, set = 0, binding = CL_INDEX_SSBO) buffer cluster_index_ssbo
|
||||
{
|
||||
uint cluster_light_indices[];
|
||||
};
|
||||
|
||||
layout(std430, set = 0, binding = CL_COUNTER_SSBO) buffer cluster_counter_ssbo
|
||||
{
|
||||
uint cluster_index_count;
|
||||
uint cluster_overflow_count;
|
||||
};
|
||||
|
||||
layout(std430, set = 0, binding = CL_LIGHT_SSBO) readonly buffer light_ssbo
|
||||
{
|
||||
vec3 ambient;
|
||||
// lights stored in lights[], what the cluster culling goes through
|
||||
uint lights_total;
|
||||
|
||||
vec3 fog_color;
|
||||
// lights the shading loop goes through when the lights are not clustered
|
||||
uint lights_count;
|
||||
// 1 if the shading takes the lights from the list of the cluster of a fragment, see cluster_ubo
|
||||
uint lights_clustered;
|
||||
// not used by the shaders of this renderer yet (the sky ambient light and the prefiltered environment map come later)
|
||||
float sky_ambient_factor;
|
||||
uint env_ggx;
|
||||
|
||||
light_s lights[];
|
||||
};
|
||||
|
||||
#elif defined(LAYOUT_POST)
|
||||
|
||||
// the post-processing reads the parameters the opengl renderer gives it in the model block from the push constants
|
||||
#define param pc.data
|
||||
|
||||
#elif !defined(LAYOUT_UI)
|
||||
|
||||
// the block of the scene, gl::scene_ubs (every member kept, the layout is the one of the c++ struct)
|
||||
layout(std140, set = PASS_SET, binding = SCENE_UBO) uniform scene_ubo
|
||||
{
|
||||
mat4 projection;
|
||||
mat4 inv_view;
|
||||
mat4 lightview[MAX_CASCADES];
|
||||
vec3 cascade_end;
|
||||
float time;
|
||||
vec4 rain_params;
|
||||
vec4 wiper_pos;
|
||||
vec4 wiper_timer_out;
|
||||
vec4 wiper_timer_return;
|
||||
mat4 headlight_shadow[MAX_HEADLIGHT_SHADOWS];
|
||||
vec4 headlight_shadow_params[MAX_HEADLIGHT_SHADOWS];
|
||||
vec4 contact_shadow_params;
|
||||
vec4 contact_shadow_lamps;
|
||||
vec4 shadow_fit;
|
||||
};
|
||||
|
||||
// the model block of a draw, gl::model_ubs (256 bytes), the one of the draw picked by pc.draw. the names below stand for its
|
||||
// fields, so the shaders read them as the uniform block of the opengl renderer
|
||||
struct model_draw_s
|
||||
{
|
||||
mat4 modelview;
|
||||
mat3 modelviewnormal;
|
||||
vec4 param[MAX_PARAMS];
|
||||
|
||||
mat4 future;
|
||||
float opacity;
|
||||
float emission;
|
||||
float fog_density;
|
||||
float alpha_mult;
|
||||
float shadow_tone;
|
||||
};
|
||||
|
||||
layout(std430, set = PASS_SET, binding = DRAW_SSBO) readonly buffer model_draw_ssbo
|
||||
{
|
||||
model_draw_s model_draws[];
|
||||
};
|
||||
|
||||
#define modelview model_draws[pc.draw].modelview
|
||||
#define modelviewnormal model_draws[pc.draw].modelviewnormal
|
||||
#define param model_draws[pc.draw].param
|
||||
#define future model_draws[pc.draw].future
|
||||
#define opacity model_draws[pc.draw].opacity
|
||||
#define emission model_draws[pc.draw].emission
|
||||
#define fog_density model_draws[pc.draw].fog_density
|
||||
#define alpha_mult model_draws[pc.draw].alpha_mult
|
||||
#define shadow_tone model_draws[pc.draw].shadow_tone
|
||||
|
||||
// per-instance modelview matrices of the instanced draws, element 0 the identity. a draw which isn't instanced is drawn with
|
||||
// firstInstance 0, an instanced one from its base instance on, with modelview set to the submodel-local chain (computed from
|
||||
// the identity, not from the camera or the instance), so the product is the final transform per instance per submodel
|
||||
layout(std430, set = PASS_SET, binding = INSTANCE_SSBO) readonly buffer instance_ssbo
|
||||
{
|
||||
mat4 instance_modelview[];
|
||||
};
|
||||
|
||||
// the light buffer of the pass, gl::light_data
|
||||
layout(std430, set = PASS_SET, binding = LIGHT_SSBO) readonly buffer light_ssbo
|
||||
{
|
||||
vec3 ambient;
|
||||
// lights stored in lights[], what the cluster culling goes through
|
||||
uint lights_total;
|
||||
|
||||
vec3 fog_color;
|
||||
// lights the shading loop goes through when the lights are not clustered
|
||||
uint lights_count;
|
||||
// 1 if the shading takes the lights from the list of the cluster of a fragment, see cluster_ubo
|
||||
uint lights_clustered;
|
||||
// not used by the shaders of this renderer yet (the sky ambient light and the prefiltered environment map come later)
|
||||
float sky_ambient_factor;
|
||||
uint env_ggx;
|
||||
|
||||
light_s lights[];
|
||||
};
|
||||
|
||||
// the grid of the light clusters of the pass, gl::cluster_ubs; the compute passes fill the lists, shading only reads them
|
||||
layout(std140, set = PASS_SET, binding = CLUSTER_UBO) uniform cluster_ubo
|
||||
{
|
||||
mat4 cluster_projection;
|
||||
float cluster_znear;
|
||||
float cluster_zfar;
|
||||
float cluster_slice_scale;
|
||||
float cluster_slice_bias;
|
||||
vec2 cluster_viewport_size;
|
||||
uint cluster_valid;
|
||||
};
|
||||
|
||||
layout(std430, set = PASS_SET, binding = CLUSTER_RANGE_SSBO) readonly buffer cluster_range_ssbo
|
||||
{
|
||||
cluster_range_s cluster_ranges[];
|
||||
};
|
||||
|
||||
layout(std430, set = PASS_SET, binding = CLUSTER_INDEX_SSBO) readonly buffer cluster_index_ssbo
|
||||
{
|
||||
uint cluster_light_indices[];
|
||||
};
|
||||
|
||||
#ifdef STAGE_VERTEX
|
||||
mat4 effective_modelview()
|
||||
{
|
||||
return instance_modelview[gl_InstanceIndex] * modelview;
|
||||
}
|
||||
|
||||
mat3 effective_modelviewnormal()
|
||||
{
|
||||
// instance_modelview can include per-instance scale (uniform or per-axis), so its upper 3x3 is not its own inverse
|
||||
// transpose in the non-uniform case
|
||||
mat3 instance_mv3 = mat3(instance_modelview[gl_InstanceIndex]);
|
||||
mat3 instance_normal = transpose(inverse(instance_mv3));
|
||||
return instance_normal * modelviewnormal;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
108
shaders/vk14/conversion.glsl
Normal file
108
shaders/vk14/conversion.glsl
Normal file
@@ -0,0 +1,108 @@
|
||||
vec3 rgb2yuv(vec3 val)
|
||||
{
|
||||
return
|
||||
clamp(
|
||||
vec3(
|
||||
(0.257 * val.r) + (0.504 * val.g) + (0.098 * val.b) + 0.0625,
|
||||
-(0.148 * val.r) - (0.291 * val.g) + (0.439 * val.b) + 0.5,
|
||||
(0.439 * val.r) - (0.368 * val.g) - (0.071 * val.b) + 0.5 ),
|
||||
0.0, 1.0);
|
||||
}
|
||||
|
||||
vec3 yuv2rgb(vec3 val)
|
||||
{
|
||||
val -= vec3(0.0625, 0.5, 0.5);
|
||||
return
|
||||
clamp(
|
||||
vec3(
|
||||
(1.164 * val.r) + (1.596 * val.b),
|
||||
(1.164 * val.r) - (0.391 * val.g) - (0.813 * val.b),
|
||||
(1.164 * val.r) + (2.018 * val.g) ),
|
||||
0.0, 1.0);
|
||||
}
|
||||
|
||||
vec3 rgb2hsl( vec3 col )
|
||||
{
|
||||
float red = col.r;
|
||||
float green = col.g;
|
||||
float blue = col.b;
|
||||
|
||||
float minc = min( col.r, min( col.g, col.b ));
|
||||
float maxc = max( col.r, max( col.g, col.b ));
|
||||
float delta = maxc - minc;
|
||||
|
||||
float lum = (minc + maxc) * 0.5;
|
||||
float sat = 0.0;
|
||||
float hue = 0.0;
|
||||
|
||||
if (lum > 0.0 && lum < 1.0) {
|
||||
float mul = (lum < 0.5) ? (lum) : (1.0-lum);
|
||||
sat = delta / (mul * 2.0);
|
||||
}
|
||||
|
||||
vec3 masks = vec3(
|
||||
(maxc == red && maxc != green) ? 1.0 : 0.0,
|
||||
(maxc == green && maxc != blue) ? 1.0 : 0.0,
|
||||
(maxc == blue && maxc != red) ? 1.0 : 0.0
|
||||
);
|
||||
|
||||
vec3 adds = vec3(
|
||||
((green - blue ) / delta),
|
||||
2.0 + ((blue - red ) / delta),
|
||||
4.0 + ((red - green) / delta)
|
||||
);
|
||||
|
||||
float deltaGtz = (delta > 0.0) ? 1.0 : 0.0;
|
||||
|
||||
hue += dot( adds, masks );
|
||||
hue *= deltaGtz;
|
||||
hue /= 6.0;
|
||||
|
||||
if (hue < 0.0)
|
||||
hue += 1.0;
|
||||
|
||||
return vec3( hue, sat, lum );
|
||||
}
|
||||
|
||||
vec3 hsl2rgb( vec3 col )
|
||||
{
|
||||
const float onethird = 1.0 / 3.0;
|
||||
const float twothird = 2.0 / 3.0;
|
||||
const float rcpsixth = 6.0;
|
||||
|
||||
float hue = col.x;
|
||||
float sat = col.y;
|
||||
float lum = col.z;
|
||||
|
||||
vec3 xt = vec3(
|
||||
rcpsixth * (hue - twothird),
|
||||
0.0,
|
||||
rcpsixth * (1.0 - hue)
|
||||
);
|
||||
|
||||
if (hue < twothird) {
|
||||
xt.r = 0.0;
|
||||
xt.g = rcpsixth * (twothird - hue);
|
||||
xt.b = rcpsixth * (hue - onethird);
|
||||
}
|
||||
|
||||
if (hue < onethird) {
|
||||
xt.r = rcpsixth * (onethird - hue);
|
||||
xt.g = rcpsixth * hue;
|
||||
xt.b = 0.0;
|
||||
}
|
||||
|
||||
xt = min( xt, 1.0 );
|
||||
|
||||
float sat2 = 2.0 * sat;
|
||||
float satinv = 1.0 - sat;
|
||||
float luminv = 1.0 - lum;
|
||||
float lum2m1 = (2.0 * lum) - 1.0;
|
||||
vec3 ct = (sat2 * xt) + satinv;
|
||||
|
||||
vec3 rgb;
|
||||
if (lum >= 0.5) { rgb = (luminv * ct) + lum2m1; }
|
||||
else { rgb = lum * ct; }
|
||||
|
||||
return rgb;
|
||||
}
|
||||
15
shaders/vk14/copy.frag
Normal file
15
shaders/vk14/copy.frag
Normal file
@@ -0,0 +1,15 @@
|
||||
#version 460 core
|
||||
#define STAGE_FRAGMENT 1
|
||||
#define LAYOUT_POST 1
|
||||
#include "common.glsl"
|
||||
layout(location = 14) in vec2 f_coords;
|
||||
|
||||
#pragma texture(tex1, 0, sRGB)
|
||||
layout(set = POST_SET, binding = POST_TEXTURE_FIRST + 0) uniform sampler2D tex1;
|
||||
|
||||
layout(location = 0) out vec4 out_color;
|
||||
|
||||
void main()
|
||||
{
|
||||
out_color = texture(tex1, f_coords);
|
||||
}
|
||||
26
shaders/vk14/dither.glsl
Normal file
26
shaders/vk14/dither.glsl
Normal file
@@ -0,0 +1,26 @@
|
||||
// noise of half a step of the 8-bit output, added to the colour about to be written to the window: smooth dark gradients (the
|
||||
// fog at night) show no bands, which otherwise crawl over the image with the smallest change of the light. interleaved gradient
|
||||
// noise (Jimenez 2014) of the pixel, the same in every frame. the colour is the one written to the window: encoded already with
|
||||
// OUTPUT_GAMMA, linear otherwise (the sRGB framebuffer encodes it, so the step is taken in the encoded values)
|
||||
#ifndef DITHER_GLSL
|
||||
#define DITHER_GLSL
|
||||
|
||||
#include "common.glsl"
|
||||
|
||||
vec3 dither_output(vec3 color)
|
||||
{
|
||||
float noise = (fract(52.9829189 * fract(dot(gl_FragCoord.xy, vec2(0.06711056, 0.00583715)))) - 0.5) / 255.0;
|
||||
if (OUTPUT_GAMMA)
|
||||
{
|
||||
return max(color + noise, vec3(0.0));
|
||||
}
|
||||
else
|
||||
{
|
||||
vec3 linear = max(color, vec3(0.0));
|
||||
vec3 encoded = mix(linear * 12.92, 1.055 * pow(linear, vec3(1.0 / 2.4)) - 0.055, step(vec3(0.0031308), linear));
|
||||
encoded = max(encoded + noise, vec3(0.0));
|
||||
return mix(encoded / 12.92, pow((encoded + 0.055) / 1.055, vec3(2.4)), step(vec3(0.04045), encoded));
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
54
shaders/vk14/envmapping.glsl
Normal file
54
shaders/vk14/envmapping.glsl
Normal file
@@ -0,0 +1,54 @@
|
||||
layout(set = PASS_SET, binding = ENV_TEX) uniform samplerCube envmap;
|
||||
|
||||
vec3 envmap_color( vec3 normal )
|
||||
{
|
||||
vec3 envcolor;
|
||||
if (ENVMAP_ENABLED)
|
||||
{
|
||||
vec3 refvec = reflect(f_pos.xyz, normal); // view space
|
||||
refvec = vec3(inv_view * vec4(refvec, 0.0)); // world space
|
||||
envcolor = texture(envmap, refvec).rgb;
|
||||
// Sanitize. The env cubemap can briefly contain NaN/Inf after a
|
||||
// reflection-pass regeneration (m_empty_cubemap was bound during the
|
||||
// face render and on NVIDIA can sample as undefined). Without this
|
||||
// guard, a single bad texel propagates through env_reflection in
|
||||
// apply_lights() and produces one-frame black flashes on glossy
|
||||
// (esp. specgloss) surfaces.
|
||||
if (any(isnan(envcolor)) || any(isinf(envcolor))) envcolor = vec3(0.0);
|
||||
envcolor = max(envcolor, vec3(0.0));
|
||||
}
|
||||
else
|
||||
{
|
||||
envcolor = vec3(0.5);
|
||||
}
|
||||
return envcolor;
|
||||
}
|
||||
|
||||
// Roughness-aware env map lookup — uses mip levels for blurry reflections.
|
||||
// lod 0.0 = mirror sharp, lod ~8.0 = fully diffuse blur.
|
||||
vec3 envmap_color_lod(vec3 fragnormal, float lod)
|
||||
{
|
||||
if (ENVMAP_ENABLED)
|
||||
{
|
||||
vec3 refvec = reflect(f_pos.xyz, fragnormal); // view space — matches envmap_color exactly
|
||||
refvec = vec3(inv_view * vec4(refvec, 0.0)); // world space — was missing
|
||||
vec3 envcolor = textureLod(envmap, refvec, lod).rgb;
|
||||
// See envmap_color() above — same NaN/Inf sanitize, also needed here
|
||||
// because mipmap generation propagates a single NaN texel across the
|
||||
// whole mip chain.
|
||||
if (any(isnan(envcolor)) || any(isinf(envcolor))) envcolor = vec3(0.0);
|
||||
return max(envcolor, vec3(0.0));
|
||||
}
|
||||
else
|
||||
{
|
||||
return vec3(0.5); // was vec3(0.0), match the non-LOD fallback
|
||||
}
|
||||
}
|
||||
|
||||
// reflection of the surroundings in a surface of the given perceptual roughness (0 mirror, 1 matte): the plain map, its mipmaps
|
||||
// (box filtered) standing for the roughness. the prefiltered GGX map of the opengl renderer (env_ggx) comes in a later stage
|
||||
vec3 envmap_color_rough(vec3 fragnormal, float roughness)
|
||||
{
|
||||
const float MAX_REFLECTION_LOD = 8.0;
|
||||
return envmap_color_lod(fragnormal, roughness * MAX_REFLECTION_LOD);
|
||||
}
|
||||
38
shaders/vk14/freespot.frag
Normal file
38
shaders/vk14/freespot.frag
Normal file
@@ -0,0 +1,38 @@
|
||||
#version 460 core
|
||||
#define STAGE_FRAGMENT 1
|
||||
#include "common.glsl"
|
||||
layout(location = 3) in vec4 f_pos;
|
||||
layout(location = 4) in vec4 f_clip_pos;
|
||||
layout(location = 5) in vec4 f_clip_future_pos;
|
||||
|
||||
|
||||
layout(location = 0) out vec4 out_color;
|
||||
#ifdef NO_MOTION_OUTPUT
|
||||
// a pass without the velocity target: the writes go nowhere
|
||||
vec4 out_motion;
|
||||
#else
|
||||
layout(location = 1) out vec4 out_motion;
|
||||
#endif
|
||||
|
||||
#include "tonemapping.glsl"
|
||||
#include "apply_fog.glsl"
|
||||
|
||||
void main()
|
||||
{
|
||||
float x = (gl_PointCoord.x - 0.5f) * 2.0f;
|
||||
float y = (gl_PointCoord.y - 0.5f) * 2.0f;
|
||||
float dist = sqrt(x * x + y * y);
|
||||
if (dist > 0.5f)
|
||||
discard;
|
||||
// vec4 color = vec4(param[0].rgb * emission, mix(param[0].a, 0.0f, dist * 2.0f));
|
||||
vec4 color = vec4(apply_fog(pow(param[0].rgb, vec3(2.2)) * emission), mix(param[0].a, 0.0f, dist * 2.0f));
|
||||
// vec4 color = vec4(add_fog(param[0].rgb * emission * (1.0 - get_fog_amount()), 1.0), mix(param[0].a, 0.0f, dist * 2.0f));
|
||||
out_color = FBOUT(color);
|
||||
if (MOTIONBLUR_ENABLED)
|
||||
{
|
||||
vec2 a = (f_clip_future_pos.xy / f_clip_future_pos.w) * 0.5 + 0.5;;
|
||||
vec2 b = (f_clip_pos.xy / f_clip_pos.w) * 0.5 + 0.5;;
|
||||
|
||||
out_motion = vec4(a - b, 0.0f, 0.0f);
|
||||
}
|
||||
}
|
||||
21
shaders/vk14/freespot.vert
Normal file
21
shaders/vk14/freespot.vert
Normal file
@@ -0,0 +1,21 @@
|
||||
#version 460 core
|
||||
#define STAGE_VERTEX 1
|
||||
#include "common.glsl"
|
||||
layout(location = 0) in vec3 v_vert;
|
||||
layout(location = 1) in vec3 v_normal;
|
||||
layout(location = 2) in vec2 v_coord;
|
||||
|
||||
|
||||
layout(location = 3) out vec4 f_pos;
|
||||
layout(location = 4) out vec4 f_clip_pos;
|
||||
layout(location = 5) out vec4 f_clip_future_pos;
|
||||
|
||||
void main()
|
||||
{
|
||||
f_pos = modelview * vec4(v_vert, 1.0);
|
||||
f_clip_pos = (projection * modelview) * vec4(v_vert, 1.0f);
|
||||
f_clip_future_pos = (projection * future * modelview) * vec4(v_vert, 1.0f);
|
||||
|
||||
gl_Position = f_clip_pos;
|
||||
gl_PointSize = param[1].x;
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
#version 460 core
|
||||
#define STAGE_FRAGMENT 1
|
||||
#define LAYOUT_UI 1
|
||||
// the user interface (imgui): the colour of the vertices times the texture of the draw (the font, an image, a texture), pushed
|
||||
// with the draw
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#version 460 core
|
||||
#define STAGE_VERTEX 1
|
||||
#define LAYOUT_UI 1
|
||||
// the user interface (imgui), drawn by vk14::imgui_backend over the image of the window
|
||||
|
||||
#include "common.glsl"
|
||||
|
||||
594
shaders/vk14/light_common.glsl
Normal file
594
shaders/vk14/light_common.glsl
Normal file
@@ -0,0 +1,594 @@
|
||||
// stage D of the vulkan renderer: the sun with its cascaded shadows, the environment map, the headlights and the lamps (in the
|
||||
// clusters or not). the cube shadow maps of the lamps, the shadow maps of the headlights, the contact shadows, the shadows of
|
||||
// the clouds, the directional sky ambient light and the prefiltered environment map of shaders/ogl46/light_common.glsl come
|
||||
// with the later stages; the code below is the one of the opengl renderer with those left out, it shades as that one does
|
||||
// with them off
|
||||
layout(set = PASS_SET, binding = SHADOW_TEX) uniform sampler2DArrayShadow shadowmap;
|
||||
layout(set = PASS_SET, binding = HEADLIGHT_TEX) uniform sampler2D headlightmap;
|
||||
|
||||
#include "envmapping.glsl"
|
||||
#include "conversion.glsl"
|
||||
|
||||
float glossiness = 1.0;
|
||||
float metalic = 0.0;
|
||||
layout(location = 7) in vec4 UserData;
|
||||
#pragma param(weathering, 2, 3, 1, zero)
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Lighting balance tunables - tweak these to control overall scene
|
||||
// exposure without touching tonemapping.glsl.
|
||||
//
|
||||
// AMBIENT_SCALE: brightness of SHADED faces (indirect/sky term).
|
||||
// Lower -> deeper shadows, less burn under bright
|
||||
// textures. Higher -> flatter / brighter shading.
|
||||
//
|
||||
// SUN_DIFFUSE_SCALE: brightness of UNSHADED (sun-lit) faces. Lower
|
||||
// this to dim hot surfaces in direct sunlight
|
||||
// without affecting shaded areas. Was 3.5; 2.5
|
||||
// calmly fits the ACES tonemap shoulder.
|
||||
//
|
||||
// SUN_NDOTL_SHARPNESS: N.L curve on the sun. 1.0 = pure Lambert, higher
|
||||
// = sharper terminator (more contrast between
|
||||
// lit and shaded faces of the same surface).
|
||||
// ---------------------------------------------------------------------
|
||||
const float AMBIENT_SCALE = 0.65;
|
||||
const float SUN_DIFFUSE_SCALE = 1.5;
|
||||
const float SUN_NDOTL_SHARPNESS = 1.25;
|
||||
|
||||
float length2(vec3 v)
|
||||
{
|
||||
return dot(v, v);
|
||||
}
|
||||
|
||||
// share of the sun (the moon) held back before the fragment by the shadow map, 0..1
|
||||
float calc_shadow_map();
|
||||
float calc_shadow()
|
||||
{
|
||||
return calc_shadow_map();
|
||||
}
|
||||
|
||||
float calc_shadow_map()
|
||||
{
|
||||
if (SHADOWMAP_ENABLED)
|
||||
{
|
||||
float distance = dot(f_pos.xyz, f_pos.xyz);
|
||||
uint cascade;
|
||||
for (cascade = 0U; cascade < MAX_CASCADES; cascade++)
|
||||
if (distance <= cascade_end[cascade])
|
||||
break;
|
||||
// cascades fitted to the depth of the view of an earlier frame (gfx.shadow.sdsm) cover only the area of the points seen
|
||||
// then: a point at the edge of the view or one which came closer since may be outside the map of its cascade. it goes to
|
||||
// the first further cascade whose map holds it with the reach of the filter, and is lit past the last one
|
||||
if (shadow_fit.x > 0.0)
|
||||
{
|
||||
float border = 4.0 / float(textureSize(shadowmap, 0).x);
|
||||
for (; cascade < MAX_CASCADES; cascade++)
|
||||
{
|
||||
vec2 fitcoords = (lightview[cascade] * vec4(f_pos.xyz, 1.0)).xy;
|
||||
if (all(greaterThanEqual(fitcoords, vec2(border))) && all(lessThanEqual(fitcoords, vec2(1.0 - border))))
|
||||
break;
|
||||
}
|
||||
if (cascade >= MAX_CASCADES)
|
||||
return 0.0;
|
||||
}
|
||||
// Normal offset: sample the shadow map from a point pushed along the surface normal
|
||||
// by a fraction of the cascade's texel footprint. A constant depth bias can't keep up
|
||||
// with large texels (far cascades, small shadow maps) on surfaces at a grazing angle
|
||||
// to the sun, which then show shadow acne stripes. lightview maps view space metres
|
||||
// to [0,1] shadow map coordinates, so its x/y row lengths give texels per metre.
|
||||
vec3 shadownormal = normalize(f_normal);
|
||||
float shadowNdotL = clamp(dot(shadownormal, normalize(-lights[0].dir)), 0.0, 1.0);
|
||||
mat4 shadowview = lightview[cascade];
|
||||
float texelspermetre = min(length(vec3(shadowview[0][0], shadowview[1][0], shadowview[2][0])),
|
||||
length(vec3(shadowview[0][1], shadowview[1][1], shadowview[2][1]))) * float(textureSize(shadowmap, 0).x);
|
||||
float texelsize = 1.0 / texelspermetre;
|
||||
vec3 shadowpos = f_pos.xyz + shadownormal * (texelsize * 1.5 * (1.0 - shadowNdotL));
|
||||
vec4 lightpos = shadowview * vec4(shadowpos, 1.0);
|
||||
vec3 coords = lightpos.xyz / lightpos.w;
|
||||
if (coords.z < 0.0)
|
||||
return 0.0f;
|
||||
|
||||
|
||||
|
||||
float bias = 0.00005f * float(cascade + 1U);
|
||||
|
||||
// Fast path: 4 textureGather() calls cover a 4x4 texel block. Raw gathered
|
||||
// comparisons must be weighted by the sub-texel position (bilinear weights),
|
||||
// otherwise the result is constant across each shadow map texel and shadow
|
||||
// edges turn into texel-sized stair steps. With per-axis weights
|
||||
// (1-f, 1, 1, f) this equals a 3x3 grid of hardware bilinear PCF taps.
|
||||
vec2 size = vec2(textureSize(shadowmap, 0).xy);
|
||||
vec2 uv = coords.xy * size - 0.5;
|
||||
vec2 base = floor(uv);
|
||||
vec2 f = uv - base;
|
||||
float refz = coords.z + bias;
|
||||
float layer = float(cascade);
|
||||
// sampling at texel corners selects blocks with lower-left texel base-1 and base+1
|
||||
vec4 g00 = textureGather(shadowmap, vec3((base + vec2(0.0, 0.0)) / size, layer), refz);
|
||||
vec4 g10 = textureGather(shadowmap, vec3((base + vec2(2.0, 0.0)) / size, layer), refz);
|
||||
vec4 g01 = textureGather(shadowmap, vec3((base + vec2(0.0, 2.0)) / size, layer), refz);
|
||||
vec4 g11 = textureGather(shadowmap, vec3((base + vec2(2.0, 2.0)) / size, layer), refz);
|
||||
// gather component order: x=(0,1) y=(1,1) z=(1,0) w=(0,0)
|
||||
float shadow = dot(g00, vec4(1.0 - f.x, 1.0, 1.0 - f.y, (1.0 - f.x) * (1.0 - f.y)))
|
||||
+ dot(g10, vec4(1.0, f.x, f.x * (1.0 - f.y), 1.0 - f.y))
|
||||
+ dot(g01, vec4((1.0 - f.x) * f.y, f.y, 1.0, 1.0 - f.x))
|
||||
+ dot(g11, vec4(f.y, f.x * f.y, f.x, 1.0));
|
||||
return shadow / 9.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// GGX Microfacet BRDF helpers (Cook-Torrance)
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
// Trowbridge-Reitz (GGX) Normal Distribution Function
|
||||
// D(N,H,α) = α⁴ / (π · ((NdotH)²·(α⁴−1)+1)²)
|
||||
// α = roughness² (perceptual remapping so the slider feels linear)
|
||||
float D_GGX(float NdotH, float roughness)
|
||||
{
|
||||
float a = roughness * roughness; // perceptual -> linear roughness
|
||||
float a2 = a * a;
|
||||
float d = (NdotH * NdotH) * (a2 - 1.0) + 1.0;
|
||||
return a2 / (3.14159265359 * d * d);
|
||||
}
|
||||
|
||||
// Schlick-GGX single-term masking/shadowing (k remapped for direct lighting)
|
||||
float G_SchlickGGX(float NdotX, float roughness)
|
||||
{
|
||||
float r = roughness + 1.0;
|
||||
float k = (r * r) * (1.0 / 8.0); // k_direct = (roughness+1)²/8
|
||||
return NdotX / (NdotX * (1.0 - k) + k);
|
||||
}
|
||||
|
||||
// Separable Smith geometry term (not height-correlated)
|
||||
// G(N,V,L) = G_SchlickGGX(NdotV) · G_SchlickGGX(NdotL)
|
||||
float G_Smith(float NdotV, float NdotL, float roughness)
|
||||
{
|
||||
return G_SchlickGGX(NdotV, roughness) * G_SchlickGGX(NdotL, roughness);
|
||||
}
|
||||
|
||||
const float BRDF_PI = 3.14159265359;
|
||||
// the smoothest surface the lights are reflected by: a mirror would make a highlight smaller than a pixel
|
||||
const float MIN_ROUGHNESS = 0.045;
|
||||
// cap of the brdf for the lamps and headlights (see specular_light()): a tiny light next to a polished surface
|
||||
const float LOCAL_LIGHT_BRDF_LIMIT = 16.0;
|
||||
// no cap for the sun
|
||||
const float SUN_BRDF_LIMIT = 1.0e6;
|
||||
|
||||
// the specular reflectance at normal incidence and the perceptual roughness the lights are reflected with, worked out by
|
||||
// apply_lights() for the fragment before it adds the lamps (add_local_lights())
|
||||
vec3 spec_f0 = vec3(0.04);
|
||||
float spec_roughness = 0.5;
|
||||
|
||||
// a matte material (mat_default) reflects nothing: neither the surroundings nor the sun and the lamps, only the diffuse light
|
||||
bool matte = false;
|
||||
|
||||
// light of a light from Light_dir reflected by the surface, in the units of the diffuse shading (a white lambertian surface
|
||||
// facing the light reflects 1 of it): pi times the cook-torrance brdf with schlick's fresnel of F0, times n.l. Limit caps the
|
||||
// brdf without the n.l
|
||||
vec3 specular_light(vec3 light_dir, vec3 fragnormal, vec3 f0, float roughness, float limit)
|
||||
{
|
||||
float NdotL = dot(fragnormal, light_dir);
|
||||
if (NdotL <= 0.0)
|
||||
return vec3(0.0);
|
||||
vec3 V = normalize(-f_pos.xyz);
|
||||
vec3 H = normalize(light_dir + V);
|
||||
float NdotV = max(dot(fragnormal, V), 1e-4);
|
||||
float NdotH = max(dot(fragnormal, H), 0.0);
|
||||
float VdotH = max(dot(V, H), 0.0);
|
||||
float brdf = D_GGX(NdotH, roughness) * G_Smith(NdotV, NdotL, roughness) / (4.0 * NdotL * NdotV);
|
||||
vec3 fresnel = f0 + (1.0 - f0) * pow(1.0 - VdotH, 5.0);
|
||||
return fresnel * (min(brdf, limit) * NdotL * BRDF_PI);
|
||||
}
|
||||
|
||||
// perceptual roughness raised where the normal changes much from a pixel to the next (normal maps, tight curves), so the
|
||||
// highlight of a detail smaller than a pixel spreads over the pixel instead of flickering. Kaplanyan, Tokuyoshi, "Improved
|
||||
// geometric specular antialiasing", 2019
|
||||
float specular_antialiasing(vec3 fragnormal, float roughness)
|
||||
{
|
||||
vec3 dndx = dFdx(fragnormal);
|
||||
vec3 dndy = dFdy(fragnormal);
|
||||
float variance = 0.25 * (dot(dndx, dndx) + dot(dndy, dndy));
|
||||
float kernel = min(2.0 * variance, 0.18);
|
||||
float a2 = roughness * roughness * roughness * roughness;
|
||||
return sqrt(sqrt(clamp(a2 + kernel, 0.0, 1.0)));
|
||||
}
|
||||
|
||||
// the materials without a specgloss map give glossiness: (param[1].w, 10 by default) as the exponent of the blinn-phong
|
||||
// highlight of the old renderer. a lobe of exponent n is about a ggx one of alpha sqrt(2 / (n + 2))
|
||||
float phong_roughness(float exponent)
|
||||
{
|
||||
return sqrt(sqrt(2.0 / (max(exponent, 0.0) + 2.0)));
|
||||
}
|
||||
|
||||
// glossiness which apply_lights() turns into the roughness of a blinn-phong exponent (it takes 1 - glossiness / param[1].w)
|
||||
float phong_glossiness(float exponent)
|
||||
{
|
||||
return (1.0 - phong_roughness(exponent)) * max(abs(param[1].w), 1.0);
|
||||
}
|
||||
|
||||
// the reflection of the surroundings of a material without a specgloss map is a smooth varnish over the rough surface: the
|
||||
// old renderer showed it as a sharp reflection, as much of it as reflection: (and the masks of the material) asked for
|
||||
bool legacy_coat = false;
|
||||
|
||||
// set up the gloss of a material without a specgloss map, before apply_lights()
|
||||
void legacy_gloss()
|
||||
{
|
||||
glossiness = phong_glossiness(abs(param[1].w));
|
||||
legacy_coat = true;
|
||||
}
|
||||
|
||||
// Returns vec2(diffuse, specular) for a single punctual light.
|
||||
//
|
||||
// diffuse – Lambert N·L (Fresnel-weighted diffuse is handled per-material
|
||||
// in apply_lights, so we return raw N·L here).
|
||||
// specular – Cook-Torrance GGX: D·G / (4·NdotL·NdotV).
|
||||
// The Fresnel factor (F) is intentionally omitted here;
|
||||
// apply_lights already carries a per-material Fresnel term
|
||||
// that is applied to env reflections and can be routed to
|
||||
// direct specular there.
|
||||
//
|
||||
// Roughness is derived identically to env_roughness in apply_lights so
|
||||
// that direct and indirect specular highlights read consistently.
|
||||
vec2 calc_light(vec3 light_dir, vec3 fragnormal)
|
||||
{
|
||||
vec3 N = fragnormal;
|
||||
vec3 L = light_dir;
|
||||
vec3 V = normalize(-f_pos.xyz);
|
||||
vec3 H = normalize(L + V);
|
||||
|
||||
float NdotL = max(dot(N, L), 0.0);
|
||||
float NdotV = max(dot(N, V), 1e-4);
|
||||
float NdotH = max(dot(N, H), 0.0);
|
||||
|
||||
float diffuse_v = NdotL;
|
||||
|
||||
// Mirror the env-map roughness derivation so direct and indirect lobes match.
|
||||
// glossiness == param[1].w → roughness == 0.04 (near-mirror)
|
||||
// glossiness == 0 → roughness == 1.0 (fully diffuse)
|
||||
float roughness = clamp(1.0 - glossiness / max(abs(param[1].w), 1.0), 0.04, 1.0);
|
||||
|
||||
// Cook-Torrance specular (no Fresnel — see above):
|
||||
// f_spec = D(N,H,α) · G(N,V,L,α) / (4 · NdotL · NdotV)
|
||||
float D = D_GGX(NdotH, roughness);
|
||||
float G = G_Smith(NdotV, NdotL, roughness);
|
||||
float specular_v = (NdotL > 0.0)
|
||||
? (D * G) / max(4.0 * NdotL * NdotV, 1e-4)
|
||||
: 0.0;
|
||||
|
||||
return vec2(diffuse_v, specular_v);
|
||||
}
|
||||
|
||||
vec2 calc_point_light(light_s light, vec3 fragnormal)
|
||||
{
|
||||
vec3 light_dir = normalize(light.pos - f_pos.xyz);
|
||||
vec2 val = calc_light(light_dir, fragnormal);
|
||||
val.x += light.ambient;
|
||||
val *= light.intensity;
|
||||
|
||||
float distance = length(light.pos - f_pos.xyz);
|
||||
float atten = 1.0f / (distance * distance);
|
||||
//float atten = 1.0f / (1.0f + light.linear * distance + light.quadratic * (distance * distance));
|
||||
|
||||
return val * atten;
|
||||
}
|
||||
|
||||
vec2 calc_spot_light(light_s light, vec3 fragnormal)
|
||||
{
|
||||
vec3 light_dir = normalize(light.pos - f_pos.xyz);
|
||||
|
||||
float theta = dot(light_dir, normalize(-light.dir));
|
||||
float epsilon = light.in_cutoff - light.out_cutoff;
|
||||
float intensity = clamp((theta - light.out_cutoff) / epsilon, 0.0, 1.0);
|
||||
|
||||
vec2 point = calc_point_light(light, fragnormal);
|
||||
return point * intensity;
|
||||
}
|
||||
|
||||
vec2 calc_dir_light(light_s light, vec3 fragnormal)
|
||||
{
|
||||
vec3 light_dir = normalize(-light.dir);
|
||||
return calc_light(light_dir, fragnormal);
|
||||
}
|
||||
|
||||
// dpdx and dpdy are the change of the view space position of the fragment from a pixel to the next one. the beam texture is
|
||||
// sampled with gradients worked out from them instead of the ones of the hardware: those are undefined where the fragments of
|
||||
// a quad do not go through the same lights, which is what happens at the edges of the clusters
|
||||
vec2 calc_headlights(light_s light, vec3 fragnormal, vec3 dpdx, vec3 dpdy)
|
||||
{
|
||||
vec4 headlightpos = light.headlight_projection * f_pos;
|
||||
vec3 coords = headlightpos.xyz / headlightpos.w;
|
||||
|
||||
if (coords.z > 1.0)
|
||||
return vec2(0.0);
|
||||
if (coords.z < 0.0)
|
||||
return vec2(0.0);
|
||||
// the beam is what the projection takes in. beyond its sides the texture would be clamped to its edge, and near the projector
|
||||
// (where a pixel spans many texels) its coarsest levels spill the average of the whole beam over the surroundings
|
||||
if (coords.x < 0.0 || coords.x > 1.0 || coords.y < 0.0 || coords.y > 1.0)
|
||||
return vec2(0.0);
|
||||
|
||||
vec3 light_dir = normalize(light.pos - f_pos.xyz);
|
||||
// Tighter wrap (was +0.25): faces angled away from the headlight cone
|
||||
// fall off to dark much faster, so cab/exterior surfaces read with a
|
||||
// clear directional shape instead of a flat half-lit wash.
|
||||
vec2 part = vec2(1.0) * clamp(dot(fragnormal, light_dir) + 0.10, 0.0, 1.0);
|
||||
float distance = length(light.pos - f_pos.xyz);
|
||||
float atten = 1.0f / (1.0f + light.linear * distance + light.quadratic * (distance * distance));
|
||||
atten *= mix(1.0, 0.0, clamp((coords.z - 0.998) * 500.0, 0.0, 1.0));
|
||||
vec2 beamcoords = headlightpos.xy / headlightpos.w;
|
||||
vec4 dheadlightposdx = light.headlight_projection * vec4(dpdx, 0.0);
|
||||
vec4 dheadlightposdy = light.headlight_projection * vec4(dpdy, 0.0);
|
||||
vec2 dbeamdx = (dheadlightposdx.xy - beamcoords * dheadlightposdx.w) / headlightpos.w;
|
||||
vec2 dbeamdy = (dheadlightposdy.xy - beamcoords * dheadlightposdy.w) / headlightpos.w;
|
||||
vec3 lights = textureGrad(headlightmap, beamcoords, dbeamdx, dbeamdy).rgb * light.headlight_weights.rgb;
|
||||
float lightintensity = max(max(lights.r, lights.g), lights.b);
|
||||
// x the diffuse light, y the light the specular reflection takes (specular_light() brings its own n.l)
|
||||
return vec2(part.x, 1.0) * (atten * lightintensity);
|
||||
}
|
||||
|
||||
// closest distance (squared) the light of a lamp is computed for: nearer the inverse square would grow without a limit
|
||||
const float LOCAL_LIGHT_MIN_DISTANCE2 = 0.01;
|
||||
|
||||
// light of a lamp (point or spot light: the lamps of models and vehicles, the cab lamp) reaching the fragment, x the diffuse
|
||||
// part and y the light the specular reflection takes (specular_light() brings its own n.l). it falls off with the square of the distance, and smoothly to nothing at the range of the light,
|
||||
// 1 / sqrt(quadratic), past which the culling of the clusters does not take it. a spot light fades from its inner cone to the
|
||||
// outer one
|
||||
vec2 calc_local_light(light_s light, vec3 fragnormal)
|
||||
{
|
||||
vec3 tolight = light.pos - f_pos.xyz;
|
||||
float distance2 = dot(tolight, tolight);
|
||||
vec3 light_dir = tolight * inversesqrt(max(distance2, 1e-8));
|
||||
float edge = clamp(1.0 - distance2 * distance2 * (light.quadratic * light.quadratic), 0.0, 1.0);
|
||||
float atten = edge * edge / max(distance2, LOCAL_LIGHT_MIN_DISTANCE2);
|
||||
if (light.type == LIGHT_SPOT)
|
||||
atten *= smoothstep(light.out_cutoff, light.in_cutoff, dot(-light_dir, normalize(light.dir)));
|
||||
if (atten <= 0.0)
|
||||
return vec2(0.0);
|
||||
return vec2(max(dot(fragnormal, light_dir), 0.0), 1.0) * atten;
|
||||
}
|
||||
|
||||
// index of the light cluster the fragment is in, see gl/cluster_grid.h: its screen tile and slice of depth. the depth is the clip
|
||||
// space w, which is 1 / gl_FragCoord.w. a tile is kept in the grid, as the far edge of the render target and rounding
|
||||
// right below it give one past the last
|
||||
uint fragment_cluster()
|
||||
{
|
||||
ivec2 tile = ivec2(gl_FragCoord.xy * (vec2(CLUSTER_GRID_X, CLUSTER_GRID_Y) / cluster_viewport_size));
|
||||
tile = clamp(tile, ivec2(0), ivec2(CLUSTER_GRID_X - 1, CLUSTER_GRID_Y - 1));
|
||||
int slice = clamp(int(floor(cluster_slice_bias - log(gl_FragCoord.w) * cluster_slice_scale)), 0, CLUSTER_GRID_Z - 1);
|
||||
return uint(tile.x + CLUSTER_GRID_X * (tile.y + CLUSTER_GRID_Y * slice));
|
||||
}
|
||||
|
||||
// adds the light of a headlight or lamp to the diffuse and the specular light of the fragment
|
||||
void add_local_light(light_s light, vec2 part, vec3 fragnormal, inout vec3 diffuse, inout vec3 specular)
|
||||
{
|
||||
if (part.y <= 0.0)
|
||||
return;
|
||||
vec3 color = light.color * light.intensity;
|
||||
diffuse += color * part.x;
|
||||
if (matte)
|
||||
return;
|
||||
specular += color * (part.y * param[1].y) * specular_light(normalize(light.pos - f_pos.xyz), fragnormal, spec_f0, spec_roughness, LOCAL_LIGHT_BRDF_LIMIT);
|
||||
}
|
||||
|
||||
// adds the light of the headlights and lamps which reach the fragment to its diffuse and specular light. these are the ones in
|
||||
// the list of its cluster when the lights are clustered (the sun is not on the list, the callers take care of it), and the
|
||||
// first lights_count - 1 of lights[] otherwise, which are headlights only. the specular light is reflected with spec_f0 and
|
||||
// spec_roughness, and is already coloured by the fresnel term
|
||||
void add_local_lights(vec3 fragnormal, inout vec3 diffuse, inout vec3 specular)
|
||||
{
|
||||
// worked out before the loops, which the fragments of a quad do not leave together
|
||||
vec3 dpdx = dFdx(f_pos.xyz);
|
||||
vec3 dpdy = dFdy(f_pos.xyz);
|
||||
|
||||
if (lights_clustered != 0U)
|
||||
{
|
||||
cluster_range_s range = cluster_ranges[fragment_cluster()];
|
||||
for (uint i = 0U; i < range.count; i++)
|
||||
{
|
||||
light_s light = lights[cluster_light_indices[range.offset + i]];
|
||||
vec2 part = (light.type == LIGHT_HEADLIGHTS) ? calc_headlights(light, fragnormal, dpdx, dpdy) : calc_local_light(light, fragnormal);
|
||||
add_local_light(light, part, fragnormal, diffuse, specular);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (uint i = 1U; i < lights_count; i++)
|
||||
{
|
||||
light_s light = lights[i];
|
||||
add_local_light(light, calc_headlights(light, fragnormal, dpdx, dpdy), fragnormal, diffuse, specular);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// the light of the headlights and lamps added to Fragcolor, diffuse and specular together (for shaders which don't tell
|
||||
// the albedo from the reflection)
|
||||
vec3 add_headlights(vec3 fragcolor, vec3 fragnormal)
|
||||
{
|
||||
vec3 diffuse = vec3(0.0);
|
||||
vec3 specular = vec3(0.0);
|
||||
add_local_lights(fragnormal, diffuse, specular);
|
||||
return fragcolor + diffuse + specular;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Split-sum environment BRDF (Karis / UE4 analytic approximation).
|
||||
//
|
||||
// This is the missing piece that made matte specgloss surfaces "shine like
|
||||
// crazy": previously the env reflection was added at full strength
|
||||
// (envcolor * fresnel * reflectivity) and roughness only blurred the mip,
|
||||
// never dimmed the energy. A rough surface therefore mirrored the bright
|
||||
// sky just as strongly as a polished one.
|
||||
//
|
||||
// EnvBRDFApprox returns the pre-integrated specular scale (the "DFG" term)
|
||||
// for a given F0, roughness and view angle. For rough surfaces it collapses
|
||||
// toward ~0, so low-glossiness materials reflect almost nothing — matching
|
||||
// what Substance 3D Painter shows. Polished surfaces keep their full
|
||||
// reflection, and the grazing-angle Fresnel edge is preserved.
|
||||
// roughness 1.0 (matte) -> scale ~0.015 (virtually no reflection)
|
||||
// roughness 0.0 (mirror) -> scale ~F0..1 (full reflection + Fresnel rim)
|
||||
vec3 EnvBRDFApprox(vec3 F0, float roughness, float NoV)
|
||||
{
|
||||
const vec4 c0 = vec4(-1.0, -0.0275, -0.572, 0.022);
|
||||
const vec4 c1 = vec4( 1.0, 0.0425, 1.040, -0.040);
|
||||
vec4 r = roughness * c0 + c1;
|
||||
float a004 = min(r.x * r.x, exp2(-9.28 * NoV)) * r.x + r.y;
|
||||
vec2 AB = vec2(-1.04, 1.04) * a004 + r.zw;
|
||||
return F0 * AB.x + AB.y;
|
||||
}
|
||||
|
||||
// Diffuse colour of the submodel (t3d/e3d) or shape, used as the albedo multiplier:
|
||||
// untextured materials take it as their colour, textured ones multiply the base texture by it
|
||||
// (same as the legacy renderer's GL_MODULATE). param[0].rgb holds the authored sRGB colour,
|
||||
// param[1].x its intensity (HSV value unless a material overrides it).
|
||||
vec3 material_diffuse()
|
||||
{
|
||||
vec3 diffusecolor = pow(max(param[0].rgb, vec3(0.0)), vec3(2.2));
|
||||
float value = max(param[0].r, max(param[0].g, param[0].b));
|
||||
return (value > 0.0 ? diffusecolor * (param[1].x / value) : vec3(0.0));
|
||||
}
|
||||
|
||||
// lights the surface: the ambient light, the sun (the moon), the headlights and lamps and the reflection of the surroundings.
|
||||
// the units are the ones of the ambient light, the irradiance over pi: a white lambertian surface lit by 1 of it shows 1.
|
||||
// Texturecolor is the albedo (the base colour of a metal), Specularity the specular level of a dielectric (0.5 is the
|
||||
// reflectance of 4% at normal incidence), Reflectivity how much of the reflected surroundings is the cubemap rather than the
|
||||
// ambient light, Shadowtone the share of the sun left in its shadow (1 for the materials which take no shadows).
|
||||
// a Sunless surface (the interior of a cab) gets no light of the sun, its shadow only darkens the ambient light
|
||||
vec3 shade_surface(vec3 fragcolor, vec3 fragnormal, vec3 texturecolor, float reflectivity, float specularity, float shadowtone, bool sunless)
|
||||
{
|
||||
// Diffuse colour is applied once, to the albedo; the light terms below are not scaled by it again
|
||||
texturecolor *= material_diffuse();
|
||||
float polished = 0.0;
|
||||
if (sunless)
|
||||
{
|
||||
// Cab interior: dim ambient less than the exterior path - ambient
|
||||
// is the dominant indoor illumination, but it was still too bright.
|
||||
fragcolor *= 0.80;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifndef NO_WEATHERING
|
||||
float weathered = (param[2].w > 0.0 ? clamp(param[2].w * UserData.x, 0.0, 1.0) : 0.0);
|
||||
float tinted = (param[2].w < 0.0 ? clamp(-param[2].w * UserData.x, 0.0, 1.0) : 0.0);
|
||||
// a tint only scales the colour of the texture, the steel keeps its own polish
|
||||
polished = weathered * smoothstep(0.03, 0.12, dot(texturecolor, vec3(0.2126, 0.7152, 0.0722)));
|
||||
float weatheredluma = min(dot(texturecolor, vec3(0.2126, 0.7152, 0.0722)), 0.05);
|
||||
vec3 unused = texturecolor * (weatheredluma / max(dot(texturecolor, vec3(0.2126, 0.7152, 0.0722)), 1e-4));
|
||||
unused = mix(unused, vec3(1.0, 0.82, 0.74) * (weatheredluma / 0.8525), 0.5);
|
||||
texturecolor = mix(texturecolor, unused, smoothstep(0.0, 0.4, weathered));
|
||||
texturecolor = (tinted > 0.0 ? texturecolor * mix(vec3(1.0), param[2].rgb, tinted) : texturecolor);
|
||||
specularity = mix(specularity, min(specularity, 0.03), smoothstep(0.0, 0.4, polished));
|
||||
metalic = mix(metalic, 0.0, polished);
|
||||
glossiness = mix(glossiness, min(glossiness, 0.06 * abs(param[1].w)), polished);
|
||||
reflectivity = mix(reflectivity, min(reflectivity, 0.08 * param[1].z), smoothstep(0.0, 0.4, polished));
|
||||
#endif
|
||||
// Scale ambient before it gets tinted by the texture.
|
||||
// Sun, headlights and emission are added afterwards so they are NOT
|
||||
// attenuated by AMBIENT_SCALE - this only dims the indirect term.
|
||||
fragcolor *= AMBIENT_SCALE;
|
||||
}
|
||||
|
||||
vec3 emissioncolor = vec3(emission);
|
||||
vec3 view_dir = normalize(-f_pos.xyz);
|
||||
float NdotV = max(dot(fragnormal, view_dir), 1e-4);
|
||||
|
||||
// glossiness == param[1].w -> mirror, glossiness == 0 -> fully rough
|
||||
float roughness = clamp(1.0 - glossiness / max(abs(param[1].w), 1.0), 0.0, 1.0);
|
||||
roughness = max(specular_antialiasing(fragnormal, roughness), MIN_ROUGHNESS);
|
||||
// metals reflect with their base colour, dielectrics with the specular level (0.5 -> 0.04)
|
||||
vec3 f0 = mix(vec3(0.08 * specularity), texturecolor, metalic);
|
||||
spec_f0 = f0;
|
||||
spec_roughness = roughness;
|
||||
|
||||
// Pre-integrated env BRDF: how much of the surroundings the surface reflects, for its F0, roughness and the view angle.
|
||||
// the surroundings are the cubemap where the material asks for it (reflectivity) and the ambient light elsewhere, so a
|
||||
// surface reflects them always, the rough one barely
|
||||
vec3 env_spec = EnvBRDFApprox(f0, roughness, NdotV);
|
||||
float env_roughness = roughness;
|
||||
vec3 cubemap_spec = env_spec;
|
||||
float cubemap_share = max(reflectivity, 0.0);
|
||||
float ambient_share = clamp(1.0 - reflectivity, 0.0, 1.0);
|
||||
if (matte)
|
||||
{
|
||||
env_spec = vec3(0.0);
|
||||
cubemap_share = 0.0;
|
||||
}
|
||||
// what the diffuse layer is left with
|
||||
vec3 diffuse_albedo = texturecolor * (1.0 - metalic) * (1.0 - env_spec);
|
||||
if (legacy_coat)
|
||||
{
|
||||
// the varnish: a smooth dielectric layer reflecting the cubemap, worn off where the material is weathered
|
||||
env_roughness = specular_antialiasing(fragnormal, roughness * smoothstep(0.0, 0.4, polished));
|
||||
cubemap_spec = EnvBRDFApprox(mix(vec3(0.04), texturecolor, metalic), env_roughness, NdotV);
|
||||
ambient_share = 1.0;
|
||||
diffuse_albedo *= 1.0 - cubemap_spec * min(cubemap_share, 1.0);
|
||||
}
|
||||
vec3 envcolor = (matte ? vec3(0.0) : envmap_color_rough(fragnormal, env_roughness));
|
||||
|
||||
if (lights_count == 0U)
|
||||
return fragcolor * diffuse_albedo
|
||||
+ emissioncolor * texturecolor
|
||||
+ fragcolor * env_spec * ambient_share
|
||||
+ envcolor * cubemap_spec * cubemap_share;
|
||||
|
||||
vec3 light_dir = normalize(-lights[0].dir);
|
||||
float NdotL = max(dot(fragnormal, light_dir), 0.0);
|
||||
// Sharpen sun N.L falloff so the lit-to-shaded terminator on cab
|
||||
// panels, vehicle bodies and terrain reads as a clear edge rather
|
||||
// than a soft Lambertian ramp. Tunable via SUN_NDOTL_SHARPNESS.
|
||||
float sun_NdotL = pow(NdotL, SUN_NDOTL_SHARPNESS);
|
||||
// the shadows of the clouds come with the weather (stage P2): nothing holds the sun back yet
|
||||
float cloudsun = 1.0;
|
||||
// Sun HDR scale -> SUN_DIFFUSE_SCALE, the same for the diffuse and the specular light
|
||||
vec3 sunlight = lights[0].color * (SUN_DIFFUSE_SCALE * lights[0].intensity * cloudsun);
|
||||
|
||||
float shadow = 0.0;
|
||||
if (shadowtone < 1.0)
|
||||
shadow = clamp(calc_shadow(), 0.0, 1.0);
|
||||
|
||||
// the cubemap knows nothing of what shades the fragment: it is dimmed a little in the shadow of the sun
|
||||
float cubemap_shadow = 1.0;
|
||||
if (sunless)
|
||||
{
|
||||
// the sun adds no light in the cab, where it would fall its shadow darkens the ambient light
|
||||
float diffuseamount = sun_NdotL * lights[0].intensity;
|
||||
float darkness = (shadowtone < 1.0 ? max(shadow, 1.0 - cloudsun) : 0.0);
|
||||
fragcolor = mix(fragcolor, fragcolor * shadowtone, clamp(diffuseamount * darkness, 0.0, 1.0));
|
||||
}
|
||||
else
|
||||
cubemap_shadow = 1.0 - (1.0 - shadowtone) * shadow * 0.5;
|
||||
|
||||
// the reflection of the surroundings, before the light of the sun and the lamps joins the ambient light
|
||||
vec3 env_reflection = fragcolor * env_spec * ambient_share
|
||||
+ envcolor * cubemap_spec * (cubemap_share * cubemap_shadow);
|
||||
|
||||
// the shadow leaves the share of the sun Shadowtone tells (the old shadow colour of the scenery) to the diffuse light,
|
||||
// nothing to the highlight
|
||||
if (!sunless)
|
||||
fragcolor += sunlight * (sun_NdotL * (1.0 - (1.0 - shadowtone) * shadow));
|
||||
vec3 specular = matte ? vec3(0.0) : sunlight * specular_light(light_dir, fragnormal, f0, roughness, SUN_BRDF_LIMIT) * (1.0 - shadow);
|
||||
|
||||
vec3 lampspecular = vec3(0.0);
|
||||
add_local_lights(fragnormal, fragcolor, lampspecular);
|
||||
|
||||
return fragcolor * diffuse_albedo // ambient, sun and lamps on the diffuse layer
|
||||
+ specular * param[1].y // highlight of the sun, fresnel coloured (metals take their base colour)
|
||||
+ lampspecular // highlights of the lamps, param[1].y already applied
|
||||
+ emissioncolor * texturecolor
|
||||
+ env_reflection;
|
||||
}
|
||||
|
||||
vec3 apply_lights(vec3 fragcolor, vec3 fragnormal, vec3 texturecolor, float reflectivity, float specularity, float shadowtone)
|
||||
{
|
||||
return shade_surface(fragcolor, fragnormal, texturecolor, reflectivity, specularity, shadowtone, false);
|
||||
}
|
||||
|
||||
// the interior of a cab: no light of the sun, its shadow darkens the ambient light
|
||||
vec3 apply_lights_sunless(vec3 fragcolor, vec3 fragnormal, vec3 texturecolor, float reflectivity, float specularity, float shadowtone)
|
||||
{
|
||||
return shade_surface(fragcolor, fragnormal, texturecolor, reflectivity, specularity, shadowtone, true);
|
||||
}
|
||||
4
shaders/vk14/mat_colored.frag
Normal file
4
shaders/vk14/mat_colored.frag
Normal file
@@ -0,0 +1,4 @@
|
||||
#version 460 core
|
||||
#define STAGE_FRAGMENT 1
|
||||
#include "common.glsl"
|
||||
#include "mat_colored.glsl"
|
||||
60
shaders/vk14/mat_colored.glsl
Normal file
60
shaders/vk14/mat_colored.glsl
Normal file
@@ -0,0 +1,60 @@
|
||||
layout(location = 0) in vec3 f_normal;
|
||||
layout(location = 2) in vec2 f_coord;
|
||||
layout(location = 3) in vec4 f_pos;
|
||||
|
||||
layout(location = 4) in vec4 f_clip_pos;
|
||||
layout(location = 5) in vec4 f_clip_future_pos;
|
||||
|
||||
#include "common.glsl"
|
||||
|
||||
#pragma param(color, 0, 0, 4, diffuse)
|
||||
#pragma param(diffuse, 1, 0, 1, diffuse)
|
||||
#pragma param(specular, 1, 1, 1, specular)
|
||||
#pragma param(reflection, 1, 2, 1, zero)
|
||||
#pragma param(glossiness, 1, 3, 1, glossiness)
|
||||
|
||||
layout(location = 0) out vec4 out_color;
|
||||
#ifdef NO_MOTION_OUTPUT
|
||||
// a pass without the velocity target: the writes go nowhere
|
||||
vec4 out_motion;
|
||||
#else
|
||||
layout(location = 1) out vec4 out_motion;
|
||||
#endif
|
||||
|
||||
#include "light_common.glsl"
|
||||
#include "apply_fog.glsl"
|
||||
#include "tonemapping.glsl"
|
||||
|
||||
void main()
|
||||
{
|
||||
// no texture: the diffuse colour alone makes the albedo, apply_lights() applies it to the white base
|
||||
vec4 tex_color = vec4(1.0, 1.0, 1.0, param[0].a);
|
||||
|
||||
// if (tex_color.a < opacity)
|
||||
// discard;
|
||||
|
||||
vec3 fragcolor = ambient;
|
||||
vec3 fragnormal = normalize(f_normal);
|
||||
float reflectivity = param[1].z;
|
||||
float specularity = dot(pow(param[0].rgb, vec3(2.2)), vec3(0.5));
|
||||
legacy_gloss();
|
||||
|
||||
fragcolor = apply_lights(fragcolor, fragnormal, tex_color.rgb, reflectivity, specularity, shadow_tone);
|
||||
|
||||
vec4 color = vec4(apply_fog(fragcolor), tex_color.a * alpha_mult);
|
||||
if (POSTFX_ENABLED)
|
||||
{
|
||||
out_color = color;
|
||||
}
|
||||
else
|
||||
{
|
||||
out_color = tonemap(color);
|
||||
}
|
||||
if (MOTIONBLUR_ENABLED)
|
||||
{
|
||||
vec2 a = (f_clip_future_pos.xy / f_clip_future_pos.w) * 0.5 + 0.5;;
|
||||
vec2 b = (f_clip_pos.xy / f_clip_pos.w) * 0.5 + 0.5;;
|
||||
|
||||
out_motion = vec4(a - b, 0.0f, 0.0f);
|
||||
}
|
||||
}
|
||||
4
shaders/vk14/mat_default.frag
Normal file
4
shaders/vk14/mat_default.frag
Normal file
@@ -0,0 +1,4 @@
|
||||
#version 460 core
|
||||
#define STAGE_FRAGMENT 1
|
||||
#include "common.glsl"
|
||||
#include "mat_default.glsl"
|
||||
69
shaders/vk14/mat_default.glsl
Normal file
69
shaders/vk14/mat_default.glsl
Normal file
@@ -0,0 +1,69 @@
|
||||
layout(location = 0) in vec3 f_normal;
|
||||
layout(location = 2) in vec2 f_coord;
|
||||
layout(location = 3) in vec4 f_pos;
|
||||
|
||||
layout(location = 4) in vec4 f_clip_pos;
|
||||
layout(location = 5) in vec4 f_clip_future_pos;
|
||||
|
||||
#include "common.glsl"
|
||||
|
||||
#pragma param(color, 0, 0, 4, diffuse)
|
||||
#pragma param(diffuse, 1, 0, 1, diffuse)
|
||||
#pragma param(specular, 1, 1, 1, specular)
|
||||
#pragma param(reflection, 1, 2, 1, zero)
|
||||
#pragma param(glossiness, 1, 3, 1, glossiness)
|
||||
|
||||
#pragma texture(diffuse, 0, sRGB_A)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 0) uniform sampler2D diffuse;
|
||||
|
||||
layout(location = 0) out vec4 out_color;
|
||||
#ifdef NO_MOTION_OUTPUT
|
||||
// a pass without the velocity target: the writes go nowhere
|
||||
vec4 out_motion;
|
||||
#else
|
||||
layout(location = 1) out vec4 out_motion;
|
||||
#endif
|
||||
|
||||
#include "light_common.glsl"
|
||||
#include "apply_fog.glsl"
|
||||
#include "tonemapping.glsl"
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 tex_color = texture(diffuse, f_coord);
|
||||
|
||||
bool alphatestfail = ( opacity >= 0.0 ? (tex_color.a < opacity) : (tex_color.a >= -opacity) );
|
||||
if(alphatestfail)
|
||||
discard;
|
||||
// if (tex_color.a < opacity)
|
||||
// discard;
|
||||
|
||||
vec3 fragcolor = ambient;
|
||||
vec3 fragnormal = normalize(f_normal);
|
||||
matte = true;
|
||||
|
||||
fragcolor = apply_lights(fragcolor, fragnormal, tex_color.rgb, 0.0, 0.0, shadow_tone);
|
||||
vec4 color = vec4(apply_fog(fragcolor), tex_color.a * alpha_mult);
|
||||
/*
|
||||
float distance = dot(f_pos.xyz, f_pos.xyz);
|
||||
if( distance <= cascade_end.x ) { color.r += 0.25; }
|
||||
else if( distance <= cascade_end.y ) { color.g += 0.25; }
|
||||
else if( distance <= cascade_end.z ) { color.b += 0.25; }
|
||||
*/
|
||||
if (POSTFX_ENABLED)
|
||||
{
|
||||
out_color = color;
|
||||
}
|
||||
else
|
||||
{
|
||||
out_color = tonemap(color);
|
||||
}
|
||||
|
||||
if (MOTIONBLUR_ENABLED)
|
||||
{
|
||||
vec2 a = (f_clip_future_pos.xy / f_clip_future_pos.w) * 0.5 + 0.5;;
|
||||
vec2 b = (f_clip_pos.xy / f_clip_pos.w) * 0.5 + 0.5;;
|
||||
|
||||
out_motion = vec4(a - b, 0.0f, tex_color.a * alpha_mult);
|
||||
}
|
||||
}
|
||||
4
shaders/vk14/mat_default_0.frag
Normal file
4
shaders/vk14/mat_default_0.frag
Normal file
@@ -0,0 +1,4 @@
|
||||
#version 460 core
|
||||
#define STAGE_FRAGMENT 1
|
||||
#include "common.glsl"
|
||||
#include "mat_colored.glsl"
|
||||
4
shaders/vk14/mat_default_1.frag
Normal file
4
shaders/vk14/mat_default_1.frag
Normal file
@@ -0,0 +1,4 @@
|
||||
#version 460 core
|
||||
#define STAGE_FRAGMENT 1
|
||||
#include "common.glsl"
|
||||
#include "mat_default.glsl"
|
||||
4
shaders/vk14/mat_default_2.frag
Normal file
4
shaders/vk14/mat_default_2.frag
Normal file
@@ -0,0 +1,4 @@
|
||||
#version 460 core
|
||||
#define STAGE_FRAGMENT 1
|
||||
#include "common.glsl"
|
||||
#include "mat_reflmap.glsl"
|
||||
77
shaders/vk14/mat_default_detail.frag
Normal file
77
shaders/vk14/mat_default_detail.frag
Normal file
@@ -0,0 +1,77 @@
|
||||
#version 460 core
|
||||
#define STAGE_FRAGMENT 1
|
||||
#include "common.glsl"
|
||||
layout(location = 0) in vec3 f_normal;
|
||||
layout(location = 2) in vec2 f_coord;
|
||||
layout(location = 3) in vec4 f_pos;
|
||||
layout(location = 8) in mat3 f_tbn;
|
||||
|
||||
layout(location = 4) in vec4 f_clip_pos;
|
||||
layout(location = 5) in vec4 f_clip_future_pos;
|
||||
|
||||
|
||||
#pragma param(color, 0, 0, 4, diffuse)
|
||||
#pragma param(diffuse, 1, 0, 1, diffuse)
|
||||
#pragma param(specular, 1, 1, 1, specular)
|
||||
#pragma param(reflection, 1, 2, 1, zero)
|
||||
#pragma param(glossiness, 1, 3, 1, glossiness)
|
||||
#pragma param(detail_scale, 2, 0, 1, one)
|
||||
|
||||
#pragma texture(diffuse, 0, sRGB_A)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 0) uniform sampler2D diffuse;
|
||||
|
||||
layout(location = 0) out vec4 out_color;
|
||||
#ifdef NO_MOTION_OUTPUT
|
||||
// a pass without the velocity target: the writes go nowhere
|
||||
vec4 out_motion;
|
||||
#else
|
||||
layout(location = 1) out vec4 out_motion;
|
||||
#endif
|
||||
|
||||
#pragma texture(detailnormalmap, 1, RGBA)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 1) uniform sampler2D detailnormalmap;
|
||||
|
||||
#define NORMALMAP
|
||||
#include "light_common.glsl"
|
||||
#include "apply_fog.glsl"
|
||||
#include "tonemapping.glsl"
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 tex_color = texture(diffuse, f_coord);
|
||||
|
||||
bool alphatestfail = ( opacity >= 0.0 ? (tex_color.a < opacity) : (tex_color.a >= -opacity) );
|
||||
if(alphatestfail)
|
||||
discard;
|
||||
// if (tex_color.a < opacity)
|
||||
// discard;
|
||||
|
||||
vec3 fragcolor = ambient;
|
||||
|
||||
vec3 normal;
|
||||
normal.xy = (texture(detailnormalmap, f_coord * param[2].x).rg * 2.0 - 1.0);
|
||||
normal.z = sqrt(1.0 - clamp((dot(normal.xy, normal.xy)), 0.0, 1.0));
|
||||
vec3 fragnormal = normalize(f_tbn * normalize(normal.xyz));
|
||||
float reflectivity = param[1].z;
|
||||
float specularity = (tex_color.r + tex_color.g + tex_color.b) * 0.5;
|
||||
legacy_gloss();
|
||||
|
||||
fragcolor = apply_lights(fragcolor, fragnormal, tex_color.rgb, reflectivity, specularity, shadow_tone);
|
||||
vec4 color = vec4(apply_fog(fragcolor), tex_color.a * alpha_mult);
|
||||
if (POSTFX_ENABLED)
|
||||
{
|
||||
out_color = color;
|
||||
}
|
||||
else
|
||||
{
|
||||
out_color = tonemap(color);
|
||||
}
|
||||
|
||||
if (MOTIONBLUR_ENABLED)
|
||||
{
|
||||
vec2 a = (f_clip_future_pos.xy / f_clip_future_pos.w) * 0.5 + 0.5;;
|
||||
vec2 b = (f_clip_pos.xy / f_clip_pos.w) * 0.5 + 0.5;;
|
||||
|
||||
out_motion = vec4(a - b, 0.0f, tex_color.a * alpha_mult);
|
||||
}
|
||||
}
|
||||
77
shaders/vk14/mat_default_specgloss.frag
Normal file
77
shaders/vk14/mat_default_specgloss.frag
Normal file
@@ -0,0 +1,77 @@
|
||||
#version 460 core
|
||||
#define STAGE_FRAGMENT 1
|
||||
#include "common.glsl"
|
||||
layout(location = 0) in vec3 f_normal;
|
||||
layout(location = 2) in vec2 f_coord;
|
||||
layout(location = 3) in vec4 f_pos;
|
||||
|
||||
layout(location = 4) in vec4 f_clip_pos;
|
||||
layout(location = 5) in vec4 f_clip_future_pos;
|
||||
|
||||
|
||||
#pragma param(color, 0, 0, 4, diffuse)
|
||||
#pragma param(diffuse, 1, 0, 1, diffuse)
|
||||
#pragma param(specular, 1, 1, 1, specular)
|
||||
#pragma param(reflection, 1, 2, 1, zero)
|
||||
#pragma param(glossiness, 1, 3, 1, glossiness)
|
||||
|
||||
#pragma texture(diffuse, 0, sRGB_A)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 0) uniform sampler2D diffuse;
|
||||
|
||||
#pragma texture(specgloss, 1, RGBA)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 1) uniform sampler2D specgloss;
|
||||
|
||||
layout(location = 0) out vec4 out_color;
|
||||
#ifdef NO_MOTION_OUTPUT
|
||||
// a pass without the velocity target: the writes go nowhere
|
||||
vec4 out_motion;
|
||||
#else
|
||||
layout(location = 1) out vec4 out_motion;
|
||||
#endif
|
||||
|
||||
#include "light_common.glsl"
|
||||
#include "apply_fog.glsl"
|
||||
#include "tonemapping.glsl"
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 tex_color = texture(diffuse, f_coord);
|
||||
|
||||
bool alphatestfail = ( opacity >= 0.0 ? (tex_color.a < opacity) : (tex_color.a >= -opacity) );
|
||||
if(alphatestfail)
|
||||
discard;
|
||||
// if (tex_color.a < opacity)
|
||||
// discard;
|
||||
|
||||
vec3 fragcolor = ambient;
|
||||
vec3 fragnormal = normalize(f_normal);
|
||||
float reflectivity = param[1].z;
|
||||
float specularity = texture(specgloss, f_coord).r;
|
||||
glossiness = texture(specgloss, f_coord).g * abs(param[1].w);
|
||||
metalic = texture(specgloss, f_coord).b;
|
||||
|
||||
fragcolor = apply_lights(fragcolor, fragnormal, tex_color.rgb, reflectivity, specularity, shadow_tone);
|
||||
vec4 color = vec4(apply_fog(fragcolor), tex_color.a * alpha_mult);
|
||||
/*
|
||||
float distance = dot(f_pos.xyz, f_pos.xyz);
|
||||
if( distance <= cascade_end.x ) { color.r += 0.25; }
|
||||
else if( distance <= cascade_end.y ) { color.g += 0.25; }
|
||||
else if( distance <= cascade_end.z ) { color.b += 0.25; }
|
||||
*/
|
||||
if (POSTFX_ENABLED)
|
||||
{
|
||||
out_color = color;
|
||||
}
|
||||
else
|
||||
{
|
||||
out_color = tonemap(color);
|
||||
}
|
||||
|
||||
if (MOTIONBLUR_ENABLED)
|
||||
{
|
||||
vec2 a = (f_clip_future_pos.xy / f_clip_future_pos.w) * 0.5 + 0.5;;
|
||||
vec2 b = (f_clip_pos.xy / f_clip_pos.w) * 0.5 + 0.5;;
|
||||
|
||||
out_motion = vec4(a - b, 0.0f, tex_color.a * alpha_mult);
|
||||
}
|
||||
}
|
||||
89
shaders/vk14/mat_detail_normalmap.frag
Normal file
89
shaders/vk14/mat_detail_normalmap.frag
Normal file
@@ -0,0 +1,89 @@
|
||||
#version 460 core
|
||||
#define STAGE_FRAGMENT 1
|
||||
#include "common.glsl"
|
||||
layout(location = 0) in vec3 f_normal;
|
||||
layout(location = 2) in vec2 f_coord;
|
||||
layout(location = 3) in vec4 f_pos;
|
||||
layout(location = 8) in mat3 f_tbn;
|
||||
|
||||
layout(location = 4) in vec4 f_clip_pos;
|
||||
layout(location = 5) in vec4 f_clip_future_pos;
|
||||
|
||||
|
||||
layout(location = 0) out vec4 out_color;
|
||||
#ifdef NO_MOTION_OUTPUT
|
||||
// a pass without the velocity target: the writes go nowhere
|
||||
vec4 out_motion;
|
||||
#else
|
||||
layout(location = 1) out vec4 out_motion;
|
||||
#endif
|
||||
|
||||
#pragma param(color, 0, 0, 4, diffuse)
|
||||
#pragma param(diffuse, 1, 0, 1, diffuse)
|
||||
#pragma param(specular, 1, 1, 1, specular)
|
||||
#pragma param(reflection, 1, 2, 1, one)
|
||||
#pragma param(glossiness, 1, 3, 1, glossiness)
|
||||
#pragma param(detail_scale, 2, 0, 1, one)
|
||||
#pragma param(detail_height_scale, 2, 1, 1, one)
|
||||
|
||||
#pragma texture(diffuse, 0, sRGB_A)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 0) uniform sampler2D diffuse;
|
||||
|
||||
#pragma texture(normalmap, 1, RGBA)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 1) uniform sampler2D normalmap;
|
||||
|
||||
#pragma texture(detailnormalmap, 2, RGBA)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 2) uniform sampler2D detailnormalmap;
|
||||
|
||||
#define NORMALMAP
|
||||
#include "light_common.glsl"
|
||||
#include "apply_fog.glsl"
|
||||
#include "tonemapping.glsl"
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 tex_color = texture(diffuse, f_coord);
|
||||
|
||||
bool alphatestfail = ( opacity >= 0.0 ? (tex_color.a < opacity) : (tex_color.a >= -opacity) );
|
||||
if(alphatestfail)
|
||||
discard;
|
||||
|
||||
vec3 fragcolor = ambient;
|
||||
|
||||
vec4 normal_map = texture(normalmap, f_coord);
|
||||
vec4 detailnormal_map = texture(detailnormalmap, f_coord * param[2].x);
|
||||
vec3 normal;
|
||||
vec3 normaldetail;
|
||||
|
||||
normaldetail.xy = detailnormal_map.rg* 2.0 - 1.0;
|
||||
normaldetail.z = sqrt(1.0 - clamp((dot(normaldetail.xy, normaldetail.xy)), 0.0, 1.0));
|
||||
normaldetail.xyz = normaldetail.xyz * param[2].y;
|
||||
normal.xy = normal_map.rg* 2.0 - 1.0;
|
||||
normal.z = sqrt(1.0 - clamp((dot(normal.xy, normal.xy)), 0.0, 1.0));
|
||||
|
||||
vec3 fragnormal = normalize(f_tbn * normalize(vec3(normal.xy + normaldetail.xy, normal.z)));
|
||||
|
||||
|
||||
float reflblend = (normal_map.a + detailnormal_map.a);
|
||||
float reflectivity = reflblend > 1.0 ? param[1].z * 1.0 : param[1].z * reflblend;
|
||||
float specularity = (tex_color.r + tex_color.g + tex_color.b) * 0.5;
|
||||
legacy_gloss();
|
||||
|
||||
fragcolor = apply_lights(fragcolor, fragnormal, tex_color.rgb, reflectivity, specularity, shadow_tone);
|
||||
vec4 color = vec4(apply_fog(fragcolor), tex_color.a * alpha_mult);
|
||||
if (POSTFX_ENABLED)
|
||||
{
|
||||
out_color = color;
|
||||
}
|
||||
else
|
||||
{
|
||||
out_color = tonemap(color);
|
||||
}
|
||||
if (MOTIONBLUR_ENABLED)
|
||||
{
|
||||
vec2 a = (f_clip_future_pos.xy / f_clip_future_pos.w) * 0.5 + 0.5;;
|
||||
vec2 b = (f_clip_pos.xy / f_clip_pos.w) * 0.5 + 0.5;;
|
||||
|
||||
out_motion = vec4(a - b, 0.0f, 0.0f);
|
||||
}
|
||||
}
|
||||
96
shaders/vk14/mat_detail_normalmap_specgloss.frag
Normal file
96
shaders/vk14/mat_detail_normalmap_specgloss.frag
Normal file
@@ -0,0 +1,96 @@
|
||||
#version 460 core
|
||||
#define STAGE_FRAGMENT 1
|
||||
#include "common.glsl"
|
||||
layout(location = 0) in vec3 f_normal;
|
||||
layout(location = 2) in vec2 f_coord;
|
||||
layout(location = 3) in vec4 f_pos;
|
||||
layout(location = 8) in mat3 f_tbn;
|
||||
|
||||
layout(location = 4) in vec4 f_clip_pos;
|
||||
layout(location = 5) in vec4 f_clip_future_pos;
|
||||
|
||||
|
||||
layout(location = 0) out vec4 out_color;
|
||||
#ifdef NO_MOTION_OUTPUT
|
||||
// a pass without the velocity target: the writes go nowhere
|
||||
vec4 out_motion;
|
||||
#else
|
||||
layout(location = 1) out vec4 out_motion;
|
||||
#endif
|
||||
|
||||
#pragma param(color, 0, 0, 4, diffuse)
|
||||
#pragma param(diffuse, 1, 0, 1, diffuse)
|
||||
#pragma param(specular, 1, 1, 1, specular)
|
||||
#pragma param(reflection, 1, 2, 1, one)
|
||||
#pragma param(glossiness, 1, 3, 1, glossiness)
|
||||
#pragma param(detail_scale, 2, 0, 1, one)
|
||||
#pragma param(detail_height_scale, 2, 1, 1, one)
|
||||
|
||||
#pragma texture(diffuse, 0, sRGB_A)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 0) uniform sampler2D diffuse;
|
||||
|
||||
#pragma texture(normalmap, 1, RGBA)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 1) uniform sampler2D normalmap;
|
||||
|
||||
#pragma texture(detailnormalmap, 2, RGBA)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 2) uniform sampler2D detailnormalmap;
|
||||
|
||||
#pragma texture(specgloss, 3, RGBA)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 3) uniform sampler2D specgloss;
|
||||
|
||||
#define NORMALMAP
|
||||
#include "light_common.glsl"
|
||||
#include "apply_fog.glsl"
|
||||
#include "tonemapping.glsl"
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 tex_color = texture(diffuse, f_coord);
|
||||
|
||||
bool alphatestfail = ( opacity >= 0.0 ? (tex_color.a < opacity) : (tex_color.a >= -opacity) );
|
||||
if(alphatestfail)
|
||||
discard;
|
||||
// if (tex_color.a < opacity)
|
||||
// discard;
|
||||
|
||||
vec3 fragcolor = ambient;
|
||||
|
||||
vec4 normal_map = texture(normalmap, f_coord);
|
||||
vec4 detailnormal_map = texture(detailnormalmap, f_coord * param[2].x);
|
||||
vec4 specgloss_map = texture(specgloss, f_coord);
|
||||
vec3 normal;
|
||||
vec3 normaldetail;
|
||||
|
||||
normaldetail.xy = detailnormal_map.rg* 2.0 - 1.0;
|
||||
normaldetail.z = sqrt(1.0 - clamp((dot(normaldetail.xy, normaldetail.xy)), 0.0, 1.0));
|
||||
normaldetail.xyz = normaldetail.xyz * param[2].y;
|
||||
normal.xy = normal_map.rg* 2.0 - 1.0;
|
||||
normal.z = sqrt(1.0 - clamp((dot(normal.xy, normal.xy)), 0.0, 1.0));
|
||||
|
||||
vec3 fragnormal = normalize(f_tbn * normalize(vec3(normal.xy + normaldetail.xy, normal.z)));
|
||||
|
||||
float reflblend = (normal_map.a + detailnormal_map.a);
|
||||
float reflectivity = reflblend > 1.0 ? param[1].z * 1.0 : param[1].z * reflblend;
|
||||
float specularity = specgloss_map.r;
|
||||
glossiness = specgloss_map.g * abs(param[1].w);
|
||||
metalic = specgloss_map.b;
|
||||
|
||||
|
||||
fragcolor = apply_lights(fragcolor, fragnormal, tex_color.rgb, reflectivity, specularity, shadow_tone);
|
||||
vec4 color = vec4(apply_fog(fragcolor), tex_color.a * alpha_mult);
|
||||
if (POSTFX_ENABLED)
|
||||
{
|
||||
out_color = color;
|
||||
}
|
||||
else
|
||||
{
|
||||
out_color = tonemap(color);
|
||||
}
|
||||
if (MOTIONBLUR_ENABLED)
|
||||
{
|
||||
vec2 a = (f_clip_future_pos.xy / f_clip_future_pos.w) * 0.5 + 0.5;;
|
||||
vec2 b = (f_clip_pos.xy / f_clip_pos.w) * 0.5 + 0.5;;
|
||||
|
||||
out_motion = vec4(a - b, 0.0f, 0.0f);
|
||||
}
|
||||
}
|
||||
152
shaders/vk14/mat_detail_parallax.frag
Normal file
152
shaders/vk14/mat_detail_parallax.frag
Normal file
@@ -0,0 +1,152 @@
|
||||
#version 460 core
|
||||
#define STAGE_FRAGMENT 1
|
||||
#include "common.glsl"
|
||||
layout(location = 0) in vec3 f_normal;
|
||||
layout(location = 2) in vec2 f_coord;
|
||||
layout(location = 3) in vec4 f_pos;
|
||||
layout(location = 8) in mat3 f_tbn; //tangent matrix nietransponowany; mnożyć przez f_tbn dla TangentLightPos; TangentViewPos; TangentFragPos;
|
||||
layout(location = 4) in vec4 f_clip_pos;
|
||||
layout(location = 5) in vec4 f_clip_future_pos;
|
||||
layout(location = 6) in vec3 TangentFragPos;
|
||||
|
||||
|
||||
layout(location = 0) out vec4 out_color;
|
||||
#ifdef NO_MOTION_OUTPUT
|
||||
// a pass without the velocity target: the writes go nowhere
|
||||
vec4 out_motion;
|
||||
#else
|
||||
layout(location = 1) out vec4 out_motion;
|
||||
#endif
|
||||
|
||||
|
||||
#pragma param(color, 0, 0, 4, diffuse)
|
||||
#pragma param(diffuse, 1, 0, 1, diffuse)
|
||||
#pragma param(specular, 1, 1, 1, specular)
|
||||
#pragma param(reflection, 1, 2, 1, one)
|
||||
#pragma param(glossiness, 1, 3, 1, glossiness)
|
||||
#pragma param(detail_scale, 2, 0, 1, one)
|
||||
#pragma param(detail_height_scale, 2, 1, 1, one)
|
||||
#pragma param(height_scale, 2, 2, 1, zero)
|
||||
#pragma param(height_offset, 2, 3, 1, zero)
|
||||
|
||||
#pragma texture(diffuse, 0, sRGB_A)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 0) uniform sampler2D diffuse;
|
||||
|
||||
#pragma texture(normalmap, 1, RGBA)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 1) uniform sampler2D normalmap;
|
||||
|
||||
#pragma texture(detailnormalmap, 2, RGBA)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 2) uniform sampler2D detailnormalmap;
|
||||
|
||||
#define PARALLAX
|
||||
// param[2].w is the height offset, not the weathering
|
||||
#define NO_WEATHERING
|
||||
#include "light_common.glsl"
|
||||
#include "apply_fog.glsl"
|
||||
#include "tonemapping.glsl"
|
||||
|
||||
vec2 ParallaxMapping(vec2 f_coord, vec3 viewDir);
|
||||
|
||||
void main()
|
||||
{
|
||||
//parallax mapping
|
||||
vec3 viewDir = normalize(-TangentFragPos); //tangent view pos - tangent frag pos
|
||||
vec2 f_coord_p = ParallaxMapping(f_coord, viewDir);
|
||||
vec4 normal_map = texture(normalmap, f_coord_p);
|
||||
vec4 detailnormal_map = texture(detailnormalmap, f_coord_p * param[2].x);
|
||||
vec4 tex_color = texture(diffuse, f_coord_p);
|
||||
|
||||
bool alphatestfail = ( opacity >= 0.0 ? (tex_color.a < opacity) : (tex_color.a >= -opacity) );
|
||||
if(alphatestfail)
|
||||
discard;
|
||||
// if (tex_color.a < opacity)
|
||||
// discard;
|
||||
|
||||
vec3 fragcolor = ambient;
|
||||
|
||||
vec3 normal;
|
||||
vec3 normaldetail;
|
||||
|
||||
normaldetail.xy = detailnormal_map.rg* 2.0 - 1.0;
|
||||
normaldetail.z = sqrt(1.0 - clamp((dot(normaldetail.xy, normaldetail.xy)), 0.0, 1.0));
|
||||
normaldetail.xyz = normaldetail.xyz * param[2].y;
|
||||
normal.xy = normal_map.rg* 2.0 - 1.0;
|
||||
normal.z = sqrt(1.0 - clamp((dot(normal.xy, normal.xy)), 0.0, 1.0));
|
||||
|
||||
vec3 fragnormal = normalize(f_tbn * normalize(vec3(normal.xy + normaldetail.xy, normal.z)));
|
||||
float reflectivity = param[1].z * normal_map.a;
|
||||
float specularity = (tex_color.r + tex_color.g + tex_color.b) * 0.5;
|
||||
legacy_gloss();
|
||||
|
||||
fragcolor = apply_lights(fragcolor, fragnormal, tex_color.rgb, reflectivity, specularity, shadow_tone);
|
||||
|
||||
vec4 color = vec4(apply_fog(fragcolor), tex_color.a * alpha_mult);
|
||||
if (POSTFX_ENABLED)
|
||||
{
|
||||
out_color = color;
|
||||
}
|
||||
else
|
||||
{
|
||||
out_color = tonemap(color);
|
||||
}
|
||||
if (MOTIONBLUR_ENABLED)
|
||||
{
|
||||
vec2 a = (f_clip_future_pos.xy / f_clip_future_pos.w) * 0.5 + 0.5;;
|
||||
vec2 b = (f_clip_pos.xy / f_clip_pos.w) * 0.5 + 0.5;;
|
||||
|
||||
out_motion = vec4(a - b, 0.0f, 0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
vec2 ParallaxMapping(vec2 f_coord, vec3 viewDir)
|
||||
{
|
||||
float pos_len = length(f_pos.xyz);
|
||||
// gradients of the coordinates taken here: inside the loop the fragments of a quad don't go the same way
|
||||
vec2 dcoorddx = dFdx(f_coord);
|
||||
vec2 dcoorddy = dFdy(f_coord);
|
||||
|
||||
if (pos_len > 100.0) {
|
||||
return f_coord;
|
||||
}
|
||||
// the shift fades out before the distance it stops at, so it doesn't switch off at once there
|
||||
float fade = 1.0 - smoothstep(80.0, 100.0, pos_len);
|
||||
|
||||
if (EXTRAEFFECTS_ENABLED)
|
||||
{
|
||||
const float minLayers = 8.0;
|
||||
const float maxLayers = 32.0;
|
||||
float LayersWeight = pos_len / 20.0;
|
||||
vec2 currentTexCoords = f_coord;
|
||||
float currentDepthMapValue = textureGrad(normalmap, currentTexCoords, dcoorddx, dcoorddy).b;
|
||||
LayersWeight = min(abs(dot(vec3(0.0, 0.0, 1.0), viewDir)),LayersWeight);
|
||||
float numLayers = mix(maxLayers, minLayers, clamp(LayersWeight, 0.0, 1.0)); // number of depth layers
|
||||
float layerDepth = 1.0 / numLayers; // calculate the size of each layer
|
||||
float currentLayerDepth = 0.0; // depth of current layer
|
||||
vec2 P = viewDir.xy * param[2].z * fade; // the amount to shift the texture coordinates per layer (from vector P)
|
||||
vec2 deltaTexCoords = P / numLayers;
|
||||
|
||||
|
||||
while(currentLayerDepth < currentDepthMapValue)
|
||||
{
|
||||
currentTexCoords -= deltaTexCoords; // shift texture coordinates along direction of P
|
||||
currentDepthMapValue = textureGrad(normalmap, currentTexCoords, dcoorddx, dcoorddy).b; // get depthmap value at current texture coordinates
|
||||
currentLayerDepth += layerDepth; // get depth of next layer
|
||||
}
|
||||
|
||||
vec2 prevTexCoords = currentTexCoords + deltaTexCoords; // get texture coordinates before collision (reverse operations)
|
||||
|
||||
float afterDepth = currentDepthMapValue - currentLayerDepth; // get depth after and before collision for linear interpolation
|
||||
float beforeDepth = textureGrad(normalmap, prevTexCoords, dcoorddx, dcoorddy).b - currentLayerDepth + layerDepth;
|
||||
|
||||
float weight = afterDepth / (afterDepth - beforeDepth); // interpolation of texture coordinates
|
||||
vec2 finalTexCoords = prevTexCoords * weight + currentTexCoords * (1.0 - weight);
|
||||
|
||||
return finalTexCoords;
|
||||
}
|
||||
else
|
||||
{
|
||||
float height = texture(normalmap, f_coord).b;
|
||||
vec2 p = viewDir.xy / viewDir.z * (height * (param[2].z - param[2].w) * 0.2) * fade;
|
||||
return f_coord - p;
|
||||
}
|
||||
}
|
||||
158
shaders/vk14/mat_detail_parallax_specgloss.frag
Normal file
158
shaders/vk14/mat_detail_parallax_specgloss.frag
Normal file
@@ -0,0 +1,158 @@
|
||||
#version 460 core
|
||||
#define STAGE_FRAGMENT 1
|
||||
#include "common.glsl"
|
||||
layout(location = 0) in vec3 f_normal;
|
||||
layout(location = 2) in vec2 f_coord;
|
||||
layout(location = 3) in vec4 f_pos;
|
||||
layout(location = 8) in mat3 f_tbn; //tangent matrix nietransponowany; mnożyć przez f_tbn dla TangentLightPos; TangentViewPos; TangentFragPos;
|
||||
layout(location = 4) in vec4 f_clip_pos;
|
||||
layout(location = 5) in vec4 f_clip_future_pos;
|
||||
layout(location = 6) in vec3 TangentFragPos;
|
||||
|
||||
|
||||
layout(location = 0) out vec4 out_color;
|
||||
#ifdef NO_MOTION_OUTPUT
|
||||
// a pass without the velocity target: the writes go nowhere
|
||||
vec4 out_motion;
|
||||
#else
|
||||
layout(location = 1) out vec4 out_motion;
|
||||
#endif
|
||||
|
||||
|
||||
#pragma param(color, 0, 0, 4, diffuse)
|
||||
#pragma param(diffuse, 1, 0, 1, diffuse)
|
||||
#pragma param(specular, 1, 1, 1, specular)
|
||||
#pragma param(reflection, 1, 2, 1, one)
|
||||
#pragma param(glossiness, 1, 3, 1, glossiness)
|
||||
#pragma param(detail_scale, 2, 0, 1, one)
|
||||
#pragma param(detail_height_scale, 2, 1, 1, one)
|
||||
#pragma param(height_scale, 2, 2, 1, zero)
|
||||
#pragma param(height_offset, 2, 3, 1, zero)
|
||||
|
||||
#pragma texture(diffuse, 0, sRGB_A)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 0) uniform sampler2D diffuse;
|
||||
|
||||
#pragma texture(normalmap, 1, RGBA)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 1) uniform sampler2D normalmap;
|
||||
|
||||
#pragma texture(specgloss, 2, RGBA)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 2) uniform sampler2D specgloss;
|
||||
|
||||
#pragma texture(detailnormalmap, 3, RGBA)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 3) uniform sampler2D detailnormalmap;
|
||||
|
||||
|
||||
#define PARALLAX
|
||||
// param[2].w is the height offset, not the weathering
|
||||
#define NO_WEATHERING
|
||||
#include "light_common.glsl"
|
||||
#include "apply_fog.glsl"
|
||||
#include "tonemapping.glsl"
|
||||
|
||||
vec2 ParallaxMapping(vec2 f_coord, vec3 viewDir);
|
||||
|
||||
void main()
|
||||
{
|
||||
//parallax mapping
|
||||
vec3 viewDir = normalize(vec3(0.0f, 0.0f, 0.0f) - TangentFragPos); //tangent view pos - tangent frag pos
|
||||
vec2 f_coord_p = ParallaxMapping(f_coord, viewDir);
|
||||
|
||||
vec4 normal_map = texture(normalmap, f_coord_p);
|
||||
vec4 detailnormal_map = texture(detailnormalmap, f_coord_p * param[2].x);
|
||||
vec4 tex_color = texture(diffuse, f_coord_p);
|
||||
vec4 specgloss_map = texture(specgloss, f_coord_p);
|
||||
|
||||
bool alphatestfail = ( opacity >= 0.0 ? (tex_color.a < opacity) : (tex_color.a >= -opacity) );
|
||||
if(alphatestfail)
|
||||
discard;
|
||||
|
||||
vec3 fragcolor = ambient;
|
||||
|
||||
vec3 normal;
|
||||
vec3 normaldetail;
|
||||
|
||||
normaldetail.xy = detailnormal_map.rg* 2.0 - 1.0;
|
||||
normaldetail.z = sqrt(1.0 - clamp((dot(normaldetail.xy, normaldetail.xy)), 0.0, 1.0));
|
||||
normaldetail.xyz = normaldetail.xyz * param[2].y;
|
||||
normal.xy = normal_map.rg* 2.0 - 1.0;
|
||||
normal.z = sqrt(1.0 - clamp((dot(normal.xy, normal.xy)), 0.0, 1.0));
|
||||
|
||||
vec3 fragnormal = normalize(f_tbn * normalize(vec3(normal.xy + normaldetail.xy, normal.z)));
|
||||
float reflectivity = param[1].z * normal_map.a;
|
||||
float specularity = specgloss_map.r;
|
||||
glossiness = specgloss_map.g * abs(param[1].w);
|
||||
metalic = specgloss_map.b;
|
||||
|
||||
fragcolor = apply_lights(fragcolor, fragnormal, tex_color.rgb, reflectivity, specularity, shadow_tone);
|
||||
|
||||
vec4 color = vec4(apply_fog(fragcolor), tex_color.a * alpha_mult);
|
||||
if (POSTFX_ENABLED)
|
||||
{
|
||||
out_color = color;
|
||||
}
|
||||
else
|
||||
{
|
||||
out_color = tonemap(color);
|
||||
}
|
||||
if (MOTIONBLUR_ENABLED)
|
||||
{
|
||||
vec2 a = (f_clip_future_pos.xy / f_clip_future_pos.w) * 0.5 + 0.5;;
|
||||
vec2 b = (f_clip_pos.xy / f_clip_pos.w) * 0.5 + 0.5;;
|
||||
|
||||
out_motion = vec4(a - b, 0.0f, 0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
vec2 ParallaxMapping(vec2 f_coord, vec3 viewDir)
|
||||
{
|
||||
|
||||
float pos_len = length(f_pos.xyz);
|
||||
// gradients of the coordinates taken here: inside the loop the fragments of a quad don't go the same way
|
||||
vec2 dcoorddx = dFdx(f_coord);
|
||||
vec2 dcoorddy = dFdy(f_coord);
|
||||
|
||||
if (pos_len > 100.0) {
|
||||
return f_coord;
|
||||
}
|
||||
// the shift fades out before the distance it stops at, so it doesn't switch off at once there
|
||||
float fade = 1.0 - smoothstep(80.0, 100.0, pos_len);
|
||||
|
||||
if (EXTRAEFFECTS_ENABLED)
|
||||
{
|
||||
const float minLayers = 8.0;
|
||||
const float maxLayers = 32.0;
|
||||
float LayersWeight = pos_len / 20.0;
|
||||
vec2 currentTexCoords = f_coord;
|
||||
float currentDepthMapValue = textureGrad(normalmap, currentTexCoords, dcoorddx, dcoorddy).b;
|
||||
LayersWeight = min(abs(dot(vec3(0.0, 0.0, 1.0), viewDir)),LayersWeight);
|
||||
float numLayers = mix(maxLayers, minLayers, clamp(LayersWeight, 0.0, 1.0)); // number of depth layers
|
||||
float layerDepth = 1.0 / numLayers; // calculate the size of each layer
|
||||
float currentLayerDepth = 0.0; // depth of current layer
|
||||
vec2 P = viewDir.xy * param[2].z * fade; // the amount to shift the texture coordinates per layer (from vector P)
|
||||
vec2 deltaTexCoords = P / numLayers;
|
||||
|
||||
|
||||
while(currentLayerDepth < currentDepthMapValue)
|
||||
{
|
||||
currentTexCoords -= deltaTexCoords; // shift texture coordinates along direction of P
|
||||
currentDepthMapValue = textureGrad(normalmap, currentTexCoords, dcoorddx, dcoorddy).b; // get depthmap value at current texture coordinates
|
||||
currentLayerDepth += layerDepth; // get depth of next layer
|
||||
}
|
||||
|
||||
vec2 prevTexCoords = currentTexCoords + deltaTexCoords; // get texture coordinates before collision (reverse operations)
|
||||
|
||||
float afterDepth = currentDepthMapValue - currentLayerDepth; // get depth after and before collision for linear interpolation
|
||||
float beforeDepth = textureGrad(normalmap, prevTexCoords, dcoorddx, dcoorddy).b - currentLayerDepth + layerDepth;
|
||||
|
||||
float weight = afterDepth / (afterDepth - beforeDepth); // interpolation of texture coordinates
|
||||
vec2 finalTexCoords = prevTexCoords * weight + currentTexCoords * (1.0 - weight);
|
||||
|
||||
return finalTexCoords;
|
||||
}
|
||||
else
|
||||
{
|
||||
float height = texture(normalmap, f_coord).b;
|
||||
vec2 p = viewDir.xy / viewDir.z * (height * (param[2].z - param[2].w) * 0.2) * fade;
|
||||
return f_coord - p;
|
||||
}
|
||||
}
|
||||
29
shaders/vk14/mat_invalid.frag
Normal file
29
shaders/vk14/mat_invalid.frag
Normal file
@@ -0,0 +1,29 @@
|
||||
#version 460 core
|
||||
#define STAGE_FRAGMENT 1
|
||||
#include "common.glsl"
|
||||
#include "tonemapping.glsl"
|
||||
|
||||
layout(location = 0) out vec4 out_color;
|
||||
#ifdef NO_MOTION_OUTPUT
|
||||
// a pass without the velocity target: the writes go nowhere
|
||||
vec4 out_motion;
|
||||
#else
|
||||
layout(location = 1) out vec4 out_motion;
|
||||
#endif
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 color = vec4(1.0, 0.0, 1.0, 1.0);
|
||||
if (POSTFX_ENABLED)
|
||||
{
|
||||
out_color = color;
|
||||
}
|
||||
else
|
||||
{
|
||||
out_color = tonemap(color);
|
||||
}
|
||||
if (MOTIONBLUR_ENABLED)
|
||||
{
|
||||
out_motion = vec4(0.0f);
|
||||
}
|
||||
}
|
||||
76
shaders/vk14/mat_normalmap.frag
Normal file
76
shaders/vk14/mat_normalmap.frag
Normal file
@@ -0,0 +1,76 @@
|
||||
#version 460 core
|
||||
#define STAGE_FRAGMENT 1
|
||||
#include "common.glsl"
|
||||
layout(location = 0) in vec3 f_normal;
|
||||
layout(location = 2) in vec2 f_coord;
|
||||
layout(location = 3) in vec4 f_pos;
|
||||
layout(location = 8) in mat3 f_tbn;
|
||||
|
||||
layout(location = 4) in vec4 f_clip_pos;
|
||||
layout(location = 5) in vec4 f_clip_future_pos;
|
||||
|
||||
|
||||
layout(location = 0) out vec4 out_color;
|
||||
#ifdef NO_MOTION_OUTPUT
|
||||
// a pass without the velocity target: the writes go nowhere
|
||||
vec4 out_motion;
|
||||
#else
|
||||
layout(location = 1) out vec4 out_motion;
|
||||
#endif
|
||||
|
||||
#pragma param(color, 0, 0, 4, diffuse)
|
||||
#pragma param(diffuse, 1, 0, 1, diffuse)
|
||||
#pragma param(specular, 1, 1, 1, specular)
|
||||
#pragma param(reflection, 1, 2, 1, one)
|
||||
#pragma param(glossiness, 1, 3, 1, glossiness)
|
||||
|
||||
#pragma texture(diffuse, 0, sRGB_A)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 0) uniform sampler2D diffuse;
|
||||
|
||||
#pragma texture(normalmap, 1, RGBA)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 1) uniform sampler2D normalmap;
|
||||
|
||||
#define NORMALMAP
|
||||
#include "light_common.glsl"
|
||||
#include "apply_fog.glsl"
|
||||
#include "tonemapping.glsl"
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 tex_color = texture(diffuse, f_coord);
|
||||
|
||||
bool alphatestfail = ( opacity >= 0.0 ? (tex_color.a < opacity) : (tex_color.a >= -opacity) );
|
||||
if(alphatestfail)
|
||||
discard;
|
||||
// if (tex_color.a < opacity)
|
||||
// discard;
|
||||
|
||||
vec3 fragcolor = ambient;
|
||||
|
||||
vec3 normal;
|
||||
normal.xy = (texture(normalmap, f_coord).rg * 2.0 - 1.0);
|
||||
normal.z = sqrt(1.0 - clamp((dot(normal.xy, normal.xy)), 0.0, 1.0));
|
||||
vec3 fragnormal = normalize(f_tbn * normalize(normal.xyz));
|
||||
float reflectivity = param[1].z * texture(normalmap, f_coord).a;
|
||||
float specularity = (tex_color.r + tex_color.g + tex_color.b) * 0.5;
|
||||
legacy_gloss();
|
||||
|
||||
fragcolor = apply_lights(fragcolor, fragnormal, tex_color.rgb, reflectivity, specularity, shadow_tone);
|
||||
|
||||
vec4 color = vec4(apply_fog(fragcolor), tex_color.a * alpha_mult);
|
||||
if (POSTFX_ENABLED)
|
||||
{
|
||||
out_color = color;
|
||||
}
|
||||
else
|
||||
{
|
||||
out_color = tonemap(color);
|
||||
}
|
||||
if (MOTIONBLUR_ENABLED)
|
||||
{
|
||||
vec2 a = (f_clip_future_pos.xy / f_clip_future_pos.w) * 0.5 + 0.5;;
|
||||
vec2 b = (f_clip_pos.xy / f_clip_pos.w) * 0.5 + 0.5;;
|
||||
|
||||
out_motion = vec4(a - b, 0.0f, 0.0f);
|
||||
}
|
||||
}
|
||||
81
shaders/vk14/mat_normalmap_specgloss.frag
Normal file
81
shaders/vk14/mat_normalmap_specgloss.frag
Normal file
@@ -0,0 +1,81 @@
|
||||
#version 460 core
|
||||
#define STAGE_FRAGMENT 1
|
||||
#include "common.glsl"
|
||||
layout(location = 0) in vec3 f_normal;
|
||||
layout(location = 2) in vec2 f_coord;
|
||||
layout(location = 3) in vec4 f_pos;
|
||||
layout(location = 8) in mat3 f_tbn;
|
||||
|
||||
layout(location = 4) in vec4 f_clip_pos;
|
||||
layout(location = 5) in vec4 f_clip_future_pos;
|
||||
|
||||
|
||||
layout(location = 0) out vec4 out_color;
|
||||
#ifdef NO_MOTION_OUTPUT
|
||||
// a pass without the velocity target: the writes go nowhere
|
||||
vec4 out_motion;
|
||||
#else
|
||||
layout(location = 1) out vec4 out_motion;
|
||||
#endif
|
||||
|
||||
#pragma param(color, 0, 0, 4, diffuse)
|
||||
#pragma param(diffuse, 1, 0, 1, diffuse)
|
||||
#pragma param(specular, 1, 1, 1, specular)
|
||||
#pragma param(reflection, 1, 2, 1, one)
|
||||
#pragma param(glossiness, 1, 3, 1, glossiness)
|
||||
|
||||
#pragma texture(diffuse, 0, sRGB_A)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 0) uniform sampler2D diffuse;
|
||||
|
||||
#pragma texture(normalmap, 1, RGBA)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 1) uniform sampler2D normalmap;
|
||||
|
||||
#pragma texture(specgloss, 2, RGBA)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 2) uniform sampler2D specgloss;
|
||||
|
||||
|
||||
#define NORMALMAP
|
||||
#include "light_common.glsl"
|
||||
#include "apply_fog.glsl"
|
||||
#include "tonemapping.glsl"
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 tex_color = texture(diffuse, f_coord);
|
||||
|
||||
bool alphatestfail = ( opacity >= 0.0 ? (tex_color.a < opacity) : (tex_color.a >= -opacity) );
|
||||
if(alphatestfail)
|
||||
discard;
|
||||
// if (tex_color.a < opacity)
|
||||
// discard;
|
||||
|
||||
vec3 fragcolor = ambient;
|
||||
|
||||
vec3 normal;
|
||||
normal.xy = (texture(normalmap, f_coord).rg * 2.0 - 1.0);
|
||||
normal.z = sqrt(1.0 - clamp((dot(normal.xy, normal.xy)), 0.0, 1.0));
|
||||
vec3 fragnormal = normalize(f_tbn * normalize(normal.xyz));
|
||||
float reflectivity = param[1].z * texture(normalmap, f_coord).a;
|
||||
float specularity = texture(specgloss, f_coord).r;
|
||||
glossiness = texture(specgloss, f_coord).g * abs(param[1].w);
|
||||
metalic = texture(specgloss, f_coord).b;
|
||||
|
||||
fragcolor = apply_lights(fragcolor, fragnormal, tex_color.rgb, reflectivity, specularity, shadow_tone);
|
||||
|
||||
vec4 color = vec4(apply_fog(fragcolor), tex_color.a * alpha_mult);
|
||||
if (POSTFX_ENABLED)
|
||||
{
|
||||
out_color = color;
|
||||
}
|
||||
else
|
||||
{
|
||||
out_color = tonemap(color);
|
||||
}
|
||||
if (MOTIONBLUR_ENABLED)
|
||||
{
|
||||
vec2 a = (f_clip_future_pos.xy / f_clip_future_pos.w) * 0.5 + 0.5;;
|
||||
vec2 b = (f_clip_pos.xy / f_clip_pos.w) * 0.5 + 0.5;;
|
||||
|
||||
out_motion = vec4(a - b, 0.0f, 0.0f);
|
||||
}
|
||||
}
|
||||
137
shaders/vk14/mat_parallax.frag
Normal file
137
shaders/vk14/mat_parallax.frag
Normal file
@@ -0,0 +1,137 @@
|
||||
#version 460 core
|
||||
#define STAGE_FRAGMENT 1
|
||||
#include "common.glsl"
|
||||
layout(location = 0) in vec3 f_normal;
|
||||
layout(location = 2) in vec2 f_coord;
|
||||
layout(location = 3) in vec4 f_pos;
|
||||
layout(location = 8) in mat3 f_tbn; //tangent matrix nietransponowany; mnożyć przez f_tbn dla TangentLightPos; TangentViewPos; TangentFragPos;
|
||||
layout(location = 4) in vec4 f_clip_pos;
|
||||
layout(location = 5) in vec4 f_clip_future_pos;
|
||||
layout(location = 6) in vec3 TangentFragPos;
|
||||
|
||||
|
||||
layout(location = 0) out vec4 out_color;
|
||||
#ifdef NO_MOTION_OUTPUT
|
||||
// a pass without the velocity target: the writes go nowhere
|
||||
vec4 out_motion;
|
||||
#else
|
||||
layout(location = 1) out vec4 out_motion;
|
||||
#endif
|
||||
|
||||
#pragma param(color, 0, 0, 4, diffuse)
|
||||
#pragma param(diffuse, 1, 0, 1, diffuse)
|
||||
#pragma param(specular, 1, 1, 1, specular)
|
||||
#pragma param(reflection, 1, 2, 1, one)
|
||||
#pragma param(glossiness, 1, 3, 1, glossiness)
|
||||
#pragma param(height_scale, 2, 1, 1, zero)
|
||||
#pragma param(height_offset, 2, 2, 1, zero)
|
||||
|
||||
#pragma texture(diffuse, 0, sRGB_A)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 0) uniform sampler2D diffuse;
|
||||
|
||||
#pragma texture(normalmap, 1, RGBA)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 1) uniform sampler2D normalmap;
|
||||
|
||||
#define PARALLAX
|
||||
#include "light_common.glsl"
|
||||
#include "apply_fog.glsl"
|
||||
#include "tonemapping.glsl"
|
||||
|
||||
vec2 ParallaxMapping(vec2 f_coord, vec3 viewDir);
|
||||
|
||||
void main()
|
||||
{
|
||||
//parallax mapping
|
||||
vec3 viewDir = normalize(vec3(0.0f, 0.0f, 0.0f) - TangentFragPos); //tangent view pos - tangent frag pos
|
||||
vec2 f_coord_p = ParallaxMapping(f_coord, viewDir);
|
||||
|
||||
vec4 tex_color = texture(diffuse, f_coord_p);
|
||||
|
||||
bool alphatestfail = ( opacity >= 0.0 ? (tex_color.a < opacity) : (tex_color.a >= -opacity) );
|
||||
if(alphatestfail)
|
||||
discard;
|
||||
// if (tex_color.a < opacity)
|
||||
// discard;
|
||||
|
||||
vec3 fragcolor = ambient;
|
||||
|
||||
vec3 normal;
|
||||
normal.xy = (texture(normalmap, f_coord_p).rg * 2.0 - 1.0);
|
||||
normal.z = sqrt(1.0 - clamp((dot(normal.xy, normal.xy)), 0.0, 1.0));
|
||||
vec3 fragnormal = normalize(f_tbn * normalize(normal.xyz));
|
||||
float reflectivity = param[1].z * texture(normalmap, f_coord_p).a;
|
||||
float specularity = (tex_color.r + tex_color.g + tex_color.b) * 0.5;
|
||||
legacy_gloss();
|
||||
|
||||
fragcolor = apply_lights(fragcolor, fragnormal, tex_color.rgb, reflectivity, specularity, shadow_tone);
|
||||
|
||||
vec4 color = vec4(apply_fog(fragcolor), tex_color.a * alpha_mult);
|
||||
if (POSTFX_ENABLED)
|
||||
{
|
||||
out_color = color;
|
||||
}
|
||||
else
|
||||
{
|
||||
out_color = tonemap(color);
|
||||
}
|
||||
if (MOTIONBLUR_ENABLED)
|
||||
{
|
||||
vec2 a = (f_clip_future_pos.xy / f_clip_future_pos.w) * 0.5 + 0.5;;
|
||||
vec2 b = (f_clip_pos.xy / f_clip_pos.w) * 0.5 + 0.5;;
|
||||
|
||||
out_motion = vec4(a - b, 0.0f, 0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
vec2 ParallaxMapping(vec2 f_coord, vec3 viewDir)
|
||||
{
|
||||
float pos_len = length(f_pos.xyz);
|
||||
// gradients of the coordinates taken here: inside the loop the fragments of a quad don't go the same way
|
||||
vec2 dcoorddx = dFdx(f_coord);
|
||||
vec2 dcoorddy = dFdy(f_coord);
|
||||
|
||||
if (pos_len > 100.0) {
|
||||
return f_coord;
|
||||
}
|
||||
// the shift fades out before the distance it stops at, so it doesn't switch off at once there
|
||||
float fade = 1.0 - smoothstep(80.0, 100.0, pos_len);
|
||||
|
||||
if (EXTRAEFFECTS_ENABLED)
|
||||
{
|
||||
const float minLayers = 8.0;
|
||||
const float maxLayers = 32.0;
|
||||
float LayersWeight = pos_len / 20.0;
|
||||
vec2 currentTexCoords = f_coord;
|
||||
float currentDepthMapValue = textureGrad(normalmap, currentTexCoords, dcoorddx, dcoorddy).b;
|
||||
LayersWeight = min(abs(dot(vec3(0.0, 0.0, 1.0), viewDir)),LayersWeight);
|
||||
float numLayers = mix(maxLayers, minLayers, clamp(LayersWeight, 0.0, 1.0)); // number of depth layers
|
||||
float layerDepth = 1.0 / numLayers; // calculate the size of each layer
|
||||
float currentLayerDepth = 0.0; // depth of current layer
|
||||
vec2 P = viewDir.xy * param[2].y * fade; // the amount to shift the texture coordinates per layer (from vector P)
|
||||
vec2 deltaTexCoords = P / numLayers;
|
||||
|
||||
|
||||
while(currentLayerDepth < currentDepthMapValue)
|
||||
{
|
||||
currentTexCoords -= deltaTexCoords; // shift texture coordinates along direction of P
|
||||
currentDepthMapValue = textureGrad(normalmap, currentTexCoords, dcoorddx, dcoorddy).b; // get depthmap value at current texture coordinates
|
||||
currentLayerDepth += layerDepth; // get depth of next layer
|
||||
}
|
||||
|
||||
vec2 prevTexCoords = currentTexCoords + deltaTexCoords; // get texture coordinates before collision (reverse operations)
|
||||
|
||||
float afterDepth = currentDepthMapValue - currentLayerDepth; // get depth after and before collision for linear interpolation
|
||||
float beforeDepth = textureGrad(normalmap, prevTexCoords, dcoorddx, dcoorddy).b - currentLayerDepth + layerDepth;
|
||||
|
||||
float weight = afterDepth / (afterDepth - beforeDepth); // interpolation of texture coordinates
|
||||
vec2 finalTexCoords = prevTexCoords * weight + currentTexCoords * (1.0 - weight);
|
||||
|
||||
return finalTexCoords;
|
||||
}
|
||||
else
|
||||
{
|
||||
float height = texture(normalmap, f_coord).b;
|
||||
vec2 p = viewDir.xy / viewDir.z * (height * (param[2].y - param[2].z) * 0.2) * fade;
|
||||
return f_coord - p;
|
||||
}
|
||||
}
|
||||
142
shaders/vk14/mat_parallax_specgloss.frag
Normal file
142
shaders/vk14/mat_parallax_specgloss.frag
Normal file
@@ -0,0 +1,142 @@
|
||||
#version 460 core
|
||||
#define STAGE_FRAGMENT 1
|
||||
#include "common.glsl"
|
||||
layout(location = 0) in vec3 f_normal;
|
||||
layout(location = 2) in vec2 f_coord;
|
||||
layout(location = 3) in vec4 f_pos;
|
||||
layout(location = 8) in mat3 f_tbn; //tangent matrix nietransponowany; mnożyć przez f_tbn dla TangentLightPos; TangentViewPos; TangentFragPos;
|
||||
layout(location = 4) in vec4 f_clip_pos;
|
||||
layout(location = 5) in vec4 f_clip_future_pos;
|
||||
layout(location = 6) in vec3 TangentFragPos;
|
||||
|
||||
|
||||
layout(location = 0) out vec4 out_color;
|
||||
#ifdef NO_MOTION_OUTPUT
|
||||
// a pass without the velocity target: the writes go nowhere
|
||||
vec4 out_motion;
|
||||
#else
|
||||
layout(location = 1) out vec4 out_motion;
|
||||
#endif
|
||||
|
||||
#pragma param(color, 0, 0, 4, diffuse)
|
||||
#pragma param(diffuse, 1, 0, 1, diffuse)
|
||||
#pragma param(specular, 1, 1, 1, specular)
|
||||
#pragma param(reflection, 1, 2, 1, one)
|
||||
#pragma param(glossiness, 1, 3, 1, glossiness)
|
||||
#pragma param(height_scale, 2, 1, 1, zero)
|
||||
#pragma param(height_offset, 2, 2, 1, zero)
|
||||
|
||||
#pragma texture(diffuse, 0, sRGB_A)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 0) uniform sampler2D diffuse;
|
||||
|
||||
#pragma texture(normalmap, 1, RGBA)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 1) uniform sampler2D normalmap;
|
||||
|
||||
#pragma texture(specgloss, 2, RGBA)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 2) uniform sampler2D specgloss;
|
||||
|
||||
|
||||
#define PARALLAX
|
||||
#include "light_common.glsl"
|
||||
#include "apply_fog.glsl"
|
||||
#include "tonemapping.glsl"
|
||||
|
||||
vec2 ParallaxMapping(vec2 f_coord, vec3 viewDir);
|
||||
|
||||
void main()
|
||||
{
|
||||
//parallax mapping
|
||||
vec3 viewDir = normalize(vec3(0.0f, 0.0f, 0.0f) - TangentFragPos); //tangent view pos - tangent frag pos
|
||||
vec2 f_coord_p = ParallaxMapping(f_coord, viewDir);
|
||||
|
||||
vec4 tex_color = texture(diffuse, f_coord_p);
|
||||
|
||||
bool alphatestfail = ( opacity >= 0.0 ? (tex_color.a < opacity) : (tex_color.a >= -opacity) );
|
||||
if(alphatestfail)
|
||||
discard;
|
||||
// if (tex_color.a < opacity)
|
||||
// discard;
|
||||
|
||||
vec3 fragcolor = ambient;
|
||||
|
||||
vec3 normal;
|
||||
normal.xy = (texture(normalmap, f_coord_p).rg * 2.0 - 1.0);
|
||||
normal.z = sqrt(1.0 - clamp((dot(normal.xy, normal.xy)), 0.0, 1.0));
|
||||
vec3 fragnormal = normalize(f_tbn * normalize(normal.xyz));
|
||||
float reflectivity = param[1].z * texture(normalmap, f_coord_p).a;
|
||||
float specularity = texture(specgloss, f_coord_p).r;
|
||||
glossiness = texture(specgloss, f_coord_p).g * abs(param[1].w);
|
||||
metalic = texture(specgloss, f_coord_p).b;
|
||||
|
||||
fragcolor = apply_lights(fragcolor, fragnormal, tex_color.rgb, reflectivity, specularity, shadow_tone);
|
||||
|
||||
vec4 color = vec4(apply_fog(fragcolor), tex_color.a * alpha_mult);
|
||||
if (POSTFX_ENABLED)
|
||||
{
|
||||
out_color = color;
|
||||
}
|
||||
else
|
||||
{
|
||||
out_color = tonemap(color);
|
||||
}
|
||||
if (MOTIONBLUR_ENABLED)
|
||||
{
|
||||
vec2 a = (f_clip_future_pos.xy / f_clip_future_pos.w) * 0.5 + 0.5;;
|
||||
vec2 b = (f_clip_pos.xy / f_clip_pos.w) * 0.5 + 0.5;;
|
||||
|
||||
out_motion = vec4(a - b, 0.0f, 0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
vec2 ParallaxMapping(vec2 f_coord, vec3 viewDir)
|
||||
{
|
||||
float pos_len = length(f_pos.xyz);
|
||||
// gradients of the coordinates taken here: inside the loop the fragments of a quad don't go the same way
|
||||
vec2 dcoorddx = dFdx(f_coord);
|
||||
vec2 dcoorddy = dFdy(f_coord);
|
||||
|
||||
if (pos_len > 100.0) {
|
||||
return f_coord;
|
||||
}
|
||||
// the shift fades out before the distance it stops at, so it doesn't switch off at once there
|
||||
float fade = 1.0 - smoothstep(80.0, 100.0, pos_len);
|
||||
|
||||
if (EXTRAEFFECTS_ENABLED)
|
||||
{
|
||||
const float minLayers = 8.0;
|
||||
const float maxLayers = 32.0;
|
||||
float LayersWeight = pos_len / 20.0;
|
||||
vec2 currentTexCoords = f_coord;
|
||||
float currentDepthMapValue = textureGrad(normalmap, currentTexCoords, dcoorddx, dcoorddy).b;
|
||||
LayersWeight = min(abs(dot(vec3(0.0, 0.0, 1.0), viewDir)),LayersWeight);
|
||||
float numLayers = mix(maxLayers, minLayers, clamp(LayersWeight, 0.0, 1.0)); // number of depth layers
|
||||
float layerDepth = 1.0 / numLayers; // calculate the size of each layer
|
||||
float currentLayerDepth = 0.0; // depth of current layer
|
||||
vec2 P = viewDir.xy * param[2].y * fade; // the amount to shift the texture coordinates per layer (from vector P)
|
||||
vec2 deltaTexCoords = P / numLayers;
|
||||
|
||||
|
||||
while(currentLayerDepth < currentDepthMapValue)
|
||||
{
|
||||
currentTexCoords -= deltaTexCoords; // shift texture coordinates along direction of P
|
||||
currentDepthMapValue = textureGrad(normalmap, currentTexCoords, dcoorddx, dcoorddy).b; // get depthmap value at current texture coordinates
|
||||
currentLayerDepth += layerDepth; // get depth of next layer
|
||||
}
|
||||
|
||||
vec2 prevTexCoords = currentTexCoords + deltaTexCoords; // get texture coordinates before collision (reverse operations)
|
||||
|
||||
float afterDepth = currentDepthMapValue - currentLayerDepth; // get depth after and before collision for linear interpolation
|
||||
float beforeDepth = textureGrad(normalmap, prevTexCoords, dcoorddx, dcoorddy).b - currentLayerDepth + layerDepth;
|
||||
|
||||
float weight = afterDepth / (afterDepth - beforeDepth); // interpolation of texture coordinates
|
||||
vec2 finalTexCoords = prevTexCoords * weight + currentTexCoords * (1.0 - weight);
|
||||
|
||||
return finalTexCoords;
|
||||
}
|
||||
else
|
||||
{
|
||||
float height = texture(normalmap, f_coord).b;
|
||||
vec2 p = viewDir.xy / viewDir.z * (height * (param[2].y - param[2].z) * 0.2) * fade;
|
||||
return f_coord - p;
|
||||
}
|
||||
}
|
||||
216
shaders/vk14/mat_rain_windscreen.frag
Normal file
216
shaders/vk14/mat_rain_windscreen.frag
Normal file
@@ -0,0 +1,216 @@
|
||||
#version 460 core
|
||||
#define STAGE_FRAGMENT 1
|
||||
#include "common.glsl"
|
||||
// Windshield rain effects
|
||||
// by @lcddisplay; wiper movement @MichauSto
|
||||
|
||||
layout(location = 0) in vec3 f_normal;
|
||||
layout(location = 2) in vec2 f_coord;
|
||||
layout(location = 3) in vec4 f_pos;
|
||||
|
||||
layout(location = 0) out vec4 out_color;
|
||||
|
||||
#ifdef NO_MOTION_OUTPUT
|
||||
// a pass without the velocity target: the writes go nowhere
|
||||
vec4 out_motion;
|
||||
#else
|
||||
layout(location = 1) out vec4 out_motion;
|
||||
#endif
|
||||
|
||||
#pragma texture(diffuse, 0, sRGB_A)
|
||||
#pragma texture(raindropsatlas, 1, sRGB_A)
|
||||
#pragma texture(wipermask, 2, sRGB_A)
|
||||
#pragma param(color, 0, 0, 4, diffuse)
|
||||
#pragma param(diffuse, 1, 0, 1, diffuse)
|
||||
#pragma param(specular, 1, 1, 1, specular)
|
||||
#pragma param(reflection, 1, 2, 1, zero)
|
||||
#pragma param(glossiness, 1, 3, 1, glossiness)
|
||||
#pragma param(raindrop_grid_size, 2, 0, 1, one)
|
||||
|
||||
#include "light_common.glsl"
|
||||
#include "apply_fog.glsl"
|
||||
#include "tonemapping.glsl"
|
||||
#include "random.glsl"
|
||||
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 0) uniform sampler2D diffuse;
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 1) uniform sampler2D raindropsatlas;
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 2) uniform sampler2D wipermask;
|
||||
|
||||
const float specular_intensity = 1.0;
|
||||
const float wobble_strength = 0.002;
|
||||
const float wobble_speed = 30.0;
|
||||
|
||||
vec4 getDropTex(float choice, vec2 uv) {
|
||||
vec2 offset;
|
||||
if (choice < 0.25) offset = vec2(0.0, 0.0);
|
||||
else if (choice < 0.5) offset = vec2(0.5, 0.0);
|
||||
else if (choice < 0.75) offset = vec2(0.0, 0.5);
|
||||
else offset = vec2(0.5, 0.5);
|
||||
return texture(raindropsatlas, offset + uv * 0.5);
|
||||
}
|
||||
|
||||
float GetMixFactor(in vec2 co, out float side);
|
||||
|
||||
void main() {
|
||||
vec4 tex_color = texture(diffuse, f_coord);
|
||||
if (tex_color.a < 0.01) discard;
|
||||
|
||||
vec2 rainCoord = f_coord;
|
||||
float gridSize = ceil(param[2].x);
|
||||
|
||||
const float numDrops = 20000.0;
|
||||
const float cycleDuration = 4.0;
|
||||
|
||||
float squareMin = 0.5 / gridSize;
|
||||
float squareMax = 1.2 / gridSize;
|
||||
|
||||
vec2 cell = floor(rainCoord * gridSize);
|
||||
|
||||
vec3 dropLayer = vec3(0.0);
|
||||
float dropMaskSum = 0.0;
|
||||
|
||||
// Grid of 9 droplets in immediate neighbourhood
|
||||
for (int oy = -1; oy <= 1; oy++) {
|
||||
for (int ox = -1; ox <= 1; ox++) {
|
||||
|
||||
vec2 neighborCell = cell + vec2(ox, oy);
|
||||
vec2 neighborCenter = (neighborCell + .5) / gridSize;
|
||||
|
||||
float side;
|
||||
float mixFactor = GetMixFactor(neighborCenter, side);
|
||||
|
||||
uint seed = Hash(uvec3(neighborCell, side));
|
||||
|
||||
if(mixFactor < RandF(seed)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Show a percentage of droplets given by rain intensity param
|
||||
float activationSeed = RandF(seed);
|
||||
if (activationSeed > rain_params.x)
|
||||
continue; // kropla nieaktywna
|
||||
|
||||
// Randomly modulate droplet center & size
|
||||
vec2 dropCenter = (neighborCell + vec2(RandF(seed), RandF(seed))) / gridSize;
|
||||
float squareSize = mix(squareMin, squareMax, RandF(seed));
|
||||
|
||||
float lifeTime = time + RandF(seed) * cycleDuration;
|
||||
float phase = fract(lifeTime / cycleDuration);
|
||||
float actiwe = clamp(1.0 - phase, 0.0, 1.0);
|
||||
|
||||
// Gravity influence (TODO add vehicle speed & wind here!)
|
||||
float gravityStart = 0.5;
|
||||
float gravityPhase = smoothstep(gravityStart, 1.0, phase);
|
||||
float dropMass = mix(0.3, 1.2, RandF(seed));
|
||||
float gravitySpeed = 0.15 * dropMass;
|
||||
vec2 gravityOffset = vec2(0.0, gravityPhase * gravitySpeed * phase);
|
||||
|
||||
// Random wobble
|
||||
bool hasWobble = (RandF(seed) < 0.10);
|
||||
vec2 wobbleOffset = vec2(0.0);
|
||||
if (hasWobble && gravityPhase > 0.0) {
|
||||
float intensity = sin(time * wobble_speed + RandF(seed) * 100.) * wobble_strength * gravityPhase;
|
||||
wobbleOffset = vec2(intensity, 0.0);
|
||||
}
|
||||
|
||||
vec2 slideOffset = gravityOffset + wobbleOffset;
|
||||
|
||||
// Flatten droplets influenced by gravity
|
||||
float flattenAmount = smoothstep(0.1, 0.5, gravityPhase);
|
||||
float flattenX = mix(1.0, 0.4, flattenAmount);
|
||||
float stretchY = mix(1.0, 1.6, flattenAmount);
|
||||
|
||||
// Droplet local position & mask
|
||||
vec2 diff = (rainCoord + slideOffset) - dropCenter;
|
||||
diff.x *= 1.0 / flattenX;
|
||||
diff.y *= 1.0 / stretchY;
|
||||
float mask = smoothstep(squareSize * 0.5, squareSize * 0.45, max(abs(diff.x), abs(diff.y)));
|
||||
|
||||
if (mask > 0.001) {
|
||||
vec2 localUV = (diff + squareSize * 0.5) / squareSize;
|
||||
float choice = RandF(seed);
|
||||
vec4 dropTex = getDropTex(choice, localUV);
|
||||
float sharpAlpha = smoothstep(0.3, 0.9, dropTex.a);
|
||||
|
||||
float ambLum = clamp(dot(ambient, vec3(0.2126, 0.7152, 0.0722)), 0.0, 1.0);
|
||||
float sunFactor = pow(clamp(ambLum * 6.0, 0.0, 1.0), 0.5);
|
||||
float dynBright = mix(0.0, 1.0, sunFactor);
|
||||
|
||||
float colorLuma = length(dropTex.rgb);
|
||||
float alphaRange = smoothstep(0.1, 0.3, colorLuma);
|
||||
float blackAlpha = mix(0.25, 0.85, alphaRange);
|
||||
|
||||
float sparkle = 0.0;
|
||||
if (hasWobble) {
|
||||
sparkle = pow(abs(sin(f_coord.x * 8.0 + time * 2.0 + RandF(seed) * 6.2831)), 40.0)
|
||||
* mix(0.2, 1.0, sunFactor);
|
||||
}
|
||||
|
||||
vec3 specularColor = vec3(1.0) * specular_intensity * sparkle;
|
||||
vec3 dropLit = dropTex.rgb * dynBright + specularColor * sharpAlpha;
|
||||
|
||||
dropLayer += dropLit * sharpAlpha * actiwe * blackAlpha * mask;
|
||||
dropMaskSum += sharpAlpha * actiwe * blackAlpha * mask;
|
||||
}
|
||||
}
|
||||
}
|
||||
vec3 finalMix = dropLayer;
|
||||
float alphaOut = clamp(dropMaskSum, 0.0, 1.0);
|
||||
out_color = vec4(finalMix, alphaOut);
|
||||
|
||||
{ // Overlay windshield texture with alpha
|
||||
vec3 fragcolor = ambient;
|
||||
vec3 fragnormal = normalize(f_normal);
|
||||
float reflectivity = param[1].z;
|
||||
float specularity = (tex_color.r + tex_color.g + tex_color.b) * 0.5;
|
||||
legacy_gloss();
|
||||
|
||||
fragcolor = apply_lights(fragcolor, fragnormal, tex_color.rgb, reflectivity, specularity, shadow_tone);
|
||||
vec4 color = vec4(fragcolor, tex_color.a * alpha_mult);
|
||||
|
||||
out_color.xyz = apply_fog(mix(out_color.xyz, color.xyz, color.a));
|
||||
out_color.a = mix(out_color.a, 1., color.a);
|
||||
}
|
||||
|
||||
if (MOTIONBLUR_ENABLED)
|
||||
{
|
||||
out_motion = vec4(0.0);
|
||||
}
|
||||
}
|
||||
|
||||
float GetMixFactor(in vec2 co, out float side) {
|
||||
vec4 movePhase = wiper_pos;
|
||||
bvec4 is_out = lessThanEqual(movePhase, vec4(1.));
|
||||
movePhase = mix(vec4(2.) - movePhase, movePhase, is_out);
|
||||
|
||||
vec4 mask = texture(wipermask, co);
|
||||
|
||||
vec4 areaMask = step(.001, mask);
|
||||
|
||||
vec4 maskVal = mix(1. - mask, mask, is_out);
|
||||
vec4 wipeWidth = smoothstep(1., .9, movePhase) * .25;
|
||||
vec4 cleaned = smoothstep(movePhase - wipeWidth, movePhase, maskVal) * areaMask;
|
||||
vec4 side_v = step(maskVal, movePhase);
|
||||
cleaned *= side_v;
|
||||
side_v = mix(side_v, vec4(1.) - side_v, is_out);
|
||||
|
||||
// "regeneration", raindrops gradually returning after wiper pass:
|
||||
vec4 regenPhase = clamp((vec4(time) - mix(wiper_timer_out, wiper_timer_return, side_v) - vec4(.2)) / vec4(rain_params.y), vec4(0.), vec4(1.));
|
||||
|
||||
side_v = mix(vec4(0.), vec4(1.) - side_v, areaMask);
|
||||
|
||||
vec4 factor_v = mix(vec4(1.), regenPhase * (vec4(1.) - cleaned), areaMask);
|
||||
|
||||
side = 0.;
|
||||
float out_factor = 1.;
|
||||
|
||||
// Find out the wiper blade that influences given grid cell the most
|
||||
for(int i = 0; i < 4; ++i)
|
||||
{
|
||||
bool is_candidate = factor_v[i] < out_factor;
|
||||
out_factor = mix(out_factor, factor_v[i], is_candidate);
|
||||
side = mix(side, side_v[i], is_candidate);
|
||||
}
|
||||
|
||||
return out_factor;
|
||||
}
|
||||
4
shaders/vk14/mat_reflmap.frag
Normal file
4
shaders/vk14/mat_reflmap.frag
Normal file
@@ -0,0 +1,4 @@
|
||||
#version 460 core
|
||||
#define STAGE_FRAGMENT 1
|
||||
#include "common.glsl"
|
||||
#include "mat_reflmap.glsl"
|
||||
72
shaders/vk14/mat_reflmap.glsl
Normal file
72
shaders/vk14/mat_reflmap.glsl
Normal file
@@ -0,0 +1,72 @@
|
||||
layout(location = 0) in vec3 f_normal;
|
||||
layout(location = 2) in vec2 f_coord;
|
||||
layout(location = 3) in vec4 f_pos;
|
||||
|
||||
layout(location = 4) in vec4 f_clip_pos;
|
||||
layout(location = 5) in vec4 f_clip_future_pos;
|
||||
|
||||
#include "common.glsl"
|
||||
|
||||
layout(location = 0) out vec4 out_color;
|
||||
#ifdef NO_MOTION_OUTPUT
|
||||
// a pass without the velocity target: the writes go nowhere
|
||||
vec4 out_motion;
|
||||
#else
|
||||
layout(location = 1) out vec4 out_motion;
|
||||
#endif
|
||||
|
||||
#pragma param(color, 0, 0, 4, diffuse)
|
||||
#pragma param(diffuse, 1, 0, 1, diffuse)
|
||||
#pragma param(specular, 1, 1, 1, specular)
|
||||
#pragma param(reflection, 1, 2, 1, one)
|
||||
#pragma param(glossiness, 1, 3, 1, glossiness)
|
||||
|
||||
#pragma texture(diffuse, 0, sRGB_A)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 0) uniform sampler2D diffuse;
|
||||
|
||||
#pragma texture(reflmap, 1, RGBA)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 1) uniform sampler2D reflmap;
|
||||
|
||||
#include "light_common.glsl"
|
||||
#include "apply_fog.glsl"
|
||||
#include "tonemapping.glsl"
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 tex_color = texture(diffuse, f_coord);
|
||||
|
||||
bool alphatestfail = ( opacity >= 0.0 ? (tex_color.a < opacity) : (tex_color.a >= -opacity) );
|
||||
if(alphatestfail)
|
||||
discard;
|
||||
// if (tex_color.a < opacity)
|
||||
// discard;
|
||||
|
||||
vec3 fragcolor = ambient;
|
||||
vec3 fragnormal = normalize(f_normal);
|
||||
float reflectivity = param[1].z * texture(reflmap, f_coord).a;
|
||||
float specularity = (tex_color.r + tex_color.g + tex_color.b) * 0.5;
|
||||
legacy_gloss();
|
||||
|
||||
fragcolor = apply_lights(fragcolor, fragnormal, tex_color.rgb, reflectivity, 0.0, shadow_tone);
|
||||
|
||||
if(alphatestfail)
|
||||
fragcolor.r = 1.0;
|
||||
|
||||
vec4 color = vec4(apply_fog(fragcolor), tex_color.a * alpha_mult);
|
||||
|
||||
if (POSTFX_ENABLED)
|
||||
{
|
||||
out_color = color;
|
||||
}
|
||||
else
|
||||
{
|
||||
out_color = tonemap(color);
|
||||
}
|
||||
if (MOTIONBLUR_ENABLED)
|
||||
{
|
||||
vec2 a = (f_clip_future_pos.xy / f_clip_future_pos.w) * 0.5 + 0.5;;
|
||||
vec2 b = (f_clip_pos.xy / f_clip_pos.w) * 0.5 + 0.5;;
|
||||
|
||||
out_motion = vec4(a - b, 0.0f, 0.0f);
|
||||
}
|
||||
}
|
||||
79
shaders/vk14/mat_reflmap_specgloss.frag
Normal file
79
shaders/vk14/mat_reflmap_specgloss.frag
Normal file
@@ -0,0 +1,79 @@
|
||||
#version 460 core
|
||||
#define STAGE_FRAGMENT 1
|
||||
#include "common.glsl"
|
||||
layout(location = 0) in vec3 f_normal;
|
||||
layout(location = 2) in vec2 f_coord;
|
||||
layout(location = 3) in vec4 f_pos;
|
||||
|
||||
layout(location = 4) in vec4 f_clip_pos;
|
||||
layout(location = 5) in vec4 f_clip_future_pos;
|
||||
|
||||
|
||||
layout(location = 0) out vec4 out_color;
|
||||
#ifdef NO_MOTION_OUTPUT
|
||||
// a pass without the velocity target: the writes go nowhere
|
||||
vec4 out_motion;
|
||||
#else
|
||||
layout(location = 1) out vec4 out_motion;
|
||||
#endif
|
||||
|
||||
#pragma param(color, 0, 0, 4, diffuse)
|
||||
#pragma param(diffuse, 1, 0, 1, diffuse)
|
||||
#pragma param(specular, 1, 1, 1, specular)
|
||||
#pragma param(reflection, 1, 2, 1, one)
|
||||
#pragma param(glossiness, 1, 3, 1, glossiness)
|
||||
|
||||
#pragma texture(diffuse, 0, sRGB_A)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 0) uniform sampler2D diffuse;
|
||||
|
||||
#pragma texture(reflmap, 1, RGBA)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 1) uniform sampler2D reflmap;
|
||||
|
||||
#pragma texture(specgloss, 2, RGBA)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 2) uniform sampler2D specgloss;
|
||||
|
||||
|
||||
#include "light_common.glsl"
|
||||
#include "apply_fog.glsl"
|
||||
#include "tonemapping.glsl"
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 tex_color = texture(diffuse, f_coord);
|
||||
|
||||
bool alphatestfail = ( opacity >= 0.0 ? (tex_color.a < opacity) : (tex_color.a >= -opacity) );
|
||||
if(alphatestfail)
|
||||
discard;
|
||||
// if (tex_color.a < opacity)
|
||||
// discard;
|
||||
|
||||
vec3 fragcolor = ambient;
|
||||
vec3 fragnormal = normalize(f_normal);
|
||||
float reflectivity = param[1].z * texture(reflmap, f_coord).a;
|
||||
float specularity = texture(specgloss, f_coord).r;
|
||||
glossiness = texture(specgloss, f_coord).g * abs(param[1].w);
|
||||
metalic = texture(specgloss, f_coord).b;
|
||||
|
||||
fragcolor = apply_lights(fragcolor, fragnormal, tex_color.rgb, reflectivity, specularity, shadow_tone);
|
||||
|
||||
if(alphatestfail)
|
||||
fragcolor.r = 1.0;
|
||||
|
||||
vec4 color = vec4(apply_fog(fragcolor), tex_color.a * alpha_mult);
|
||||
|
||||
if (POSTFX_ENABLED)
|
||||
{
|
||||
out_color = color;
|
||||
}
|
||||
else
|
||||
{
|
||||
out_color = tonemap(color);
|
||||
}
|
||||
if (MOTIONBLUR_ENABLED)
|
||||
{
|
||||
vec2 a = (f_clip_future_pos.xy / f_clip_future_pos.w) * 0.5 + 0.5;;
|
||||
vec2 b = (f_clip_pos.xy / f_clip_pos.w) * 0.5 + 0.5;;
|
||||
|
||||
out_motion = vec4(a - b, 0.0f, 0.0f);
|
||||
}
|
||||
}
|
||||
75
shaders/vk14/mat_shadowlessnormalmap.frag
Normal file
75
shaders/vk14/mat_shadowlessnormalmap.frag
Normal file
@@ -0,0 +1,75 @@
|
||||
#version 460 core
|
||||
#define STAGE_FRAGMENT 1
|
||||
#include "common.glsl"
|
||||
layout(location = 0) in vec3 f_normal;
|
||||
layout(location = 2) in vec2 f_coord;
|
||||
layout(location = 3) in vec4 f_pos;
|
||||
layout(location = 8) in mat3 f_tbn;
|
||||
|
||||
layout(location = 4) in vec4 f_clip_pos;
|
||||
layout(location = 5) in vec4 f_clip_future_pos;
|
||||
|
||||
|
||||
layout(location = 0) out vec4 out_color;
|
||||
#ifdef NO_MOTION_OUTPUT
|
||||
// a pass without the velocity target: the writes go nowhere
|
||||
vec4 out_motion;
|
||||
#else
|
||||
layout(location = 1) out vec4 out_motion;
|
||||
#endif
|
||||
|
||||
#pragma param(color, 0, 0, 4, diffuse)
|
||||
#pragma param(diffuse, 1, 0, 1, diffuse)
|
||||
#pragma param(specular, 1, 1, 1, specular)
|
||||
#pragma param(reflection, 1, 2, 1, zero)
|
||||
#pragma param(glossiness, 1, 3, 1, glossiness)
|
||||
|
||||
#pragma texture(diffuse, 0, sRGB_A)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 0) uniform sampler2D diffuse;
|
||||
|
||||
#pragma texture(normalmap, 1, RGBA)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 1) uniform sampler2D normalmap;
|
||||
|
||||
#define NORMALMAP
|
||||
#include "light_common.glsl"
|
||||
#include "apply_fog.glsl"
|
||||
#include "tonemapping.glsl"
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 tex_color = texture(diffuse, f_coord);
|
||||
|
||||
bool alphatestfail = ( opacity >= 0.0 ? (tex_color.a < opacity) : (tex_color.a >= -opacity) );
|
||||
if(alphatestfail)
|
||||
discard;
|
||||
// if (tex_color.a < opacity)
|
||||
// discard;
|
||||
|
||||
vec3 fragcolor = ambient;
|
||||
|
||||
vec3 normal;
|
||||
normal.xy = (texture(normalmap, f_coord).rg * 2.0 - 1.0);
|
||||
normal.z = sqrt(1.0 - clamp((dot(normal.xy, normal.xy)), 0.0, 1.0));
|
||||
vec3 fragnormal = normalize(f_tbn * normalize(normal.xyz));
|
||||
float reflectivity = param[1].z * texture(normalmap, f_coord).a;
|
||||
float specularity = (tex_color.r + tex_color.g + tex_color.b) * 0.5;
|
||||
legacy_gloss();
|
||||
|
||||
fragcolor = apply_lights(fragcolor, fragnormal, tex_color.rgb, reflectivity, specularity, 1.0);
|
||||
vec4 color = vec4(apply_fog(fragcolor), tex_color.a * alpha_mult);
|
||||
if (POSTFX_ENABLED)
|
||||
{
|
||||
out_color = color;
|
||||
}
|
||||
else
|
||||
{
|
||||
out_color = tonemap(color);
|
||||
}
|
||||
if (MOTIONBLUR_ENABLED)
|
||||
{
|
||||
vec2 a = (f_clip_future_pos.xy / f_clip_future_pos.w) * 0.5 + 0.5;;
|
||||
vec2 b = (f_clip_pos.xy / f_clip_pos.w) * 0.5 + 0.5;;
|
||||
|
||||
out_motion = vec4(a - b, 0.0f, 0.0f);
|
||||
}
|
||||
}
|
||||
80
shaders/vk14/mat_shadowlessnormalmap_specgloss.frag
Normal file
80
shaders/vk14/mat_shadowlessnormalmap_specgloss.frag
Normal file
@@ -0,0 +1,80 @@
|
||||
#version 460 core
|
||||
#define STAGE_FRAGMENT 1
|
||||
#include "common.glsl"
|
||||
layout(location = 0) in vec3 f_normal;
|
||||
layout(location = 2) in vec2 f_coord;
|
||||
layout(location = 3) in vec4 f_pos;
|
||||
layout(location = 8) in mat3 f_tbn;
|
||||
|
||||
layout(location = 4) in vec4 f_clip_pos;
|
||||
layout(location = 5) in vec4 f_clip_future_pos;
|
||||
|
||||
|
||||
layout(location = 0) out vec4 out_color;
|
||||
#ifdef NO_MOTION_OUTPUT
|
||||
// a pass without the velocity target: the writes go nowhere
|
||||
vec4 out_motion;
|
||||
#else
|
||||
layout(location = 1) out vec4 out_motion;
|
||||
#endif
|
||||
|
||||
#pragma param(color, 0, 0, 4, diffuse)
|
||||
#pragma param(diffuse, 1, 0, 1, diffuse)
|
||||
#pragma param(specular, 1, 1, 1, specular)
|
||||
#pragma param(reflection, 1, 2, 1, zero)
|
||||
#pragma param(glossiness, 1, 3, 1, glossiness)
|
||||
|
||||
#pragma texture(diffuse, 0, sRGB_A)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 0) uniform sampler2D diffuse;
|
||||
|
||||
#pragma texture(normalmap, 1, RGBA)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 1) uniform sampler2D normalmap;
|
||||
|
||||
#pragma texture(specgloss, 2, RGBA)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 2) uniform sampler2D specgloss;
|
||||
|
||||
|
||||
#define NORMALMAP
|
||||
#include "light_common.glsl"
|
||||
#include "apply_fog.glsl"
|
||||
#include "tonemapping.glsl"
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 tex_color = texture(diffuse, f_coord);
|
||||
|
||||
bool alphatestfail = ( opacity >= 0.0 ? (tex_color.a < opacity) : (tex_color.a >= -opacity) );
|
||||
if(alphatestfail)
|
||||
discard;
|
||||
// if (tex_color.a < opacity)
|
||||
// discard;
|
||||
|
||||
vec3 fragcolor = ambient;
|
||||
|
||||
vec3 normal;
|
||||
normal.xy = (texture(normalmap, f_coord).rg * 2.0 - 1.0);
|
||||
normal.z = sqrt(1.0 - clamp((dot(normal.xy, normal.xy)), 0.0, 1.0));
|
||||
vec3 fragnormal = normalize(f_tbn * normalize(normal.xyz));
|
||||
float reflectivity = param[1].z * texture(normalmap, f_coord).a;
|
||||
float specularity = texture(specgloss, f_coord).r;
|
||||
glossiness = texture(specgloss, f_coord).g * abs(param[1].w);
|
||||
metalic = texture(specgloss, f_coord).b;
|
||||
|
||||
fragcolor = apply_lights(fragcolor, fragnormal, tex_color.rgb, reflectivity, specularity, 1.0);
|
||||
vec4 color = vec4(apply_fog(fragcolor), tex_color.a * alpha_mult);
|
||||
if (POSTFX_ENABLED)
|
||||
{
|
||||
out_color = color;
|
||||
}
|
||||
else
|
||||
{
|
||||
out_color = tonemap(color);
|
||||
}
|
||||
if (MOTIONBLUR_ENABLED)
|
||||
{
|
||||
vec2 a = (f_clip_future_pos.xy / f_clip_future_pos.w) * 0.5 + 0.5;;
|
||||
vec2 b = (f_clip_pos.xy / f_clip_pos.w) * 0.5 + 0.5;;
|
||||
|
||||
out_motion = vec4(a - b, 0.0f, 0.0f);
|
||||
}
|
||||
}
|
||||
38
shaders/vk14/mat_stars.frag
Normal file
38
shaders/vk14/mat_stars.frag
Normal file
@@ -0,0 +1,38 @@
|
||||
#version 460 core
|
||||
#define STAGE_FRAGMENT 1
|
||||
#include "common.glsl"
|
||||
#include "tonemapping.glsl"
|
||||
|
||||
layout(location = 1) flat in vec3 f_normal_raw;
|
||||
|
||||
layout(location = 0) out vec4 out_color;
|
||||
#ifdef NO_MOTION_OUTPUT
|
||||
// a pass without the velocity target: the writes go nowhere
|
||||
vec4 out_motion;
|
||||
#else
|
||||
layout(location = 1) out vec4 out_motion;
|
||||
#endif
|
||||
|
||||
void main()
|
||||
{
|
||||
float x = (gl_PointCoord.x - 0.5f) * 2.0f;
|
||||
float y = (gl_PointCoord.y - 0.5f) * 2.0f;
|
||||
float dist2 = abs(x * x + y * y);
|
||||
if (dist2 > 0.5f * 0.5f)
|
||||
discard;
|
||||
|
||||
// color data space is shared with normals, ugh
|
||||
vec4 color = vec4(pow(f_normal_raw.rgb, vec3(2.2)), 1.0f);
|
||||
if (POSTFX_ENABLED)
|
||||
{
|
||||
out_color = color;
|
||||
}
|
||||
else
|
||||
{
|
||||
out_color = tonemap(color);
|
||||
}
|
||||
if (MOTIONBLUR_ENABLED)
|
||||
{
|
||||
out_motion = vec4(0.0f);
|
||||
}
|
||||
}
|
||||
75
shaders/vk14/mat_sunlessnormalmap.frag
Normal file
75
shaders/vk14/mat_sunlessnormalmap.frag
Normal file
@@ -0,0 +1,75 @@
|
||||
#version 460 core
|
||||
#define STAGE_FRAGMENT 1
|
||||
#include "common.glsl"
|
||||
layout(location = 0) in vec3 f_normal;
|
||||
layout(location = 2) in vec2 f_coord;
|
||||
layout(location = 3) in vec4 f_pos;
|
||||
layout(location = 8) in mat3 f_tbn;
|
||||
|
||||
layout(location = 4) in vec4 f_clip_pos;
|
||||
layout(location = 5) in vec4 f_clip_future_pos;
|
||||
|
||||
|
||||
layout(location = 0) out vec4 out_color;
|
||||
#ifdef NO_MOTION_OUTPUT
|
||||
// a pass without the velocity target: the writes go nowhere
|
||||
vec4 out_motion;
|
||||
#else
|
||||
layout(location = 1) out vec4 out_motion;
|
||||
#endif
|
||||
|
||||
#pragma param(color, 0, 0, 4, diffuse)
|
||||
#pragma param(diffuse, 1, 0, 1, diffuse)
|
||||
#pragma param(specular, 1, 1, 1, specular)
|
||||
#pragma param(reflection, 1, 2, 1, zero)
|
||||
#pragma param(glossiness, 1, 3, 1, glossiness)
|
||||
|
||||
#pragma texture(diffuse, 0, sRGB_A)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 0) uniform sampler2D diffuse;
|
||||
|
||||
#pragma texture(normalmap, 1, RGBA)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 1) uniform sampler2D normalmap;
|
||||
|
||||
#define NORMALMAP
|
||||
#include "light_common.glsl"
|
||||
#include "apply_fog.glsl"
|
||||
#include "tonemapping.glsl"
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 tex_color = texture(diffuse, f_coord);
|
||||
|
||||
bool alphatestfail = ( opacity >= 0.0 ? (tex_color.a < opacity) : (tex_color.a >= -opacity) );
|
||||
if(alphatestfail)
|
||||
discard;
|
||||
// if (tex_color.a < opacity)
|
||||
// discard;
|
||||
|
||||
vec3 fragcolor = ambient;
|
||||
|
||||
vec3 normal;
|
||||
normal.xy = (texture(normalmap, f_coord).rg * 2.0 - 1.0);
|
||||
normal.z = sqrt(1.0 - clamp((dot(normal.xy, normal.xy)), 0.0, 1.0));
|
||||
vec3 fragnormal = normalize(f_tbn * normalize(normal.xyz));
|
||||
float reflectivity = param[1].z * texture(normalmap, f_coord).a;
|
||||
float specularity = (tex_color.r + tex_color.g + tex_color.b) * 0.5;
|
||||
legacy_gloss();
|
||||
|
||||
fragcolor = apply_lights_sunless(fragcolor, fragnormal, tex_color.rgb, reflectivity, specularity, shadow_tone);
|
||||
vec4 color = vec4(apply_fog(fragcolor), tex_color.a * alpha_mult);
|
||||
if (POSTFX_ENABLED)
|
||||
{
|
||||
out_color = color;
|
||||
}
|
||||
else
|
||||
{
|
||||
out_color = tonemap(color);
|
||||
}
|
||||
if (MOTIONBLUR_ENABLED)
|
||||
{
|
||||
vec2 a = (f_clip_future_pos.xy / f_clip_future_pos.w) * 0.5 + 0.5;;
|
||||
vec2 b = (f_clip_pos.xy / f_clip_pos.w) * 0.5 + 0.5;;
|
||||
|
||||
out_motion = vec4(a - b, 0.0f, 0.0f);
|
||||
}
|
||||
}
|
||||
80
shaders/vk14/mat_sunlessnormalmap_specgloss.frag
Normal file
80
shaders/vk14/mat_sunlessnormalmap_specgloss.frag
Normal file
@@ -0,0 +1,80 @@
|
||||
#version 460 core
|
||||
#define STAGE_FRAGMENT 1
|
||||
#include "common.glsl"
|
||||
layout(location = 0) in vec3 f_normal;
|
||||
layout(location = 2) in vec2 f_coord;
|
||||
layout(location = 3) in vec4 f_pos;
|
||||
layout(location = 8) in mat3 f_tbn;
|
||||
|
||||
layout(location = 4) in vec4 f_clip_pos;
|
||||
layout(location = 5) in vec4 f_clip_future_pos;
|
||||
|
||||
|
||||
layout(location = 0) out vec4 out_color;
|
||||
#ifdef NO_MOTION_OUTPUT
|
||||
// a pass without the velocity target: the writes go nowhere
|
||||
vec4 out_motion;
|
||||
#else
|
||||
layout(location = 1) out vec4 out_motion;
|
||||
#endif
|
||||
|
||||
#pragma param(color, 0, 0, 4, diffuse)
|
||||
#pragma param(diffuse, 1, 0, 1, diffuse)
|
||||
#pragma param(specular, 1, 1, 1, specular)
|
||||
#pragma param(reflection, 1, 2, 1, zero)
|
||||
#pragma param(glossiness, 1, 3, 1, glossiness)
|
||||
|
||||
#pragma texture(diffuse, 0, sRGB_A)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 0) uniform sampler2D diffuse;
|
||||
|
||||
#pragma texture(normalmap, 1, RGBA)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 1) uniform sampler2D normalmap;
|
||||
|
||||
#pragma texture(specgloss, 2, RGBA)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 2) uniform sampler2D specgloss;
|
||||
|
||||
|
||||
#define NORMALMAP
|
||||
#include "light_common.glsl"
|
||||
#include "apply_fog.glsl"
|
||||
#include "tonemapping.glsl"
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 tex_color = texture(diffuse, f_coord);
|
||||
|
||||
bool alphatestfail = ( opacity >= 0.0 ? (tex_color.a < opacity) : (tex_color.a >= -opacity) );
|
||||
if(alphatestfail)
|
||||
discard;
|
||||
// if (tex_color.a < opacity)
|
||||
// discard;
|
||||
|
||||
vec3 fragcolor = ambient;
|
||||
|
||||
vec3 normal;
|
||||
normal.xy = (texture(normalmap, f_coord).rg * 2.0 - 1.0);
|
||||
normal.z = sqrt(1.0 - clamp((dot(normal.xy, normal.xy)), 0.0, 1.0));
|
||||
vec3 fragnormal = normalize(f_tbn * normalize(normal.xyz));
|
||||
float reflectivity = param[1].z * texture(normalmap, f_coord).a;
|
||||
float specularity = texture(specgloss, f_coord).r;
|
||||
glossiness = texture(specgloss, f_coord).g * abs(param[1].w);
|
||||
metalic = texture(specgloss, f_coord).b;
|
||||
|
||||
fragcolor = apply_lights_sunless(fragcolor, fragnormal, tex_color.rgb, reflectivity, specularity, shadow_tone);
|
||||
vec4 color = vec4(apply_fog(fragcolor), tex_color.a * alpha_mult);
|
||||
if (POSTFX_ENABLED)
|
||||
{
|
||||
out_color = color;
|
||||
}
|
||||
else
|
||||
{
|
||||
out_color = tonemap(color);
|
||||
}
|
||||
if (MOTIONBLUR_ENABLED)
|
||||
{
|
||||
vec2 a = (f_clip_future_pos.xy / f_clip_future_pos.w) * 0.5 + 0.5;;
|
||||
vec2 b = (f_clip_pos.xy / f_clip_pos.w) * 0.5 + 0.5;;
|
||||
|
||||
out_motion = vec4(a - b, 0.0f, 0.0f);
|
||||
}
|
||||
}
|
||||
13
shaders/vk14/mat_trackblend.frag
Normal file
13
shaders/vk14/mat_trackblend.frag
Normal file
@@ -0,0 +1,13 @@
|
||||
#version 460 core
|
||||
#define STAGE_FRAGMENT 1
|
||||
#include "common.glsl"
|
||||
// the rails and the ballast of a track faded into those of the tracks joined at its ends, see trackblend.glsl
|
||||
#pragma texture(diffuse, 0, sRGB_A)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 0) uniform sampler2D diffuse;
|
||||
#pragma texture(diffuse1, 1, sRGB_A)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 1) uniform sampler2D diffuse1;
|
||||
#pragma texture(diffuse2, 2, sRGB_A)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 2) uniform sampler2D diffuse2;
|
||||
#pragma texture(diffuse3, 3, sRGB_A)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 3) uniform sampler2D diffuse3;
|
||||
#include "trackblend.glsl"
|
||||
22
shaders/vk14/mat_trackblend_normalmap.frag
Normal file
22
shaders/vk14/mat_trackblend_normalmap.frag
Normal file
@@ -0,0 +1,22 @@
|
||||
#version 460 core
|
||||
#define STAGE_FRAGMENT 1
|
||||
#include "common.glsl"
|
||||
// the rails and the ballast of a track of a normal mapped material faded into those of the tracks joined at its ends, see trackblend.glsl
|
||||
#define TRACKBLEND_NORMALMAP 1
|
||||
#pragma texture(diffuse, 0, sRGB_A)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 0) uniform sampler2D diffuse;
|
||||
#pragma texture(diffuse1, 1, sRGB_A)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 1) uniform sampler2D diffuse1;
|
||||
#pragma texture(diffuse2, 2, sRGB_A)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 2) uniform sampler2D diffuse2;
|
||||
#pragma texture(diffuse3, 3, sRGB_A)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 3) uniform sampler2D diffuse3;
|
||||
#pragma texture(normalmap, 4, RGBA)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 4) uniform sampler2D normalmap;
|
||||
#pragma texture(normalmap1, 5, RGBA)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 5) uniform sampler2D normalmap1;
|
||||
#pragma texture(normalmap2, 6, RGBA)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 6) uniform sampler2D normalmap2;
|
||||
#pragma texture(normalmap3, 7, RGBA)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 7) uniform sampler2D normalmap3;
|
||||
#include "trackblend.glsl"
|
||||
25
shaders/vk14/mat_trackblend_parallax.frag
Normal file
25
shaders/vk14/mat_trackblend_parallax.frag
Normal file
@@ -0,0 +1,25 @@
|
||||
#version 460 core
|
||||
#define STAGE_FRAGMENT 1
|
||||
#include "common.glsl"
|
||||
// the rails and the ballast of a track of a parallax material faded into those of the tracks joined at its ends, see trackblend.glsl
|
||||
#define TRACKBLEND_NORMALMAP 1
|
||||
#define TRACKBLEND_PARALLAX 1
|
||||
#pragma param(height_scale, 2, 1, 1, zero)
|
||||
#pragma param(height_offset, 2, 2, 1, zero)
|
||||
#pragma texture(diffuse, 0, sRGB_A)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 0) uniform sampler2D diffuse;
|
||||
#pragma texture(diffuse1, 1, sRGB_A)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 1) uniform sampler2D diffuse1;
|
||||
#pragma texture(diffuse2, 2, sRGB_A)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 2) uniform sampler2D diffuse2;
|
||||
#pragma texture(diffuse3, 3, sRGB_A)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 3) uniform sampler2D diffuse3;
|
||||
#pragma texture(normalmap, 4, RGBA)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 4) uniform sampler2D normalmap;
|
||||
#pragma texture(normalmap1, 5, RGBA)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 5) uniform sampler2D normalmap1;
|
||||
#pragma texture(normalmap2, 6, RGBA)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 6) uniform sampler2D normalmap2;
|
||||
#pragma texture(normalmap3, 7, RGBA)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 7) uniform sampler2D normalmap3;
|
||||
#include "trackblend.glsl"
|
||||
21
shaders/vk14/mat_trackblend_specgloss.frag
Normal file
21
shaders/vk14/mat_trackblend_specgloss.frag
Normal file
@@ -0,0 +1,21 @@
|
||||
#version 460 core
|
||||
#define STAGE_FRAGMENT 1
|
||||
#include "common.glsl"
|
||||
// the rails and the ballast of a track of a material with normal and specgloss maps faded into those of the tracks joined at its ends, see trackblend.glsl
|
||||
#define TRACKBLEND_NORMALMAP 1
|
||||
#define TRACKBLEND_SPECGLOSS 1
|
||||
#pragma texture(diffuse, 0, sRGB_A)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 0) uniform sampler2D diffuse;
|
||||
#pragma texture(diffuse1, 1, sRGB_A)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 1) uniform sampler2D diffuse1;
|
||||
#pragma texture(diffuse2, 2, sRGB_A)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 2) uniform sampler2D diffuse2;
|
||||
#pragma texture(normalmap, 3, RGBA)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 3) uniform sampler2D normalmap;
|
||||
#pragma texture(normalmap1, 4, RGBA)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 4) uniform sampler2D normalmap1;
|
||||
#pragma texture(normalmap2, 5, RGBA)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 5) uniform sampler2D normalmap2;
|
||||
#pragma texture(specgloss, 6, RGBA)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 6) uniform sampler2D specgloss;
|
||||
#include "trackblend.glsl"
|
||||
98
shaders/vk14/mat_water.frag
Normal file
98
shaders/vk14/mat_water.frag
Normal file
@@ -0,0 +1,98 @@
|
||||
#version 460 core
|
||||
#define STAGE_FRAGMENT 1
|
||||
#include "common.glsl"
|
||||
layout(location = 0) in vec3 f_normal;
|
||||
layout(location = 2) in vec2 f_coord;
|
||||
layout(location = 3) in vec4 f_pos;
|
||||
layout(location = 8) in mat3 f_tbn;
|
||||
|
||||
layout(location = 4) in vec4 f_clip_pos;
|
||||
layout(location = 5) in vec4 f_clip_future_pos;
|
||||
|
||||
|
||||
layout(location = 0) out vec4 out_color;
|
||||
#ifdef NO_MOTION_OUTPUT
|
||||
// a pass without the velocity target: the writes go nowhere
|
||||
vec4 out_motion;
|
||||
#else
|
||||
layout(location = 1) out vec4 out_motion;
|
||||
#endif
|
||||
|
||||
#pragma param(color, 0, 0, 4, diffuse)
|
||||
#pragma param(diffuse, 1, 0, 1, diffuse)
|
||||
#pragma param(specular, 1, 1, 1, specular)
|
||||
#pragma param(reflection, 1, 2, 1, one)
|
||||
#pragma param(glossiness, 1, 3, 1, glossiness)
|
||||
#pragma param(wave_strength, 2, 1, 1, one)
|
||||
#pragma param(wave_speed, 2, 2, 1, one)
|
||||
|
||||
#pragma texture(normalmap, 0, RGBA)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 0) uniform sampler2D normalmap;
|
||||
|
||||
#pragma texture(dudvmap, 1, RGB)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 1) uniform sampler2D dudvmap;
|
||||
|
||||
#pragma texture(diffuse, 2, sRGB_A)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 2) uniform sampler2D diffuse;
|
||||
|
||||
//wave distortion variables
|
||||
float move_factor = 0.0;
|
||||
|
||||
#define WATER
|
||||
#include "light_common.glsl"
|
||||
#include "apply_fog.glsl"
|
||||
#include "tonemapping.glsl"
|
||||
|
||||
void main()
|
||||
{
|
||||
//wave distortion
|
||||
move_factor += (param[2].z * time);
|
||||
move_factor = mod(move_factor, 1.0);
|
||||
vec2 texture_coords = f_coord;
|
||||
vec2 distorted_tex_coord = texture(dudvmap, vec2(texture_coords.x + move_factor, texture_coords.y)).rg * 0.1;
|
||||
distorted_tex_coord = texture_coords + vec2(distorted_tex_coord.x , distorted_tex_coord.y + move_factor);
|
||||
vec2 total_distorted_tex_coord = (texture(dudvmap, distorted_tex_coord).rg * 2.0 - 1.0 ) * param[2].y;
|
||||
texture_coords += total_distorted_tex_coord;
|
||||
|
||||
vec4 tex_color = texture(diffuse, texture_coords);
|
||||
|
||||
vec3 fragcolor = ambient * 0.25;
|
||||
|
||||
vec3 normal;
|
||||
normal.xy = (texture(normalmap, texture_coords).rg * 2.0 - 1.0);
|
||||
normal.z = sqrt(1.0 - clamp((dot(normal.xy, normal.xy)), 0.0, 1.0));
|
||||
vec3 fragnormal = normalize(f_tbn * normalize(normal.xyz));
|
||||
float reflectivity = param[1].z * texture(normalmap, texture_coords ).a;
|
||||
// water reflects 2% at normal incidence
|
||||
float specularity = 0.25;
|
||||
glossiness = abs(param[1].w);
|
||||
|
||||
fragcolor = apply_lights(fragcolor, fragnormal, tex_color.rgb, reflectivity, specularity, shadow_tone);
|
||||
|
||||
//fragcolor = mix(fragcolor, param[0].rgb, param[1].z);
|
||||
// fragcolor = (fragcolor * tex_color.rgb * param[1].z) + (fragcolor * (1.0 - param[1].z)); //multiply
|
||||
//fragcolor = ( max(fragcolor + param[0].rgb -1.0,0.0) * param[1].z + fragcolor * (1.0 - param[1].z)); //linear burn
|
||||
//fragcolor = ( min(param[0].rgb,fragcolor) * param[1].z + fragcolor * (1.0 - param[1].z)); //darken
|
||||
|
||||
// fresnel effect
|
||||
vec3 view_dir = normalize(vec3(0.0f, 0.0f, 0.0f) - f_pos.xyz);
|
||||
float fresnel = pow(max(dot(normalize(f_normal), view_dir), 0.0), 0.2);
|
||||
float fresnel_inv = ((fresnel - 1.0 ) * -1.0 );
|
||||
|
||||
vec4 color = vec4(apply_fog(fragcolor), clamp((fresnel_inv + param[0].a), 0.0, 1.0));
|
||||
if (POSTFX_ENABLED)
|
||||
{
|
||||
out_color = color;
|
||||
}
|
||||
else
|
||||
{
|
||||
out_color = tonemap(color);
|
||||
}
|
||||
if (MOTIONBLUR_ENABLED)
|
||||
{
|
||||
vec2 a = (f_clip_future_pos.xy / f_clip_future_pos.w) * 0.5 + 0.5;;
|
||||
vec2 b = (f_clip_pos.xy / f_clip_pos.w) * 0.5 + 0.5;;
|
||||
|
||||
out_motion = vec4(a - b, 0.0f, 0.0f);
|
||||
}
|
||||
}
|
||||
103
shaders/vk14/mat_water_specgloss.frag
Normal file
103
shaders/vk14/mat_water_specgloss.frag
Normal file
@@ -0,0 +1,103 @@
|
||||
#version 460 core
|
||||
#define STAGE_FRAGMENT 1
|
||||
#include "common.glsl"
|
||||
layout(location = 0) in vec3 f_normal;
|
||||
layout(location = 2) in vec2 f_coord;
|
||||
layout(location = 3) in vec4 f_pos;
|
||||
layout(location = 8) in mat3 f_tbn;
|
||||
|
||||
layout(location = 4) in vec4 f_clip_pos;
|
||||
layout(location = 5) in vec4 f_clip_future_pos;
|
||||
|
||||
|
||||
layout(location = 0) out vec4 out_color;
|
||||
#ifdef NO_MOTION_OUTPUT
|
||||
// a pass without the velocity target: the writes go nowhere
|
||||
vec4 out_motion;
|
||||
#else
|
||||
layout(location = 1) out vec4 out_motion;
|
||||
#endif
|
||||
|
||||
#pragma param(color, 0, 0, 4, diffuse)
|
||||
#pragma param(diffuse, 1, 0, 1, diffuse)
|
||||
#pragma param(specular, 1, 1, 1, specular)
|
||||
#pragma param(reflection, 1, 2, 1, one)
|
||||
#pragma param(glossiness, 1, 3, 1, glossiness)
|
||||
#pragma param(wave_strength, 2, 1, 1, one)
|
||||
#pragma param(wave_speed, 2, 2, 1, one)
|
||||
|
||||
#pragma texture(normalmap, 0, RGBA)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 0) uniform sampler2D normalmap;
|
||||
|
||||
#pragma texture(dudvmap, 1, RGB)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 1) uniform sampler2D dudvmap;
|
||||
|
||||
#pragma texture(diffuse, 2, sRGB_A)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 2) uniform sampler2D diffuse;
|
||||
|
||||
#pragma texture(specgloss, 3, RGBA)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 3) uniform sampler2D specgloss;
|
||||
|
||||
|
||||
//wave distortion variables
|
||||
float move_factor = 0.0;
|
||||
|
||||
#define WATER
|
||||
#include "light_common.glsl"
|
||||
#include "apply_fog.glsl"
|
||||
#include "tonemapping.glsl"
|
||||
|
||||
void main()
|
||||
{
|
||||
//wave distortion
|
||||
move_factor += (param[2].z * time);
|
||||
move_factor = mod(move_factor, 1.0);
|
||||
vec2 texture_coords = f_coord;
|
||||
vec2 distorted_tex_coord = texture(dudvmap, vec2(texture_coords.x + move_factor, texture_coords.y)).rg * 0.1;
|
||||
distorted_tex_coord = texture_coords + vec2(distorted_tex_coord.x , distorted_tex_coord.y + move_factor);
|
||||
vec2 total_distorted_tex_coord = (texture(dudvmap, distorted_tex_coord).rg * 2.0 - 1.0 ) * param[2].y;
|
||||
texture_coords += total_distorted_tex_coord;
|
||||
|
||||
vec4 tex_color = texture(diffuse, texture_coords);
|
||||
|
||||
vec3 fragcolor = ambient * 0.25;
|
||||
|
||||
vec3 normal;
|
||||
normal.xy = (texture(normalmap, texture_coords).rg * 2.0 - 1.0);
|
||||
normal.z = sqrt(1.0 - clamp((dot(normal.xy, normal.xy)), 0.0, 1.0));
|
||||
vec3 fragnormal = normalize(f_tbn * normalize(normal.xyz));
|
||||
float reflectivity = param[1].z * texture(normalmap, texture_coords ).a;
|
||||
vec4 specgloss_map = texture(specgloss, texture_coords);
|
||||
float specularity = specgloss_map.r;
|
||||
glossiness = specgloss_map.g * abs(param[1].w);
|
||||
metalic = specgloss_map.b;
|
||||
|
||||
fragcolor = apply_lights(fragcolor, fragnormal, tex_color.rgb, reflectivity, specularity, shadow_tone);
|
||||
|
||||
//fragcolor = mix(fragcolor, param[0].rgb, param[1].z);
|
||||
// fragcolor = (fragcolor * tex_color.rgb * param[1].z) + (fragcolor * (1.0 - param[1].z)); //multiply
|
||||
//fragcolor = ( max(fragcolor + param[0].rgb -1.0,0.0) * param[1].z + fragcolor * (1.0 - param[1].z)); //linear burn
|
||||
//fragcolor = ( min(param[0].rgb,fragcolor) * param[1].z + fragcolor * (1.0 - param[1].z)); //darken
|
||||
|
||||
// fresnel effect
|
||||
vec3 view_dir = normalize(vec3(0.0f, 0.0f, 0.0f) - f_pos.xyz);
|
||||
float fresnel = pow(max(dot(normalize(f_normal), view_dir), 0.0), 0.2);
|
||||
float fresnel_inv = ((fresnel - 1.0 ) * -1.0 );
|
||||
|
||||
vec4 color = vec4(apply_fog(fragcolor), clamp((fresnel_inv + param[0].a), 0.0, 1.0));
|
||||
if (POSTFX_ENABLED)
|
||||
{
|
||||
out_color = color;
|
||||
}
|
||||
else
|
||||
{
|
||||
out_color = tonemap(color);
|
||||
}
|
||||
if (MOTIONBLUR_ENABLED)
|
||||
{
|
||||
vec2 a = (f_clip_future_pos.xy / f_clip_future_pos.w) * 0.5 + 0.5;;
|
||||
vec2 b = (f_clip_pos.xy / f_clip_pos.w) * 0.5 + 0.5;;
|
||||
|
||||
out_motion = vec4(a - b, 0.0f, 0.0f);
|
||||
}
|
||||
}
|
||||
10
shaders/vk14/pick.frag
Normal file
10
shaders/vk14/pick.frag
Normal file
@@ -0,0 +1,10 @@
|
||||
#version 460 core
|
||||
#define STAGE_FRAGMENT 1
|
||||
#include "common.glsl"
|
||||
|
||||
layout(location = 0) out vec4 out_color;
|
||||
|
||||
void main()
|
||||
{
|
||||
out_color = vec4(param[0].rgb, 1.0);
|
||||
}
|
||||
11
shaders/vk14/pick_surface.frag
Normal file
11
shaders/vk14/pick_surface.frag
Normal file
@@ -0,0 +1,11 @@
|
||||
#version 460 core
|
||||
#define STAGE_FRAGMENT 1
|
||||
#include "common.glsl"
|
||||
|
||||
layout(location = 0) out vec4 out_color;
|
||||
layout(location = 2) in vec2 f_coord;
|
||||
|
||||
void main()
|
||||
{
|
||||
out_color = vec4(param[0].r, f_coord, 1.0);
|
||||
}
|
||||
64
shaders/vk14/postfx_chromaticaberration.frag
Normal file
64
shaders/vk14/postfx_chromaticaberration.frag
Normal file
@@ -0,0 +1,64 @@
|
||||
#version 460 core
|
||||
#define STAGE_FRAGMENT 1
|
||||
#define LAYOUT_POST 1
|
||||
#include "common.glsl"
|
||||
layout(location = 14) in vec2 f_coords;
|
||||
|
||||
layout(location = 0) out vec4 out_color;
|
||||
|
||||
#pragma texture(color_tex, 0, RGB)
|
||||
|
||||
layout(set = POST_SET, binding = POST_TEXTURE_FIRST + 0) uniform sampler2D iChannel0;
|
||||
|
||||
#include "dither.glsl"
|
||||
|
||||
vec2 barrelDistortion(vec2 f_coords, float amt) {
|
||||
vec2 cc = f_coords - 0.5;
|
||||
float dist = dot(cc, cc);
|
||||
return f_coords + cc * dist * amt;
|
||||
}
|
||||
|
||||
float sat( float t )
|
||||
{
|
||||
return clamp( t, 0.0, 1.0 );
|
||||
}
|
||||
|
||||
float linterp( float t ) {
|
||||
return sat( 1.0 - abs( 1.0*t - 1.0 ) );
|
||||
}
|
||||
|
||||
float remap( float t, float a, float b ) {
|
||||
return sat( (t - a) / (b - a) );
|
||||
}
|
||||
|
||||
vec4 spectrum_offset( float t ) {
|
||||
vec4 ret;
|
||||
float lo = step(t,0.5);
|
||||
float hi = 1.0-lo;
|
||||
float w = linterp( remap( t, 1.0/6.0, 5.0/6.0 ) );
|
||||
ret = vec4(lo,1.0,hi, 1.) * vec4(1.0-w, w, 1.0-w, 1.);
|
||||
|
||||
return pow( ret, vec4(1.0/2.2) );
|
||||
}
|
||||
|
||||
const float max_distort = 0.05;
|
||||
const int num_iter = 10;
|
||||
const float reci_num_iter_f = 1.0 / float(num_iter);
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 uv=f_coords.xy;
|
||||
|
||||
vec4 sumcol = vec4(0.0);
|
||||
vec4 sumw = vec4(0.0);
|
||||
for ( int i=0; i<num_iter;++i )
|
||||
{
|
||||
float t = float(i) * reci_num_iter_f;
|
||||
vec4 w = spectrum_offset( t );
|
||||
sumw += w;
|
||||
sumcol += w * texture( iChannel0, barrelDistortion(uv, .6 * max_distort*t ) );
|
||||
}
|
||||
|
||||
out_color = sumcol / sumw;
|
||||
out_color.rgb = dither_output(out_color.rgb);
|
||||
}
|
||||
46
shaders/vk14/postfx_motionblur.frag
Normal file
46
shaders/vk14/postfx_motionblur.frag
Normal file
@@ -0,0 +1,46 @@
|
||||
#version 460 core
|
||||
#define STAGE_FRAGMENT 1
|
||||
#define LAYOUT_POST 1
|
||||
#include "common.glsl"
|
||||
// param is pc.data of the push constants (the model block in the opengl renderer): param[0].x the scale of the velocities
|
||||
layout(location = 14) in vec2 f_coords;
|
||||
layout(location = 0) out vec4 out_color;
|
||||
|
||||
#pragma texture(color_tex, 0, RGB)
|
||||
layout(set = POST_SET, binding = POST_TEXTURE_FIRST + 0) uniform sampler2D color_tex;
|
||||
|
||||
#pragma texture(velocity_tex, 1, RG)
|
||||
layout(set = POST_SET, binding = POST_TEXTURE_FIRST + 1) uniform sampler2D velocity_tex;
|
||||
|
||||
#pragma texture(depth_tex, 2, R)
|
||||
layout(set = POST_SET, binding = POST_TEXTURE_FIRST + 2) uniform sampler2D depth_tex;
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
float ori_depth = texture(depth_tex, f_coords).x;
|
||||
|
||||
vec2 texelSize = 1.0 / vec2(textureSize(color_tex, 0));
|
||||
vec2 velocity = texture(velocity_tex, f_coords).xy * param[0].x;
|
||||
|
||||
float speed = length(velocity / texelSize);
|
||||
int nSamples = clamp(int(speed), 1, 32);
|
||||
|
||||
float depth_diff = 0.001 * 8.0;
|
||||
vec4 result = vec4(0.0);
|
||||
|
||||
result += vec4(texture(color_tex, f_coords).rgb, 1.0);
|
||||
|
||||
for (int i = 1; i < nSamples; ++i)
|
||||
{
|
||||
vec2 offset = velocity * (float(i) / float(nSamples - 1) - 0.5);
|
||||
|
||||
vec2 coord = f_coords + offset;
|
||||
float depth = texture(depth_tex, coord).x;
|
||||
|
||||
if (abs(depth - ori_depth) < depth_diff)
|
||||
result += vec4(texture(color_tex, coord).rgb, 1.0);
|
||||
}
|
||||
|
||||
out_color = vec4((result.rgb / result.w), 1.0);
|
||||
}
|
||||
78
shaders/vk14/postfx_ssao.frag
Normal file
78
shaders/vk14/postfx_ssao.frag
Normal file
@@ -0,0 +1,78 @@
|
||||
#version 460 core
|
||||
#define STAGE_FRAGMENT 1
|
||||
#define LAYOUT_POST 1
|
||||
#include "common.glsl"
|
||||
// the projection of the view (projection of the scene block in the opengl renderer) is pc.data[0..3] of the push constants,
|
||||
// its columns
|
||||
#define projection mat4(pc.data[0], pc.data[1], pc.data[2], pc.data[3])
|
||||
layout(location = 14) in vec2 f_coords;
|
||||
layout(location = 0) out vec4 out_color;
|
||||
|
||||
#pragma texture(depth_tex, 0, R)
|
||||
layout(set = POST_SET, binding = POST_TEXTURE_FIRST + 0) uniform sampler2D depth_tex;
|
||||
|
||||
#pragma texture(noise_tex, 1, RGB)
|
||||
layout(set = POST_SET, binding = POST_TEXTURE_FIRST + 1) uniform sampler2D noise_tex;
|
||||
|
||||
// the depth is reversed (0..1, 1 at the near plane, 0 at infinity), so it is the clip z itself
|
||||
vec3 view_pos_from_depth(vec2 uv, float depth) {
|
||||
vec4 clip = vec4(uv * 2.0 - 1.0, depth, 1.0);
|
||||
vec4 view = inverse(projection) * clip;
|
||||
return view.xyz / view.w;
|
||||
}
|
||||
|
||||
// Deterministic hemisphere sample (z > 0), mimics the C++ kernel generator
|
||||
vec3 kernel_sample(int i) {
|
||||
float fi = float(i);
|
||||
vec3 dir = normalize(vec3(
|
||||
fract(sin(fi * 12.9898) * 43758.5453) * 2.0 - 1.0,
|
||||
fract(sin(fi * 78.2330) * 43758.5453) * 2.0 - 1.0,
|
||||
fract(sin(fi * 37.7190) * 43758.5453) // z >= 0 -> hemisphere
|
||||
));
|
||||
float len = fract(sin(fi * 94.6720) * 43758.5453);
|
||||
float scale = fi / 32.0;
|
||||
scale = mix(0.1, 1.0, scale * scale); // bias samples inward
|
||||
return dir * len * scale;
|
||||
}
|
||||
|
||||
void main() {
|
||||
float d = texture(depth_tex, f_coords).r;
|
||||
if (d <= 0.0) { out_color = vec4(1.0); return; } // skybox -> no occlusion
|
||||
|
||||
vec3 pos = view_pos_from_depth(f_coords, d);
|
||||
|
||||
vec3 ddx = dFdx(pos);
|
||||
vec3 ddy = dFdy(pos);
|
||||
vec3 n = normalize(cross(ddx, ddy));
|
||||
|
||||
// derive screen size from the depth texture instead of a UBO field
|
||||
vec2 screen_size = vec2(textureSize(depth_tex, 0));
|
||||
vec2 noise_uv = f_coords * (screen_size / 4.0);
|
||||
vec3 rvec = texture(noise_tex, noise_uv).xyz;
|
||||
|
||||
vec3 t = normalize(rvec - n * dot(rvec, n));
|
||||
vec3 b = cross(n, t);
|
||||
mat3 TBN = mat3(t, b, n);
|
||||
|
||||
const int KERNEL = 32;
|
||||
const float RADIUS = 0.5;
|
||||
const float BIAS = 0.025;
|
||||
|
||||
float occ = 0.0;
|
||||
for (int i = 0; i < KERNEL; ++i) {
|
||||
vec3 sp = TBN * kernel_sample(i);
|
||||
sp = pos + sp * RADIUS;
|
||||
|
||||
vec4 clip = projection * vec4(sp, 1.0);
|
||||
vec3 ndc = clip.xyz / clip.w;
|
||||
vec2 suv = ndc.xy * 0.5 + 0.5;
|
||||
|
||||
float sd = texture(depth_tex, suv).r;
|
||||
float szv = view_pos_from_depth(suv, sd).z;
|
||||
|
||||
float range = smoothstep(0.0, 1.0, RADIUS / abs(pos.z - szv));
|
||||
occ += (szv >= sp.z + BIAS ? 1.0 : 0.0) * range;
|
||||
}
|
||||
|
||||
out_color = vec4(1.0 - occ / float(KERNEL));
|
||||
}
|
||||
99
shaders/vk14/postfx_ssao_apply.frag
Normal file
99
shaders/vk14/postfx_ssao_apply.frag
Normal file
@@ -0,0 +1,99 @@
|
||||
#version 460 core
|
||||
#define STAGE_FRAGMENT 1
|
||||
#define LAYOUT_POST 1
|
||||
#include "common.glsl"
|
||||
// applies the ambient occlusion of the half size target to the image at full size, as a multiplier: drawn with the
|
||||
// blending dst * src over the image (opengl46_ao::apply). the four nearest pixels of the occlusion are weighed by how
|
||||
// close they are and by how close their distance is to that of the pixel, so the occlusion does not spill over the
|
||||
// edges of objects. each pixel of the occlusion stands for the top left one of the four full size pixels it covers
|
||||
// params.x: 0 ground truth ambient occlusion, 1 the older ssao (its own fixed curve)
|
||||
// params.y: strength, a power of the occlusion (1 = as computed); params.z: albedo assumed by the multiple bounce term.
|
||||
// the fog in front of a surface hides its occlusion as it hides the surface: the analytic fog of apply_fog.glsl, the fog
|
||||
// volume comes with the stage P2.
|
||||
// the parameters are in the push constants (loose uniforms in the opengl renderer): pc.data[0..3] the columns of the inverse
|
||||
// of the projection (inv_projection), pc.data[4] params, pc.data[5].x the density of the fog of the scene (fog_density of the
|
||||
// regular draws, 0: no fog), pc.data[5].yzw unused
|
||||
|
||||
layout(location = 14) in vec2 f_coords;
|
||||
|
||||
layout(location = 0) out vec4 out_color;
|
||||
|
||||
layout(set = POST_SET, binding = POST_TEXTURE_FIRST + 0) uniform sampler2D depth_tex;
|
||||
layout(set = POST_SET, binding = POST_TEXTURE_FIRST + 1) uniform sampler2D ao_tex;
|
||||
|
||||
#define inv_projection mat4(pc.data[0], pc.data[1], pc.data[2], pc.data[3])
|
||||
#define params pc.data[4]
|
||||
#define scene_fog_density pc.data[5].x
|
||||
|
||||
vec3 view_position(ivec2 pixel, float depth)
|
||||
{
|
||||
ivec2 full_size = textureSize(depth_tex, 0);
|
||||
vec2 uv = (vec2(pixel) + 0.5) / vec2(full_size);
|
||||
vec4 position = inv_projection * vec4(uv * 2.0 - 1.0, depth, 1.0);
|
||||
return position.xyz / position.w;
|
||||
}
|
||||
|
||||
float view_distance(ivec2 pixel, float depth)
|
||||
{
|
||||
return length(view_position(pixel, depth));
|
||||
}
|
||||
|
||||
// light which comes back after more than one bounce off surfaces of the given albedo, fit of Jimenez et al. 2016
|
||||
float multi_bounce(float visibility, float albedo)
|
||||
{
|
||||
float a = 2.0404 * albedo - 0.3324;
|
||||
float b = -4.7951 * albedo + 0.6417;
|
||||
float c = 2.7552 * albedo + 0.6903;
|
||||
return max(visibility, ((visibility * a + b) * visibility + c) * visibility);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
ivec2 full_size = textureSize(depth_tex, 0);
|
||||
ivec2 half_size = textureSize(ao_tex, 0);
|
||||
ivec2 pixel = ivec2(gl_FragCoord.xy);
|
||||
float depth = texelFetch(depth_tex, pixel, 0).r;
|
||||
if (depth <= 0.0)
|
||||
{
|
||||
// the sky
|
||||
out_color = vec4(1.0);
|
||||
return;
|
||||
}
|
||||
float distance = view_distance(pixel, depth);
|
||||
|
||||
vec2 position = vec2(pixel) * 0.5;
|
||||
ivec2 base = ivec2(floor(position));
|
||||
vec2 fraction = position - vec2(base);
|
||||
float sum = 0.0;
|
||||
float weights = 0.0;
|
||||
for (int y = 0; y < 2; ++y)
|
||||
{
|
||||
for (int x = 0; x < 2; ++x)
|
||||
{
|
||||
ivec2 texel = clamp(base + ivec2(x, y), ivec2(0), half_size - 1);
|
||||
ivec2 texelpixel = min(texel * 2, full_size - 1);
|
||||
float texeldepth = texelFetch(depth_tex, texelpixel, 0).r;
|
||||
float texeldistance = (texeldepth > 0.0) ? view_distance(texelpixel, texeldepth) : 1e30;
|
||||
float bilinear = (x == 0 ? 1.0 - fraction.x : fraction.x) * (y == 0 ? 1.0 - fraction.y : fraction.y);
|
||||
float weight = (bilinear + 1e-3) / (1e-3 + abs(texeldistance - distance) / distance);
|
||||
sum += texelFetch(ao_tex, texel, 0).r * weight;
|
||||
weights += weight;
|
||||
}
|
||||
}
|
||||
float ao = clamp(sum / max(weights, 1e-6), 0.0, 1.0);
|
||||
|
||||
if (params.x > 0.5)
|
||||
{
|
||||
// the curve the older ssao was applied with, a floor so the shadows do not go black
|
||||
ao = mix(0.3, 1.0, pow(ao, 0.8));
|
||||
}
|
||||
else
|
||||
{
|
||||
ao = pow(ao, params.y);
|
||||
ao = multi_bounce(ao, params.z);
|
||||
}
|
||||
// what the fog lets through of the surface is what is left to occlude
|
||||
float transmittance = (scene_fog_density > 0.0) ? clamp(exp(-distance * scene_fog_density), 0.0, 1.0) : 1.0;
|
||||
ao = mix(1.0, ao, transmittance);
|
||||
out_color = vec4(vec3(ao), 1.0);
|
||||
}
|
||||
18
shaders/vk14/postfx_ssao_blur.frag
Normal file
18
shaders/vk14/postfx_ssao_blur.frag
Normal file
@@ -0,0 +1,18 @@
|
||||
#version 460 core
|
||||
#define STAGE_FRAGMENT 1
|
||||
#define LAYOUT_POST 1
|
||||
#include "common.glsl"
|
||||
layout(location = 14) in vec2 f_coords;
|
||||
layout(location = 0) out vec4 out_color;
|
||||
|
||||
#pragma texture(ssao_tex, 0, R)
|
||||
layout(set = POST_SET, binding = POST_TEXTURE_FIRST + 0) uniform sampler2D ssao_tex;
|
||||
|
||||
void main() {
|
||||
vec2 texel = 1.0 / vec2(textureSize(ssao_tex, 0));
|
||||
float sum = 0.0;
|
||||
for (int x = -2; x < 2; ++x)
|
||||
for (int y = -2; y < 2; ++y)
|
||||
sum += texture(ssao_tex, f_coords + vec2(x, y) * texel).r;
|
||||
out_color = vec4(sum / 16.0);
|
||||
}
|
||||
40
shaders/vk14/postfx_tonemapping.frag
Normal file
40
shaders/vk14/postfx_tonemapping.frag
Normal file
@@ -0,0 +1,40 @@
|
||||
#version 460 core
|
||||
#define STAGE_FRAGMENT 1
|
||||
#define LAYOUT_POST 1
|
||||
#include "common.glsl"
|
||||
layout(location = 14) in vec2 f_coords;
|
||||
|
||||
layout(location = 0) out vec4 out_color;
|
||||
|
||||
#pragma texture(tex1, 0, RGB)
|
||||
layout(set = POST_SET, binding = POST_TEXTURE_FIRST + 0) uniform sampler2D tex1;
|
||||
|
||||
// glow of the bright parts of the image (postfx_bloom_*.frag)
|
||||
#pragma texture(bloom_tex, 1, RGB)
|
||||
layout(set = POST_SET, binding = POST_TEXTURE_FIRST + 1) uniform sampler2D bloom_tex;
|
||||
|
||||
// the automatic exposure (exposure_ssbo of the opengl renderer, exposure_average.comp) comes in a later stage: the fixed
|
||||
// exposure multiplier alone
|
||||
const float exposure = 0.0;
|
||||
|
||||
#include "tonemapping.glsl"
|
||||
#include "dither.glsl"
|
||||
|
||||
// param is pc.data of the push constants (the model block in the opengl renderer).
|
||||
// param[0].x: share of the bloom in the image (0: no bloom, the texture is not read), param[0].y: 1 if the automatic
|
||||
// exposure is applied (there is none yet, so it has no effect), param[0].z: fixed exposure multiplier, param[0].w: scale of
|
||||
// the bloom texture (it holds the sum of the levels of the chain), param[1].x: 1 when this is the last pass before the
|
||||
// window, which takes the dither
|
||||
void main()
|
||||
{
|
||||
vec2 texcoord = f_coords;
|
||||
vec3 hdr_color = texture(tex1, texcoord).xyz;
|
||||
if (param[0].x > 0.0)
|
||||
hdr_color = mix(hdr_color, texture(bloom_tex, texcoord).rgb * param[0].w, param[0].x);
|
||||
float exposurescale = param[0].z;
|
||||
if (param[0].y > 0.5 && exposure > 0.0)
|
||||
exposurescale *= exposure;
|
||||
out_color = tonemap(vec4(hdr_color * exposurescale, 1.0));
|
||||
if (param[1].x > 0.5)
|
||||
out_color.rgb = dither_output(out_color.rgb);
|
||||
}
|
||||
42
shaders/vk14/precipitation.frag
Normal file
42
shaders/vk14/precipitation.frag
Normal file
@@ -0,0 +1,42 @@
|
||||
#version 460 core
|
||||
#define STAGE_FRAGMENT 1
|
||||
#include "common.glsl"
|
||||
layout(location = 2) in vec2 f_coord;
|
||||
|
||||
#pragma texture(tex1, 0, sRGB_A)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 0) uniform sampler2D tex1;
|
||||
|
||||
|
||||
layout(location = 0) out vec4 out_color;
|
||||
#ifdef NO_MOTION_OUTPUT
|
||||
// a pass without the velocity target: the writes go nowhere
|
||||
vec4 out_motion;
|
||||
#else
|
||||
layout(location = 1) out vec4 out_motion;
|
||||
#endif
|
||||
|
||||
layout(location = 4) in vec4 f_clip_pos;
|
||||
layout(location = 5) in vec4 f_clip_future_pos;
|
||||
|
||||
#include "tonemapping.glsl"
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 tex_color = texture(tex1, vec2(f_coord.x, f_coord.y + param[1].x));
|
||||
vec4 color = tex_color * param[0];
|
||||
if (POSTFX_ENABLED)
|
||||
{
|
||||
out_color = color;
|
||||
}
|
||||
else
|
||||
{
|
||||
out_color = tonemap(color);
|
||||
}
|
||||
if (MOTIONBLUR_ENABLED)
|
||||
{
|
||||
vec2 a = (f_clip_future_pos.xy / f_clip_future_pos.w) * 0.5 + 0.5;
|
||||
vec2 b = (f_clip_pos.xy / f_clip_pos.w) * 0.5 + 0.5;
|
||||
|
||||
out_motion = vec4(a - b, 0.0f, tex_color.a * alpha_mult);
|
||||
}
|
||||
}
|
||||
20
shaders/vk14/precipitation.vert
Normal file
20
shaders/vk14/precipitation.vert
Normal file
@@ -0,0 +1,20 @@
|
||||
#version 460 core
|
||||
#define STAGE_VERTEX 1
|
||||
#include "common.glsl"
|
||||
layout(location = 0) in vec3 v_vert;
|
||||
layout(location = 1) in vec2 v_coord;
|
||||
|
||||
layout(location = 2) out vec2 f_coord;
|
||||
|
||||
layout(location = 4) out vec4 f_clip_pos;
|
||||
layout(location = 5) out vec4 f_clip_future_pos;
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
f_clip_pos = (projection * modelview) * vec4(v_vert, 1.0f);
|
||||
f_clip_future_pos = (projection * future * modelview) * vec4(v_vert, 1.0f);
|
||||
|
||||
gl_Position = f_clip_pos;
|
||||
f_coord = v_coord;
|
||||
}
|
||||
17
shaders/vk14/present.frag
Normal file
17
shaders/vk14/present.frag
Normal file
@@ -0,0 +1,17 @@
|
||||
#version 460 core
|
||||
#define STAGE_FRAGMENT 1
|
||||
#define LAYOUT_POST 1
|
||||
#include "common.glsl"
|
||||
// the finished image to the window (with quad.vert). the renderer draws with the matrices of the opengl one, so its images
|
||||
// have the rows in the memory order of opengl, the bottom of the picture first; the window shows the first row at the top.
|
||||
// this is the only place the picture is turned upside down. no push constants
|
||||
layout(location = 14) in vec2 f_coords;
|
||||
|
||||
layout(set = POST_SET, binding = POST_TEXTURE_FIRST + 0) uniform sampler2D tex1;
|
||||
|
||||
layout(location = 0) out vec4 out_color;
|
||||
|
||||
void main()
|
||||
{
|
||||
out_color = FBOUT(texture(tex1, vec2(f_coords.x, 1.0 - f_coords.y)));
|
||||
}
|
||||
27
shaders/vk14/quad.vert
Normal file
27
shaders/vk14/quad.vert
Normal file
@@ -0,0 +1,27 @@
|
||||
#version 460 core
|
||||
#define STAGE_VERTEX 1
|
||||
#define LAYOUT_POST 1
|
||||
#include "common.glsl"
|
||||
const vec2 vert[4] = vec2[]
|
||||
(
|
||||
vec2(-1.0, 1.0),
|
||||
vec2(-1.0, -1.0),
|
||||
vec2( 1.0, 1.0),
|
||||
vec2( 1.0, -1.0)
|
||||
);
|
||||
|
||||
const vec2 uv[4] = vec2[]
|
||||
(
|
||||
vec2(0.0, 1.0),
|
||||
vec2(0.0, 0.0),
|
||||
vec2(1.0, 1.0),
|
||||
vec2(1.0, 0.0)
|
||||
);
|
||||
|
||||
layout(location = 14) out vec2 f_coords;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(vert[gl_VertexIndex], 0.0, 1.0);
|
||||
f_coords = uv[gl_VertexIndex];
|
||||
}
|
||||
39
shaders/vk14/random.glsl
Normal file
39
shaders/vk14/random.glsl
Normal file
@@ -0,0 +1,39 @@
|
||||
|
||||
uint Hash(uint s);
|
||||
uint Hash(uvec2 s);
|
||||
uint Hash(uvec3 s);
|
||||
uint Hash(float s);
|
||||
uint HashCombine(uint seed, uint value);
|
||||
|
||||
// Evolving Sub-Grid Turbulence for Smoke Animation
|
||||
// H. Schechter and R. Bridson
|
||||
uint Hash(uint s) {
|
||||
s ^= 2747636419u;
|
||||
s *= 2654435769u;
|
||||
s ^= s >> 16u;
|
||||
s *= 2654435769u;
|
||||
s ^= s >> 16u;
|
||||
s *= 2654435769u;
|
||||
return s;
|
||||
}
|
||||
|
||||
uint Hash(uvec2 s) {
|
||||
return HashCombine(Hash(s.x), s.y);
|
||||
}
|
||||
|
||||
uint Hash(uvec3 s) {
|
||||
return HashCombine(Hash(s.xy), s.z);
|
||||
}
|
||||
|
||||
uint HashCombine(uint seed, uint value) {
|
||||
return seed ^ (Hash(value) + 0x9e3779b9u + (seed<<6u) + (seed>>2u));
|
||||
}
|
||||
|
||||
uint Rand(inout uint seed) {
|
||||
seed = Hash(seed);
|
||||
return seed;
|
||||
}
|
||||
|
||||
float RandF(inout uint seed) {
|
||||
return float(Rand(seed)) * 2.3283064365386963e-10;
|
||||
}
|
||||
25
shaders/vk14/settings.glsl
Normal file
25
shaders/vk14/settings.glsl
Normal file
@@ -0,0 +1,25 @@
|
||||
// the settings of the game the shaders depend on (gfx.* in eu07.ini): specialization constants the renderer sets when it makes a
|
||||
// pipeline, the ids are the SPEC_* of rendering/vulkan14/vulkan14bindings.h. included by common.glsl after the constants
|
||||
#ifndef SETTINGS_GLSL
|
||||
#define SETTINGS_GLSL
|
||||
|
||||
#ifndef SPEC_OUTPUT_GAMMA
|
||||
#error "settings.glsl takes the ids of the specialization constants from common.glsl: include common.glsl instead"
|
||||
#endif
|
||||
|
||||
layout(constant_id = SPEC_SHADOWMAP_ENABLED) const bool SHADOWMAP_ENABLED = true;
|
||||
layout(constant_id = SPEC_ENVMAP_ENABLED) const bool ENVMAP_ENABLED = true;
|
||||
layout(constant_id = SPEC_MOTIONBLUR_ENABLED) const bool MOTIONBLUR_ENABLED = true;
|
||||
// the colour goes on to the post-processing; tonemapped by the shaders of the scene otherwise
|
||||
layout(constant_id = SPEC_POSTFX_ENABLED) const bool POSTFX_ENABLED = true;
|
||||
layout(constant_id = SPEC_EXTRAEFFECTS_ENABLED) const bool EXTRAEFFECTS_ENABLED = true;
|
||||
// whether the colour written to the window is encoded by the shader (FBOUT): the window has no srgb format (gfx.shadergamma yes)
|
||||
layout(constant_id = SPEC_OUTPUT_GAMMA) const bool OUTPUT_GAMMA = false;
|
||||
|
||||
// the colour written to the window
|
||||
vec4 FBOUT(vec4 x)
|
||||
{
|
||||
return (OUTPUT_GAMMA ? vec4(pow(x.rgb, vec3(1.0 / 2.2)), x.a) : x);
|
||||
}
|
||||
|
||||
#endif
|
||||
8
shaders/vk14/shadowmap.frag
Normal file
8
shaders/vk14/shadowmap.frag
Normal file
@@ -0,0 +1,8 @@
|
||||
#version 460 core
|
||||
#define STAGE_FRAGMENT 1
|
||||
#include "common.glsl"
|
||||
layout(location = 2) in vec2 f_coord;
|
||||
|
||||
void main()
|
||||
{
|
||||
}
|
||||
14
shaders/vk14/simpleuv.vert
Normal file
14
shaders/vk14/simpleuv.vert
Normal file
@@ -0,0 +1,14 @@
|
||||
#version 460 core
|
||||
#define STAGE_VERTEX 1
|
||||
#include "common.glsl"
|
||||
layout(location = 0) in vec3 v_vert;
|
||||
layout(location = 2) in vec2 v_coord;
|
||||
|
||||
layout(location = 2) out vec2 f_coord;
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = (projection * effective_modelview()) * vec4(v_vert, 1.0f);
|
||||
f_coord = v_coord;
|
||||
}
|
||||
16
shaders/vk14/sky_shoulder.glsl
Normal file
16
shaders/vk14/sky_shoulder.glsl
Normal file
@@ -0,0 +1,16 @@
|
||||
// the skydome vertex colours carry Perez luminance scaled by a fixed exposure
|
||||
// (see CSkyDome::SetExposure), so the circumsolar region and the horizon band
|
||||
// routinely land well above 1.0. hard-clipping them, as this shader used to do,
|
||||
// flattened everything within ~20 degrees of the sun - and most of the lower sky -
|
||||
// into one solid white patch. compress the top end instead: below the knee the
|
||||
// response is unchanged, above it it rolls off towards SKY_SHOULDER_WHITE, so the
|
||||
// brightness gradient around the sun survives and the patch keeps a soft edge.
|
||||
const float SKY_SHOULDER_KNEE = 0.25;
|
||||
const float SKY_SHOULDER_WHITE = 0.95;
|
||||
|
||||
vec3 sky_shoulder(vec3 color)
|
||||
{
|
||||
const float range = SKY_SHOULDER_WHITE - SKY_SHOULDER_KNEE;
|
||||
vec3 excess = max(color - vec3(SKY_SHOULDER_KNEE), vec3(0.0));
|
||||
return min(color, vec3(SKY_SHOULDER_KNEE)) + range * (vec3(1.0) - exp(-excess / range));
|
||||
}
|
||||
43
shaders/vk14/smoke.frag
Normal file
43
shaders/vk14/smoke.frag
Normal file
@@ -0,0 +1,43 @@
|
||||
#version 460 core
|
||||
#define STAGE_FRAGMENT 1
|
||||
#include "common.glsl"
|
||||
layout(location = 13) in vec4 f_color;
|
||||
layout(location = 2) in vec2 f_coord;
|
||||
layout(location = 3) in vec4 f_pos;
|
||||
|
||||
layout(location = 4) in vec4 f_clip_pos;
|
||||
layout(location = 5) in vec4 f_clip_future_pos;
|
||||
|
||||
#pragma texture(tex1, 0, sRGB_A)
|
||||
layout(set = MATERIAL_SET, binding = MATERIAL_TEXTURE_FIRST + 0) uniform sampler2D tex1;
|
||||
|
||||
#include "apply_fog.glsl"
|
||||
#include "tonemapping.glsl"
|
||||
|
||||
layout(location = 0) out vec4 out_color;
|
||||
#ifdef NO_MOTION_OUTPUT
|
||||
// a pass without the velocity target: the writes go nowhere
|
||||
vec4 out_motion;
|
||||
#else
|
||||
layout(location = 1) out vec4 out_motion;
|
||||
#endif
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 tex_color = texture(tex1, f_coord) * f_color;
|
||||
if (POSTFX_ENABLED)
|
||||
{
|
||||
out_color = vec4(apply_fog(tex_color.rgb), tex_color.a);
|
||||
}
|
||||
else
|
||||
{
|
||||
out_color = tonemap(vec4(apply_fog(tex_color.rgb), tex_color.a));
|
||||
}
|
||||
if (MOTIONBLUR_ENABLED)
|
||||
{
|
||||
vec2 a = (f_clip_future_pos.xy / f_clip_future_pos.w) * 0.5 + 0.5;;
|
||||
vec2 b = (f_clip_pos.xy / f_clip_pos.w) * 0.5 + 0.5;;
|
||||
|
||||
out_motion = vec4(a - b, 0.0f, tex_color.a * alpha_mult);
|
||||
}
|
||||
}
|
||||
25
shaders/vk14/smoke.vert
Normal file
25
shaders/vk14/smoke.vert
Normal file
@@ -0,0 +1,25 @@
|
||||
#version 460 core
|
||||
#define STAGE_VERTEX 1
|
||||
#include "common.glsl"
|
||||
layout(location = 0) in vec3 v_vert;
|
||||
layout(location = 1) in vec4 v_color;
|
||||
layout(location = 2) in vec2 v_coord;
|
||||
|
||||
layout(location = 3) out vec4 f_pos;
|
||||
layout(location = 13) out vec4 f_color;
|
||||
layout(location = 2) out vec2 f_coord;
|
||||
|
||||
layout(location = 4) out vec4 f_clip_pos;
|
||||
layout(location = 5) out vec4 f_clip_future_pos;
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
f_pos = modelview * vec4(v_vert, 1.0f);
|
||||
f_clip_pos = (projection * modelview) * vec4(v_vert, 1.0f);
|
||||
f_clip_future_pos = (projection * future * modelview) * vec4(v_vert, 1.0f);
|
||||
|
||||
gl_Position = f_clip_pos;
|
||||
f_coord = v_coord;
|
||||
f_color = v_color;
|
||||
}
|
||||
154
shaders/vk14/tonemapping.glsl
Normal file
154
shaders/vk14/tonemapping.glsl
Normal file
@@ -0,0 +1,154 @@
|
||||
#include "common.glsl"
|
||||
|
||||
const float pureWhite = 1.0;
|
||||
|
||||
vec3 reinhard(vec3 x)
|
||||
{
|
||||
// return x / (x + vec3(1.0));
|
||||
|
||||
// Reinhard tonemapping operator.
|
||||
// see: "Photographic Tone Reproduction for Digital Images", eq. 4
|
||||
float luminance = dot(x, vec3(0.2126, 0.7152, 0.0722));
|
||||
float mappedLuminance = (luminance * (1.0 + luminance/(pureWhite*pureWhite))) / (1.0 + luminance);
|
||||
// Scale color by ratio of average luminances.
|
||||
return (mappedLuminance / luminance) * x;
|
||||
}
|
||||
|
||||
// https://knarkowicz.wordpress.com/2016/01/06/aces-filmic-tone-mapping-curve/
|
||||
vec3 ACESFilm(vec3 x)
|
||||
{
|
||||
float a = 2.51f;
|
||||
float b = 0.03f;
|
||||
float c = 2.43f;
|
||||
float d = 0.59f;
|
||||
float e = 0.14f;
|
||||
return (x*(a*x+b))/(x*(c*x+d)+e);
|
||||
}
|
||||
|
||||
// https://www.slideshare.net/ozlael/hable-john-uncharted2-hdr-lighting
|
||||
vec3 filmicF(vec3 x)
|
||||
{
|
||||
float A = 0.22f;
|
||||
float B = 0.30f;
|
||||
float C = 0.10f;
|
||||
float D = 0.20f;
|
||||
float E = 0.01f;
|
||||
float F = 0.30f;
|
||||
return ((x*(A*x+C*B)+D*E)/(x*(A*x+B)+D*F)) - E/F;
|
||||
}
|
||||
|
||||
vec3 filmic(vec3 x)
|
||||
{
|
||||
return filmicF(x) / filmicF(vec3(11.2f));
|
||||
}
|
||||
|
||||
|
||||
// AgX tonemapping based on nxrighthere / Missing Deadlines implementation.
|
||||
// 0: Default, 1: Golden, 2: Punchy
|
||||
#ifndef AGX_LOOK
|
||||
#define AGX_LOOK 0
|
||||
#endif
|
||||
|
||||
vec3 AgxDefaultContrastApprox(vec3 x)
|
||||
{
|
||||
vec3 x2 = x * x;
|
||||
vec3 x4 = x2 * x2;
|
||||
|
||||
return 15.5 * x4 * x2
|
||||
- 40.14 * x4 * x
|
||||
+ 31.96 * x4
|
||||
- 6.868 * x2 * x
|
||||
+ 0.4298 * x2
|
||||
+ 0.1191 * x
|
||||
- 0.00232;
|
||||
}
|
||||
|
||||
vec3 Agx(vec3 val)
|
||||
{
|
||||
mat3 agx_mat = mat3(
|
||||
0.842479062253094, 0.0784335999999992, 0.0792237451477643,
|
||||
0.0423282422610123, 0.878468636469772, 0.0791661274605434,
|
||||
0.0423756549057051, 0.0784336, 0.879142973793104
|
||||
);
|
||||
|
||||
// DEFAULT_LOG2_MIN = -6.0
|
||||
// DEFAULT_LOG2_MAX = +4.5
|
||||
// MIDDLE_GRAY = 0.18
|
||||
// log2(pow(2, VALUE) * MIDDLE_GRAY)
|
||||
const float min_ev = -8.47393;
|
||||
const float max_ev = 2.026069;
|
||||
const float agx_eps = 1e-6;
|
||||
|
||||
// Input transform (inset)
|
||||
val = agx_mat * val;
|
||||
|
||||
// Log2 space encoding. max() avoids -INF/NaN for zero/negative inputs.
|
||||
val = clamp(log2(max(val, vec3(agx_eps))), min_ev, max_ev);
|
||||
val = (val - min_ev) / (max_ev - min_ev);
|
||||
|
||||
// Apply sigmoid function approximation.
|
||||
return AgxDefaultContrastApprox(val);
|
||||
}
|
||||
|
||||
vec3 AgxEotf(vec3 val)
|
||||
{
|
||||
mat3 agx_mat_inv = mat3(
|
||||
1.19687900512017, -0.0980208811401368, -0.0990297440797205,
|
||||
-0.0528968517574562, 1.15190312990417, -0.0989611768448433,
|
||||
-0.0529716355144438, -0.0980434501171241, 1.15107367264116
|
||||
);
|
||||
|
||||
// Inverse input transform (outset)
|
||||
val = agx_mat_inv * val;
|
||||
|
||||
return max(val, vec3(0.0));
|
||||
}
|
||||
|
||||
vec3 AgxLook(vec3 val)
|
||||
{
|
||||
vec3 lw = vec3(0.2126, 0.7152, 0.0722);
|
||||
float luma = dot(val, lw);
|
||||
|
||||
vec3 offset = vec3(0.0);
|
||||
vec3 slope = vec3(1.0);
|
||||
vec3 power = vec3(1.6);
|
||||
float sat = 0.9;
|
||||
|
||||
#if AGX_LOOK == 1
|
||||
// Golden
|
||||
slope = vec3(1.0, 0.9, 0.5);
|
||||
power = vec3(0.8);
|
||||
sat = 0.8;
|
||||
#elif AGX_LOOK == 2
|
||||
// Punchy
|
||||
slope = vec3(1.0);
|
||||
power = vec3(1.35);
|
||||
sat = 1.1;
|
||||
#endif
|
||||
|
||||
// ASC CDL
|
||||
val = pow(max(val * slope + offset, vec3(0.0)), power);
|
||||
return vec3(luma) + sat * (val - vec3(luma));
|
||||
}
|
||||
|
||||
vec3 ApplyAgX(vec3 linearColorRec709)
|
||||
{
|
||||
linearColorRec709 = Agx(linearColorRec709);
|
||||
linearColorRec709 = AgxLook(linearColorRec709);
|
||||
linearColorRec709 = AgxEotf(linearColorRec709);
|
||||
return linearColorRec709;
|
||||
}
|
||||
|
||||
vec4 tonemap(vec4 x)
|
||||
{
|
||||
// Use AgX by default. Reinhard and ACES above are kept for reference.
|
||||
|
||||
// Last-line-of-defense sanitize so NaN/Inf/negative HDR values do not
|
||||
// escape into log2()/pow() and produce black flashes or invalid output.
|
||||
vec3 hdr = x.rgb;
|
||||
hdr = mix(hdr, vec3(0.0), vec3(any(isnan(hdr)) || any(isinf(hdr))));
|
||||
hdr = max(hdr, vec3(0.0));
|
||||
return FBOUT(vec4(ApplyAgX(hdr), x.a));
|
||||
//return FBOUT(vec4(ACESFilm(hdr), x.a));
|
||||
//return FBOUT(vec4(reinhard(x.rgb), x.a));
|
||||
}
|
||||
205
shaders/vk14/trackblend.glsl
Normal file
205
shaders/vk14/trackblend.glsl
Normal file
@@ -0,0 +1,205 @@
|
||||
// a track drawn with the textures of the tracks joined at its ends blended in near them (world/TrackBlend.h): the weights of the
|
||||
// tracks joined at the ends p1, p2 and p4 of a switch in UserData.yzw, their textures in diffuse1..3, normalmap1..3, faded into
|
||||
// the texture of the track. the including shader declares the textures and sets:
|
||||
// TRACKBLEND_NORMALMAP with the normal maps of the four, lit as the shader of the material of the track: param[2].x 0 as
|
||||
// mat_default, 1 normalmap, 2 sunlessnormalmap, 3 shadowlessnormalmap
|
||||
// TRACKBLEND_SPECGLOSS the specgloss map of the track itself as well, the textures of the ends p1 and p2 alone (no room
|
||||
// for a third set of them)
|
||||
// TRACKBLEND_PARALLAX with the normal maps, as mat_parallax: each texture shifted by the heights in its own normal map
|
||||
layout(location = 0) in vec3 f_normal;
|
||||
layout(location = 2) in vec2 f_coord;
|
||||
layout(location = 3) in vec4 f_pos;
|
||||
#ifdef TRACKBLEND_NORMALMAP
|
||||
layout(location = 8) in mat3 f_tbn;
|
||||
#endif
|
||||
#ifdef TRACKBLEND_PARALLAX
|
||||
layout(location = 6) in vec3 TangentFragPos;
|
||||
#endif
|
||||
|
||||
layout(location = 4) in vec4 f_clip_pos;
|
||||
layout(location = 5) in vec4 f_clip_future_pos;
|
||||
|
||||
#include "common.glsl"
|
||||
|
||||
#pragma param(color, 0, 0, 4, diffuse)
|
||||
#pragma param(diffuse, 1, 0, 1, diffuse)
|
||||
#pragma param(specular, 1, 1, 1, specular)
|
||||
#pragma param(reflection, 1, 2, 1, zero)
|
||||
#pragma param(glossiness, 1, 3, 1, glossiness)
|
||||
#pragma param(blendlighting, 2, 0, 1, zero)
|
||||
|
||||
layout(location = 0) out vec4 out_color;
|
||||
#ifdef NO_MOTION_OUTPUT
|
||||
// a pass without the velocity target: the writes go nowhere
|
||||
vec4 out_motion;
|
||||
#else
|
||||
layout(location = 1) out vec4 out_motion;
|
||||
#endif
|
||||
|
||||
#include "light_common.glsl"
|
||||
#include "apply_fog.glsl"
|
||||
#include "tonemapping.glsl"
|
||||
|
||||
#ifdef TRACKBLEND_PARALLAX
|
||||
// the texture coordinates shifted by the heights (b) of the normal map, as ParallaxMapping() of mat_parallax.frag
|
||||
vec2 parallax_coord(sampler2D heights, vec2 coord, vec3 viewdir, vec2 dcoorddx, vec2 dcoorddy)
|
||||
{
|
||||
float pos_len = length(f_pos.xyz);
|
||||
if (pos_len > 100.0)
|
||||
return coord;
|
||||
float fade = 1.0 - smoothstep(80.0, 100.0, pos_len);
|
||||
if (EXTRAEFFECTS_ENABLED)
|
||||
{
|
||||
const float minLayers = 8.0;
|
||||
const float maxLayers = 32.0;
|
||||
float LayersWeight = pos_len / 20.0;
|
||||
vec2 currentTexCoords = coord;
|
||||
float currentDepthMapValue = textureGrad(heights, currentTexCoords, dcoorddx, dcoorddy).b;
|
||||
LayersWeight = min(abs(dot(vec3(0.0, 0.0, 1.0), viewdir)), LayersWeight);
|
||||
float numLayers = mix(maxLayers, minLayers, clamp(LayersWeight, 0.0, 1.0));
|
||||
float layerDepth = 1.0 / numLayers;
|
||||
float currentLayerDepth = 0.0;
|
||||
vec2 P = viewdir.xy * param[2].y * fade;
|
||||
vec2 deltaTexCoords = P / numLayers;
|
||||
while (currentLayerDepth < currentDepthMapValue)
|
||||
{
|
||||
currentTexCoords -= deltaTexCoords;
|
||||
currentDepthMapValue = textureGrad(heights, currentTexCoords, dcoorddx, dcoorddy).b;
|
||||
currentLayerDepth += layerDepth;
|
||||
}
|
||||
vec2 prevTexCoords = currentTexCoords + deltaTexCoords;
|
||||
float afterDepth = currentDepthMapValue - currentLayerDepth;
|
||||
float beforeDepth = textureGrad(heights, prevTexCoords, dcoorddx, dcoorddy).b - currentLayerDepth + layerDepth;
|
||||
float weight = afterDepth / (afterDepth - beforeDepth);
|
||||
return prevTexCoords * weight + currentTexCoords * (1.0 - weight);
|
||||
}
|
||||
else
|
||||
{
|
||||
float height = textureGrad(heights, coord, dcoorddx, dcoorddy).b;
|
||||
vec2 p = viewdir.xy / viewdir.z * (height * (param[2].y - param[2].z) * 0.2) * fade;
|
||||
return coord - p;
|
||||
}
|
||||
}
|
||||
// each texture at the coordinates shifted by the heights of its own normal map
|
||||
#define TRACKBLEND_COORD(heights) parallax_coord(heights, f_coord, viewdir, dx, dy)
|
||||
#else
|
||||
#define TRACKBLEND_COORD(heights) f_coord
|
||||
#endif
|
||||
|
||||
void main()
|
||||
{
|
||||
// how far the fragment is into the track from the ends, in the lengths of their blending (track_blend::blending::weigh()):
|
||||
// from -100 down where the track joined there doesn't blend back and its texture goes all the way to the joint, 10000 where
|
||||
// nothing's blended at the end
|
||||
#ifdef TRACKBLEND_SPECGLOSS
|
||||
vec3 along = vec3(UserData.yz, 10000.0);
|
||||
#else
|
||||
vec3 along = UserData.yzw;
|
||||
#endif
|
||||
vec3 single = vec3(lessThan(along, vec3(-50.0)));
|
||||
vec3 fraction = mix(along, -100.0 - along, single);
|
||||
vec3 weights = mix(vec3(0.5), vec3(1.0), single) * clamp(1.0 - fraction, 0.0, 1.0);
|
||||
float total = weights.x + weights.y + weights.z;
|
||||
if (total > 1.0)
|
||||
{
|
||||
weights /= total;
|
||||
total = 1.0;
|
||||
}
|
||||
// the gradients are taken outside the branches the textures are sampled in
|
||||
vec2 dx = dFdx(f_coord);
|
||||
vec2 dy = dFdy(f_coord);
|
||||
#ifdef TRACKBLEND_PARALLAX
|
||||
vec3 viewdir = normalize(vec3(0.0) - TangentFragPos);
|
||||
#endif
|
||||
vec2 coord = TRACKBLEND_COORD(normalmap);
|
||||
vec4 tex_color = textureGrad(diffuse, coord, dx, dy);
|
||||
#ifdef TRACKBLEND_NORMALMAP
|
||||
vec4 tex_normal = textureGrad(normalmap, coord, dx, dy);
|
||||
#endif
|
||||
if (total > 0.0)
|
||||
{
|
||||
vec4 blended = tex_color * (1.0 - total);
|
||||
#ifdef TRACKBLEND_NORMALMAP
|
||||
vec4 blendednormal = tex_normal * (1.0 - total);
|
||||
#endif
|
||||
if (weights.x > 0.0)
|
||||
{
|
||||
vec2 coord1 = TRACKBLEND_COORD(normalmap1);
|
||||
blended += textureGrad(diffuse1, coord1, dx, dy) * weights.x;
|
||||
#ifdef TRACKBLEND_NORMALMAP
|
||||
blendednormal += textureGrad(normalmap1, coord1, dx, dy) * weights.x;
|
||||
#endif
|
||||
}
|
||||
if (weights.y > 0.0)
|
||||
{
|
||||
vec2 coord2 = TRACKBLEND_COORD(normalmap2);
|
||||
blended += textureGrad(diffuse2, coord2, dx, dy) * weights.y;
|
||||
#ifdef TRACKBLEND_NORMALMAP
|
||||
blendednormal += textureGrad(normalmap2, coord2, dx, dy) * weights.y;
|
||||
#endif
|
||||
}
|
||||
#ifndef TRACKBLEND_SPECGLOSS
|
||||
if (weights.z > 0.0)
|
||||
{
|
||||
vec2 coord3 = TRACKBLEND_COORD(normalmap3);
|
||||
blended += textureGrad(diffuse3, coord3, dx, dy) * weights.z;
|
||||
#ifdef TRACKBLEND_NORMALMAP
|
||||
blendednormal += textureGrad(normalmap3, coord3, dx, dy) * weights.z;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
tex_color = blended;
|
||||
#ifdef TRACKBLEND_NORMALMAP
|
||||
tex_normal = blendednormal;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool alphatestfail = ( opacity >= 0.0 ? (tex_color.a < opacity) : (tex_color.a >= -opacity) );
|
||||
if(alphatestfail)
|
||||
discard;
|
||||
|
||||
vec3 fragcolor = ambient;
|
||||
#ifdef TRACKBLEND_NORMALMAP
|
||||
vec3 normal;
|
||||
normal.xy = (tex_normal.rg * 2.0 - 1.0);
|
||||
normal.z = sqrt(1.0 - clamp((dot(normal.xy, normal.xy)), 0.0, 1.0));
|
||||
vec3 fragnormal = normalize(f_tbn * normalize(normal.xyz));
|
||||
float reflectivity = param[1].z * tex_normal.a;
|
||||
#ifdef TRACKBLEND_SPECGLOSS
|
||||
vec4 tex_specgloss = textureGrad(specgloss, coord, dx, dy);
|
||||
float specularity = tex_specgloss.r;
|
||||
glossiness = tex_specgloss.g * abs(param[1].w);
|
||||
metalic = tex_specgloss.b;
|
||||
#else
|
||||
float specularity = (tex_color.r + tex_color.g + tex_color.b) * 0.5;
|
||||
legacy_gloss();
|
||||
#endif
|
||||
int lighting = int(param[2].x + 0.5);
|
||||
if (lighting == 2)
|
||||
fragcolor = apply_lights_sunless(fragcolor, fragnormal, tex_color.rgb, reflectivity, specularity, shadow_tone);
|
||||
else
|
||||
fragcolor = apply_lights(fragcolor, fragnormal, tex_color.rgb, reflectivity, specularity, (lighting == 3 ? 1.0 : shadow_tone));
|
||||
#else
|
||||
vec3 fragnormal = normalize(f_normal);
|
||||
matte = true;
|
||||
|
||||
fragcolor = apply_lights(fragcolor, fragnormal, tex_color.rgb, 0.0, 0.0, shadow_tone);
|
||||
#endif
|
||||
vec4 color = vec4(apply_fog(fragcolor), tex_color.a * alpha_mult);
|
||||
if (POSTFX_ENABLED)
|
||||
{
|
||||
out_color = color;
|
||||
}
|
||||
else
|
||||
{
|
||||
out_color = tonemap(color);
|
||||
}
|
||||
|
||||
if (MOTIONBLUR_ENABLED)
|
||||
{
|
||||
vec2 a = (f_clip_future_pos.xy / f_clip_future_pos.w) * 0.5 + 0.5;
|
||||
vec2 b = (f_clip_pos.xy / f_clip_pos.w) * 0.5 + 0.5;
|
||||
|
||||
out_motion = vec4(a - b, 0.0f, tex_color.a * alpha_mult);
|
||||
}
|
||||
}
|
||||
39
shaders/vk14/traction.frag
Normal file
39
shaders/vk14/traction.frag
Normal file
@@ -0,0 +1,39 @@
|
||||
#version 460 core
|
||||
#define STAGE_FRAGMENT 1
|
||||
#include "common.glsl"
|
||||
|
||||
layout(location = 3) in vec4 f_pos;
|
||||
layout(location = 4) in vec4 f_clip_pos;
|
||||
layout(location = 5) in vec4 f_clip_future_pos;
|
||||
|
||||
layout(location = 0) out vec4 out_color;
|
||||
#ifdef NO_MOTION_OUTPUT
|
||||
// a pass without the velocity target: the writes go nowhere
|
||||
vec4 out_motion;
|
||||
#else
|
||||
layout(location = 1) out vec4 out_motion;
|
||||
#endif
|
||||
|
||||
#include "tonemapping.glsl"
|
||||
#include "apply_fog.glsl"
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 color = vec4(apply_fog(pow(param[0].rgb, vec3(2.2))), param[0].a);
|
||||
if (POSTFX_ENABLED)
|
||||
{
|
||||
out_color = color;
|
||||
}
|
||||
else
|
||||
{
|
||||
out_color = tonemap(color);
|
||||
}
|
||||
|
||||
if (MOTIONBLUR_ENABLED)
|
||||
{
|
||||
vec2 a = (f_clip_future_pos.xy / f_clip_future_pos.w) * 0.5 + 0.5;;
|
||||
vec2 b = (f_clip_pos.xy / f_clip_pos.w) * 0.5 + 0.5;;
|
||||
|
||||
out_motion = vec4(a - b, 0.0f, 0.0f);
|
||||
}
|
||||
}
|
||||
20
shaders/vk14/traction.vert
Normal file
20
shaders/vk14/traction.vert
Normal file
@@ -0,0 +1,20 @@
|
||||
#version 460 core
|
||||
#define STAGE_VERTEX 1
|
||||
#include "common.glsl"
|
||||
layout(location = 0) in vec3 v_vert;
|
||||
layout(location = 1) in vec3 v_normal;
|
||||
layout(location = 2) in vec2 v_coord;
|
||||
|
||||
|
||||
layout(location = 4) out vec4 f_clip_pos;
|
||||
layout(location = 5) out vec4 f_clip_future_pos;
|
||||
layout(location = 3) out vec4 f_pos;
|
||||
|
||||
void main()
|
||||
{
|
||||
f_pos = modelview * vec4(v_vert, 1.0f);
|
||||
f_clip_pos = (projection * modelview) * vec4(v_vert, 1.0f);
|
||||
f_clip_future_pos = (projection * future * modelview) * vec4(v_vert, 1.0f);
|
||||
|
||||
gl_Position = f_clip_pos;
|
||||
}
|
||||
19
shaders/vk14/vbocolor.vert
Normal file
19
shaders/vk14/vbocolor.vert
Normal file
@@ -0,0 +1,19 @@
|
||||
#version 460 core
|
||||
#define STAGE_VERTEX 1
|
||||
#include "common.glsl"
|
||||
layout(location = 0) in vec3 v_vert;
|
||||
layout(location = 1) in vec3 v_color;
|
||||
|
||||
layout(location = 13) out vec3 f_color;
|
||||
layout(location = 3) out vec4 f_pos;
|
||||
layout(location = 4) out vec4 f_clip_pos;
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
f_pos = modelview * vec4(v_vert, 1.0);
|
||||
f_clip_pos = (projection * modelview) * vec4(v_vert, 1.0);
|
||||
f_color = pow(v_color, vec3(1.0));
|
||||
|
||||
gl_Position = f_clip_pos;
|
||||
}
|
||||
55
shaders/vk14/vertex.vert
Normal file
55
shaders/vk14/vertex.vert
Normal file
@@ -0,0 +1,55 @@
|
||||
#version 460 core
|
||||
#define STAGE_VERTEX 1
|
||||
#include "common.glsl"
|
||||
layout(location = 0) in vec3 v_vert;
|
||||
layout(location = 1) in vec3 v_normal;
|
||||
layout(location = 2) in vec2 v_coord;
|
||||
layout(location = 3) in vec4 v_tangent;
|
||||
layout(location = 4) in vec4 v_userdata;
|
||||
|
||||
|
||||
// the depth prepass (depthprepass.vert) works the position out the same way, and has to get the same depth
|
||||
invariant gl_Position;
|
||||
|
||||
layout(location = 0) out vec3 f_normal;
|
||||
layout(location = 1) flat out vec3 f_normal_raw;
|
||||
layout(location = 2) out vec2 f_coord;
|
||||
layout(location = 3) out vec4 f_pos;
|
||||
layout(location = 8) out mat3 f_tbn;
|
||||
|
||||
layout(location = 4) out vec4 f_clip_pos;
|
||||
layout(location = 5) out vec4 f_clip_future_pos;
|
||||
|
||||
//out vec3 TangentLightPos;
|
||||
//out vec3 TangentViewPos;
|
||||
layout(location = 6) out vec3 TangentFragPos;
|
||||
layout(location = 7) out vec4 UserData;
|
||||
|
||||
void main()
|
||||
{
|
||||
mat4 mv = effective_modelview();
|
||||
mat3 mvn = effective_modelviewnormal();
|
||||
|
||||
f_normal = normalize(mvn * v_normal);
|
||||
f_normal_raw = v_normal;
|
||||
f_coord = v_coord;
|
||||
f_pos = mv * vec4(v_vert, 1.0);
|
||||
f_clip_pos = projection * f_pos;
|
||||
f_clip_future_pos = (projection * future) * f_pos;
|
||||
|
||||
gl_Position = f_clip_pos;
|
||||
gl_PointSize = param[1].x;
|
||||
|
||||
vec3 N = f_normal;
|
||||
vec3 T = mvn * v_tangent.xyz;
|
||||
T = normalize(T - N * dot(N, T));
|
||||
// w is -1 where the texture is mirrored (calculate_tangents()), the bitangent turns with it
|
||||
vec3 B = cross(N, T) * (v_tangent.w < 0.0 ? -1.0 : 1.0);
|
||||
f_tbn = mat3(T, B, N);
|
||||
|
||||
mat3 TBN = transpose(f_tbn);
|
||||
// TangentLightPos = TBN * f_light_pos.xyz;
|
||||
// TangentViewPos = TBN * vec3(0.0, 0.0, 0.0);
|
||||
TangentFragPos = TBN * f_pos.xyz;
|
||||
UserData = v_userdata;
|
||||
}
|
||||
10
shaders/vk14/vertexonly.vert
Normal file
10
shaders/vk14/vertexonly.vert
Normal file
@@ -0,0 +1,10 @@
|
||||
#version 460 core
|
||||
#define STAGE_VERTEX 1
|
||||
#include "common.glsl"
|
||||
layout(location = 0) in vec3 v_vert;
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = (projection * effective_modelview()) * vec4(v_vert, 1.0);
|
||||
}
|
||||
Reference in New Issue
Block a user