GLSL教程 第5章:光照和材质

目录

5.1 光照模型基础

5.2 Phong光照模型

5.3 Blinn-Phong光照模型

5.4 Cook-Torrance光照模型

5.5 Lambert光照模型

5.6 材质属性的深入讲解

小结


       光照和材质是计算机图形学中至关重要的元素,它们共同决定了渲染图像的视觉效果。光照模型用于模拟光源与物体表面之间的光交互,而材质则定义了物体表面对这些光线的响应。深入理解光照模型和材质属性对于创建逼真的3D图形至关重要。本章将介绍多种光照模型,包括Phong光照模型、Blinn-Phong光照模型、Cook-Torrance光照模型和Lambert光照模型,并对材质进行详细讲解。

5.1 光照模型基础

       光照模型用于计算场景中物体的光照效果,考虑光源的类型、物体表面的材质属性以及光源与物体之间的相对位置。以下是几种常见的光照模型:

  1. 环境光(Ambient Light)

    • 定义:环境光是均匀照射在场景中所有表面的光线,模拟环境中的背景光。它不依赖于光源的位置,通常用于为所有表面提供一个基本的光照水平。

    • 计算:环境光的强度是恒定的,通常由一个固定的环境光强度系数和光源颜色相乘得到。例如:

      vec3 ambient = ambientStrength * lightColor;
      
  2. 漫反射光(Diffuse Light)

    • 定义:漫反射光模拟光源照射到粗糙表面上的光线,光的强度取决于光线与表面法线之间的夹角。漫反射光的强度与光源到表面的角度和距离有关。

    • 计算:漫反射光的强度可以通过光线与表面法线的点积来计算,即:

      vec3 norm = normalize(Normal);
      vec3 lightDir = normalize(lightPos - FragPos);
      float diff = max(dot(norm, lightDir), 0.0);
      vec3 diffuse = diff * lightColor;
      
  3. 镜面反射光(Specular Light)

    • 定义:镜面反射光模拟光线在光滑表面上的高光反射。镜面反射光的强度取决于视角和光源之间的角度。

    • 计算:镜面反射光的强度可以通过视角与反射方向的点积来计算,通常使用一个光泽度因子来调整高光的强度。例如:

      float specularStrength = 0.5;
      vec3 viewDir = normalize(viewPos - FragPos);
      vec3 reflectDir = reflect(-lightDir, norm);
      float spec = pow(max(dot(viewDir, reflectDir), 0.0), shininess);
      vec3 specular = specularStrength * spec * lightColor;
      
光照模型示意图
  • 环境光:展示环境光的均匀分布对物体表面的照射。
  • 漫反射光:展示光源照射到粗糙表面时的光线散射效果。
  • 镜面反射光:展示光源在光滑表面上的高光效果和视角对高光的影响。
5.2 Phong光照模型

       Phong光照模型是计算机图形学中一种经典的光照模型,它结合了环境光、漫反射光和镜面反射光,提供了一个全面的光照解决方案。Phong模型的公式如下:

 

其中:

  • I 是最终的光照强度。
  • I_{_{a}}是环境光强度。
  • I_{b} 是漫反射光强度。
  • I{_{s}}是镜面反射光强度。
  • K{_{a}}是环境反射系数。
  • K{_{d}}​ 是漫反射反射系数。
  • K{_{s}}​ 是镜面反射系数。
  • norm 是表面法线。
  • lightDir是光源方向。
  • viewDir是视角方向。
  • reflectDir 是反射方向。
  • shininess 是材质的光泽度。
    Phong光照模型示意图

示例:Phong光照模型的GLSL代码

  • 顶点着色器代码
#version 330 corelayout(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() {FragPos = vec3(model * vec4(aPos, 1.0)); // 计算片段位置Normal = mat3(transpose(inverse(model))) * aNormal; // 计算变换后的法线gl_Position = projection * view * vec4(FragPos, 1.0); // 计算最终位置
}
  • 片段着色器代码
