OpenGL with QtWidgets:投光物、多光源

 (本文是LearnOpenGL的学习笔记, 教程中文翻译地址https://learnopengl-cn.github.io/(备用地址https://learnopengl-cn.readthedocs.io/zh/latest/),写于 2021-10-2)

0.前言

上一节学习了材质和光照贴图(https://gongjianbo1992.blog.csdn.net/article/details/120397134),教程接下来讲了投光物和多光源。

1.知识点

投光物就是在基础光照的内容上进行扩展,之前的光照都是拟定一个点,现实世界中,我们有很多种类的光照,每种的表现都不同。将光投射(Cast)到物体的光源叫做投光物(Light Caster)。教程讲了三种投光物:定向光(Directional Light),点光源(Point Light),聚光(Spotlight)。

平行光:当一个光源处于很远的地方时,来自光源的每条光线就会近似于互相平行。(相对于之前基础光照的点光源,简化了光照方向的计算,只需要固定值,而不是计算光源指向物体表面顶点的向量)

点光源:前面基础光照用的就是点光源,某个点的光源朝着所有方向散射光线。只是前面课程没有进行衰减模拟计算,距离越远光照强度越弱。

聚光:聚光是位于环境中某个位置的光源,它只朝一个特定方向而不是所有方向照射光线(手电筒/聚光灯的效果)。相当于以一个方向为基准,夹角超过一定就不进行光照计算。

2.实现代码

(项目git链接:https://github.com/gongjianbo/OpenGLwithQtWidgets.git

多光源实现效果:

OpenGL with QtWidgets:投光物、多光源

#pragma once
#include <QOpenGLWidget>
#include <QOpenGLFunctions_3_3_Core>
#include <QOpenGLShaderProgram>
#include <QOpenGLVertexArrayObject>
#include <QOpenGLBuffer>
#include <QOpenGLTexture>
#include <QVector3D>
#include <QMatrix4x4>
#include <QQuaternion>
#include <QTimer>

//多光源
//QOpenGLWidget窗口上下文
//QOpenGLFunctions访问OpenGL接口,可以不继承作为成员变量使用
class GLMultipleLights
        : public QOpenGLWidget
        , protected QOpenGLFunctions_3_3_Core
{
    Q_OBJECT
public:
    explicit GLMultipleLights(QWidget *parent = nullptr);
    ~GLMultipleLights();

protected:
    //【】继承QOpenGLWidget后重写这三个虚函数
    //设置OpenGL资源和状态。在第一次调用resizeGL或paintGL之前被调用一次
    void initializeGL() override;
    //渲染OpenGL场景,每当需要更新小部件时使用
    void paintGL() override;
    //设置OpenGL视口、投影等,每当尺寸大小改变时调用
    void resizeGL(int width, int height) override;

private:
    void initShader();
    QOpenGLTexture *initTexture(const QString &imgpath);

private:
    //着色器程序
    QOpenGLShaderProgram lightingShader,lampShader;
    //顶点数组对象
    QOpenGLVertexArrayObject lightingVao,lampVao;
    //顶点缓冲
    QOpenGLBuffer vbo;
    //纹理
    QOpenGLTexture *diffuseMap{ nullptr };
    QOpenGLTexture *specularMap{ nullptr };
    //
    QTimer timer;
    int rotate{ 0 };
};

#include "GLMultipleLights.h"
#include <cmath>
#include <QtMath>
#include <QDebug>

GLMultipleLights::GLMultipleLights(QWidget *parent)
    : QOpenGLWidget(parent)
{
    connect(&timer,&QTimer::timeout,this,[this](){
        rotate+=1;
        if(isVisible()){
            update();
        }
    });
    timer.setInterval(50);
}

GLMultipleLights::~GLMultipleLights()
{
    //initializeGL在显示时才调用,释放未初始化的会异常
    if(!isValid())
        return;
    //QOpenGLWidget
    //三个虚函数不需要makeCurrent,对应的操作已由框架完成
    //但是释放时需要设置当前上下文
    makeCurrent();
    vbo.destroy();
    lightingVao.destroy();
    lampVao.destroy();
    delete diffuseMap;
    delete specularMap;
    doneCurrent();
}

void GLMultipleLights::initializeGL()
{
    //为当前上下文初始化OpenGL函数解析
    initializeOpenGLFunctions();
    initShader();

    //方块的顶点、法向量、纹理坐标
    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
    };

    vbo=QOpenGLBuffer(QOpenGLBuffer::VertexBuffer);
    vbo.create();

    //light vao
    lightingVao.create();
    lightingVao.bind();
    vbo.bind();
    vbo.allocate(vertices,sizeof(vertices));
    //setAttributeBuffer(int location, GLenum type, int offset, int tupleSize, int stride = 0)
    lightingShader.setAttributeBuffer(0, GL_FLOAT, sizeof(GLfloat) * 0, 3, sizeof(GLfloat) * 8);
    lightingShader.enableAttributeArray(0);
    lightingShader.setAttributeBuffer(1, GL_FLOAT, sizeof(GLfloat) * 3, 3, sizeof(GLfloat) * 8);
    lightingShader.enableAttributeArray(1);
    lightingShader.setAttributeBuffer(2, GL_FLOAT, sizeof(GLfloat) * 6, 2, sizeof(GLfloat) * 8);
    lightingShader.enableAttributeArray(2);
    vbo.release();
    lightingVao.release();

    //lamp vao
    lampVao.create();
    lampVao.bind();
    vbo.bind();
    //setAttributeBuffer(int location, GLenum type, int offset, int tupleSize, int stride = 0)
    lampShader.setAttributeBuffer(0, GL_FLOAT, 0, 3, sizeof(GLfloat) * 8);
    lampShader.enableAttributeArray(0);
    vbo.release();
    lampVao.release();

    //纹理
    diffuseMap = initTexture(":/container2.png");
    specularMap = initTexture(":/container2_specular.png");
    //shader configuration
    lightingShader.bind();
    lightingShader.setUniformValue("material.diffuse", 0);
    lightingShader.setUniformValue("material.specular", 1);
    lightingShader.release();

    //timer.start();
}

//绘制多个盒子
static QVector3D cubePositions[] = {
    QVector3D( 0.0f,  0.0f,  0.0f),
    QVector3D( 0.0f, -4.0f,  0.0f),
    QVector3D( 0.0f,  4.0f,  0.0f),
    QVector3D( 1.0f, -5.0f, 1.0f),
    QVector3D(-1.5f, -2.2f, -2.5f),
    QVector3D(-3.8f, -2.0f, -7.3f),
    QVector3D( 2.4f, -0.4f, -3.5f),
    QVector3D(-1.7f, -3.0f, -6.5f),
    QVector3D( 5.3f, -2.0f, -2.5f),
    QVector3D(-1.3f,  1.0f, -1.5f)
};

//多个光源
static QVector3D pointLightPositions[] = {
    QVector3D( 0.0f,  2.0f,  0.0f),
    QVector3D( 2.3f, -3.0f, -1.0f),
    QVector3D(-3.0f,  2.0f, 0.5f),
    QVector3D( 2.0f,  3.0f, 2.0f)
};

void GLMultipleLights::paintGL()
{
    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    //清除深度缓冲
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    //Z缓冲(Z-buffer),深度缓冲(Depth Buffer)。
    glEnable(GL_DEPTH_TEST);

    //draw lighting
    lightingShader.bind();
    QMatrix4x4 view; //观察矩阵
    view.translate(0.0f, 0.0f, -10.0f);
    view.rotate(45, QVector3D(1.0f, 0.8f, 0.0f));
    lightingShader.setUniformValue("view", view);
    QMatrix4x4 projection; //透视投影
    projection.perspective(45.0f, 1.0f * width() / height(), 0.1f, 100.0f);
    lightingShader.setUniformValue("projection", projection);
    // Directional light
    lightingShader.setUniformValue("dirLight.direction", -0.2f, -1.0f, -0.3f);
    lightingShader.setUniformValue("dirLight.ambient", 0.05f, 0.05f, 0.05f);
    lightingShader.setUniformValue("dirLight.diffuse", 0.2f, 0.2f, 0.2f);
    lightingShader.setUniformValue("dirLight.specular", 0.5f, 0.5f, 0.5f);
    QVector3D ambient_color(0.05f, 0.05f, 0.05f);
    QVector3D diffuse_color(0.0f, 0.0f, 0.4f);
    QVector3D specular_color(0.0f, 0.0f, 1.0f);
    // Point light 1
    lightingShader.setUniformValue("pointLights[0].position", pointLightPositions[0]);
    lightingShader.setUniformValue("pointLights[0].ambient", ambient_color);
    lightingShader.setUniformValue("pointLights[0].diffuse", diffuse_color);
    lightingShader.setUniformValue("pointLights[0].specular", specular_color);
    lightingShader.setUniformValue("pointLights[0].constant", 1.0f);
    lightingShader.setUniformValue("pointLights[0].linear", 0.09f);
    lightingShader.setUniformValue("pointLights[0].quadratic", 0.032f);
    // Point light 2
    lightingShader.setUniformValue("pointLights[1].position", pointLightPositions[1]);
    lightingShader.setUniformValue("pointLights[1].ambient", ambient_color);
    lightingShader.setUniformValue("pointLights[1].diffuse", diffuse_color);
    lightingShader.setUniformValue("pointLights[1].specular", specular_color);
    lightingShader.setUniformValue("pointLights[1].constant", 1.0f);
    lightingShader.setUniformValue("pointLights[1].linear", 0.09f);
    lightingShader.setUniformValue("pointLights[1].quadratic", 0.032f);
    // Point light 3
    lightingShader.setUniformValue("pointLights[2].position", pointLightPositions[2]);
    lightingShader.setUniformValue("pointLights[2].ambient", ambient_color);
    lightingShader.setUniformValue("pointLights[2].diffuse", diffuse_color);
    lightingShader.setUniformValue("pointLights[2].specular", specular_color);
    lightingShader.setUniformValue("pointLights[2].constant", 1.0f);
    lightingShader.setUniformValue("pointLights[2].linear", 0.09f);
    lightingShader.setUniformValue("pointLights[2].quadratic", 0.032f);
    // Point light 4
    lightingShader.setUniformValue("pointLights[3].position", pointLightPositions[3]);
    lightingShader.setUniformValue("pointLights[3].ambient", ambient_color);
    lightingShader.setUniformValue("pointLights[3].diffuse", diffuse_color);
    lightingShader.setUniformValue("pointLights[3].specular", specular_color);
    lightingShader.setUniformValue("pointLights[3].constant", 1.0f);
    lightingShader.setUniformValue("pointLights[3].linear", 0.09f);
    lightingShader.setUniformValue("pointLights[3].quadratic", 0.032f);
    // SpotLight
    QMatrix4x4 model;//模型矩阵
    model.translate(pointLightPositions[0]);
    model.scale(0.2f);
    QVector3D light_pos = model.map(QVector3D(0.0f, 0.0f, 0.0f));
    QVector3D direction_pos = QVector3D(0.0f, -20.0f, 0.0f);
    lightingShader.setUniformValue("spotLight.direction", direction_pos);
    lightingShader.setUniformValue("spotLight.position", light_pos);
    lightingShader.setUniformValue("spotLight.ambient", 0.0f, 0.0f, 0.0f);
    lightingShader.setUniformValue("spotLight.diffuse", 0.3f, 1.0f, 0.3f);
    lightingShader.setUniformValue("spotLight.specular", 0.3f, 1.0f, 0.3f);
    lightingShader.setUniformValue("spotLight.constant", 1.0f);
    lightingShader.setUniformValue("spotLight.linear", 0.09f);
    lightingShader.setUniformValue("spotLight.quadratic", 0.032f);
    lightingShader.setUniformValue("spotLight.cutOff", (float)std::cos(qDegreesToRadians(12.5)));
    lightingShader.setUniformValue("spotLight.outerCutOff", (float)std::cos(qDegreesToRadians(15.0)));
    //材质-material properties
    //shininess影响镜面高光的散射/半径
    lightingShader.setUniformValue("material.shininess", 32.0f);
    lightingVao.bind();
    //绑定2d纹理
    //bind diffuse map
    glActiveTexture(GL_TEXTURE0);
    diffuseMap->bind();
    //bind specular map
    glActiveTexture(GL_TEXTURE1);
    specularMap->bind();
    //glDrawArrays(GL_TRIANGLES, 0, 36);
    //多个盒子便于对比
    for (unsigned int i = 0; i < 10; i++) {
        //模型矩阵
        QMatrix4x4 box_model;
        //平移
        box_model.translate(cubePositions[i]);
        float angle = 20.0f * i;
        //旋转
        box_model.rotate(angle, QVector3D(1.0f, 0.3f, 0.5f));
        //传入着色器并绘制
        lightingShader.setUniformValue("model", box_model);
        glDrawArrays(GL_TRIANGLES, 0, 36);
    }
    lightingVao.release();
    lightingShader.release();

    //draw lamp
    lampShader.bind();
    lampShader.setUniformValue("view", view);
    lampShader.setUniformValue("projection", projection);
    lampVao.bind();
    for (unsigned int i = 0; i < 4; i++) {
        //模型矩阵
        QMatrix4x4 lamb_model;
        lamb_model.translate(pointLightPositions[i]);
        lamb_model.scale(0.2f);
        //传入着色器并绘制
        lampShader.setUniformValue("model", lamb_model);
        glDrawArrays(GL_TRIANGLES, 0, 36);
    }
    lampVao.release();
    lampShader.release();
}

void GLMultipleLights::resizeGL(int width, int height)
{
    glViewport(0, 0, width, height);
}

void GLMultipleLights::initShader()
{
    //lingting shader
    //in输入,out输出,uniform从cpu向gpu发送
    const char *lighting_vertex=R"(#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;
layout (location = 2) in vec2 aTexCoords;

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

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

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

    gl_Position = projection * view * vec4(FragPos, 1.0);
})";
    const char *lighting_fragment=R"(#version 330 core
struct Material {
    sampler2D diffuse;
    sampler2D specular;
    float shininess;
};

struct DirLight {
    vec3 direction;

    vec3 ambient;
    vec3 diffuse;
    vec3 specular;
};

struct PointLight {
    vec3 position;

    float constant;
    float linear;
    float quadratic;

    vec3 ambient;
    vec3 diffuse;
    vec3 specular;
};

struct SpotLight {
    vec3 position;
    vec3 direction;
    float cutOff;
    float outerCutOff;

    float constant;
    float linear;
    float quadratic;

    vec3 ambient;
    vec3 diffuse;
    vec3 specular;
};

#define NR_POINT_LIGHTS 4

in vec3 FragPos;
in vec3 Normal;
in vec2 TexCoords;

out vec4 color;

uniform vec3 viewPos;
uniform DirLight dirLight;
uniform PointLight pointLights[NR_POINT_LIGHTS];
uniform SpotLight spotLight;
uniform Material material;

// Function prototypes
vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir);
vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir);
vec3 CalcSpotLight(SpotLight light, vec3 normal, vec3 fragPos, vec3 viewDir);

