Skip to content
Open
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
18 changes: 18 additions & 0 deletions code/def_files/data/effects/gamma-correct-f.sdr
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
in vec4 fragTexCoord;
out vec4 fragOut0;

uniform sampler2D tex;

layout (std140) uniform genericData {
float gamma;
};

void main()
{
vec4 color = texture(tex, fragTexCoord.xy);

float g = max(gamma, 0.001);
color.rgb = pow(color.rgb, vec3(1.0 / g));

fragOut0 = color;
}
112 changes: 8 additions & 104 deletions code/graphics/2d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ bool Save_custom_screen_size;
bool Deferred_lighting = false;
bool High_dynamic_range = false;

static ushort* Gr_original_gamma_ramp = nullptr;


static int videodisplay_deserializer(const json_t* value)
{
Expand Down Expand Up @@ -755,7 +755,6 @@ void removeVSyncOption()
static std::unique_ptr<graphics::util::UniformBufferManager> UniformBufferManager;

// Forward definitions
static void uniform_buffer_managers_init();
static void uniform_buffer_managers_deinit();
static void uniform_buffer_managers_retire_buffers();

Expand Down Expand Up @@ -1305,15 +1304,6 @@ void gr_close()
if(Cmdline_enable_vr)
openxr_close();

if (Gr_original_gamma_ramp != nullptr && os::getSDLMainWindow() != nullptr) {
SDL_SetWindowGammaRamp(os::getSDLMainWindow(), Gr_original_gamma_ramp, (Gr_original_gamma_ramp + 256),
(Gr_original_gamma_ramp + 512));
}

// This is valid even if Gr_original_gamma_ramp is nullptr
vm_free(Gr_original_gamma_ramp);
Gr_original_gamma_ramp = nullptr;

gpu_heap_deinit();

// Cleanup uniform buffer managers
Expand Down Expand Up @@ -1870,8 +1860,13 @@ bool gr_init(std::unique_ptr<os::GraphicsOperations>&& graphicsOps, int d_mode,
// (be that a window, a render overlay from nsight, or an FSO-internal buffer) instead of directly rendering to the OS-provided direct screen backbuffer.
// As the cost of -window_res is one single blit of a fullscreen buffer, it's probably an acceptable compromise to get rid of render artifacts.
// As such, forcibly enable -window_res at the screen resolution here, if we're in fullscreen.

//
// Additionally, SDL3+ doesn't work when reading from the GL_FRONT buffers, so we need our own intermediate buffers.
//
// Furthermore, gamma handling now also requires a blit of the final scene (not just the 3D scene, since it needs to work on menus as well).
//
// As such, window_res is effectively no longer optional, part of the core render path and must always be enabled.
// The only reason it is not yet refactored into an always-on thing is due to issues with FRED integration.
Cmdline_window_res.emplace(static_cast<uint16_t>(width), static_cast<uint16_t>(height));
}

Expand Down Expand Up @@ -1984,9 +1979,6 @@ bool gr_init(std::unique_ptr<os::GraphicsOperations>&& graphicsOps, int d_mode,

gr_light_init();

// Initialize uniform buffer managers
uniform_buffer_managers_init();

gpu_heap_init();

mprintf(("Checking graphics capabilities:\n"));
Expand Down Expand Up @@ -2995,7 +2987,7 @@ void gr_print_timestamp(int x, int y, fix timestamp, int resize_mode)
gr_string(x, y, time.c_str(), resize_mode);
}

static void uniform_buffer_managers_init()
void gr_uniform_buffer_managers_init()
{
if (gr_screen.mode == GR_STUB) {
return;
Expand Down Expand Up @@ -3197,101 +3189,13 @@ void gr_heap_deallocate(GpuHeap heap_type, size_t data_offset)
gpuHeap->freeGpuData(data_offset);
}

// I feel dirty...
static void make_gamma_ramp(float gamma, ushort* ramp)
{
ushort x, y;
ushort base_ramp[256];

Assert(ramp != nullptr);

// generate the base ramp values first off

// if no gamma set then just do this quickly
if (gamma <= 0.0f) {
memset(ramp, 0, 3 * 256 * sizeof(ushort));
return;
}
// identity gamma, avoid all of the math
else if (gamma == 1.0f || Gr_original_gamma_ramp == nullptr) {
if (Gr_original_gamma_ramp != nullptr) {
memcpy(ramp, Gr_original_gamma_ramp, 3 * 256 * sizeof(ushort));
}
// set identity if no original ramp
else {
for (x = 0; x < 256; x++) {
ramp[x] = (x << 8) | x;
ramp[x + 256] = (x << 8) | x;
ramp[x + 512] = (x << 8) | x;
}
}

return;
}
// for everything else we need to actually figure it up
else {
double g = 1.0 / (double)gamma;
double val;

Assert(Gr_original_gamma_ramp != nullptr);

for (x = 0; x < 256; x++) {
val = (pow(x / 255.0, g) * 65535.0 + 0.5);
CLAMP(val, 0., 65535.);

base_ramp[x] = (ushort)val;
}

for (y = 0; y < 3; y++) {
for (x = 0; x < 256; x++) {
val = (base_ramp[x] * 2) - Gr_original_gamma_ramp[x + y * 256];
CLAMP(val, 0., 65535.);

ramp[x + y * 256] = (ushort)val;
}
}
}
}

void gr_set_gamma(float gamma)
{
if (gr_screen.mode == GR_STUB) {
return;
}

Gr_gamma = gamma;

// new way - but not while running FRED
if (!Fred_running && !Cmdline_no_set_gamma && os::getSDLMainWindow() != nullptr) {
if (Gr_original_gamma_ramp == nullptr) {
// First time we are here so get the current (original) gamma ramp here so we can reset it later
Gr_original_gamma_ramp = (ushort*)vm_malloc(3 * 256 * sizeof(ushort), memory::quiet_alloc);

if (Gr_original_gamma_ramp == nullptr) {
mprintf((" Unable to allocate memory for gamma ramp! Disabling...\n"));
Cmdline_no_set_gamma = 1;
} else {
SDL_GetWindowGammaRamp(os::getSDLMainWindow(), Gr_original_gamma_ramp, (Gr_original_gamma_ramp + 256),
(Gr_original_gamma_ramp + 512));
}
}

auto gamma_ramp = (ushort*)vm_malloc(3 * 256 * sizeof(ushort), memory::quiet_alloc);

if (gamma_ramp == nullptr) {
Int3();
return;
}

memset(gamma_ramp, 0, 3 * 256 * sizeof(ushort));

// Create the Gamma lookup table
make_gamma_ramp(gamma, gamma_ramp);

SDL_SetWindowGammaRamp(os::getSDLMainWindow(), gamma_ramp, (gamma_ramp + 256), (gamma_ramp + 512));

vm_free(gamma_ramp);
}
}

void gr_get_post_process_effect_names(SCP_vector<SCP_string>& names)
Expand Down
4 changes: 4 additions & 0 deletions code/graphics/2d.h
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,8 @@ enum shader_type {

SDR_TYPE_IRRADIANCE_MAP_GEN,

SDR_TYPE_GAMMA_BLIT,

NUM_SHADER_TYPES
};

Expand Down Expand Up @@ -1487,6 +1489,8 @@ void gr_get_post_process_effect_names(SCP_vector<SCP_string> &names);

bool gr_is_viewport_window();

void gr_uniform_buffer_managers_init();

// Include this last to make the 2D rendering function available everywhere
#include "graphics/render.h"

Expand Down
25 changes: 18 additions & 7 deletions code/graphics/opengl/gropengl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,15 +119,24 @@ void gr_opengl_flip()
return;

if (Cmdline_window_res) {
GL_state.BindFrameBuffer(0, GL_DRAW_FRAMEBUFFER);
GL_state.BindFrameBuffer(Back_framebuffer, GL_READ_FRAMEBUFFER);
GL_state.PopFramebufferState();

glReadBuffer(GL_COLOR_ATTACHMENT0);
glDrawBuffer(GL_BACK);
glBlitFramebuffer(0, 0, gr_screen.max_w, gr_screen.max_h, 0, 0, Cmdline_window_res->first, Cmdline_window_res->second, GL_COLOR_BUFFER_BIT, GL_LINEAR);
glDrawBuffer(GL_NONE);
glViewport(0, 0, Cmdline_window_res->first, Cmdline_window_res->second);

GL_state.PopFramebufferState();
opengl_shader_set_current(gr_opengl_maybe_create_shader(SDR_TYPE_GAMMA_BLIT, 0));

GL_state.Texture.Enable(0, GL_TEXTURE_2D, Back_texture);
Current_shader->program->Uniforms.setTextureUniform("tex", 0);

GL_state.SetAlphaBlendMode(gr_alpha_blend::ALPHA_BLEND_NONE);
GL_state.SetZbufferType(ZBUFFER_TYPE_NONE);

opengl_set_generic_uniform_data<graphics::generic_data::gamma_blit_data>(
[](graphics::generic_data::gamma_blit_data* data) {
data->gamma = Cmdline_no_set_gamma ? 1.f : Gr_gamma;
});

opengl_draw_full_screen_textured(0.0f, 0.0f, 1.0f, 1.0f);
}

if (Cmdline_gl_finish)
Expand Down Expand Up @@ -1485,6 +1494,8 @@ bool gr_opengl_init(std::unique_ptr<os::GraphicsOperations>&& graphicsOps)
Gr_current_green = &Gr_green;
Gr_current_alpha = &Gr_alpha;

// Initialize uniform buffer managers
gr_uniform_buffer_managers_init();

gr_setup_frame();
gr_opengl_reset_clip();
Expand Down
3 changes: 3 additions & 0 deletions code/graphics/opengl/gropenglshader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,9 @@ static opengl_shader_type_t GL_shader_types[] = {

{ SDR_TYPE_IRRADIANCE_MAP_GEN, "post-v.sdr", "irrmap-f.sdr", nullptr,
{ opengl_vert_attrib::POSITION, opengl_vert_attrib::TEXCOORD }, "Irradiance Map Generation", false },

{ SDR_TYPE_GAMMA_BLIT, "post-v.sdr", "gamma-correct-f.sdr", nullptr,
{ opengl_vert_attrib::POSITION, opengl_vert_attrib::TEXCOORD }, "Gamma correct blit", false },
};
// clang-format on

Expand Down
5 changes: 5 additions & 0 deletions code/graphics/util/uniform_structs.h
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,11 @@ struct irrmap_data {
int face;
};

struct gamma_blit_data {
float gamma;
float pad[3];
};

} // namespace generic_data

} // namespace graphics
1 change: 1 addition & 0 deletions code/source_groups.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,7 @@ add_file_folder("Default files\\\\data\\\\effects"
def_files/data/effects/fxaa-v.sdr
def_files/data/effects/fxaapre-f.sdr
def_files/data/effects/gamma.sdr
def_files/data/effects/gamma-correct-f.sdr
def_files/data/effects/irrmap-f.sdr
def_files/data/effects/lighting.sdr
def_files/data/effects/ls-f.sdr
Expand Down
Loading