问题标签 [shadow-mapping]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
1 回答
5767 浏览

graphics - 如何为多个点光源使用单个阴影贴图?

据我了解,阴影映射是通过从灯光的角度渲染场景以创建深度图来完成的。然后从摄像机的 POV 重新渲染场景,并为场景中的每个点(GLSL 中的片段)计算从那里到光源的距离;如果它与您的阴影贴图中的内容相匹配,那么它就在光中,否则就在阴影中。

我只是在阅读本教程以了解如何使用点/全向光进行阴影映射。

根据第 12.2.2 节,它说:

我们为所有光源使用单个阴影贴图

然后在 12.3.6 下它说:

1) 计算当前像素到光源的距离平方。
...
4) 将计算出的距离值与获取的阴影贴图值进行比较,以确定我们是否处于阴影中。

这大致就是我上面所说的。

我不明白的是,如果我们将所有的灯光都烘焙到一个阴影贴图中,那么我们需要将距离与哪个灯光进行比较?烘焙到地图中的距离不应该对应任何东西,因为它是所有灯光的混合,不是吗?

我确定我遗漏了一些东西,但希望有人可以向我解释这一点。


另外,如果我们使用单个阴影贴图,我们如何为所有光源混合它?

对于单个光源,阴影贴图只存储最近物体到光源的距离(即深度图),但对于多个光源,它会包含什么?

0 投票
1 回答
2246 浏览

opengl-es - OpenGL|ES 添加阴影/阴影映射

向 3d 对象添加阴影的最简单方法是什么?

我将对象信息(顶点、texCoordinates、法线、索引)存储在数组中。

有一些框架,如iOS 的isgl3d,允许用户加载 3d .obj 文件并添加阴影,但它们添加了很多无用的东西并且不是多平台的(iOS + android)

向 3d 对象添加阴影的最简单方法是什么?
你能显示/链接到一个工作示例(iOS/Android)吗?

0 投票
1 回答
1349 浏览

opengl-es - 阴影映射 - 与光正交的薄壁上的伪影

我的背面(对光)和阴影贴图有问题,我似乎无法通过。我仍处于优化引擎的相对早期阶段,但我似乎无法到达那里,因为即使为这一几何图形手动调整了所有内容,它仍然看起来像垃圾。

它是一堵通过大约 5 块不同的墙“弯曲”的瘦墙。当我创建我的深度图时,我正在剔除正面(对光)。这肯定有帮助,但墙另一侧的正面似乎是导致 z 冲突/投影阴影的原因。

弯墙上的文物

截图上的一些注释:

  • 绘制深度纹理(来自灯光)时剔除正面
  • 我为这块几何图形调整了近平面和远平面(分别设置为 20 和 25)
  • 一个定向光源,以轻微的角度朝向场景的右侧向下照射,足以表明墙壁应该被遮蔽,但大部分是笔直向下
  • 使用非常大的 4096x4096 阴影贴图纹理
  • 所有照明都被禁用,但知道我正在做柔和的照明(因此顶点的顶点法线)即使在这面墙上

正如这里提到的,它得出的结论是,您不应该对光线背面的多边形进行阴影处理。我正在努力解决这个特殊问题,因为我不想将面部法线一直传递到片段着色器以排除那里的光线的真正背面 - 但是如果有人认为这是最好/唯一的解决方案对于这个几何,这就是我必须要做的。考虑到管道如何让面部法线通过它变得不容易/明显,这让我觉得这不是阻力最小的路径。请注意,我传递的法线是顶点法线,以允许在边缘周围产生更柔和的照明效果(可能包括非阴影和阴影表面)。

请注意,我有一些令人讨厌的Perspective Aliasing,但我希望我的下一步是处理级联阴影贴图,但如果没有解决这个问题,我觉得我只是在推迟不可避免的事情,因为我已经手动收紧了视图尽我所能(或者我认为)。

无论如何,我觉得我错过了一些东西,所以如果您有任何想法或帮助,将不胜感激!

编辑