void main()
{
    // Properties
    vec3 norm = normalize(Normal);
    vec3 viewDir = normalize(viewPos - FragPos);

    // == ======================================
    // Our lighting is set up in 3 phases: directional, point lights and an optional flashlight
    // For each phase, a calculate function is defined that calculates the corresponding color
    // per lamp. In the main() function we take all the calculated colors and sum them up for
    // this fragment's final color.
    // == ======================================
    // Phase 1: Directional lighting
    vec3 result = CalcDirLight(dirLight, norm, viewDir);
    // Phase 2: Point lights
    for(int i = 0; i < NR_POINT_LIGHTS; i++)
        result += CalcPointLight(pointLights[i], norm, FragPos, viewDir);
    // Phase 3: Spot light
    result += CalcSpotLight(spotLight, norm, FragPos, viewDir);

    color = vec4(result, 1.0);
}

// Calculates the color when using a directional light.
vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir)
{
    vec3 lightDir = normalize(-light.direction);
    // Diffuse shading
    float diff = max(dot(normal, lightDir), 0.0);
    // Specular shading
    vec3 reflectDir = reflect(-lightDir, normal);
    float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
    // Combine results
    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));
    return (ambient + diffuse + specular);
}

// Calculates the color when using a point light.
vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir)
{
    vec3 lightDir = normalize(light.position - fragPos);
    // Diffuse shading
    float diff = max(dot(normal, lightDir), 0.0);
    // Specular shading
    vec3 reflectDir = reflect(-lightDir, normal);
    float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
    // Attenuation
    float distance = length(light.position - fragPos);
    float attenuation = 1.0f / (light.constant + light.linear * distance + light.quadratic * (distance * distance));
    // Combine results
    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));
    ambient *= attenuation;
    diffuse *= attenuation;
    specular *= attenuation;
    return (ambient + diffuse + specular);
}

