tr2/render: add ps1 lighting contrast modes

Resolves #1646.
Implementation similar to TR2Main, with 100%/150%/200% brightness caps.
This commit is contained in:
Marcin Kurczewski 2024-12-16 21:44:05 +01:00
parent ce95692576
commit 3afcc7d6a3
16 changed files with 112 additions and 28 deletions

View file

@ -30,6 +30,7 @@ uniform bool texturingEnabled;
uniform bool smoothingEnabled;
uniform bool alphaPointDiscard;
uniform float alphaThreshold;
uniform float brightnessMultiplier;
#ifdef OGL33C
#define OUTCOLOR outColor
@ -72,7 +73,7 @@ void main(void) {
discard;
}
OUTCOLOR = vec4(OUTCOLOR.rgb * texColor.rgb, texColor.a);
OUTCOLOR = vec4(OUTCOLOR.rgb * texColor.rgb * brightnessMultiplier, texColor.a);
}
}
#endif // VERTEX

View file

@ -30,6 +30,7 @@ uniform bool texturingEnabled;
uniform bool smoothingEnabled;
uniform bool alphaPointDiscard;
uniform float alphaThreshold;
uniform float brightnessMultiplier;
#ifdef OGL33C
#define OUTCOLOR outColor
@ -72,7 +73,7 @@ void main(void) {
discard;
}
OUTCOLOR = vec4(OUTCOLOR.rgb * texColor.rgb, texColor.a);
OUTCOLOR = vec4(OUTCOLOR.rgb * texColor.rgb * brightnessMultiplier, texColor.a);
}
}
#endif // VERTEX

View file

@ -1,4 +1,5 @@
## [Unreleased](https://github.com/LostArtefacts/TRX/compare/tr2-0.7.1...develop) - ××××-××-××
- added an option to use PS1 contrast levels, available under F8 (#1646)
## [0.7.1](https://github.com/LostArtefacts/TRX/compare/tr2-0.7...tr2-0.7.1) - 2024-12-17
- fixed a crash when selecting the sound option (#2057, regression from 0.6)

View file

@ -27,6 +27,7 @@ struct GFX_3D_RENDERER {
GLint loc_smoothing_enabled;
GLint loc_alpha_point_discard;
GLint loc_alpha_threshold;
GLint loc_brightness_multiplier;
};
static void M_Flush(GFX_3D_RENDERER *renderer);
@ -114,6 +115,8 @@ GFX_3D_RENDERER *GFX_3D_Renderer_Create(void)
GFX_GL_Program_UniformLocation(&renderer->program, "alphaPointDiscard");
renderer->loc_alpha_threshold =
GFX_GL_Program_UniformLocation(&renderer->program, "alphaThreshold");
renderer->loc_brightness_multiplier = GFX_GL_Program_UniformLocation(
&renderer->program, "brightnessMultiplier");
GFX_GL_Program_FragmentData(&renderer->program, "fragColor");
GFX_GL_Program_Bind(&renderer->program);
@ -131,6 +134,8 @@ GFX_3D_RENDERER *GFX_3D_Renderer_Create(void)
&renderer->program, renderer->loc_alpha_point_discard, false);
GFX_GL_Program_Uniform1f(
&renderer->program, renderer->loc_alpha_threshold, -1.0);
GFX_GL_Program_Uniform1f(
&renderer->program, renderer->loc_brightness_multiplier, 1.0);
GFX_3D_VertexStream_Init(&renderer->vertex_stream);
return renderer;
@ -425,13 +430,23 @@ void GFX_3D_Renderer_SetAlphaPointDiscard(
}
void GFX_3D_Renderer_SetAlphaThreshold(
GFX_3D_RENDERER *const renderer, const float threshold)
GFX_3D_RENDERER *const renderer, const float value)
{
ASSERT(renderer != NULL);
M_Flush(renderer);
GFX_GL_Program_Bind(&renderer->program);
GFX_GL_Program_Uniform1f(
&renderer->program, renderer->loc_alpha_threshold, threshold);
&renderer->program, renderer->loc_alpha_threshold, value);
}
void GFX_3D_Renderer_SetBrightnessMultiplier(
GFX_3D_RENDERER *const renderer, const float value)
{
ASSERT(renderer != NULL);
M_Flush(renderer);
GFX_GL_Program_Bind(&renderer->program);
GFX_GL_Program_Uniform1f(
&renderer->program, renderer->loc_brightness_multiplier, value);
}
void GFX_3D_Renderer_SetTexturingEnabled(

View file

@ -54,6 +54,7 @@ ENUM_MAP_DEFINE(INPUT_ROLE, INPUT_ROLE_RESET_BINDINGS, "reset_bindings")
ENUM_MAP_DEFINE(INPUT_ROLE, INPUT_ROLE_PERSPECTIVE, "perspective")
ENUM_MAP_DEFINE(INPUT_ROLE, INPUT_ROLE_SWITCH_RESOLUTION, "switch_resolution")
ENUM_MAP_DEFINE(INPUT_ROLE, INPUT_ROLE_SWITCH_INTERNAL_SCREEN_SIZE, "switch_internal_screen_size")
ENUM_MAP_DEFINE(INPUT_ROLE, INPUT_ROLE_CYCLE_LIGHTING_CONTRAST, "cycle_lighting_contrast")
ENUM_MAP_DEFINE(INPUT_ROLE, INPUT_ROLE_TOGGLE_BILINEAR_FILTER, "toggle_bilinear_filter")
ENUM_MAP_DEFINE(INPUT_ROLE, INPUT_ROLE_TOGGLE_PERSPECTIVE_FILTER, "toggle_perspective_filter")
ENUM_MAP_DEFINE(INPUT_ROLE, INPUT_ROLE_TOGGLE_Z_BUFFER, "toggle_z_buffer")

View file

@ -36,6 +36,7 @@ INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_SWITCH_INTERNAL_SCREEN_SIZE, SDL_SCANCODE_F2)
INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_TOGGLE_BILINEAR_FILTER, SDL_SCANCODE_F3)
INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_TOGGLE_PERSPECTIVE_FILTER, SDL_SCANCODE_F4)
INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_TOGGLE_Z_BUFFER, SDL_SCANCODE_F7)
INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_CYCLE_LIGHTING_CONTRAST, SDL_SCANCODE_F8)
INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_TOGGLE_FULLSCREEN, SDL_SCANCODE_UNKNOWN)
INPUT_KEYBOARD_ASSIGN(INPUT_ROLE_TOGGLE_RENDERING_MODE, SDL_SCANCODE_F12)

