#version 450 layout (set = 0, binding = 1) uniform sampler2D Texture; layout (set = 0, binding = 2) uniform sampler2D GlowMap; layout (set = 0, binding = 3) uniform sampler2D LightMap; layout (set = 0, binding = 4) uniform sampler2DArray SkySheet; layout (set = 0, binding = 5) uniform samplerCube SkyCube; layout (push_constant) uniform PushConstants { layout (offset = 64) vec4 fog; float time; }; layout (location = 0) in vec4 tl_st; layout (location = 1) in vec3 direction; layout (location = 2) in vec3 normal; layout (location = 0) out vec4 frag_color; layout (location = 1) out vec4 frag_normal; layout (constant_id = 0) const bool doWarp = false; layout (constant_id = 1) const bool doLight = true; layout (constant_id = 2) const bool doSkyCube = false; layout (constant_id = 3) const bool doSkySheet = false; const float PI = 3.14159265; const float SPEED = 20.0; const float CYCLE = 128.0; const float FACTOR = PI * 2.0 / CYCLE; const vec2 BIAS = vec2 (1.0, 1.0); const float SCALE = 8.0; vec2 warp_st (vec2 st, float time) { vec2 angle = st.ts * CYCLE / 2.0; vec2 phase = vec2 (time, time) * SPEED; return st + (sin ((angle + phase) * FACTOR) + BIAS) / SCALE; } vec4 fogBlend (vec4 color) { float az = fog.a * gl_FragCoord.z / gl_FragCoord.w; vec3 fog_color = fog.rgb; float fog_factor = exp (-az * az); return vec4 (mix (fog_color.rgb, color.rgb, fog_factor), color.a); } vec4 sky_sheet (vec3 dir, float time) { float len; vec2 flow = vec2 (1.0, 1.0); vec2 base; vec3 st1, st2; vec4 c1, c2, c; dir.z *= 3.0; len = dot (dir, dir); len = SCALE * inversesqrt (len); base = dir.yx * vec2(1.0, -1.0) * len; st1 = vec3 (base + flow * time / 8.0, 0); st2 = vec3 (base + flow * time / 16.0, 1); c1 = texture (SkySheet, st1); c2 = texture (SkySheet, st2); c = vec4 (mix (c2.rgb, c1.rgb, c1.a), max (c1.a, c2.a)); return c; } vec4 sky_cube (vec3 dir, float time) { // NOTE: quake's world is right-handed with Z up and X forward, but // Vulkan's cube maps are left-handed with Y up and Z forward. The // rotation to X foward is done by the Sky matrix so all that's left // to do here is swizzle the Y and Z coordinates return texture (SkyCube, dir.xzy); } vec4 sky_color (vec3 dir, float time) { if (!doSkySheet) { return vec4 (1, 0, 1, 1); //return sky_cube (dir, time); } if (!doSkyCube) { return sky_sheet (dir, time); } else { // can see through the sheet (may look funny when looking down) // maybe have 4 sheet layers instead of 2? vec4 c1 = sky_sheet (dir, time); vec4 c2 = sky_cube (dir, time); return vec4 (mix (c2.rgb, c1.rgb, c1.a), max (c1.a, c2.a)); return vec4 (1, 0, 1, 1); } } void main (void) { vec4 c; vec2 t_st = tl_st.xy; vec2 l_st = tl_st.zw; if (doWarp) { t_st = warp_st (t_st, time); } if (doSkyCube || doSkySheet) { c = sky_color (direction, time); } else { c = texture (Texture, t_st); if (doLight) { c *= vec4 (texture (LightMap, l_st).xyz, 1); } c += texture (GlowMap, t_st); } frag_color = c;//fogBlend (c); frag_normal = vec4 (normal, 0); }