需要明确的是,根据光线的来源,从技术上讲,墙不应该处于阴影中。

俯视图

下面是关闭阴影的图像。这只是使用顶点法线来计算漫反射照明 - 它并不漂亮(太多几何图形可见),但它确实表明某些边缘有些可见。

没有开启阴影

所以是的,墙应该在阴影中,但我希望我可以让平滑工作更好,这样边缘就可以有一些漫射照明。如果我需要将它完全置于阴影中,那么如果是将其置于阴影中的阴影贴图,或者我的代码专门将其置于阴影中,因为面法线已消失,我对此很好 - 但将面法线通过对我的顶点/片段着色器来说似乎不是阻力最小的路径。

也许这些将有助于更好地说明我的问题,或者可能会揭示我缺少的一些基本理解。

编辑#2

我在下面包含了深度纹理。您可以在左下角看到有问题的墙,从屏幕截图中您可以看到我如何将深度值修剪到 ~0.4->1。这意味着该墙的深度值从 0.4 范围开始。所以它没有完美地剪裁,但它很接近。这看起来合理吗?我很确定它是一个完整的 24 位或 32 位深度缓冲区,是 iOS 上的一个 DEPTH_COMPONENT 扩展。对于@starmole,这是否有助于确定我的投影中是否存在缩放错误?您是否认为我的地图所覆盖的大小/区域太大,因此如果它聚焦得更近可能会有所帮助?

在此处输入图像描述

0 投票
1 回答
1033 浏览

opengl - 全向阴影映射聚光灯

我在延迟渲染器中实现全向阴影映射,但无法解决这个问题:

这是一张图片:阴影问题示例

这就是当我将六个聚光灯沿正负方向指向每个轴时发生的。我知道这个问题是由聚光灯计算引起的,将灯光保持在锥体中,这就是为什么它是圆形的。

我的第一个想法是禁用锥体计算,但显然因为如果你通过一个灯看到另一个灯会混合在一起,就会有重叠。如果我将要为灯光渲染的几何形状从锥形更改为基于方形的金字塔(我认为我无论如何都需要这样做?)然后我将能够使用灯光的平截头体(我已经拥有)锥体计算来测试当前像素是否落在截锥体内,对吗?

如果是这样,有人知道在像素着色器中执行此操作的最佳方法是什么吗?我只想检查该点是否位于平截头体的每个平面的前面,但这在像素着色器中似乎很昂贵。

0 投票
1 回答
3990 浏览

c++ - 现代 OpenGL 阴影立方体贴图的指针?

背景

我正在使用 C++ 和现代 OpenGL (3.3) 开发 3D 游戏。我现在正在研究照明和阴影渲染,并且我已经成功实现了定向阴影映射。在阅读了游戏的要求后,我决定我需要点光阴影贴图。在做了一些研究之后,我发现要做全向阴影贴图我会做一些类似于定向阴影贴图的事情,但是用立方体贴图代替。

我以前没有立方体贴图的知识,但我对它们的理解是立方体贴图是六个纹理,无缝连接。我环顾四周,但不幸的是,我很难找到关于现代 OpenGL 主题的权威“教程”。我首先寻找从头到尾解释它的教程,因为我很难从源代码片段或只是概念中学习,但我尝试了。

目前的理解

这是我对这个想法的一般理解,减去技术细节。请纠正我。

  • 对于每个点光源,都会设置一个帧缓冲区,例如定向阴影映射
  • 然后生成单个立方体贴图纹理,并使用glBindTexture(GL_TEXTURE_CUBE_MAP, shadowmap).
  • 立方体贴图设置有以下属性:

    /li>

(这也类似于定向阴影贴图)

  • 现在glTexImage2D()迭代六次,每个面一次。我这样做:

    /li>
  • 纹理通过调用附加到帧缓冲区

    /li>
  • 当要渲染场景时,它会分两次渲染,就像定向阴影贴图一样。

  • 首先,绑定阴影帧缓冲区,将视口调整为阴影贴图的大小(本例中为 1024 x 1024)。
  • 剔除设置为正面glCullFace(GL_FRONT)
  • 活动着色器程序切换到顶点和片段阴影着色器,我将提供进一步向下的来源
  • 计算所有六个视图的光照视图矩阵。我通过创建一个 glm::mat4 和push_back()矩阵的向量来做到这一点,如下所示:

    /li>
  • 绑定了默认的framebuffer,正常绘制场景。

