Reputation: 31
I am working on a Windows Form application, I am drawing rectangles onto a GLControl
in one tab.
After I'm done drawing the rectangles, I am trying to draw them into another GLControl
that is inside another tab.
Currently, for the first tab I am using a lot of for
loops for each kind of object that is created (to display them accordingly); to make the code tidier, and more efficient, I want to draw everything on the first tab into a Texture
bound to a Framebuffer
, and later, use that texture on the other GLControls
to draw over it without damaging the first layout of rectangles.
To debug after writing into the Texture
, I converted the Texture
into a Bitmap
, and saved the Bitmap
as a JPG
and looked at the result using the Windows' native image visualizer.
The problem is that only the stuff that is inside the Viewport
is drawn into the image, so the half of some rectangles and the rectangles outside of the Viewport
are not being drawn, and everything out of the Viewport's
bounds are just zeros (found out using the debugger of Visual Studio and copying and pasting the image into PowerPoint).
I already tinkered with the Viewport's
x
, y
, width
and height
values but nothing changed, only made the background get drawn further out, but the rectangles out of bounds are not drawn into the image.
These are the results that I am getting so far:
This one works well when it is inside the Viewport:
This happens when the image is in the lower left corner (as you can see, there are transparent pixels given that all of their RGBA values are zero:
And this happens when the image is in the upper right corner:
This behavior is given due to my approach to make the texture/image; because there are going to be objects attached to the blue points, I am only reading the pixels that are close to the group of rectangles, giving this clipped appearance (instead of reading the all the pixels of the whole texture).
If it is not clear what I would like to do, I want to render all my objects that are inside and outside the viewport, so I can use the texture on other GLControls.
This is my code:
Button event to create the Framebuffer and do more actions:
private void buttonLoadFrameBuffer_Click(object sender, EventArgs e)
{
this.Enabled = false;
if (V.tunnelList.Count > 0)
{
CalculateTextureSize(
out V.FrameBufferMáxX,
out V.FrameBufferMínX,
out V.FrameBufferMáxY,
out V.FrameBufferMínY,
V.tunnelList
);
V.FrameBuffer = new FrameBuffer(
V.FrameBufferMáxX,
V.FrameBufferMínX,
V.FrameBufferMáxY,
V.FrameBufferMínY
);
RenderScene();
CaptureFramebufferData();
}
this.Enabled = true;
}
My code to render the scene:
private void RenderScene()
{
int width= glControlLayout.Width;
int height= glControlLayout.Height;
GL.BindFramebuffer(FramebufferTarget.Framebuffer, V.FrameBuffer.FramebufferHandle);
GL.Viewport(
0, //x
0, //y
width,
height
);
GL.ClearColor(245f / 255f, 244f / 255f, 239f / 255f, 1f);
GL.Clear(ClearBufferMask.ColorBufferBit);
D.Matrix4 projectionMatrix = D.Matrix4.CreateOrthographicOffCenter(
0,
width,
0,
height,
-1.0f,
1.0f
);
this.ShaderProgram.SetUniform("Transformation", true, projectionMatrix);
DrawObjects();
V.FrameBuffer.Finalized = true;
GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0);
glControlLayout.Refresh();
}
My code to get the framebuffer data:
private void CaptureFramebufferData()
{
int width= V.FrameBufferMáxX - V.FrameBufferMínX;
int heigth = V.FrameBufferMáxY - V.FrameBufferMínY;
GL.BindFramebuffer(FramebufferTarget.Framebuffer, V.FrameBuffer.FramebufferHandle);
byte[] pixels = new byte[width * height * 4];
GL.ReadPixels(
V.FrameBufferMínX,
V.FrameBufferMínY,
width,
height,
OpenTK.Graphics.OpenGL.PixelFormat.Bgra,
PixelType.UnsignedByte,
pixels
);
GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0);
UpdateTexture(pixels, width, height);
}
My code to turn the texture into a bitmap and later into a JPG:
private void UpdateTexture(byte[] pixels, int width, int height)
{
GL.BindTexture(TextureTarget.Texture2D, V.FrameBuffer.TextureColorHandle);
Bitmap bitmap = new Bitmap(
width,
height,
System.Drawing.Imaging.PixelFormat.Format32bppArgb
);
BitmapData bitmapData = bitmap.LockBits(
new Rectangle(0, 0, bitmap.Width, bitmap.Height),
ImageLockMode.WriteOnly,
bitmap.PixelFormat
);
IntPtr ptr = bitmapData.Scan0;
Marshal.Copy(pixels, 0, ptr, pixels.Length);
bitmap.UnlockBits(bitmapData);
bitmap.RotateFlip(RotateFlipType.RotateNoneFlipY);
bitmap.Save("D:\\some\\folder\\image.jpg");
}
Upvotes: 0
Views: 44