在纸牌游戏中,我将使用什么渲染技术为纸牌绘制阴影效果?


13

什么样的阴影算法可以用来创建像这样的阴影? 在此处输入图片说明

我正在制作的是类似的东西,但是都由OpenGL驱动的2D绘图API完成,因此没有Z坐标。

另外,对于手本身,我真的很想得到一种阴影效果,如下所示: 在此处输入图片说明

我只是不确定如何获得接近它的阴影外观。

卡的数量一定会发生变化,并且卡会扔到桌子上,所以我不能使用任何类型的光照图。

我应该研究哪种算法(除了模糊,我知道需要做些什么?)

谢谢

更新资料

我正在制作2D纸牌游戏。我想从卡上添加阴影阴影偏移,有点像:

在此处输入图片说明

我正在考虑的方式是:

  • 保留与后缓冲大小相同的纹理。
  • 绘制黑色矩形作为该纹理的临时卡片。

  • 模糊该纹理。

  • 用这种纹理画我的卡片。
  • 对卡进行其他照明。
  • 将此纹理绘制到后缓冲区。

我的问题是:

  • 这是正确的方法吗?

  • 有没有一种方法可以在不渲染纹理的情况下(保持位图
    与后缓冲区一样大)?

  • 是否可以安全地假定后
    缓冲区大小不会超过最大纹理大小?(我的意思是,如果后缓冲区
    为2000x3000,那么可以说我可以在
    该大小的视频内存中创建纹理了吗?

谢谢


1
在第二个问题上,一个美学观点是:如果您实际上手里拿着这些卡片,那实际上是不可能的。紧挨着的卡不会互相遮挡。除非您持有很多。您不能真正按照该图像中所描绘的方式来放置卡片。这些卡看起来像相隔几毫米;他们彼此之间并不持平。我只是不用担心。
Nicol Bolas

Answers:


18

我认为每个人都为这个问题提供了过于复杂的解决方案。

在此处输入图片说明

因此,首先,我们有(a)所示的卡片(或您要抽奖的任何卡片)。接下来,我们对其进行复制,将其填充为黑色,然后对其进行高斯模糊处理(b)。所有这些都发生在photoshop或您最喜欢的美术工具中。

接下来,在游戏中,当我们要绘制卡片时,首先绘制具有乘法(或Alpha)混合效果的模糊黑色图像,并在某个方向上稍微偏移,然后在其顶部绘制卡片。Voilá。

为了进一步提高技巧,您可以在阴影和卡片渲染之间进行切换,以获得(d)所示的效果,或者先绘制所有阴影,然后再绘制卡片,例如(e)中的(我在(e)情况下对卡片进行了着色以显示它们还是分开的=)

最好不要对阴影使用纯黑色(或全alpha),以创建更细微,透明的阴影。


2
+1用于消除游戏中的阴影。如果场景中有灯光,您还可以更进一步,修改阴影的放置位置。
FrenchyNZ 2011年

+1,很好的插图。此外,在E的情况下,您可以在桌子上使用深色阴影在桌子上,而在带有模板的卡片上使用半明亮。那样会更复杂,但是效果会更好:)
Kromster

2

第一个不太难。如果为您的卡片手渲染一个Alpha通道(对于其中有卡片的像素,它可能像黑色一样简单,而对于透明像素,它可以像白色一样简单),则可以仅在Alpha通道上执行任何类型的模糊处理,并且然后偏移它并使用它来控制桌子的照明。(大概,如果您没有Z缓冲区,则必须首先在屏幕外的某个位置渲染出Alpha通道,然后使用蒙版制作表格,然后渲染实际的卡片。)

第二个看起来有点像SSAO(屏幕空间环境光遮挡)。该技术需要Z坐标。但是,如果两个卡之间的角度没有变化(如果没有Z缓冲区,这就是我的猜测),则可以通过为每个渲染阴影(如第一个阴影)来做一个很好的近似卡。但是,性能可能会有些棘手-每个平面都需要一个模糊的Alpha通道用于其上方的所有平面,并且如果桌子上有一堆卡片,则可能需要进行大量渲染。


SSAO太过强大了=)如果不看动画示例,很难说出使用了哪种阴影技术。如果卡牌总是以这种顺序排列,并且彼此之间间隔一定,那么最简单的方法就是简单地预先渲染阴影,但是您永远都不知道要怎么玩游戏。
Patrick Hughes

0

您可以不做阴影贴图吗?将场景渲染到fbo。仅保存深度值,并在着色器中进行常规深度值检查,以查看是否应渲染阴影。


我没有使用Z缓冲区,没有“深度”。
jmasterx 2011年

0

以下过程不需要屏幕外渲染目标。但是,这样做获得了首先绘制表格的要求。或者至少,在绘制表格之前,不会在表格将覆盖的像素上绘制任何内容。它还要求表本身是一个不重叠的单块图像。

