Performance 如何选择正确的缓冲区来绘制并阻止其连续交换

Performance 如何选择正确的缓冲区来绘制并阻止其连续交换,performance,opengl,drawing,buffer,cpu-usage,Performance,Opengl,Drawing,Buffer,Cpu Usage,请告诉我这个问题是否流行,我需要尽快回复 有关此问题的更多信息,请参阅此。我只是不知道如何正确管理缓冲区 处于自定义类的最后阶段: 我在MFC对话框中创建了该类的两个实例: 无论何时在较大的窗口中更改缩放范围,都会在较小的窗口中将其绘制为红色矩形。始终处于完全扩展模式。为了在两个实例之间建立这种关系,我使用了用户定义消息的概念,并将消息发送给类的父级 主要故障 根据上述信息: 1-当我在较大的窗口中平移时(意味着我会快速发送用户定义的消息,并调用m_oglWindow2.DrawRectan

请告诉我这个问题是否流行,我需要尽快回复

有关此问题的更多信息,请参阅此。我只是不知道如何正确管理缓冲区

处于自定义类的最后阶段:
我在MFC对话框中创建了该类的两个实例:

无论何时在较大的窗口中更改缩放范围,都会在较小的窗口中将其绘制为红色矩形。始终处于完全扩展模式。为了在两个实例之间建立这种关系,我使用了用户定义消息的概念,并将消息发送给类的父级

主要故障
根据上述信息:

1-当我在较大的窗口中平移时(意味着我会快速发送用户定义的消息,并调用
m_oglWindow2.DrawRectangleOnToPoftExtrade()
快速调用),我看到显示的红色矩形轨迹,但在较小的窗口中立即消失

2-当从3%平移到25%时,CPU使用率立即变高

3-在其他导航任务中,如
固定放大
固定缩小
平移
等,红色矩形闪烁,然后立即消失,我的意思是,就在控件位于函数
m_oglWindow2.DrawRectangleOnPoftexture()中时,红色矩形似乎就在那里
但我希望矩形在下一次调用之前一直存在
m_oglWindow2.drawRectangleOnTopTexture()

4-调用
glDrawBuffer(GL\u-FRONT\u AND\u-BACK)
glClear(GL\u-COLOR\u-BUFFER\u-BIT | GL\u-DEPTH\u-BUFFER\u-BIT)
会导致较小窗口中的纹理关闭和打开,即使鼠标处于空闲状态

我知道问题主要是因为以下代码中的行
glClear
glDrawBuffer
SwapBuffers
。但我不知道确切的解决方法

void COpenGLControl::OnTimer(UINT nIDEvent)
{
wglMakeCurrent(hdc,hrc);
switch (nIDEvent)
{
    case 1:
    {
        // Clear color and depth buffer bits
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        // Draw OpenGL scene
        oglDrawScene();

        // Swap buffers
        SwapBuffers(hdc);

        break;
    }

    default:
        break;
}

CWnd::OnTimer(nIDEvent);
wglMakeCurrent(NULL, NULL);
}  

void COpenGLControl::DrawRectangleOnTopOfTexture()
{
wglMakeCurrent(hdc, hrc);
//glDrawBuffer(GL_FRONT_AND_BACK);
//glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushAttrib(GL_ENABLE_BIT|GL_CURRENT_BIT);
glDisable(target);
glColor3f(1.0f,0.0f,0.0f);
glBegin(GL_LINE_LOOP);
   glVertex2f(RectangleToDraw.at(0),RectangleToDraw.at(1));
   glVertex2f(RectangleToDraw.at(0),RectangleToDraw.at(3));
   glVertex2f(RectangleToDraw.at(2),RectangleToDraw.at(3));
   glVertex2f(RectangleToDraw.at(2),RectangleToDraw.at(1));
glEnd();
glPopAttrib();
SwapBuffers(hdc);
wglMakeCurrent(NULL, NULL);
}  

void COpenGLControl::OnDraw(CDC *pDC)
{
// TODO: Camera controls
wglMakeCurrent(hdc,hrc);
glLoadIdentity();
gluLookAt(0,0,1,0,0,0,0,1,0);
glTranslatef(m_fPosX, m_fPosY, 0.0f);
glScalef(m_fZoom,m_fZoom,1.0);
wglMakeCurrent(NULL, NULL);
}  
记住:

OnDraw
函数在较小的窗口中只调用了两次,第一次是在初始化窗口时,第二次是在调用
m_oglWindow2.ZoomToFullExtent()
时,然后在较大的窗口中,每次调用
OnDraw
函数,都会调用
DrawRectangleOnTopOfTexture()
在较小的窗口中,但在较大的窗口中从未调用此函数

如果:

  • 你能更正我的密码吗

  • 为我介绍一个关于如何在多个应用程序中使用缓冲区的优秀教程 不能在单个函数或单个线程中完成的图形(关于缓冲区的优秀教程,如opengl中的颜色缓冲区等)

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

void COpenGLControl::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
if (WantToPan)
{
    if (m_fLastX < 0.0f && m_fLastY < 0.0f)
    {
        m_fLastX = (float)point.x;
        m_fLastY = (float)point.y;
    }
    int diffX = (int)(point.x - m_fLastX);
    int diffY = (int)(point.y - m_fLastY);
    m_fLastX = (float)point.x;
    m_fLastY = (float)point.y;
    if (nFlags & MK_MBUTTON)
    {
        m_fPosX += (float)0.05f*m_fZoomInverse*diffX;
        m_fPosY -= (float)0.05f*m_fZoomInverse*diffY;
    }
    if (WantToSetViewRectangle)
        setViewRectangle();
    OnDraw(NULL);
}
CWnd::OnMouseMove(nFlags, point);
}     
我只是在下面添加了一些解释,以便在需要时提供有关该课程如何运行的更多信息。如果您认为它会困扰观众,请编辑它,删除您认为不需要的部分。但请确实帮助我

