我正在阅读“C#Game Programming For Serious Game Creation”一书中的例子,我看到了一些奇怪的行为。我设置了一个视口和正射投影,然后尝试绘制一个50px宽的三角形。我一开始只看到三角形的一小部分,但是当我调整窗口大小(例如,最大化然后恢复)时,三角形突然显示为正确的大小。
以下是一个重现问题的简单示例:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Tao.OpenGl;
namespace SimpleExample
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
_openGLControl.InitializeContexts();
}
protected override void OnClientSizeChanged(EventArgs e)
{
base.OnClientSizeChanged(e);
int width = ClientSize.Width;
int height = ClientSize.Height;
double halfWidth = (double)width / 2;
double halfHeight = (double)height / 2;
Gl.glViewport(0, 0, width, height);
Gl.glMatrixMode(Gl.GL_PROJECTION);
Gl.glLoadIdentity();
Gl.glOrtho(-halfWidth, halfWidth, -halfHeight, halfHeight, -100, 100);
Gl.glMatrixMode(Gl.GL_MODELVIEW);
Gl.glLoadIdentity();
}
private void _openGLControl_Paint(object sender, PaintEventArgs e)
{
Gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
Gl.glClear(Gl.GL_COLOR_BUFFER_BIT);
Gl.glBegin(Gl.GL_TRIANGLE_STRIP);
{
Gl.glColor4d(1.0, 0.0, 0.0, 0.5);
Gl.glVertex3d(-50, 0, 0);
Gl.glColor3d(0.0, 1.0, 0.0);
Gl.glVertex3d(50, 0, 0);
Gl.glColor3d(0.0, 0.0, 1.0);
Gl.glVertex3d(0, 50, 0);
}
Gl.glEnd();
Gl.glFinish();
}
}
}
在绘制三角形之前程序启动时会触发OnClientSizeChanged事件,但在调整窗口大小之前,视口/ ortho似乎没有任何变化。
我正在使用OpenTk库并包含Tao.OpenGL(如您所见)。我在我的表单上使用SimpleOpenGlControl,其中Dock设置为Fill。在Windows 7上运行VS2012。我希望尽可能贴近书中的示例,而不是使用过剩或任何额外的库。谁能指出我做错了什么?
答案 0 :(得分:2)
更改OpenGL视图的任何方面都需要完全重绘场景。由于典型的OpenGL渲染将包括叠加(HUD,注释等),因此将视口和投影矩阵与绘图分开设置是没有意义的。因此,应在绘图程序中执行glViewport和投影矩阵设置。
窗口大小或其他观看方面的任何更改都必须触发完全重绘,并且在绘图例程中设置视口和投影时会处理完毕,而不需要进一步考虑。
答案 1 :(得分:2)
我的猜测是在OnClientSizeChanged
期间调用了初始InitializeComponent();
,这意味着尚未调用_openGLControl.InitializeContexts();
,并且视口的更改不会应用于您的控件。因此,要修复它,我会在初始化控件的上下文后设置视口。