複雑な 2D シーンを OpenGL ウィンドウに描画します。ユーザーがシーンのスクリーンショットを撮り、JPG として保存できるようにしたいと考えています。ただし、シーンを画面よりも大きく描画できることを指定できるようにしてほしいです (これにより、より多くの詳細を見ることができるようになります)。
画面に収まるビューポートより大きい数値を指定すると、見えないものはすべてビットマップに描画されません。追跡できなかったこれらの OpenGL 関数のいくつかの動作について、誤った理解をしているように感じます。
renderSize
以下のコードは、プログラムを開始するデフォルトのビューポートよりも小さい場合、完全に正常に動作します。が大きい場合renderSize
、適切なサイズの JPG が作成されますが、画面の表示領域を超えた右側/上部のセクションは単に空白になります。ビューポートをクリックして 2 番目のモニターにドラッグすると、より多くの画像が描画されますがrenderSize
、両方のモニターよりも大きい場合はすべてではありません。画面に表示されるビューポートとは無関係に、この図面を作成するにはどうすればよいですか?
( 7000 x 2000 のような大きな数値で、この関数が呼び出されたときに正しく設定されているrenderLocation
ことを確認できます)renderSize
renderSize
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ウィンドウが発生した場合に備えて、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
}