【求助】OPENGL显示位图的问题

veryfd 2012-09-06 02:27:56
最近尝试着在MFC构架下,以OPENGL的方式渲染位图于窗体,思路是先将位图读取成纹理,再将对应的纹理渲染至矩形上。

具体代码如下:

.h文件:

// TestRenderDlg.h : header file
//

#pragma once


// CTestRenderDlg dialog
class CTestRenderDlg : public CDialogEx
{
// Construction
public:
CTestRenderDlg(CWnd* pParent = NULL); // standard constructor

// Dialog Data
enum { IDD = IDD_TESTRENDER_DIALOG };

protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support


// Implementation
protected:
HICON m_hIcon;
BOOL SetWindowPixelFormat(HDC hDC);
BOOL CreateViewGLContext(HDC hDC);

int m_GLPixelIndex;
HGLRC m_hGLContext;
UINT m_clrBK;
bool m_bLeftbtDown;
CPoint m_ptStart;
AUX_RGBImageRec* m_bmp;
GLuint m_texture;

// Generated message map functions
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
DECLARE_MESSAGE_MAP()

public:
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnDestroy();
afx_msg void OnSize(UINT nType, int cx, int cy);
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
afx_msg void OnMouseMove(UINT nFlags, CPoint point);
afx_msg void OnBnClickedButton1();
void OPENGLDraw(void);
void GDIDraw(HDC hDC);
};


.cpp

// CTestRenderDlg dialog




CTestRenderDlg::CTestRenderDlg(CWnd* pParent /*=NULL*/)
: CDialogEx(CTestRenderDlg::IDD, pParent)
{
m_hGLContext = NULL;
m_GLPixelIndex = 0;
m_clrBK = 255;
m_bLeftbtDown = false;
m_bmp = NULL;
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CTestRenderDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CTestRenderDlg, CDialogEx)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_WM_CREATE()
ON_WM_DESTROY()
ON_WM_SIZE()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
ON_BN_CLICKED(IDC_BUTTON1, &CTestRenderDlg::OnBnClickedButton1)
END_MESSAGE_MAP()


// CTestRenderDlg message handlers

BOOL CTestRenderDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();

// Add "About..." menu item to system menu.

// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);

CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
BOOL bNameValid;
CString strAboutMenu;
bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
ASSERT(bNameValid);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}

// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon

// TODO: Add extra initialization here

return TRUE; // return TRUE unless you set the focus to a control
}

void CTestRenderDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialogEx::OnSysCommand(nID, lParam);
}
}

// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.

void CTestRenderDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting

SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;

// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialogEx::OnPaint();
}
}

// The system calls this function to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CTestRenderDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}

int CTestRenderDlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
lpCreateStruct->style |= (WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
if (CDialogEx::OnCreate(lpCreateStruct) == -1)
return -1;

// TODO: Add your specialized creation code here
HWND hWnd = GetSafeHwnd();
HDC hDC = ::GetDC(hWnd);
if (SetWindowPixelFormat(hDC)==FALSE)
return 0;
if (CreateViewGLContext(hDC)==FALSE)
return 0;

m_bmp = auxDIBImageLoad(_T("D:\\workfile\\xingxiang\\TestRender\\Debug\\Bluestream.bmp"));

return 0;
}

BOOL CTestRenderDlg::CreateViewGLContext(HDC hDC)
{
m_hGLContext = wglCreateContext(hDC);//用当前DC产生绘制环境(RC)
if (m_hGLContext == NULL)
{
return FALSE;
}

if (wglMakeCurrent(hDC, m_hGLContext)==FALSE)
{
return FALSE;
}

return TRUE;
}

BOOL CTestRenderDlg::SetWindowPixelFormat(HDC hDC)
{
PIXELFORMATDESCRIPTOR pixelDesc;
pixelDesc.nSize = sizeof(PIXELFORMATDESCRIPTOR);
pixelDesc.nVersion = 1;
pixelDesc.dwFlags = PFD_DRAW_TO_WINDOW | PFD_DRAW_TO_BITMAP | PFD_SUPPORT_OPENGL |
PFD_SUPPORT_GDI | PFD_STEREO_DONTCARE;
pixelDesc.iPixelType = PFD_TYPE_RGBA;
pixelDesc.cColorBits = 32;
pixelDesc.cRedBits = 8;
pixelDesc.cRedShift = 16;
pixelDesc.cGreenBits = 8;
pixelDesc.cGreenShift = 8;
pixelDesc.cBlueBits = 8;
pixelDesc.cBlueShift = 0;
pixelDesc.cAlphaBits = 0;
pixelDesc.cAlphaShift = 0;
pixelDesc.cAccumBits = 64;
pixelDesc.cAccumRedBits = 16;
pixelDesc.cAccumGreenBits = 16;
pixelDesc.cAccumBlueBits = 16;
pixelDesc.cAccumAlphaBits = 0;
pixelDesc.cDepthBits = 32;
pixelDesc.cStencilBits = 8;
pixelDesc.cAuxBuffers = 0;
pixelDesc.iLayerType = PFD_MAIN_PLANE;
pixelDesc.bReserved = 0;
pixelDesc.dwLayerMask = 0;
pixelDesc.dwVisibleMask = 0;
pixelDesc.dwDamageMask = 0;

//接着用鼠标右键在COpenGLView中添加保护型的成员变量: int m_GLPixelIndex;

m_GLPixelIndex = ChoosePixelFormat( hDC, &pixelDesc);
if (m_GLPixelIndex==0) // Let's choose a default index.
{
m_GLPixelIndex = 1;
if (DescribePixelFormat(hDC, m_GLPixelIndex, sizeof(PIXELFORMATDESCRIPTOR), &pixelDesc)==0)
{
return FALSE;
}
}
if (SetPixelFormat( hDC, m_GLPixelIndex, &pixelDesc)==FALSE)
{
return FALSE;
}
return TRUE;
}

