像素着色器PixelShader
2024-05-14
35
0
什么是像素着色器?
像素着色器是针对逐个像素进行的。在光栅化阶段,一个三角形在其所覆盖的每个像素处使用插值来计算相应顶点的各个属性,然后把插值后的顶点传递给像素着色器。
- 像素着色器也是一组指令,这组指令在顶点中像素被渲染时执行。在每个执行时间,都会有很多像素被渲染。(像素的数目依靠屏幕的分辨率决定)
- 像素着色器的指令和顶点着色器的指令非常接近。像素着色器不能像顶点着色器那样,单独存在。他们在运行的时候,必须有一个顶点着色器被激活。
为什么大家要使用像素着色器?
- 像素着色器过去是一种高级图形技术,专门用来提高渲染速度。
- 和顶点着色器一样,使用像素着色器,程序员能自定义渲染每个像素。
像素着色器如何运作?
一个像素着色器操作顶点上单独的像素。和顶点着色器一样,像素着色器源代码也是通过一些API加载到硬件的。
如何创建一个像素着色器?
也和顶点着色器一样,你只需要一个文本编辑器和支持着色器编程的显卡即可。同样,API(Direct3D OpenGL)加载像素着色器代码指令到硬件中。
像素着色器示例
PixelShader.hlsl
Texture2D txY : register(t0);
Texture2D txU : register(t1);
Texture2D txV : register(t2);
SamplerState samLinear : register(s0);
struct PS_INPUT
{
float4 Pos : SV_POSITION;
float2 Tex : TEXCOORD;//纹理坐标
};
float3 yuv_to_rgb(float3 YUV)
{
/*Y'= 0.299*R' + 0.587*G' + 0.114*B'
U'= -0.147*R' - 0.289*G' + 0.436*B' = 0.492*(B'- Y')
V'= 0.615*R' - 0.515*G' - 0.100*B' = 0.877*(R'- Y')
R' = Y' + 1.140*V'
G' = Y' - 0.394*U' - 0.581*V'
B' = Y' + 2.032*U'*/
float u = YUV.y;
float v = YUV.z;
float r = YUV.x + 1.403f*v;
float g = YUV.x - 0.344f*u - 1.403f*v;
float b = YUV.x + 1.770f*u;
/*if (r < 0.018 && g < 0.018 && b < 0.018)
{*/
/*r = (r < 0.018) ? 4.5*r : 1.099*pow(r, 0.45) - 0.099;
g = (g < 0.018) ? 4.5*g : 1.099*pow(g, 0.45) - 0.099;
b = (b < 0.018) ? 4.5*b : 1.099*pow(b, 0.45) - 0.099;*/
/*}
else
{
r = 1.099*pow(r, 0.45) - 0.099;
g = 1.099*pow(g, 0.45) - 0.099;
b = 1.099*pow(b, 0.45) - 0.099;
}*/
return float3(r, g, b);
}
float3 rgb_to_yuv(float3 RGB)
{
float y = dot(RGB, float3(0.299, 0.587, 0.114));
float u = (RGB.z - y) * 0.565;
float v = (RGB.x - y) * 0.713;
return float3(y, u, v);
}
float3 rgb_to_yuv1(float3 RGB)
{
float y = RGB.x * 0.299 + RGB.y * 0.587 + RGB.z * 0.114;
float u = -RGB.x * 0.169 - RGB.y * 0.331 + RGB.z * 0.500;
float v = RGB.x * 0.500 - RGB.y * 0.419 - RGB.z * 0.081;
return float3(y, u, v);
}
float3 yuv_to_rgb1(float3 YUV)
{
float u = YUV.y;
float v = YUV.z;
float r = YUV.x + 1.400*v;
float g = YUV.x - 0.343*u - 0.711*v;
float b = YUV.x + 1.765*u;
return float3(r, g, b);
}
float3 yuv_to_rgb2(float3 YUV)
{
float y = YUV.x;
float u = YUV.y;
float v = YUV.z;
float r = y + 1.140*v;
float g = y - 0.395*u - 0.581*v;
float b = y + 2.032*u;
return float3(r, g, b);
}
float4 PS(PS_INPUT input) : SV_Target
{
//这一行从三个纹理(txY,txU,txV)中分别采样Y、U和V通道的值,并将它们存储在一个4维向量中。
float4 yuva = {txY.Sample(samLinear, input.Tex).r, txU.Sample(samLinear, input.Tex).r, txV.Sample(samLinear, input.Tex).r, 0};
//YUV to RGB uncomment the below 2 lines
yuva -= float4(0, .5f, .5f, 0);
float4 f= float4(yuv_to_rgb2(yuva.xyz), yuva.w); // don't lose alpha
return f;
}
具体的介绍详见:https://www.vaczh.com/article/detail-27.html
PixelShader.hlsl经过编译后为PixelShader.h。和顶点着色器类似:
const BYTE g_PS[] =
{
...
}
在D3D11中:
ID3D11PixelShader* m_PixelShader;
Size = ARRAYSIZE(g_PS);
hr = m_Device->CreatePixelShader(g_PS, Size, nullptr, &m_PixelShader);
if (FAILED(hr))
{
return ProcessFailure(m_Device, L"Failed to create pixel shader in OUTPUTMANAGER", L"Error", hr, SystemTransitionsExpectedErrors);
}
m_DeviceContext->PSSetShader(m_PixelShader, nullptr, 0);