在NativeWindow OpenGL控件中渲染

时间:2016-02-09 04:12:42

标签: c# opengl

我使用本机API调用和C#中的NativeWindow创建了自己的OpenGL上下文。我基于WIN32 OpenGL示例并得到了这个:

public class OpenGLControl : System.Windows.Forms.NativeWindow{

        private IntPtr HDC;
        //private Form Parent;

        #region Imports     
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
        static extern IntPtr GetDC(IntPtr hWnd);

        [DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
        static extern int ChoosePixelFormat(IntPtr hdc, [In] ref PIXELFORMATDESCRIPTOR ppfd);

        [DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
        static extern bool SetPixelFormat(IntPtr hdc, int iPixelFormat, ref PIXELFORMATDESCRIPTOR ppfd);

        [StructLayout(LayoutKind.Sequential)]
        struct PIXELFORMATDESCRIPTOR
        {
            ushort nSize;
            ushort nVersion;
            PFD_FLAGS dwFlags;
            PFD_PIXEL_TYPE iPixelType;
            byte cColorBits;
            byte cRedBits;
            byte cRedShift;
            byte cGreenBits;
            byte cGreenShift;
            byte cBlueBits;
            byte cBlueShift;
            byte cAlphaBits;
            byte cAlphaShift;
            byte cAccumBits;
            byte cAccumRedBits;
            byte cAccumGreenBits;
            byte cAccumBlueBits;
            byte cAccumAlphaBits;
            byte cDepthBits;
            byte cStencilBits;
            byte cAuxBuffers;
            PFD_LAYER_TYPES iLayerType;
            byte bReserved;
            uint dwLayerMask;
            uint dwVisibleMask;
            uint dwDamageMask;

            public void Init()
            {
                nSize = (ushort) Marshal.SizeOf(typeof (PIXELFORMATDESCRIPTOR));
                nVersion = 1;
                dwFlags = PFD_FLAGS.PFD_DRAW_TO_WINDOW | PFD_FLAGS.PFD_SUPPORT_OPENGL | PFD_FLAGS.PFD_DOUBLEBUFFER | PFD_FLAGS.PFD_SUPPORT_COMPOSITION;
                iPixelType = PFD_PIXEL_TYPE.PFD_TYPE_RGBA;
                cColorBits = 24;
                cRedBits = cRedShift = cGreenBits = cGreenShift = cBlueBits = cBlueShift = 0;
                cAlphaBits = cAlphaShift = 0;
                cAccumBits = cAccumRedBits = cAccumGreenBits = cAccumBlueBits = cAccumAlphaBits = 0;
                cDepthBits = 32;
                cStencilBits = cAuxBuffers = 0;
                iLayerType = PFD_LAYER_TYPES.PFD_MAIN_PLANE;
                bReserved = 0;
                dwLayerMask = dwVisibleMask = dwDamageMask = 0;
            }
        }
        #endregion

        #region Flags Win32
        [Flags]
        enum PFD_FLAGS : uint 
        {
            PFD_DOUBLEBUFFER = 0x00000001,
            PFD_STEREO = 0x00000002,
            PFD_DRAW_TO_WINDOW = 0x00000004,
            PFD_DRAW_TO_BITMAP = 0x00000008,
            PFD_SUPPORT_GDI = 0x00000010,
            PFD_SUPPORT_OPENGL = 0x00000020,
            PFD_GENERIC_FORMAT = 0x00000040,
            PFD_NEED_PALETTE = 0x00000080,
            PFD_NEED_SYSTEM_PALETTE = 0x00000100,
            PFD_SWAP_EXCHANGE = 0x00000200,
            PFD_SWAP_COPY = 0x00000400,
            PFD_SWAP_LAYER_BUFFERS = 0x00000800,
            PFD_GENERIC_ACCELERATED = 0x00001000,
            PFD_SUPPORT_DIRECTDRAW = 0x00002000,
            PFD_DIRECT3D_ACCELERATED = 0x00004000,
            PFD_SUPPORT_COMPOSITION = 0x00008000,
            PFD_DEPTH_DONTCARE = 0x20000000,
            PFD_DOUBLEBUFFER_DONTCARE = 0x40000000,
            PFD_STEREO_DONTCARE = 0x80000000
        }

        enum PFD_LAYER_TYPES : byte
        {
            PFD_MAIN_PLANE = 0,
            PFD_OVERLAY_PLANE = 1,
            PFD_UNDERLAY_PLANE = 255
        }

        enum PFD_PIXEL_TYPE : byte
        {
            PFD_TYPE_RGBA = 0,
            PFD_TYPE_COLORINDEX = 1
        }       
        #endregion

        public OpenGLControl(Form Parent){

            //this.Parent = Parent;

            CreateParams cp = new CreateParams(){ 
                X = 0, 
                Y = 0, 
                Height = Parent.Height, 
                Width = Parent.Width,
                Parent = Parent.Handle,
                Style = 0x40000000 | 0x10000000 | 0x04000000 | 0x02000000
            };

            CreateHandle(cp);

            HDC = GetDC(Parent.Handle);
            if(!SetPixelFormat(HDC))
                MessageBox.Show("Error creando el control OpenGL", "¡Error!");

            SetShadeMode(ShadeModes.SMOOTH);
            ClearColor(1.0f, 0.0f, 0.0f, 0.5f);
            ClearDepth(1.0f);
            Enable(Caps.DEPTH_TEST);
            DepthFunction(DepthFunctions.LEQUAL);
            Hint(TargetHints.PERSPECTIVE_CORRECTION, TargetModes.NICEST);

        }

        ~OpenGLControl(){
            this.DestroyHandle();
        }

        public void Resize(Form container){
            ViewPort(0,0, container.Width, container.Height);
            SetMatrixMode(MatrixModes.PROJECTION);
            LoadIdentity();
            GLU.Perspective(45.0f, (float)container.Width/(float)container.Height, 0.1f, 100.0f);
            SetMatrixMode(MatrixModes.MODELVIEW);
            LoadIdentity();

        }

        protected Boolean SetPixelFormat(IntPtr hWnd){

            PIXELFORMATDESCRIPTOR PFD = new PIXELFORMATDESCRIPTOR();
            PFD.Init();

            int PixelFormat;

            if((PixelFormat = ChoosePixelFormat(HDC, ref PFD)) == 0){
                MessageBox.Show("ChoosePixel Error");
                return false;
            }

            if(!SetPixelFormat(HDC, PixelFormat, ref PFD)){
                MessageBox.Show("SetPixel Error");
                return false;
            }

            IntPtr HGLRC;
            if((HGLRC = OpenGL.CreateRenderingContext(HDC)) == IntPtr.Zero){
                MessageBox.Show("HGLRC Error");
                return false;
            }

            if(!OpenGL.CreateGLContext(HDC, HGLRC)){
                MessageBox.Show("CreateGL Context Error");
                return false;
            }

            return true;
        }
    }

当我编译代码时,它工作并显示一个白色框,这是GLContext,但现在我不知道如何渲染这个控件。我如何借鉴这一点,我需要覆盖哪些事件?我尝试覆盖父Form个事件OnResize()OnPaint(),但没有任何效果:c 这是我添加到OnPaint事件中的内容:

glShadeModel(GL_SMOOTH);
glClearColor(1.0f, 0.0f, 0.0f, 0.5f);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
//The this:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();   

但在WIN32示例中,这些函数在MessageLoop中完成:

if (!PeekMessage(&msg,NULL,0,0,PM_REMOVE){
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();   
}

但没有任何反应。我需要添加更多内容吗?

编辑:我用作基础的示例:http://www.ism.univmed.fr/mestre/CDRV-C/Documents/7_Doc_Avancee/1/Lesson5.cpp

0 个答案:

没有答案