# Learn OpenGL with Qt——光照贴图

19 篇文章 173 订阅

## 光照贴图

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

vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords));


vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords));


vertices = {
//位置               //法向量               //纹理坐标
-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
};

#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;
layout (location = 2) in vec2 aTexCoords;
...
out vec2 TexCoords;

void main()
{
...
TexCoords = aTexCoords;
}


    , tex_diffuse(QOpenGLTexture::Target2D)
    tex_diffuse.setData(QImage(":/container_diffuse.png"));
    shaderProgram.setAttributeBuffer("aPos", GL_FLOAT, 0, 3, sizeof(GLfloat) * 8);
shaderProgram.setAttributeBuffer("aNormal", GL_FLOAT, sizeof(GLfloat) * 3, 3, sizeof(GLfloat) * 8);
shaderProgram.setAttributeBuffer("aTexCoords", GL_FLOAT, sizeof(GLfloat) * 6, 2, sizeof(GLfloat) * 8);
//...
lampShader.setAttributeBuffer("aPos", GL_FLOAT, 0, 3, sizeof(GLfloat) * 8);
lampShader.enableAttributeArray("aPos");
    tex_diffuse.bind(0);
shaderProgram.setUniformValue("material.diffuse",0);

### 代码节点

#### widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include "camera.h"

#include <QOpenGLWidget>
#include <QOpenGLExtraFunctions>
#include <QOpenGLBuffer>
#include <QOpenGLVertexArrayObject>
#include <QOpenGLTexture>
#include <QTimer>
#include <QTime>
#include <QtMath>
#include <QKeyEvent>
class Widget : public QOpenGLWidget,public QOpenGLExtraFunctions
{
Q_OBJECT

public:
Widget(QWidget *parent = 0);
~Widget();
protected:
virtual void initializeGL() override;
virtual void resizeGL(int w,int h) override;
virtual void paintGL() override;

virtual bool event(QEvent *e) override;

private:
QVector<float> vertices;
QVector<QVector3D> cubePositions;
QOpenGLBuffer VBO;
QOpenGLVertexArrayObject VAO;
QOpenGLVertexArrayObject lightVAO;
QTimer timer;
QOpenGLTexture tex_diffuse;
Camera camera;
};

#endif // WIDGET_H


#### widget.cpp

#include "widget.h"
#include <QtMath>

Widget::Widget(QWidget *parent)
: QOpenGLWidget(parent)
, VBO(QOpenGLBuffer::VertexBuffer)
, tex_diffuse(QOpenGLTexture::Target2D)
, camera(this)

{

vertices = {
//位置               //法向量               //纹理坐标
-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
};

timer.setInterval(18);
connect(&timer,&QTimer::timeout,this,static_cast<void (Widget::*)()>(&Widget::update));
timer.start();

QSurfaceFormat format;
format.setSamples(20);
setFormat(format);

}

Widget::~Widget()
{
makeCurrent();
tex_diffuse.destroy();
doneCurrent();
}

void Widget::initializeGL()
{
this->initializeOpenGLFunctions();        //初始化opengl函数
}
}
}

tex_diffuse.setData(QImage(":/container_diffuse.png"));
QOpenGLVertexArrayObject::Binder{&VAO};

VBO.create();       //生成VBO对象
VBO.bind();         //将VBO绑定到当前的顶点缓冲对象（QOpenGLBuffer::VertexBuffer）中

//将顶点数据分配到VBO中，第一个参数为数据指针，第二个参数为数据的字节长度
VBO.allocate(vertices.data(),sizeof(float)*vertices.size());

//设置顶点解析格式，并启用顶点
shaderProgram.setAttributeBuffer("aPos", GL_FLOAT, 0, 3, sizeof(GLfloat) * 8);
shaderProgram.setAttributeBuffer("aNormal", GL_FLOAT, sizeof(GLfloat) * 3, 3, sizeof(GLfloat) * 8);
shaderProgram.setAttributeBuffer("aTexCoords", GL_FLOAT, sizeof(GLfloat) * 6, 2, sizeof(GLfloat) * 8);

}
}
}

QOpenGLVertexArrayObject::Binder{&lightVAO};
VBO.bind(); //只需要绑定VBO不用再次设置VBO的数据，因为箱子的VBO数据中已经包含了正确的立方体顶点数据
lampShader.setAttributeBuffer("aPos", GL_FLOAT, 0, 3, sizeof(GLfloat) * 8);

this->glEnable(GL_DEPTH_TEST);

camera.init();

}

void Widget::resizeGL(int w, int h)
{
this->glViewport(0,0,w,h);                  //定义视口区域
}

void Widget::paintGL()
{
this->glClearColor(0.0f,0.0f,0.0f,1.0f);                       //设置清屏颜色
this->glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT);       //清除颜色缓存和深度缓存
float time=QTime::currentTime().msecsSinceStartOfDay()/1000.0;

