OpenGL笔记十五:GLSL光照计算

前言

期待您移步上篇:OpenGL笔记十四:GLSL语法

顶点着色器

  • 业务

1.矩阵变换位置
2.计算光照公式⽣成逐顶点颜⾊
3.⽣成/变换纹理坐标

  • 总结: 它可以⽤于执⾏⾃定义计算,实施新的变换,照明或者传统的固定功能所不允许的基于顶点的效果。
  • 内建特殊变量

gl_VertexID ,是一个输入变量。用于保存顶点的整数索引。gl_VertexID 是整数型变量,用 highp 精度限定修饰符声明。
gl_InstanceID ,是一个输入变量。用于保存实例化绘图调用中图元的实例编号。对于常规的绘图调用,该值为0;gl_InstanceID 是整数型变量,用 highp 精度限定修饰符声明。
gl_Position ,用于输出顶点位置的裁剪坐标。该值在裁剪和视口变换用于执行相应的图元裁剪以及从裁剪坐标到屏幕坐标的顶点位置转换。如果顶点着色器位写入 gl_Position ,则 gl_Position 的值未定义。 gl_Position 是浮点型变量,用 highp 精度限定修饰符声明。
gl_PointSize ,可以写入像素标识点精灵(即像素点)的尺寸,在渲染点精灵时使用。顶点着色器输出的 gl_PointSize 值被限定在 OpenGL ES 3.0 实现支持的费平滑点大小范围之内。gl_PointSize 是浮点型变量,用 highp 精度限定修饰符声明。
gl_FrontFacing ,是一个特殊变量,但不是由顶点着色器直接写入的,而是根据顶点着色器生成的位置值和渲染图元的类型生成的。gl_FrontFacing 是一个布尔值类型。

在顶点着色器内可用的唯一内键 Uniform 状态是窗口坐标中的深度范围。这些由内建统一变量名 gl_DepthRange 给出。

struct gl_DepthRangeParameters 
{
  highp float near; //near z
  highp float far; //near far
  highp float diff; //far - near 
}
uniform gl_DepthRangeParameters gl_DepthRange;
  • 内建常量
 const mediump int gl_MaxVertexAttribs = 16;
 const mediump int gl_MaxVertexUniformVectors = 256;
 const mediump int gl_MaxVertexOutputVectors = 16;
 const mediump int gl_MaxVertexTextureImageUnits = 16;
 const mediump int gl_MaxCombinedTextureImageUnits = 32;

gl_MaxVertexAttribs :可以指定得顶点数据的最大数量。
gl_MaxVertexUniformVectors :顶点着色器可以使用的 vect4 Uniform 变量的最大数量。
gl_MaxVertexOutputVectors :输出向量的最大数量。
gl_MaxVertexTextureImageUnits :顶点着色器可用纹理单元的最大数量。
gl_MaxCombinedTextureImageUnits :顶点/片元着色器中的可用纹理单元的最大数量的总和。

  • 矩阵变换
    MVP矩阵(模型-视图-投影矩阵) 顶点着色器的位置输入保存的是物体坐标,而输出的坐标保存为剪裁坐标。MVP矩阵是3D图形中进行这种变化的3个非常重要的变换矩阵的乘积:模型矩阵,视图矩阵和投影矩阵。

组成MVP矩阵的每个单独矩阵执行的变换如下

  • 模型矩阵 -- 将物体坐标变换为世界坐标
  • 视图矩阵 -- 将世界坐标变换为眼睛坐标(观察坐标)
  • 投影矩阵 -- 讲眼睛坐标(观察者坐标)变换为裁剪坐标

片元着色器

  • 业务

1.计算颜⾊
2.获取纹理值
3.往像素点中填充颜⾊值(纹理值/颜⾊值)

  • 总结: 它可以⽤于图⽚/视频/图形中每个像素的颜⾊填充(⽐如给视频添加滤镜,实际上就是将视频中每个图⽚的像素点颜⾊填充进⾏修改)。
  • 内建特殊变量

gl_FragCoord :片元着色器中一个只读变量,这个变量保存片元的窗口相对坐标。
gl_FrontFacing :片元着色器中额的一个只读变量,为布尔类型变量,正面图元时为true,否则为false。
gl_PointCoord :只读变量,可以在渲染点精灵使用,保存点精灵的纹理坐标,这个坐标在点精灵光栅化期间自动生成,处于(0,1)区间。
gl_FragDepth :一个只写输出变量,在片元着色器写入时,覆盖片元的固定功能深度值。尽量减少手动实现深度值写入。这个功能需要谨慎使用,因为它可能禁用许多GPU的深度优化。例如:许多GPU都有"Early -Z"的功能,在执行片元着色器之前进行深度测试,使用"Early -Z"的好处就是不能通过深度测试的片元就不会被着色(从而减少了着色器调用次数,提高性能),但是使用 gl_FragDepth 就必须禁用该功能,因为GPU在执行着色器之前不知道深度值。

  • 内建常量
