You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让片段着色器输出至模板附件?实现模板图像复制管线

模板图像复制管线的实现方案

1. 片段着色器输出到模板附件的前提

要让片段着色器直接控制模板输出,需满足以下条件:

  • 若使用OpenGL 4.5及以上版本:核心规范已原生支持片段着色器输出模板值,无需额外扩展。
  • 若使用更低版本:需启用GL_EXT_fragment_shader_stencil_export扩展,并在着色器开头声明#extension GL_EXT_fragment_shader_stencil_export : enable。

同时,帧缓冲必须绑定有效的模板附件(可以是单独的模板缓冲,或深度-模板联合缓冲),且绘制前需配置模板写入权限:调用glStencilMask(0xFF)允许写入所有模板位,同时设置glStencilFunc(GL_ALWAYS, 0, 0xFF)让所有片段通过模板测试,确保输出值能写入附件。

2. 对应gl_FragDepth的模板内置变量

确实存在专门用于控制模板输出的内置变量,作用和gl_FragDepth类似:

  • OpenGL 4.5+核心版本:out int gl_FragStencilRef;
  • 扩展版本(EXT_fragment_shader_stencil_export):out int gl_FragStencilRefEXT;

通过给这个变量赋值,就能直接指定当前片段要写入模板附件的数值。

3. 具体实现代码示例

顶点着色器(最简全屏绘制版本)

#version 450 core
layout (location = 0) in vec2 aPos;

void main() {
    gl_Position = vec4(aPos, 0.0, 1.0);
}

片段着色器(实现模板图像复制)

#version 450 core
layout (binding = 0) uniform sampler2D srcStencilSampler; // 绑定源模板纹理

// 声明模板输出变量
out int gl_FragStencilRef;

void main() {
    // 用texelFetch读取源模板纹理的当前片段值
    // 注意:模板纹理格式通常为GL_STENCIL_INDEX8,采样后r通道对应模板值(0-1范围,需转整数)
    vec4 srcSample = texelFetch(srcStencilSampler, ivec2(gl_FragCoord.xy), 0);
    gl_FragStencilRef = int(srcSample.r * 255.0); // 转换为0-255的整数模板值
}

4. 关键注意事项

  • 源模板转纹理:要将源模板缓冲作为sampler2D读取,需先把模板缓冲创建为纹理(或使用纹理缓冲对象TBO),确保纹理格式与模板缓冲匹配(如GL_STENCIL_INDEX8)。
  • 变量兼容性:如果使用扩展版本,需将gl_FragStencilRef替换为gl_FragStencilRefEXT,并在着色器开头添加扩展声明。

内容的提问来源于stack exchange,提问作者Lucas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 22:37:38