void CTestRenderDlg::OnDestroy()
{
if(wglGetCurrentContext()!=NULL)
{
// make the rendering context not current
wglMakeCurrent(NULL, NULL) ;
}

if (m_hGLContext!=NULL)
{
wglDeleteContext(m_hGLContext);
m_hGLContext = NULL;
}

if(NULL != m_bmp)
{
free(m_bmp->data);
free(m_bmp);
m_bmp = NULL;//*/
}

CDialogEx::OnDestroy();

// TODO: Add your message handler code here
}


void CTestRenderDlg::OnSize(UINT nType, int cx, int cy)
{
CDialogEx::OnSize(nType, cx, cy);

// TODO: Add your message handler code here
GLsizei width, height;
GLdouble aspect;
width = cx;
height = cy;

if (cy==0)
aspect = (GLdouble)width;
else
aspect = (GLdouble)width/(GLdouble)height;

glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0, 500.0*aspect, 0.0, 500.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}


void CTestRenderDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
m_bLeftbtDown = true;
m_ptStart = point;
CDialogEx::OnLButtonDown(nFlags, point);
}


void CTestRenderDlg::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
m_ptStart = point;
CDialogEx::OnLButtonUp(nFlags, point);
}


void CTestRenderDlg::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
if(m_bLeftbtDown)
{
m_clrBK += (point.y - m_ptStart.y);
}

//Invalidate(0);
m_bLeftbtDown = false;

CDialogEx::OnMouseMove(nFlags, point);
}


void CTestRenderDlg::OnBnClickedButton1()
{
// TODO: Add your control notification handler code here
glLoadIdentity();
glClearColor(.5f, .5f, .5f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_TEXTURE_2D);

m_texture = 0;
glGenTextures(1, &m_texture);
glBindTexture(GL_TEXTURE_2D, m_texture);

//glDisable(GL_BLEND);

glDisable(GL_ALPHA_TEST);
glDisable(GL_BLEND);
glDisable(GL_DEPTH_TEST);
glDisable(GL_DITHER);
glDisable(GL_FOG);
glDisable(GL_LIGHTING);
glDisable(GL_LOGIC_OP);
glDisable(GL_STENCIL_TEST);
glDisable(GL_TEXTURE_1D);
//glDisable(GL_TEXTURE_2D);
glPixelTransferi(GL_MAP_COLOR, GL_FALSE);
glPixelTransferi(GL_RED_SCALE, 1);
glPixelTransferi(GL_RED_BIAS, 0);
glPixelTransferi(GL_GREEN_SCALE, 1);
glPixelTransferi(GL_GREEN_BIAS, 0);
glPixelTransferi(GL_BLUE_SCALE, 1);
glPixelTransferi(GL_BLUE_BIAS, 0);
glPixelTransferi(GL_ALPHA_SCALE, 1);
glPixelTransferi(GL_ALPHA_BIAS, 0);

OPENGLDraw();
glFlush();
}

void CTestRenderDlg::OPENGLDraw(void)
{
if(NULL != m_bmp)
{
gluBuild2DMipmaps( GL_TEXTURE_2D, 3, m_bmp->sizeX, m_bmp->sizeY,
GL_RGB, GL_UNSIGNED_BYTE, m_bmp->data);

glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_NEAREST);//设置放大滤镜
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_NEAREST); //设置缩小滤镜

//glDrawPixels(m_bmp->sizeX, m_bmp->sizeY, GL_RGB,GL_UNSIGNED_BYTE, m_bmp->data);
glShadeModel(GL_SMOOTH);
glBegin(GL_QUADS);

glTexCoord2f(0.0f, 0.0f);
glVertex2f(0, 0);

glTexCoord2f(0.0f, 1.0f);
glVertex2f(0, 512);

glTexCoord2f(1.0f, 1.0f);
glVertex2f(512, 512);

glTexCoord2f(1.0f, 0.0f);
glVertex2f(512, 0);
glEnd();//*/
}
}

现在的问题是对于一副1024*768的图像,仅仅将其渲染出来的耗时约在0.3秒左右,这样的效率甚至比GDI还低很多,在后续的开发中是不可接受的,是不是有高手可以看看该怎么做才能提升效率?
...全文
68 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

19,468

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 图形处理/算法
社区管理员
  • 图形处理/算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