OpenGL学习笔记(模型材质、光照贴图)

news2025/4/8 7:07:19

目录

  • 光照与材质
  • 光照贴图
    • 漫反射贴图
    • 采样镜面光贴图

GitHub主页:https://github.com/sdpyy
OpenGL学习仓库:https://github.com/sdpyy1/CppLearn/tree/main/OpenGLtree/main/OpenGL):https://github.com/sdpyy1/CppLearn/tree/main/OpenGL

光照与材质

在现实世界里,每个物体会对光产生不同的反应。比如,钢制物体看起来通常会比陶土花瓶更闪闪发光,一个木头箱子也不会与一个钢制箱子反射同样程度的光。有些物体反射光的时候不会有太多的散射(Scatter),因而产生较小的高光点,而有些物体则会散射很多,产生一个有着更大半径的高光点。如果我们想要在OpenGL中模拟多种类型的物体,我们必须针对每种表面定义不同的材质(Material)属性。
在这里插入图片描述

当描述一个表面时,我们可以分别为三个光照分量定义一个材质颜色(Material Color):环境光照(Ambient Lighting)、漫反射光照(Diffuse Lighting)和镜面光照(Specular Lighting),再添加一个反光度(Shininess)分量。将这个结构体写入片段着色器,简单理解就是把物体颜色分成了三部分,然后在三种光照计算中分别使用,最后直接将光照相加即可

#version 330 core
out vec4 FragColor;

// 材质结构体
struct Material {
    vec3 ambient;
    vec3 diffuse;
    vec3 specular;
    float shininess;
};

// 法线
in vec3 Normal;
// 像素对应空间位置
in vec3 FragPos;
// 光照位置
uniform vec3 lightPos;
// 光照颜色
uniform vec3 lightColor;
// 摄像机位置
uniform vec3 viewPos;
// 材质
uniform Material material;
void main()
{
    // 环境光
    vec3 ambient = lightColor * material.ambient;

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

    // 高光反射
    vec3 viewDir = normalize(viewPos - FragPos);
    vec3 reflectDir = reflect(-lightDir, norm);
    float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32);
    vec3 specular = (spec * material.specular) * lightColor;
	
	// 综合
    vec3 result = ambient + diffuse + specular;
    FragColor = vec4(result, 1.0);
}

对于结构体的uniform,赋值方法比较简单

lightingShader.setVec3("material.ambient",  1.0f, 0.5f, 0.31f);
lightingShader.setVec3("material.diffuse",  1.0f, 0.5f, 0.31f);
lightingShader.setVec3("material.specular", 0.5f, 0.5f, 0.5f);
lightingShader.setFloat("material.shininess", 32.0f);

在这里插入图片描述
这个物体太亮了。物体过亮的原因是环境光、漫反射和镜面光这三个颜色对任何一个光源都全力反射。同样,我们可以对光源的环境光、漫反射和镜面光属性进行分别设置。这样设置可以对被光照物体的比如环境光强度统一设置

struct Light {
    vec3 position;

    vec3 ambient;
    vec3 diffuse;
    vec3 specular;
};

uniform Light light;

这样设置光照

        cubeShader.setVec3("light.ambient",  0.2f, 0.2f, 0.2f);
        cubeShader.setVec3("light.diffuse",  0.5f, 0.5f, 0.5f); // 将光照调暗了一些以搭配场景
        cubeShader.setVec3("light.specular", 1.0f, 1.0f, 1.0f);
        cubeShader.setVec3("light.position", lightPos);

在这里插入图片描述
下面可以做一些有趣的处理,让光源的ambientColor和diffuseColor随时间变化

        glm::vec3 lightColor;
        lightColor.x = sin(glfwGetTime() * 2.0f);
        lightColor.y = sin(glfwGetTime() * 0.7f);
        lightColor.z = sin(glfwGetTime() * 1.3f);
        glm::vec3 diffuseColor = lightColor   * glm::vec3(0.5f); // 降低影响
        glm::vec3 ambientColor = diffuseColor * glm::vec3(0.2f); // 很低的影响
        cubeShader.setVec3("light.ambient", ambientColor);
        cubeShader.setVec3("light.diffuse", diffuseColor);

光照贴图

在上一节中,我们将整个物体的材质定义为一个整体,但现实世界中的物体通常并不只包含有一种材质,而是由多种材质所组成。想想一辆汽车:它的外壳非常有光泽,车窗会部分反射周围的环境,轮胎不会那么有光泽,所以它没有镜面高光,轮毂非常闪亮(如果你洗车了的话)。汽车同样会有漫反射和环境光颜色,它们在整个物体上也不会是一样的,汽车有着许多种不同的环境光/漫反射颜色。总之,这样的物体在不同的部件上都有不同的材质属性。

漫反射贴图

我们希望通过某种方式对物体的每个片段单独设置漫反射颜色。用纹理就能实现。其实都是使用一张覆盖物体的图像,让我们能够逐片段索引其独立的颜色值。在光照场景中,它通常叫做一个漫反射贴图(Diffuse Map)。这也就解释了为什么把纹理作为漫反射系数。