View file

@ -47,4 +47,5 @@ INPUT_ROLE_DEFINE(SWITCH_INTERNAL_SCREEN_SIZE, switch_internal_screen_size)
INPUT_ROLE_DEFINE(TOGGLE_BILINEAR_FILTER, toggle_bilinear_filter)
INPUT_ROLE_DEFINE(TOGGLE_PERSPECTIVE_FILTER, toggle_perspective_filter)
INPUT_ROLE_DEFINE(TOGGLE_Z_BUFFER, toggle_z_buffer)
INPUT_ROLE_DEFINE(CYCLE_LIGHTING_CONTRAST, cycle_lighting_contrast)
INPUT_ROLE_DEFINE(TOGGLE_RENDERING_MODE, toggle_rendering_mode)

View file

@ -68,3 +68,5 @@ void GFX_3D_Renderer_SetAnisotropyFilter(
void GFX_3D_Renderer_SetAlphaPointDiscard(
GFX_3D_RENDERER *renderer, bool is_enabled);
void GFX_3D_Renderer_SetAlphaThreshold(GFX_3D_RENDERER *renderer, float value);
void GFX_3D_Renderer_SetBrightnessMultiplier(
GFX_3D_RENDERER *renderer, float value);

View file

@ -55,6 +55,7 @@ typedef struct {
float wireframe_width;
GFX_TEXTURE_FILTER texture_filter;
SCREENSHOT_FORMAT screenshot_format;
LIGHTING_CONTRAST lighting_contrast;
TEXEL_ADJUST_MODE texel_adjust_mode;
int32_t nearest_adjustment;
int32_t linear_adjustment;

View file

@ -10,6 +10,7 @@ CFG_BOOL(g_Config, visuals.fix_item_rots, true)
CFG_ENUM(g_Config, rendering.screenshot_format, SCREENSHOT_FORMAT_JPEG, SCREENSHOT_FORMAT)
CFG_ENUM(g_Config, rendering.render_mode, RM_HARDWARE, RENDER_MODE)
CFG_ENUM(g_Config, rendering.aspect_mode, AM_ANY, ASPECT_MODE)
CFG_ENUM(g_Config, rendering.lighting_contrast, LIGHTING_CONTRAST_MEDIUM, LIGHTING_CONTRAST)
CFG_ENUM(g_Config, rendering.texture_filter, GFX_TF_NN, GFX_TEXTURE_FILTER)
CFG_BOOL(g_Config, rendering.enable_zbuffer, true)
CFG_BOOL(g_Config, rendering.enable_perspective_filter, true)

View file

@ -105,6 +105,7 @@ static void M_UpdateFromBackend(
s->toggle_bilinear_filter |= backend->is_pressed(layout, INPUT_ROLE_TOGGLE_BILINEAR_FILTER);
s->toggle_perspective_filter |= backend->is_pressed(layout, INPUT_ROLE_TOGGLE_PERSPECTIVE_FILTER);
s->toggle_z_buffer |= backend->is_pressed(layout, INPUT_ROLE_TOGGLE_Z_BUFFER);
s->cycle_lighting_contrast |= backend->is_pressed(layout, INPUT_ROLE_CYCLE_LIGHTING_CONTRAST);
s->toggle_fullscreen |= backend->is_pressed(layout, INPUT_ROLE_TOGGLE_FULLSCREEN);
s->toggle_rendering_mode |= backend->is_pressed(layout, INPUT_ROLE_TOGGLE_RENDERING_MODE);
// clang-format on

View file

@ -34,10 +34,11 @@ static GFX_3D_VERTEX *m_HWR_VertexPtr = NULL;
static void M_ShadeColor(
GFX_3D_VERTEX *target, uint32_t red, uint32_t green, uint32_t blue,
uint8_t alpha);
static void M_ShadeLight(GFX_3D_VERTEX *target, uint32_t shade);
static void M_ShadeLight(
GFX_3D_VERTEX *target, uint32_t shade, bool is_textured);
static void M_ShadeLightColor(
GFX_3D_VERTEX *target, uint32_t shade, uint32_t red, uint32_t green,
uint32_t blue, uint8_t alpha);
GFX_3D_VERTEX *target, uint32_t shade, bool is_textured, uint32_t red,
uint32_t green, uint32_t blue, uint8_t alpha);
static void M_ReleaseTextures(RENDERER *renderer);
static void M_LoadTexturePages(
@ -149,22 +150,37 @@ static void M_ShadeColor(
target->a = alpha;
}
static void M_ShadeLight(GFX_3D_VERTEX *const target, const uint32_t shade)
static void M_ShadeLight(
GFX_3D_VERTEX *const target, uint32_t shade, const bool is_textured)
{
uint32_t value = (uint32_t)(0x1FFF - shade) >> 4;
CLAMPG(value, 0xFF);
M_ShadeColor(target, value, value, value, 0xFF);
M_ShadeLightColor(target, shade, is_textured, 255, 255, 255, 255);
}
static void M_ShadeLightColor(
GFX_3D_VERTEX *const target, uint32_t shade, uint32_t red, uint32_t green,
uint32_t blue, const uint8_t alpha)
GFX_3D_VERTEX *const target, uint32_t shade, const bool is_textured,
uint32_t red, uint32_t green, uint32_t blue, const uint8_t alpha)
{
CLAMPG(shade, 0x1FFF);
shade = 0x1FFF - shade;
red = (red * shade) >> 12;
green = (green * shade) >> 12;
blue = (blue * shade) >> 12;
if (g_Config.rendering.lighting_contrast == LIGHTING_CONTRAST_MEDIUM) {
CLAMPL(shade, 0x800);
}
if (g_Config.rendering.lighting_contrast != LIGHTING_CONTRAST_LOW
&& is_textured) {
shade = 0x1000 + shade / 2;
}
if (g_Config.rendering.lighting_contrast == LIGHTING_CONTRAST_LOW
&& !is_textured) {
CLAMPL(shade, 0x1000);
}
if (shade != 0x1000) {
const int32_t brightness = 0x1FFF - shade;
red = (red * brightness) >> 12;
green = (green * brightness) >> 12;
blue = (blue * brightness) >> 12;
}
CLAMPG(red, 0xFF);
CLAMPG(green, 0xFF);
CLAMPG(blue, 0xFF);
@ -263,7 +279,7 @@ static void M_DrawPolyTextured(
vbuf_gl->w = vbuf->rhw;
vbuf_gl->t = vbuf->v / (double)PHD_ONE;
vbuf_gl->s = vbuf->u / (double)PHD_ONE;
M_ShadeLight(vbuf_gl, vbuf->g);
M_ShadeLight(vbuf_gl, vbuf->g, true);
}
M_DrawPrimitive(renderer, GFX_3D_PRIM_TRI, m_VBufferGL, vtx_count, true);
}
@ -279,7 +295,7 @@ static void M_DrawPolyFlat(
vbuf_gl->y = vbuf->y;
vbuf_gl->z = MAKE_DEPTH(vbuf);
vbuf_gl->w = vbuf->rhw;
M_ShadeLightColor(vbuf_gl, vbuf->g, red, green, blue, 0xFF);
M_ShadeLightColor(vbuf_gl, vbuf->g, false, red, green, blue, 0xFF);
}
M_DrawPrimitive(renderer, GFX_3D_PRIM_TRI, m_VBufferGL, vtx_count, true);
}
@ -307,7 +323,7 @@ static void M_InsertPolyTextured(
vbuf_gl->w = vbuf->rhw;
vbuf_gl->s = vbuf->u / (double)PHD_ONE;
vbuf_gl->t = vbuf->v / (double)PHD_ONE;
M_ShadeLight(vbuf_gl, vbuf->g);
M_ShadeLight(vbuf_gl, vbuf->g, true);
}
m_HWR_VertexPtr += vtx_count;
@ -335,7 +351,7 @@ static void M_InsertPolyFlat(
vbuf_gl->z = MAKE_DEPTH(vbuf);
vbuf_gl->w = vbuf->rhw;
M_ShadeLightColor(
vbuf_gl, vbuf->g, red, green, blue,
vbuf_gl, vbuf->g, false, red, green, blue,
poly_type == POLY_HWR_TRANS ? 0x80 : 0xFF);
}
@ -387,7 +403,7 @@ static void M_InsertGT3_Sorted(
vbuf_gl->w = vtx[i]->rhw;
vbuf_gl->s = (double)uv[i]->u * vtx[i]->rhw / (double)PHD_ONE;
vbuf_gl->t = (double)uv[i]->v * vtx[i]->rhw / (double)PHD_ONE;
M_ShadeLight(vbuf_gl, vtx[i]->g);
M_ShadeLight(vbuf_gl, vtx[i]->g, true);
}
m_HWR_VertexPtr += 3;
@ -479,7 +495,7 @@ static void M_InsertGT4_Sorted(
vbuf_gl->w = vtx[i]->rhw;
vbuf_gl->s = texture->uv[i].u * vtx[i]->rhw / (double)PHD_ONE;
vbuf_gl->t = texture->uv[i].v * vtx[i]->rhw / (double)PHD_ONE;
M_ShadeLight(vbuf_gl, vtx[i]->g);
M_ShadeLight(vbuf_gl, vtx[i]->g, true);
}
m_HWR_VertexPtr += 4;
@ -998,7 +1014,7 @@ static void M_InsertGT3_ZBuffered(
vbuf_gl->w = vtx[i]->rhw;
vbuf_gl->s = (double)uv[i]->u * vtx[i]->rhw / (double)PHD_ONE;
vbuf_gl->t = (double)uv[i]->v * vtx[i]->rhw / (double)PHD_ONE;
M_ShadeLight(vbuf_gl, vtx[i]->g);
M_ShadeLight(vbuf_gl, vtx[i]->g, true);
}
M_SelectTexture(renderer, texture->tex_page);
@ -1091,7 +1107,7 @@ static void M_InsertGT4_ZBuffered(
vbuf_gl->w = vtx[i]->rhw;
vbuf_gl->s = texture->uv[i].u * vtx[i]->rhw / (double)PHD_ONE;
vbuf_gl->t = texture->uv[i].v * vtx[i]->rhw / (double)PHD_ONE;
M_ShadeLight(vbuf_gl, vtx[i]->g);
M_ShadeLight(vbuf_gl, vtx[i]->g, true);
}
M_SelectTexture(renderer, texture->tex_page);
@ -1506,6 +1522,7 @@ static void M_EndScene(RENDERER *const renderer)
static void M_Reset(RENDERER *const renderer, const RENDER_RESET_FLAGS flags)
{
M_PRIV *const priv = renderer->priv;
if (!renderer->initialized) {
return;
}
@ -1513,6 +1530,13 @@ static void M_Reset(RENDERER *const renderer, const RENDER_RESET_FLAGS flags)
LOG_DEBUG("Reloading textures");
M_LoadTexturePages(renderer, g_TexturePageCount, g_TexturePageBuffer16);
}
if (flags & RENDER_RESET_PARAMS) {
GFX_3D_Renderer_SetBrightnessMultiplier(
priv->renderer_3d,
g_Config.rendering.lighting_contrast == LIGHTING_CONTRAST_LOW
? 1.0
: 2.0);
}
M_ResetFuncPtrs(renderer);
}