// Calculates the color when using a spot light.
vec3 CalcSpotLight(SpotLight light, vec3 normal, vec3 fragPos, vec3 viewDir)
{
    vec3 lightDir = normalize(light.position - fragPos);
    // Diffuse shading
    float diff = max(dot(normal, lightDir), 0.0);
    // Specular shading
    vec3 reflectDir = reflect(-lightDir, normal);
    float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
    // Attenuation
    float distance = length(light.position - fragPos);
    float attenuation = 1.0f / (light.constant + light.linear * distance + light.quadratic * (distance * distance));
    // Spotlight intensity
    float theta = dot(lightDir, normalize(-light.direction));
    float epsilon = light.cutOff - light.outerCutOff;
    float intensity = clamp((theta - light.outerCutOff) / epsilon, 0.0, 1.0);
    // Combine results
    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));
    ambient *= attenuation * intensity;
    diffuse *= attenuation * intensity;
    specular *= attenuation * intensity;
    return (ambient + diffuse + specular);
})";

    //将source编译为指定类型的着色器,并添加到此着色器程序
    if(!lightingShader.addCacheableShaderFromSourceCode(
                QOpenGLShader::Vertex,lighting_vertex)){
        qDebug()<<"compiler vertex error"<<lightingShader.log();
    }
    if(!lightingShader.addCacheableShaderFromSourceCode(
                QOpenGLShader::Fragment,lighting_fragment)){
        qDebug()<<"compiler fragment error"<<lightingShader.log();
    }
    //使用addShader()将添加到该程序的着色器链接在一起。
    if(!lightingShader.link()){
        qDebug()<<"link shaderprogram error"<<lightingShader.log();
    }

    //lamp shader
    const char *lamp_vertex=R"(#version 330 core