另外,您的帧缓冲区需要一个alpha分量。

  1. 获取卡片的灰度图像。使边缘模糊,可能会扩大其大小。这是您的影子卡图像。请注意,这是一个单通道图像。在着色器中访问此纹理时,应确保将单个值放在alpha组件中。这可以在您的着色器或其他地方完成。

    图像中的值为0.0表示没有阴影。图像中的值1.0表示总阴影。即,完全变黑。您可能希望将0.5设为最暗的颜色。

  2. 清除屏幕,以将Alpha设置为零

  3. 在渲染任何东西(或至少将要在桌子“下” 渲染的任何东西)之前,为每张卡片渲染模糊纹理,从卡片的实际位置偏移(但方向相同)。着色器输出的颜色应为“混合”配置(以OpenGL的说法):

    glBlendEquation(GL_MAX);

    此混合模式用于防止重叠阴影越来越暗。它只是采用写入该像素的最暗值。它看起来应该足够好。

    您还应该使用颜色写入遮罩关闭颜色写入。

  4. 渲染表。这样做时,应按以下步骤设置混合:

    glBlendEquation(GL_ADD);
    glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_ZERO);

如果这些限制对您来说太过严格,则必须使用渲染目标。这样做如下:

  1. 像以前一样创建影子卡图像。

  2. 首先,渲染阴影。绑定阴影帧缓冲区(如果您的硬件可以渲染到其中之一,则只需要是一个单通道图像)。将其值清零。

  3. 对于每张卡,渲染阴影卡图像,并像以前一样偏移。着色器应将相同的值写入输出颜色的所有四个分量。混合模式应再次为glBlendEquation(GL_MAX)

  4. 切换回常规帧缓冲区。绘制所有您想要阴影的东西。

  5. 现在,用我们渲染的阴影图像绘制一个全屏四边形。着色器应将从阴影图像中提取的纹理像素存储在输出的alpha中;RGB无关紧要。混合模式应为:

    glBlendEquation(GL_ADD);
    glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_ALPHA);

在第一种方法中,我认为您忘记了步骤5:禁用混合并渲染卡片。另外,值得注意的是,第一种方法不允许您获得卡间阴影,如OP的第二张屏幕截图所示。
内森·里德

@NathanReed:我想他知道自己该怎么做。另外,正如我在问题下的评论中指出的那样,“卡间阴影”没有任何意义。
Nicol Bolas

1
它可能不现实地代表您实际上如何持卡,但看起来很酷!就像第一次射击一样,让卡片漂浮在桌子上方真的没有任何“意义”
内森·里德

0

我会使用模板缓冲区。将其清除为1(最好在清除深度的同时),绘制表格。然后启用模板测试,使用模糊的矩形纹理绘制阴影,如果模板和深度通过则增加阴影,如果模板失败则不执行任何操作,如果深度失败则不执行任何操作,并将模板功能设置为GL_EQUAL(参考1,蒙版0xff),禁用模板测试。(我还没有完全测试过它,但是它是从类似的代码派生出来的,应该可以正常工作;您可能需要调整参数)。然后画其他所有东西。

这些电话将是:

glEnable (GL_STENCIL_TEST);
glStencilFunc (GL_EQUAL, 1, 2);
glStencilOp (GL_KEEP, GL_KEEP, GL_INCR);

// draw shadow textures

glDisable (GL_STENCIL_TEST);

唯一可能造成麻烦的情况是,如果两个模糊的边缘稍微重叠,则边缘会模糊。否则,除了基本的OpenGL 1.1提供的功能之外,它不需要任何花哨的东西,并且可以在所有硬件上运行(可能是旧的3DFX卡,我认为您并不真正担心支持...)

第二个替代方法是glCopyTexSubImage2D,它在非性能要求较高的游戏中应该能很好地工作。这也可以使用比后缓冲区小的纹理,并且在所有硬件上也都很好地支持它(它是OpenGL 1.1的一部分,Doom 3使用了它,因此可以期望很好的支持)。

基本设置如下:

  • 清除颜色为黑色。
  • 禁用深度写入(尽管此方法不需要深度缓冲区,因此您可以在不使用深度缓冲的情况下忽略该部分)。
  • 将视口设置为与纹理相同的尺寸。
  • 将卡片绘制为白色填充的几何图形。
  • glCopyTexSubImage2D到您的纹理。
  • 将视口切换回完整窗口大小。
  • 正常绘制表格。
  • 使用着色器将纹理绘制为全屏混合四边形,以使其模糊并反转颜色。
  • 画其他所有东西。

这也应该会很好地工作,它比模板缓冲方法要占用更多的GPU,但是可以正确处理重叠的情况,而且-正如我说的那样-我认为像您这样的游戏即使在低端设备上也可以燃烧GPU的能力卡。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.