OGLINIALIZE设置场景的初始参数:

void COpenGLControl::oglInitialize(void)
{
// Initial Setup:
//
static PIXELFORMATDESCRIPTOR pfd =
{
    sizeof(PIXELFORMATDESCRIPTOR),
    1,
    PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
    PFD_TYPE_RGBA,
    32, // bit depth
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    24, // z-buffer depth
    8,0,PFD_MAIN_PLANE, 0, 0, 0, 0,
};

// Get device context only once.
hdc = GetDC()->m_hDC;
// Pixel format.
m_nPixelFormat = ChoosePixelFormat(hdc, &pfd);
SetPixelFormat(hdc, m_nPixelFormat, &pfd);
// Create the OpenGL Rendering Context.
hrc = wglCreateContext(hdc);
wglMakeCurrent(hdc, hrc);
// Basic Setup:
//
// Set color to use when clearing the background.
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClearDepth(1.0f);
// Turn on backface culling
glFrontFace(GL_CCW);
glCullFace(GL_BACK);
// Turn on depth testing
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
// Send draw request
OnDraw(NULL);
wglMakeCurrent(NULL, NULL);
}  
导航任务的示例:

PAN:

void COpenGLControl::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
if (WantToPan)
{
    if (m_fLastX < 0.0f && m_fLastY < 0.0f)
    {
        m_fLastX = (float)point.x;
        m_fLastY = (float)point.y;
    }
    int diffX = (int)(point.x - m_fLastX);
    int diffY = (int)(point.y - m_fLastY);
    m_fLastX = (float)point.x;
    m_fLastY = (float)point.y;
    if (nFlags & MK_MBUTTON)
    {
        m_fPosX += (float)0.05f*m_fZoomInverse*diffX;
        m_fPosY -= (float)0.05f*m_fZoomInverse*diffY;
    }
    if (WantToSetViewRectangle)
        setViewRectangle();
    OnDraw(NULL);
}
CWnd::OnMouseMove(nFlags, point);
}     
这是我们在客户端代码中使用类的方式:

MyOpenGLTestDlg.h

void COpenGLControl::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
if (WantToPan)
{
    if (m_fLastX < 0.0f && m_fLastY < 0.0f)
    {
        m_fLastX = (float)point.x;
        m_fLastY = (float)point.y;
    }
    int diffX = (int)(point.x - m_fLastX);
    int diffY = (int)(point.y - m_fLastY);
    m_fLastX = (float)point.x;
    m_fLastY = (float)point.y;
    if (nFlags & MK_MBUTTON)
    {
        m_fPosX += (float)0.05f*m_fZoomInverse*diffX;
        m_fPosY -= (float)0.05f*m_fZoomInverse*diffY;
    }
    if (WantToSetViewRectangle)
        setViewRectangle();
    OnDraw(NULL);
}
CWnd::OnMouseMove(nFlags, point);
}     
类的两个实例:

COpenGLControl m_oglWindow;
COpenGLControl m_oglWindow2;  
MyOpenGLTestDlg.cpp