问题

现在,到着色器。这就是我的理解枯竭的地方。我完全不确定我应该做什么,我的研究似乎相互冲突,因为它适用于不同的版本。我最终从随机来源温和地复制和粘贴代码,并希望它能够实现除黑屏之外的其他功能。我知道这很糟糕,但似乎没有关于做什么的明确定义。我在哪些空间工作?我什至需要一个单独的阴影着色器,就像我在定向点照明中使用的那样?我到底用什么作为阴影立方体贴图的类型?采样立方体?采样立方体阴影?如何正确采样所述立方体贴图?我希望有人可以为我清除它并提供一个很好的解释。我目前对着色器部分的理解是: - 当场景被渲染到立方体贴图时,顶点着色器简单地采用我在 C++ 代码中计算的 depthMVP 统一,并通过它们转换输入顶点。- 立方体贴图传递的片段着色器只是将单出值分配给gl_FragCoord.z. (这部分与我实现定向阴影贴图时没有变化。我认为立方体贴图是一样的,因为着色器甚至不与立方体贴图交互 - OpenGL 只是将它们的输出渲染到立方体贴图,对吧?因为它是帧缓冲区?)

  • 正常渲染的顶点着色器没有改变。
  • 在用于法线渲染的片段着色器中,顶点位置通过灯光的投影和视图矩阵转换到灯光的空间中。
  • 这在立方体贴图纹理查找中以某种方式使用。???
  • 一旦使用魔法手段检索到深度,就会将其与光到顶点的距离进行比较,就像定向阴影贴图一样。如果它较少,则该点必须被遮蔽,反之亦然。

理解的不多。我对顶点如何转换并用于查找立方体贴图一无所知,因此我将粘贴我的着色器的源代码,希望人们能澄清这一点。请注意,很多代码都是盲目复制和粘贴的,我没有做任何更改以免影响任何理解。

阴影顶点着色器:

阴影片段着色器:

标准顶点着色器:

标准片段着色器:

我不记得 ComputerShadowFactor 和 VectorToDepthValue 函数代码是从哪里来的,因为我在我的笔记本电脑上研究它,我现在无法访问,但这是这些着色器的结果:

这些着色器的结果

它是一个被阴影空间包围的无阴影空间的小正方形。

我显然在这里做错了很多,可能集中在我的着色器上,由于缺乏对该主题的了解,因为我发现除了教程之外很难从任何东西中学习,对此我感到非常抱歉。我很茫然,如果有人可以清楚地解释我做错了什么,为什么它错了,我该如何解决它,甚至可能是一些代码,那就太好了。我认为问题可能是因为我在错误的空间工作。

0 投票
1 回答
753 浏览

opengl - OpenGL深度纹理伪影

我正在为我的小 3d 引擎实现阴影映射。但是,深度纹理中似乎存在伪影,可以通过使用纹理并观察阴影,或者在四边形上绘制深度纹理来看到。

这是在四边形上绘制深度纹理时的样子:

是的,那些白色的小矩形不应该在那里。

那么,可能是什么原因造成的呢?

打开glfw窗口:

创建深度帧缓冲区和纹理:

渲染到深度纹理:

0 投票
1 回答
240 浏览

opengl - 阴影映射 opengl glsl 着色器 图形 数学

我很难理解不同着色器阶段之间的数学。

在从灯光的角度来看的片段着色器中,我基本上将 fragDepth 写成 rgb 颜色

使用上述着色器渲染场景时,它会以全白色显示场景。我想那是因为 gl_FragCoord.z 大于 1。希望它不会在 1 时达到最大值。但我们现在可以不理会这个问题。

