不带hWnd

时间:2018-04-06 11:09:01

标签: windows opengl

我正在尝试使用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来获得颜色和深度。

它正在工作 - 我能够使用这个类渲染到不可见的窗口,然后读取像素并将它们传递给任何感兴趣的人。

但我怀疑我做错了(或者至少不完全正确)。

我的主要问题 - 我仍然需要一个隐形窗口的句柄。我有一个问题 - 是否可以在不创建窗口(可见或隐藏)的情况下执行屏幕外渲染?

0 个答案:

没有答案