mirror of
https://github.com/gnif/LookingGlass.git
synced 2026-07-20 22:32:01 +00:00
[obs] hdr: improve hdr cursor rendering
This commit is contained in:
@@ -78,6 +78,7 @@ build_effects(
|
|||||||
effect
|
effect
|
||||||
effect/rgb24.effect
|
effect/rgb24.effect
|
||||||
effect/hdrpq.effect
|
effect/hdrpq.effect
|
||||||
|
effect/cursor.effect
|
||||||
)
|
)
|
||||||
|
|
||||||
add_definitions(-D ATOMIC_LOCKING)
|
add_definitions(-D ATOMIC_LOCKING)
|
||||||
|
|||||||
64
obs/effect/cursor.effect
Normal file
64
obs/effect/cursor.effect
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
uniform float4x4 ViewProj;
|
||||||
|
uniform texture2d image;
|
||||||
|
uniform float multiplier;
|
||||||
|
|
||||||
|
sampler_state def_sampler
|
||||||
|
{
|
||||||
|
Filter = Linear;
|
||||||
|
AddressU = Clamp;
|
||||||
|
AddressV = Clamp;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VertData
|
||||||
|
{
|
||||||
|
float4 pos : POSITION;
|
||||||
|
float2 uv : TEXCOORD0;
|
||||||
|
};
|
||||||
|
|
||||||
|
VertData VSDefault(VertData vert_in)
|
||||||
|
{
|
||||||
|
VertData vert_out;
|
||||||
|
vert_out.pos = mul(float4(vert_in.pos.xyz, 1.0), ViewProj);
|
||||||
|
vert_out.uv = vert_in.uv;
|
||||||
|
return vert_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
float srgbToLinearChannel(float value)
|
||||||
|
{
|
||||||
|
return value <= 0.04045 ? value / 12.92 :
|
||||||
|
pow((value + 0.055) / 1.055, 2.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
float3 srgbToLinear(float3 color)
|
||||||
|
{
|
||||||
|
return float3(
|
||||||
|
srgbToLinearChannel(color.r),
|
||||||
|
srgbToLinearChannel(color.g),
|
||||||
|
srgbToLinearChannel(color.b));
|
||||||
|
}
|
||||||
|
|
||||||
|
float4 PSCursor(VertData vert_in) : TARGET
|
||||||
|
{
|
||||||
|
float4 pixel = image.Sample(def_sampler, vert_in.uv);
|
||||||
|
|
||||||
|
if (pixel.a > 0.0)
|
||||||
|
{
|
||||||
|
/* Cursor RGB is premultiplied in nonlinear sRGB. Recover the straight
|
||||||
|
* color before decoding it, then premultiply again in linear light. */
|
||||||
|
float3 srgb = clamp(pixel.rgb / pixel.a, 0.0, 1.0);
|
||||||
|
pixel.rgb = srgbToLinear(srgb) * pixel.a * multiplier;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
pixel.rgb = float3(0.0, 0.0, 0.0);
|
||||||
|
|
||||||
|
return pixel;
|
||||||
|
}
|
||||||
|
|
||||||
|
technique Draw
|
||||||
|
{
|
||||||
|
pass
|
||||||
|
{
|
||||||
|
vertex_shader = VSDefault(vert_in);
|
||||||
|
pixel_shader = PSCursor(vert_in);
|
||||||
|
}
|
||||||
|
}
|
||||||
49
obs/lg.c
49
obs/lg.c
@@ -38,6 +38,7 @@
|
|||||||
|
|
||||||
#include "rgb24.effect.h"
|
#include "rgb24.effect.h"
|
||||||
#include "hdrpq.effect.h"
|
#include "hdrpq.effect.h"
|
||||||
|
#include "cursor.effect.h"
|
||||||
|
|
||||||
/* scRGB reference white in cd/m² (OBS GS_CS_709_SCRGB is defined as
|
/* scRGB reference white in cd/m² (OBS GS_CS_709_SCRGB is defined as
|
||||||
* 1.0 = 80 cd/m²). PQ encodes an absolute 0..10000 cd/m² range, so linear
|
* 1.0 = 80 cd/m²). PQ encodes an absolute 0..10000 cd/m² range, so linear
|
||||||
@@ -142,6 +143,10 @@ typedef struct
|
|||||||
gs_eparam_t * hdrOutputSize;
|
gs_eparam_t * hdrOutputSize;
|
||||||
gs_eparam_t * hdrColorMatrix[3];
|
gs_eparam_t * hdrColorMatrix[3];
|
||||||
gs_eparam_t * hdrScaleParam;
|
gs_eparam_t * hdrScaleParam;
|
||||||
|
|
||||||
|
gs_effect_t * cursorEffect;
|
||||||
|
gs_eparam_t * cursorImage;
|
||||||
|
gs_eparam_t * cursorMultiplier;
|
||||||
}
|
}
|
||||||
LGPlugin;
|
LGPlugin;
|
||||||
|
|
||||||
@@ -202,6 +207,24 @@ static void * lgCreate(obs_data_t * settings, obs_source_t * context)
|
|||||||
this->hdrEffect, "colorMatrix2");
|
this->hdrEffect, "colorMatrix2");
|
||||||
this->hdrScaleParam = gs_effect_get_param_by_name(
|
this->hdrScaleParam = gs_effect_get_param_by_name(
|
||||||
this->hdrEffect, "scale" );
|
this->hdrEffect, "scale" );
|
||||||
|
|
||||||
|
this->cursorEffect = gs_effect_create(
|
||||||
|
b_effect_cursor_effect, "cursor", &error);
|
||||||
|
if (!this->cursorEffect)
|
||||||
|
{
|
||||||
|
blog(LOG_ERROR, "%s", error);
|
||||||
|
bfree(error);
|
||||||
|
gs_effect_destroy(this->hdrEffect);
|
||||||
|
gs_effect_destroy(this->unpackEffect);
|
||||||
|
bfree(this);
|
||||||
|
obs_leave_graphics();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->cursorImage = gs_effect_get_param_by_name(
|
||||||
|
this->cursorEffect, "image" );
|
||||||
|
this->cursorMultiplier = gs_effect_get_param_by_name(
|
||||||
|
this->cursorEffect, "multiplier");
|
||||||
obs_leave_graphics();
|
obs_leave_graphics();
|
||||||
|
|
||||||
os_sem_init (&this->frameSem , 0);
|
os_sem_init (&this->frameSem , 0);
|
||||||
@@ -320,6 +343,7 @@ static void lgDestroy(void * data)
|
|||||||
obs_enter_graphics();
|
obs_enter_graphics();
|
||||||
gs_effect_destroy(this->unpackEffect);
|
gs_effect_destroy(this->unpackEffect);
|
||||||
gs_effect_destroy(this->hdrEffect);
|
gs_effect_destroy(this->hdrEffect);
|
||||||
|
gs_effect_destroy(this->cursorEffect);
|
||||||
obs_leave_graphics();
|
obs_leave_graphics();
|
||||||
|
|
||||||
bfree(this);
|
bfree(this);
|
||||||
@@ -1198,9 +1222,24 @@ static void lgVideoRender(void * data, gs_effect_t * effect)
|
|||||||
};
|
};
|
||||||
gs_set_scissor_rect(&r);
|
gs_set_scissor_rect(&r);
|
||||||
|
|
||||||
effect = obs_get_base_effect(OBS_EFFECT_DEFAULT);
|
/* Color cursor pixels are premultiplied sRGB. When rendering into OBS's
|
||||||
gs_eparam_t * image = gs_effect_get_param_by_name(effect, "image");
|
* linear scRGB space, decode and scale them to its configured SDR white. */
|
||||||
|
bool mapCursorToScRGB = false;
|
||||||
|
float cursorScale = 1.0f;
|
||||||
|
#if LIBOBS_API_MAJOR_VER >= 28
|
||||||
|
mapCursorToScRGB = this->colorSpace == GS_CS_709_SCRGB;
|
||||||
|
if (mapCursorToScRGB)
|
||||||
|
cursorScale =
|
||||||
|
obs_get_video_sdr_white_level() / LG_SCRGB_REFERENCE_WHITE;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
effect = mapCursorToScRGB && !this->cursorMono ?
|
||||||
|
this->cursorEffect : obs_get_base_effect(OBS_EFFECT_DEFAULT);
|
||||||
|
gs_eparam_t * image = mapCursorToScRGB && !this->cursorMono ?
|
||||||
|
this->cursorImage : gs_effect_get_param_by_name(effect, "image");
|
||||||
gs_effect_set_texture(image, this->cursorTex);
|
gs_effect_set_texture(image, this->cursorTex);
|
||||||
|
if (mapCursorToScRGB && !this->cursorMono)
|
||||||
|
gs_effect_set_float(this->cursorMultiplier, cursorScale);
|
||||||
|
|
||||||
gs_matrix_push();
|
gs_matrix_push();
|
||||||
gs_matrix_translate3f(
|
gs_matrix_translate3f(
|
||||||
@@ -1213,13 +1252,17 @@ static void lgVideoRender(void * data, gs_effect_t * effect)
|
|||||||
|
|
||||||
if (!this->cursorMono)
|
if (!this->cursorMono)
|
||||||
{
|
{
|
||||||
gs_blend_function(GS_BLEND_SRCALPHA, GS_BLEND_INVSRCALPHA);
|
gs_blend_function_separate(
|
||||||
|
GS_BLEND_ONE, GS_BLEND_INVSRCALPHA,
|
||||||
|
GS_BLEND_ONE, GS_BLEND_INVSRCALPHA);
|
||||||
while (gs_effect_loop(effect, "Draw"))
|
while (gs_effect_loop(effect, "Draw"))
|
||||||
gs_draw_sprite(this->cursorTex, 0, 0, 0);
|
gs_draw_sprite(this->cursorTex, 0, 0, 0);
|
||||||
|
|
||||||
if (this->cursor.type == CURSOR_TYPE_MASKED_COLOR &&
|
if (this->cursor.type == CURSOR_TYPE_MASKED_COLOR &&
|
||||||
this->cursorXorTex)
|
this->cursorXorTex)
|
||||||
{
|
{
|
||||||
|
effect = obs_get_base_effect(OBS_EFFECT_DEFAULT);
|
||||||
|
image = gs_effect_get_param_by_name(effect, "image");
|
||||||
gs_effect_set_texture(image, this->cursorXorTex);
|
gs_effect_set_texture(image, this->cursorXorTex);
|
||||||
gs_blend_function_separate(
|
gs_blend_function_separate(
|
||||||
GS_BLEND_INVDSTCOLOR, GS_BLEND_INVSRCALPHA,
|
GS_BLEND_INVDSTCOLOR, GS_BLEND_INVSRCALPHA,
|
||||||
|
|||||||
Reference in New Issue
Block a user