请选择 进入手机版 | 继续访问电脑版

开源计算机图形学社区(Open Source Computer Graphics Community) |OpenGPU Forum (2007-2013)| OpenGPU Project

 找回密码
 注册
搜索
查看: 167|回复: 1

UE4是如何计算点光源,平行光源产生的最终颜色的? [复制链接]

Rank: 5Rank: 5

注册时间
2015-10-17
积分
58
发表于 2017-12-19 19:16:59 |显示全部楼层
渲染一个场景最简单的像素着色器是这样的:
outColor = diffuseColor * Normal dot Light。
这是最简单的lambert着色模型。
在UE4中,引入了PBR的渲染方法,其中有很多来自于离线渲染中的概念。我尝试在网络上查找相关的很多知识,但是解释大多是晦涩难懂的,很难跟现实对应起来。比如UE4中计算上面的漫反射颜色用到了这个函数

float3 Diffuse_Lambert( float3 DiffuseColor )
{
        return DiffuseColor * (1 / PI);
}


这种函数被称做BRDF,即给定出射和入射角计算反射后原光线发生的变化。我现在的理解是这样的:用brdf可以求得某一点上反射得来自某个特定角度得光线,然后对四面八方得光线求积分,再对一个像素上能看到得所有得这些点产生得颜色积分,这样一个双重得积分来得到最终屏幕上显示出来得颜色。我不知道我哪里理解得有问题,但是按照我现在得理解,利用这个BRDF在各个方向上采样很多次才可以得到最终得颜色。我浏览过很多离线渲染相关得资料,大概了解离线渲染使用一种叫做蒙特卡洛得方法来对这些BRDF进行采样跟积分,然而这种方法原本是用来造原子弹得,所以它非常得慢,不适合实时渲染。我不知道UE4这种实时的游戏引擎如何做这个积分操作的,说的再直白一点,怎么把这个DiffuseColor / PI最终累积成为DiffuseColor的。我在UE4的代码中找了好长时间,我能看到的就是

float3 VolumeLighting = Diffuse_Lambert(GBuffer.DiffuseColor);
LightAccumulator_Add(LightAccumulator, VolumeLighting, (1.0/PI), LightColor * SurfaceAttenuation, bNeedsSeparateSubsurfaceLightAccumulation);


完了,但是按照我刚才的理解,至少得有个for循环之类的不是吗?我能找到的代码就是直接把这个 DiffuseColor / PI直接加到光线累计中,后面可能会再加一些specular...之类的吧。最后放到MRT[0]里面去了。那么这个它究竟是怎么做使得最终的漫反射颜色=DiffuseColor了呢?
求各路大神不吝赐教,感激不尽!

Rank: 16Rank: 16Rank: 16Rank: 16

注册时间
2010-10-30
积分
3098
发表于 2018-1-13 22:32:49 |显示全部楼层
游戏中的普通光源是一个点啊。每个点对光源唯一相交一次,所以你所谓的积分就变成了对每一个光源单独计算的累加了。蒙特卡洛积分这些一般是用在light probe这些上面的。但是一般也是预计算后存储在纹理里面的。
你没有看到for循环,是因为这些在cpu代码那边干了。

使用道具 举报

最近看过此主题的会员

您需要登录后才可以回帖 登录 | 注册

‹‹
我的工具栏

关于我们|手机版|Archiver|开源计算机图形学社区(Open Source Computer Graphics Community) | OpenGPU Project | OpenGPU Forum (2007-2013)

GMT+8, 2018-1-22 14:29 , Processed in 0.018215 second(s), 11 queries .

Powered by Discuz! X2

© 2001-2011 Comsenz Inc.

回顶部