gpt4 book ai didi

c++ - OpenGL 两个不同的 3d 渲染图片控件在单个 MFC 对话框上不起作用

转载 作者:行者123 更新时间:2023-11-27 23:21:54 28 4
gpt4 key购买 nike

我正在使用 VC++ MFC 创建一个应用程序,其中我有两个不同的 opengl 窗口。我已经按照enter link description here的教程做了

我能够成功使用一个图片控件,其中 opengl 窗口显示正确的渲染,但如果我创建该控件的两个不同对象,那么一个窗口不会显示任何内容。

这里更详细的解释是代码

m_WinGL 和 m_WinGL2 是 initDialog 内部自定义类的两个不同对象。

// Get size and position of the template textfield we created before in the dialog editor
CRect rect;
GetDlgItem(IDC_STATIC_GL)->GetWindowRect(rect);
ScreenToClient(rect);// Convert screen coordinates to client coordinates

m_WinGL.oglCreate(rect, this);// Create OpenGL Control window
m_WinGL.m_unpTimer = m_WinGL.SetTimer(1, 1, 0);// Setup the OpenGL Window's timer to render


GetDlgItem(IDC_STATIC_GL2)->GetWindowRect(rect);
ScreenToClient(rect);// Convert screen coordinates to client coordinates

m_WinGL2.oglCreate(rect, this,L"X");// Create OpenGL Control window
m_WinGL2.m_unpTimer = m_WinGL2.SetTimer(1, 1, 0);// Setup the OpenGL Window's timer to render

这里是自定义控件的类

头文件

#pragma once
#include "afxwin.h"

#include <gl/gl.h>
#include <gl/glu.h>

class COpenGLControl : public CWnd
{
public:
/******************/
/* Public Members */
/******************/
UINT_PTR m_unpTimer;
// View information variables
float m_fLastX;
float m_fLastY;
float m_fPosX;
float m_fPosY;
float m_fZoom;
float m_fRotX;
float m_fRotY;
bool m_bIsMaximized;

private:
/*******************/
/* Private Members */
/*******************/
// Window information
CWnd *hWnd;
HDC hdc;
HGLRC hrc;
int m_nPixelFormat;
CRect m_rect;
CRect m_oldWindow;
CRect m_originalRect;

public:
COpenGLControl(void);
virtual ~COpenGLControl(void);

void oglCreate(CRect rect, CWnd *parent,CString strWindowName=L"OpenGl");
void oglInitialize(void);
void oglDrawScene(void);

// Added message classes:
afx_msg void OnPaint();
afx_msg void OnSize(UINT nType, int cx, int cy);
afx_msg void OnDraw(CDC *pDC);
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnTimer(UINT nIDEvent);
afx_msg void OnMouseMove(UINT nFlags, CPoint point);

DECLARE_MESSAGE_MAP()
};

cpp文件

    #include "stdafx.h"
#include "OpenGLControl.h"

COpenGLControl::COpenGLControl(void)
{
m_fPosX = 0.0f; // X position of model in camera view
m_fPosY = 0.0f; // Y position of model in camera view
m_fZoom = 10.0f; // Zoom on model in camera view
m_fRotX = 0.0f; // Rotation on model in camera view
m_fRotY = 0.0f; // Rotation on model in camera view
m_bIsMaximized = false;
}

COpenGLControl::~COpenGLControl(void)
{
}

BEGIN_MESSAGE_MAP(COpenGLControl, CWnd)
ON_WM_PAINT()
ON_WM_SIZE()
ON_WM_CREATE()
ON_WM_TIMER()
ON_WM_MOUSEMOVE()
END_MESSAGE_MAP()

void COpenGLControl::OnPaint()
{
//CPaintDC dc(this); // device context for painting
ValidateRect(NULL);
}

void COpenGLControl::OnSize(UINT nType, int cx, int cy)
{
CWnd::OnSize(nType, cx, cy);

if (0 >= cx || 0 >= cy || nType == SIZE_MINIMIZED) return;

// Map the OpenGL coordinates.
glViewport(0, 0, cx, cy);

// Projection view
glMatrixMode(GL_PROJECTION);

glLoadIdentity();

// Set our current view perspective
gluPerspective(35.0f, (float)cx / (float)cy, 0.01f, 2000.0f);

// Model view
glMatrixMode(GL_MODELVIEW);

switch (nType)
{
// If window resize token is "maximize"
case SIZE_MAXIMIZED:
{
// Get the current window rect
GetWindowRect(m_rect);

// Move the window accordingly
MoveWindow(6, 6, cx - 14, cy - 14);

// Get the new window rect
GetWindowRect(m_rect);

// Store our old window as the new rect
m_oldWindow = m_rect;

break;
}

// If window resize token is "restore"
case SIZE_RESTORED:
{
// If the window is currently maximized
if (m_bIsMaximized)
{
// Get the current window rect
GetWindowRect(m_rect);

// Move the window accordingly (to our stored old window)
MoveWindow(m_oldWindow.left, m_oldWindow.top - 18, m_originalRect.Width() - 4, m_originalRect.Height() - 4);

// Get the new window rect
GetWindowRect(m_rect);

// Store our old window as the new rect
m_oldWindow = m_rect;
}

break;
}
}
}

