我已经下载了课程Setting Up OpenGL in an MFC Control并根据我的目的进行了自定义(显示图像并制作缩放和其他翻译):
OpenGLControl.h
#pragma once
#include "afxwin.h"
#include "gl\GL.h"
#include "gl\GLU.h"
#include "gdal_priv.h"
#include <algorithm>
#include <math.h>
#include <vector>
using std::vector;
using std::min;
class COpenGLControl2D : public CWnd
{
public:
COpenGLControl2D(void); //Constructor and destructor
virtual ~COpenGLControl2D(void);
void oglCreate(CRect , CWnd *); //Manually added functions
void oglInitialize(void);
void oglDrawScene(void);
//call this function just first time of calling OnTimer and after setting pImage
//for the next calls of OnTimer and when updating pImage there's no need to call
//this function. If you do so, your client code slows down
void setImageWidthHeightType(int,int,GDALDataType);
//For second and more calls of OnTimer you should call this function after setting pImage
//In the first call of OnTimer and before calling setImageWidthHeightType(int,int,GDALDataType)
//this function should not be called and if so, the program will encounter an unhandled exception
//because there you still don't have any texture object to be updated
void updataTextureObject();
void ZoomToFullExtent();
/******************/
/* PUBLIC MEMBERS */
/******************/
// Timer
UINT_PTR m_unpTimer;
//you should update value of this member variable whenever you want to call OnTimer
vector<unsigned char>pImage;
private:
//used internally by function ZoomIn,ZoomOut and Pan and etc
float m_fLastX;
float m_fLastY;
float m_fPosX;
float m_fPosY;
float m_fZoom;
//texture object used internally by the class
GLuint *textures;
GLsizei numberOfTextures;
private:
/*******************/
/* PRIVATE MEMBERS */
/*******************/
// Window information
CWnd *hWnd;
HDC hdc;
HGLRC hrc;
int m_nPixelFormat;
CRect m_rect;
CRect m_oldWindow;
CRect m_originalRect;
GLsizei ImageWidth;
GLsizei ImageHeight;
GLsizei oglWindowWidth;
GLsizei oglWindowHeight;
GLenum format;
GLenum type;
GLenum target;
GLint level;
GLint internalformat;
GLint border;
GLint xOffset;
GLint yOffset;
private:
//used internally by the public member function setImageWidthHeightType of the class
void InitializeTextureObject();
public:
DECLARE_MESSAGE_MAP()
afx_msg void OnPaint();
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnDraw(CDC *pDC);
afx_msg void OnTimer(UINT_PTR nIDEvent);
afx_msg void OnSize(UINT nType, int cx, int cy);
//afx_msg void OnMouseMove(UINT nFlags, CPoint point);
};
OpenGLControl.cpp
#include "StdAfx.h"
#include "OpenGLControl.h"
COpenGLControl2D::COpenGLControl2D(void)
{
ImageWidth = 0;
ImageHeight = 0;
format = GL_LUMINANCE;
type = GL_BITMAP;
m_fPosX = 0.0f; // X position of model in camera view
m_fPosY = 0.0f; // Y position of model in camera view
m_fZoom = 1.0f; // Zoom on model in camera view
oglWindowWidth = 0;
oglWindowHeight = 0;
textures = new GLuint();
numberOfTextures = 1;
target = GL_TEXTURE_2D;
level = 0;
internalformat = format;
border = 0;
xOffset = 0;
yOffset = 0;
}
COpenGLControl2D::~COpenGLControl2D(void)
{
delete textures;
}
void COpenGLControl2D::oglCreate(CRect rect, CWnd *parent)
{
CString className = AfxRegisterWndClass(CS_HREDRAW |
CS_VREDRAW | CS_OWNDC, NULL,
(HBRUSH)GetStockObject(BLACK_BRUSH), NULL);
char *windowName = "OpenGL";
CA2T TwindowName(windowName);
CString strTwindowName = TwindowName.m_psz;
CreateEx(0, className, strTwindowName, WS_CHILD | WS_VISIBLE |
WS_CLIPSIBLINGS | WS_CLIPCHILDREN, rect, parent, 0);
// Set initial variables' values
m_oldWindow = rect;
m_originalRect = rect;
oglWindowWidth = rect.right - rect.left;
oglWindowHeight = rect.bottom - rect.top;
hWnd = parent;
}
BEGIN_MESSAGE_MAP(COpenGLControl2D, CWnd)
ON_WM_PAINT()
ON_WM_CREATE()
ON_WM_TIMER()
ON_WM_SIZE()
//ON_WM_MOUSEMOVE()
END_MESSAGE_MAP()
void COpenGLControl2D::OnPaint()
{
//CPaintDC dc(this); // device context for painting
// TODO: Add your message handler code here
// Do not call CWnd::OnPaint() for painting messages
ValidateRect(NULL);
}
int COpenGLControl2D::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CWnd::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: Add your specialized creation code here
oglInitialize();
return 0;
}
void COpenGLControl2D::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,
16, // z-buffer depth
0, 0, 0, 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.
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!PRODUCES ERROR!!!!!!!!!!!!!!!!!!!!!!!!!!!
hrc = wglCreateContext(hdc);
GLenum error1 = glGetError();
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);
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!PRODUCES ERROR!!!!!!!!!!!!!!!!!!!!!!!!!!!
wglMakeCurrent(NULL, NULL);
GLenum error9 = glGetError();
}
void COpenGLControl2D::OnDraw(CDC *pDC)
{
wglMakeCurrent(hdc, hrc);
// TODO: Camera controls.
glLoadIdentity();
glScalef(m_fZoom,m_fZoom,1);
GLenum error42 = glGetError();
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!PRODUCES ERROR!!!!!!!!!!!!!!!!!!!!!!!!!!!
wglMakeCurrent(NULL,NULL);
GLenum error12 = glGetError();
}
void COpenGLControl2D::OnTimer(UINT_PTR nIDEvent)
{
wglMakeCurrent(hdc, hrc);
// TODO: Add your message handler code here and/or call default
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);
}
void COpenGLControl2D::setImageWidthHeightType(int localWidth,int localHeight,GDALDataType localType)
{
ImageWidth = localWidth;
ImageHeight = localHeight;
switch (localType)
{
case GDT_Byte:
{
type = GL_UNSIGNED_BYTE;
break;
}
case GDT_UInt16:
{
type = GL_UNSIGNED_SHORT;
break;
}
case GDT_Int16:
{
type = GL_SHORT;
break;
}
case GDT_UInt32:
{
type = GL_UNSIGNED_INT;
break;
}
case GDT_Int32:
{
type = GL_INT;
break;
}
}
InitializeTextureObject();
}
void COpenGLControl2D::oglDrawScene(void)
{
wglMakeCurrent(hdc, hrc);
float x0 = 0; // top left corner of image
float y0 = 0;
float x1 = x0 + ImageWidth; // bottom right corner of image
float y1 = y0 + ImageHeight;
glBegin(GL_TRIANGLE_STRIP);
{
glTexCoord2f(0, 1); glVertex2f(x0, y1);
glTexCoord2f(0, 0); glVertex2f(x0, y0);
glTexCoord2f(1, 1); glVertex2f(x1, y1);
glTexCoord2f(1, 0); glVertex2f(x1, y0);
}
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!PRODUCES ERROR!!!!!!!!!!!!!!!!!!!!!!!!!!!
glEnd();
GLenum error24 = glGetError();
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!PRODUCES ERROR!!!!!!!!!!!!!!!!!!!!!!!!!!!
wglMakeCurrent(NULL, NULL);
GLenum error26 = glGetError();
}
void COpenGLControl2D::OnSize(UINT nType, int cx, int cy)
{
wglMakeCurrent(hdc, hrc);
CWnd::OnSize(nType, cx, cy);
// TODO: Add your message handler code here
if (0 >= cx || 0 >= cy || nType == SIZE_MINIMIZED) return;
oglWindowWidth = cx;
oglWindowHeight = cy;
// Map the OpenGL coordinates.
glViewport(0, 0, oglWindowWidth, oglWindowHeight);
// Projection view
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// Set our current view perspective
glOrtho(0, oglWindowWidth, oglWindowHeight,0, -1, 1);
// Model view
glMatrixMode(GL_MODELVIEW);
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!PRODUCES ERROR!!!!!!!!!!!!!!!!!!!!!!!!!!!
wglMakeCurrent(NULL, NULL);
GLenum error33 = glGetError();
}
void COpenGLControl2D::InitializeTextureObject()
{
wglMakeCurrent(hdc, hrc);
glGenTextures(numberOfTextures,textures);
glBindTexture(GL_TEXTURE_2D, *textures);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glTexImage2D(target,level,internalformat,ImageWidth,ImageHeight,border,format,type,&pImage[0]);
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!PRODUCES ERROR!!!!!!!!!!!!!!!!!!!!!!!!!!!
wglMakeCurrent(NULL, NULL);
GLenum error38 = glGetError();
}
void COpenGLControl2D::updataTextureObject()
{
wglMakeCurrent(hdc, hrc);
glTexSubImage2D(target,level,xOffset,yOffset,ImageWidth,ImageHeight,format,type,&pImage[0]);
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!PRODUCES ERROR!!!!!!!!!!!!!!!!!!!!!!!!!!!
wglMakeCurrent(NULL, NULL);
GLenum error41 = glGetError();
}
void COpenGLControl2D::ZoomToFullExtent()
{
float zoom1 = oglWindowWidth/ImageWidth;
float zoom2 = oglWindowHeight/ImageHeight;
float minZoom = min(zoom1,zoom2);
m_fZoom = floor(minZoom);
OnDraw(NULL);
}
void COpenGLControl2D::FixedZoomIn()
{
m_fZoom = 2*m_fZoom;
}
当我将此类与此代码一起使用时:
COpenGLControl m_oglWindow;
m_oglWindow = new COpenGLControl2D();
CRect rect;
GetDlgItem(IDC_OPENGL)->GetWindowRect(rect);
ScreenToClient(rect);
m_oglWindow -> oglCreate(rect, this);
const char* filename = "D:\\DataPrevious\\globalMapper.tif";
GDALDataset *poDataset = NULL ;
GDALAllRegister();
poDataset = (GDALDataset *) GDALOpen( filename, GA_ReadOnly );
m_files -> ReadRasterData(poDataset);
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_oglWindow ->updataTextureObject();
m_oglWindow ->ZoomToFullExtent();
m_oglWindow ->FixedZoomIn();
我得到的是我的512x512图像:
您会看到纹理未应用于几何体。并且函数FixedZoomIn()
和ZoomToFullExtent()
似乎什么都不做。我想这可能是因为OpenGL仅在OnTimer
函数中进行绘图?
无论如何,我在以前缀glGetError()
开头的所有函数之后使用gl
,并注意到我指定的位置抛出了INVALID_OPERATION(1282)
错误。我的意思是似乎没有创建hrc(rendering context)
,但我不明白opengl怎么能在那里绘制那个白色几何体?并且glEnd()
也抛出了这个错误
也许你质疑为什么我在课堂上的几个函数中使用了wglMakeCurrent(hdc,hrc)
和wglMakeCurrent(NULL,NULL)
?
这是因为我研究的内容here, OpenGL two different 3d rendering picture control on single MFC dialog not working
所以我的问题是,如果未创建渲染上下文或设备上下文无效,那么opengl如何绘制该白色矩形?
如果问题是其他问题那么它是什么?
为什么纹理没有应用于矩形几何体?
为什么像缩放操作中使用的glScale()这样的函数不起作用?
为什么glEnd()也会产生1282错误?是因为函数glTexCoord
还是glVertex
?
并且如果问题是没有创建上下文我该如何创建它请注意我在类刚刚启动时在函数hrc = wglCreateContext(hdc)
之后收到错误INVALID_OPERATION?
答案 0 :(得分:1)
所以我的问题是如果没有创建渲染上下文或设备上下文无效,那么opengl如何绘制那个白色矩形?
我真的没有耐心去处理您发布的代码的混乱。但我要说,因为在绘制矩形时,有一个上下文活动。
为什么纹理没有应用于矩形几何体?
启用了不完整的图片定义和mipmaping。在绘制时没有纹理目标绑定和活动。这通常是原因。
为什么像缩放操作中使用的glScale()这样的函数不起作用?
您似乎认为glScale会对之前绘制的内容产生某种直接影响。这不是glScale所做的。 glScale所做的就是修改有源矩阵堆栈的当前顶部元素。没什么。
通常,OpenGL不会维护场景或对象。如果您希望以不同的方式显示某些内容,则必须重新绘制。
BTW:除了错误使用OpenGL之外,代码中有太多混乱,我强烈建议你重新访问你的C ++ 101.你的代码中有很多错误的结构。首先考虑一下(如果numberOfTextures
不是1,那么下面的问题是什么,甚至是错误的?):
textures = new GLuint(); … glGenTextures(numberOfTextures,textures);