我的游戏是在C#中使用OpenTK,它是OpenGL的包装器。我正在渲染我的迷你地图,如下所示。问题是物体没有被夹在边缘,所以它们会流血。我可以渲染一个较粗的边框来隐藏它,但这并不理想,它不适用于较大的物体。可能存在轨迹线和其他东西也超出界限。我只是使用基本原语渲染它们。
我该如何剪裁这个区域?有没有办法将它渲染到隐藏的画布然后只复制圆形区域?
解
@BDL回答了这个问题,但我不得不调整更多的东西才能让它发挥作用,所以这里有完整的解决方案,万一有人发现它有用:
在GameWindow构造函数GraphicsMode param中启用模板缓冲区。
private static OpenTK.Graphics.GraphicsMode GraphicsMode {
get {
var defaultMode = OpenTK.Graphics.GraphicsMode.Default;
var custom = new OpenTK.Graphics.GraphicsMode(
defaultMode.ColorFormat,
defaultMode.Depth,
1, // enable stencil buffer
defaultMode.Samples,
defaultMode.ColorFormat,
defaultMode.Buffers,
defaultMode.Stereo);
return custom;
}
}
public BaseHelioUI(int windowWidth, int windowHeight)
: base(
windowWidth,
windowHeight,
BaseHelioUI.GraphicsMode,
"",
GameWindowFlags.Default )
{
然后使用此块绘制模板,在我的情况下是一个圆圈:
GL.Enable(EnableCap.StencilTest);
GL.StencilFunc(StencilFunction.Always, 1, 0xFF);
GL.StencilOp( StencilOp.Keep, StencilOp.Keep, StencilOp.Replace );
GL.Clear(ClearBufferMask.StencilBufferBit);
// draw background & outline
this.Renderer.DrawCircle(
this.MinimapScreenCenter,
SENSOR_RANGE_IN_METERS * this.GameMetersToMinimapUnitsFactor,
Colors.ReduceAlpha( Colors.Black, MINIMAP_BACKGROUND_OPACITY )
//Colors.ReduceAlpha( Colors.DarkGrey, MINIMAP_BACKGROUND_OUTLINE_OPACITY),
//MINI_MAP_BORDER_WIDTH
);
GL.Enable(EnableCap.StencilTest);
GL.StencilFunc(StencilFunction.Equal, 1, 0xFF);
GL.StencilOp(StencilOp.Keep, StencilOp.Keep, StencilOp.Keep);
然后在该区域内绘制您想要的所有其他内容,在我的情况下,这是小地图上的项目。
然后,当您完成模板使用时,只需清除它,以便其他所有内容都可以正常运行。就我而言,这是在RenderMinimap方法的最后。
// disable stencil
GL.Clear(ClearBufferMask.StencilBufferBit);
GL.Disable(EnableCap.StencilTest);
这里生成的迷你地图正确剪裁了圆圈边缘的项目。看起来很棒。 (船舶在游戏空间,而不是在小地图上)
答案 0 :(得分:1)
使用模板缓冲区可以在任意区域进行剪切:
首先用0(glClear
)清除模板缓冲区。
接下来,在启用以下模板操作的情况下渲染背景圆(剪切区域):
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_ALWAYS, 1, 0xFF);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
这将为圆圈覆盖的所有像素将模板缓冲区设置为1。
现在渲染应在圆圈内显示的内容时,请使用以下设置:
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_EQUAL, 1, 0xFF);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
此处,模板测试仅在模板缓冲区中已存储1个位置时才成功(对于剪切区域内的像素仅适用)。在其他地方,模板测试将失败,并且不会呈现任何内容。
请勿忘记确保您的帧缓冲区有可用的模板缓冲区。