init
This commit is contained in:
commit
87bff164f1
416 files changed
+279512
No files matched your search
@@ -0,0 +1,112 @@
|
||||
#version 450
|
||||
#extension GL_GOOGLE_include_directive : require
|
||||
layout(local_size_x = 8, local_size_y = 8) in;
|
||||
#include "common.glsl"
|
||||
|
||||
// Fog of war, as FogOfWarRadiusSystem (lambda 00d8f000 -> 00aeef70): a persistent map of the world in 32 x 32 pixel texels (the engine's fog byte, 255 = fog, 0 = clear;
|
||||
// kept here as its complement, the "clear" amount, so that the zeroed buffer is all fog). It only clears: what was seen stays seen. Every frame, for the player
|
||||
// (FogOfWarRadiusComponent radius 200, data/entities/misc/fogofwar_radius.xml; the position lifted by 4 x uniform(0, 3) pixels):
|
||||
// * the 3 x 3 texels around it: fog = min(fog, max(fog - 3 d, 255 d)), d = the distance from the texel centre in texels;
|
||||
// * 36 rays (10 degrees apart) of the radius, stopped by the terrain: at 0, 1/4, 2/4 and 3/4 of the free part of each ray the texel loses 5 of fog
|
||||
// (a texel crossed by several rays loses more; 51 frames clear one entirely).
|
||||
// render.comp reads the map bilinearly (the texel centres at 32 n + 16) as post_final.frag reads tex_fog.
|
||||
struct Ent { vec4 a, box, mv, ai; ivec4 st; vec4 hp; ivec4 x; ivec4 rg; ivec4 rg2; ivec4 aux; vec4 ex; vec4 ex2; ivec4 ex3; vec4 ex4; vec4 ex5; vec4 ex6; vec4 ex7; ivec4 ex8; vec4 ex9; vec4 ex10; vec4 ex11; vec4 ex12, ex13, ex14, ex15, ex16, ex17, ex18, ex19; };
|
||||
layout(std430, set = 0, binding = 22) readonly buffer Ents { Ent ents[]; };
|
||||
layout(std430, set = 0, binding = 49) buffer Fog { uint fog[]; }; // per texel: 255 - the fog byte (the clear amount)
|
||||
|
||||
layout(std430, set = 0, binding = 8) readonly buffer Tables { uint tbl[]; }; // after the fire palettes: the biome map's width, height and fog_of_war_type per tile (main.cpp)
|
||||
#include "biome_mods.glsl"
|
||||
uint fog_type_at(vec2 w) { // 0 default, 1 HEAVY_CLEAR_AT_PLAYER, 2 HEAVY_CLEAR_WITH_MAGIC, 3 HEAVY_NO_CLEAR; outside the map: the default
|
||||
const uint n = mats[mats.length() - 1u].w;
|
||||
const uint fb = 1024u + 9u * n + 132u + n;
|
||||
const int bw = int(tbl[fb]), bh = int(tbl[fb + 1u]);
|
||||
const ivec2 t = ivec2(floor(w / 512.0)) + ivec2(35, 14);
|
||||
if (bw <= 0 || t.x < 0 || t.y < 0 || t.x >= bw || t.y >= bh) return 0u;
|
||||
return tbl[fb + 2u + uint(t.y * bw + t.x)];
|
||||
}
|
||||
const int FOG_TW = 1152, FOG_TH = 896, FOG_OX = 18432, FOG_OY = 14336; // texels of 32 pixels from the world origin (-18432, -14336)
|
||||
const float RADIUS = 256.0; // the player's (component_documentation: "256 is the default player has"; the X-ray card's fogofwar_radius.xml has 200)
|
||||
|
||||
bool solid_at(ivec2 w) { // (world cell; outside the window: open)
|
||||
const ivec2 p = w - ivec2(pc.view_x, pc.view_y);
|
||||
if (p.x < 0 || p.y < 0 || p.x >= pc.gw || p.y >= pc.gh) return false;
|
||||
const uint m = cell_mat(cells[p.y * pc.gw + p.x]);
|
||||
return m != 0u && (mflags(m) & (F_STATIC | F_SAND)) != 0u;
|
||||
}
|
||||
int texel_index(vec2 w) {
|
||||
const ivec2 t = ivec2(floor((w + vec2(FOG_OX, FOG_OY)) / 32.0));
|
||||
if (t.x < 0 || t.y < 0 || t.x >= FOG_TW || t.y >= FOG_TH) return -1;
|
||||
return t.y * FOG_TW + t.x;
|
||||
}
|
||||
|
||||
// the solid share of the 64 x 64 pixel region of a point, 0..255 (the coarse map of the world the 3 x 3 rule reads; outside the window: 0)
|
||||
float coarse_at(vec2 w) {
|
||||
const ivec2 r0 = ivec2(floor(w / 64.0)) * 64;
|
||||
int n = 0, tot = 0;
|
||||
for (int y = 2; y < 64; y += 4) for (int x = 2; x < 64; x += 4) {
|
||||
const ivec2 p = r0 + ivec2(x, y) - ivec2(pc.view_x, pc.view_y);
|
||||
if (p.x < 0 || p.y < 0 || p.x >= pc.gw || p.y >= pc.gh) continue;
|
||||
++tot;
|
||||
const uint m = cell_mat(cells[p.y * pc.gw + p.x]);
|
||||
if (m != 0u && (mflags(m) & (F_STATIC | F_SAND)) != 0u) ++n;
|
||||
}
|
||||
return tot > 0 ? 255.0 * float(n) / float(tot) : 0.0;
|
||||
}
|
||||
|
||||
void main() {
|
||||
// one workgroup per source: 0 the player (radius 256), then the other FogOfWarRadiusComponents (main.cpp, after the holes in the tables)
|
||||
const uint t = gl_LocalInvocationIndex;
|
||||
if (pc.pass_ != 0) return;
|
||||
if (t >= 45u) { // 00c42d30: the biome's fog_of_war_delta (FOG_OF_WAR_REAPPEARS: 2) - every frame the fog bytes of the 17 x 17 texels around the player (ceil(427 / 32 x 0.5) + 1 = 8 each way) gain it
|
||||
if (gl_WorkGroupID.x != 0u || (ents[0].st.w & 8) != 0) return;
|
||||
const vec2 P0 = ents[0].a.xy;
|
||||
const int delta = int(bitfieldExtract(int(bm_bytes(P0)), 0, 8)); // (a signed byte)
|
||||
if (delta == 0) return;
|
||||
for (uint k = t - 45u; k < 289u; k += 19u) {
|
||||
const int ti = texel_index(P0 + vec2(float(int(k % 17u) - 8), float(int(k / 17u) - 8)) * 32.0);
|
||||
if (ti < 0) continue;
|
||||
uint old = fog[ti];
|
||||
for (int tries = 0; tries < 4; ++tries) { const uint nv = uint(clamp(int(min(old, 255u)) - delta, 0, 255)); const uint got = atomicCompSwap(fog[ti], old, nv); if (got == old) break; old = got; } // (fog[] holds 255 - the fog byte)
|
||||
}
|
||||
return;
|
||||
}
|
||||
const uint wg = gl_WorkGroupID.x;
|
||||
vec2 P;
|
||||
float R = RADIUS;
|
||||
if (wg == 0u) {
|
||||
if ((ents[0].st.w & 8) != 0) return; // (dead)
|
||||
P = ents[0].a.xy;
|
||||
} else {
|
||||
const uint n = mats[mats.length() - 1u].w;
|
||||
const uint sb = 1024u + 9u * n + 132u + n + 2u + 8192u + 1u + 64u * 6u;
|
||||
if (int(wg) > int(uintBitsToFloat(tbl[sb]))) return;
|
||||
const uint o = sb + 1u + (wg - 1u) * 3u;
|
||||
P = vec2(uintBitsToFloat(tbl[o]), uintBitsToFloat(tbl[o + 1u]));
|
||||
R = uintBitsToFloat(tbl[o + 2u]);
|
||||
}
|
||||
P -= vec2(0.0, 4.0 * float(hash3(uint(pc.frame) + wg * 131u, 61u, 7u) & 3u));
|
||||
if (t < 36u) { // a ray
|
||||
const float a = float(t) * 0.17453294;
|
||||
const vec2 dir = vec2(cos(a), sin(a));
|
||||
float len = R;
|
||||
for (int s = 1; s < int(R); ++s) if (solid_at(ivec2(floor(P + dir * float(s))))) { len = float(s); break; }
|
||||
for (int k = 0; k < 4; ++k) {
|
||||
const vec2 sw = P + dir * (len * 0.25 * float(k));
|
||||
if (fog_type_at(sw) != 0u) continue; // only the default fog of war clears along the rays
|
||||
const int i = texel_index(sw);
|
||||
if (i >= 0 && fog[i] < 255u) atomicAdd(fog[i], 5u);
|
||||
}
|
||||
return;
|
||||
}
|
||||
// the 3 x 3 texels around the player
|
||||
const int k = int(t) - 36;
|
||||
const vec2 tc = (floor((P + vec2(FOG_OX, FOG_OY)) / 32.0) + vec2(float(k % 3 - 1), float(k / 3 - 1))) * 32.0 + 16.0 - vec2(FOG_OX, FOG_OY);
|
||||
const int i = texel_index(tc);
|
||||
if (i < 0 || fog_type_at(tc) > 1u) return; // the default and HEAVY_CLEAR_AT_PLAYER clear around the player
|
||||
const float d = distance(P, tc) / 32.0;
|
||||
const float old = 255.0 - float(min(fog[i], 255u));
|
||||
float target = 255.0 * d;
|
||||
if (k % 3 != 1 && k / 3 != 1) target = max(target, (coarse_at(tc) * 16.0 / 1024.0 - d) * 255.0); // the four diagonal texels: a solid region stays fogged (the coarse byte x 16 / 1024)
|
||||
const float nf = min(old, max(old - 3.0 * d, clamp(target, 0.0, 255.0)));
|
||||
atomicMax(fog[i], uint(255.0 - nf));
|
||||
}
|
||||
Reference in new issue
Block a user