View file

@ -290,7 +290,9 @@ static void M_HandleConfigChange(const EVENT *const event, void *const data)
|| old->rendering.enable_perspective_filter
!= new->rendering.enable_perspective_filter
|| old->rendering.enable_wireframe != new->rendering.enable_wireframe
|| old->rendering.texture_filter != new->rendering.texture_filter) {
|| old->rendering.texture_filter != new->rendering.texture_filter
|| old->rendering.lighting_contrast
!= new->rendering.lighting_contrast) {
Render_Reset(RENDER_RESET_PARAMS);
}
}

View file

@ -19,6 +19,7 @@
static void M_ToggleBilinearFiltering(void);
static void M_TogglePerspectiveCorrection(void);
static void M_ToggleZBuffer(void);
static void M_CycleLightingContrast(void);
static void M_ToggleFullscreen(void);
static void M_ToggleRenderingMode(void);
static void M_DecreaseResolutionOrBPP(void);
@ -46,8 +47,8 @@ static void M_TogglePerspectiveCorrection(void)
: SW_DETAIL_MEDIUM;
Overlay_DisplayModeInfo(
g_Config.rendering.enable_perspective_filter
? "Perspective correction enabled"
: "Perspective correction disabled");
? "Perspective Correction On"
: "Perspective Correction Off");
Config_Write();
}
@ -67,6 +68,22 @@ static void M_ToggleZBuffer(void)
Config_Write();
}
static void M_CycleLightingContrast(void)
{
const int32_t direction = g_Input.slow ? -1 : 1;
LIGHTING_CONTRAST value = g_Config.rendering.lighting_contrast;
value += direction;
value += LIGHTING_CONTRAST_NUMBER_OF;
value %= LIGHTING_CONTRAST_NUMBER_OF;
g_Config.rendering.lighting_contrast = value;
char tmp[100];
sprintf(
tmp, "Lighting Contrast: %s",
ENUM_MAP_TO_STRING(LIGHTING_CONTRAST, value));
Overlay_DisplayModeInfo(tmp);
Config_Write();
}
static void M_ToggleFullscreen(void)
{
g_Config.window.is_fullscreen = !g_Config.window.is_fullscreen;
@ -164,6 +181,10 @@ void Shell_ProcessInput(void)
M_ToggleZBuffer();
}
if (g_InputDB.cycle_lighting_contrast) {
M_CycleLightingContrast();
}
if (g_InputDB.toggle_fullscreen) {
M_ToggleFullscreen();
}

