1.opengl 中reshape函数怎么用
2.《图形编程技术学习》(十三)OpenGLStarter程序问题解答(二)
3.glViewport参数
4.glViewport功能
5.å¦ä½å¨mfcä¸è¿è¡openglç¼ç¨åå§åç¯å¢
6.OpenGLä¹Viewport
opengl 中reshape函数怎么用
你说的应该是改变窗口形状,所绘制的源码物体不变形,而只是函数大小发生变化是吧?\x0d\void reshape (int w, int h)\x0d\{ \x0d\ glViewport (0, 0, (GLsizei) w, (GLsizei) h);\x0d\ glMatrixMode (GL_PROJECTION);\x0d\ glLoadIdentity ();\x0d\ if (w <= h)\x0d\ gluOrtho2D (0.0, .0, 0.0, .0 * (GLfloat) h/(GLfloat) w);\x0d\ else\x0d\ gluOrtho2D (0.0, .0 * (GLfloat) w/(GLfloat) h, 0.0, .0);\x0d\ glMatrixMode(GL_MODELVIEW);\x0d\}\x0d\看这个reshape函数当窗口发生变化,窗口的源码w(宽度)和h(高度)参数传给reshape函数,\x0d\ glViewport (0,函数 0, (GLsizei) w, (GLsizei) h);\x0d\把视口设置为铺满整个窗口, if (w <= h)\x0d\ gluOrtho2D (0.0,源码因库源码 .0, 0.0, .0 * (GLfloat) h/(GLfloat) w);\x0d\ else\x0d\ gluOrtho2D (0.0, .0 * (GLfloat) w/(GLfloat) h, 0.0, .0);\x0d\把投影得到的视景体按照视口变化的比例变化视景体的比例;简单地说,本来视景体宽高比是函数1:1,视口宽高比也是源码1:1,这时绘制了一个物体。函数然后因为窗口发生变化,源码视口也变化,函数假如变成了2:1;这时如果用1:1的源码视景体放到2:1的视口上肯定会变形,所以要把视景体变成2:1,函数这样,源码虽然物体看起来变大(或变小)了,函数但长宽比例不变,也就看起来不变形了。注意这个参数(GLfloat) w/(GLfloat) h。
《图形编程技术学习》(十三)OpenGLStarter程序问题解答(二)
一、resnet 源码OpenGLStarter程序相关问题解析
1. 通过免费glut进行OpenGL编程时,重点在于理解消息驱动和回调函数的概念。这有助于程序在特定事件发生时执行特定代码。
2. 函数display()和myReshape()的调用时机取决于OpenGL的窗口状态。display()在窗口更新时调用,而myReshape()在窗口大小发生变化时被调用。
3. 程序通过设置键盘事件的回调函数来实现对物体的旋转和平移控制。当特定键被按下或释放时,回调函数会根据预设规则更新物体的位置。
4. glutIdleFunc()函数用于指定一个函数,在OpenGL上下文空闲时调用。这为实现动画效果提供了一个基础。
5. display()函数中调用glTranslatef(0.0,0.0,-G_fDistance)是为了平移三维空间中的视点,使得场景从不同距离观察。
6. 从程序中可以找到图形绘制的整个流程,即OpenGL的图形流水线,包括CPU和GPU的分工。
7. gluPerspective()函数用于设置透视投影,delta源码定义了视角的垂直视野角度、宽高比、近裁剪面和远裁剪面。
8. glViewport()函数用于设置视口,即确定在屏幕上显示的区域大小。
二、详细解答
5. 在display()函数中调用glTranslatef是为了调整视点位置,实现不同深度的场景观察,提高3D图形的视觉效果。
6. OpenGL的图形流水线可以形象理解为一条流水线,包括顶点着色、几何着色、片段着色、深度测试、模板测试和混合等步骤,最终生成屏幕上的图像。
7. gluPerspective()的使用确保了3D场景中物体的正确透视效果,使得远处的densenet源码物体看起来更小,符合人类视觉经验。
8. glViewport()的设定有助于优化GPU的渲染过程,使屏幕显示更高效、更清晰。
扩展阅读:理解右手坐标系和左手坐标系的原理及其在OpenGL编程中的应用。
在OpenGL编程中,右手坐标系和左手坐标系的概念对理解3D空间的旋转和方向至关重要。右手坐标系中,拇指、食指和中指分别代表X、Y、Z轴的正方向,旋转方向遵循右手定则。左手坐标系中,坐标轴的指向与右手坐标系相反。
OpenGL作为一个状态机,控制着绘制操作的整个流程。glRotatef()函数计算旋转矩阵,页脚源码实现物体的旋转。此外,了解编译与链接的概念、OpenGL的跨平台特性、回调函数和消息映射等知识对于深入理解OpenGLStarter程序至关重要。
glViewport参数
在进行图形绘制时,`glViewport`函数成为了一个关键的组件。其函数原型为:
glViewport(GLint x, GLint y, GLsizei width, GLsizei height)
通过`glViewport`函数,我们可以灵活地控制渲染区域的位置和大小。具体来说:
其中,参数`x`和`y`分别以像素为单位,表示视口的左下角位置坐标。想象一下,你正在绘制一个巨大的画布,`x`和`y`就是你想要从画布的哪个角落开始绘制。比如,如果你想从屏幕左上角开始绘制,`x`和`y`都设置为0;若想从屏幕右下角开始绘制,可以将`x`设置为屏幕宽度减去所需宽度,`y`同样设置为屏幕高度减去所需高度。
参数`width`和`height`则用来定义视口矩形的宽度和高度,决定了实际的绘制区域大小。与`x`和`y`类似,这同样可以根据窗口的实际尺寸实时调整。举个例子,如果你的窗口大小动态变化,通过`glViewport`函数可以相应地调整绘制区域的大小,确保在任何窗口尺寸下都能精确地绘制出你想要的内容。
综上所述,`glViewport`函数的巧妙使用,使得在OpenGL等图形处理库中,能够灵活地控制渲染区域的位置和大小,适应不同的显示需求,从而实现更丰富、更灵活的图形界面。
glViewport功能
在计算机图形学领域,OpenGL是一个广泛使用的图形渲染引擎。它提供了一系列强大的工具和函数,帮助开发者实现复杂的图形渲染任务。其中,glViewport功能就显得尤为重要。
glViewport是OpenGL中的一个关键函数,用于调整视口的大小和位置。在默认情况下,视口被设定为占据打开窗口的整个像素矩形。然而,为了适应不同的应用需求,开发者往往需要选择一个更小的绘图区域。这时,glViewport就扮演了关键角色。
通过使用glViewport函数,开发者可以定义一个像素矩形,作为最终图像映射的目标区域。这一功能允许在同一个窗口中显示分割屏幕的效果,进而展示多个视图。例如,在游戏开发中,开发者可能需要在同一个屏幕上同时显示玩家视角和环境信息,此时,glViewport就成为实现这一目标的强大工具。
使用glViewport函数的过程相对简单,开发者只需要提供四个参数:x、y、width、height。其中,x和y分别表示视口左下角在窗口中的坐标,width和height则表示视口的宽度和高度。通过调整这些参数,开发者可以精确控制视口的大小和位置,从而实现更加灵活和精细的图像渲染。
在实际应用中,glViewport的灵活性和高效性为开发者提供了极大的便利。它不仅简化了图像渲染的复杂性,还极大地增强了OpenGL的可定制性。无论是游戏开发、图形设计还是其他需要复杂图形处理的应用场景,glViewport都是不可或缺的工具。
总之,glViewport功能是OpenGL中一个强大且灵活的工具,它帮助开发者在屏幕上定义和调整绘图区域,实现多样化的图形渲染效果。通过合理使用glViewport,开发者可以创造出更加丰富和吸引人的视觉体验,满足不同应用场景的需求。
å¦ä½å¨mfcä¸è¿è¡openglç¼ç¨åå§åç¯å¢
æ¨å¥½ï¼å¾é«å ´ä¸ºæ¨è§£çã1ï¼æ°å»ºä¸ä¸ªMFCçå·¥ç¨ï¼åææ¡£çå·¥ç¨ã
2ï¼å·¥ç¨å»ºå¥½ä¹åï¼å¯ä»¥å ç¼è¯è¿è¡ä¸ä¸ãä¸é¢å°±æ¯è¦æViewççªå£åå§å为OpenGLçç¼ç¨ç¯å¢ãå½ç¶ä»¥ä¸ææçæä½é½æ¯å¨Viewç±»ä¸è¿è¡çã
å å¨Project->Settings->Linkä¸ï¼å ä¸opengl.lib
glu.lib glut.lib glaux.libï¼ç¶åå¨View.hçç±»å®ä¹ä¸å ä¸å¦ä¸å¼ç¨ã
#include <gl\gl.h>
#include <gl\glu.h>
#include <gl\glaux.h>
3ï¼é¦å è¦è®©çªå£æ¯æOpenGLï¼é£å°±å¿ é¡»è¦å¯¹PIXELFORMATDESCRIPTORè¿ä¸ªç»æææäºè§£ï¼å å¨Viewç±»ä¸æ°å»ºä¸ä¸ªå½æ°SetupPixFormat(CDC
*pDC)ï¼ç±»åï¼çä¸é¢çå½æ°å°±ç¥é为BOOLï¼ï¼æ¹æ³ï¼å¨classviewä¸ï¼æ¾å°**viewç±»ï¼é¼ æ å³å»ï¼æ·»å å½æ°ï¼å ¬æç§ææ æè°ï¼å¦ä¸ï¼
BOOLCTestGLInitialView::SetupPixFormat(CDC *pDC)
//æ建ç«çå·¥ç¨åå«TestGLInitial{ static PIXELFORMATDESCRIPTOR pfd =
//å®ä¹åç´ æ ¼å¼{ sizeof(PIXELFORMATDESCRIPTOR), //
ä¸è¿°æ ¼å¼æ述符çå¤§å° 1, //
çæ¬å· PFD_DRAW_TO_WINDOW | //
æ ¼å¼æ¯æçªå£ PFD_SUPPORT_OPENGL | //
æ ¼å¼å¿ é¡»æ¯æOpenGL PFD_DOUBLEBUFFER, //
å¿ é¡»æ¯æåç¼å² PFD_TYPE_RGBA, // ç³è¯· RGBA
æ ¼å¼ , //
ä½è²å½©æ·±åº¦ï¼å³1.åä¸ççå½©è² 0, 0, 0, 0, 0, 0, //
忽ç¥çè²å½©ä½ 0, //
æ Alphaç¼å 0, //
忽ç¥Shift Bit 0,
// æ ç´¯å ç¼å 0, 0, 0, 0, //
忽ç¥èéä½ , // ä½
Z-ç¼å (深度ç¼å) 0,
// æ èæ¿ç¼å 0, //
æ è¾ å©ç¼å PFD_MAIN_PLANE, //
主ç»å¾å± 0, //
Reserved 0, 0, 0 //
忽ç¥å±é®ç½©};
int nIndex = ChoosePixelFormat(pDC->GetSafeHdc(), &pfd);
//éæ©ååå®ä¹çåç´ æ ¼å¼if( nIndex == 0 ) return FALSE;return
SetPixelFormat(pDC->GetSafeHdc(), nIndex, &pfd);
//设置åç´ æ ¼å¼}
è¿ä¸ªå½æ°ç主è¦ç®çå°±æ¯è®¾ç½®çªå£çåç´ æ ¼å¼ï¼ä½¿ä¹æ¯æOpenGLï¼æç½è¿ç¹å°±è¡äºãå¨å建çªå£çæ¶åï¼è°ç¨è¿ä¸ªå½æ°ã
5ï¼ååé£ä¸ªå½æ°æ¯ç¨æ¥å¨å建çªå£æ¯è°ç¨çï¼å¨å建çªå£æ¶ï¼è¿éè¦å¯¹OpenGLçç¯å¢åä¸äºåå§åï¼åå®ä¹ä¸ä¸ªå½æ°InitialGL()ï¼ï¼æ¹æ³ï¼å¨classviewä¸ï¼æ¾å°**viewç±»ï¼é¼ æ å³å»ï¼æ·»å å½æ°ï¼å ¬æç§æä¹æ æè°ï¼åæ£æ¯èªå·±è°ç¨çï¼å¦ä¸ï¼
BOOLCTestGLInitialView::InitialGL()
{
glShadeModel(GL_SMOOTH);
// å¯ç¨é´å½±å¹³æ»
glClearColor(0.0f, 0.0f, 0.0f,
0.0f); //
é»è²èæ¯
glClearDepth(1.0f);
//
设置深度ç¼å
glEnable(GL_DEPTH_TEST);
//
å¯ç¨æ·±åº¦æµè¯
glDepthFunc(GL_LEQUAL);
// æä½æ·±åº¦æµè¯çç±»å
glHint(GL_PERSPECTIVE_CORRECTION_HINT,
GL_NICEST); // åè¯ç³»ç»å¯¹éè§è¿è¡ä¿®æ£
return
TRUE;
// åå§å OK
}
è¿éç代ç æé½æ¯æçNeHeæç¨ä¸é¢ç代ç ã
6ï¼ç°å¨å¯ä»¥æè·WM_CREATEæ¶æ¯äºï¼æ¹æ³ï¼view-->classvizard -->messages
maps:classname
é**view,æ¾å°WM_CREATEï¼æ·»å å½æ°ï¼ç¼è¾ä»£ç ï¼ãä½æ¯ï¼è¿è¦å å®ä¹ä¸ä¸ªCClientDC*çæåï¼ï¼æ¹æ³ï¼å¨classviewä¸ï¼æ¾å°**viewç±»ï¼é¼ æ å³å»ï¼æ·»å å½æ°æååéãç±»åï¼CClientDC*ï¼ååï¼m_pDCï¼è¿ä¸ªæåæåViewçªå£èªå·±ï¼æ¯ç¨æ¥ä¼ éç»SetupPixFormat(CDC
*pDC)å½æ°çï¼æ²¡å«çææã
ç°å¨ï¼æ¥æè·WM_CREATEæ¶æ¯ï¼ï¼ï¼åä¸å¦ä¸ä»£ç ï¼
intCTestGLInitialView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if
(CView::OnCreate(lpCreateStruct) == -1)
return -1;
//
TODO: Add your specialized creation code here
m_pDC = new
CClientDC(this);
SetupPixFormat(m_pDC);
HGLRC hrc =
wglCreateContext(m_pDC->GetSafeHdc());
wglMakeCurrent(m_pDC->GetSafeHdc(),
hrc);
InitialGL();
return
0;
}
å½ç¶ï¼å½çªå£å ³éçæ¶åï¼è¿åºè¯¥è¦éæ¾ä¸äºèµæºãæè·WM_DESTROYæ¶æ¯ï¼ï¼æ¹æ³ï¼view-->classvizard
-->messages maps:classname é**view,æ¾å°WM_DESTROYï¼æ·»å å½æ°ï¼ç¼è¾ä»£ç ï¼åä¸å¦ä¸ä»£ç ï¼
voidCTestGLInitialView::OnDestroy()
{
CView::OnDestroy();
// TODO: Add
your message handler code here
HGLRC hrc =
wglGetCurrentContext();
wglMakeCurrent(NULL,
0);
wglDeleteContext(hrc);
delete
m_pDC;
}
ç°å¨å¯ä»¥ç¼è¯ä¸ä¸äºï¼æ²¡æé误ã
7ï¼ç°å¨ï¼OpenGLçç¯å¢å·²ç»åå§åå·®ä¸å¤äºãå¯ä»¥å¼å§åå¾äºï¼å å®ä¹ä¸ä¸ªä½å¾çå½æ°DrawScene()ï¼åä¸å¦ä¸ç代ç ï¼
BOOLCTestGLInitialView::DrawScene()
{
glClear(GL_COLOR_BUFFER_BIT |
GL_DEPTH_BUFFER_BIT); //
æ¸ é¤å±å¹å深度ç¼å
glLoadIdentity();
//
éç½®å½åç模åè§å¯ç©éµ
SwapBuffers(m_pDC->GetSafeHdc());
// 交æ¢ç¼å²åº
return TRUE;
}
ç¶åï¼è¦å¨OnDrawä¸ï¼è°ç¨è¿ä¸ªå½æ°ï¼
voidCTestGLInitialView::OnDraw(CDC* pDC)
{
CTestGLInitialDoc* pDoc =
GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data
here
DrawScene();
}
8ï¼è¿è¡ä¸ä¸ï¼é»è²çèæ¯åºæ¥äºã
9ï¼è¿æ¶ï¼å¯ä»¥ä¿®æ¹DrawScene()è¿ä¸ªä½å¾å½æ°ï¼ä½å¾ãç»åºNeHe第3课çé£ä¸ªä¸è§å½¢åæ£æ¹å½¢æ¥ãå代ç å¦ä¸ï¼
BOOLCTestGLInitialView::DrawScene(){ glClear(GL_COLOR_BUFFER_BIT |
GL_DEPTH_BUFFER_BIT); //
æ¸ é¤å±å¹å深度ç¼åglLoadIdentity();
// éç½®å½åç模åè§å¯ç©éµ
glTranslatef(-1.5f,0.0f,-6.0f); // 左移
1.5 åä½ï¼å¹¶ç§»å ¥å±å¹
6.0glBegin(GL_TRIANGLES); //
ç»å¶ä¸è§å½¢glColor3f(1.0f, 0.0f, 0.0f);glVertex3f( 0.0f, 1.0f,
0.0f); // ä¸é¡¶ç¹glColor3f(0.0f, 1.0f,
0.0f);glVertex3f(-1.0f,-1.0f, 0.0f); //
å·¦ä¸glColor3f(0.0f, 0.0f, 1.0f);glVertex3f( 1.0f,-1.0f,
0.0f); //
å³ä¸glEnd();
//
ä¸è§å½¢ç»å¶ç»æglTranslatef(3.0f,0.0f,0.0f);
// å³ç§»3åä½glColor3f(0.0f, 0.0f,
1.0f);glBegin(GL_QUADS);
// ç»å¶æ£æ¹å½¢glVertex3f(-1.0f, 1.0f, 0.0f);
// å·¦ä¸glVertex3f( 1.0f, 1.0f, 0.0f); //
å³ä¸glVertex3f( 1.0f,-1.0f, 0.0f); //
å·¦ä¸glVertex3f(-1.0f,-1.0f, 0.0f); //
å³ä¸
glEnd();SwapBuffers(m_pDC->GetSafeHdc());
// 交æ¢ç¼å²åºreturn TRUE;}
è¿è¡ä¸ä¸ï¼åç°å¾å½¢æ²¡æåºç°ï¼è¿ä¸ªæä¹åäºå¢ãåæ¥æ¯å 为è¿æ²¡æå®ä¹æå½±æ¹å¼åè§å£ãå³ç¨æ£äº¤æå½±è¿æ¯éè§æå½±ãå®ä¹æå½±ï¼è¿è¦æè·WM_SIZEæ¶æ¯ãåå¦ä¸ä»£ç ï¼
voidCTestGLInitialView::OnSize(UINT nType, int cx, int
cy)
{
CView::OnSize(nType, cx, cy);
// TODO: Add your message
handler code here
if (0 ==
cy) //
é²æ¢è¢«é¶é¤
{
cy =
1; //
å°Height设为1
}
glViewport(0, 0, cx, cy);
// éç½®å½åçè§å£
glMatrixMode(GL_PROJECTION); //
éæ©æå½±ç©éµ
glLoadIdentity(); //
éç½®æå½±ç©éµ
//
设置è§å£ç大å°
gluPerspective(.0f,(GLfloat)cx/(GLfloat)cy,0.1f,.0f);
glMatrixMode(GL_MODELVIEW);
// éæ©æ¨¡åè§å¯ç©éµ
glLoadIdentity(); //
é置模åè§å¯ç©éµ
}
åè¿è¡ä¸ä¸ï¼å¾å½¢å·²ç»åºæ¥äºã以åï¼å°±å¯ä»¥å¨DrawScene()åä»»ä½ç»å¾ç代ç äºï¼å½çªå£éç»çæ¶åï¼é½å¯ä»¥èªå¨éåºãå¦æè¦åä¸æ®µå¯ä»¥è¿å¨ç3Då¾ç»ï¼å¯ä»¥åæè·WM_TIMERæ¶æ¯ï¼éè¿å¨OnCreateçæ¶åå®ä¹ä¸ä¸ªæ¶éï¼åé åä¸äºåéï¼å°±å¯ä»¥åç®åçå¨ç»äº
å¦è¥æ»¡æï¼è¯·ç¹å»å³ä¾§ãé纳çæ¡ãï¼å¦è¥è¿æé®é¢ï¼è¯·ç¹å»ã追é®ã
å¸ææçåç对æ¨ææ帮å©ï¼æé纳ï¼
~ O(â©_â©)O~
OpenGLä¹Viewport
1.1 çªå£(Screen)çªå£å ¶å®å°±æ¯å±å¹ï¼å¦ä¸å¾1ä¸çº¢è²åä¸é»è²èæ¯çé¨åãææçåºæ¯æç»é½æ¯è¦è¢«å æ åä¹æ¾ç¤ºå¨ä¸çå¾åï¼å±å¹æ¯ææåºæ¯ï¼2Dã3Dçï¼çæç»è¾åºç®çå°ãä¸ä¸ªscreenå¯ä»¥æ¾ç¤ºå¤ä¸ªè§å£ä¸çå 容ï¼
1.2 è§å£(Viewport)
è§å£å°±æ¯çªå£ä¸ç¨æ¥æ¾ç¤ºå¾å½¢çä¸åç©å½¢åºåï¼å®å¯ä»¥åçªå£ç大ï¼ä¹å¯ä»¥æ¯çªå£å¤§æè å°,å¦å¾1ä¸èè²æ 示ç绿è²èæ¯çåºåãå®å ·æ两个æä¹:
ãã• å®ä¹äºè§éä½ä¸çæ¯ç©è¦è¢«ç»å¶å°ä¸å¼ ä»ä¹å°ºå¯¸çç»å¸ä¹ä¸ï¼
ãã• å®ä¹äºç»å¸å¨å±å¹çä»ä¹åºåï¼
æ¾ç¶ï¼å¦æ è§æ¯ä½çæå½±å¹³é¢ å®ä¹ç宽é«æ¯å è§å£ æå®ä¹ç宽é«æ¯ ä¸ç¸å çè¯ï¼é£ä¹å°è§æ¯ä½ä¸çç©ä½ç»å¶å°ç»å¸ä¸çæ¶åä¼è¿è¡ æ伸æè å缩 ï¼èå½è§æ¯ä½æ影平é¢ç宽é«æ¯åè§å£æå®ä¹ç宽é«æ¯ä¸è´çæ¶åï¼å¾åå°ä¼ä¸è¿è¡ä»»ä½ç¼©æ¾ç»å¶å°è§å£æå®ä¹çç»å¸ä¹ä¸ã
å¨å®é åºç¨ä¸ï¼ä¸ä¸ªçªå£ä¸ä¼ç»å¶å¤ä¸ª3Dåºæ¯ï¼è¿ä¸ªéè¿å®ä¹å¤ä¸ªè§å£ï¼ç»å¶å¤ä¸ªå¾åï¼ç¶åè´´å¨å±å¹çä¸ååºåå³å¯ãæ¯å¦å¾ä¸é»è²ç¬åä¸çåºåï¼å¨ç»å¸ä¸å®äºä¸¤ä¸ªä¸åçviewport1 ï¼0,0;w/2,yï¼å viewport2 ï¼0,w/2;w/2,yï¼ï¼
1.4 è§éä½(View Frustum)
è§æ¯ä½(View Volume)å®ä¹äºæ们è½å¤éè¿èæç3Dæåæºæè½çå°çåºæ¯ãå¨ä¸ä¸ª3Dåºæ¯ä¸ç«ç«ä¸ï¼éè¦æåæºçææ¾ä½ç½®åè§éæ¥å®ä¹æ们æè½å¤çå°çä¸è¥¿ï¼èè¿ä¸ªè§éå°±æ¯éè¿è§æ¯ä½æ¥å®ä¹çãå¨3Dä¸ï¼ä¸è¬å¯ä»¥éè¿ä»¥ä¸ä¸¤ç§æ¹å¼æ¥å®ä¹è§æ¯ä½ï¼
éè¿åé¢çä»ç»ï¼æ们大è´çäºè§£äºè¿ä¸ä¸ªä¸åä¸è¥¿çæ¦å¿µãä»ä¸æ们å¯ä»¥ç¥éï¼éè¿å®ä¹æå½±ç©éµï¼æ们å®é ä¸æ¯å¨èæç3D空é´ä¸ï¼å建äºä¸ä¸ªè§éï¼ä¹å°±æ¯è§æ¯ä½ãå¨æ¥çï¼æ们éè¿å®ä¹è§å£ï¼æ¥æè¿°è§æ¯ä½ä¸çå 容å¦ä½æ å°å°ä¸ä¸ªèæçç»å¸ä¹ä¸ï¼å¹¶ä¸è¿ä¸ªç»å¸æç»å°æ¾ç¤ºå¨å±å¹ä¸çä»ä¹ä½ç½®ãå½ææçè¿äºé½è®¾ç½®å®æ¯ï¼æ们ç»å¶å®æ¯åºæ¯ä¹åï¼å°±è½å¤éè¿ç¡¬ä»¶å¨æ们çæ¾ç¤ºå¨å±å¹ä¸çå°æç»çç»é¢ãæ´ç论ç表述就æ¯ï¼éè¿å®ä¹æå½±ç©éµï¼å°3Dåºæ¯æå½±å°ä¸ä¸ªæ影平é¢ä¹ä¸ãéè¿å®ä¹è§å£ï¼æ们å°æ影平é¢ä¸çå 容æ å°å°è¿ä¸ªè§å£ä¸å»ï¼å¹¶ä¸å¡«æ»¡å®ï¼åæ¶æ ¹æ®å®ä¹è§å£æ¯ç»å®çå±å¹åæ çä½ç½®ï¼å°è¿ä¸ªè§å£ä¸çå¾åæ å°å°çªå£çæå®ä½ç½®ä¹ä¸ï¼æç»æ们就çå°äºå¾åã
glViewportæ¯OpenGLä¸çä¸ä¸ªå½æ°ã计ç®æºå¾å½¢å¦ä¸ï¼å¨å±å¹ä¸æå¼çªå£çä»»å¡æ¯ç±çªå£ç³»ç»ï¼èä¸æ¯OpenGLè´è´£çãglViewportå¨é»è®¤æ åµä¸ï¼è§å£è¢«è®¾ç½®ä¸ºå æ®æå¼çªå£çæ´ä¸ªåç´ ç©å½¢ï¼å¦å¾1ï¼çªå£å¤§å°å设置è§å£å¤§å°ç¸åï¼æ以为äºéæ©ä¸ä¸ªæ´å°çç»å¾åºåï¼å°±å¯ä»¥ç¨glViewportå½æ°æ¥å®ç°è¿ä¸åæ¢ï¼å¨çªå£ä¸å®ä¹ä¸ä¸ªåç´ ç©å½¢ï¼æç»å°å¾åæ å°å°è¿ä¸ªç©å½¢ä¸ãä¾å¦å¯ä»¥å¯¹çªå£åºåè¿è¡ååï¼å¨åä¸ä¸ªçªå£ä¸æ¾ç¤ºåå²å±å¹çææï¼ä»¥æ¾ç¤ºå¤ä¸ªè§å¾ã
OpenGL中的reshape函数如何处理窗口形状改变事件?
在OpenGL和GLUT的世界中,你是否对reshape函数有所困惑?当窗口尺寸发生变化时,GLUT中的glutReshapeFunc(reshape)正是那个关键的幕后英雄,它负责响应窗口形状调整的事件,引导我们调整图形的显示。 “reshape”这个词,其实是在说窗口调整时的图形处理策略。它给予开发者灵活的空间,可以根据实际需求定制反应。例如,你可能选择图形的长宽比例跟随窗口尺寸动态变化,实现精细的缩放效果。 比如,你可以编写这样的函数来实现这一目标:void reshape(int cur_w, int cur_h) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if (cur_h <= 0) {
cur_h = ; // 防止窗口过小时的处理
}
glViewport(0, 0, cur_w, cur_h);
float xfactor = (float) glutGet(GLUT_WINDOW_WIDTH) / (float) img_width; // 按窗口宽度缩放
float yfactor = (float) glutGet(GLUT_WINDOW_HEIGHT) / (float) img_height; // 按窗口高度缩放
glutPostRedisplay(); // 通知系统进行图形的更新
}
通过这样的reshape函数,你可以确保图形始终适应窗口变化,保持视觉一致性。希望这个简要的解释能帮助你理解并应用到实际项目中。 至此,关于reshape函数的分享就到这里,期待它能为你的OpenGL编程旅程增添一抹亮色。glViewPort
glViewPortä¸åæ¯Pè¦å°å -- glViewport(...)
å½æ°ååæ¯
void glViewport(GLint x,
GLint y,
GLsizei width,
GLsizei height)
å®æ¯OpenGLåºéçä¸è¥¿,å«å¿äº #include æå ³çOpenGLç头æ件.