新书推介:《语义网技术体系》
作者:瞿裕忠,胡伟,程龚
   XML论坛     W3CHINA.ORG讨论区     >>计算机科学论坛<<     SOAChina论坛     Blog     开放翻译计划     新浪微博  
 
  • 首页
  • 登录
  • 注册
  • 软件下载
  • 资料下载
  • 核心成员
  • 帮助
  •   Add to Google

    >> 本版讨论高级C/C++编程、代码重构(Refactoring)、极限编程(XP)、泛型编程等话题
    [返回] 计算机科学论坛计算机技术与应用『 C/C++编程思想 』 → OPENGL详解 查看新帖用户列表

      发表一个新主题  发表一个新投票  回复主题  (订阅本版) 您是本帖的第 38284 个阅读者浏览上一篇主题  刷新本主题   平板显示贴子 浏览下一篇主题
     * 贴子主题: OPENGL详解 举报  打印  推荐  IE收藏夹 
       本主题类别:     
     卷积内核 帅哥哟,离线,有人找我吗?
      
      
      威望:8
      头衔:总统
      等级:博士二年级(版主)
      文章:3942
      积分:27590
      门派:XML.ORG.CN
      注册:2004/7/21

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给卷积内核发送一个短消息 把卷积内核加入好友 查看卷积内核的个人资料 搜索卷积内核在『 C/C++编程思想 』的所有贴子 访问卷积内核的主页 引用回复这个贴子 回复这个贴子 查看卷积内核的博客楼主
    发贴心情 

    二 投影变换


    1.正射投影(即没有“近大远小”)
    void glOrtho(GLdouble left,GLdouble right,GLdouble bottom,GLdouble top,
    GLdouble near,GLdouble far)
    创建一个平行视景体(的矩阵),即投射线是平行线,把第一个矩形
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    视景投影到第二个矩形视景上。并用这个矩阵乘以当前矩阵,以完成变换。
    近景第一个矩形的左上角三维空间坐标(left,bottom,-near),右下角的三维空间坐标(right,top,-near);
    远景第二个矩形左上角三维空间坐标(left,bottom,-far),右下角的三维空间坐标(right,top,-far);


    2.透射投影(“近大远小”)
    void glFrustum(
    GLdouble left,
    GLdouble right,
    GLdouble bottom,
    GLdouble top,
    GLdouble znear,
    GLdouble zfar
    );
    创建一个型如棱台的视景体,其近截取面由left right bottom top znear
    确定,远截取面由从视点投影近截取面到Z轴zfar位置决定


    三 视口变换
    void glViewport(GLint x,GLint y,GLsize width,GLsize height);
    这个函数定义一个视口,x和y是视口在屏幕窗口坐标系中左上坐标
    缺省是(0,0)。width height是宽和高。
    注意使用中视口长宽比例的调整会导致图象变形。因此reshape()中
    要检测窗口尺寸,修正视口大小,保证图象不变形。


    附:
    void glMatrixMode(GLenum mode );
    把当前矩阵转换为指定的矩阵类型


    这三个函数的利用见例子中的中文说明:
    ////////////////////////////////////////////////////////////
    //sample.cpp
    #include "glos.h"
    #include <GL/gl.h>
    #include <GL/glaux.h>
    #include "windows.h"
    void myinit(void);
    void CALLBACK display(void);
    void CALLBACK reshape(GLsizei w,GLsizei h);
    /////////////////////////////////////////////////////////////
    void myinit(void)
    {
    /*初始化:*/
    auxInitDisplayMode(AUX_SINGLE|AUX_RGBA);
    //窗口显示单缓存和RGB(彩色)模式
    auxInitPosition(0,0,500,500);
    //大小x=500 y=500 (0,0)是屏幕左上点
    auxInitWindow("sample1");
    //窗口初始化,参数是标题
    glClearColor(0.0,0.0,0.0,0.0);
    //将窗口清为黑色
    glClear(GL_COLOR_BUFFER_BIT);
    //将颜色缓存清为glClearColor命令所设置的颜色
    //即背景色
    }
    //////////////////////////////////////////////////
    void CALLBACK reshape(GLsizei w,GLsizei h)
    {
    //设定视口X Y方向不要大于500单位
    if(w<=500&&h<=500)
    glViewport(0,0,w,h);
    if(w>500&&h<=500)
    glViewport(0,0,500,h);
    if(w<=500&&h>500)
    glViewport(0,0,w,500);
    if(w>500&&h>500)
    glViewport(0,0,500,500);


    //进入世界坐标系,准备变换
    //必要的步骤,初始化变换矩阵步骤: 1确定类型 2清成单位阵
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();


    //定义一个合适的视景体
    if(w<=h)
    glOrtho(-20.0,20.0,-20.0*(GLfloat)h/(GLfloat)w,
    20.0*(GLfloat)h/(GLfloat)w,-50.0,50.0);
    else
    glOrtho(-20.0*(GLfloat)h/(GLfloat)w,
    20.0*(GLfloat)h/(GLfloat)w,-20.0,20.0,-50.0,50.0);


    //把变换结果返回视点坐标系
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    }
    //////////////////////////////////////
    //画三棱锥,功能同上一讲
    void draw(void)
    {
    glBegin(GL_TRIANGLE_STRIP);
    glColor3f(1.0,0.0,0.0);
    glVertex3f(15.0,0.0,0.0);
    glColor3f(0.0,1.0,0.0);
    glVertex3f(-15.0,0.0,0.0);
    glColor3f(0.0,0.0,1.0);
    glVertex3f(0.0,15.0,15.0);
    //
    glColor3f(0.0,1.0,1.0);
    glVertex3f(10.0,15.0,-15.0);
    //
    glColor3f(1.0,1.0,0.0);
    glVertex3f(15.0,0.0,0.0);
    //
    glEnd();
    }
    ////////////////////////////////////////
    void CALLBACK display(void)
    {
    //按上个例子中方法画第一个三棱锥
    glClearColor(0.0,0.0,0.0,1.0);
    glClear(GL_COLOR_BUFFER_BIT);
    glLoadIdentity();
    glTranslatef(0.0,0.0,-25.0);
    draw();


    //开始画第二个三棱锥
    //变换开始,清变换矩阵为单位阵
    glLoadIdentity();
    //先沿X Y Z平移-5 -10 -4,屏幕上看就是向左下移动
    //Z方向由于是平行投影,没有“近大远小”所以看不出效果
    glTranslatef(-5.0,-10.0,-4.0);
    //再沿Z轴转90度
    glRotatef(90,0.0,0.0,1.0);
    draw();


    //绘图工作完成,强制绘图结束
    glFlush();
    }


    void main(void)
    {
    myinit();
    auxReshapeFunc(reshape);
    auxMainLoop(display);
    }


    //sample ends here
    /////////////////////
    如果大家运行一下就知道上述函数的作用,无非是把物体移动、转动、变形缩放、透视...
    我想有了前3讲,OPENGL的基本原理已经如此了它就是提供了一个标准的计算机图形学所使用的数学模型到显示的接口,只要具备图形学知识,掌握OPENGL API函数使用,绘图很EASY啦基础部分已经完毕,慢慢再来谈高级一些的绘图功能如:纹理、光源、动画...
    真诚希望大家提提意见和高论  

    前面三篇文章已经把OPENGL的编程基本结构描述完毕。以后会在这个基础上逐渐深化,不断增添新内容。这一篇是讲述键盘操作和动画基础(实际还差的远哪)。只是个简单的能由用户控制的动画,让物体前后移动,左右旋转。是我们自己的第一个QUAKE!当然这个版本谁买谁上当,呵呵。
    这篇的另一个目的就是加深前面对于CALLBACK函数的认识以及对于变换的直观解释,任何变换你都可以从屏幕上通过自己的操作看出来:
    我只把和以前变化的部分标记中文解释


    ////////////////////////////////////////////////////
    //sample.cpp
    #include "glos.h"
    #include <GL/gl.h>
    #include <GL/glaux.h>
    #include "windows.h"


    void myinit(void);
    void CALLBACK display(void);
    void CALLBACK reshape(GLsizei w,GLsizei h);


    //注意到乐吗?这里新加乐4个CALLBACK函数
    //类似display() reshape(),也由主函数调用它们
    //实现对键盘输入的响应
    void CALLBACK left(void);//按 LEFT
    void CALLBACK right(void);//按 RIGHT
    void CALLBACK up(void);//按 UP
    void CALLBACK down(void);//按 DOWN


    //两个全局变量,z_motion用来控制物体远近
    //rotate用来控制物体旋转
    static int z_motion=0,rotate=0;


    void myinit(void)
    {
    auxInitDisplayMode(AUX_SINGLE|AUX_RGBA);
    auxInitPosition(0,0,500,500);
    auxInitWindow("sample1");
    glClearColor(0.0,0.0,0.0,0.0);
    glClear(GL_COLOR_BUFFER_BIT);
    }


    void CALLBACK reshape(GLsizei w,GLsizei h)
    {
    if(w<=500&&h<=500)
    glViewport(0,0,w,h);
    if(w>500&&h<=500)
    glViewport(0,0,500,h);
    if(w<=500&&h>500)
    glViewport(0,0,w,500);
    if(w>500&&h>500)
    glViewport(0,0,500,500);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    ///*if(w<=h)
    // glOrtho(-20.0,20.0,-20.0*(GLfloat)h/(GLfloat)w,
    // 20.0*(GLfloat)h/(GLfloat)w,-50.0,50.0);
    //else
    // glOrtho(-20.0*(GLfloat)h/(GLfloat)w,
    // 20.0*(GLfloat)h/(GLfloat)w,-20.0,20.0,-50.0,50.0);
    //*/
    /************************************************************/
    //这里我们换一种投影方法:透射投影,有立体感的说
    //取代上次的平行投影。前4个参数是控制第一个截取面的
    //left right top bottom,然后两个参数控制近截取面的
    //Z坐标,远截取面的Z作标,函数声名如下:
    //void glFrustum(GLdouble left,GLdouble right,
    // GLdouble bottom,GLdouble top,
    // GLdouble near,GLdouble far);
    /************************************************************/
    glFrustum(-20.0,20.0,-20.0,20.0,10.0,50.0);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    }


    void draw(void)
    {
    glBegin(GL_TRIANGLE_STRIP);
    glColor3f(1.0,0.0,0.0);
    glVertex3f(15.0,0.0,0.0);
    glColor3f(0.0,1.0,0.0);
    glVertex3f(-15.0,0.0,0.0);
    glColor3f(0.0,0.0,1.0);
    glVertex3f(0.0,15.0,15.0);
    //
    glColor3f(0.0,1.0,1.0);
    glVertex3f(10.0,15.0,-15.0);
    //
    glColor3f(1.0,1.0,0.0);
    glVertex3f(15.0,0.0,0.0);
    //
    glEnd();
    }


    void CALLBACK display(void)
    {
    glClearColor(0.0,0.0,0.0,1.0);
    glClear(GL_COLOR_BUFFER_BIT);


    //glPushMatrix();
    glLoadIdentity();


    //根据z_motion rotate两个参数确定变换的具体数值:
    //z_motion改变时,物体从原Z坐标-25,平移z_motion个单位
    glTranslatef(0.0,0.0,-25.0+z_motion);
    //rotate改变时,物体延Y轴(上下方向)旋转5*rotate度
    glRotatef(rotate*5.0,0.0,1.0,0.0);


    draw();
    //glPopMatrix();


    glFlush();
    }
    void CALLBACK left(void)
    {
    //每当按下LEFT,rotate数值 +1
    //以下函数都类似
    rotate++;
    }
    void CALLBACK right(void)
    {
    rotate--;
    }
    void CALLBACK up(void)
    {
    z_motion++;
    }
    void CALLBACK down(void)
    {
    z_motion--;
    }
    void main(void)
    {
    myinit();


    //用辅助库的函数调用把left() right() up() down()
    //设为标准键盘输入处理函数
    auxKeyFunc(AUX_LEFT,left);
    auxKeyFunc(AUX_RIGHT,right);
    auxKeyFunc(AUX_UP,up);
    auxKeyFunc(AUX_DOWN,down);


    auxReshapeFunc(reshape);
    auxMainLoop(display);
    }
    //end of sample
    ////////////////////////////////////////////////////
    如果运行这个程序会发现有较明显的闪烁感,这是单缓存模式造成的以后会讲到动画应采用双缓存模式,这样可以避免闪烁

    这回可能是OPENGL最简单的内容:颜色。
    一 RGB模式
    一般来讲实现彩色是用RGB三基色来调配的。这就是
    RGB模式,我们前面一直用这种方法
    (例如:
    glColor3f(1.0,0.0,0.0);
    glVertex3f(0.0,0.0,0/0);
    绘制一个红色点。)
    void glColor3{b s i f d ub us ui}(TYPE r,TYPE g, TYPE b);
    void glColor4{b s i f d ub us ui}(TYPE r,TYPE g, TYPE b,TYPE a);
    void glColor3{b s i f d ub us ui}v(TYPE *v);
    void glColor4{b s i f d ub us ui}v(TYPE *v);
    {}内是任选一种数值精度(看前面的介绍);
    参数a是表征透明度的Alpha值。
    后两个带v后缀的函数表明他们的参数是向量(详细使用看本篇的例子)。
    以glColor3f为例,其参数取值范围-1.0--1.0,其它数值类型的函数将
    自动把参数均匀影射到这个区间,例如:

    后缀 类型 MIN MIN映射 MAX MAX映射
    b 1byte整数 -128 -1.0 127 1.0

    二 颜色索引模式
    使用
    void glIndex{s i f d}(TYPE c);
    void glIndex{s i f d}(TYPE *c);
    来从颜色索引表中选取颜色。设置当前颜色索引值(调色板号),大于
    总数时取模。

    前面所有例子都是RGB模式,所以这里给出一个颜色索引的例子:

    //sample.cpp
    //////////////////////////////
    #include "glos.h"
    #include <GL/gl.h>
    #include <GL/glaux.h>
    #include "windows.h"
    void myinit(void);
    void InitPalette(void);
    void CALLBACK display(void);
    void CALLBACK reshape(GLsizei w,GLsizei h);


    void myinit(void)
    {
    auxInitDisplayMode(AUX_SINGLE|AUX_INDEX);
    auxInitPosition(0,0,500,500);
    auxInitWindow("sample1");
    glClearColor(0.0,0.0,0.0,0.0);
    glClear(GL_COLOR_BUFFER_BIT);
    glShadeModel(GL_FLAT);//GL_FLAT填色模式
    }


    void CALLBACK reshape(GLsizei w,GLsizei h)
    {
    if(w<=500&&h<=500)
    glViewport(0,0,w,h);
    if(w>500&&h<=500)
    glViewport(0,0,500,h);
    if(w<=500&&h>500)
    glViewport(0,0,w,500);
    if(w>500&&h>500)
    glViewport(0,0,500,500);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    if(w<=h)
    glOrtho(-20.0,20.0,-20.0*(GLfloat)h/(GLfloat)w,
    20.0*(GLfloat)h/(GLfloat)w,-50.0,50.0);
    else
    glOrtho(-20.0*(GLfloat)h/(GLfloat)w,
    20.0*(GLfloat)h/(GLfloat)w,-20.0,20.0,-50.0,50.0);


    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    }


    void draw(void)
    {
    GLint n;


    //首先给定三角扇的坐标信息
    GLfloat pp[8][2]={{7.0,-7.0},{0.0,-10.0},{-7.0,-7.0},{-10.0,0.0},
    {-7.0,7.0},{0.0,10.0},{7.0,7.0},{10.0,0.0}};


    //先画前两个点,然后用循环读取前面的向量(数组)信息绘制
    //完整图形
    glBegin(GL_TRIANGLE_FAN);
    glVertex2f(0.0,0.0);
    glVertex2f(10.0,0.0);
    for(n=0;n<8;n++)
    {


    //每次从颜色查找表中找出新颜色,然后以这个颜色绘制三角扇
    //注意glVertex2fv()中v后缀的使用,以前没有碰到过,v后缀代表
    //参数是个向量(数组)
    glIndexi(n+1);
    glVertex2fv(pp[n]);
    }
    glEnd();
    }


    void InitPalette(void)
    {
    //这是本例子的关键,初始化颜色查找表,这里一共定义
    //乐8种颜色,是从蓝到青的渐进。
    GLint i;
    static GLfloat rgb[][3]={{0.0,0.0,0.2},{0.0,0.0,0.4},{0.0,0.0,0.6},
    {0.0,0.0,1.0},{0.0,0.2,1.0},{0.0,0.4,1.0},{0.0,0.8,1.0},{0.0,1.0,1.0}};


    //调用简单的辅助库函数设置系统调色板,把刚才8个颜色定为全部
    //颜色索引的内容
    for(i=0;i<8;i++)
    auxSetOneColor(i+1,rgb[0],rgb[1],rgb[2]);
    }


    void CALLBACK display(void)
    {
    //首先调用自定义的InitPalette()初始化调色板
    InitPalette();
    glClearColor(0.0,0.0,0.0,1.0);
    glClear(GL_COLOR_BUFFER_BIT);


    glLoadIdentity();
    draw();
    glFlush();
    }


    void main(void)
    {
    myinit();
    auxReshapeFunc(reshape);
    auxMainLoop(display);
    }
    //end of sample
    下次将介绍OPENGL的光照和材质效果,一个步入3D的阶梯,
    大家快来呀 ......

    ----------------------------------------------
    事业是国家的,荣誉是单位的,成绩是领导的,工资是老婆的,财产是孩子的,错误是自己的。

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2006/2/7 10:32:00
     
     GoogleAdSense
      
      
      等级:大一新生
      文章:1
      积分:50
      门派:无门无派
      院校:未填写
      注册:2007-01-01
    给Google AdSense发送一个短消息 把Google AdSense加入好友 查看Google AdSense的个人资料 搜索Google AdSense在『 C/C++编程思想 』的所有贴子 访问Google AdSense的主页 引用回复这个贴子 回复这个贴子 查看Google AdSense的博客广告
    2024/5/22 9:16:00

    本主题贴数11,分页: [1] [2]

     *树形目录 (最近20个回帖) 顶端 
    主题:  OPENGL详解(7067字) - 卷积内核,2006年2月7日
        回复:  支持正版,向LZ 学习(19字) - wain,2007年5月9日
        回复:  写的全部是基础 不错!(21字) - qduxiao,2007年5月8日
        回复:  楼主,你好. 请问"另外在你的运行程序路径下或\win95\system\下你需要一些*.d..(168字) - lnn1316,2007年4月1日
        回复:  楼主,你好.我是刚接触opengl,你说的 "另外在你的运行程序路径下或\win95\sys..(182字) - hehe365,2006年4月18日
            回复:  楼主,你好. 请问"另外在你的运行程序路径下或\win95\system\下你需要一些*.dll..(167字) - hailing10505,2006年6月10日
        回复:  OPENGL的纹理 在3D图形中,纹理映射是广泛使用的。纹理映射也是相当复杂的过程: 一 定义..(9890字) - 卷积内核,2006年2月7日
        回复:  OPENGL的位图和图象 与一般的位图定义不同,OPENGL中的位图是指用每个象素只有一位信..(5978字) - 卷积内核,2006年2月7日
        回复:  这次把材质完全搞定,呵呵 上次12个不同的立体材质球的程序运用glMaterialfv()来改变..(3305字) - 卷积内核,2006年2月7日
        回复:  这部分是最重要的部分,前面只是基础。这里会介绍光照处理、明暗处理、光源 设置、材质定义以及相关计..(15512字) - 卷积内核,2006年2月7日
        回复:  二 投影变换 1.正射投影(即没有“近大远小”) void glOrtho(GLdoubl..(11515字) - 卷积内核,2006年2月7日

    W3C Contributing Supporter! W 3 C h i n a ( since 2003 ) 旗 下 站 点
    苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
    78.125ms