NeHe 系列教程之七: 光照及纹理过滤

英文教程地址:lesson07

本课将以第一课的代码为基础, 实现光照效果。

首先是对象定义与纹理加载的代码:

namespace {
bool    light;                       // Lighting ON / OFF
bool    lp;                         // L Pressed?
bool    fp;                         // F Pressed?
GLfloat xrot;                       // X Rotation
GLfloat yrot;                       // Y Rotation
GLfloat xspeed;                     // X Rotation Speed
GLfloat yspeed;                     // Y Rotation Speed
GLfloat z=-5.0f;                    // Depth Into The ScreenGLfloat LightAmbient[]= { 0.5f, 0.5f, 0.5f, 1.0f };             // Ambient Light Values ( NEW )
GLfloat LightDiffuse[]= { 1.0f, 1.0f, 1.0f, 1.0f };              // Diffuse Light Values ( NEW )
GLfloat LightPosition[]= { 0.0f, 0.0f, 2.0f, 1.0f };            // Light Position ( NEW )
GLuint  filter;                                 // Which Filter To Use
GLuint  texture[3];                             // Storage for 3 texturesQVector<QVector3D> vertices;
QVector<QVector2D> texCoords;
QVector<QVector3D> normals;void makeObject()
{vertices<<QVector3D(-1.0f, -1.0f,  1.0f)<<QVector3D(1.0f, -1.0f,  1.0f)<<QVector3D(1.0f,  1.0f,  1.0f)<<QVector3D(-1.0f,  1.0f,  1.0f)<<QVector3D(-1.0f, -1.0f, -1.0f)<<QVector3D(-1.0f,  1.0f, -1.0f)<<QVector3D(1.0f,  1.0f, -1.0f)<<QVector3D(1.0f, -1.0f, -1.0f)<<QVector3D(-1.0f,  1.0f, -1.0f)<<QVector3D(-1.0f,  1.0f,  1.0f)<<QVector3D(1.0f,  1.0f,  1.0f)<<QVector3D(1.0f,  1.0f, -1.0f)<<QVector3D(-1.0f, -1.0f, -1.0f)<<QVector3D(1.0f, -1.0f, -1.0f)<<QVector3D(1.0f, -1.0f,  1.0f)<<QVector3D(-1.0f, -1.0f,  1.0f)<<QVector3D(1.0f, -1.0f, -1.0f)<<QVector3D(1.0f,  1.0f, -1.0f)<<QVector3D(1.0f,  1.0f,  1.0f)<<QVector3D(1.0f, -1.0f,  1.0f)<<QVector3D(-1.0f, -1.0f, -1.0f)<<QVector3D(-1.0f, -1.0f,  1.0f)<<QVector3D(-1.0f,  1.0f,  1.0f)<<QVector3D(-1.0f,  1.0f, -1.0f);texCoords<<QVector2D(0.0f, 0.0f)<<QVector2D(1.0f, 0.0f)<<QVector2D(1.0f, 1.0f)<<QVector2D(0.0f, 1.0f)<<QVector2D(1.0f, 0.0f)<<QVector2D(1.0f, 1.0f)<<QVector2D(0.0f, 1.0f)<<QVector2D(0.0f, 0.0f)<<QVector2D(0.0f, 1.0f)<<QVector2D(0.0f, 0.0f)<<QVector2D(1.0f, 0.0f)<<QVector2D(1.0f, 1.0f)<<QVector2D(1.0f, 1.0f)<<QVector2D(0.0f, 1.0f)<<QVector2D(0.0f, 0.0f)<<QVector2D(1.0f, 0.0f)<<QVector2D(1.0f, 0.0f)<<QVector2D(1.0f, 1.0f)<<QVector2D(0.0f, 1.0f)<<QVector2D(0.0f, 0.0f)<<QVector2D(0.0f, 0.0f)<<QVector2D(1.0f, 0.0f)<<QVector2D(1.0f, 1.0f)<<QVector2D(0.0f, 1.0f);normals<<QVector3D(0.0f, 0.0f, 1.0f)<<QVector3D(0.0f, 0.0f, 1.0f)<<QVector3D(0.0f, 0.0f, 1.0f)<<QVector3D(0.0f, 0.0f, 1.0f)<<QVector3D(0.0f, 0.0f,-1.0f)<<QVector3D(0.0f, 0.0f,-1.0f)<<QVector3D(0.0f, 0.0f,-1.0f)<<QVector3D(0.0f, 0.0f,-1.0f)<<QVector3D(0.0f, 1.0f, 0.0f)<<QVector3D(0.0f, 1.0f, 0.0f)<<QVector3D(0.0f, 1.0f, 0.0f)<<QVector3D(0.0f, 1.0f, 0.0f)<<QVector3D(0.0f, -1.0f, 0.0f)<<QVector3D(0.0f, -1.0f, 0.0f)<<QVector3D(0.0f, -1.0f, 0.0f)<<QVector3D(0.0f, -1.0f, 0.0f)<<QVector3D(1.0f, 0.0f, 0.0f)<<QVector3D(1.0f, 0.0f, 0.0f)<<QVector3D(1.0f, 0.0f, 0.0f)<<QVector3D(1.0f, 0.0f, 0.0f)<<QVector3D(-1.0f, 0.0f, 0.0f)<<QVector3D(-1.0f, 0.0f, 0.0f)<<QVector3D(-1.0f, 0.0f, 0.0f)<<QVector3D(-1.0f, 0.0f, 0.0f);glVertexPointer(3, GL_FLOAT, 0, vertices.constData());glTexCoordPointer(2, GL_FLOAT, 0, texCoords.constData());glNormalPointer(GL_FLOAT, 0, normals.constData());}void drawObject()
{glEnableClientState(GL_VERTEX_ARRAY);glEnableClientState(GL_TEXTURE_COORD_ARRAY);glEnableClientState(GL_NORMAL_ARRAY);glBindTexture(GL_TEXTURE_2D, texture[filter]);glDrawArrays(GL_QUADS, 0, vertices.size());glDisableClientState(GL_VERTEX_ARRAY);glDisableClientState(GL_TEXTURE_COORD_ARRAY);glDisableClientState(GL_NORMAL_ARRAY);
}
}