#version 330 corein vec3 FragPos; // 从顶点着色器接收的片段位置
in vec3 Normal; // 从顶点着色器接收的法线out vec4 FragColor; // 片段的最终颜色uniform vec3 lightPos; // 光源位置
uniform vec3 viewPos; // 观察者位置
uniform vec3 lightColor; // 光源颜色
uniform vec3 objectColor; // 物体颜色void main() {// 环境光float ambientStrength = 0.1;vec3 ambient = ambientStrength * lightColor;// 漫反射光vec3 norm = normalize(Normal);vec3 lightDir = normalize(lightPos - FragPos);float diff = max(dot(norm, lightDir), 0.0);vec3 diffuse = diff * lightColor;// 镜面反射光float specularStrength = 0.5;vec3 viewDir = normalize(viewPos - FragPos);vec3 reflectDir = reflect(-lightDir, norm);float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32);vec3 specular = specularStrength * spec * lightColor;// 合成最终颜色vec3 result = (ambient + diffuse + specular) * objectColor;FragColor = vec4(result, 1.0);
}

解释

  • 顶点着色器
    • FragPos:计算片段在世界空间中的位置。
    • Normal:计算片段的法线,考虑模型的变换。
  • 片段着色器
    • ambient:环境光的贡献。
    • diffuse:漫反射光的贡献,计算光线与表面法线的夹角。
    • specular:镜面反射光的贡献,计算视角和反射方向的夹角。
    • FragColor:最终颜色的合成,包括环境光、漫反射光和镜面反射光。
5.3 Blinn-Phong光照模型

       Blinn-Phong光照模型是对Phong模型的改进,主要目的是提高计算效率。Blinn-Phong模型用半角向量(lightDir + viewDir的归一化向量)代替了Phong模型中的反射向量来计算镜面反射光,这可以减少计算复杂度,特别是在处理大量光源时。

公式

 

其中:

  • halfVec 是光线方向和视角方向的半角向量,即:
Blinn-Phong光照模型的效果图

 

示例:Blinn-Phong光照模型的GLSL代码

  • 顶点着色器代码:与Phong模型相同。

  • 片段着色器代码

#version 330 corein vec3 FragPos; // 从顶点着色器接收的片段位置
in vec3 Normal; // 从顶点着色器接收的法线out vec4 FragColor; // 片段的最终颜色uniform vec3 lightPos; // 光源位置
uniform vec3 viewPos; // 观察者位置
uniform vec3 lightColor; // 光源颜色
uniform vec3 objectColor; // 物体颜色void main() {// 环境光float ambientStrength = 0.1;vec3 ambient = ambientStrength * lightColor;// 漫反射光vec3 norm = normalize(Normal);vec3 lightDir = normalize(lightPos - FragPos);float diff = max(dot(norm, lightDir), 0.0);vec3 diffuse = diff * lightColor;// 镜面反射光(Blinn-Phong)float specularStrength = 0.5;vec3 viewDir = normalize(viewPos - FragPos);vec3 halfVec = normalize(lightDir + viewDir);float spec = pow(max(dot(norm, halfVec), 0.0), 32);vec3 specular = specularStrength * spec * lightColor;// 合成最终颜色vec3 result = (ambient + diffuse + specular) * objectColor;FragColor = vec4(result, 1.0);
}

解释

  • Blinn-Phong模型中,镜面反射光使用halfVec来代替reflectDir,计算更为高效。
5.4 Cook-Torrance光照模型

       Cook-Torrance光照模型是一种基于物理的光照模型,提供了更为真实的光照效果。它考虑了光线在表面上的微观粗糙度,并引入了菲涅尔反射效应。

公式

其中:

  • F 是菲涅尔反射项,计算反射的强度。
  • G 是几何遮蔽项,考虑表面粗糙度对光照的影响。

示例:Cook-Torrance光照模型的GLSL代码

#version 330 corein vec3 FragPos; // 从顶点着色器接收的片段位置
in vec3 Normal; // 从顶点着色器接收的法线out vec4 FragColor; // 片段的最终颜色uniform vec3 lightPos; // 光源位置
uniform vec3 viewPos; // 观察者位置
uniform vec3 lightColor; // 光源颜色
uniform vec3 objectColor; // 物体颜色// 菲涅尔反射项
float Fresnel(float cosTheta) {float f0 = 0.04; // 玻璃的菲涅尔反射return f0 + (1.0 - f0) * pow(1.0 - cosTheta, 5.0);
}// 几何遮蔽项
float Geometry(float NdotH, float roughness) {float k = pow(roughness + 1.0, 2.0) / 8.0;return NdotH / (NdotH * (1.0 - k) + k);
}void main() {// 环境光float ambientStrength = 0.1;vec3 ambient = ambientStrength * lightColor;// 漫反射光vec3 norm = normalize(Normal);vec3 lightDir = normalize(lightPos - FragPos);float diff = max(dot(norm, lightDir), 0.0);vec3 diffuse = diff * lightColor;// 镜面反射光(Cook-Torrance)vec3 viewDir = normalize(viewPos - FragPos);vec3 halfVec = normalize(lightDir + viewDir);float NdotH = max(dot(norm, halfVec), 0.0);float F = Fresnel(dot(viewDir, halfVec));float G = Geometry(NdotH, 0.5);vec3 specular = F * G * lightColor;// 合成最终颜色vec3 result = (ambient + diffuse + specular) * objectColor;FragColor = vec4(result, 1.0);
}

