Skip to content
Closed
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
5 changes: 4 additions & 1 deletion code/def_files/data/effects/fxaa-v.sdr
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ void main() {
}
#else
in vec4 vertPosition;
in vec4 vertTexCoord;

out vec2 v_rcpFrame;
noperspective out vec2 v_pos;
Expand All @@ -20,6 +21,8 @@ layout (std140) uniform genericData {
void main() {
gl_Position = vertPosition;
v_rcpFrame = vec2(1.0/rt_w, 1.0/rt_h);
v_pos = vertPosition.xy*0.5 + 0.5;
// Use the real texcoord rather than deriving it from vertPosition: the draw call may ask for a
// sub-rectangle of the source texture, which the clip-space formula ignored. Matches post-v.sdr.
v_pos = vertTexCoord.xy;
}
#endif
30 changes: 30 additions & 0 deletions code/graphics/2d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -859,6 +859,29 @@ bool gr_is_smaa_mode(AntiAliasMode mode) {
return mode == AntiAliasMode::SMAA_Low || mode == AntiAliasMode::SMAA_Medium || mode == AntiAliasMode::SMAA_High || mode == AntiAliasMode::SMAA_Ultra;
}

SCP_vector<float> gr_get_supported_anisotropy_levels()
{
float max;
if (!gr_get_property(gr_property::MAX_ANISOTROPY, &max)) {
return {};
}

if (max <= 2.0f) {
return {};
}

SCP_vector<float> out;

// We assume here that the anisotropy levels are powers of two...
float current = 1.0f;
while (current <= max) {
out.push_back(current);
current *= 2.0f;
}

return out;
}

static void parse_post_processing_func()
{
bool value;
Expand Down Expand Up @@ -1647,6 +1670,13 @@ void gr_screen_resize(int width, int height)
gr_screen.save_max_h_unscaled_zoomed = gr_screen.max_h_unscaled_zoomed;

gr_setup_viewport();

// The offscreen targets that back the scene/post-processing pipeline were sized for the old
// gr_screen; give the backend a chance to grow them before anything renders at the new size.
// Backends that already handle this elsewhere (Vulkan, via recreateSwapChain()) leave it unset.
if (gr_screen.gf_resize_render_targets) {
gr_screen.gf_resize_render_targets();
}
}

void gr_window_to_render_pos(float& x, float& y)
Expand Down
12 changes: 12 additions & 0 deletions code/graphics/2d.h
Original file line number Diff line number Diff line change
Expand Up @@ -917,6 +917,12 @@ typedef struct screen {
std::function<void()> gf_scene_texture_end;
std::function<void()> gf_copy_effect_texture;

// Grow the offscreen render targets that back the scene/post-processing pipeline to cover the
// current gr_screen, if they don't already. Called from gr_screen_resize(). Optional: the
// Vulkan backend leaves this unset because VulkanRenderer::recreateSwapChain() already owns
// resizing its extent-sized targets.
std::function<void()> gf_resize_render_targets;

std::function<void(int zbias)> gf_zbias;

std::function<void(int)> gf_set_fill_mode;
Expand Down Expand Up @@ -1494,6 +1500,12 @@ inline bool gr_get_property(gr_property property, void* destination)
return gr_screen.gf_get_property(property, destination);
}

// Anisotropic filtering levels the current hardware supports: 1.0 (off), then powers of two up to
// the reported maximum. Empty if anisotropy is unavailable or the hardware caps out below 4x, in
// which case there is nothing meaningful to offer. Backs both the in-game option's enumerator and
// qtFRED's Preferences combo, so the two can't drift.
SCP_vector<float> gr_get_supported_anisotropy_levels();

inline void gr_push_debug_group(const char* name)
{
gr_screen.gf_push_debug_group(name);
Expand Down
3 changes: 2 additions & 1 deletion code/graphics/opengl/gropengl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1126,6 +1126,7 @@ void gr_opengl_init_function_pointers()
gr_screen.gf_scene_texture_begin = gr_opengl_scene_texture_begin;
gr_screen.gf_scene_texture_end = gr_opengl_scene_texture_end;
gr_screen.gf_copy_effect_texture = gr_opengl_copy_effect_texture;
gr_screen.gf_resize_render_targets = gr_opengl_resize_render_targets;

gr_screen.gf_deferred_lighting_begin = gr_opengl_deferred_lighting_begin;
gr_screen.gf_deferred_lighting_msaa = gr_opengl_deferred_lighting_msaa;
Expand Down Expand Up @@ -1514,7 +1515,7 @@ bool gr_opengl_init(std::unique_ptr<os::GraphicsOperations>&& graphicsOps)
opengl_shader_init();

// post processing effects, after shaders are initialized
opengl_setup_scene_textures();
opengl_setup_scene_textures(gr_screen.max_w, gr_screen.max_h);
opengl_post_process_init();

// must be called after extensions are setup
Expand Down
23 changes: 18 additions & 5 deletions code/graphics/opengl/gropengldeferred.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ void gr_opengl_deferred_lighting_begin(bool clearNonColorBufs)
Current_shader->program->Uniforms.setTextureUniform("tex", 0);
GL_state.SetAlphaBlendMode(gr_alpha_blend::ALPHA_BLEND_NONE);
GL_state.SetZbufferType(ZBUFFER_TYPE_NONE);
opengl_draw_full_screen_textured(0, 0, 1, 1);
opengl_draw_full_screen_scene_texture();
} else {
// Copy the existing color data into the emissive part of the G-buffer since everything that already existed is
// treated as emissive
Expand Down Expand Up @@ -159,7 +159,9 @@ void gr_opengl_deferred_lighting_msaa()
});
GL_state.SetAlphaBlendMode(gr_alpha_blend::ALPHA_BLEND_NONE);
GL_state.SetZbufferType(ZBUFFER_TYPE_WRITE);
opengl_draw_full_screen_textured(0, 0, 1, 1);
// msaa-f.sdr resolves via ivec2(textureSize(texColor) * fragTexCoord), so the texcoords have to
// stay inside the rendered sub-rectangle of the multisampled G-buffer.
opengl_draw_full_screen_scene_texture();
}