加载纹理的代码如下, 采用了三种不同的纹理过滤方式:

  void MyGLWidget::loadTextures()
{QImage image;if (image.load(":/Crate.bmp")) {image =  convertToGLFormat(image);glGenTextures(3, texture);// Create Nearest Filtered TextureglBindTexture(GL_TEXTURE_2D, texture[0]);glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width(), image.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, image.bits());// Create Linear Filtered TextureglBindTexture(GL_TEXTURE_2D, texture[1]);glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width(), image.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, image.bits());// Create MipMapped TextureglBindTexture(GL_TEXTURE_2D, texture[2]);glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, image.width(), image.height(), GL_RGBA, GL_UNSIGNED_BYTE, image.bits());}
}

接着是OpenGL 初始函数,启用了光照效果

void MyGLWidget::initializeGL()
{makeObject();loadTextures();glEnable(GL_TEXTURE_2D);    // Enable Texture MappingglShadeModel(GL_SMOOTH);   // Enables Smooth ShadingglClearColor(0.0f, 0.0f, 0.0f, 0.5f);  // Black BackgroundglClearDepth(1.0f);             // Depth Buffer SetupglEnable(GL_DEPTH_TEST);        // Enables Depth TestingglDepthFunc(GL_LEQUAL);        // The Type Of Depth Test To DoglHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Really Nice Perspective CalculationsglLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient);             // Setup The Ambient LightglLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse);glLightfv(GL_LIGHT1, GL_POSITION,LightPosition);            // Position The LightglEnable(GL_LIGHT1);                            // Enable Light One
}

绘制函数如下:

void MyGLWidget::paintGL()
{glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);  // Clear The Screen And The Depth BufferglLoadIdentity();       // Reset The Current Modelview MatrixglTranslatef(0.0f,0.0f,z);                      // Translate Into/Out Of The Screen By zglRotatef(xrot,1.0f,0.0f,0.0f);                     // Rotate On The X Axis By xrotglRotatef(yrot,0.0f,1.0f,0.0f);                     // Rotate On The Y Axis By yrotdrawObject();xrot += xspeed;                        // Add xspeed To xrotyrot += yspeed;                       // Add yspeed To yrot
}

最后按键处理,主要是开启和关闭光照,以及切换不同的纹理过滤方式:

void MyGLWidget::keyReleaseEvent(QKeyEvent *e)
{switch (e->key()) {case Qt::Key_L:lp = false;break;case Qt::Key_I:fp = false;break;default:QGLWidget::keyReleaseEvent(e);}
}
void MyGLWidget::keyPressEvent(QKeyEvent *e)
{switch (e->key()) {case Qt::Key_I:fp = true;filter += 1;if (filter > 2)filter = 0;break;case Qt::Key_F:fullscreen = !fullscreen;if (fullscreen) {showFullScreen();} else {resize(640, 480);showNormal();}break;case Qt::Key_L:if (!lp) {lp=true;                // lp Becomes TRUElight=!light;               // Toggle Light TRUE/FALSEif (!light)             // If Not Light{glDisable(GL_LIGHTING);     // Disable Lighting}else                    // Otherwise{glEnable(GL_LIGHTING);      // Enable Lighting}}break;case Qt::Key_PageUp:z -= 0.02f;break;case Qt::Key_PageDown:z += 0.02f;break;case Qt::Key_Up:xspeed -= 0.01f;break;case Qt::Key_Down:xspeed += 0.01f;break;case Qt::Key_Right:yspeed += 0.01f;break;case Qt::Key_Left:yspeed -= 0.01f;break;case Qt::Key_Escape:QMessageBox::StandardButton reply;reply = QMessageBox::question(NULL, "NeHe","Do you want to exit?",QMessageBox::Yes | QMessageBox::No,QMessageBox::Yes);if (reply == QMessageBox::Yes) {qApp->quit();}break;default:QGLWidget::keyPressEvent(e);break;}
}

运行效果图如下所示:

转载于:https://my.oschina.net/fuyajun1983cn/blog/263951

NeHe教程Qt实现——lesson07相关推荐

  1. NeHe教程Qt实现——lesson01

    NeHe 系列教程之一: 创建一个OpenGL 窗口 英文教程地址: lesson01 在Qt的实现中, 我们主要依赖QGLWidget类, 我们主要重载三个重要方法 :     void initi ...

  2. NeHe教程Qt实现——lesson10

    NeHe 系列教程之十:在3D空间中漫游 英文教程地址:lesson10 本课演示了从外部文件中加载数据构建3D模型的实例,代码基于第一课. 首先是3D模型的数据结构定义: namespace {bo ...

  3. NeHe教程Qt实现——lesson08

    NeHe 系列教程之八: 混合 英文教程地址:lesson08 本课将在第七课的基础上添加颜色混合的代码: namespace { ... bool blend; // Blending OFF/ON ...

  4. NeHe教程Qt实现——lesson09

    NeHe 系列教程之九: 在3D空间中移动位图 英文教程地址:lesson09 本课基于第一课的代码, 利用颜色混合的方法,将一个黑白纹理与随机颜色进行混合,产生绚丽的效果. 首先是定义相关变量和数据 ...

  5. NeHe教程Qt实现——lesson16

    NeHe 系列教程之十四:雾 英文教程地址:lesson16 本课展示产生雾. 相关变量和函数定义: namespace { bool gp; GLuint fogMode[] = { GL_EXP, ...

  6. NeHe教程Qt实现——lesson06

    NeHe 系列教程之六: 纹理映射 英文教程地址:lesson06 本课以第一课的代码为基础,演示了加载纹理的过程. 首先给出的是绘制几何对象和加载纹理坐标的代码 namespace {GLfloat ...

  7. NeHe教程Qt实现——lesson15

    NeHe 系列教程之十四:纹理 轮廓字体 英文教程地址:lesson15 本课展示如何创建和显示纹理轮廓字体, 代码基于第一课. 首先是字体库的创建: namespace {#define USE_D ...

  8. NeHe教程Qt实现——lesson13

    NeHe 系列教程之十三: 位图字体 英文教程地址:lesson13 本课将展示位图字体的创建和显示, 代码基于第一课. 首先是字休库的创建,如下所示: namespace {#define USE_ ...

  9. NeHe教程Qt实现——lesson14

    NeHe 系列教程之十四: 轮廓字体 英文教程地址:lesson14 本课展示如何创建和显示轮廓字体,即带有尝试的字体,可沿Z轴旋转和移动, 代码基于第一课. 同前一课类似,首先也是要创建字体库以及对 ...

最新文章

  1. base64的c语言实现方法
  2. AAAI2020录用论文汇总(一)
  3. java 10000阶乘_Java ForkJoinPool: 3秒计算100万的阶乘
  4. SAP UI5 应用开发教程之二十三 - 列表控件的排序 Sort 和分组 Group
  5. LINQ 学习路程 -- 查询语法 LINQ Query Syntax
  6. Unity Editor自制工具(1)--“Editor目录栏按钮+全局搜索方法+自制Editor窗口”实现搜索与删除场景中任意名称游戏物体
  7. RoaringBitmap 原理
  8. 手机卫星定位系统_真的可以通过手机号码,准确定位对方信息吗?
  9. 【演讲实录+PPT下载】一网打尽AI年度热点,2017中国人工智能大会资料曝光(持续更新)...
  10. Unity3D方向键控制人物移动的代码
  11. 华硕T100 安装linux,【华硕T100TA3740评测】双硬盘组合 华硕T100TA挑战存储极限(全文)_华硕 T100TA3740_笔记本评测-中关村在线...
  12. CVPR2020/2021行人检测重识别等论文,共33篇
  13. The root link base_link has an inertia specified in the URDF, but KDL does not support a root ...
  14. 基于python开发植物大战僵尸
  15. 物联网云平台应用于远程污水在线检测
  16. Bailian2725 跳格问题【模拟】
  17. java-Stringbuffer
  18. Python文本特征提取 DictVectorizer CountVectorizer TfidfVectorizer 附代码详解
  19. Java集合(十一)TreeSet解读
  20. kafka python 性能_使用 Python 监控 Kafka Consumer LAG

热门文章

  1. 自定义Title(可以实现类似于携程网上价格的显示方式)
  2. 需要注意的小问题------闹的笑话
  3. 2018年台湾为陕西最大贸易伙伴
  4. Centos7下的Ambari安装
  5. vim入门教程(实践第一)
  6. HeadFirst设计模式(四) - 工厂模式之1 - 简单工厂
  7. python selenium --处理下拉框
  8. 如何做EL表达式能调用的函数-小例子(转)
  9. strlen与sizeof区别
  10. scala_until