第八课,OpenGL光照之基本光照

2023-11-13

冯氏光照模型(Phong Lighting Model)

环境光照(Ambient Lighting):即使在黑暗的情况下,世界上通常也仍然有一些光亮(月亮、远处的光),所以物体几乎永远不会是完全黑暗的。为了模拟这个,我们会使用一个环境光照常量,它永远会给物体一些颜色。
漫反射光照(Diffuse Lighting):模拟光源对物体的方向性影响(Directional Impact)。它是冯氏光照模型中视觉上最显著的分量。物体的某一部分越是正对着光源,它就会越亮。
镜面光照(Specular Lighting):模拟有光泽物体上面出现的亮点。镜面光照的颜色相比于物体的颜色会更倾向于光的颜色。

生成GPU管线

Shader lightShader("./lightShader.vs", "./lightShader.fs");

由程序传入GPU(管线)的变量

使用冯氏光照处理管线

lightShader.use();

传入顶点属性

float vertices[] = {图形顶点位置,图形顶点法向量}

一般情况,法向量不能通过由顶点数据直接给定,而要通过三角形的表达式计算。

向管线传入冯氏模型需要的数据:物体颜色,光照颜色,光照位置,摄像机位置。

lightShader.setVec3("objectColor", 1.0f, 0.5f, 0.31f);//物体颜色
lightShader.setVec3("lightColor", 0.5f, 0.5f, 0.3f);//光照颜色
lightShader.setVec3("lightPos", 2.1f, 1.0f, 0.5f );//光照位置
lightShader.setVec3("viewPos",maincamera.getCameraPos() );//摄像机位置

传入视口变化矩阵

lightShader.setMat4("projection", projection);
lightShader.setMat4("view", view);
lightShader.setMat4("model", model);

绘制

glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 36);

GPU(管线)内对数据的操作

1.顶点着色器
#version 450 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;

out vec3 FragPos;
out vec3 Normal;

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

void main()
{
    Normal = aNormal;  
    //Normal = mat3(transpose(inverse(model))) * aNormal;//用于图形变换
    FragPos = vec3(model * vec4(aPos, 1.0));
    gl_Position = projection * view * vec4(FragPos, 1.0);
}

顶点着色器处理顶点在观察坐标系中的位置,故只是用model,view,projection三个全局值。
而对model(物体模型在世界坐标)的变化,会影响图形法线在世界坐标的方向,故使用Normal = mat3(transpose(inverse(model))) * aNormal;用于图形变化中法线的变换。链接
但在GPU中对model进行逆运算和转置运算会导致大量的重复计算降低效率,因此对model的运算(法线变换矩阵)应该放在cpu中进行(在model变化时计算),通过全局变量引入GPU替代mat3(transpose(inverse(model)))

2.片段着色器
#version 330 core
out vec4 FragColor;

in vec3 Normal;  
in vec3 FragPos;  
  
uniform vec3 lightPos; 
uniform vec3 lightColor;
uniform vec3 objectColor;
uniform vec3 viewPos;

void main()
{
    // ambient
    float ambientStrength = 0.4;
    vec3 ambient = ambientStrength * lightColor;
  	
    // diffuse 
    vec3 norm = normalize(Normal);//单位法向量
    vec3 lightDir = normalize(lightPos - FragPos);//该渲染点指向光源
    float diff = max(dot(norm, lightDir), 0.0);//向量点乘,角度越大数值越小.(不为负数)
    vec3 diffuse = diff * lightColor;//漫反射强度与光线到该点与该平面的夹角有关,夹角越小,光照越弱.

    // specular
    float specularStrength = 0.5;//反光强度
    vec3 viewDir = normalize(viewPos - FragPos);//绘制点指向摄像机
    vec3 reflectDir = reflect(-lightDir, norm); //reflect(入射光线,法线),返回反射向量
    float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32);//两向量点乘后的32次方,次方数大--集中程度高
    vec3 specular = specularStrength * spec * lightColor; //反光强度*反光角度权值*光照颜色
            
    vec3 result = (ambient + diffuse + specular) * objectColor;
    FragColor = vec4(result, 1.0);
}

片段着色器主要处理该点在屏幕中显示的颜色
使用lightPos(光照位置)
, lightColor(光照颜色)
, objectColor(物体颜色)
, viewPos(观察值位置 、摄像机位置)
, Normal(该点法线方向)
, FragPos(该点在世界空间坐标系位置);

由于光照位置摄像机位置处理点位置法线都是世界坐标系下坐标,故可通过世界坐标系计算在摄像机角度观察该点时光照对该点颜色的影响

全局光照强度
// ambient
    float ambientStrength = 0.4;//全局光照系数
    vec3 ambient = ambientStrength * lightColor;//全局光照强度
