创建一个Opencascade视图,过程如下:
代码逻辑如下:
Handle(Aspect_DisplayConnection) aDisplayConnection = new Aspect_DisplayConnection();
if (GetGraphicDriver().IsNull())
{
GetGraphicDriver() = new OpenGl_GraphicDriver(aDisplayConnection);
}
--- 创建图形系统驱动
myViewer = new V3d_Viewer(GetGraphicDriver());
myView = myViewer->CreateView();
--- 创建V3d_View
Handle(WNT_Window) wind = new WNT_Window((Aspect_Handle) hwnd);
--- 根据已有窗口句柄,创建原生窗口
myView->SetWindow(wind);
---- 捆绑原生窗口
OpenGl_GraphDriver 通过EGL(EGL是地产原生窗口与Khronos渲染API(例如OpenGL ES,OpenVG等)之间的接口)建立OpenGl与原生窗口系统(例如:微软Windows,MacOS,Linux XServer)的联系、创建绘制上下文。OpenGl_GraphDriver的初始化函数(为了便于理解,去掉了一些不关键代码):
Standard_Boolean OpenGl_GraphicDriver::InitContext()
{
myEglDisplay = (Aspect_Display )eglGetDisplay (EGL_DEFAULT_DISPLAY);
------ 建立本地系统和 OpenGL ES 的连接
EGLint aVerMajor = 0; EGLint aVerMinor = 0;
eglInitialize ((EGLDisplay )myEglDisplay, &aVerMajor, &aVerMinor)
---- 初始化
myEglConfig = chooseEglSurfConfig ((EGLDisplay )myEglDisplay);
---- chooseEglSurfConfig对eglChooseChofig进行了封装,作用是确定Surface(绘制区域)
的配置。
EGLint* anEglCtxAttribs = NULL;
eglBindAPI (EGL_OPENGL_API) != EGL_TRUE)
---- 绑定OpenGl
myEglContext = eglCreateContext (myEglDisplay, myEglConfig, EGL_NO_CONTEXT, anEglCtxAttribs);
--- 创建EGL上下文
myIsOwnContext = Standard_True;
return Standard_True;
}
创建V3d_View的主要逻辑在V3d_View构造函数中,主要做两件事情:1. 调用驱动创建与OpenGl关联的代理子对象Openl_View;2.初始化相机等。
V3d_View构造函数:
V3d_View::V3d_View (const Handle(V3d_Viewer)& theViewer, const V3d_TypeOfView theType)
{
myView = theViewer->Driver()->CreateView (theViewer->StructureManager());
--- 创建OpenGl_View
Handle(Graphic3d_Camera) aCamera = new Graphic3d_Camera();
aCamera->SetFOVy (45.0);
aCamera->SetIOD (Graphic3d_Camera::IODType_Relative, 0.05);
aCamera->SetZFocus (Graphic3d_Camera::FocusType_Relative, 1.0);
aCamera->SetProjectionType ((theType == V3d_ORTHOGRAPHIC)
? Graphic3d_Camera::Projection_Orthographic
: Graphic3d_Camera::Projection_Perspective);
SetCamera (aCamera);
--- 初始化相机
}
驱动为V3d_View创建代理对象OpenGl_View:
Handle(Graphic3d_CView) OpenGl_GraphicDriver::CreateView
(const Handle(Graphic3d_StructureManager)& theMgr)
{
Handle(OpenGl_View) aView = new OpenGl_View (theMgr, this, myCaps, &myStateCounter);
myMapOfView.Add (aView);
---- 创建OpenGl_View
}
比较简单,不在此罗列。
捆绑原生窗口,本质上是为其代理子对象OpenGl_View捆绑原生窗口:
void V3d_View::SetWindow (const Handle(Aspect_Window)& theWindow,
const Aspect_RenderingContext theContext)
{
myView->SetWindow (theWindow, theContext);
---- OpenGl_View 设置窗口
......
}
OpenGl_View 捆绑原生窗口主要做3事情:1. 创建一个渲染窗口捆绑原生窗口;2. 创建工作空间;3.初始化纹理环境。
void OpenGl_View::SetWindow (const Handle(Aspect_Window)& theWindow,
const Aspect_RenderingContext theContext)
{
myWindow = myDriver->CreateRenderWindow (theWindow, theContext);
--- 创建渲染窗口OpenGl_Window,绑定原生窗口
myWorkspace = new OpenGl_Workspace (this, myWindow);
--- 创建工作空间,OpenGl_Workspace 实现渲染图元、维护状态的方法。
initTextureEnv (myWorkspace->GetGlContext());
--- 初始化纹理环境
}
Handle(OpenGl_Window) OpenGl_GraphicDriver::CreateRenderWindow
(const Handle(Aspect_Window)& theWindow,
const Aspect_RenderingContext theContext)
{
return new OpenGl_Window (this, theWindow, theContext, myCaps, aShareCtx);
}
OpenGl_Window::OpenGl_Window(...)
{
#if defined(HAVE_EGL)
EGLDisplay anEglDisplay = (EGLDisplay )theDriver->getRawGlDisplay();
EGLContext anEglContext = (EGLContext )theDriver->getRawGlContext();
EGLConfig anEglConfig = (EGLConfig )theDriver->getRawGlConfig();
anEglSurf = eglCreateWindowSurface
(anEglDisplay,
anEglConfig,
(EGLNativeWindowType )myPlatformWindow->NativeHandle(),--- 原生窗口句柄
NULL);
---- 创建屏幕渲染区:EGL窗口
myGlContext = new OpenGl_Context (theCaps));
myGlContext->Init
(
(Aspect_Drawable )anEglSurf,
(Aspect_Display )anEglDisplay,
(Aspect_RenderingContext )anEglContext, isCoreProfile
);
---- 创建OpenGl_Context(OpenGl上下文),并初始化:调用eglMakeCurrent,把EGL 上下设置为当前上下文;调用::glGetString (GL_VENDOR)检查当前OpenGL版本等信息。
Init();
--- 渲染窗口初始化
#endif
}
上下文初始化
OpenGl_Context::init(isCoreProfile)
{
GLint aMajor = 0, aMinor = 0;
glGetIntegerv (GL_MAJOR_VERSION, &aMajor);
glGetIntegerv (GL_MINOR_VERSION, &aMinor);
...
--- 检索版本,确认当前版本支持情况。
myVendor = (const char* )::glGetString (GL_VENDOR);
--- 检索开发者
glGetIntegerv (GL_CONTEXT_PROFILE_MASK, &aProfile);
glGetIntegerv (GL_MAX_DRAW_BUFFERS, &myMaxDrawBuffers);
glGetIntegerv (GL_MAX_COLOR_ATTACHMENTS, &myMaxColorAttachments);
glGetIntegerv (GL_MAX_TEXTURE_SIZE, &myMaxTexDim);
glGetIntegerv (GL_MAX_TEXTURE_UNITS, &myMaxTexUnitsFFP);
glGetIntegerv (GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &myMaxTexCombined);
glGetIntegerv (GL_MAX_VIEWPORT_DIMS, aMaxVPortSize);
glGetIntegerv (GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &myAnisoMax);
glGetIntegerv (GL_MAX_SAMPLES, &myMaxMsaaSamples);
glGetIntegerv (GL_MAX_SAMPLES, &myMaxMsaaSamples);
glGetIntegerv (GL_MAX_COLOR_TEXTURE_SAMPLES, &aNbColorSamples);
glGetIntegerv (GL_MAX_DEPTH_TEXTURE_SAMPLES, &aNbDepthSamples);
glGetIntegerv (GL_STEREO, &aStereo);
glGetIntegerv (GL_MAX_CLIP_PLANES, &myMaxClipPlanes);
--- 确定当前OpenGl支持特性
}
渲染窗口初始化
void OpenGl_Window::Init()
{
Activate();
--- 把上下文设为当前上下文
const Standard_Integer aViewport[4] = { 0, 0, myWidth, myHeight };
myGlContext->ResizeViewport (aViewport);
--- 修改视口大小
glDisable (GL_DITHER);
--- 关闭颜色抖动
glDisable (GL_SCISSOR_TEST);
--- 关闭裁剪测试
glMatrixMode (GL_MODELVIEW);
--- 指定GL_MODELVIEW 为当前矩阵
}
OpenGl_Workspace::OpenGl_Workspace
(OpenGl_View* theView, const Handle(OpenGl_Window)& theWindow)
{
myGlContext = theWindow->GetGlContext()
myGlContext->core11fwd->glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
--- 设置像素对齐方式
myGlContext->core11ffp->glLightModeli ((GLenum )GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
--- 设置光照模式
myGlContext->core11fwd->glHint (GL_POINT_SMOOTH_HINT, GL_FASTEST);
--- 指定反走样点的采样质量
if (myGlContext->caps->ffpEnable)
{
myGlContext->core11fwd->glHint (GL_FOG_HINT, GL_FASTEST);
--- 指定雾化计算的精度
}
myGlContext->core11fwd->glHint (GL_LINE_SMOOTH_HINT, GL_FASTEST);
--- 指定反走样线段的采样质量
myGlContext->core11fwd->glHint (GL_POLYGON_SMOOTH_HINT, GL_FASTEST);
--- 指定反走样多边形的采样质量
}