void COpenGLControl::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
if (WantToPan)
{
    if (m_fLastX < 0.0f && m_fLastY < 0.0f)
    {
        m_fLastX = (float)point.x;
        m_fLastY = (float)point.y;
    }
    int diffX = (int)(point.x - m_fLastX);
    int diffY = (int)(point.y - m_fLastY);
    m_fLastX = (float)point.x;
    m_fLastY = (float)point.y;
    if (nFlags & MK_MBUTTON)
    {
        m_fPosX += (float)0.05f*m_fZoomInverse*diffX;
        m_fPosY -= (float)0.05f*m_fZoomInverse*diffY;
    }
    if (WantToSetViewRectangle)
        setViewRectangle();
    OnDraw(NULL);
}
CWnd::OnMouseMove(nFlags, point);
}     
在窗口上应用纹理,并在
OnInitDlg

    m_oglWindow.pImage = m_files.pRasterData;
    m_oglWindow.setImageWidthHeightType(m_files.RasterXSize,m_files.RasterYSize,m_files.eType);
    m_oglWindow.m_unpTimer = m_oglWindow.SetTimer(1, 1, 0);  

    m_oglWindow2.pImage = m_files.pRasterData;
    m_oglWindow2.setImageWidthHeightType(m_files.RasterXSize,m_files.RasterYSize,m_files.eType);
    m_oglWindow2.m_unpTimer = m_oglWindow2.SetTimer(1, 20, 0);  
    m_oglWindow2.ZoomToFullExtent();
    m_oglWindow.ZoomToFullExtent();  
要对较大的窗口而不是较小的窗口激活平移、缩放工具和setViewRectangle:

m_oglWindow.WantToPan = true;
m_oglWindow.WantToUseZoomTool = true;
m_oglWindow.WantToSetViewRectangle = true;  
在父窗口中处理用户定义的消息。将
ViewRectangle
数据交换到较小的窗口,并绘制红色矩形:

LRESULT CMyOpenGLTestDlg::OnRectangleChanged(WPARAM wParam,LPARAM lParam)
{
m_oglWindow2.RectangleToDraw = m_oglWindow.ViewRectangle;
m_oglWindow2.DrawRectangleOnTopOfTexture();
return 0;
}  

这里是您是否有兴趣下载它并修复我的问题。

问题是您正在使用计时器绘图,并且当您的应用程序收到
WM_PAINT
消息时。MFC调用您的
OnDraw(…)
回调当需要重新绘制窗口时,您应该将绘图功能的所有部分移动到
OnDraw(…)
中,并从计时器函数调用
OnDraw(…)

void COpenGLControl::OnTimer(UINT nIDEvent)
{
  switch (nIDEvent)
  {
    case 1:
    {
      OnDraw (NULL);
      break;
    }

    default:
      break;
  }

  CWnd::OnTimer(nIDEvent);
}

void COpenGLControl::OnDraw(CDC *pDC)
{
  // TODO: Camera controls
  wglMakeCurrent(hdc,hrc);

  // Clear color and depth buffer bits
  glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  glLoadIdentity ();
  gluLookAt      (0,0,1,0,0,0,0,1,0);
  glTranslatef   (m_fPosX, m_fPosY, 0.0f);
  glScalef       (m_fZoom,m_fZoom,1.0);

  // Draw OpenGL scene
  oglDrawScene();

  // Swap buffers
  SwapBuffers(hdc);

  wglMakeCurrent(NULL, NULL);
}

void COpenGLControl::DrawRectangleOnTopOfTexture()
{
  glPushAttrib(GL_ENABLE_BIT|GL_CURRENT_BIT);
  glDisable(target);
  glColor3f(1.0f,0.0f,0.0f);
  glBegin(GL_LINE_LOOP);
    glVertex2f(RectangleToDraw.at(0),RectangleToDraw.at(1));
    glVertex2f(RectangleToDraw.at(0),RectangleToDraw.at(3));
    glVertex2f(RectangleToDraw.at(2),RectangleToDraw.at(3));
    glVertex2f(RectangleToDraw.at(2),RectangleToDraw.at(1));
  glEnd();
  glPopAttrib();
}

并且只能在
OnDraw(…)中调用
wglMakeCurrent(…)
。此函数适用于渲染到多个渲染上下文或使用多个线程进行绘制的情况。

有什么方法可以让您发布的代码少一点吗?我说过,我确信主要的问题在于水平线下的代码。我只是添加了它们来说明这一点,例如当
 OnDraw
被调用,您注意到MFC不会自动运行OnDraw。因为它不包含在消息映射中,我刚刚手动创建了它,WM_PAINT的代码是{ValidateStright(NULL)}立即绘制所有内容,这就是我在这里说的。清除颜色/深度缓冲区{Draw X,Draw Y,Draw Z}交换缓冲区。如果您必须调用多个函数来绘制所需的所有内容,则它们都应该发生在您清除缓冲区并在
OnDraw(…)
中交换缓冲区的时间之间,并且除了
OnDraw(…)
之外的任何内容都应该是交换缓冲区,或者调用
wglMakeCurrent(…)
如果在父窗口中有用户定义的处理程序,请让它重新绘制所有内容。更改某些状态并使其调用控件的OnDraw(…)函数。在双缓冲系统中不能部分绘制内容,基本上必须绘制所有内容,然后交换缓冲区。对,
wglMakeCurrent(…)
当您有两个控件时调用它非常重要。但实际上,您只需要在开始/完成渲染一个控件时调用它,而不需要在只做一两件事情的小函数中调用它(如