const mediump int gl_MaxFragmentInputVectors = 15;
 const mediump int gl_MaxTextureImageUnits = 16;
 const mediump int gl_MaxFragmentUniformVectors = 224;
 const mediump int gl_MaxDrawBuffers = 4;
 const mediump int gl_MinProgramTexelOffset = -8;
 const mediump int gl_MaxProgramTexelOffset = 7;

gl_MaxFragmentInputVectors :片元着色器输入的最大数量
gl_MaxFragmentUniformVectors :可用纹理图像单元的最大数量
gl_MaxFragmentUniformVectors :片元着色器可用vec4 Uniform变量的最大数量
gl_MaxDrawBuffers :多重渲染目标最大支持数量

  • 多个纹理单元渲染
  • 1.片元着色器(服务端)代码:
 attribute vec2 v_texCoord;
 uniform sampler2D s_baseMap;
 uniform sampler2D s_SecondMap;
 void main() {
 vec4 baseColor;
 vec4 secondColor;
 baseColor = texture(s_baseMap,v_texCoord);
 secondColor = texture(s_SecondMap,v_texCoord);
 gl_FragColor = baseColor * secondColor;
}
  • 2.客户端代码:
//将各个纹理对象绑定到纹理单元0和1,为采样器设置数 值,将采集器绑定到对应的纹理单元
glActiveTexutre(GL_TEXTURE0);
glBindTeture(GL_TEXTURE_2D,baseMapTexId);
glUniformli(baseMapTexId,0);
glActiveTexutre(GL_TEXTURE1);
glBindTeture(GL_TEXTURE_2D,secondMapTexId);
glUniformli(secondMapTexId,1);
  • 内建函数
    常⽤内建函数:

dot :点乘
cross :叉乘
texture2D :⽤于对纹理采样
normalize :对⼀个向量规格化
clamp :将⼀个向量固定在⼀个最⼩值和最⼤值之间

光照特性

  • 发射光:由物体⾃⾝发光
  • 环境光:就是在环境中充分散射的光,⽽且⽆法分辨它的⽅向
  • 漫反射光:光线来⾃某个⽅向,但在物体上各个⽅向反射
  • 镜⾯⾼光:光线来⾃⼀个特定的⽅向,然后在物体表⾯上以⼀个特定的 ⽅向反射出去

材质属性

  • 泛射材质
  • 漫反射材质
  • 镜⾯反射材质
  • 发射材质

光照计算

1.环境光的计算

环境光 = 环境因子 * 物体的材质颜⾊

2.发射光的计算

发射颜⾊ = 物体的反射材质颜⾊

3.漫反射光计算

漫反射颜⾊ = 光源的漫反射颜⾊ * 物体的漫发射材质颜⾊ * DiffuseFactor

DiffuseFactor = max(0,dot(N,L))

漫反射因⼦DiffuseFactor 是光线 与顶点法线向量的点积

4.镜⾯光计算

镜⾯反射颜⾊ = 光源的镜⾯光的颜⾊ * 物体的镜⾯材质颜⾊ * SpecularFactor

SpecularFactor = power(max(0,dot(N,H)),shininess)

H :视线向量E 与 光线向量L 的半向量
dot(N,H) :H,N的点积⼏何意义,平⽅线与法线夹⻆角的cos值
shiniess : ⾼光的反光度

光照计算

光照颜⾊ = (环境颜⾊ + 漫反射颜⾊ + 镜⾯反射颜⾊) * 衰减因⼦

衰减因⼦

衰减因⼦ = 1.0/(距离衰减常量 + 线性衰减常量 * 距离 + ⼆次衰减常量 * 距离的平⽅)

注:

  • 距离衰减常量,线性衰减常量和⼆次衰减常量均为常量值
  • 环境光,漫反射光和镜⾯光的强度都会受距离的增⼤⽽衰减,只有发射光和全局环境光的强度不会受影响

聚光灯因⼦

聚光灯夹⻆角cos值 = power(max(0,dot(单位光源位置,单位光线向量)),聚光灯指数)

  • 单位光线向量是从光源指向顶点的单位向量
  • 聚光灯指数,表示聚光灯的亮度程度
  • 公式解读:单位光源位置 * 单位光线向量 点积 的 聚光灯指数次⽅

增加过渡计算

聚光灯因⼦ = clamp((外环的聚光灯⻆角度cos值 - 当前顶点的聚光灯⻆角度cos值)/ (外环的聚光灯⻆角度cos值- 内环聚光灯的⻆角度的cos值),0,1)

光照计算终极公式

光照颜⾊ = 发射颜⾊ + 全局环境颜⾊ + (环境颜⾊ + 漫反射颜⾊ + 镜⾯反 射颜⾊) * 聚光灯效果 * 衰减因⼦

期待您移步下篇:OpenGL笔记十六:CAEmitterLayer粒子效果

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,492评论 6 513
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,048评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,927评论 0 358
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,293评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,309评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,024评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,638评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,546评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,073评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,188评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,321评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,998评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,678评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,186评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,303评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,663评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,330评论 2 358