定制cocos2d的GLView

前端之家收集整理的这篇文章主要介绍了定制cocos2d的GLView前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

使用场景

需求:将cocos2d 的输出窗口设置为一个子窗口,父窗口其它部分仍然有控件

cocos2d功能强大,但是却不好整合进各种gdi和MFC程序中,有些实现是改cocos2d的项目源代码,这样的话,后续升级版本麻烦些,本文提供的方法可以不修改cocos2d源码

实现步骤

1.从cocos2d::GLView派生类WGLView,需要实现 end,swapBuffers,isOpenGLReady,setIMEKeyboardState,windowShouldClose,getWin32Window 这几个虚函数

2.windows 下的 OpenGL初始化流程有这么几项:

(1).外部提供一个HWND,需要窗口类注册时具有 CS_OWNDC标志

(2).获取HWND的HDC,使用SetPixelFormat来调整窗口像素格式,选择的格式需要具有PFD_SUPPORT_OPENGL,PFD_DRAW_TO_WINDOW,PFD_TYPE_RGBA,PFD_DOUBLEBUFFER这几个标志

(3).使用wglCreateContext创建OpenGL环境上下文

//如果准备在其它线程内使用OpenGL,下面转入该线程执行

(4).wglMakeCurrent使用创建好的上下文

(5).初始化glew (必须在 wglMakeCurrent调用后执行,否则glewInit() 会返回错误 1)

(6).Director::setOpenGLView 设置 GLView(必须在glew初始化后执行,否则内部会报空指针错误,因为对应的glew函数指针尚未初始化)

(7).一些后续的初始化

代码(适用于cocos2d 3.13)

