Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions codemp/rd-vulkan/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ set(MPVulkanRendererFiles
"${MPDir}/rd-vulkan/vk_shade_geometry.cpp"
"${MPDir}/rd-vulkan/vk_swapchain.cpp"
"${MPDir}/rd-vulkan/vk_vbo.cpp"
"${MPDir}/rd-vulkan/vk_vbo_surfacesprites.cpp"
)
source_group("renderer" FILES ${MPVulkanRendererFiles})

Expand Down
13 changes: 13 additions & 0 deletions codemp/rd-vulkan/shaders/compile.bat
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,19 @@ for %%f in (%glsl%*.frag) do (
"%cl%" -S frag -V -o "%tmpf%" %glsl%light_frag.tmpl -DUSE_LINE -DUSE_FOG
"%bh%" "%tmpf%" %outf% frag_light_line_fog

@rem compile surface sprites from templates
"%cl%" -S vert -V -o "%tmpf%" %glsl%surface_sprite_vert.tmpl
"%bh%" "%tmpf%" %outf% vert_surface_sprites

"%cl%" -S vert -V -o "%tmpf%" %glsl%surface_sprite_vert.tmpl -DUSE_FOG
"%bh%" "%tmpf%" %outf% vert_surface_sprites_fog

"%cl%" -S frag -V -o "%tmpf%" %glsl%surface_sprite_frag.tmpl -DUSE_ATEST
"%bh%" "%tmpf%" %outf% frag_surface_sprites

"%cl%" -S frag -V -o "%tmpf%" %glsl%surface_sprite_frag.tmpl -DUSE_ATEST -DUSE_FOG
"%bh%" "%tmpf%" %outf% frag_surface_sprites_fog

@rem template shader identifiers and flags
:: ident-fixed:
set "mode[0]=-DUSE_CLX_IDENT"
Expand Down
228 changes: 228 additions & 0 deletions codemp/rd-vulkan/shaders/glsl/surface_sprite_frag.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
#version 450
// based on OpenJK rend2 surface_sprites.glsl

#ifdef USE_ATEST
layout (constant_id = 0) const int alpha_test_func = 0;
layout (constant_id = 1) const float alpha_test_value = 0.0;
#ifdef USE_DF
layout (constant_id = 2) const float depth_fragment = 0.85;
#endif
#endif
layout (constant_id = 3) const int alpha_to_coverage = 0;
layout (constant_id = 8) const int discard_mode = 0;

#ifdef USE_FOG
layout (constant_id = 5) const int hw_fog = 0;
layout (constant_id = 11) const int acff = 0; // NONE, RGB, RGBA, ALPHA
#endif
layout (constant_id = 12) const int kFaceCamera = 0;
layout (constant_id = 13) const int kFaceUp = 0;
layout (constant_id = 14) const int kFaceFlattened = 0;
layout (constant_id = 15) const int kFxSprite = 0;
layout (constant_id = 16) const int kAdditive = 0;
layout (constant_id = 17) const int kUseFog = 0;


#if defined (USE_FOG)
layout(set = 0, binding = 0) uniform UBO {
// light/env/material parameters:
vec4 eyePos;
vec4 lightPos;
vec4 lightColor;
vec4 lightVector;

// fog parameters:
vec4 fogDistanceVector;
vec4 fogDepthVector;
vec4 fogEyeT;
vec4 fogColor;
};

struct vkUniformFogEntry_t {
vec4 plane;
vec4 color;
float depthToOpaque;
int hasPlane;
};

struct vkUniformFog_t {
int num_fogs;
vkUniformFogEntry_t fogs[16];
};

layout(set = 0, binding = 1) uniform Camera {
vec4 u_ViewOrigin;
};

layout(set = 0, binding = 4) uniform Fog {
vkUniformFog_t u_fogs;
};
#endif

layout(set = 1, binding = 0) buffer SurfaceSprite
{
vec2 u_FxGrow;
float u_FxDuration;
float u_FadeStartDistance;
float u_FadeEndDistance;
float u_FadeScale;
float u_Wind;
float u_WindIdle;
float u_FxAlphaStart;
float u_FxAlphaEnd;
};

layout(set = 2, binding = 0) uniform sampler2D texture0;
#ifdef USE_FOG
layout(set = 3, binding = 0) uniform sampler2D fog_texture;
#endif

layout(location = 0) in vec4 frag_color0;
layout(location = 1) in vec2 frag_tex_coord0;
layout(location = 2) in float var_Effectpos;
#ifdef USE_FOG
layout(location = 3) in vec3 fog_tex_coord; // or ws_worldpos
#endif

layout(location = 0) out vec4 out_color;

#ifdef USE_ATEST
float CorrectAlpha(float threshold, float alpha, vec2 tc)
{
ivec2 ts = textureSize(texture0, 0);
float dx = max(abs(dFdx(tc.x * float(ts.x))), 0.001);
float dy = max(abs(dFdy(tc.y * float(ts.y))), 0.001);
float dxy = max(dx, dy); // apply the smallest boost
float scale = max(1.0 / dxy, 1.0);
float ac = threshold + (alpha - threshold) * scale;
return ac;
}
#endif

#ifdef USE_FOG
void ApplyACFF(inout vec4 base, in vec4 fogColor, in float fogAlpha)
{
if ( acff == 1 ) // ACFF_RGB
base.rgb *= ( 1.0 - fogAlpha );

else if ( acff == 2 ) // ACFF_RGBA
base *= ( 1.0 - fogAlpha );

else if ( acff == 3 ) // ACFF_ALPHA
base.a *= ( 1.0 - fogAlpha );

else // default: ACFF_NONE
base = mix( base, fogColor, fogAlpha );
}

vec4 CalcFog(in vec3 viewOrigin, in vec3 position, in vkUniformFogEntry_t fog)
{
bool inFog = dot(viewOrigin, fog.plane.xyz) - fog.plane.w >= 0.0 || (fog.hasPlane == 0);

// line: x = o + tv
// plane: (x . n) + d = 0
// intersects: dot(o + tv, n) + d = 0
// dot(o + tv, n) = -d
// dot(o, n) + t*dot(n, v) = -d
// t = -(d + dot(o, n)) / dot(n, v)
vec3 V = position - viewOrigin;

// fogPlane is inverted in tr_bsp for some reason.
float t = -(fog.plane.w + dot(viewOrigin, -fog.plane.xyz)) / dot(V, -fog.plane.xyz);

// only use this for objects with potentially two contibuting fogs
#if defined(USE_FALLBACK_GLOBAL_FOG)
bool intersects = (t > 0.0 && t < 0.995);
if (inFog == intersects)
{
int u_globalFogIndex = int(fogDistanceVector[0]);
Fog globalFog = u_fogs.fogs[u_globalFogIndex];

float distToVertex = length(V);
float distFromIntersection = distToVertex - (t * distToVertex);
float z = globalFog.depthToOpaque * mix(distToVertex, distFromIntersection, intersects);
return vec4(globalFog.color.rgb, 1.0 - clamp(exp(-(z * z)), 0.0, 1.0));
}
#else
bool intersects = (t > 0.0 && t < 0.995);
if (inFog == intersects)
return vec4(0.0);
#endif

float distToVertexFromViewOrigin = length(V);
float distToIntersectionFromViewOrigin = t * distToVertexFromViewOrigin;

float distOutsideFog = max(distToVertexFromViewOrigin - distToIntersectionFromViewOrigin, 0.0);
float distThroughFog = mix(distOutsideFog, distToVertexFromViewOrigin, inFog);

float z = fog.depthToOpaque * distThroughFog;
return vec4(fog.color.rgb * fogDistanceVector[2], 1.0 - clamp(exp(-(z * z)), 0.0, 1.0));
}
#endif

void main() {
vec4 base;
vec4 color0 = texture(texture0, frag_tex_coord0);
color0.rgb *= frag_color0.rgb;
base = color0;

if ( kFxSprite > 0 ) {
float fxalpha = u_FxAlphaEnd - u_FxAlphaStart;
if (u_FxAlphaEnd < 0.05)
{
if (var_Effectpos > 0.5)
base.a *= u_FxAlphaStart + (fxalpha * (var_Effectpos - 0.5) * 2.0);
else
base.a *= u_FxAlphaStart + (fxalpha * (0.5 - var_Effectpos) * 2.0);
}
else
{
base.a *= u_FxAlphaStart + (fxalpha * var_Effectpos);
}
}

#ifdef USE_ATEST
if (alpha_to_coverage != 0) {
if (alpha_test_func == 1) {
base.a = base.a > 0.0 ? 1.0 : 0.0;
} else if (alpha_test_func == 2) {
base.a = CorrectAlpha(alpha_test_value, 1.0 - base.a, frag_tex_coord0);
} else if (alpha_test_func == 3) {
base.a = CorrectAlpha(alpha_test_value, base.a, frag_tex_coord0);
}
} else
// specialization: alpha-test function
if (alpha_test_func == 1) {
if (color0.a == alpha_test_value) discard;
} else if (alpha_test_func == 2) {
if (color0.a >= alpha_test_value) discard;
} else if (alpha_test_func == 3) {
if (color0.a < alpha_test_value) discard;
}
#endif

#ifdef USE_FOG
if ( hw_fog == 1 ) {
int u_fogIndex = int(fogDistanceVector[1]);
vec4 fog_color = CalcFog( u_ViewOrigin.rgb, fog_tex_coord, u_fogs.fogs[u_fogIndex] );
ApplyACFF( base, fog_color, fog_color.a );
}
else {
vec4 fog = texture( fog_texture, fog_tex_coord.xy );
vec4 fog_color = fog * fogColor;
ApplyACFF( base, fog_color, fog.a );
}
#endif

if ( discard_mode == 1 ) {
if ( base.a == 0.0 ) {
discard;
}
} else if ( discard_mode == 2 ) {
if ( dot( base.rgb, base.rgb ) == 0.0 ) {
discard;
}
}

out_color = base;
}
Loading