OpenGL/SharpGL - 仅指向正射投影的近表面
本文关键字:投影 表面 SharpGL OpenGL | 更新日期: 2023-09-27 18:36:24
当您为每个点使用三维创建点并使用正射投影查看点时,是否有理由只显示 -near 表面上的点? 例如,如果使用(SharpGL 方法)gl.Ortho(0, width, height, 0, -10, 10)
,则实际上只显示 z=10 处的点(因为近表面位于 -10)。
我目前正在使用 SharpGL - 但我希望我遇到的问题不是那个特定的实现/库。
编辑:我正在添加下面的代码来演示该问题。 请注意,此示例需要 SharpGL,实际上是对当前 SharpGL 源代码附带的 WPF 示例项目的修改(原始示例项目称为 TwoDSample)。
该项目需要一个 MainWindow.xaml 和一个 MainWindow.xaml.cs。 这是 xaml:
<Window x:Class="TwoDSample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525"
xmlns:my="clr-namespace:SharpGL.WPF;assembly=SharpGL.WPF">
<Grid>
<my:OpenGLControl Name="openGLControl1" OpenGLDraw="openGLControl1_OpenGLDraw" OpenGLInitialized="openGLControl1_OpenGLInitialized"
Resized="openGLControl1_Resized"/>
</Grid>
</Window>
下面是背后的代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using SharpGL.Enumerations;
namespace TwoDSample
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
// NOTE: I use this to restrict the openGLControl1_OpenGLDraw method to
// drawing only once after m_drawCount is set to zero;
int m_drawCount = 0;
private void openGLControl1_OpenGLDraw(object sender, SharpGL.SceneGraph.OpenGLEventArgs args)
{
// NOTE: Only draw once after m_drawCount is set to zero
if (m_drawCount < 1)
{
// Get the OpenGL instance.
var gl = args.OpenGL;
gl.Color(1f, 0f, 0f);
gl.PointSize(2.0f);
// Draw 10000 random points.
gl.Begin(BeginMode.Points);
Random random = new Random();
for (int i = 0; i < 10000; i++)
{
double x = 10 + 400 * random.NextDouble();
double y = 10 + 400 * random.NextDouble();
double z = (double)random.Next(-10, 0);
// Color the point according to z value
gl.Color(0f, 0f, 1f); // default to blue
if (z == -10)
gl.Color(1f, 0f, 0f); // Red for z = -10
else if (z == -1)
gl.Color(0f, 1f, 0f); // Green for z = -1
gl.Vertex(x, y, z);
}
gl.End();
m_drawCount++;
}
}
private void openGLControl1_OpenGLInitialized(object sender, SharpGL.SceneGraph.OpenGLEventArgs args)
{
}
private void openGLControl1_Resized(object sender, SharpGL.SceneGraph.OpenGLEventArgs args)
{
// NOTE: force the draw routine to happen again when resize occurs
m_drawCount = 0;
// Get the OpenGL instance.
var gl = args.OpenGL;
// Create an orthographic projection.
gl.MatrixMode(MatrixMode.Projection);
gl.LoadIdentity();
// NOTE: Basically no matter what I do, the only points I see are those at
// the "near" surface (with z = -zNear)--in this case, I only see green points
gl.Ortho(0, openGLControl1.ActualWidth, openGLControl1.ActualHeight, 0, 1, 10);
// Back to the modelview.
gl.MatrixMode(MatrixMode.Modelview);
}
}
}
感谢MadcoreTom关于深度缓冲区的评论和一些谷歌搜索,我想我找到了(或至少"a")解决方案。 如果我在绘图例程开始时清除深度缓冲区,(如果 z == -9 而不是 z == -10,则颜色点为红色,因为是随机的。Next(-10,0) 不会给出 -10 的值),那么事情似乎按预期工作。
要查看所有 z 值(在 Ortho 限制内)处的点,我只是将 openGlControl1_OpenGLDraw 方法替换为以下内容:
private void openGLControl1_OpenGLDraw(object sender, SharpGL.SceneGraph.OpenGLEventArgs args)
{
// NOTE: Only draw once after m_drawCount is set to zero
if (m_drawCount < 1)
{
// Get the OpenGL instance.
var gl = args.OpenGL;
// ADDED THIS LINE
gl.Clear(SharpGL.OpenGL.GL_DEPTH_BUFFER_BIT);
gl.Color(1f, 0f, 0f);
gl.PointSize(2.0f);
// Draw 10000 random points.
gl.Begin(BeginMode.Points);
Random random = new Random();
for (int i = 0; i < 10000; i++)
{
double x = 10 + 400 * random.NextDouble();
double y = 10 + 400 * random.NextDouble();
double z = (double)random.Next(-10, 0);
// Color the point according to z value
gl.Color(0f, 0f, 1f); // default to blue
if (z == -9)
gl.Color(1f, 0f, 0f); // Red for z = -10
else if (z == -1)
gl.Color(0f, 1f, 0f); // Green for z = -1
gl.Vertex(x, y, z);
}
gl.End();
m_drawCount++;
}
}