如何将平面阴影应用于 RGB 颜色?

Posted

技术标签:

【中文标题】如何将平面阴影应用于 RGB 颜色?【英文标题】:How to apply flat shading to RGB colors? 【发布时间】:2015-05-26 07:09:33 【问题描述】:

我正在创建一个小型 3D 渲染应用程序。我决定对我的三角形使用简单的平面着色 - 只需计算面法线和光源之间角度的余弦值,并以此来缩放光强度。

但我不确定我应该如何将阴影系数应用于我的 RGB 颜色。

例如,想象某个与光源成 60 度角的表面。 cos(60°) = 0.5,所以我应该只保留发射光的一半能量。

我可以简单地按该系数缩放 RGB 值,如下面的伪代码所示:

double shade = cos(angle(normal, lightDir))
Color out = new Color(in.r * shade, in.g * shade, in.b * shade)

但即使在较小的角度下,生成的颜色也会变得太暗。经过一番思考,这似乎是合乎逻辑的——我们的眼睛感知到光能的对数(这就是为什么我们在明亮的白天和夜晚都能看到的原因)。并且 RGB 值已经代表了对数比例。

我的下一个尝试是使用线性/对数洞察力。理论上:

output energy = lg(exp(input energy) * shade)

这可以简化为:

output energy = lg(exp(input energy)) + lg(shade)
output energy = input energy + lg(shade)

所以这样的阴影只是将阴影系数的对数(负数)添加到 RGB 值:

double shade = lg(cos(angle(normal, lightDir)))
Color out = new Color(in.r + shade, in.g + shade, in.b + shade)

这似乎可行,但它正确吗?在真实的渲染管线中是如何做到的?

【问题讨论】:

【参考方案1】:

    颜色 RGB 向量乘以阴影系数

    您最初假设的余弦值。对数缩放由目标成像设备和人眼完成

    如果你的颜色太深,那么可能的原因是:

    余弦或角度值被截断为整数 或者您的管道没有线性比例输出(一些伽马校正可以做到这一点) 或者你的某个地方有错误 或者您的角度和余弦使用不同的度量(弧度/度) 您忘记将环境光系数添加到阴影值中 您的向量是相反的或错误的(目视检查它们,请参阅第一个链接了解如何) 您的矢量不在同一个坐标系中(光线通常在 GCS 中,而 LCS 模型中的法线矢量,因此您需要将其中至少一个转换为另一个的坐标系)

    cos(angle) 本身通常不通过余弦计算

    当您将所有数据作为向量时,只需使用点积

    double shade = dot(normal, lightDir)/(|normal|.|lightDir|)
    

    如果向量是单位大小,那么您可以放弃按大小划分...这就是正常和光向量被归一化的原因...

    一些相关问题和注意事项

    Normal shading 这可能会启发一两件事(对于初学者) Normal/Bump mapping 查看片段着色器并搜索 dot mirrored light 查看稍微复杂的照明方案

    GCS/LCS表示全局/局部坐标系

【讨论】:

感谢您的全面回答!但是你能再解释一下第二点吗?我四处阅读,发现线性 RGB 和 sRGB 之间的区别——后者似乎是前者的日志版本。我认为我提供给绘图 api 的 RGB 值是 sRGB,因此是我的问题。 确实,java 的 Color 文档明确声明它使用 sRGB。 @Rogach 首先忘记 RGB/sRGB,由于硬件功能和与旧东西的兼容性,大多数 API 使用对数输出方案。如果您创建从 0.0 到 1.0 的线性渐变,则阴影是线性的,因此您渲染的 RGB 值可以视为线性。实际上,我们的感官具有对数刻度,而硬件是以对数刻度输出的方式构建的(我的意思是,缩放是由硬件和眼睛完成的)这是因为很长一段时间以来,我们并不知道我们的在光度测量出现之前,视力也是对数的。这就是为什么恒星尺度大小是一样的...... @Rogach 和成像设备已经构建/使用,因此行业保持原样(由于兼容性),只是术语略有变化

以上是关于如何将平面阴影应用于 RGB 颜色?的主要内容,如果未能解决你的问题,请参考以下文章

Revit 平面图常规模型怎么换颜色

平面设计中的金色字体是怎么调的,RGB或者CMYK值是多少

DirectX学习笔记:利用平面着色和Gouraud着色模式绘制具有颜色的三角形

在场景包中的透明地板/平面上显示阴影

3D光照阴影 平面阴影矩阵推导及代码实现

3D光照阴影 平面阴影矩阵推导及代码实现