void gr_opengl_deferred_lighting_end()
Expand Down Expand Up @@ -325,8 +327,12 @@ void gr_opengl_deferred_lighting_finish()
shadow_cascade_params_bind(offset, count);
}

header->invScreenWidth = 1.0f / gr_screen.max_w;
header->invScreenHeight = 1.0f / gr_screen.max_h;
// deferred-f.sdr turns gl_FragCoord into a G-buffer texture coordinate with these, so they
// have to normalize against the G-buffer's own dimensions. Those only equal gr_screen while
// the viewport exactly fills the scene textures -- not after a shrink, and not when the
// allocation was clamped by GL_max_renderbuffer_size.
header->invScreenWidth = 1.0f / Scene_texture_width;
header->invScreenHeight = 1.0f / Scene_texture_height;
header->nearPlane = gr_near_plane;

{
Expand Down Expand Up @@ -561,7 +567,8 @@ void gr_opengl_deferred_lighting_finish()
data->clip_dist = Neb2_fog_clip_distance;
});

opengl_draw_full_screen_textured(0.0f, 0.0f, 1.0f, 1.0f);
// fog-f.sdr samples the composite and depth targets straight off fragTexCoord.
opengl_draw_full_screen_scene_texture();

if (bDrawNebVolumetrics) {
glReadBuffer(GL_COLOR_ATTACHMENT0);
Expand Down Expand Up @@ -657,6 +664,12 @@ void gr_opengl_deferred_lighting_finish()

{
GR_DEBUG_SCOPE("Volumetric Nebulae Draw");
// Deliberately unscaled. volumetric-f.sdr uses fragTexCoord for two incompatible
// things: reconstructing an eye-space ray direction, which needs the full 0..1 range
// across the viewport, and sampling composite/depth/emissive, which needs the
// rendered sub-rectangle. Scaling here would fix the sampling and skew every ray.
// Separating the two needs a second varying (or a scale uniform) in the shader; until
// then volumetrics are only correct while the targets exactly match the viewport.
opengl_draw_full_screen_textured(0.0f, 0.0f, 1.0f, 1.0f);
}
GL_state.Texture.Enable(Scene_emissive_texture);
Expand Down
Loading
Loading