我已经在其他帖子中看过SceneKit only has two blend modes,但我仍然想知道这些是如何工作以及如何使用它们。
我目前正尝试使用片段着色器绘制一些anti-aliased circles。因此,我希望平滑这些圆圈的边缘,并blur
/ fade
将它们透明化。
使用普通混合模式(没有#transparent),SceneKit的片段着色器将忽略任何alpha值变化,但它仍然会进行alpha混合。 alpha混合根据材质颜色的alpha值进行。因此,alpha混合是可能的,但不能在片段着色器中更改。
为了测试这个,我使用了一个片段着色器添加,如下所示:
#pragma body
_output.color = vec4(1.0, 1.0, 1.0, 1.0);
这是创建我圈子的代码:
#define kDefaultCircleColor [UIColor colorWithRed: 0.5 green: 0.0 blue: 0.0 alpha: 0.5]
NSMutableDictionary *shaders = [NSMutableDictionary dictionary];
shaders[SCNShaderModifierEntryPointFragment] = [[NSString alloc] initWithContentsOfURL: [[NSBundle mainBundle] URLForResource: @"test" withExtension: @"shader"] encoding: NSUTF8StringEncoding error: NULL];
MLCircleNode *circNode1 = [MLCircleNode node];
circNode1.radius = 50;
circNode1.position = SCNVector3Make(100, 400, 0);
circNode1.color = kDefaultCircleColor;
circNode1.lineWidth = 15.0;
circNode1.geometry.firstMaterial.shaderModifiers = shaders;
[_baseNode addChildNode: circNode1];
MLCircleNode *circNode2 = [MLCircleNode node];
circNode2.radius = 50;
circNode2.position = SCNVector3Make(125, 400, -1);
circNode2.color = kDefaultCircleColor;
circNode2.lineWidth = 15.0;
circNode2.geometry.firstMaterial.shaderModifiers = shaders;
[_baseNode addChildNode: circNode2];
这是结果。可以看出,应用了片段着色器的颜色变化,但没有应用alpha值,从而产生50%透明度的白色。
我通过在着色器中添加#transparent来使用透明混合模式来实现想要的效果,但在这里我也遇到了一些问题。 #transparent混合模式的透明材质的颜色与默认混合模式的透明材质的颜色不同(我猜这是由于使用了(GL_ONE,GL_ONE_MINUS_SRC_ALPHA),但我不确定)。 #opaque混合模式的结果与这两者不同。
以下图片之间的区别只是添加#transparent或在片段着色器修改器中添加#opaque:
没有任何附加物。
使用#transparent
使用#opaque
感谢您阅读迄今为止的这篇长篇文章,现在是有趣的部分,问题!
1)我的第一个例子中的颜色在哪里计算?我怎么可能在片段着色器中设置(1.0,1.0,1.0,1.0)的颜色,但我看到的是50%alpha混合的白色?我想了解着色过程如何在这里起作用,颜色来自哪里以及alpha值来自哪里,所以我知道如何有效地使用它。
2)使用非#透明混合和#transparent-blending时,为什么颜色会发生变化?这是否意味着SceneKit中有第三种混合模式?
3)如何将两种不同的混合模式结合使用?例如,我希望有一些节点可以在片段着色器中更改其alpha值,因此这些节点将使用#transparent。其他人不应该使用它,但它们应该具有相同的颜色。如何在这两种混合模式之间绕过颜色变化?
4)你有什么建议让我的圆圈的平滑alpha绘图工作?