int COpenGLControl::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CWnd::OnCreate(lpCreateStruct) == -1) return -1;

oglInitialize();

return 0;
}

void COpenGLControl::OnDraw(CDC *pDC)
{
// If the current view is perspective...
glLoadIdentity();

glTranslatef(0.0f, 0.0f, -m_fZoom);
glTranslatef(m_fPosX, m_fPosY, 0.0f);
glRotatef(m_fRotX, 1.0f, 0.0f, 0.0f);
glRotatef(m_fRotY, 0.0f, 1.0f, 0.0f);
}

void COpenGLControl::OnTimer(UINT nIDEvent)
{
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 COpenGLControl::OnMouseMove(UINT nFlags, CPoint point)
{
int diffX = (int)(point.x - m_fLastX);
int diffY = (int)(point.y - m_fLastY);
m_fLastX = (float)point.x;
m_fLastY = (float)point.y;

// Left mouse button
if (nFlags & MK_LBUTTON)
{
m_fRotX += (float)0.5f * diffY;

if ((m_fRotX > 360.0f) || (m_fRotX < -360.0f))
{
m_fRotX = 0.0f;
}

m_fRotY += (float)0.5f * diffX;

if ((m_fRotY > 360.0f) || (m_fRotY < -360.0f))
{
m_fRotY = 0.0f;
}
}

// Right mouse button
else if (nFlags & MK_RBUTTON)
{
m_fZoom -= (float)0.1f * diffY;
}

// Middle mouse button
else if (nFlags & MK_MBUTTON)
{
m_fPosX += (float)0.05f * diffX;
m_fPosY -= (float)0.05f * diffY;
}

OnDraw(NULL);

CWnd::OnMouseMove(nFlags, point);
}

void COpenGLControl::oglCreate(CRect rect, CWnd *parent,CString strWindowName)
{
CString className = AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW | CS_OWNDC, NULL, (HBRUSH)GetStockObject(BLACK_BRUSH), NULL);

CreateEx(0, className,strWindowName, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, rect, parent, 0);

// Set initial variables' values
m_oldWindow = rect;
m_originalRect = rect;

hWnd = parent;
}

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

void COpenGLControl::oglDrawScene(void)
{
// Wireframe Mode
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

glBegin(GL_QUADS);
// Front Side
glVertex3f( 1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f( 1.0f, -1.0f, 1.0f);

// Back Side
glVertex3f(-1.0f, -1.0f, -1.0f);
glVertex3f(-1.0f, 1.0f, -1.0f);
glVertex3f( 1.0f, 1.0f, -1.0f);
glVertex3f( 1.0f, -1.0f, -1.0f);

// Top Side
glVertex3f( 1.0f, 1.0f, 1.0f);
glVertex3f( 1.0f, 1.0f, -1.0f);
glVertex3f(-1.0f, 1.0f, -1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);

// Bottom Side
glVertex3f(-1.0f, -1.0f, -1.0f);
glVertex3f( 1.0f, -1.0f, -1.0f);
glVertex3f( 1.0f, -1.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);

// Right Side
glVertex3f( 1.0f, 1.0f, 1.0f);
glVertex3f( 1.0f, -1.0f, 1.0f);
glVertex3f( 1.0f, -1.0f, -1.0f);
glVertex3f( 1.0f, 1.0f, -1.0f);

// Left Side
glVertex3f(-1.0f, -1.0f, -1.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, -1.0f);
glEnd();
}

最佳答案

OpenGL 是一个线程全局上下文状态机。这意味着,您必须将当前线程的 OpenGL 上下文切换到正确的窗口,以便绘图命令在您想要的位置结束。

在每个调用 OpenGL 的成员函数中放在开头

wglMakeCurrent(hdc, hrc);

在您离开函数之前(即在结束时或返回之前)

wglMakeCurrent(NULL, NULL);

顺便说一句:您可以对任意数量的窗口使用单个 OpenGL 上下文,只要它们共享相同的视觉属性,即如果您调用 SetPixelFormatDescriptor 并为每个窗口使用相同的 PFD,您希望使用的上下文。

最后但同样重要的是,OnSize 中的所有代码和 onInitialize 中的所有“基本设置”都应放入绘图代码中。您的 OnDraw 也不是很有用。

关于c++ - OpenGL 两个不同的 3d 渲染图片控件在单个 MFC 对话框上不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12227586/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com