php图像去光照,11.opengl光照-常见的三种光照实现

对glBindVertexArray的理解,学习这一章节时,开始run出来的效果是黑色的立方体,检查发现在while循环中少了'glBindVertexArray(VAO)', 每执行一个不同位置的模型渲染之前,都需要重新glBindVertexArray,否则glDrawArrays等操作都是基于之前glBindVertexArray的数据。黑色的其实是关联到了lightCubeVAO(灯模型),灯模型是没有纹理贴纸的。

这一篇没有复杂的原理,对三种常见的光照做了简单的实现,还是用的opengl中光照的基本原理

一、平行光

4c5e4aa0f0f5adacc99663906530fc6b.png

平行光

1. 定义一个光线方向向量而不是位置向量来模拟一个定向光,用一个方向代替position。注意direction的方向取反,入射方向是朝向物体的,而夹角求的是入射角和法线之间的锐角。

2. 观察多个箱子对光照的反应,把前面章节中的箱子坐标copy一份

3. 实现效果

4866957

平行光

注意光照的参数改变了:

二、点光源

1. 原理介绍

1.1. 点光源:

4866957

点光源示意图

1.2.点光源特征: 点光源随着距离增大,一开始快速衰减,达到一定距离后衰减降低,100的距离几乎衰减为0.

4866957

衰减

1.3. 衰减公式:

4866957

点光源衰减

1.4. 可以通过查表来确定参数k

4866957

参数

2. 代码说明,代码改动不大,不贴完整代码了,注意平行光是directiion计算,点光源是基于position计算

2.1 片元着色器中修改光照参数

2.2 在主程序中设置常量参数,这几个参数覆盖到50的范围内了

2.3 计算光源离片元的距离

2.4 光照计算,注意环境光也需要跟着一起衰减,因为可能有多个光源,一起衰减更逼真

3. 效果

4866957

点光源效果

三、聚光,如手电筒

聚光的特点是,聚光方向特定半径内的物体会被照亮,其他部分保持黑暗。

四个参数定义聚光:1)聚光光源position; 2)灯光方向;3)切光角

1. 示意图:

4866957

聚光

LightDir:从片段指向光源的向量。

SpotDir:聚光所指向的方向。

Phiϕ:指定了聚光半径的切光角。落在这个角度之外的物体都不会被这个聚光所照亮。

Thetaθ:LightDir向量和SpotDir向量之间的夹角。在聚光内部的话θ值应该比ϕ值小。

2. 实现效果

4866957

聚光

3. 代码说明

着色器中增加聚光的参数

设置参数到着色器

主程序代码改动较小,仅附上着色器完整代码

四、聚光-平滑/软化边缘

1. 原理

上面实现的聚光,边界太清晰,和实际的光照不符,需要在边界进行平滑过渡处理。

我们可以用下面这个公式来计算这个值:

4866957

这里ϵ(Epsilon)是内(ϕ)和外圆锥(γ)之间的余弦值差(ϵ=ϕ−γ)。最终的I值就是在当前片段聚光的强度。

很难去表现这个公式是怎么工作的,所以我们用一些实例值来看看:

4866957

按照余弦值来计算比较方便,单位向量的点乘结果就是余弦值,有其他的线性差值实现也是可行的,比如按角度渐进。

这里有个技巧,用clamp可以把值归一化到0-1之间

下面的demo中,内切光是12.5,外切光角是17.5

2. 实现效果

4866957

平滑

3. 详细代码,主要是着色器中对聚光灯边缘处环状做了线性渐进的效果

主程序中增加几个角度的设置

五、三种光源的综合使用

4866957

实现效果

本文同步分享在 博客“天叔”(JianShu)。

如有侵权,请联系 support@oschina.cn 删除。

本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值