View file

@ -6,6 +6,10 @@ ENUM_MAP_DEFINE(TEXEL_ADJUST_MODE, TAM_DISABLED, "never")
ENUM_MAP_DEFINE(TEXEL_ADJUST_MODE, TAM_BILINEAR_ONLY, "bilinear-only")
ENUM_MAP_DEFINE(TEXEL_ADJUST_MODE, TAM_ALWAYS, "always")
ENUM_MAP_DEFINE(LIGHTING_CONTRAST, LIGHTING_CONTRAST_LOW, "low")
ENUM_MAP_DEFINE(LIGHTING_CONTRAST, LIGHTING_CONTRAST_MEDIUM, "medium")
ENUM_MAP_DEFINE(LIGHTING_CONTRAST, LIGHTING_CONTRAST_HIGH, "high")
ENUM_MAP_DEFINE(RENDER_MODE, RM_SOFTWARE, "software")
ENUM_MAP_DEFINE(RENDER_MODE, RM_HARDWARE, "hardware")

View file

@ -8,3 +8,10 @@ typedef struct {
PHD_UV uv[4];
PHD_UV uv_backup[4];
} PHD_TEXTURE;
typedef enum {
LIGHTING_CONTRAST_LOW,
LIGHTING_CONTRAST_MEDIUM,
LIGHTING_CONTRAST_HIGH,
LIGHTING_CONTRAST_NUMBER_OF,
} LIGHTING_CONTRAST;