漫反射光照强度
// diffuse 
    vec3 norm = normalize(Normal);//单位法向量
    vec3 lightDir = normalize(lightPos - FragPos);//该渲染点指向光源
    float diff = max(dot(norm, lightDir), 0.0);//向量点乘,角度越大数值越小.(不为负数)
    vec3 diffuse = diff * lightColor;//漫反射强度与光线到该点与该平面的夹角有关,夹角越小,光照越弱.
反射光照强度
// specular
    float specularStrength = 0.5;//反光强度系数
    vec3 viewDir = normalize(viewPos - FragPos);//绘制点指向摄像机
    vec3 reflectDir = reflect(-lightDir, norm); //reflect(入射光线,法线),返回反射向量
    float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32);//两向量点乘后的32次方,次方数大--集中程度高
    vec3 specular = specularStrength * spec * lightColor; //反光强度系数*反光角度权值*光照颜色

reflect(入射光线向量,法线)返回反射光线向量,是GLSL内置函数。

最终颜色值
 vec3 result = (ambient + diffuse + specular) * objectColor;
 FragColor = vec4(result, 1.0);

光照总强度(全局光照强度+漫反射光照强度+反射光照强度)* 物体颜色。

该管线BUG或不足

1.环境光照不能很好的替代物体间的光照影响。
2.该管线只能处理但单一光源对单一摄像机的影响。
3.最终光照强度有可能大于光源本身,不符合实际。
4.每种材质对光线的反射,漫反射强度系数不同(这将在下一节提到)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