将Material的漫反射项改为采样器,通过UV坐标采样漫反射贴图,这里还移除了环境光,因为因为环境光颜色在几乎所有情况下都等于漫反射颜色

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

之后就是常规的把采样器设置好,就可以了。提供一个加载纹理的方法

// 加载材质返回纹理ID
GLuint loadTexture(char const * path)
{
    GLuint textureID;
    glGenTextures(1, &textureID);

    int width, height, nrComponents;
    unsigned char *data = stbi_load(path, &width, &height, &nrComponents, 0);
    if (data)
    {
        GLenum format;
        if (nrComponents == 1)
            format = GL_RED;
        else if (nrComponents == 3)
            format = GL_RGB;
        else if (nrComponents == 4)
            format = GL_RGBA;

        glBindTexture(GL_TEXTURE_2D, textureID);
        glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
        glGenerateMipmap(GL_TEXTURE_2D);

        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

        stbi_image_free(data);
    }
    else
    {
        std::cout << "Texture failed to load at path: " << path << std::endl;
        stbi_image_free(data);
    }

    return textureID;
}

在这里插入图片描述

采样镜面光贴图

虽然纹理颜色上了,但是木头和铁边的高光应该是不一样的,所以高光的系数也需要一张贴图来定义,来保证不同的位置高光系数是不一样的,下图就表示边上才有颜色,中间对高光的贡献小
在这里插入图片描述
同样,把高光颜色也设置为采样器

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

最终就只有铁边反射
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2330291.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

视频分析设备平台EasyCVR打造汽车门店经营场景安全:AI智慧安防技术全解析

一、方案背景 某电动车企业不停爆出维权新闻&#xff0c;支持和反对的声音此起彼伏&#xff0c;事情不断发酵、反转&#xff0c;每天都有新消息&#xff0c;令人目不暇接。车展、车店作为维权事件的高发场所&#xff0c;事后复盘和责任认定时&#xff0c;安防监控和视频监控平…

Hibernate里的对象不同状态和Session的核心方法

临时状态的测试 Student student new Student("张三", "男", 22, new Date()); 以上student就是一个Transient(临时状态),此时student并没有被session进行托管&#xff0c;即在session的缓存中还不存在student这个对象&#xff0c;当执行完save方法后&a…

模型嵌入式部署

背景 自从深度学习大规模应用以来&#xff0c;其中一个应用方向就是将深度学习视觉算法部署到嵌入式平台上&#xff0c;使用NPU推理。虽然已经做了很久的模型部署&#xff0c;但一直都是在公司默默耕耘&#xff0c;为了发展一下自己“边缘部署专家”这个个人品牌&#xff0c;打…

Redlinux(2025.3.29)

1、将你的虚拟机的网卡模式设置为nat模式&#xff0c;给虚拟机网卡配置三个主机位分别为100、200、168的ip地址。(以nmtui命令为例) 2、测试你的虚拟机是否能够ping通网关和dns&#xff0c;如果不能请修改网关和dns的地址。 首先打开虚拟网络编辑器查看NAT设置里的网关IP&…

uni-app项目运行在浏览器、微信开发者工具、mumu模拟器

一、安装HBuilder X 1、下载HBuilder X 官网网址&#xff1a;https://dcloud.io/hbuilderx.html 根据电脑系统下载对应的版本&#xff08;我的电脑是Windows 10&#xff09; 2.安装HBuilder X 直接将HBuilderX.4.61.2025040322-alpha.zip解压到自己想要存放的文件夹中 双击…

2025-04-07 NO.3 Quest3 MR 配置

文章目录 1 MR 介绍1.1 透视1.2 场景理解1.3 空间设置 2 配置 MR 环境2.1 场景配置2.2 MR 配置 3 运行测试 配置环境&#xff1a; Windows 11Unity 6000.0.42f1Meta SDK v74.0.2Quest3 1 MR 介绍 1.1 透视 ​ 透视&#xff08;Passthrough&#xff09;是将应用的背景从虚拟的…

抓wifi无线空口包之Macbook Pro抓包(一)

参考&#xff1a; 在MAC OS上进行Wi-Fi抓包和空中包分析_空口抓包和无线网卡抓包的区别-CSDN博客 WireShark中802.11帧的类型、子类型对照表_wireshark 怎么看disassociate帧和deauthenticate-CSDN博客 一、在macbook pro上&#xff0c;点击option 同时点击右上角wifi 功能&a…

单元测试原则之——不要模拟值对象 (1)

