OBS画布与输出缩放
2024-12-20
5
0
使用D3D11渲染后的数据位于纹理video->render_texture或者video->output_texture中。
- 如果不需要缩放,则render_texture就是输出的最终纹理
- 如果需要缩放,则output_texture就是缩放后输出的纹理;
缩放很简单,由于是RGBA格式,使用default.effect-DrawAlphaDivide着色器实现。输入参数为render_texture,输出为output_texture。具体过程详见render_output_texture。
static inline gs_texture_t *render_output_texture(struct obs_core_video *video)
{
gs_texture_t *texture = video->render_texture;
gs_texture_t *target = video->output_texture;
uint32_t width = gs_texture_get_width(target);
uint32_t height = gs_texture_get_height(target);
gs_set_render_target(target, NULL);
set_render_size(width, height);
{
gs_enable_depth_test(false);
gs_set_cull_mode(GS_NEITHER);
gs_ortho(0.0f, (float)width, 0.0f, (float)height, -100.0f, 100.0f);
gs_set_viewport(0, 0, width, height);
}
//set paramter
gs_effect_set_texture_srgb(image, texture);
...
}
VS着色器:
uniform float4x4 ViewProj;
struct VertInOut {
float4 pos : POSITION;
float2 uv : TEXCOORD0;
};
VertInOut VSDefault(VertInOut vert_in)
{
VertInOut vert_out;
vert_out.pos = mul(float4(vert_in.pos.xyz, 1.0), ViewProj);
vert_out.uv = vert_in.uv;
return vert_out;
}
VertInOut main(VertInOut vert_in)
{
return VSDefault(vert_in);
}
PS着色器
uniform texture2d image;
sampler_state def_sampler {
Filter = Linear;
AddressU = Clamp;
AddressV = Clamp;
};
struct VertInOut {
float4 pos : POSITION;
float2 uv : TEXCOORD0;
};
float4 PSDrawAlphaDivide(VertInOut vert_in)
{
float4 rgba = image.Sample(def_sampler, vert_in.uv);
rgba.rgb *= (rgba.a > 0.) ? (1. / rgba.a) : 0.;
return rgba;
}
float4 main(VertInOut vert_in) : TARGET
{
return PSDrawAlphaDivide(vert_in);
}
解释:
uniform texture2d image;
sampler_state def_sampler {
Filter = Linear;
AddressU = Clamp;
AddressV = Clamp;
};
- uniform texture2d image;声明一个名为 image 的2D纹理资源,用于存储输入图像。
- sampler_state def_sampler:定义了一个采样器状态 def_sampler,它指定了纹理采样的方式:
- Filter = Linear;:使用线性过滤(双线性插值),使得纹理在放大或缩小时平滑过渡。
- AddressU = Clamp; 和 AddressV = Clamp;当纹理坐标超出 [0, 1] 范围时,使用边缘像素进行填充。
PSDrawAlphaDivide 函数的作用是:
- 使用 def_sampler 从 image 纹理中采样得到当前片段的RGBA颜色值。
- 对于每个像素,检查其 Alpha 值 (rgba.a) 是否大于0:
- 如果 Alpha 值大于0,则将 RGB 分量除以 Alpha 值
(rgba.rgb *= 1. / rgba.a)
,以标准化颜色。 - 如果 Alpha 值等于0,则将 RGB 分量设置为0 (
rgba.rgb *= 0
.),避免除以零的错误。 - •返回处理后的 RGBA 颜色值。