opengl编程视口:Win32 OpenGL编程(10) 视口变换

  提要

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

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

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

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

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

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

  视口变换

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

  OpenGL Programming Guide:

    glViewport —  the viewport
    C Specication
    void glViewport(    GL      x,
         GL      y,
         GLsizei      width,
         GLsizei      height);
    Parameters
    x, y
                            Specy the lower left corner of the viewport rectangle,
                            in pixels. The initial value is (0,0).
    width, height
                            Specy the width and height
                            of the viewport.
                            When a GL context is first attached to a window,
                            width and height are  to the dimensions of that
                            window.


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

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

  正常情况:



  图片看不清楚?请点击这里查看原图(大图)

  窗口缩小时:图像偏移了



  图片看不清楚?请点击这里查看原图(大图)

  窗口放大时:图像不居中



  图片看不清楚?请点击这里查看原图(大图)

  看 7巧板中例子:

  有以下代码:

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  message handler of the system
    PAINTSTRUCT        ps;        // used in WM_PAINT
    HDC                hdc;    // handle to a device context
    // what is the message 
    switch(msg)
    {    
     WM_CREATE: 
        {
            // do initialization stuff here
            //  success
            (0);
        } ;
     WM_PAINT: 
        {
            // simply validate the window 
            hdc = BeginPa(hwnd,&ps);     
            // end paing
            EndPa(hwnd,&ps);
            //  success
            (0);
        } ;
     WM_DESTROY: 
        {
            // kill the application, this sends a WM_QUIT message 
            PostQuitMessage(0);
            //  success
            (0);
        } ;
     WM_SIZE:
        {
            ReShape(LOWORD(lparam), HIWORD(lparam));
        }
    default:;
    } // end switch
    // process any messages that we didn't take care of 
     (DefWindowProc(hwnd, msg, wparam, lparam));
} // end WinProc


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

  正常情况下:



  窗口缩小:图形还是居中纵横比改变导致图形纵横比也改变了



  窗口放大时:图形还是居中纵横比改变导致图形纵横比也改变了



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

  屏幕分割

  玩过真 3国无双系列玩家们不知道在同台机器上和战友们浴血奋斗过没有我是有过显示时个玩家在上面个在下面在同台机器上不需要通过网络就能享受联机乐趣确很有意思事实上我们通过视口变换连续绘制图形两次就能达到这样效果(我不知道真 3国是否也是通过这样技术实现)比如上述 7巧板例子吧我们想在屏幕上绘制4次让 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;
}  




  显示效果:



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

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

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



Tags:  opengl编程视口

延伸阅读

最新评论

发表评论