我正在尝试使用imlement类来执行屏幕外渲染。
这是我到目前为止所写的内容:
public class OffscreenRenderer
{
private uint[] m_fbo_id = new uint[1];
private uint[] m_rbo_id = new uint[2];
private Size m_size = new Size();
private Graphics m_graphics = null;
private IntPtr m_hDC = IntPtr.Zero;
private IntPtr m_hRC = IntPtr.Zero;
public void Initialize(object parameter)
{
IntPtr? hWnd = parameter as IntPtr?;
if (hWnd.HasValue && hWnd.Value != IntPtr.Zero)
{
RECT bounds = new RECT();
User32.GetWindowRect(hWnd.Value, ref bounds);
m_size.Width = bounds.right - bounds.left;
m_size.Height = bounds.bottom - bounds.top;
if (m_hDC == IntPtr.Zero && m_graphics == null)
{
m_graphics = Graphics.FromHwnd(hWnd.Value);
if (m_graphics != null)
{
m_hDC = m_graphics.GetHdc();
if (m_hDC != IntPtr.Zero)
{
if (InitPixelFormat(m_hDC))
{
m_hRC = OpenGL32.wglCreateContext(m_hDC);
if (m_hRC != IntPtr.Zero)
{
if (OpenGL32.wglMakeCurrent(m_hDC, m_hRC))
{
OpenGL32.ReadExtensions();
if (OpenGL32.SupportsFBO)
{
uint[] ids = new uint[1];
OpenGL32.glGenFramebuffers(1, m_fbo_id);
OpenGL32.glGenRenderbuffers(2, m_rbo_id);
OpenGL32.glBindFramebuffer(OpenGL32.GL_FRAMEBUFFER_EXT, m_fbo_id[0]);
OpenGL32.glBindRenderbuffer(OpenGL32.GL_RENDERBUFFER, m_rbo_id[0]);
OpenGL32.glRenderbufferStorage(OpenGL32.GL_RENDERBUFFER, OpenGL32.GL_RGBA, m_size.Width, m_size.Height);
OpenGL32.glFramebufferRenderbuffer(OpenGL32.GL_FRAMEBUFFER, OpenGL32.GL_COLOR_ATTACHMENT0, OpenGL32.GL_RENDERBUFFER, m_rbo_id[0]);
OpenGL32.glBindRenderbuffer(OpenGL32.GL_RENDERBUFFER, m_rbo_id[1]);
OpenGL32.glRenderbufferStorage(OpenGL32.GL_RENDERBUFFER, OpenGL32.GL_DEPTH_COMPONENT, m_size.Width, m_size.Height);
OpenGL32.glFramebufferRenderbuffer(OpenGL32.GL_FRAMEBUFFER, OpenGL32.GL_DEPTH_ATTACHMENT, OpenGL32.GL_RENDERBUFFER, m_rbo_id[1]);
OpenGL32.glBindFramebuffer(OpenGL32.GL_FRAMEBUFFER_EXT, 0);
}
}
}
}
}
}
}
}
}
protected bool InitPixelFormat(IntPtr hDC)
{
bool result = false;
PIXELFORMATDESCRIPTOR pfd = new PIXELFORMATDESCRIPTOR()
{
nSize = (ushort)Marshal.SizeOf(typeof(PIXELFORMATDESCRIPTOR)),/* Size of this structure */
nVersion = 1, /* Version of this structure */
dwFlags = OpenGL32.PFD_DRAW_TO_WINDOW | /* Draw to Window */
OpenGL32.PFD_DOUBLEBUFFER | /* Double buffered mode */
OpenGL32.PFD_SUPPORT_OPENGL, /* Support OpenGL calls in window */
iPixelType = OpenGL32.PFD_TYPE_RGBA, /* RGBA Color mode */
cColorBits = 32, /* Want 32 bit color */
cDepthBits = 16 /* Size of depth buffer */
};
// Choose a pixel format that best matches that described in pfd
int nPixelFormat = GDI32.ChoosePixelFormat(hDC, ref pfd);
if (nPixelFormat != 0)
{
// Set the pixel format for the device context
result = GDI32.SetPixelFormat(hDC, nPixelFormat, ref pfd);
}
return result;
}
public void Render()
{
OpenGL32.wglMakeCurrent(m_hDC, m_hRC);
if (CheckFBO())
{
OpenGL32.glBindFramebuffer(OpenGL32.GL_FRAMEBUFFER_EXT, m_fbo_id[0]);
OpenGL32.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
OpenGL32.glClear(OpenGL32.GL_COLOR_BUFFER_BIT | OpenGL32.GL_DEPTH_BUFFER_BIT);
// draw something
OpenGL32.glFlush();
// place to read pixels
OpenGL32.glBindFramebuffer(OpenGL32.GL_FRAMEBUFFER_EXT, 0);
}
}
public void Release()
{
OpenGL32.wglMakeCurrent(m_hDC, m_hRC);
if (OpenGL32.SupportsFBO)
{
OpenGL32.glDeleteRenderbuffers(2, m_rbo_id);
OpenGL32.glDeleteFramebuffers(1, m_fbo_id);
}
OpenGL32.wglMakeCurrent(IntPtr.Zero, IntPtr.Zero);
if (m_hRC != IntPtr.Zero)
{
OpenGL32.wglDeleteContext(m_hRC);
m_hRC = IntPtr.Zero;
}
if (m_graphics != null)
{
m_graphics.ReleaseHdc();
m_graphics = null;
m_hDC = IntPtr.Zero;
}
GC.Collect();
}
private static bool CheckFBO()
{
return OpenGL32.SupportsFBO && OpenGL32.glCheckFramebufferStatus(OpenGL32.GL_FRAMEBUFFER_EXT) == OpenGL32.GL_FRAMEBUFFER_COMPLETE_EXT;
}
}
正如你所看到的,我正在使用带有两个RBO的FBO来获得颜色和深度。
它正在工作 - 我能够使用这个类渲染到不可见的窗口,然后读取像素并将它们传递给任何感兴趣的人。
但我怀疑我做错了(或者至少不完全正确)。
我的主要问题 - 我仍然需要一个隐形窗口的句柄。我有一个问题 - 是否可以在不创建窗口(可见或隐藏)的情况下执行屏幕外渲染?