1. 什么是值对象(Value Objects)? 值对象是指那些不可变且仅通过其属性(数据)来定义的对象。它们通常没有复杂的逻辑或行为,主要用于存储和传递数据。例如: ● 字符串(String) ● 数字(Integer, Double) ● 日期(LocalDate, Instant) ● 自定义的简单数据类(如…

版本控制工具——SVN

目录 【版本控制系统】 【SVN概述】 【SVN基本使用】 【解决SVN拉取文件到本地后不显示绿色图标问题】 【版本控制系统】 版本控制系统&#xff08;version control system&#xff09;是一种用于管理文件变更的软件工具&#xff0c;主要用于记录文件的修改历史&#xff0c…

2022第十三届蓝桥杯大赛软件赛省赛C/C++ 大学 B 组(题解解析)

记录刷题的过程、感悟、题解。 希望能帮到&#xff0c;那些与我一同前行的&#xff0c;来自远方的朋友&#x1f609; 大纲&#xff1a; 1、九进制转十进制-&#xff08;解析&#xff09;-简单的进制转化问题&#x1f604; 2、顺子日期-&#xff08;解析&#xff09;-考察日期 3…

【EC200N-CN——Linux驱动移植】问题回顾

【EC200N-CN——Linux驱动移植】问题回顾 1&#xff09;、开发回顾一、问题回顾与解决过程二、核心原理分析1. **USB设备识别的关键&#xff1a;VID/PID**2. **为什么之前不生成ttyUSB节点&#xff1f;**3. **为什么添加PID后就能生成节点&#xff1f;** 三、日志关键信息解读1…

构建k8s下Helm私有仓库与自定义Chart开发指南

#作者&#xff1a;程宏斌 文章目录 自定义helm模板1、开发自己的chare包2、调试chart3、安装chart 自定义helm模板 https://hub.helm.sh/ 1、开发自己的chare包 [rootmaster ~]# helm create mychare //创建一个名为mychare的chare包 [rootmaster ~]# tree -C mychare/ //以…

【7】C#上位机---Modbus RTU 界面设计与封装

C#上位机---Modbus通讯 1 Modbus RTU 通讯1.1 RS485串口与串行通信(Serial Communications)1.2 Modbus RTU协议1.3 Modbus RTU主从模式1.4 Modbus 主从站模拟调试2 Modbus RTU 界面设计与封装2.1 温度控件的类属性2.2 C#封装Modbus实现通讯2.3 C#封装Modbus TRU通用类2.4 上位…

【嵌入式学习6】多任务版TCP服务器

目录 如何实现&#xff1a; 客户端1.0版本&#xff1a; 服务端&#xff1a; 客户端2.0版本&#xff1a; thread.join() 是一个线程同步方法&#xff0c;用于主线程等待子线程完成。当你调用 thread.join() 时&#xff0c;主线程会阻塞&#xff0c;直到调用 join() 的子线程…

每天认识一个设计模式-外观模式:化繁为简的接口魔法

一、前言 在设计模式中&#xff0c;结构型设计模式处理类或对象组合&#xff0c;可助力构建灵活、可维护软件结构。此前探讨过组合模式&#xff08;将对象组合成树形结构&#xff0c;统一处理单个与组合对象&#xff0c;如文件系统管理&#xff09;和装饰器模式&#xff08;动…

VLAN(虚拟局域网)

一、vlan概述 VLAN(virtual local area network)是一种通过逻辑方式划分网络的技术&#xff0c;允许将一个物理网络划分为多个独立的虚拟网络。每一个vlan是一个广播域&#xff0c;不同vlan之间的通信需要通过路由器或三层交换机 [!注意] vlan是交换机独有的技术&#xff0c;P…

Transformers without Normalization论文翻译

论文信息&#xff1a; 作者&#xff1a;Jiachen Zhu, Xinlei Chen, Kaiming He, Yann LeCun, Zhuang Liu 论文地址&#xff1a;arxiv.org/pdf/2503.10622 代码仓库&#xff1a;jiachenzhu/DyT: Code release for DynamicTanh (DyT) 摘要 归一化层在现代神经网络中无处不在…

题目练习之set的奇妙使用

♥♥♥~~~~~~欢迎光临知星小度博客空间~~~~~~♥♥♥ ♥♥♥零星地变得优秀~也能拼凑出星河~♥♥♥ ♥♥♥我们一起努力成为更好的自己~♥♥♥ ♥♥♥如果这一篇博客对你有帮助~别忘了点赞分享哦~♥♥♥ ♥♥♥如果有什么问题可以评论区留言或者私信我哦~♥♥♥ ✨✨✨✨✨✨ 个…

网站提示“不安全“怎么办?原因分析与解决方法

引言&#xff1a;为什么浏览器会提示网站"不安全"&#xff1f; 当您访问某些网站时&#xff0c;浏览器可能会显示"不安全"警告。这通常意味着该网站存在安全风险&#xff0c;可能影响您的隐私或数据安全。本文将介绍常见原因及解决方法&#xff0c;帮助您…

如何利用AI智能生成PPT,提升工作效率与创意表现

如何利用AI智能生成PPT&#xff0c;提升工作效率与创意表现&#xff01;在这个信息爆炸的时代&#xff0c;制作一份既专业又富有创意的PPT&#xff0c;已经不再是一个简单的任务。尤其是对于每天都需要做报告、做展示的职场人士来说&#xff0c;PPT的质量直接影响着工作效率和个…