QVector3D lightColor(qSin(time*2.0f),qSin(time*0.7f),qSin(time*1.3f));
QVector3D objectColor(1.0f,0.5f,0.31f);
QVector3D lightPos(-4.0f,0.0f,0.5f);

QMatrix4x4 model;

tex_diffuse.bind(0);

shaderProgram.setUniformValue("light.diffuse", QVector3D(0.5f, 0.5f, 0.5f));    // 将光照调暗了一些以搭配场景

QMatrix4x4 projection;
projection.perspective(45.0f,width()/(float)height(),0.1f,100.0f);
QOpenGLVertexArrayObject::Binder{&VAO};
this->glDrawArrays(GL_TRIANGLES, 0, 36);

model.translate(lightPos);
model.scale(0.2);

QOpenGLVertexArrayObject::Binder{&lightVAO};
this->glDrawArrays(GL_TRIANGLES, 0, 36);
}

bool Widget::event(QEvent *e)
{
camera.handle(e);
return QWidget::event(e);   //调用父类的事件分发函数
}


#### triangle.vert

#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;
layout (location = 2) in vec2 aTexCoords;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

out vec3 FragPos;
out vec3 Normal;
out vec2 TexCoords;

void main()
{
gl_Position = projection * view * model * vec4(aPos, 1.0);
FragPos = vec3(model * vec4(aPos, 1.0));
Normal = mat3(transpose(inverse(model))) * aNormal;
TexCoords = aTexCoords;
}


#### triangle.frag

#version 330 core

out vec4 FragColor;

uniform vec3 objectColor;
uniform vec3 lightColor;

in vec3 FragPos;
in vec3 Normal;

uniform vec3 viewPos;

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

in vec2 TexCoords;

uniform Material material;

struct Light {
vec3 position;

vec3 ambient;
vec3 diffuse;
vec3 specular;
};

uniform Light light;

void main()
{
// 环境光
vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords));

// 漫反射
vec3 norm = normalize(Normal);
vec3 lightDir = normalize(light.position - FragPos);
float diff = max(dot(norm, lightDir), 0.0);
vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords));

// 镜面光
vec3 viewDir = normalize(viewPos - FragPos);
vec3 reflectDir = reflect(-lightDir, norm);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
vec3 specular = light.specular * (spec * material.specular);

vec3 result = ambient + diffuse + specular;
FragColor = vec4(result, 1.0);

}


### 镜面光贴图

使用PhotoshopGimp之类的工具，将漫反射纹理转换为镜面光纹理还是比较容易的，只需要剪切掉一些部分，将图像转换为黑白的，并增加亮度/对比度就好了。

### 采样镜面光贴图

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

vec3 ambient  = light.ambient  * vec3(texture(material.diffuse, TexCoords));
vec3 diffuse  = light.diffuse  * diff * vec3(texture(material.diffuse, TexCoords));
vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords));
FragColor = vec4(ambient + diffuse + specular, 1.0);


### 代码节点

#### widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include "camera.h"

#include <QOpenGLWidget>
#include <QOpenGLExtraFunctions>
#include <QOpenGLBuffer>
#include <QOpenGLVertexArrayObject>
#include <QOpenGLTexture>
#include <QTimer>
#include <QTime>
#include <QtMath>
#include <QKeyEvent>
class Widget : public QOpenGLWidget,public QOpenGLExtraFunctions
{
Q_OBJECT

public:
Widget(QWidget *parent = 0);
~Widget();
protected:
virtual void initializeGL() override;
virtual void resizeGL(int w,int h) override;
virtual void paintGL() override;

virtual bool event(QEvent *e) override;

private:
QVector<float> vertices;
QVector<QVector3D> cubePositions;
QOpenGLBuffer VBO;
QOpenGLVertexArrayObject VAO;
QOpenGLVertexArrayObject lightVAO;
QTimer timer;
QOpenGLTexture tex_diffuse;
QOpenGLTexture tex_specular;
Camera camera;
};

#endif // WIDGET_H


#### widget.cpp

#include "widget.h"
#include <QtMath>

Widget::Widget(QWidget *parent)
: QOpenGLWidget(parent)
, VBO(QOpenGLBuffer::VertexBuffer)
, tex_diffuse(QOpenGLTexture::Target2D)
, tex_specular(QOpenGLTexture::Target2D)
, camera(this)

{

vertices = {
//位置               //法向量               //纹理坐标
-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
};

timer.setInterval(18);
connect(&timer,&QTimer::timeout,this,static_cast<void (Widget::*)()>(&Widget::update));
timer.start();

QSurfaceFormat format;
format.setSamples(20);
setFormat(format);

}

Widget::~Widget()
{
makeCurrent();
tex_diffuse.destroy();
tex_specular.destroy();
doneCurrent();
}

void Widget::initializeGL()
{
this->initializeOpenGLFunctions();        //初始化opengl函数
}
}
}

