Использование OpenTK (z-indexing)
Я делаю нечто среднее между следованием некоторым учебникам NeHe (перевод их на OpenTK) и образцом OpenTK, который я нашел в Интернете, чтобы нарисовать треугольник (для простой начальной настройки):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Diagnostics;
using System.IO;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
using System.Windows.Forms;
namespace GravSimBasic
{
class GLMain : GameWindow
{
int vbo;
Vector3[,] vertices;
float time = 0.01f;
void CreateVertexBuffer()
{
vertices = new Vector3[2,3];
vertices[0,0] = new Vector3(-1f, -1f, (float)Math.Sin(time));
vertices[0, 1] = new Vector3(0.5f, -1f, (float)Math.Sin(time));
vertices[0, 2] = new Vector3(-0.25f, 1f, -(float)Math.Sin(time));
vertices[1, 0] = new Vector3(-0.5f, -1f, (float)Math.Cos(time));
vertices[1, 1] = new Vector3(1f, -1f, (float)Math.Cos(time));
vertices[1, 2] = new Vector3(0.25f, 1f, -(float)Math.Cos(time));
//MessageBox.Show("Length: " + vertices.Length.ToString());
GL.GenBuffers(1, out vbo);
GL.BindBuffer(BufferTarget.ArrayBuffer, vbo);
GL.BufferData<Vector3>(BufferTarget.ArrayBuffer,
new IntPtr(vertices.Length * Vector3.SizeInBytes),
vertices, BufferUsageHint.StaticDraw);
}
protected override void OnLoad(EventArgs e)
{
//set the window area
GL.Viewport(0, 0, 400, 400);
//background color
GL.ClearColor(Color.Black);
//set the view area
GL.MatrixMode(MatrixMode.Projection);
GL.LoadIdentity();
GL.Ortho(-2, 2, -2, 2, 2, -2);
//now back to 'scene editing' mode
GL.MatrixMode(MatrixMode.Modelview);
GL.LoadIdentity();
//make things look nice
GL.ShadeModel(ShadingModel.Smooth);
//set up our z-rendering logic
GL.ClearDepth(2.0000f);
GL.Enable(EnableCap.DepthTest);
GL.DepthFunc(DepthFunction.Lequal);
//other improvements to quality
GL.Hint(HintTarget.PerspectiveCorrectionHint, HintMode.Nicest);
GL.Hint(HintTarget.LineSmoothHint, HintMode.Nicest);
//initialize our scene data
CreateVertexBuffer();
}
protected override void OnRenderFrame(FrameEventArgs e)
{
time += 0.01f;
vertices[0, 0].Z = (float)Math.Sin(time);
vertices[0, 1].Z = (float)Math.Sin(time);
vertices[0, 2].Z = -(float)Math.Sin(time);
vertices[1, 0].Z = (float)Math.Cos(time);
vertices[1, 1].Z = (float)Math.Cos(time);
vertices[1, 2].Z = -(float)Math.Cos(time);
GL.BufferData<Vector3>(BufferTarget.ArrayBuffer,
new IntPtr(vertices.Length * Vector3.SizeInBytes),
vertices, BufferUsageHint.StaticDraw);
System.Threading.Thread.Sleep(10);
GL.Clear(ClearBufferMask.ColorBufferBit);
GL.EnableVertexAttribArray(0);
GL.BindBuffer(BufferTarget.ArrayBuffer, vbo);
GL.Color4(0.75f,0.0f,0.0f,0.25f);
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 0, 0);
GL.DrawArrays(BeginMode.Triangles, 0, 3);
GL.Color4(0.0f, 0.75f, 0.0f, 0.55f);
GL.VertexAttribPointer(3, 3, VertexAttribPointerType.Float, false, 0, 0);
GL.DrawArrays(BeginMode.Triangles, 3, 3);
GL.DisableVertexAttribArray(0);
SwapBuffers();
}
}
}
Я подозреваю, что проблема в строках 58-60, но я изменил значение в строке 58 между -2.0, 0.00001 и 2.0, ни один не изменил результаты. Впрочем, это может быть перспективная установка на несколько строк раньше. Я испробовал почти все функции, доступные в качестве параметра для строки 60 - Lequal кажется лучшим вариантом, как я и ожидал, и он дает наиболее близкий результат к тому, что я хочу, но это не совсем правильно.
Установка: есть зеленый и красный треугольник. Они частично перекрываются по оси XY. Верхняя ось z одного из них отображается с помощью функции -sin(время), а нижняя - с помощью функции sin(время). Другой использует cos() вместо sin, но в остальном тот же. Значение "time" меняет каждый рендеринг.
Что я хочу / ожидаю: два перекрывающихся треугольника - один красный, один зеленый. Поскольку это вращается назад и вперед, непересекающаяся часть каждого должна всегда быть видимой, и перекрывающиеся части должны показывать только передний треугольник.
Что я получаю: (а) ничего (б) отображение обоих треугольников, один поверх другого. (c) Изменяющееся изображение битов одного, обоих или ни одного из треугольников - даже если один или оба показывают, это биты любого треугольника, которые должны быть видимыми, которые отсутствуют (фон).
Если я уберу время, он покажет правильный снимок - красный треугольник спереди в нижней половине и зеленый спереди сверху.
Кто-нибудь может помочь диагностировать это?
1 ответ
В строке 86 вы очищаете только цветной буфер, а не буфер глубины, поэтому любые изменения в 58 не будут иметь никакого эффекта:
GL.Clear(ClearBufferMask.ColorBufferBit);
Я никогда не использовал OpenTK, но я предполагаю, что нужно что-то вроде этого:
GL.Clear(ClearBufferMask.ColorBufferBit|ClearBufferMask.DepthBufferBit);