Application
  1. static bool glew_dynamic_binding()
  2. {
  3. const char *gl_extensions = (const char*)glGetString(GL_EXTENSIONS);
  4.  
  5. // If the current opengl driver doesn't have framebuffers methods,check if an extension exists
  6. if (glGenFramebuffers == nullptr)
  7. {
  8. log("OpenGL: glGenFramebuffers is nullptr,try to detect an extension");
  9. if (strstr(gl_extensions,"ARB_framebuffer_object"))
  10. {
  11. log("OpenGL: ARB_framebuffer_object is supported");
  12.  
  13. glIsRenderbuffer = (PFNGLISRENDERBUFFERPROC)wglGetProcAddress("glIsRenderbuffer");
  14. glBindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC)wglGetProcAddress("glBindRenderbuffer");
  15. glDeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSPROC)wglGetProcAddress("glDeleteRenderbuffers");
  16. glGenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC)wglGetProcAddress("glGenRenderbuffers");
  17. glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEPROC)wglGetProcAddress("glRenderbufferStorage");
  18. glGetRenderbufferParameteriv = (PFNGLGETRENDERBUFFERPARAMETERIVPROC)wglGetProcAddress("glGetRenderbufferParameteriv");
  19. glIsFramebuffer = (PFNGLISFRAMEBUFFERPROC)wglGetProcAddress("glIsFramebuffer");
  20. glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC)wglGetProcAddress("glBindFramebuffer");
  21. glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC)wglGetProcAddress("glDeleteFramebuffers");
  22. glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC)wglGetProcAddress("glGenFramebuffers");
  23. glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC)wglGetProcAddress("glCheckFramebufferStatus");
  24. glFramebufferTexture1D = (PFNGLFRAMEBUFFERTEXTURE1DPROC)wglGetProcAddress("glFramebufferTexture1D");
  25. glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC)wglGetProcAddress("glFramebufferTexture2D");
  26. glFramebufferTexture3D = (PFNGLFRAMEBUFFERTEXTURE3DPROC)wglGetProcAddress("glFramebufferTexture3D");
  27. glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFERPROC)wglGetProcAddress("glFramebufferRenderbuffer");
  28. glGetFramebufferAttachmentParameteriv = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC)wglGetProcAddress("glGetFramebufferAttachmentParameteriv");
  29. glGenerateMipmap = (PFNGLGENERATEMIPMAPPROC)wglGetProcAddress("glGenerateMipmap");
  30. }
  31. else if (strstr(gl_extensions,"EXT_framebuffer_object"))
  32. {
  33. log("OpenGL: EXT_framebuffer_object is supported");
  34. glIsRenderbuffer = (PFNGLISRENDERBUFFERPROC)wglGetProcAddress("glIsRenderbufferEXT");
  35. glBindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC)wglGetProcAddress("glBindRenderbufferEXT");
  36. glDeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSPROC)wglGetProcAddress("glDeleteRenderbuffersEXT");
  37. glGenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC)wglGetProcAddress("glGenRenderbuffersEXT");
  38. glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEPROC)wglGetProcAddress("glRenderbufferStorageEXT");
  39. glGetRenderbufferParameteriv = (PFNGLGETRENDERBUFFERPARAMETERIVPROC)wglGetProcAddress("glGetRenderbufferParameterivEXT");
  40. glIsFramebuffer = (PFNGLISFRAMEBUFFERPROC)wglGetProcAddress("glIsFramebufferEXT");
  41. glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC)wglGetProcAddress("glBindFramebufferEXT");
  42. glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC)wglGetProcAddress("glDeleteFramebuffersEXT");
  43. glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC)wglGetProcAddress("glGenFramebuffersEXT");
  44. glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC)wglGetProcAddress("glCheckFramebufferStatusEXT");
  45. glFramebufferTexture1D = (PFNGLFRAMEBUFFERTEXTURE1DPROC)wglGetProcAddress("glFramebufferTexture1DEXT");
  46. glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC)wglGetProcAddress("glFramebufferTexture2DEXT");
  47. glFramebufferTexture3D = (PFNGLFRAMEBUFFERTEXTURE3DPROC)wglGetProcAddress("glFramebufferTexture3DEXT");
  48. glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFERPROC)wglGetProcAddress("glFramebufferRenderbufferEXT");
  49. glGetFramebufferAttachmentParameteriv = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC)wglGetProcAddress("glGetFramebufferAttachmentParameterivEXT");
  50. glGenerateMipmap = (PFNGLGENERATEMIPMAPPROC)wglGetProcAddress("glGenerateMipmapEXT");
  51. }
  52. else
  53. {
  54. log("OpenGL: No framebuffers extension is supported");
  55. log("OpenGL: Any call to Fbo will crash!");
  56. return false;
  57. }
  58. }
  59. return true;
  60. }
  61. static bool initGlew()
  62. {
  63. GLenum GlewInitResult = glewInit();
  64. if (GLEW_OK != GlewInitResult)
  65. return false; //must be called after calling wglMakeCurrent
  66.  
  67. if (glew_dynamic_binding() == false)
  68. return false;
  69. return true;
  70. }
  71.  
  72. class AppDelegate : public cocos2d::Application
  73. {
  74. float sceneWidth_,sceneHeight_,frameRate_;
  75. HWND hwnd_;
  76. cocos2d::GLView *glview_;
  77.  
  78. public:
  79. AppDelegate(float sceneWidth,float sceneHeight,float frameRate,HWND hwndRender)
  80. : sceneWidth_(sceneWidth),sceneHeight_(sceneHeight),frameRate_(frameRate),hwnd_(hwndRender),glview_(nullptr)
  81. {
  82. extern cocos2d::GLView* CreateWGLView(HWND);
  83. glview_ = CreateWGLView(hwnd_);
  84. }
  85.  
  86. virtual bool applicationDidFinishLaunching()
  87. { // execute in engine thread
  88. glview_->setFrameSize(sceneWidth_,sceneHeight_);
  89. glview_->setDesignResolutionSize(sceneWidth_,ResolutionPolicy::NO_BORDER);
  90.  
  91. extern void ActiveWGLView(cocos2d::GLView *);
  92. ActiveWGLView(glview_);
  93. initGlew();
  94. auto director = Director::getInstance();
  95. director->setOpenGLView(glview_);
  96. director->setContentScaleFactor(1.0);
  97. director->setDisplayStats(false);
  98. director->setAnimationInterval(1.0 / frameRate_);
  99. return true;
  100. }
  101. virtual void applicationDidEnterBackground()
  102. {
  103. Director::getInstance()->stopAnimation();
  104. }
  105. virtual void applicationWillEnterForeground()
  106. {
  107. Director::getInstance()->startAnimation();
  108. }
  109. };
