Arc*_* Pi 7 c++ opengl graphics outlining highlight
我正在尝试实现选择轮廓功能.这就是我现在所要做的.
如您所见,当鼠标悬停并在所选对象周围绘制轮廓时,可以正确选择对象.
我现在想做的是以这种方式勾勒出对象的可见边缘
左边的图像是我现在拥有的,右边的图像是我想要实现的.
这是我现在使用的程序.
void paintGL()
{
/* ... */
int w = geometry().width();
int h = geometry().height();
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_NOTEQUAL, 1, 0xFF);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
glStencilMask(0xFF);
setClearColor(Qt::GlobalColor::darkGray);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glStencilMask(0x00);
DrawGeometry();
if (HoveredSphere != RgbFromColorToString(Qt::GlobalColor::black))
{
glBindFramebuffer(GL_FRAMEBUFFER, addFBO(FBOIndex::OUTLINE));
{
glStencilFunc(GL_ALWAYS, 1, 0xFF);
glStencilMask(0xFF);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
DrawOutline(HoveredSphere, 1.0f - 0.025f);
}
glBindFramebuffer(GL_FRAMEBUFFER, defaultFramebufferObject());
glBindFramebuffer(GL_READ_FRAMEBUFFER, addFBO(FBOIndex::OUTLINE));
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, defaultFramebufferObject());
{
// copy stencil buffer
GLbitfield mask = GL_STENCIL_BUFFER_BIT;
glBlitFramebuffer(0, 0, w, h, 0, 0, w, h, mask, GL_NEAREST);
glStencilFunc(GL_NOTEQUAL, 1, 0xFF);
glStencilMask(0x00);
glDepthFunc(GL_LEQUAL);
DrawOutline(HoveredSphere, 1.0f);
}
glBindFramebuffer(GL_FRAMEBUFFER, defaultFramebufferObject());
}
update();
}
Run Code Online (Sandbox Code Playgroud)
其中DrawGeometry绘制的所有对象,并DrawOutline绘制由作为第二个参数传递的因子按比例缩放所选择的对象.
谢谢你的任何建议.
按照@MichaelMahn的提示,我找到了解决方案.
首先,我在纹理中绘制所选对象的可见部分的轮廓.
然后我使用这个纹理通过检查相邻像素来计算轮廓,以确定我是否站在轮廓的边缘.
大纲片段着色器
#version 450
uniform sampler2D silhouette;
in FragData
{
smooth vec2 coords;
} frag;
out vec4 PixelColor;
void main()
{
// if the pixel is black (we are on the silhouette)
if (texture(silhouette, frag.coords).xyz == vec3(0.0f))
{
vec2 size = 1.0f / textureSize(silhouette, 0);
for (int i = -1; i <= +1; i++)
{
for (int j = -1; j <= +1; j++)
{
if (i == 0 && j == 0)
{
continue;
}
vec2 offset = vec2(i, j) * size;
// and if one of the neighboring pixels is white (we are on the border)
if (texture(silhouette, frag.coords + offset).xyz == vec3(1.0f))
{
PixelColor = vec4(vec3(1.0f), 1.0f);
return;
}
}
}
}
discard;
}
Run Code Online (Sandbox Code Playgroud)
paintgl
void paintGL()
{
int w = geometry().width();
int h = geometry().height();
setClearColor(Qt::GlobalColor::darkGray);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
DrawGeometry();
// if we hover a sphere
if (HoveredSphere != RgbFromColorToString(Qt::GlobalColor::black))
{
glBindFramebuffer(GL_READ_FRAMEBUFFER, defaultFramebufferObject());
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, addFBO(FBOIndex::SILHOUETTE));
{
// copy depth buffer
GLbitfield mask = GL_DEPTH_BUFFER_BIT;
glBlitFramebuffer(0, 0, w, h, 0, 0, w, h, mask, GL_NEAREST);
// set clear color
setClearColor(Qt::GlobalColor::white);
// enable depth test
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
// clear color buffer
glClear(GL_COLOR_BUFFER_BIT);
// draw silhouette
DrawSilhouette(HoveredSphere);
}
glBindFramebuffer(GL_FRAMEBUFFER, defaultFramebufferObject());
// clear depth buffer
glClear(GL_DEPTH_BUFFER_BIT);
// draw outline
DrawOutline();
}
}
Run Code Online (Sandbox Code Playgroud)
问题 ::现在我想参数化轮廓的宽度,其厚度当前固定为1像素.
非常感谢您的任何建议!
| 归档时间: |
|
| 查看次数: |
1122 次 |
| 最近记录: |