Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/opengl/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# COLLADA混合:基于纹理的透明度_C#_Opengl_Opengl 3_Collada - Fatal编程技术网

C# COLLADA混合:基于纹理的透明度

C# COLLADA混合:基于纹理的透明度,c#,opengl,opengl-3,collada,C#,Opengl,Opengl 3,Collada,我现在想做的是让我的COLLADA进口商在一些透明的COLLADA模型上工作。模型混合由第7章“渲染/确定透明度”一段规定 简而言之,混合方程有两个输入:透射率和透射率;前者可以是RGBA颜色或纹理,后者只能是浮点值。此外,Transparent可以指定两个混合方程(ColladaFxOpaqueType.AlphaOne和ColladaFxOpaqueType.RgbZero): 以下是两个混合方程式: // AlphaOne // // result.r = fb.r * (1.0f -

我现在想做的是让我的COLLADA进口商在一些透明的COLLADA模型上工作。模型混合由第7章“渲染/确定透明度”一段规定

简而言之,混合方程有两个输入:透射率和透射率;前者可以是RGBA颜色或纹理,后者只能是浮点值。此外,Transparent可以指定两个混合方程(ColladaFxOpaqueType.AlphaOne和ColladaFxOpaqueType.RgbZero):

以下是两个混合方程式:

// AlphaOne 
//
// result.r = fb.r * (1.0f - transparent.a * transparency) + mat.r * (transparent.a * transparency)
// result.g = fb.g * (1.0f - transparent.a * transparency) + mat.g * (transparent.a * transparency)
// result.b = fb.b * (1.0f - transparent.a * transparency) + mat.b * (transparent.a * transparency)
// result.a = fb.a * (1.0f - transparent.a * transparency) + mat.a * (transparent.a * transparency)

// RgbZero
//
// result.r = fb.r * (transparent.r * transparency) + mat.r * (1.0f -transparent.r * transparency)
// result.g = fb.g * (transparent.g * transparency) + mat.g * (1.0f -transparent.g * transparency)
// result.b = fb.b * (transparent.b * transparency) + mat.b * (1.0f -transparent.b * transparency)
// result.a = fb.a * (luminance(transparent.rgb) * transparency) + mat.a * (1.0f - luminance(transparent.rgb) * transparency)

where
- result: draw framebuffer
- fb: destination blend color
- mat: source blend color
- transparent: COLLADA parameter described above
- transparency: COLLADA parameter described above
- luminance: function to average color following ITU-R Recommendation BT.709-4
我现在实现的是在透明表示颜色的情况下混合几何体(以及两个混合方程)。下面是实现此功能的特殊代码:

internal void CompileBlendStateParameters(ColladaShaderParameters shaderParameters, ColladaFxCommonContext commonContext)
{
    if (shaderParameters == null)
        throw new ArgumentNullException("shaderParameters");
    if (commonContext == null)
        throw new ArgumentNullException("commonContext");

    // Apply alpha blending, if required
    if ((Transparent != null) || (Transparency != null)) {
        BlendState blendState = null;
        ColorRGBAF blendFactors = new ColorRGBAF(1.0f); // No effect value
        float trasparency = 1.0f;                       // No effect value

        if (Transparency != null)
            trasparency = Transparency.GetValue(commonContext);

        if ((Transparent != null) && (Transparent.IsFixedColor(commonContext) == true)) {
            switch (Transparent.Opaque) {
                case ColladaFxOpaqueType.AlphaOne:

                    // Equation from COLLADA specification:
                    //
                    // result.r = fb.r * (1.0f - transparent.a * transparency) + mat.r * (transparent.a * transparency)
                    // result.g = fb.g * (1.0f - transparent.a * transparency) + mat.g * (transparent.a * transparency)
                    // result.b = fb.b * (1.0f - transparent.a * transparency) + mat.b * (transparent.a * transparency)
                    // result.a = fb.a * (1.0f - transparent.a * transparency) + mat.a * (transparent.a * transparency)

                    // Determine blend factor constant color
                    blendFactors = new ColorRGBAF(Transparent.GetFixedColor(commonContext).Alpha);
                    // Modulate constant color
                    blendFactors = blendFactors * trasparency;
                    // Create blend state
                    blendState = new BlendState(BlendState.BlendEquation.Add, BlendState.BlendFactor.ConstColor, BlendState.BlendFactor.ConstColorComplement, blendFactors);
                    break;
                case ColladaFxOpaqueType.RgbZero:

                    // Equation from COLLADA specification:
                    //
                    // result.r = fb.r * (transparent.r * transparency) + mat.r * (1.0f -transparent.r * transparency)
                    // result.g = fb.g * (transparent.g * transparency) + mat.g * (1.0f -transparent.g * transparency)
                    // result.b = fb.b * (transparent.b * transparency) + mat.b * (1.0f -transparent.b * transparency)
                    // result.a = fb.a * (luminance(transparent.rgb) * transparency) + mat.a * (1.0f - luminance(transparent.rgb) * transparency)

                    // Determine blend factor constant color
                    blendFactors = new ColorRGBAF(Transparent.GetFixedColor(commonContext));
                    // Define alpha blend factor as luminance
                    blendFactors.Alpha = blendFactors.Red * 0.212671f + blendFactors.Green * 0.715160f + blendFactors.Blue * 0.072169f;
                    // Modulate constant color
                    blendFactors = blendFactors * trasparency;
                    // Create blend state
                    blendState = new BlendState(BlendState.BlendEquation.Add, BlendState.BlendFactor.ConstColorComplement, BlendState.BlendFactor.ConstColor, blendFactors);
                    break;
            }
        } else if ((Transparent != null) && (Transparent.IsTextureColor(commonContext) == true)) {

            throw new NotSupportedException();

        } else {
            // Modulate constant color
            blendFactors = blendFactors * trasparency;
            // Create blend state
            blendState = new BlendState(BlendState.BlendEquation.Add, BlendState.BlendFactor.ConstColor, BlendState.BlendFactor.ConstColorComplement, blendFactors);
        }

        if (blendState != null)
            shaderParameters.RenderState.DefineState(blendState);
    }
}
Rougly,上面的代码抽象了OpenGL层,相当于:

 // AlphaOne equation
 glEnable(GL_BLEND);
 glBlendEquation(GL_FUNC_ADD);
 glBlendFunc(GL_CONSTANT_COLOR, GL_ONE_MINUS_CONSTANT_COLOR);
 glBlendColor(blendFactors.Red, blendFactors.Green, blendFactors.Blue, blendFactors.Alpha);

 // RgbZero equation
 glEnable(GL_BLEND);
 glBlendEquation(GL_FUNC_ADD);
 glBlendFunc(GL_ONE_MINUS_CONSTANT_COLOR, GL_CONSTANT_COLOR);
 glBlendColor(blendFactors.Red, blendFactors.Green, blendFactors.Blue, blendFactors.Alpha);

 // Having calculated blendFactor appropriately!!
