-1

我已经下载了在 MFC 控件中设置 OpenGL类并为我的目的对其进行了自定义(显示图像并对其进行缩放和其他翻译):

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);
};  

OpenGL控制.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)几个函数?

那是因为我在这里研究过,OpenGL 两个不同的 3d 渲染图片控件在单个 MFC 对话框上不起作用

所以我的问题是,如果没有创建渲染上下文或者设备上下文无效,opengl 如何绘制那个白色矩形?
如果问题是其他问题,那么问题是什么?
为什么纹理不应用于矩形几何?
为什么缩放操作中使用的 glScale() 等函数不起作用?
为什么 glEnd() 也会产生 1282 错误?是因为功能glTexCoord还是glVertex
如果问题是没有创建上下文,我该如何创建它,请注意,hrc = wglCreateContext(hdc)当课程刚开始时,我在函数之后收到错误 INVALID_OPERATION?

4

1 回答 1

1

所以我的问题是,如果没有创建渲染上下文或者设备上下文无效,opengl 如何绘制那个白色矩形?

我真的没有耐心浏览你发布的代码的混乱。但我想说,因为在绘制矩形时,有一个上下文处于活动状态。

为什么纹理不应用于矩形几何?

启用了不完整的图片定义和 mipmaping。绘制时没有绑定和激活纹理目标。这通常是原因。

为什么缩放操作中使用的 glScale() 等函数不起作用?

您似乎认为 glScale 会对先前绘制的内容产生某种直接影响。这不是 glScale 所做的。glScale 所做的只是修改活动矩阵堆栈的当前顶部元素。而已。

一般来说,OpenGL 不维护场景或对象。如果你想让某些东西看起来不同,你必须重绘。

顺便说一句:除了错误使用 OpenGL 之外,您的代码中有很多混乱,我强烈建议您重新访问您的 C++ 101。您的代码中有大量错误的构造。numberOfTextures对于初学者来说,考虑一下(以下有什么问题,如果不是 1 ,甚至是错误的?):

textures = new GLuint(); 
…
glGenTextures(numberOfTextures,textures);
于 2013-08-14T16:18:20.683 回答