解释

  • Cook-Torrance模型更为复杂,考虑了菲涅尔反射效应和几何遮蔽,适用于需要高度真实感的渲染。
5.5 Lambert光照模型

       Lambert光照模型是一种简单的漫反射光照模型,基于Lambert余弦定律。它假设光线均匀地散射在表面上,使得每个点的光照强度与光线和表面法线的夹角余弦成正比。

公式

示例:Lambert光照模型的GLSL代码

#version 330 corein vec3 FragPos; // 从顶点着色器接收的片段位置
in vec3 Normal; // 从顶点着色器接收的法线out vec4 FragColor; // 片段的最终颜色uniform vec3 lightPos; // 光源位置
uniform vec3 lightColor; // 光源颜色
uniform vec3 objectColor; // 物体颜色void main() {// 漫反射光(Lambert)vec3 norm = normalize(Normal);vec3 lightDir = normalize(lightPos - FragPos);float diff = max(dot(norm, lightDir), 0.0);vec3 diffuse = diff * lightColor;// 合成最终颜色vec3 result = diffuse * objectColor;FragColor = vec4(result, 1.0);
}

解释

  • Lambert模型非常简单,只考虑漫反射光,适合需要快速计算的应用。
5.6 材质属性的深入讲解

       材质属性定义了物体表面的光照响应特性,包括环境反射、漫反射和镜面反射。以下是材质属性的详细介绍:

  1. 环境反射(Ambient Reflectance)

    • 定义:环境反射决定了材质对环境光的响应能力。通常较低的环境反射系数会使物体看起来较为暗淡。
    • 计算:环境反射的计算包括环境光强度和材质的环境反射颜色。
  2. 漫反射(Diffuse Reflectance)

    • 定义:漫反射决定了材质对漫射光的响应能力。粗糙表面的漫反射效果通常比光滑表面更为明显。
    • 计算:漫反射光的强度基于光源方向和表面法线之间的夹角。光源和表面法线的点积用于计算漫反射光的贡献。
  3. 镜面反射(Specular Reflectance)

    • 定义:镜面反射决定了材质对镜面光的响应能力。光滑的表面会产生更强的镜面反射效果。
    • 计算:镜面反射的强度基于视角和反射方向之间的夹角。光泽度控制高光的集中程度和强度。
  4. 光泽度(Shininess)

    • 定义:光泽度控制镜面反射的高光强度。高光泽度会产生更加集中和锐利的高光效果。
    • 计算:光泽度的计算通常通过指数函数来调整高光的强度,影响镜面反射的最终效果。

示例:材质属性的GLSL代码

#version 330 corein vec3 FragPos; // 从顶点着色器接收的片段位置
in vec3 Normal; // 从顶点着色器接收的法线out vec4 FragColor; // 片段的最终颜色uniform vec3 lightPos; // 光源位置
uniform vec3 viewPos; // 观察者位置
uniform vec3 lightColor; // 光源颜色
uniform vec3 materialAmbient; // 材质环境反射
uniform vec3 materialDiffuse; // 材质漫反射
uniform vec3 materialSpecular; // 材质镜面反射
uniform float materialShininess; // 材质光泽度void main() {// 环境光float ambientStrength = 0.1;vec3 ambient = ambientStrength * materialAmbient * lightColor;// 漫反射光vec3 norm = normalize(Normal);vec3 lightDir = normalize(lightPos - FragPos);float diff = max(dot(norm, lightDir), 0.0);vec3 diffuse = diff * materialDiffuse * lightColor;// 镜面反射光float specularStrength = 0.5;vec3 viewDir = normalize(viewPos - FragPos);vec3 reflectDir = reflect(-lightDir, norm);float spec = pow(max(dot(viewDir, reflectDir), 0.0), materialShininess);vec3 specular = specularStrength * spec * materialSpecular * lightColor;// 合成最终颜色vec3 result = ambient + diffuse + specular;FragColor = vec4(result, 1.0);
}

