HLSL DirectX问题:像素着色器颜色生成异常
HLSL线段颜色渐变问题:方案1失效原因解析
问题场景
通过SV_VertexID索引颜色表生成3条线段,预期每条线段两个顶点颜色不同,中段实现颜色渐变。实际测试结果:
- 方案2可行:顶点着色器(VS)中从颜色表获取对应顶点的颜色,传递给像素着色器(PS)后直接输出,渐变效果正常。
- 方案1失效:将SV_VertexID传递给PS,在PS中通过该索引从颜色表取色,此时每条线段颜色单一,无渐变效果。
测试代码
static float2 vertices[6] = { float2(-0.95f, -0.95f), float2(0.95f, 0.95f), float2(-0.95f, 0), float2(0.95f, 0), float2(-0.95f, 0.95f), float2(0.95f, -0.95f) }; static float3 colors[6] = { float3(1,0,1), // 紫色 float3(0,0,1), // 蓝色 float3(0,1,1), // 青色 float3(0,1,0), // 绿色 float3(1,1,0), // 黄色 float3(1,0,0) // 红色 }; struct Output { float4 pos : SV_POSITION; float3 color1 : COLOR; uint vID : TEXCOORD0; }; //----------------------------------------- 顶点着色器 Output VSMain(uint vID : SV_VertexID) { Output v1; v1.pos = float4(vertices[vID], 0, 1); v1.color1 = colors[vID]; v1.vID = vID; return v1; } //----------------------------------------- 像素着色器 float4 PSMain(Output v1) : SV_Target { float4 color2 = float4(colors[v1.vID],0); // 方案1:失效 //float4 color2 = float4(v1.color1,0); // 方案2:可行 return color2; }
原因解析
核心逻辑:GPU光栅化的属性插值规则
GPU完成顶点着色器计算后,进入光栅化阶段时,会对不同类型的顶点输出属性执行不同处理:
- 浮点类型属性(如
color1):自动执行线性插值,线段上的每个像素会拿到起点和终点属性值的混合结果,这就是颜色渐变的来源。 - 整数/无符号整数类型属性(如
vID):不会执行插值操作,光栅化时会直接取距离当前像素最近的顶点的整数值,因此PS中拿到的vID只会是线段两个端点的其中一个ID,用它取色自然只能得到单一颜色,无法实现渐变。
方案对比
- 方案2直接传递浮点类型的颜色值,利用GPU的自动插值特性,完美实现了线段的颜色渐变。
- 方案1传递的是无符号整数类型的顶点ID,绕过了GPU的插值逻辑,导致无法产生渐变效果。
内容的提问来源于stack exchange,提问作者MarcioAB
相关产品推荐
相关产品推荐

