定制cocos2d的GLView
使用场景需求:将cocos2d 的输出窗口设置为一个子窗口,父窗口其它部分仍然有控件 cocos2d功能强大,但是却不好整合进各种gdi和MFC程序中,有些实现是改cocos2d的项目源代码,这样的话,后续升级版本麻烦些,本文提供的方法可以不修改cocos2d源码 实现步骤1.从cocos2d::GLView派生类WGLView,需要实现 end,swapBuffers,isOpenGLReady,setIMEKeyboardState,windowShouldClose,getWin32Window 这几个虚函数 2.windows 下的 OpenGL初始化流程有这么几项:
代码(适用于cocos2d 3.13)
Application
static bool glew_dynamic_binding() { const char *gl_extensions = (const char*)glGetString(GL_EXTENSIONS); // If the current opengl driver doesn't have framebuffers methods,check if an extension exists if (glGenFramebuffers == nullptr) { log("OpenGL: glGenFramebuffers is nullptr,try to detect an extension"); if (strstr(gl_extensions,"ARB_framebuffer_object")) { log("OpenGL: ARB_framebuffer_object is supported"); glIsRenderbuffer = (PFNGLISRENDERBUFFERPROC)wglGetProcAddress("glIsRenderbuffer"); glBindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC)wglGetProcAddress("glBindRenderbuffer"); glDeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSPROC)wglGetProcAddress("glDeleteRenderbuffers"); glGenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC)wglGetProcAddress("glGenRenderbuffers"); glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEPROC)wglGetProcAddress("glRenderbufferStorage"); glGetRenderbufferParameteriv = (PFNGLGETRENDERBUFFERPARAMETERIVPROC)wglGetProcAddress("glGetRenderbufferParameteriv"); glIsFramebuffer = (PFNGLISFRAMEBUFFERPROC)wglGetProcAddress("glIsFramebuffer"); glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC)wglGetProcAddress("glBindFramebuffer"); glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC)wglGetProcAddress("glDeleteFramebuffers"); glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC)wglGetProcAddress("glGenFramebuffers"); glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC)wglGetProcAddress("glCheckFramebufferStatus"); glFramebufferTexture1D = (PFNGLFRAMEBUFFERTEXTURE1DPROC)wglGetProcAddress("glFramebufferTexture1D"); glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC)wglGetProcAddress("glFramebufferTexture2D"); glFramebufferTexture3D = (PFNGLFRAMEBUFFERTEXTURE3DPROC)wglGetProcAddress("glFramebufferTexture3D"); glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFERPROC)wglGetProcAddress("glFramebufferRenderbuffer"); glGetFramebufferAttachmentParameteriv = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC)wglGetProcAddress("glGetFramebufferAttachmentParameteriv"); glGenerateMipmap = (PFNGLGENERATEMIPMAPPROC)wglGetProcAddress("glGenerateMipmap"); } else if (strstr(gl_extensions,"EXT_framebuffer_object")) { log("OpenGL: EXT_framebuffer_object is supported"); glIsRenderbuffer = (PFNGLISRENDERBUFFERPROC)wglGetProcAddress("glIsRenderbufferEXT"); glBindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC)wglGetProcAddress("glBindRenderbufferEXT"); glDeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSPROC)wglGetProcAddress("glDeleteRenderbuffersEXT"); glGenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC)wglGetProcAddress("glGenRenderbuffersEXT"); glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEPROC)wglGetProcAddress("glRenderbufferStorageEXT"); glGetRenderbufferParameteriv = (PFNGLGETRENDERBUFFERPARAMETERIVPROC)wglGetProcAddress("glGetRenderbufferParameterivEXT"); glIsFramebuffer = (PFNGLISFRAMEBUFFERPROC)wglGetProcAddress("glIsFramebufferEXT"); glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC)wglGetProcAddress("glBindFramebufferEXT"); glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC)wglGetProcAddress("glDeleteFramebuffersEXT"); glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC)wglGetProcAddress("glGenFramebuffersEXT"); glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC)wglGetProcAddress("glCheckFramebufferStatusEXT"); glFramebufferTexture1D = (PFNGLFRAMEBUFFERTEXTURE1DPROC)wglGetProcAddress("glFramebufferTexture1DEXT"); glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC)wglGetProcAddress("glFramebufferTexture2DEXT"); glFramebufferTexture3D = (PFNGLFRAMEBUFFERTEXTURE3DPROC)wglGetProcAddress("glFramebufferTexture3DEXT"); glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFERPROC)wglGetProcAddress("glFramebufferRenderbufferEXT"); glGetFramebufferAttachmentParameteriv = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC)wglGetProcAddress("glGetFramebufferAttachmentParameterivEXT"); glGenerateMipmap = (PFNGLGENERATEMIPMAPPROC)wglGetProcAddress("glGenerateMipmapEXT"); } else { log("OpenGL: No framebuffers extension is supported"); log("OpenGL: Any call to Fbo will crash!"); return false; } } return true; } static bool initGlew() { GLenum GlewInitResult = glewInit(); if (GLEW_OK != GlewInitResult) return false; //must be called after calling wglMakeCurrent if (glew_dynamic_binding() == false) return false; return true; } class AppDelegate : public cocos2d::Application { float sceneWidth_,sceneHeight_,frameRate_; HWND hwnd_; cocos2d::GLView *glview_; public: AppDelegate(float sceneWidth,float sceneHeight,float frameRate,HWND hwndRender) : sceneWidth_(sceneWidth),sceneHeight_(sceneHeight),frameRate_(frameRate),hwnd_(hwndRender),glview_(nullptr) { extern cocos2d::GLView* CreateWGLView(HWND); glview_ = CreateWGLView(hwnd_); } virtual bool applicationDidFinishLaunching() { // execute in engine thread glview_->setFrameSize(sceneWidth_,sceneHeight_); glview_->setDesignResolutionSize(sceneWidth_,ResolutionPolicy::NO_BORDER); extern void ActiveWGLView(cocos2d::GLView *); ActiveWGLView(glview_); initGlew(); auto director = Director::getInstance(); director->setOpenGLView(glview_); director->setContentScaleFactor(1.0); director->setDisplayStats(false); director->setAnimationInterval(1.0 / frameRate_); return true; } virtual void applicationDidEnterBackground() { Director::getInstance()->stopAnimation(); } virtual void applicationWillEnterForeground() { Director::getInstance()->startAnimation(); } };GLView static int findPixelFormat(HDC hdc,int colorBits,int depthBits,int stencilBits) { int currMode; // pixel format mode ID int bestMode = 0; // return value,best pixel format int currScore = 0; // points of current mode int bestScore = 0; // points of best candidate PIXELFORMATDESCRIPTOR pfd; // search the available formats for the best mode bestMode = 0; bestScore = 0; for (currMode = 1; ::DescribePixelFormat(hdc,currMode,sizeof(pfd),&pfd) > 0; ++currMode) { // ignore if cannot support opengl if (!(pfd.dwFlags & PFD_SUPPORT_OPENGL)) continue; // ignore if cannot render into a window if (!(pfd.dwFlags & PFD_DRAW_TO_WINDOW)) continue; // ignore if cannot support rgba mode if ((pfd.iPixelType != PFD_TYPE_RGBA) || (pfd.dwFlags & PFD_NEED_PALETTE)) continue; // ignore if not double buffer if (!(pfd.dwFlags & PFD_DOUBLEBUFFER)) continue; // try to find best candidate currScore = 0; // colour bits if (pfd.cColorBits >= colorBits) ++currScore; if (pfd.cColorBits == colorBits) ++currScore; // depth bits if (pfd.cDepthBits >= depthBits) ++currScore; if (pfd.cDepthBits == depthBits) ++currScore; // stencil bits if (pfd.cStencilBits >= stencilBits) ++currScore; if (pfd.cStencilBits == stencilBits) ++currScore; // alpha bits if (pfd.cAlphaBits > 0) ++currScore; // check if it is best mode so far if (currScore > bestScore) { bestScore = currScore; bestMode = currMode; } } return bestMode; } static bool setPixelFormat(HDC hdc,int stencilBits) { PIXELFORMATDESCRIPTOR pfd; // find out the best matched pixel format int pixelFormat = findPixelFormat(hdc,colorBits,depthBits,stencilBits); if (pixelFormat == 0) return false; // set members of PIXELFORMATDESCRIPTOR with given mode ID ::DescribePixelFormat(hdc,pixelFormat,&pfd); // set the fixel format if (!::SetPixelFormat(hdc,&pfd)) return false; return true; } class WGLView : public cocos2d::GLView { HWND hwnd_; HDC hdc_; HGLRC hglrc_; public: WGLView() : hwnd_(0),hdc_(0),hglrc_(0) {} virtual void end() override { closeContext(); } virtual void swapBuffers() override { ::SwapBuffers(hdc_); } virtual bool isOpenGLReady() override { return hwnd_ != 0; } virtual void setIMEKeyboardState(bool open) override {} virtual bool windowShouldClose() override { return true; }; virtual HWND getWin32Window() override { return hwnd_; } bool createContext(HWND hwnd,int stencilBits) { // retrieve a handle to a display device context hwnd_ = hwnd; hdc_ = ::GetDC(hwnd); // set pixel format if (!setPixelFormat(hdc_,stencilBits)) { ::ReleaseDC(hwnd,hdc_); return false; } // create a new OpenGL rendering context hglrc_ = ::wglCreateContext(hdc_); ::ReleaseDC(hwnd,hdc_); return true; } void activeContext() { ::wglMakeCurrent(hdc_,hglrc_); } void closeContext() { if (!hdc_ || !hglrc_) return; // delete DC and RC ::wglMakeCurrent(0,0); ::wglDeleteContext(hglrc_); ::ReleaseDC(hwnd_,hdc_); hdc_ = 0; hglrc_ = 0; hwnd_ = 0; } }; void ActiveWGLView(cocos2d::GLView *view) { WGLView *v = dynamic_cast<WGLView *>(view); if (v) v->activeContext(); } cocos2d::GLView* CreateWGLView(HWND wndExist) { WGLView *view = new WGLView(); if (!view->createContext(wndExist,32,24,8)) { delete view; return nullptr; } return view; }函数 initGlew 从cocos2d-2.2.6拷贝的,3.13一样可以用
另外,推荐一下一个wgl + OpenGL的例子:http://www.songho.ca/opengl/gl_mvc.html
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |