1.简介

现实世界中的物体通常并不只包含有一种材质,而是由多种材质所组成。想想一辆汽车:它的外壳非常有光泽,车窗会部分反射周围的环境,轮胎不会那么有光泽,所以它没有镜面高光,轮毂非常闪亮。

2.漫反射贴图

用一张覆盖物体的图像,让我们能够逐片段索引其独立的颜色值,它是一个表现了物体所有的漫反射颜色的纹理图像。

这次我们会将纹理储存为Material结构体中的一个sampler2D。我们将之前定义的vec3漫反射颜色向量替换为漫反射贴图。移除了环境光材质颜色向量,因为环境光颜色在几乎所有情况下都等于漫反射颜色,所以我们不需要将它们分开储存:

struct Material {sampler2D diffuse;vec3      specular;float     shininess;
};
...
in vec2 TexCoords;

接下来我们只需要从纹理中采样片段的漫反射颜色值即可:

    vec3 diffuseTexColor = vec3(texture(material.diffuse,TexCoords));//diffusevec3 norm = normalize(outNormal);vec3 lightDir = normalize(lightPos - FragPos);float diff = max(dot(norm, lightDir), 0.0);vec3 diffuse = light.diffuse * diff * diffuseTexColor;

不要忘记将环境光的材质颜色设置为漫反射材质颜色同样的值。

    //ambinetvec3 ambient = light.ambient * diffuseTexColor;

3.镜面光贴图

你可能会注意到,镜面高光看起来有些奇怪,因为我们的物体大部分都是木头,我们知道木头不应该有这么强的镜面高光的。我们可以将物体的镜面光材质设置为vec3(0.0)来解决这个问题,但这也意味着箱子钢制的边框将不再能够显示镜面高光了,我们知道钢铁应该是有一些镜面高光的。

我们同样可以使用一个专门用于镜面高光的纹理贴图。这也就意味着我们需要生成一个黑白的纹理,来定义物体每部分的镜面光强度。

由于箱子大部分都由木头所组成,而且木头材质应该没有镜面高光,所以漫反射纹理的整个木头部分全部都转换成了黑色。箱子钢制边框的镜面光强度是有细微变化的,钢铁本身会比较容易受到镜面高光的影响,而裂缝则不会。

接下来更新片段着色器的材质属性,让其接受一个sampler2D而不是vec3作为镜面光分量:

struct Material {sampler2D diffuse;sampler2D specular;float     shininess;
};

4.示例

#include "myopenglwidget.h"
#include <QMatrix4x4>
#include <QTime>
#include <QTimer>
#include <math.h>
#include <QDebug>float vertices[] = {// positions          // normals           // texture coords-0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  0.0f, 0.0f,0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  1.0f, 0.0f,0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  1.0f, 1.0f,0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  1.0f, 1.0f,-0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  0.0f, 1.0f,-0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  0.0f, 0.0f,-0.5f, -0.5f,  0.5f,  0.0f,  0.0f, 1.0f,   0.0f, 0.0f,0.5f, -0.5f,  0.5f,  0.0f,  0.0f, 1.0f,   1.0f, 0.0f,0.5f,  0.5f,  0.5f,  0.0f,  0.0f, 1.0f,   1.0f, 1.0f,0.5f,  0.5f,  0.5f,  0.0f,  0.0f, 1.0f,   1.0f, 1.0f,-0.5f,  0.5f,  0.5f,  0.0f,  0.0f, 1.0f,   0.0f, 1.0f,-0.5f, -0.5f,  0.5f,  0.0f,  0.0f, 1.0f,   0.0f, 0.0f,-0.5f,  0.5f,  0.5f, -1.0f,  0.0f,  0.0f,  1.0f, 0.0f,-0.5f,  0.5f, -0.5f, -1.0f,  0.0f,  0.0f,  1.0f, 1.0f,-0.5f, -0.5f, -0.5f, -1.0f,  0.0f,  0.0f,  0.0f, 1.0f,-0.5f, -0.5f, -0.5f, -1.0f,  0.0f,  0.0f,  0.0f, 1.0f,-0.5f, -0.5f,  0.5f, -1.0f,  0.0f,  0.0f,  0.0f, 0.0f,-0.5f,  0.5f,  0.5f, -1.0f,  0.0f,  0.0f,  1.0f, 0.0f,0.5f,  0.5f,  0.5f,  1.0f,  0.0f,  0.0f,  1.0f, 0.0f,0.5f,  0.5f, -0.5f,  1.0f,  0.0f,  0.0f,  1.0f, 1.0f,0.5f, -0.5f, -0.5f,  1.0f,  0.0f,  0.0f,  0.0f, 1.0f,0.5f, -0.5f, -0.5f,  1.0f,  0.0f,  0.0f,  0.0f, 1.0f,0.5f, -0.5f,  0.5f,  1.0f,  0.0f,  0.0f,  0.0f, 0.0f,0.5f,  0.5f,  0.5f,  1.0f,  0.0f,  0.0f,  1.0f, 0.0f,-0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,  0.0f, 1.0f,0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,  1.0f, 1.0f,0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,  1.0f, 0.0f,0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,  1.0f, 0.0f,-0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,  0.0f, 0.0f,-0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,  0.0f, 1.0f,-0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f,  0.0f, 1.0f,0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f,  1.0f, 1.0f,0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,  1.0f, 0.0f,0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,  1.0f, 0.0f,-0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,  0.0f, 0.0f,-0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f,  0.0f, 1.0f
};GLuint indices[] = {0, 1, 3,1, 2, 3
};GLuint VBO, VAO,EBO,lightVAO;
GLuint shaderProgram;QVector3D lightPos(1.2f,1.0f,2.0f);
QVector3D lightColor(1.0f,1.0f,1.0f);
QVector3D objectColor(1.0f,0.5f,0.31f);QTimer *timer;
QTime gtime;QVector<QVector3D> cubePositions = {QVector3D( 0.0f,  0.0f,  0.0f),QVector3D( 2.0f,  5.0f, -15.0f),QVector3D(-1.5f, -2.2f, -2.5f),QVector3D(-3.8f, -2.0f, -12.3f),QVector3D( 2.4f, -0.4f, -3.5f),QVector3D(-1.7f,  3.0f, -7.5f),QVector3D( 1.3f, -2.0f, -2.5f),QVector3D( 1.5f,  2.0f, -2.5f),QVector3D( 1.5f,  0.2f, -1.5f),QVector3D(-1.3f,  1.0f, -1.5f)
};float fov = 45.0f;MyOpenGLWidget::MyOpenGLWidget(QWidget *parent): QOpenGLWidget(parent)
{cameraPos = QVector3D( 0.0f,  0.0f,  5.0f);//摄像机位置cameraTarget = QVector3D( 0.0f,  0.0f,  0.0f);//摄像机看到的位置cameraDirection = QVector3D(cameraPos - cameraTarget);//摄像机的方向cameraDirection.normalize();up = QVector3D(0.0f,  1.0f,  0.0f);cameraRight = QVector3D::crossProduct(up,cameraDirection);//两个向量叉乘的结果会同时垂直于两向量,因此我们会得到指向x轴正方向的那个向量cameraRight.normalize();cameraUp = QVector3D::crossProduct(cameraDirection,cameraRight);cameraFront = QVector3D( 0.0f,  0.0f,  -1.0f);timer = new QTimer();timer->start(50);gtime.start();connect(timer,&QTimer::timeout,[=]{update();});setFocusPolicy(Qt::StrongFocus);//setMouseTracking(true);}void MyOpenGLWidget::initializeGL()
{initializeOpenGLFunctions();m_program = new QOpenGLShaderProgram();m_program->addShaderFromSourceFile(QOpenGLShader::Vertex,":/shapes.vert");m_program->addShaderFromSourceFile(QOpenGLShader::Fragment,":/shapes.frag");m_program->link();qDebug()<<m_program->log();m_lightProgram = new QOpenGLShaderProgram();m_lightProgram->addShaderFromSourceFile(QOpenGLShader::Vertex,":/light.vert");m_lightProgram->addShaderFromSourceFile(QOpenGLShader::Fragment,":/light.frag");m_lightProgram->link();glGenVertexArrays(1, &VAO);glGenBuffers(1, &VBO);glBindVertexArray(VAO);//绑定VAOglBindBuffer(GL_ARRAY_BUFFER, VBO);//顶点缓冲对象的缓冲类型是GL_ARRAY_BUFFERglBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);//把顶点数据复制到缓冲的内存中GL_STATIC_DRAW :数据不会或几乎不会改变。glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0);glEnableVertexAttribArray(0);glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3*sizeof(GLfloat)));glEnableVertexAttribArray(1);glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6*sizeof(GLfloat)));glEnableVertexAttribArray(2);glGenBuffers(1, &EBO);glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);glGenVertexArrays(1, &lightVAO);glGenBuffers(1, &VBO);glBindVertexArray(lightVAO);//绑定VAOglBindBuffer(GL_ARRAY_BUFFER, VBO);//顶点缓冲对象的缓冲类型是GL_ARRAY_BUFFERglBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);//把顶点数据复制到缓冲的内存中GL_STATIC_DRAW :数据不会或几乎不会改变。glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0);glEnableVertexAttribArray(0);glBindBuffer(GL_ARRAY_BUFFER, 0);m_program->bind();m_program->setUniformValue("lightPos",lightPos);m_program->setUniformValue("viewPos",cameraPos);m_program->setUniformValue("material.shininess", 32.0f);m_diffseTexture = new QOpenGLTexture(QImage(":/container2.png").mirrored());m_program->setUniformValue("material.diffuse",0);m_specularTexture = new QOpenGLTexture(QImage(":/container2_specular.png").mirrored());m_program->setUniformValue("material.specular",1);m_lightProgram->bind();m_lightProgram->setUniformValue("lightColor",lightColor);glBindVertexArray(0);//解绑VAO}void MyOpenGLWidget::paintGL()
{glClearColor(0.2f,0.3f,0.3f,1.0f);glEnable(GL_DEPTH_TEST);glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);QMatrix4x4 model;QMatrix4x4 view;float time = gtime.elapsed()/50.0;//int time = QTime::currentTime().msec();QMatrix4x4 projection;projection.perspective(fov,(float)( width())/(height()),0.1,100);view.lookAt(cameraPos,cameraPos + cameraFront,up);m_program->bind();m_program->setUniformValue("projection",projection);m_program->setUniformValue("view",view);lightColor.setX(sin(time/100 * 2.0f));lightColor.setY(sin(time/100 * 0.7f));lightColor.setZ(sin(time/100 * 1.3f));QVector3D diffuseColor = QVector3D(0.3f,0.3f,0.3f);QVector3D ambinetColor = QVector3D(0.7f,0.7f,0.7f);m_program->setUniformValue("light.ambient",  ambinetColor);m_program->setUniformValue("light.diffuse",  diffuseColor); // 将光照调暗了一些以搭配场景m_program->setUniformValue("light.specular", QVector3D(1.0,1.0,1.0));m_diffseTexture->bind(0);m_specularTexture->bind(1);glBindVertexArray(VAO);//绑定VAOmodel.rotate(time,1.0f,1.0f,0.5f);m_program->setUniformValue("model",model);glDrawArrays(GL_TRIANGLES,0,36);m_lightProgram->bind();m_lightProgram->setUniformValue("projection",projection);m_lightProgram->setUniformValue("view",view);//m_lightProgram->setUniformValue("lightColor",lightColor);model.setToIdentity();model.translate(lightPos);model.rotate(1.0f,1.0f,5.0f,0.5f);model.scale(0.2);m_lightProgram->setUniformValue("model",model);glBindVertexArray(lightVAO);//绑定VAOglDrawArrays(GL_TRIANGLES,0,36);//    foreach(auto pos , cubePositions)
//    {
//        model.setToIdentity();
//        model.translate(pos);
//        //model.rotate(time,1.0f,5.0f,3.0f);
//        m_program->setUniformValue("model",model);
//        glDrawArrays(GL_TRIANGLES,0,36);
//    }}void MyOpenGLWidget::resizeGL(int w, int h)
{}void MyOpenGLWidget::keyPressEvent(QKeyEvent *event)
{qDebug()<<event->key();cameraSpeed = 2.5 * 100 / 1000.0;switch (event->key()) {case Qt::Key_W:{cameraPos += cameraSpeed * cameraFront;}break;case Qt::Key_S:{cameraPos -= cameraSpeed * cameraFront;}break;case Qt::Key_A:{cameraPos -= cameraSpeed * cameraRight;}break;case Qt::Key_D:{cameraPos += cameraSpeed * cameraRight;}break;default:break;}update();
}
float PI = 3.1415926;
QPoint deltaPos;
void MyOpenGLWidget::mouseMoveEvent(QMouseEvent *event)
{
//    static float yaw = -90;
//    static float pitch = 0;
//    static QPoint lastPos(width()/2,height()/2);
//    auto currentPos = event->pos();
//    deltaPos = currentPos-lastPos;
//    lastPos=currentPos;
//    float sensitivity = 0.1f;
//    deltaPos *= sensitivity;
//    yaw += deltaPos.x();
//    pitch -= deltaPos.y();
//    if(pitch > 89.0f) pitch = 89.0f;
//    if(pitch < -89.0f) pitch = -89.0f;
//    cameraFront.setX(cos(yaw*PI/180.0) * cos(pitch *PI/180));
//    cameraFront.setY(sin(pitch*PI/180));
//    cameraFront.setZ(sin(yaw*PI/180) * cos(pitch *PI/180));
//    cameraFront.normalize();
//    update();
}void MyOpenGLWidget::wheelEvent(QWheelEvent *event)
{if(fov >= 1.0f && fov <= 75.0f)fov -= event->angleDelta().y()/120;if(fov <= 1.0f)fov = 1.0f;if(fov >= 75.0f)fov = 75.0f;update();
}

OpenGL 光照贴图相关推荐

  1. OpenGL 光照贴图Lighting maps

    OpenGL光照贴图Lighting maps 光照贴图Lighting maps简介 漫反射贴图 镜面光贴图 采样镜面光贴图 光照贴图Lighting maps简介 在上一节中,我们讨论了让每个物体 ...

  2. OpenGL光照贴图

    光照贴图 1. 光照贴图的意义 2. 漫反射贴图 3. 镜面光贴图 1. 光照贴图的意义 现实世界中的物体通常并不只包含有一种材质,而是由多种材质所组成.只有光照颜色的材质系统是不够的,它只是一个最简 ...

  3. OpenGL Lightmap光照贴图的实例

    OpenGL Lightmap光照贴图 先上图,再解答. 完整主要的源代码 源代码剖析 先上图,再解答. 完整主要的源代码 #include <glad/glad.h> #include ...

  4. OpenGL学习笔记(四)-光照-材质-光照贴图

    参考网址:LearnOpenGL 中文版 哔哩哔哩教程 第二章 光照 2.1 颜色 现实生活中人眼看到某一物体的颜色,是它所反射的颜色.如将白光照在红色的玩具上,玩具会吸收白光中除了红色以外的所有子颜 ...

  5. OpenGL原理与实践——核心模式(六):光照贴图、光源分类以及多光源场景主要源码实现

    本章主要以代码为主,理论理解即可.详细分析代码 目录 光照贴图 光源分类 平行光 点光源 shader--点光源 聚光灯 聚光灯边缘优化--光强递减 源码解析 main 全局变量.句柄 main函数主 ...

  6. 【OpenGL学习】光照贴图

    光照贴图 上节中我们给物体添加了材质,使得物体能够对光照做出不同的反应,但是有个问题就是,使用该种材质的物体,只能够表现出我们所定义的一种性质,而实际生活中我们的一个物体往往具有多种材质,因此本节中我 ...

  7. OpenGl L9光照贴图

    一.光照贴图 在上一节中,我们将整个物体的材质定义为一个整体,但现实世界中的物体通常并不只包含有一种材质,而是由多种材质所组成. 比如一辆汽车:它的外壳非常有光泽,车窗会部分反射周围的环境,轮胎不会那 ...

  8. GraphicsLab Project之光照贴图烘焙(一)

    作者:i_dovelemon 来源:CSDN 日期:2018-05-19 主题:Radiosity Algorithm, Global Illumination, Barycentric Coordi ...

  9. OpenGL 视差贴图 Parallax Mapping

    OpenGL 视差贴图 Parallax Mapping 视差贴图 Parallax Mapping简介 视差贴图 陡峭视差映射 视差遮蔽映射 视差贴图 Parallax Mapping简介 视差贴图 ...

最新文章

  1. SIM300实现GPRS上网
  2. 【正一专栏】内马尔要走快走、走好不送!
  3. python移动文件中某个内容_如果python中的某些文件类型,则移动文件并创建目录...
  4. java webmethod 参数_java详解Spring接收web请求参数的方式
  5. mysql 主从同步-读写分离
  6. js删除mysql记录_(DELETEUPDATE)修改、删除数据记录_MySQL
  7. 网络传输之TCP/IP协议族
  8. python js返回 json_[python爬虫]把js转化成json
  9. 分析业务模型-类图(Class Diagram)(上)
  10. java通过InputStream读取文件
  11. java map 缓存数据_Map方式实现JAVA数据缓存
  12. ES(Elasticsearch)解除索引只读限制
  13. Visual C# 2008+SQL Server 2005 数据库与网络开发――3.1.2 C# 2005和2008之间的关系
  14. amaze ui使用简介
  15. linux欺骗技术,显卡欺骗器状态检测及安装注意事项
  16. java替换特殊字符_Java处理特殊字符替换(正则表达式)
  17. 一款好用的插件——油猴子
  18. 《RRU-Net: The Ringed Residual U-Net for Image Splicing Forgery Detection》论文阅读
  19. 2020版影视制作学习路线图(含大纲+视频+工具+书籍+面试)
  20. 异常检测(2)—基于统计学的方法

热门文章

  1. BUUCTF RE WP39-40 [WUSTCTF2020]Cr0ssfun、[WUSTCTF2020]level3
  2. 含文档+PPT+源码等]精品基于java开发的航空订票系统SSM[包运行成功]计算机毕设Java项目源码
  3. EXCEL2010教程(一)
  4. ByteBuf 操作
  5. java除法转百分比
  6. 找一个机器学习的工作,学历重要吗?
  7. tfrecord读取过程简介
  8. 【学习分享】2、创龙 TMS320C6748开发板程序加载和烧写(二)
  9. [rm]realmedia文件格式解析
  10. 留学生计算机辅导理论作业题目-数据库相关