OpenGL之光照贴图

 我们需要拓展之前的系统,引入漫反射镜面光贴图(Map)。这允许我们对物体的漫反射分量和镜面光分量有着更精确的控制。

漫反射贴图

我们希望通过种方式对物体的每个片段单独设置漫反射颜色。我们仅仅是对同样的原理使用了不同的名字:其实都是使用一张覆盖物体的图像,让我们能够逐片段索引其独立的颜色值。在光照场景中,它通常叫做一个漫反射贴图(Diffuse Map)(3D艺术家通常都这么叫它),它是一个表现了物体所有的漫反射颜色的纹理图像。

在着色器中使用漫反射贴图的方法和纹理教程中是完全一样的。但这次我们会将纹理储存为Material结构体中的一个sampler2D。我们将之前定义的vec3漫反射颜色向量替换为漫反射贴图。 

我们也移除了环境光材质颜色向量,因为环境光颜色在几乎所有情况下都等于漫反射颜色,所以我们不需要将它们分开储存:

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));

就是使用漫反射贴图的全部步骤了。你可以看到,这并不是什么新的东西,但这能够极大地提高视觉品质。为了让它正常工作,我们还需要使用纹理坐标更新顶点数据,将它们作为顶点属性传递到片段着色器,加载材质并绑定材质到合适的纹理单元。

更新后的顶点数据可以在这里找到。顶点数据现在包含了顶点位置、法向量和立方体顶点处的纹理坐标。让我们更新顶点着色器来以顶点属性的形式接受纹理坐标,并将它们传递到片段着色器中:

#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;
}

记得去更新两个VAO的顶点属性指针来匹配新的顶点数据,并加载箱子图像为一个纹理。在绘制箱子之前,我们希望将要用的纹理单元赋值到material.diffuse这个uniform采样器,并绑定箱子的纹理到这个纹理单元:

lightingShader.setInt("material.diffuse", 0);
...
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, diffuseMap);

使用了漫反射贴图之后,细节再一次得到惊人的提升,这次箱子有了光照开始闪闪发光(字面意思也是)了。箱子看起来可能像这样:

4.1.lighting_maps.vs

#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);
}

4.1.lighting_maps.fs

#version 330 core
out vec4 FragColor;struct Material {sampler2D diffuse;vec3 specular;    float shininess;
}; struct Light {vec3 position;vec3 ambient;vec3 diffuse;vec3 specular;
};in vec3 FragPos;  
in vec3 Normal;  
in vec2 TexCoords;uniform vec3 viewPos;
uniform Material material;
uniform Light light;void main()
{// ambientvec3 ambient = light.ambient * texture(material.diffuse, TexCoords).rgb;// diffuse vec3 norm = normalize(Normal);vec3 lightDir = normalize(light.position - FragPos);float diff = max(dot(norm, lightDir), 0.0);vec3 diffuse = light.diffuse * diff * texture(material.diffuse, TexCoords).rgb;  // specularvec3 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);
} 

4.1.light_cube.vs

#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.0);
}

4.1.light_cube.fs 

