我在一个OpenGL窗口中绘制了一个复杂的2D场景。我希望用户能够截取场景并将其保存为JPG格式,但我希望他们能够指定大于屏幕大小的场景可以被绘制(这将允许他们看到更多细节等)。当他们指定的数字比适合屏幕的视口更大时,所有对他们不可见的部分都不会被绘制到位图上。我感觉我对一些OpenGL函数的行为有误解,但我一直没有找到原因。以下代码在renderSize比我程序启动时的默认视口小的情况下完全正常。如果renderSize更大,则会创建一个适当大小的JPG,但是超出屏幕可见区域的右/顶部部分为空白。如果我点击并拖动我的视口到第二个监视器上,那么图片的更多部分会被绘制,但如果renderSize大于两个监视器的大小,仍然无法绘制全部。如何使此绘制与屏幕显示的视口无关?(我可以验证调用此函数时renderLocation和renderSize已正确设置,其中renderSize是一些大数,例如7000 x 2000)
public Bitmap renderToBitmap(RenderMode mode)
{
// load a specific ortho projection that will contain the entire graph
GL.MatrixMode(MatrixMode.Projection);
GL.PushMatrix();
GL.LoadIdentity();
GL.Ortho(0, renderSize.Width, 0, renderSize.Height, -1, 1);
GL.Viewport(0, 0, renderSize.Width, renderSize.Height);
GL.MatrixMode(MatrixMode.Modelview);
GL.PushMatrix();
GL.LoadIdentity();
// move the graph so it starts drawing at 0, 0 and fills the entire viewport
GL.Translate(-renderLocation.X, -renderLocation.Y, 0);
GL.ClearColor(Color.White);
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
// render the graph
this.render(mode);
// set up bitmap we will save to
Bitmap bitmap = new Bitmap(renderSize.Width, renderSize.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
BitmapData bData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, bitmap.PixelFormat);
// read the data directly into the bitmap's buffer (bitmap is stored in BGRA)
GL.ReadPixels(0, 0, renderSize.Width, renderSize.Height, OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, bData.Scan0);
bitmap.UnlockBits(bData);
bitmap.RotateFlip(RotateFlipType.RotateNoneFlipY); // compensate for openGL/GDI y-coordinates being flipped
// revert the stuff about openGL we changed
GL.MatrixMode(MatrixMode.Projection);
GL.PopMatrix();
GL.MatrixMode(MatrixMode.Modelview);
GL.PopMatrix();
return bitmap;
}
这是我初始化GL窗口的方式,以防这与内容有关。
private void initGL()
{
GL.ClearColor(Color.AntiqueWhite);
GL.Disable(EnableCap.Lighting);
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
resetCamera();
}
private void resetCamera()
{
offsetX = offsetY = 0; // Bottom-left corner pixel has coordinate (0, 0)
zoomFactor = 1;
setupViewport();
glWindow.Invalidate();
}
private void setupViewport()
{
int w = glWindow.Width;
int h = glWindow.Height;
GL.MatrixMode(MatrixMode.Projection);
GL.LoadIdentity();
GL.Ortho(0 + offsetX, w + offsetX, 0 + offsetY, h + offsetY, -1, 1);
GL.Viewport(0, 0, w, h); // Use all of the glControl painting area
}