GLView
  1. static int findPixelFormat(HDC hdc,int colorBits,int depthBits,int stencilBits)
  2. {
  3. int currMode; // pixel format mode ID
  4. int bestMode = 0; // return value,best pixel format
  5. int currscore = 0; // points of current mode
  6. int bestscore = 0; // points of best candidate
  7. PIXELFORMATDESCRIPTOR pfd;
  8.  
  9. // search the available formats for the best mode
  10. bestMode = 0;
  11. bestscore = 0;
  12. for (currMode = 1; ::DescribePixelFormat(hdc,currMode,sizeof(pfd),&pfd) > 0; ++currMode)
  13. {
  14. // ignore if cannot support opengl
  15. if (!(pfd.dwFlags & PFD_SUPPORT_OPENGL))
  16. continue;
  17.  
  18. // ignore if cannot render into a window
  19. if (!(pfd.dwFlags & PFD_DRAW_TO_WINDOW))
  20. continue;
  21.  
  22. // ignore if cannot support rgba mode
  23. if ((pfd.iPixelType != PFD_TYPE_RGBA) || (pfd.dwFlags & PFD_NEED_PALETTE))
  24. continue;
  25.  
  26. // ignore if not double buffer
  27. if (!(pfd.dwFlags & PFD_DOUBLEBUFFER))
  28. continue;
  29.  
  30. // try to find best candidate
  31. currscore = 0;
  32.  
  33. // colour bits
  34. if (pfd.cColorBits >= colorBits) ++currscore;
  35. if (pfd.cColorBits == colorBits) ++currscore;
  36.  
  37. // depth bits
  38. if (pfd.cDepthBits >= depthBits) ++currscore;
  39. if (pfd.cDepthBits == depthBits) ++currscore;
  40.  
  41. // stencil bits
  42. if (pfd.cStencilBits >= stencilBits) ++currscore;
  43. if (pfd.cStencilBits == stencilBits) ++currscore;
  44.  
  45. // alpha bits
  46. if (pfd.cAlphaBits > 0) ++currscore;
  47.  
  48. // check if it is best mode so far
  49. if (currscore > bestscore)
  50. {
  51. bestscore = currscore;
  52. bestMode = currMode;
  53. }
  54. }
  55. return bestMode;
  56. }
  57. static bool setPixelFormat(HDC hdc,int stencilBits)
  58. {
  59. PIXELFORMATDESCRIPTOR pfd;
  60.  
  61. // find out the best matched pixel format
  62. int pixelFormat = findPixelFormat(hdc,colorBits,depthBits,stencilBits);
  63. if (pixelFormat == 0)
  64. return false;
  65.  
  66. // set members of PIXELFORMATDESCRIPTOR with given mode ID
  67. ::DescribePixelFormat(hdc,pixelFormat,&pfd);
  68.  
  69. // set the fixel format
  70. if (!::SetPixelFormat(hdc,&pfd))
  71. return false;
  72.  
  73. return true;
  74. }
  75.  
  76. class WGLView : public cocos2d::GLView
  77. {
  78. HWND hwnd_;
  79. HDC hdc_;
  80. HGLRC hglrc_;
  81. public:
  82. WGLView() : hwnd_(0),hdc_(0),hglrc_(0)
  83. {}
  84.  
  85. virtual void end() override
  86. {
  87. closeContext();
  88. }
  89. virtual void swapBuffers() override
  90. {
  91. ::SwapBuffers(hdc_);
  92. }
  93. virtual bool isOpenGLReady() override { return hwnd_ != 0; }
  94. virtual void setIMEKeyboardState(bool open) override {}
  95. virtual bool windowShouldClose() override { return true; };
  96. virtual HWND getWin32Window() override { return hwnd_; }
  97.  
  98. bool createContext(HWND hwnd,int stencilBits)
  99. {
  100. // retrieve a handle to a display device context
  101. hwnd_ = hwnd;
  102. hdc_ = ::GetDC(hwnd);
  103.  
  104. // set pixel format
  105. if (!setPixelFormat(hdc_,stencilBits))
  106. {
  107. ::ReleaseDC(hwnd,hdc_);
  108. return false;
  109. }
  110.  
  111. // create a new OpenGL rendering context
  112. hglrc_ = ::wglCreateContext(hdc_);
  113. ::ReleaseDC(hwnd,hdc_);
  114. return true;
  115. }
  116. void activeContext()
  117. {
  118. ::wglMakeCurrent(hdc_,hglrc_);
  119. }
  120. void closeContext()
  121. {
  122. if (!hdc_ || !hglrc_)
  123. return;
  124.  
  125. // delete DC and RC
  126. ::wglMakeCurrent(0,0);
  127. ::wglDeleteContext(hglrc_);
  128. ::ReleaseDC(hwnd_,hdc_);
  129.  
  130. hdc_ = 0;
  131. hglrc_ = 0;
  132. hwnd_ = 0;
  133. }
  134.  
  135. };
  136.  
  137. void ActiveWGLView(cocos2d::GLView *view)
  138. {
  139. WGLView *v = dynamic_cast<WGLView *>(view);
  140. if (v)
  141. v->activeContext();
  142. }
  143. cocos2d::GLView* CreateWGLView(HWND wndExist)
  144. {
  145. WGLView *view = new WGLView();
  146. if (!view->createContext(wndExist,32,24,8))
  147. {
  148. delete view;
  149. return nullptr;
  150. }
  151. return view;
  152. }
函数 initGlew 从cocos2d-2.2.6拷贝的,3.13一样可以用

另外,推荐一下一个wgl + OpenGL的例子:http://www.songho.ca/opengl/gl_mvc.html

猜你在找的Cocos2d-x相关文章