在从相机角度看的几何着色器中,我基本上将所有点变成四边形并写出可能“不正确”的纹理位置以在 lightTexture 中查找。这里的数学就是问题。我也有点不确定插值在下一个着色器阶段是否正确。

在从相机角度来看的片段着色器中,我基本上在 lightTexture 中查找从灯光角度显示的颜色并写出相同的颜色。

当从相机的角度进行渲染时,我看到场景是按原样绘制的,但在它们上应用了不正确的纹理坐标并重复出现。重复纹理可能是由纹理坐标超出 0 到 1 的范围引起的。

我已经尝试了几件事,但仍然无法理解数学应该是什么。一些注释掉的代码和一个我不确定的例子是:

为左下角。其他角落的类似代码

从解决方案中,我希望从摄像机的角度渲染场景,其颜色与从灯光的角度完全相同。可能有一些精度误差。

0 投票
1 回答
801 浏览

opengl - ShadowMap 混淆

我对阴影贴图感到困惑。这是我所理解的(以下步骤不起作用:))

如何获得利润(请不要对代码感到困惑,大致是因为我是用Java写的):

1.用参数创建空的depthTexture(我的是1024x1024)

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE)

glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, width, height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, GL_NULL)

2.创建 FBO 并将该纹理附加到它

glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTexture, 0)

3.为照明相机设置新的投影和视图矩阵

我使用与我的主相机相同的另一个坐标,因为场景看起来更好(我试过了,所以没有问题......我猜..)。

4.创建新的小着色器来确定 FBO 的 gl_Position 并用花哨的东西修改主着色器(偏置矩阵 * lightCamera 矩阵 * 顶点,sampler2Dshadow 等等)

5.当然要统一一切,做一些事情。

现在渲染循环

1.当然要统一一切并做某事(再次)。

2.绑定FBO,绑定little shader,,glViewport(0, 0, 1024, 1024)colorMask为false,清除深度缓冲区glCullFace(GL_FRONT),,glBindTexture(GL_TEXTURE_2D, 0)

3.只使用顶点位置属性完全渲染一切

4.取消绑定FBO,将程序重新绑定到主着色器(那个有花哨的东西)glViewport,启用colorMask,glCullFace(GL_BACK)

5.正常渲染场景,甚至不用考虑“该死的主着色器将如何得到sampler2DShadow,因为我们不绑定它,不统一它,甚至不触摸它”

6.观看无数的故障、错误和像素狂欢

实际上我试图将 depthTexture 统一到采样器,但我只有黑屏。即使我不渲染 FBO,当我这样做时,我也会得到相同的画面。

有人可以解释一下,我错过了什么吗?

我觉得着色器使用了漫反射纹理两次:作为漫反射纹理和作为depthTexture,但我不知道如何给它那个depthTexture。

0 投票
1 回答
1577 浏览

c++ - 奇怪的 OpenGL 阴影映射行为

我正在使用 SFML 开发 C++ 和 OpenGL 3.2 的 3D 游戏。我一直在努力实现点光阴影映射。到目前为止,我所做的似乎与我所学到的和我所看到的例子一致,但仍然没有阴影。

我所做的是按照我使用它的确切顺序编写我使用的所有代码的简单列表,但不是完整的源代码,只有相关的代码(因为我的项目分为几个类):

这是我的代码现在所做的图片:

破碎的阴影贴图

这是一个奇怪的效果,但似乎接近我的意思。似乎任何在 0、0、0 处暴露在光线下的表面在其中心都有一个无阴影的圆圈,而其他一切都没有阴影。

0 投票
1 回答
2438 浏览

opengl - 阴影映射中的偏置矩阵混淆

我对阴影映射中的偏置矩阵感到困惑。根据这个问题:阴影映射中的偏置矩阵,偏置矩阵用于按比例缩小并转换为 [0..1]x 和 [0..1]y。所以我想如果我们不使用偏置矩阵,纹理将仅填充 1/4 场景大小?真的吗?还是这里有什么魔力?