【求助】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还低很多,在后续的开发中是不可接受的,是不是有高手可以看看该怎么做才能提升效率?
...全文
78 回复 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复
Welcome to my OpenGL tutorials. I am an average guy with a passion for OpenGL! The first time I heard about OpenGL was back when 3Dfx released their Hardware accelerated OpenGL driver for the Voodoo 1 card. Immediately I knew OpenGL was something I had to learn. Unfortunately, it was very hard to find any information about OpenGL in books or on the net. I spent hours trying to make code work and even more time begging people for help in email and on IRC. I found that those people that understood OpenGL considered themselves elite, and had no interest in sharing their knowledge. VERY frustrating! I created this web site so that people interested in learning OpenGL would have a place to come if they needed help. In each of my tutorials I try to explain, in as much detail as humanly possible, what each line of code is doing. I try to keep my code simple (no MFC code to learn)! An absolute newbie to both Visual C++ and OpenGL should be able to go through the code, and have a pretty good idea of what’s going on. My site is just one of many sites offering OpenGL tutorials. If you’re a hardcore OpenGL programmer, my site may be too simplistic, but if you’re just starting out, I feel my site has a lot to offer! This tutorial was completely rewritten January 2000. This tutorial will teach you how to set up an OpenGL window. The window can be windowed or fullscreen, any size you want, any resolution you want, and any color depth you want. The code is very flexible and can be used for all your OpenGL projects. All my tutorials will be based on this code! I wrote the code to be flexible, and powerful at the same time. All errors are reported. There should be no memory leaks, and the code is easy to read and easy to modify. Thanks to Fredric Echols for his modifications to the code! I’ll start this tutorial by jumping right into the code. The first thing you will have to do is build a project in Visual C++. If you don’t know how to do that, you should not be learning OpenGL, you should be learning Visual C++. The downloadable code is Visual C++ 6.0 code. Some versions of VC++ require that bool is changed to BOOL, true is changed to TRUE, and false is changed to FALSE. By making the changes mentioned, I have been able to compile the code on Visual C++ 4.0 and 5.0 with no other problems. After you have created a new Win32 Application (NOT a console application) in Visual C++, you will need to link the OpenGL libraries. In Visual C++ go to Project, Settings, and then click on the LINK tab. Under „Object/Library Modules” at the beginning of the line (before kernel32.lib) add OpenGL32.lib Glu32.lib and Glaux.lib. Once you’ve done this click on OK. You’re now ready to write an OpenGL Windows program.

19,472

社区成员

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

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