tex_diffuse.setData(QImage(":/container_diffuse.png"));
tex_specular.setData(QImage(":/container_specular.png"));
QOpenGLVertexArrayObject::Binder{&VAO};

VBO.create();       //生成VBO对象
VBO.bind();         //将VBO绑定到当前的顶点缓冲对象（QOpenGLBuffer::VertexBuffer）中

//将顶点数据分配到VBO中，第一个参数为数据指针，第二个参数为数据的字节长度
VBO.allocate(vertices.data(),sizeof(float)*vertices.size());

//设置顶点解析格式，并启用顶点
shaderProgram.setAttributeBuffer("aPos", GL_FLOAT, 0, 3, sizeof(GLfloat) * 8);
shaderProgram.setAttributeBuffer("aNormal", GL_FLOAT, sizeof(GLfloat) * 3, 3, sizeof(GLfloat) * 8);
shaderProgram.setAttributeBuffer("aTexCoords", GL_FLOAT, sizeof(GLfloat) * 6, 2, sizeof(GLfloat) * 8);

}
}
}

QOpenGLVertexArrayObject::Binder{&lightVAO};
VBO.bind(); //只需要绑定VBO不用再次设置VBO的数据，因为箱子的VBO数据中已经包含了正确的立方体顶点数据
lampShader.setAttributeBuffer("aPos", GL_FLOAT, 0, 3, sizeof(GLfloat) * 8);

this->glEnable(GL_DEPTH_TEST);

camera.init();

}

void Widget::resizeGL(int w, int h)
{
this->glViewport(0,0,w,h);                  //定义视口区域
}

void Widget::paintGL()
{
this->glClearColor(0.0f,0.0f,0.0f,1.0f);                       //设置清屏颜色
this->glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT);       //清除颜色缓存和深度缓存
float time=QTime::currentTime().msecsSinceStartOfDay()/1000.0;

QVector3D lightColor(qSin(time*2.0f),qSin(time*0.7f),qSin(time*1.3f));
QVector3D objectColor(1.0f,0.5f,0.31f);
QVector3D lightPos(-4.0f,0.0f,0.5f);

QMatrix4x4 model;

tex_diffuse.bind(0);

shaderProgram.setUniformValue("light.diffuse", QVector3D(0.5f, 0.5f, 0.5f));    // 将光照调暗了一些以搭配场景

QMatrix4x4 projection;
projection.perspective(45.0f,width()/(float)height(),0.1f,100.0f);
QOpenGLVertexArrayObject::Binder{&VAO};
this->glDrawArrays(GL_TRIANGLES, 0, 36);

model.translate(lightPos);
model.scale(0.2);

QOpenGLVertexArrayObject::Binder{&lightVAO};
this->glDrawArrays(GL_TRIANGLES, 0, 36);
}

bool Widget::event(QEvent *e)
{
camera.handle(e);
return QWidget::event(e);   //调用父类的事件分发函数
}


#### triangle.vert

#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;
layout (location = 2) in vec2 aTexCoords;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

out vec3 FragPos;
out vec3 Normal;
out vec2 TexCoords;

void main()
{
gl_Position = projection * view * model * vec4(aPos, 1.0);
FragPos = vec3(model * vec4(aPos, 1.0));
Normal = mat3(transpose(inverse(model))) * aNormal;
TexCoords = aTexCoords;
}


#### triangle.frag

#version 330 core

out vec4 FragColor;

uniform vec3 objectColor;
uniform vec3 lightColor;

in vec3 FragPos;
in vec3 Normal;

uniform vec3 viewPos;

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

in vec2 TexCoords;

uniform Material material;

struct Light {
vec3 position;

vec3 ambient;
vec3 diffuse;
vec3 specular;
};

uniform Light light;

void main()
{
// 环境光
vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords));

// 漫反射
vec3 norm = normalize(Normal);
vec3 lightDir = normalize(light.position - FragPos);
float diff = max(dot(norm, lightDir), 0.0);
vec3 diffuse  = light.diffuse  * diff * vec3(texture(material.diffuse, TexCoords));

// 镜面光
vec3 viewDir = normalize(viewPos - FragPos);
vec3 reflectDir = reflect(-lightDir, norm);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords));

vec3 result = ambient + diffuse + specular;
FragColor = vec4(result, 1.0);

}


#### lamp.frag

#version 330 core
out vec4 FragColor;

void main()
{
FragColor = vec4(1.0); // 将向量的四个分量全部设置为1.0
}


• 5
点赞
• 3
收藏
觉得还不错? 一键收藏
• 1
评论
08-13 193
09-20 9557
06-09 1477
01-09 718
02-16 584
07-18 482
04-07
02-16 794
11-09 2087
12-10 1123

### “相关推荐”对你有帮助么？

• 非常没帮助
• 没帮助
• 一般
• 有帮助
• 非常有帮助

1.余额是钱包充值的虚拟货币，按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载，可以购买VIP、付费专栏及课程。