- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在将我的 webgl 延迟渲染器转换为使用高动态范围的渲染器。我从网上的各种来源阅读了很多有关该主题的内容,并且有一些问题希望能够得到澄清。我完成的大部分阅读内容都涉及 HDR 图像渲染,但我的问题与渲染器可能需要如何更改才能支持 HDR 相关。
据我了解,HDR 本质上是试图捕捉更高的光线范围,以便我们可以在极亮或黑暗的场景中看到细节。通常在游戏中,我们使用强度 1 表示白光,使用强度 0 表示黑色。但在 HDR/现实世界中,范围要多样化得多。 IE。引擎中的太阳可能比 10 的灯泡亮 10000 倍。
为了应对这些更大的范围,您必须将渲染器转换为使用浮点渲染目标(或者理想情况下是半浮点,因为它们使用更少的内存)进行光 channel 。
我的第一个问题是关于照明的。除了浮点渲染目标之外,这是否仅仅意味着如果以前我有一个代表太阳的光,其强度为 1,那么它现在可以/应该表示为 10000?即
float spec = calcSpec();
vec4 diff = texture2D( sampler, uv );
vec4 color = diff * max(0.0, dot( N, L )) * lightIntensity + spec; //Where lightIntensity is now 10000?
return color;
照明系统是否还有其他根本性变化(除了 float 纹理和更高的范围)?
接下来,我们现在有了一个 float 渲染目标,它已经累加了所有灯光值(在如上所述的较高范围内)。此时,我可能会使用诸如Bloom之类的东西对渲染目标进行一些后期处理。完成后,现在需要对其进行色调映射,然后才能将其发送到屏幕。这是因为光线范围必须转换回我们显示器的范围。
因此,对于色调映射阶段,我可能会使用后期处理,然后使用色调映射公式将 HDR 光照转换为低动态范围。我选择的技术是《神秘海域 2》中的 John Hables:
const float A = 0.15;
const float B = 0.50;
const float C = 0.10;
const float D = 0.20;
const float E = 0.02;
const float F = 0.30;
const float W = 11.2;
vec3 Uncharted2Tonemap(vec3 x)
{
return ((x*(A*x+C*B)+D*E)/(x*(A*x+B)+D*F))-E/F;
}
... // in main pixel shader
vec4 texColor = texture2D(lightSample, texCoord );
texColor *= 16; // Hardcoded Exposure Adjustment
float ExposureBias = 2.0;
vec3 curr = Uncharted2Tonemap( ExposureBias * texColor.xyz );
vec3 whiteScale = 1.0 / Uncharted2Tonemap(W);
vec3 color = curr * whiteScale;
// Gama correction
color.x = pow( color.x, 1.0 /2.2 );
color.y = pow( color.y, 1.0 /2.2 );
color.z = pow( color.z, 1.0 /2.2 );
return vec4( color, 1.0 );
我的第二个问题与色调映射阶段有关。除了这个技术之外,还有更多的东西吗?仅仅使用更高的光强度并调整曝光就可以被认为是 HDR——还是还有更多?据我所知,有些游戏具有自动曝光功能来计算平均发光度,但在最基本的层面上是否需要这样做?想必您可以手动调整曝光?
许多文档中讨论的其他内容是 Gamma 校正。 Gamma 校正似乎是在两个区域进行的。首先是在读取纹理时,然后是在将纹理发送到屏幕时再次读取纹理。当读取纹理时,它们必须简单地更改为如下所示:
vec4 diff = pow( texture2D( sampler, uv), 2.2 );
然后在上述色调映射技术中,输出校正是通过以下方式完成的:
pow(color,1/2.2);
在 John Hables 的演讲中,他说并非所有纹理都必须像这样进行校正。漫反射纹理必须如此,但法线贴图之类的东西不一定必须如此。
我的第三个问题是关于 Gamma 校正的。为了让它发挥作用,这是必要的吗?这是否意味着我必须在读取漫反射贴图的所有地方更改引擎?
这是我目前对此次转换所涉及内容的理解。它是否正确?我是否有任何误解或错误?
最佳答案
轻量计算/累加是的,您通常可以保持闪电计算相同,并且增加方向光的强度(例如超过 1.0)当然没问题。该值可以超过一个的另一种方法是简单地将多个灯光的贡献加在一起。
色调映射
你当然理解这个概念。有很多不同的方法来进行实际的映射,从更简单/天真的方法color = clamp(hdrColor * exposure)
到您发布的更复杂(更好)的内容。
自适应色调映射很快就会变得更加复杂。同样,天真的方法是通过使用最亮的像素来简单地标准化颜色,这肯定会使得很难/不可能感知图像较暗部分的细节。您还可以平均亮度和钳位。或者您可以保存最后几帧的整个直方图并在映射中使用它们。
另一种方法是仅使用相邻像素的值来标准化每个像素,即“局部色调映射”。这通常不会在实时渲染中完成。
虽然听起来很复杂,但您发布的公式将产生非常好的结果,因此可以使用它。一旦你有了一个可行的实现,请随意在这里进行实验。还有一些很棒的论文可供使用:)
Gamma 现在,即使您不使用 hdr 渲染, Gamma 校正也很重要。但不用担心,这并不难。
最重要的是始终了解您正在使用的色彩空间。就像没有单位的数字一样,没有色彩空间的颜色几乎没有意义。现在我们喜欢在着色器中使用线性 (rgb) 颜色空间,这意味着具有两倍 rgb 值的颜色应该是两倍的亮度。然而,这不是监视器的工作方式。
相机和照片编辑软件通常只是向我们隐藏所有这些,只是以显示器喜欢的格式(称为 sRGB)保存图片。
sRGB 还有一个额外的优势,那就是压缩。我们通常以每 channel 每像素 8/16/32 位保存图像。如果您在线性空间中保存图片,并且图像中存在小但非常亮的点,则您的 8/16/32 位可能不够精确,无法保存图像较暗部分的亮度差异,并且如果您再次显示它们(当然 Gamma 正确)细节可能会在黑暗中丢失。
您可以更改许多相机和程序中保存的图像的色彩空间,即使它有时有点隐藏。因此,如果您告诉艺术家将所有图像保存在线性 (rgb) 色彩空间中,则根本不需要对图像进行 Gamma 校正。由于大多数程序(如 sRGB 和 sRGB)提供更好的压缩,因此通常最好将描述颜色的图像保存为 sRGB,因此需要对这些图像进行 Gamma 校正。描述值/数据的图像(如法线贴图或凹凸贴图)通常保存在线性颜色空间中(如果您的法线 [1.0, 0.5, 0.0] 没有 45 度角,每个人都会感到困惑;对于非颜色,压缩优势也毫无意义)。
如果您想使用 sRGB 纹理,只需告诉 OpenGL,它就会为您将其转换为线性颜色空间,而不会影响性能。
void glTexImage2D( GLenum target,
GLint level,
GLint internalFormat, // Use **GL_SRGB** here
GLsizei width,
GLsizei height,
GLint border,
GLenum format,
GLenum type,
const GLvoid * data);
哦,当然,您必须对发送到显示器的所有内容进行 Gamma 校正(因此从线性更改为 sRGB 或 Gamma 2.2)。您可以在色调映射或其他后处理步骤中执行此操作。或者让 OpenGL 为您做这件事;参见glEnable(GL_FRAMEBUFFER_SRGB)
关于opengl-es - 如何转换为 HDR 渲染器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27942736/
我正在尝试将一个字符串逐个字符地复制到另一个字符串中。目的不是复制整个字符串,而是复制其中的一部分(我稍后会为此做一些条件......) 但我不知道如何使用迭代器。 你能帮帮我吗? std::stri
我想将 void 指针转换为结构引用。 结构的最小示例: #include "Interface.h" class Foo { public: Foo() : mAddress((uint
这有点烦人:我有一个 div,它从窗口的左上角开始过渡,即使它位于文档的其他任何位置。我试过 usign -webkit-transform-origin 但没有成功,也许我用错了。有人可以帮助我吗?
假设,如果将 CSS3 转换/转换/动画分配给 DOM 元素,我是否可以检测到该过程的状态? 我想这样做的原因是因为我正在寻找类似过渡链的东西,例如,在前一个过渡之后运行一个过渡。 最佳答案 我在 h
最近我遇到了“不稳定”屏幕,这很可能是由 CSS 转换引起的。事实上,它只发生在 Chrome 浏览器 上(可能还有 Safari,因为一些人也报告了它)。知道如何让它看起来光滑吗?此外,您可能会注意
我正在开发一个简单的 slider ,它使用 CSS 过渡来为幻灯片设置动画。我用一些基本样式和一些 javascript 创建了一支笔 here .注意:由于 Codepen 使用 Prefixfr
我正在使用以下代码返回 IList: public IList FindCodesByCountry(string country) { var query =
如何设计像这样的操作: 计算 转化 翻译 例如:从“EUR”转换为“CNY”金额“100”。 这是 /convert?from=EUR&to=CNY&amount=100 RESTful 吗? 最佳答
我使用 jquery 组合了一个图像滚动器,如下所示 function rotateImages(whichHolder, start) { var images = $('#' +which
如何使用 CSS (-moz-transform) 更改一个如下所示的 div: 最佳答案 你可以看看Mozilla Developer Center .甚至还有例子。 但是,在我看来,您的具体示例不
我需要帮助我正在尝试在选中和未选中的汉堡菜单上实现动画。我能够为菜单设置动画,但我不知道如何在转换为 0 时为左菜单动画设置动画 &__menu { transform: translateX(
我正在为字典格式之间的转换而苦苦挣扎:我正在尝试将下面的项目数组转换为下面的结果数组。本质上是通过在项目第一个元素中查找重复项,然后仅在第一个参数不同时才将文件添加到结果集中。 var items:[
如果我有两个定义相同的结构,那么在它们之间进行转换的最佳方式是什么? struct A { int i; float f; }; struct B { int i; float f; }; void
我编写了一个 javascript 代码,可以将视口(viewport)从一个链接滑动到另一个链接。基本上一切正常,你怎么能在那里看到http://jsfiddle.net/DruwJ/8/ 我现在的
我需要将文件上传到 meteor ,对其进行一些图像处理(必要时进行图像转换,从图像生成缩略图),然后将其存储在外部图像存储服务器(s3)中。这应该尽可能快。 您对 nodejs 图像处理库有什么建议
刚开始接触KDB+,有一些问题很难从Q for Mortals中得到。 说,这里 http://code.kx.com/wiki/JB:QforMortals2/casting_and_enumera
我在这里的一个项目中使用 JSF 1.2 和 IceFaces 1.8。 我有一个页面,它基本上是一大堆浮点数字段的大编辑网格。这是通过 inputText 实现的页面上的字段指向具有原始值的值对象
ScnMatrix4 是一个 4x4 矩阵。我的问题是什么矩阵行对应于位置(ScnVector3),旋转(ScnVector4),比例(ScnVector3)。第 4 行是空的吗? 编辑: 我玩弄了
恐怕我是 Scala 新手: 我正在尝试根据一些简单的逻辑将 Map 转换为新 Map: val postVals = Map("test" -> "testing1", "test2" -> "te
输入: This is sample 1 This is sample 2 输出: ~COLOR~[Green]This is sample 1~COLOR~[Red]This is sam
我是一名优秀的程序员,十分优秀!