第八课,OpenGL光照之基本光照 的相关文章

  • 重新创建窗口而不破坏上下文

    这个问题是关于使用 OpenGL 的图形应用程序 当时我正在使用 GLFW 框架 但我考虑更改它 我的目标是让用户 尽可能 在全屏模式和窗口模式之间不断切换 此过程应该花费不到一秒的时间 并且可以在运行时发生 例如 看看游戏 我的世界 用户
  • 帧缓冲区和在 opengl 中使用着色器

    我对帧缓冲区有点困惑 我想要做的是使用附加了多个纹理的帧缓冲区 填充每个纹理 然后使用着色器组合 混合 所有纹理以创建新的输出 听起来很容易 是的 我也是这么想的 但我不明白 如何将当前绑定的纹理传递给着色器 您需要的是将纹理放入特定的槽中
  • 如何在 GLSL 1.3 和 OpenGL 2.1 中使用位运算

    我正在尝试编写一个使用许多位操作的着色器 事实上 从 glsl 1 30 开始就支持它们 但我只使用 OpenGL 2 1 有没有办法在我的 OpenGL 版本中使用位运算 所有 SM3 兼容 OpenGL 2 1 硬件支持limited整
  • OpenGL:顶点越多,性能越慢

    我正在开发一个程序的一部分 其中给定 xyz 坐标集合 制作 3D 模型 我已经完成了这张图片所需的所有功能 即平移 旋转 缩放 但是给出的 xyz 坐标越多 程序运行速度就越慢 我的程序在处理 29 000 个坐标时运行得非常流畅 但当我
  • 为什么 glClear 不清除我的屏幕?

    这是我编写的一个简单的 opengl 程序 我试图在绘制三角形之前清除屏幕 我在 init 函数中调用了 glClear 但是 它似乎无法清除屏幕 include
  • LibGDX纹理混合与OpenGL混合功能

    在 libGdx 中 我试图创建一个成形纹理 采用完全可见的矩形纹理并将其遮罩以获得成形纹理 如下所示 在这里我在矩形上测试它 但我想在任何形状上使用它 我调查过本教程 http www learnopengles com tag addi
  • OpenGL 使用着色器将 NV12 转换为 RGB24

    我尝试编写一个应用程序来在 OpenGL 中显示 YUV 图像 我使用此代码片段在 C 中成功将 Y UV 转换为 RGB source https blog csdn net subfate article details 4730514
  • glm 中矩阵值的顺序不正确?

    我开始使用GLM http glm g truc net通过 OpenGL 3 和 GLSL 进行数学运算的库 我需要正交投影来绘制 2D 图形 所以我编写了这个简单的代码 glm mat4 projection 1 0 projectio
  • GL_COLOR_ATTACHMENT 有什么作用?

    我现在正在学习帧缓冲区 但我只是不明白颜色附件的作用 我了解帧缓冲区 第二个参数的意义是什么 glFramebufferTexture2D GL FRAMEBUFFER GL COLOR ATTACHMENT0 GL TEXTURE 2D
  • OpenGL:始终相同的颜色

    我正在 Windows 上编写一个程序 使用c opengl 2 1 and SDL我在顶点颜色方面遇到了一些问题 我在用着glColor3f设置每个顶点集的颜色 但它似乎不起作用 无论我选择什么颜色 我都会将每个顶点绘制为红色 我检查了传
  • 按像素值偏移 gl_Position 或 gl_Vertex

    我的属性包含像素值 我想用这个属性值来偏移我的 gl vertex 问题是我的 gl vertex 以世界单位为单位 而 offset attribute 以像素为单位 如果我将屏幕尺寸作为统一发送 然后将像素转换为 1 到 1 值 并将其
  • 如何在opengl中使用四元数绕屏幕中心旋转?

    我正在尝试实现轨迹球 轨迹球旋转 但我的中心有问题 回转 无论如何 我希望中心成为屏幕的中心 让我解释一下到目前为止我所做的事情 我创建了一个四元数 旋转轴 向量起点x向量结束 角度 向量起点 向量结束 从该四元数中 我创建了一个旋转矩阵
  • matplotlib:渲染到缓冲区/访问像素数据

    我想使用 matplotlib 生成的图作为 OpenGL 中的纹理 到目前为止 我遇到的 matplotlib 的 OpenGL 后端要么不成熟 要么已经停止使用 所以我想避免使用它们 我当前的方法是将图形保存到临时 png 文件中 并从
  • 如何为 glDrawElements() 指定每个图元的颜色

    我想渲染一个索引几何体 所以 我有一堆顶点和关联的排序索引 我在用glDrawElements 渲染 2 个四边形 如下所示 现在 我知道我可以使用glColorPointer 用于指定每个顶点的颜色 我的问题是 我可以指定吗每个基元的颜色
  • Qt 5.5 QOpenGLWidget 链接错误未链接任何 openGL 调用

    我尝试使用 Qt 5 5 1 构建一个简单的 OpenGL 应用程序 一切都很好 直到我尝试使用 glClearColor 等 openGL 本机函数调用 该小部件实际上编译并产生黑屏 但在我尝试使用任何 openGL 本机函数后 它甚至不
  • Windows 上的 OpenGL SDK

    我正在尝试编写一个 OpenGL 应用程序 因此我安装了 Windows 7 SDK 然而 它似乎是OpenGL 1 1 define GL VERSION 1 1 1 如何找到我安装的 OpenGL 版本 dll 以及在哪里可以找到较新的
  • 仅在发布模式下使用 glGenBuffer 时出现未处理的异常 - QT

    我在 Windows 7 上使用 Qt 4 8 发布模式编译项目时遇到了一些问题 调试时一切正常 但在发布时我收到未处理的异常 0xC0000005 访问冲突 我将范围缩小到发生这种情况的行 即生成像素缓冲区的时间 我的第一个猜测是 DLL
  • 为贝塞尔曲线中的每个点绘制切线

    我设法绘制了一条贝塞尔曲线 如下所示 glColor3f 0 1 0 glBegin GL LINE STRIP for int i 3 i lt nPt i 3 glColor3f 0 0 0 for float k 0 k lt NLI
  • glTranslatef 不在 glBegin .. glEnd 中工作

    我正在尝试并排绘制不同颜色的两个方块 我的问题是我无法让 glTranslatef 将第二个方块向右移动 第二个方块只是绘制在第一个方块上 void display void glClear GL COLOR BUFFER BIT glMa
  • GLSL memoryBarrierShared() 有用吗?

    我想知道 memoryBarrierShared 的用处 事实上 当我查找屏障功能的文档时 我读到 对于计算着色器中任何给定的静态屏障实例 单个工作组内的所有调用都必须进入该实例 然后才能允许任何调用继续超出该实例 这确保了在给定的屏障静态