解释

  • 材质属性:包括环境反射、漫反射、镜面反射和光泽度,影响物体在不同光照条件下的视觉效果。
  • 环境反射:决定物体在暗环境中的基础亮度。
  • 漫反射:影响物体在光源照射下的亮度分布。
  • 镜面反射:影响高光的强度和集中度。
  • 光泽度:控制镜面反射的锐利程度。

小结

       本章介绍了光照和材质的基本概念及其在GLSL中的实现,包括环境光、漫反射光和镜面反射光的计算方法。通过实现各种光照模型,我们可以创建更加逼真的3D场景。掌握光照和材质的编程技巧有助于提升渲染效果的真实感和视觉效果,为复杂场景的开发奠定了基础。

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

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

相关文章

政安晨【零基础玩转各类开源AI项目】基于Ubuntu系统部署LivePortrait :通过缝合和重定向控制实现高效的肖像动画制作

目录 项目论文介绍 论文中实际开展的工作 非扩散性的肖像动画 基于扩散的肖像动画 方法论 基于Ubuntu的部署实践开始 1. 克隆代码并准备环境 2. 下载预训练权重 3. 推理 快速上手 驱动视频自动裁剪 运动模板制作 4. Gradio 界面 5. 推理速度评估 社区资源 政安…

electron安装及快速创建

electron安装及快速创建 electron是一个使用 JavaScript、HTML 和 CSS 构建桌面应用程序的框架。 详细内容见官网:https://www.electronjs.org/zh/docs/latest/。 今天来记录下练习中的安装过程和hello world的创建。 创建项目文件夹,并执行npm 初始化命…

迅雷强制升级,漠视用户权力

用着迅雷,突然闪退,弹出升级界面。没有任何经过我的同意和操作,直接退出,强制升级。非常的蛮横和强硬。 升级完成之后,弹出一个提示框,提示框里有一个启动按钮,和一个加入开机自启的勾选框。意…

【Python实战】Google Chrome的离线小恐龙游戏

文章目录 Google Chrome的离线小恐龙游戏项目结构大纲 📊👣逐步编码过程 🧩💡第一步:项目初始化与主程序框架第二步:实现T-Rex的跳跃功能第三步:添加障碍物和碰撞检测第四步:添加得分…

前端面试项目细节重难点分享(十三)

面试题提问:分享你最近做的这个项目,并讲讲该项目的重难点? 答:最近这个项目是一个二次迭代开发项目,迭代周期一年,在做这些任务需求时,确实有很多值得分享的印象深刻的点,我讲讲下面…

go语言学习文档精简版

Go语言是一门开源的编程语言,目的在于降低构建简单、可靠、高效软件的门槛。Go平衡了底层系统语言的能力,以及在现代语言中所见到的高级特性。 你好,Go package main // 程序组织成包import "fmt" // fmt包用于格式化输出数据// …

排序算法详解

​ 💎所属专栏:数据结构与算法学习 💎 欢迎大家互三:2的n次方_ 🍁1. 插入排序 🍁1.1 直接插入排序 插入排序是一种简单直观的排序算法,它的原理是通过构建有序序列,对于未排序数…

使用 Visual Studio 2022 自带的 cl.exe 测试编译 opencv helloworld

1. 参考博客&#xff1a;https://blog.csdn.net/yangSHU21/article/details/130237669( 利用OpenCV把一幅彩色图像转换成灰度图 )( 代码用的此博客的&#xff0c;就改了下图片文件路径而已 )。 2. 编译探索步骤&#xff1a; test.cpp&#xff1a; #include <iostream>…

Golang | Leetcode Golang题解之第283题移动零

题目&#xff1a; 题解&#xff1a; func moveZeroes(nums []int) {left, right, n : 0, 0, len(nums)for right < n {if nums[right] ! 0 {nums[left], nums[right] nums[right], nums[left]left}right} }

单证不一致清关难题 | 国际贸易综合服务平台 | 箱讯科技

什么是单证一致&#xff1f; 单证一致出口方所提供的所有单据要严格符合进口方开证银行所开信用证的要求&#xff0c;或者说出口方制作和提供的所有与本项货物买卖有关的单据&#xff0c;与进口方申请开立的信用证对单据的要求完全吻合&#xff0c;没有矛盾。 添加图片注释&am…

