如何在 opengl 中分离颜色和 alpha 混合函数?

发布于 2024-07-26 15:57:36 字数 1855 浏览 3 评论 0原文

在尝试将 2D 阴影渲染技术从 Directx 移植到 Opengl 的过程中,我遇到了一个问题,即我似乎无法足够精细地访问 opengl 混合器。

但首先,为了让以下内容有意义,我的算法:

我从后到前对所有精灵进行排序和渲染,而不使用深度缓冲区。 阴影精灵在投射它们的对象之前绘制,并使用下面的第二个混合状态 gShadowBlendState。 这使得它们只将 alpha 值绘制到帧缓冲区上的 alpha 通道。

常规对象的精灵使用下面首先指定的 gBlendState,这只是后备缓冲区的常规 alpha 混合。 然而,它们也会从后台缓冲区 alpha 通道中删除 alpha,使其变得不透明; 这可以确保阴影不会透过它们前面的不透明物体显示出来。

绘制的第三个东西是在其他所有东西之后绘制的,是一个全屏四边形,它使用阴影颜色和下面的最终混合状态进行渲染。 它使用后缓冲区的 Alpha 通道来实现不透明度,有效地显示出之前记录的所有阴影信息。

这个练习的重点是让阴影在重叠的地方不会变暗。

    gBlendState.SrcBlend       = D3DBLEND_SRCALPHA;
    gBlendState.BlendOp        = D3DBLENDOP_ADD;
    gBlendState.DestBlend      = D3DBLEND_INVSRCALPHA;
    gBlendState.SrcBlendAlpha  = D3DBLEND_ZERO;
    gBlendState.BlendOpAlpha   = D3DBLENDOP_ADD;
    gBlendState.DestBlendAlpha = D3DBLEND_INVSRCALPHA;

    gShadowBlendState.SrcBlend       = D3DBLEND_ZERO;
    gShadowBlendState.BlendOp        = D3DBLENDOP_ADD;
    gShadowBlendState.DestBlend      = D3DBLEND_ONE;
    gShadowBlendState.SrcBlendAlpha  = D3DBLEND_ONE;
    gShadowBlendState.BlendOpAlpha   = D3DBLENDOP_MAX;
    gShadowBlendState.DestBlendAlpha = D3DBLEND_ONE;

    gShadowFillBlendState.SrcBlend       = D3DBLEND_DESTALPHA;
    gShadowFillBlendState.BlendOp        = D3DBLENDOP_ADD;
    gShadowFillBlendState.DestBlend      = D3DBLEND_INVDESTALPHA;
    gShadowFillBlendState.SrcBlendAlpha  = D3DBLEND_ONE;
    gShadowFillBlendState.BlendOpAlpha   = D3DBLENDOP_MAX;
    gShadowFillBlendState.DestBlendAlpha = D3DBLEND_ONE;

反正。 我现在正在尝试在 Opengl 中执行此操作。 目前我启用了 alpha 混合,

    glEnable(GL_BLEND);
    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

但我不确定如何为其提供单独的说明以计算颜色和 alpha 分量。 所以我的问题是:有没有办法比 glBlendFunc() 更好地控制 OpenGL 中的搅拌器?

In the process of trying to port my 2D shadow rendering technique from Directx to Opengl, I've run across a problem where I can't seem to get fine enough access to the opengl blender.

But first, so that the following makes sense, my algorithm:

I sort and render all sprites from back to front without using a depth buffer. Shadow sprites are drawn just before the objects that cast them and use the second blendstate below, gShadowBlendState. That makes them draw only their alpha values to the alpha channel on the framebuffer.

Sprites for regular objects use gBlendState specified first below, which is just a regular alpha blend to the backbuffer. However, they also remove alpha from the backbuffer alpha channel to the extent that they are opaque; this makes sure that shadows don't show through opaque objects that are in front of them.

The third thing that is drawn, and which is drawn after everything else, is a fullscreen quad that renders using the shadow colour and the final blend state below. It uses the backbuffer's alpha channel for opacity, effectively bringing out all the shadow information inscribed earlier.

The whole point of this exercise is to get shadows that don't get darker where they overlap.

    gBlendState.SrcBlend       = D3DBLEND_SRCALPHA;
    gBlendState.BlendOp        = D3DBLENDOP_ADD;
    gBlendState.DestBlend      = D3DBLEND_INVSRCALPHA;
    gBlendState.SrcBlendAlpha  = D3DBLEND_ZERO;
    gBlendState.BlendOpAlpha   = D3DBLENDOP_ADD;
    gBlendState.DestBlendAlpha = D3DBLEND_INVSRCALPHA;

    gShadowBlendState.SrcBlend       = D3DBLEND_ZERO;
    gShadowBlendState.BlendOp        = D3DBLENDOP_ADD;
    gShadowBlendState.DestBlend      = D3DBLEND_ONE;
    gShadowBlendState.SrcBlendAlpha  = D3DBLEND_ONE;
    gShadowBlendState.BlendOpAlpha   = D3DBLENDOP_MAX;
    gShadowBlendState.DestBlendAlpha = D3DBLEND_ONE;

    gShadowFillBlendState.SrcBlend       = D3DBLEND_DESTALPHA;
    gShadowFillBlendState.BlendOp        = D3DBLENDOP_ADD;
    gShadowFillBlendState.DestBlend      = D3DBLEND_INVDESTALPHA;
    gShadowFillBlendState.SrcBlendAlpha  = D3DBLEND_ONE;
    gShadowFillBlendState.BlendOpAlpha   = D3DBLENDOP_MAX;
    gShadowFillBlendState.DestBlendAlpha = D3DBLEND_ONE;

Anyway. I'm trying to do this now in Opengl. Currently I have alpha blending enabled with

    glEnable(GL_BLEND);
    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

but I'm not sure how to give it separate instructions for how to calculate the colour and alpha components. So my question is this: Is there a way to get finer control over the blender in OpenGL than just glBlendFunc() ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

我恋#小黄人 2024-08-02 15:57:36

我不确定您是否可以获得更好的控制,但是您应该能够通过使用 glColorMask 首先渲染颜色通道然后渲染 alpha 通道来实现您想要做的大部分事情。 最后一步似乎应该保持不变。

I'm not sure that you can get finer control, but you should be able to achieve most of what you want to do through using glColorMask to first render the color channels and then render the alpha channel. The last step seems like it should remain unchanged.

豆芽 2024-08-02 15:57:36

我把答案留在这里:

http://pastie.org/542369

除了有一个问题:替换所有 GL_使用 GL_ FUNC_ ADD 添加。 我的错。

I left the answer here:

http://pastie.org/542369

Except there's one problem: Replace all the GL_ ADD with GL_ FUNC_ ADD. My mistake.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文