use*_*268 5 c++ photoshop graphics direct3d alphablending
我正在尝试将Photoshop滤镜复制为Direct3D。我一直在阅读和搜索不同的渲染状态,并且效果几乎可以正常工作。问题在于它忽略了纹理的Alpha值。
这是说明情况的图像:
http://www.kloonigames.com/petri/stackoverflow_doesnt_allow_.jpg
我找到了一种解决方案,那就是保存没有透明度和白色背景的图像。但是我对这种解决方案不满意。问题是我真的需要使用alpha值。我想逐渐淡出图像。如果混合模式忽略了alpha值,则无法执行此操作。
所以问题是如何用alpha渲染图像?
这是混合模式代码:
dev->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
dev->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO);
dev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_SRCCOLOR);
Run Code Online (Sandbox Code Playgroud)
编辑添加了SetTextureStageState
dev->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
dev->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
dev->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
dev->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
Run Code Online (Sandbox Code Playgroud)
您可以通过在像素着色器中预乘alpha或通过使用具有预乘alpha的纹理来一步实现此效果。
例如,如果您有3种可能的着色器混合操作,并且您希望每个着色器都考虑alpha。
Blend = ( src.rgb * src.a ) + ( dest.rgb * (1-src.a) )
Add = ( src.rgb * src.a ) + ( dest.rgb )
Multiply = (src.rgb * dest.rgb * src.a) + (dest.rgb * (1-src.a) )
Run Code Online (Sandbox Code Playgroud)
您会注意到,单次遍历是不可能实现乘法的,因为对源颜色有两项操作。但是,如果在着色器中预乘Alpha,则可以从混合操作中提取Alpha分量,并且可以在同一着色器中混合所有三个操作。
在像素着色器中,您可以手动预乘Alpha。或使用DirectXTex texconv之类的工具来修改纹理。
return float4(color.rgb*color.a, color.a);
Run Code Online (Sandbox Code Playgroud)
操作变为:
Blend = ( src.rgb ) + ( dest.rgb * (1-src.a) )
Add = ( src.rgb ) + ( dest.rgb )
Multiply = ( src.rgb * dest.rgb ) + (dest.rgb * (1-src.a) )
Run Code Online (Sandbox Code Playgroud)
小智 1
听起来你想要:
dst.rgb = (src.a * src.rgb) * ((1 - src.a) * dst.rgb)
Run Code Online (Sandbox Code Playgroud)
您可以使用 D3DRS_BLENDOP 来执行此操作,但不幸的是没有 D3DBLENDOP_MULTIPLY。我认为如果没有片段着色器,这个操作是不可能的。