【Stable Diffusion】(基础篇四)—— 模型

模型 本系列博客笔记主要参考B站nenly同学的视频教程&#xff0c;传送门&#xff1a;B站第一套系统的AI绘画课&#xff01;零基础学会Stable Diffusion&#xff0c;这绝对是你看过的最容易上手的AI绘画教程 | SD WebUI 保姆级攻略_哔哩哔哩_bilibili 本文主要讲解如何下载和使…

Spire.PDF for .NET【文档操作】演示:在 PDF 中添加、隐藏或删除图层

PDF 图层是一种将 PDF 文件的内容按图层排列的功能&#xff0c;允许用户在同一个 PDF 文件中选择性地将某些内容设置为可见&#xff0c;将其他内容设置为不可见。PDF 图层是分层艺术品、地图和 CAD 图纸中使用的常见元素。本文将演示如何使用Spire.PDF for .NET以编程方式在 PD…

分类常用的评价指标-二分类/多分类

二分类常用的性能度量指标 精确率、召回率、F1、TPR、FPR、AUC、PR曲线、ROC曲线、混淆矩阵 「精确率」查准率 PrecisionTP/(TPFP) 「召回率」查全率RecallTP/(TPFN) 「真正例率」即为正例被判断为正例的概率TPRTP/(TPFN) 「假正例率」即为反例被判断为正例的概率FPRFP/(TNFP)…

唯众物联网(IOT)全功能综合实训教学解决方案

一、引言 在信息技术日新月异的今天&#xff0c;物联网&#xff08;IoT&#xff09;作为推动数字化转型的关键力量&#xff0c;其触角已延伸至我们生活的方方面面&#xff0c;深刻地重塑了工作模式、生活习惯乃至社会结构的每一个角落。面对这一前所未有的变革浪潮&#xff0c…

Java的类加载机制

Java的类加载机制是指将类的字节码文件&#xff08;.class文件&#xff09;加载到JVM中并将其转换为Class对象的过程。这个过程由类加载器&#xff08;ClassLoader&#xff09;完成。Java的类加载机制具有动态性和灵活性&#xff0c;使得Java能够支持动态加载类、实现模块化开发…

day4 vue2以及ElementUI

创建vue2项目 可能用到的命令行们 vue create 项目名称 // 创建项目 cd 项目名称 // 只有进入项目下&#xff0c;才能运行 npm run serve // 运行项目 D: //切换盘符 更改 Vue项目的端口配置 基础语法 项目创建完成之后&#xff0c;会有一个组件HelloWorld.vue&#xff0c;…

推动智慧交通建设,边缘计算赋能交通信号灯数据处理与决策能力

随着智慧城市建设的快速发展&#xff0c;智慧交通已成为城市发展的重要组成项目。智慧交通旨在通过大数据、人工智能、物联网等先进技术&#xff0c;实现交通系统的全面感知、智能分析、主动服务和协同管理。边缘计算在交通信号灯物联网应用中展现了交通信号灯数据处理与决策能…

手机怎么设置不同的ip地址

在数字化日益深入的今天&#xff0c;智能手机已成为我们生活、工作和学习中不可或缺的设备。然而&#xff0c;随着网络应用的广泛和深入&#xff0c;我们有时需要为手机设置不同的IP地址来满足特定需求。比如&#xff0c;避免网络限制、提高网络安全、或者进行网络测试等。本文…

内网对抗-隧道技术篇防火墙组策略HTTP反向SSH转发出网穿透CrossC2解决方案

知识点&#xff1a; 1、C2/C2上线-CrossC2插件-多系统平台支持 2、隧道技术篇-应用层-SSH协议-判断&封装&建立&穿透 3、隧道技术篇-应用层-HTTP协议-判断&封装&建立&穿透隧道技术主要解决网络通讯问题&#xff1a;遇到防火墙就用隧道技术&#xff0c;…

Ubuntu设置网络

进入网络配置文件夹 cd /etc/netplan 使用 vim 打开下的配置文件 打开后的配置 配置说明&#xff1a; network:# 网络配置部分ethernets:# 配置名为ens33的以太网接口ens33:addresses:# 为ens33接口分配IP地址192.168.220.30&#xff0c;子网掩码为24位- 192.168.220.30/24n…