`
izuoyan
  • 浏览: 8934733 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Win32 OpenGL编程(10) 视口变换

阅读更多

write by 九天雁翎(JTianLing) -- blog.csdn.net/vagrxie

讨论新闻组及文件

提要

在前文(系列文章(7),以下简称XO7,系列其他文章类似)中的照相机比喻中提到了4种3D变换,如下:

1.确定照相机的位置的过程对应于“视图变换”(Viewing Transformations)

2.确定物体位置的过程对应于“模型变换”(Modeling Transformations)

3.确定照相机放大倍数的过程对应于“投影变换”(Projection Transformations)

4.确定照片大小的过程对应于“视口变换”(Viewport Transformations)

XO7中我们讲的是第一种变换视图变换,即改变观察者本身的位置,视角等的变换效果,XO8中讲的是第二种变换模型变换,XO9中讲的是投影变换,本文开始讲解最后一个变换,视口变换。

视口变换

此变换应该算是4种变换中最简单的了,在照相机比喻中我说他是确认照片大小,在实际中,确认的是绘制的区域,当然,我们以前没有设定视口变换前,默认是占据整个窗口的客户区的。只有一个关键函数glViewport,而且较易理解:

OpenGL Programming Guide 》:

glViewport — set the viewport
C Specification
void glViewport( GLint x,
GLint y,
GLsizei width,
GLsizei height);
Parameters

x, y

Specify the lower left corner of the viewport rectangle,
in pixels. The initial value is (0,0).
width, height

Specify the width and height
of the viewport.
When a GL context is first attached to a window,
width and height are set to the dimensions of that
window.

无论前面进行了多少处理,最终的图像将映射到这个矩形中,默认情况时占据整个窗口的客户区,在前面的所有例子中,(七巧板的例子除外)我们没有接触到视口变换,那么默认就是窗口创建那一瞬间的大小,我们可以尝试改变窗口大小,发现事实上图形没有变大,并且,位置也不再居中了,这个时候我们就需要进行视口变换,调整视口。这里,因为以前有七巧板的例子了,也有原来没有使用的例子,我就不提供新的此用途的例子了,仅仅看两个例子的区别。

未在窗口改变时重新设定视口的情况:

正常情况:

image

窗口缩小时:图像偏移了。

image

窗口放大时:图像不居中。

image

看七巧板中的例子:

因为有以下代码:

void 
ReShape
(unsigned 
auWidth
, unsigned 
auHeight
)
{
    glViewport
(0, 0, auWidth
, auHeight
);
}

// FUNCTIONS //////////////////////////////////////////////

LRESULT CALLBACK WindowProc
(HWND hwnd
, 
                            UINT msg
, 
                            WPARAM wparam
, 
                            LPARAM lparam
)
{
    // this is the main message handler of the system
    
PAINTSTRUCT        ps
;        // used in WM_PAINT
    
HDC                hdc
;    // handle to a device context

    // what is the message 
    
switch
(msg
)
    {    
    case 
WM_CREATE
: 
        {
            // do initialization stuff here
            // return success
            
return
(0);
        } break
;

    case 
WM_PAINT
: 
        {
            // simply validate the window 
            
hdc 
= BeginPaint
(hwnd
,&ps
);     

            // end painting
            
EndPaint
(hwnd
,&ps
);

            // return success
            
return
(0);
        } break
;

    case 
WM_DESTROY
: 
        {
            // kill the application, this sends a WM_QUIT message 
            
PostQuitMessage
(0);

            // return success
            
return
(0);
        } break
;
    case 
WM_SIZE
:
        {
            ReShape
(LOWORD
(lparam
), HIWORD
(lparam
));
        }
    default
:break
;

    } // end switch

    // process any messages that we didn't take care of 
    
return 
(DefWindowProc
(hwnd
, msg
, wparam
, lparam
));

} // end WinProc

注意reshape的作用,此时,窗口大小改变时,会重新设定视口,这样,图形将会随着窗口大小改变而改变(这是大部分情况下我们需要的)

正常情况下:

image 窗口缩小:图形还是居中,因为纵横比的改变,导致图形纵横比也改变了。

image 窗口放大时:图形还是居中,因为纵横比的改变,导致图形纵横比也改变了。

image

上述七巧板的例子中,很好的演示了glViewport的作用,源代码在以前就已经提供了,这里不再说了。但是,我们会发现一个问题,就是窗口纵横比改变的时候,图形实际也改变了纵横比导致变形了,这样不太符合大部分情况下我们的想法,我们可以通过控制窗口的纵横比来控制这一点,(大部分情况下)或者直接通过控制glViewport参数的纵横比也可以达到保证图像不扭曲的目的。(但是图形可能移位)

屏幕分割

玩过真三国无双系列的玩家们不知道在同一台机器上与战友们浴血奋斗过没有,我是有过,显示时,一个玩家在上面,一个在下面,在同一台机器上不需要通过网络就能享受联机的乐趣,的确很有意思,事实上,我们通过视口变换连续绘制图形两次就能达到这样的效果(我不知道真三国是否也是通过这样的技术实现的),比如上述的七巧板的例子吧,我们想在屏幕上绘制4次,让四个人同时玩,进行对战,那么我们就可以这样做:

void 
ReShape
(unsigned 
auWidth
, unsigned 
auHeight
)
{
    WindowWidth 
= auWidth
;
    WindowHeight 
= auHeight
;

}

// All Scene Show code 

void 
SceneShow
(GLvoid
)        
{
    glClear
(GL_COLOR_BUFFER_BIT
);    

    // left bottom
    
glViewport
(0, 0, WindowWidth
/2, WindowHeight
/2);

    gTriBTop
.Draw
();
    gTriBRight
.Draw
();
    gTriSLeft
.Draw
();
    gRectangle
.Draw
();
    gTriSMid
.Draw
();
    gTriMLeft
.Draw
();
    gParal
.Draw
();

    // right bottom
    
glViewport
(WindowWidth
/2, 0, WindowWidth
/2, WindowHeight
/2);

    gTriBTop
.Draw
();
    gTriBRight
.Draw
();
    gTriSLeft
.Draw
();
    gRectangle
.Draw
();
    gTriSMid
.Draw
();
    gTriMLeft
.Draw
();
    gParal
.Draw
();

    // left top 
    
glViewport
(0 , WindowHeight
/2, WindowWidth
/2, WindowHeight
/2);

    gTriBTop
.Draw
();
    gTriBRight
.Draw
();
    gTriSLeft
.Draw
();
    gRectangle
.Draw
();
    gTriSMid
.Draw
();
    gTriMLeft
.Draw
();
    gParal
.Draw
();

    // right top 
    
glViewport
(WindowWidth
/2 , WindowHeight
/2, WindowWidth
/2, WindowHeight
/2);

    gTriBTop
.Draw
();
    gTriBRight
.Draw
();
    gTriSLeft
.Draw
();
    gRectangle
.Draw
();
    gTriSMid
.Draw
();
    gTriMLeft
.Draw
();
    gParal
.Draw
();

    glFlush
();
}  

显示效果:

image

注意上述代码中,我们的具体的显示代码只有一份,显示代码中并不知道自己绘制了几份,绘制在什么地方,这也就是OpenGL这样设计的好处,本身图形的绘制很简单,在原点附近绘制一个标准的图形而已,一种又一种变换后,却可以产生于原来图形千差万别的图形,这一点有点像设计模式中的decorator模式.

为节省篇幅仅贴出关键片段,完整源代码见我博客源代码的2009-10-29\JTFourTangram 目录,获取方式见文章最后关于获取博客完整源代码的说明。

呵呵,相当happy吧,同一台机子,4个人同时玩七巧板,(事实上,什么游戏都可以借鉴),什么?就一个鼠标没有办法操作?晕哪,你不会插四个鼠标?插四个鼠标也没有用?呵呵,推荐你看看我以前写的关于多鼠标的东西,4个人用4个鼠标同时玩,不是什么不可能的^^以前魔兽好像有个4国战争的游戏地图很流行,要是额外设计,我们可以在同一台机器上玩^^发挥大家的创意吧。

参考资料

1. 《OpenGL Reference Manual 》,OpenGL参考手册

2. 《OpenGL 编程指南》(《OpenGL Programming Guide 》),Dave Shreiner,Mason Woo,Jackie Neider,Tom Davis 著,徐波译,机械工业出版社

3. 《Nehe OpenGL Tutorials》,Nehe著,在http://nehe.gamedev.net/ 上可以找到教程及相关的代码下载,(有PDF版本教程下载)Nehe自己还做了一个面向对象的框架,作为演示程序来说,这样的框架非常合适。也有中文版 ,各取所需吧。

4. 《OpenGL入门学习》 ,eastcowboy著,这是我在网上找到的一个比较好的教程,较为完善,而且非常通俗。这是第一篇的地址:http://bbs.pfan.cn/post-184355.html

本OpenGL系列其他文章

1. Win32 OpenGL 编程(1)Win32下的OpenGL编程必须步骤

2. 《Win32 OpenGL编程(2) 寻找缺失的OpenGL函数

3. 《Win32 OpenGL编程(3) 基本图元(点,直线,多边形)的绘制

4. 《Win32 OpenGL编程(4) 2D图形基础(颜色及坐标体系进阶知识)

5. 《Win32 OpenGL编程(5)顶点数组详细介绍

6.《Win32 OpenGL编程(6) 踏入3D世界

7.《Win32 OpenGL编程(7) 3D视图变换——真3D的关键

8.《Win32 OpenGL编程(8) 3D模型变换及其组合应用

9.《Win32 OpenGL编程(9) 投影变换

应用举例:《Win32 OpenGL编程系列 2D例子 -- 七巧板图形绘制

完整源代码获取说明

由于篇幅限制,本文一般仅贴出代码的主要关心的部分,代码带工程(或者makefile)完整版(如果有的话)都能用Mercurial在Google Code中下载。文章以博文发表的日期分目录存放,请直接使用Mercurial克隆下库:

https://blog-sample-code.jtianling.googlecode.com/hg/

Mercurial使用方法见《分布式的,新一代版本控制系统Mercurial的介绍及简要入门

要是仅仅想浏览全部代码也可以直接到google code上去看,在下面的地址:

http://code.google.com/p/jtianling/source/browse?repo=blog-sample-code

原创文章作者保留版权 转载请注明原作者 并给出链接

write by 九天雁翎(JTianLing) -- blog.csdn.net/vagrxie

分享到:
评论

相关推荐

    opengl 中模型变换,投影变换,视点变换,视口变换的演示程序及源码

    opengl中模型变换,投影变换,视点变换,视口变换比较让人头晕,看个这个演示就会有清楚的认识啦 http://www.99pan.com/Invite?uid=171324

    视口变换程序

    本软件可实现单视口到多视口的变换

    OpenGL视口变换

    OpenGL利用C语言做出4个不同的视口,每个视口中都有一个按不同方向旋转的带颜色的四棱锥,C语言代码完整,并标注完整注释,适合初学者参考学习。

    opengl多视口显示模型

    实现opengl多视口显示模型 窗口分割

    OpenGL编程指南(第八版)完整版

    本书共12张,第一章:OpenGL概述,第二章:着色器基础,第三章:OpenGL绘制方式,第四章:颜色、像素和帧缓存,第五章:视口变换、剪切与反馈,第六章:纹理,第七章:光照与阴影,第八章:程序式纹理,第九章:细分...

    多视口OpenGL程序

    多视口OpenGL程序,将单文档的窗口分成左右两个部分,使其独立渲染图形。

    win程序窗口与视口关系

    win程序窗口与视口关系,讲述win程序窗口与视口关系

    窗口到视口的坐标变换源代码

    窗口到视口的坐标变换源代码

    OpenGL教程第42课多重视口.rar

    OpenGL教程第42课多重视口.rar

    opengl中关于图形变换的VC++程序

    使用opengl写的关于图形和颜色变换的VC++程序。 主要涉及有关投影,视口变换,旋转、平移和缩放等有关的编程方法。

    OpenGL基础图形编程

     8.5 视口变换  8.6 堆栈操作  第九章 OpenGL颜色  9.1 计算机颜色  9.1.1 颜色生成原理  9.1.2 RGB色立体  9.2 颜色模式  9.2.1 RGBA模式  9.2.2 颜色表模式  9.2.3 两种模式应用场合  9.3 颜色应用...

    OpenGL图形管线和坐标变换

    OpenGL 图形管线 渲染管线 坐标变换 模型观测变换 投影变换 正交投影 投影设置 视口变换

    OpenGL中的三维物体的显示中使用的坐标变换

    OpenGL通过相机模拟可以实现计算机图形学中最基本的三维变换,即几何变换、投影变换、裁剪变换、视口变换等,同时,OpenGL还实现了矩阵堆栈等。 为了使被显示的三维物体数字化,要在被显示的物体所在的空间中定义一...

    窗口 视口概念详解

    窗口 视口 概念区别 详解 如何对其进行判别

    OpenGL教程NeHe源代码

    OpenGL教程NeHe源代码,教程源代码。 NeHe教程是学习OpenGL的经典网址: http://nehe.gamedev.net/

    OPenGL编程书籍

    理解OpenGL如何工作非常重要,你可以在教程的末尾下载源程序,但我强烈建议你至少读一遍教程,然后再开始编程. 2.你的第一个多边形: 在第一个教程的基础上,我们添加了一个三角形和一个四边形。也许你认为这很简单...

    从窗口到视口的映射(图形方式直观描述容易理解)【原创】

    以前在学习窗口和视口映射关系时,难以理解其中的概念,在网上查找资料也只找到一些跟书本上一样的文字解释。后来自己建立了一对坐标系模型,终于理解了窗口和视口的关系。本文是自己的心得体会,用图形的方式直观...

    控件坐标转换(窗口视口转换)

    控件坐标转换(窗口视口转换)

    OpenGL坐标系统

    OpenGL通过相机模拟、可以实现计算机图形学中最基本的三维变换,即几何变换、投影变换、裁剪变换、视口变换等,同时,OpenGL还实现了矩阵堆栈等。理解掌握了有关坐标变换的内容,就算真正走进了精彩地三维世界。

Global site tag (gtag.js) - Google Analytics