我想要的是支持基于纹理的trasparencies(确实移除了可怕的NotSupportedException)。通常,这将通过将纹理附加到输出的片段alpha组件来实现,并像往常一样设置混合(alpha和OneMinusAlpha混合因子),但遗憾的是,这在上述等式中是不可能的(alpha组件不会被混合,不是吗?)

另外,您可以注意到,我通过使用一个简单的解决方案实现了混合,但是基于恒定的混合颜色(
blendFactors
代码中的变量)(确实使用GL_EXT_blend_color extension)。如何使用普通混合函数删除此依赖关系?我认为上一个问题的解决方案可以帮助我了解基于纹理的混合…

我不太确定我是否理解你的意图,但我会尝试一下(请随时在评论中跟进)

您希望使用标准opengl混合实现AlphaOne和RgbZero方程,并且希望对图像的每个纹理计算混合函数,而不是使用恒定颜色。透明度的典型混合函数(SRC_ALPHA,一个_减去_SRC_ALPHA)使用传入片段的ALPHA值,计算结果如下:

result = dst * (1-src_alpha) + src * src_alpha
一次看一个你想要实现的两个方程(为了简洁起见,只看红色和alpha):

AlphaOne:

result.r = fb.r * (1.0f - transparent.a * transparency) + mat.r * (transparent.a * transparency);
result.a = fb.a * (1.0f - transparent.a * transparency) + mat.a * (transparent.a * transparency);
如果我们看这个方程,我们会发现它看起来非常类似于最初公布的方程。我们所要做的就是用
transparent.a*transparency
代替
src\u alpha

这意味着,如果使用值为
transparent.a
的像素着色器来自纹理样本,并将
transparency
作为统一浮点,它将实现AlphaOne功能:

sampler2D tex;
uniform transparency;

main() {
   vec4 texel = texture2D(tex,uv);
   vec3 out_rgb = texel.rgb;
   float out_alpha = texel.a * transparency;
   gl_FragColor = vec4(out_rgb, out_alpha);
}
此着色器提交
transparent.a*transparency
作为混合方程中要使用的src_alpha值

我相信,这表明您可以轻松地用典型的opengl混合实现该算法


然而,RGBZero函数对我来说更难,我不相信有任何混合函数可以实现这一点。我有一个奇怪的想法,就是一次画一个彩色通道(锁定G、B、A进行编辑,只需绘制R,输出alpha作为R混合因子,然后对其他3个颜色通道重复。对我来说,这看起来有点奇怪的混合函数,但我想不出它会用于什么。

我认为,如果不使用多通道渲染,即使是AlphaOne混合,也无法解决这个问题:您的解决方案覆盖“mat.a”信息(来自上一次计算)。解决方案将是两次混合:第一次用于RGB值,第二次仅用于alpha值(通过掩蔽颜色缓冲区渲染occour)通过使用GL_blend_equation_separate extension并应用不同的alpha混合函数,RGBZero混合适用。