У проблемы есть 2 причины.
Первая действительно проблема Z-боя , вызванная чудовищным расстоянием между ближним и дальним самолетом
gl.Perspective(30, 1, 0.1F, 1.0E+7F);
и тот факт, что при перспективной проекции глубина не является линейной. См. Также Как визуализировать глубину линейно ... .
Это можно улучшить, поместив ближнюю плоскость как можно ближе к геометрии. Поскольку расстояние до объекта составляет 3000,0, а радиус сферы равен 300, ближняя плоскость должна быть меньше 2700,0:
, например * * 1016
gl.Perspective(30, 1, 2690.0F, 5000.0F);
Вторая проблема связана с тем, что сфера состоит из примитивов треугольника. Как вы предложили в своем ответе, вы можете улучшить это, увеличив число примитивов.
Я предоставлю альтернативное решение, используя плоскость отсечения. Клип красный шар внизу и синий шар сверху. Именно в плоскости, где сферы пересекаются, так что колпачок отрезан от каждой сферы.
Плоскость обрезки может быть установлена с помощью glClipPlane
и активирована с помощью glEnable
.
Параметры для плоскости отсечения интерпретируются как Уравнение плоскости .
Первые 3 компонента уравнения плоскости представляют собой вектор нормали к плоскости отсечения. 4-й компонент - это расстояние до начала координат.
Таким образом, уравнение плоскости отсечения для красной сферы должно быть {0, 0, -1, 50}
, а для голубой сферы {0, 0, 1, -50}
.
Обратите внимание, что когда вызывается glClipPlane
, уравнение преобразуется в обратную сторону матрицы вида модели. Таким образом, плоскость отсечения должна быть установлена до преобразования модели, такого как вращение, перемещение и масштабирование.
* * +1036 например,
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);
}