layout (location = 0) in vec3 aPos;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

void main()
{
gl_Position = projection * view * model * vec4(aPos, 1.0f);
})";
    const char *lamp_fragment=R"(#version 330 core
out vec4 FragColor;
void main()
{
FragColor = vec4(1.0);
})"; // set alle 4 vector values to 1.0

    if(!lampShader.addCacheableShaderFromSourceCode(
                QOpenGLShader::Vertex,lamp_vertex)){
        qDebug()<<"compiler vertex error"<<lampShader.log();
    }
    if(!lampShader.addCacheableShaderFromSourceCode(
                QOpenGLShader::Fragment,lamp_fragment)){
        qDebug()<<"compiler fragment error"<<lampShader.log();
    }
    if(!lampShader.link()){
        qDebug()<<"link shaderprogram error"<<lampShader.log();
    }
}

QOpenGLTexture *GLMultipleLights::initTexture(const QString &imgpath)
{
    QOpenGLTexture *texture = new QOpenGLTexture(QImage(imgpath), QOpenGLTexture::GenerateMipMaps);
    if(!texture->isCreated()){
        qDebug() << "Failed to create texture";
    }
    //set the texture wrapping parameters
    //等于glTexParameteri(GLtexture_2D, GLtexture_WRAP_S, GL_REPEAT);
    texture->setWrapMode(QOpenGLTexture::DirectionS, QOpenGLTexture::Repeat);
    texture->setWrapMode(QOpenGLTexture::DirectionT, QOpenGLTexture::Repeat);//
    //set texture filtering parameters
    //等价于glTexParameteri(GLtexture_2D, GLtexture_MIN_FILTER, GL_LINEAR);
    texture->setMinificationFilter(QOpenGLTexture::Linear);
    texture->setMagnificationFilter(QOpenGLTexture::Linear);
    return texture;
}

3.参考

LearnOpenGL:https://learnopengl-cn.github.io/02%20Lighting/05%20Light%20casters/

LearnOpenGL:https://learnopengl-cn.github.io/02%20Lighting/06%20Multiple%20lights/

上一篇:记录:实现mapbox的测面功能


下一篇:mapbox层级变小,部分图标+文字不进行绘制问题