OpenGL延迟渲染:点光源实现
Posted
技术标签:
【中文标题】OpenGL延迟渲染:点光源实现【英文标题】:OpenGL deferred rendering: point light implementation 【发布时间】:2015-04-14 16:06:31 【问题描述】:我正在尝试使用 C# 和 OpenGL(使用 OpenTK)编写延迟渲染器。
但不明白我应该如何实现点光源的正常计算。
点光源片段着色器:
vec2 texCoord = gl_FragCoord.xy / ScreenSize; vec3 pixelPos = texture2D(PositionBuffer,texCoord).xyz; vec3 pixelNormal = normalize(texture2D(NormalBuffer, texCoord).xyz); vec3diffuseColor = texture2D(ColorBuffer, texCoord).xyz; vec3 toLight = LightCenter - pixelPos; 浮动衰减 = 钳位(1.0 - 长度(toLight)/LightRadius,0.0,1.0); toLight = 归一化(toLight); 浮动 nDotL = max(dot(pixelNormal, toLight),0.0); vec3diffuseLight =diffuseColor * nDotL; LightMap = LightIntensity * 衰减 * vec4(diffuseLight,1.0);结果:
看起来不错。但是光线是在一个10*10的平面上,光线的半径是5,所以光线应该几乎覆盖了这个表面。
我明白这个问题,我只是不知道如何解决它......
nDotL 的更多像素会更小,这会导致这种“伪影”。
如果我删除“* nDotL”部分,灯光看起来像这样:
在这种情况下,范围很好,但地板的底部也被点亮了......
如果有人能告诉我如何解决这个问题,我将不胜感激。
Also the source code is here if it's needed.
【问题讨论】:
衰减术语对我来说似乎有些错误。这通常不应该是 1/length(toLight) 吗?您现在所做的是在 0 和 LightRadius 之间进行线性淡出。 使用“浮动衰减=clamp(1.0 / length(toLight),0.0,1.0);”它看起来更好,但仍然有问题,因为我可以看到光球的边缘。 i.imgur.com/Vzlyj1s.png 【参考方案1】:当您结合使用 Decay + Diffuse 时,您的闪电变暗是正常的。 因为它们不是 1.0(但在 0.0,1.0 之间的某个值),如果你将两者相乘,你会得到一个更暗的结果。你应该增加光的强度。你可以这样做
lightStrength / (ConstantDecay + distance*LinearDecay + distance*distance*CuadraticDecay).
它会给你一个更柔和的衰减,并允许你增加灯光效果以照亮更大的半径。
【讨论】:
另外,您在纹理坐标上使用屏幕坐标,我认为这是故意的。 我使用的是屏幕坐标,因为我使用的是 RT-s 来渲染东西。不管怎样,谢谢你的回答,我试试看。 是的,我想知道它可能是光线追踪,但没有相机光线计算,所以我被误导了。您似乎正在使用距 3d 点光源的像素距离。您正在为灯光使用屏幕坐标,而不是光线投射的灯光位置。 vec3 toLight = LightCenter - pixelPos;您需要获取光线投射碰撞的 3D 位置。 编辑:哦,现在我明白了。你在纹理中保存了距离数据? 是的,很抱歉,我忘了提及纹理的工作原理以及它们存储的内容:/【参考方案2】:vec3 distance = toLight * (1.0 / LightRadius);
float attenuation = clamp(1 - dot(distance, distance), 0, 1);
attenuation = attenuation * attenuation;
使用这个“公式”,它看起来就像它应该的那样工作。
【讨论】:
以上是关于OpenGL延迟渲染:点光源实现的主要内容,如果未能解决你的问题,请参考以下文章