#version 330 core
out vec4 FragColor;void main()
{FragColor = vec4(1.0); // set all 4 vector values to 1.0
}
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <stb_image.h>#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>#include <learnopengl/shader_m.h>
#include <learnopengl/camera.h>#include <iostream>void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
void processInput(GLFWwindow *window);
unsigned int loadTexture(const char *path);// settings
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;// camera
Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));
float lastX = SCR_WIDTH / 2.0f;
float lastY = SCR_HEIGHT / 2.0f;
bool firstMouse = true;// timing
float deltaTime = 0.0f;
float lastFrame = 0.0f;// lighting
glm::vec3 lightPos(1.2f, 1.0f, 2.0f);int main()
{// glfw: initialize and configure// ------------------------------glfwInit();glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);#ifdef __APPLE__glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif// glfw window creation// --------------------GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);if (window == NULL){std::cout << "Failed to create GLFW window" << std::endl;glfwTerminate();return -1;}glfwMakeContextCurrent(window);glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);glfwSetCursorPosCallback(window, mouse_callback);glfwSetScrollCallback(window, scroll_callback);// tell GLFW to capture our mouseglfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);// glad: load all OpenGL function pointers// ---------------------------------------if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)){std::cout << "Failed to initialize GLAD" << std::endl;return -1;}// configure global opengl state// -----------------------------glEnable(GL_DEPTH_TEST);// build and compile our shader zprogram// ------------------------------------Shader lightingShader("4.1.lighting_maps.vs", "4.1.lighting_maps.fs");Shader lightCubeShader("4.1.light_cube.vs", "4.1.light_cube.fs");// set up vertex data (and buffer(s)) and configure vertex attributes// -----------------------------------------------------

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

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

相关文章

通讯网关软件013——利用CommGate X2ORACLE实现Modbus RTU数据转储ORACLE

本文介绍利用CommGate X2ORACLE实现从Modbus RTU设备读取数据并转储至ORACLE数据库。CommGate X2ORACLE是宁波科安网信开发的网关软件&#xff0c;软件可以登录到网信智汇(wangxinzhihui.com)下载。 【案例】如下图所示&#xff0c;实现从Modbus RTU设备读取数据并转储至ORACL…

洛谷P5732 【深基5.习7】杨辉三角题解

目录 题目【深基5.习7】杨辉三角题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1传送门 代码解释亲测 题目 【深基5.习7】杨辉三角 题目描述 给出 n ( n ≤ 20 ) n(n\le20) n(n≤20)&#xff0c;输出杨辉三角的前 n n n 行。 如果你不知道什么是杨辉三角&#xf…

Android Jetpack组件架构:ViewModel的原理

Android Jetpack组件架构&#xff1a;ViewModel的原理 导言 本篇文章是关于介绍ViewModel的&#xff0c;由于ViewModel的使用还是挺简单的&#xff0c;这里就不再介绍其的基本应用&#xff0c;我们主要来分析ViewModel的原理。 ViewModel的生命周期 众所周知&#xff0c;一般…

【进阶C语言】自定义类型

本节内容大致目录如下&#xff1a; 1.结构体 2.位段 3.枚举 4.联合&#xff08;共用体&#xff09; 以上都是C语言中的自定义类型&#xff0c;可以根据我们的需要去定义。 一、结构体 一些基础知识在初阶C语言的时候已经介绍过&#xff0c;在这里粗略概括&#xff1b;重…

C++17中std::filesystem::directory_entry的使用

C17引入了std::filesystem库(文件系统库, filesystem library)。这里整理下std::filesystem::directory_entry的使用。 std::filesystem::directory_entry&#xff0c;目录项&#xff0c;获取文件属性。此directory_entry类主要用法包括&#xff1a; (1).构造函数、…

Flutter笔记:滚动之-无限滚动与动态加载的实现(GetX简单状态管理版)

Flutter笔记 无限滚动与动态加载的实现&#xff08;GeX简单状态管理版&#xff09; 作者&#xff1a;李俊才 &#xff08;jcLee95&#xff09;&#xff1a;https://blog.csdn.net/qq_28550263 邮箱 &#xff1a;291148484163.com 本文地址&#xff1a;https://blog.csdn.net/qq…

阿里云RDS关系型数据库详细介绍_多版本数据库说明

阿里云RDS关系型数据库大全&#xff0c;关系型数据库包括MySQL版、PolarDB、PostgreSQL、SQL Server和MariaDB等&#xff0c;NoSQL数据库如Redis、Tair、Lindorm和MongoDB&#xff0c;阿里云百科分享阿里云RDS关系型数据库大全&#xff1a; 目录 阿里云RDS关系型数据库大全 …

通过containerd部署k8s集群环境及初始化时部分报错解决

目录 一.基础环境配置&#xff08;每个节点都做&#xff09; 1.hosts解析 2.防火墙和selinux 3.安装基本软件并配置时间同步 4.禁用swap分区 5.更改内核参数 6.配置ipvs 7.k8s下载 &#xff08;1&#xff09;配置镜像下载相关软件 &#xff08;2&#xff09;配置kube…

【视频去噪】基于全变异正则化最小二乘反卷积是最标准的图像处理、视频去噪研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

stl格式-3D三角形

文章目录 什么是stl文件?格式首选stl的语法1.这是一个stl格式的文件:(ASCII码)2.下面先举个例子(难度略微提示)补充:关于\<\<我试了一下:这个法线你随便写好像也没问题\>> 3.来个立方体4.最后再写一个由三个直角形组成的立方体(直棱锥)5.amend 修正(右手定则,法线…

毛玻璃态计算器

效果展示 页面结构组成 从上述的效果可以看出&#xff0c;计算机的页面比较规整&#xff0c;适合grid布局。 CSS3 知识点 grid 布局 实现计算机布局 <div class"container"><form class"calculator" name"calc"><input type…

EasyEdge 智能边缘控制台通过sdk发布应用

离线部署SDK生成 模型部署完成后会出现下载SDK的按钮&#xff0c;点击按钮下载SDK并保存好SDK。 进入EasyDL官网的技术文档 安装智能边缘控制台 跟着教程&#xff0c;完成安装&#xff1a;点此链接 树莓派4b是Linux arm64的架构&#xff0c;点击对应的链接进行下载。 下载完成…

金融帝国实验室(CapLab)官方更新_V9.1.15版本(2023年第64次)

〖金融帝国实验室〗&#xff08;Capitalism Lab&#xff09;游戏更新记录&#xff08;2023年度&#xff09; ————————————— ◎游戏开发&#xff1a;Enlight Software Ltd.&#xff08;微启软件有限公司&#xff09; ◎官方网站&#xff1a;https://www.capitalis…

阿里云通义千问14B模型开源!性能超越Llama2等同等尺寸模型

9月25日&#xff0c;阿里云开源通义千问140亿参数模型Qwen-14B及其对话模型Qwen-14B-Chat,免费可商用。Qwen-14B在多个权威评测中超越同等规模模型&#xff0c;部分指标甚至接近Llama2-70B。阿里云此前开源了70亿参数模型Qwen-7B等&#xff0c;一个多月下载量破100万&#xff0…

【C++】笔试训练(三)

目录 一、选择题二、编程题1、字符串中找出连续最长的数字串2、数组中出现次数超过一半的数字 一、选择题 1、以下程序的输出结果是&#xff08;&#xff09; #include <stdio.h> int main() {char a[10] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }, * p;int i;i 8;p a i;p…

IO流之File类

File类 File 对应的硬盘上的文件或者文件夹 位于java.io包下 File对文件/文件夹进行操作&#xff0c;但是无法对文件内容进行操作&#xff0c;读取/写入不可以操作&#xff0c;但是可以创文件夹/读取文件路径,IO流才可以进行操作 文件/文件夹的路径&#xff1a;linux使用/作为文…

【红外与可见光图像融合】离散平稳小波变换域中基于离散余弦变换和局部空间频率的红外与视觉图像融合方法(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

音频编辑软件Steinberg SpectraLayers Pro mac中文软件介绍

Steinberg SpectraLayers Pro mac是一款专业的音频编辑软件&#xff0c;旨在帮助音频专业人士进行精细的音频编辑和声音处理。它提供了强大的频谱编辑功能&#xff0c;可以对音频文件进行深入的频谱分析和编辑。 Steinberg SpectraLayers Pro mac软件特点 1. 频谱编辑&#xff…

基于SpringBoot的知识管理系统

目录 前言 一、技术栈 二、系统功能介绍 用户管理 文章分类 资料分类 文章信息 论坛交流 资料下载 三、核心代码 1、登录模块 2、文件上传模块 3、代码封装 前言 随着信息互联网信息的飞速发展&#xff0c;无纸化作业变成了一种趋势&#xff0c;针对这个问题开发一个…

Windows历史版本下载

1、微PE工具箱&#xff08;非广告本人常用&#xff09; 常用安装Windows系统的微PE工具 地址&#xff1a;https://www.wepe.com.cn/download.html 2、Windows系统下载地址&#xff08;非微软官方&#xff09; 地址&#xff1a;MSDN, 我告诉你 - 做一个安静的工具站 下载&…