OpenGL重叠丑陋的渲染

标签 opengl opengl-compat

我正在尝试使用 OpenGL 2.1 渲染场景,但重叠形状的边框很奇怪。我测试了一些 OpenGL 初始化,但没有任何改变。我将问题简化为一个简单的测试应用程序,其中包含 2 个球体,但结果相同。

我尝试了一些关于 Gl_DEPTH_TEST 的方法,启用/禁用平滑但没有成功。

这是我使用 2 个 gluSphere 的结果:

enter image description here

当一条线足以分隔蓝色和红色的面时,我们可以看到某种锯齿......

我使用SharpGL但我认为这并不重要(因为我仅将它用作 OpenGL 包装器)。这是我渲染相同内容的最简单的代码(您可以将其复制到表单中进行测试):

OpenGL gl;
IntPtr hdc;
int cpt;

private void Init()
{
    cpt = 0;
    hdc = this.Handle;

    gl = new OpenGL();
    gl.Create(SharpGL.Version.OpenGLVersion.OpenGL2_1, RenderContextType.NativeWindow, 500, 500, 32, hdc);

    gl.Enable(OpenGL.GL_DEPTH_TEST);
    gl.DepthFunc(OpenGL.GL_LEQUAL);

    gl.ClearColor(1.0F, 1.0F, 1.0F, 0);
    gl.ClearDepth(1);

    gl.MatrixMode(OpenGL.GL_PROJECTION);
    gl.Perspective(30, 1, 0.1F, 1.0E+7F);

    gl.MatrixMode(OpenGL.GL_MODELVIEW);
    gl.LookAt(0, 3000, 0, 0, 0, 0, 0, 0, 1);
}

private void Render(int angle)
{
    gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT | OpenGL.GL_STENCIL_BUFFER_BIT);

    RenderSphere(gl, 0, 0, 0, 0, 300, Color.Red);
    RenderSphere(gl, 0, 0, 100, angle, 300, Color.Blue);

    gl.Blit(hdc);
}

private void RenderSphere(OpenGL gl, int x, int y, int z, int angle, int radius, Color col)
{
    IntPtr obj = gl.NewQuadric();

    gl.PushMatrix();
    gl.Translate(x, y, z);
    gl.Rotate(angle, 0, 0);

    gl.Color(new float[] { col.R / 255f, col.G / 255f, col.B / 255f, col.A / 255f });
    gl.QuadricDrawStyle(obj, OpenGL.GLU_FILL);
    gl.Sphere(obj, radius, 20, 10);

    gl.Color(new float[] { 0, 0, 0, 1 });
    gl.QuadricDrawStyle(obj, OpenGL.GLU_SILHOUETTE);
    gl.Sphere(obj, radius, 20, 10);

    gl.DeleteQuadric(obj);

    gl.PopMatrix();
}

提前感谢您的建议!

编辑:

我测试过但没有成功:

gl.Enable(OpenGL.GL_LINE_SMOOTH);
gl.Enable(OpenGL.GL_POLYGON_SMOOTH);
gl.ShadeModel(OpenGL.GL_SMOOTH);

gl.Hint(OpenGL.GL_LINE_SMOOTH_HINT, OpenGL.GL_NICEST);
gl.Hint(OpenGL.GL_POLYGON_SMOOTH_HINT, OpenGL.GL_NICEST);
gl.Hint(OpenGL.GL_PERSPECTIVE_CORRECTION_HINT, OpenGL.GL_NICEST);

EDIT2:有更多面孔,有线条和没有线条的图像

enter image description here

它……不同……但并不令人愉快。

最佳答案

该问题有 2 个原因。

第一个确实是 Z-fighting问题是由近平面和远平面之间的巨大距离引起的

gl.Perspective(30, 1, 0.1F, 1.0E+7F);

事实上,在透视投影中,深度不是线性的。另请参阅How to render depth linearly ... .

这可以通过将近平面尽可能靠近几何体来改进。由于到物体的距离为 3000.0,球体半径为 300,因此近平面必须小于 2700.0:

例如

gl.Perspective(30, 1, 2690.0F, 5000.0F);

第二个问题是由球体由三角形基元组成的事实引起的。正如您在答案中所建议的,您可以通过增加基元的数量来改进这一点。

我将通过使用裁剪平面提供替代解决方案。夹住底部的红色球体和顶部的蓝色球体。正好在球体相交的平面上,以便从每个球体上切掉一个盖子。
剪裁平面可以通过 glClipPlane 设置并通过 glEnable 启用。
剪切平面的参数被解释为 Plane Equation 。 平面方程的前 3 个分量是剪切平面的法向量。第四个分量是到原点的距离。

因此,红色球体的裁剪平面方程必须为 {0, 0, -1, 50},蓝色球体的裁剪平面方程必须为 {0, 0, 1, -50}
请注意,当调用glClipPlane时,方程将通过模型 View 矩阵的逆矩阵进行变换。因此,必须在进行旋转、平移和缩放等模型变换之前设置裁剪平面。

例如

private void Render(int angle)
{
    gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT | OpenGL.GL_STENCIL_BUFFER_BIT);

    double[] plane1 = new double[] {0, 0, -1, 50};
    RenderSphere(gl, 0, 0, 0, 0, 300, Color.Red, plane1);

    double[] plane2 = new double[] {0, 0, 1, -50};
    RenderSphere(gl, 0, 0, 100, angle, 300, Color.Blue, plane2);

    gl.Blit(hdc);
}
private void RenderSphere(
    OpenGL gl, int x, int y, int z, int angle, int radius,
    Color col, double[] plane)
{
    IntPtr obj = gl.NewQuadric();

    gl.ClipPlane(OpenGL.GL_CLIP_PLANE0, plane);
    gl.Enable(OpenGL.GL_CLIP_PLANE0);

    gl.PushMatrix();
    gl.Translate(x, y, z);
    gl.Rotate(angle, 0, 0);

    gl.Color(new float[] { col.R / 255f, col.G / 255f, col.B / 255f, col.A / 255f });
    gl.QuadricDrawStyle(obj, OpenGL.GLU_FILL);
    gl.Sphere(obj, radius, 20, 10);

    gl.Color(new float[] { 0, 0, 0, 1 });
    gl.QuadricDrawStyle(obj, OpenGL.GLU_SILHOUETTE);
    gl.Sphere(obj, radius, 20, 10);

    gl.DeleteQuadric(obj);

    gl.PopMatrix();

    gl.Disable(OpenGL.GL_CLIP_PLANE0);
}

关于OpenGL重叠丑陋的渲染,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56056083/

相关文章:

c++ - 如何重新创建/修改正交投影矩阵 (OpenGL)

linux - 获取 EGL DRM/KMS 应用程序的屏幕截图

c++ - QT OpenGL无法完全渲染立方体吗?

java - 在 Java 中使用 GLUT 库

c++ - 在 C++ 中使用遗留 OpenGL(立即模式)画一条粗线

c - 在原点和用户给定的旋转点处相对于其坐标保持相同的三角形?

c - opengl 不显示 renderFunction 的输出

c++ - 鼠标单击OpenGL无法围绕其自身中心旋转对象

c++ - 如何在 Windows 上安装 FTGL 库?

C++ 顶点缓冲区问题