随机推荐

  • 设计模式(2)之单例模式

    外链图片转存失败 源站可能有防盗链机制 建议将图片保存下来直接上传 img AHenjiIs 1610326440502 https img shields io badge link 996 icu red svg 单例模式 顾名思义就是
  • 数据库表结构设计

    数据库表结构设计 一 数据库 二 数据库类型 三 设计步骤 四 表设计 本来最近不想写东西的 奈何平台给推了个流量券 一 数据库 简而言之就是 存储数据的一个容器 常见的数据库软件有MySQL Oracle SQL Server Postg
  • python的下载和安装步骤,python下载安装教程3.10.0

    大家好 给大家分享一下python下载安装教程3 10 0 很多人还不知道这一点 下面详细解释一下 现在让我们来看看 第一步 下载Python安装包 在Python的官网 www python org 中找到最新版本的Python安装包 点
  • 企业级springboot项目架构模板V2.0,开箱即用

    此次 2 0 更新点 1 优化 Controller 接口入参 post 和 put 接口使用 json 格式入参 2 日志服务 quick log serve 增加查询操作日志列表接口 3 quick log serve 服务会记录需要鉴
  • Linux命令_lsof & 网络/文件监控

    官方描述 一个打开的文件可以是一个常规文件 一个目录 一个块特殊文件 一个字符特殊文件 一个执行文本引用 一个库 一个流或一个网络文件 Internet套接字 NFS文件或UNIX域套接字 可以通过路径选择文件系统中的某个文件 也可以选择文
  • Python数据可视化的例子——条形图(bar)

    1 matplotlib模块 应用matplotlib模块绘制条形图 需要调用bar函数 关于该函数的语法和参数含义如下 bar x height width 0 8 bottom None color None edgecolor Non
  • Axure RP 9软件安装步骤

    1 官网下载软件 第一步 点击安装文件 建议安装到D盘 请记住具体安装位置 后续汉化需要用到 本人实际位置 D Program Files x86 Axure Axure RP 9 第二步 激活 打开软件中的激活 第三步 汉化 复制汉化文件
  • discuz数据库密码修改

    在源码config目录下找到这两个文件 然后打开修改密码
  • [开发过程]<软件设计>UML建模初体验

    0 引言 前文提到UML的相关工具 前文链接如下 开发过程 软件设计 关于统一建模语言UML 崭蓝码农的博客 CSDN博客从某一个需求出发 开发中有4个重点问题 1 业务逻辑 2 程序逻辑 3 各进程之间的关系 4 物理实现 为了根据需求
  • 【AI工具】 一款多SOTA模型集成的高精度自动标注工具(直接安装使用,附源码)

    目录 高精度自动标注工具简介及其特性 标注工具的安装 开启自动标注 简介 X AnyLabeling 是一款全新的交互式自动标注工具 其基于AnyLabeling进行构建和二次开发 在此基础上扩展并支持了许多的模型和功能 并借助Segmen
  • java--基础--21.2--注解--案例

    java 基础 21 2 注解 案例 1 类注解 可以在运行时获取类 方法或字段的注解 下面是获取类注解的示例 Class aClass TheClass class Annotation annotations aClass getAnn
  • jar包快速启动和远程监听

    jar包快速启动 制作bat文件 设置窗口背景和字体颜色 设置窗口大小 设置启动内存大小 设置依赖lib文件路径 设置远程debug 制作bat文件 if root set root d root cd root jar bat color
  • STM32的12位ADC过采样实现16位分辨率

    1 什么是过采样 过采样技术是一种以牺牲采样速度来提高ADC分辨率的技术 部分STM32单片机是支持硬件过采样的 如STM32G0系列 通过过采样 可以将12位的ADC提升到16位 非常实用 根据过采样技术 每提高1位ADC分辨率 需要增加
  • CSV文件简介及C++实现

    逗号分隔值 Comma Separated Values CSV 有时也称为字符分隔值 因为分隔字符也可以不是逗号 其文件以纯文本形式存储表格数据 数字和文本 纯文本意味着该文件是一个字符序列 不含必须象二进制数字那样被解读的数据 CSV文
  • Java之继承

    继承 继承 为什么使用继承 继承是什么 继承的语法 访问父类成员 访问父类成员变量 访问父类成员方法 super关键字 子类构造方法 super和this 异同 分别的使用方法 继承的方式 final关键字 作者简介 zoro 1 目前大一
  • 解决安装android studio时用户文件夹为中文名

    第一步 使用登陆管理员账号登陆电脑 更改c盘用户文件夹的名字 创建管理员账户 百度经验 第二步 win r调出运行界面 输入regedit 依此进入 HKEY LOCAL MACHINE SOFTWARE Microsoft Windows
  • Python读取Excel,日期列读出来是数字的处理

    Python读取Excel 里面如果是日期 直接读出来是float类型 无法直接使用 通过判断读取表格的数据类型ctype 进一步处理 返回的单元格内容的类型有5种 ctype 0 empty 1 string 2 number 3 dat
  • Spring学习总结【二】---IoC(控制反转)

    文章目录 IoC理论推导 IoC本质 工作原理 IoC创建对象的方式 IoC理论推导 在我们之前的业务中 用户的需求可能会影响我们原来的代码 我们需要根据用户的需求去修改原代码 如果程序代码量十分大 修改一次的成本代价十分昂贵 之前 程序是
  • 免费送书啦!细数Github大神们的开源书籍![二]

    计算机软件设计 软件设计的哲学 软件设计的哲学 斯坦福教授 Tcl 语言发明者 John Ousterhout 的著作 A Philosophy of Software Design 自出版以来 好评如潮 按照 IT 图书出版的惯例 如果冠
  • 第八课,OpenGL光照之基本光照

    冯氏光照模型 Phong Lighting Model 环境光照 Ambient Lighting 即使在黑暗的情况下 世界上通常也仍然有一些光亮 月亮 远处的光 所以物体几乎永远不会是完全黑暗的 为了模拟这个 我们会使用一个环境光照常量