2016-09-18 124 views
2

This介绍了使用OpenGL的过时API进行体绘制的方法。但现在,我想使用GLSL完成体绘制,并完成了它的一些部分。我的问题是如何做混合。如何在使用GLSL的体绘制中进行混合?

glEnable(GL_BLEND); 
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 

但我怎么能完成使用GLSL混合:在上面的链接,混合由以下代码完成?

我试图使用以下等式:

C = Cs*As + Cd(1 - As) 

Cs为源对象的颜色。 Cd是目标对象的颜色。正如源对象的alpha一样。而我在片段着色器的代码如下:

...... 
vec3 dir = backPoint - frontPoint; 
float len = length(dir); 
float stepSize = 0.01; 
vec3 deltaDir = normalize(dir)*stepSize; 
float deltaLen = length(deltaDir); 
float accLen = 0; 
float accAlpha = 0; 
float sampleAlpha = 0; 
vec4 accColor = vec4(0.0); 

vec3 samplePoint = frontPoint; 
vec4 sampleColor; 
while(accLen < len && accColor.a <= 1.0){ 
    sampleColor = texture(texture3D, samplePoint); 

    accColor = sampleColor*sampleColor.a + accColor*(1-sampleColor.a); 

    accLen += deltaLen; 
    samplePoint += deltaDir; 
} 
color = accColor; 
...... 

在我的项目,我让R,G,B,A的3D纹理的是相同的值。但我无法获得上述链接的结果。你能帮我解决使用GLSL的混合问题吗?

+0

混合由HW自身完成,而不是由GLSL中的着色器完成,所以您应该将'glEnable'和'glBlendFunc'保持原样并保留在GLSL项目中,并且只输出来自片段着色器的颜色,而不处理混合方程。只有当你将每个Blended原语作为单独的渲染传递给/从非常慢的纹理时才会起作用,除非原始类型的数量不高。 – Spektre

+0

例如,参见[我在GLSL中的简单大气散射着色器](http://stackoverflow.com/a/19659648/2521214),它结合了gfx卡和GLSL着色器的本地混合(尽管在2遍渲染中没有任何关系与混合) – Spektre

+1

这是光线投射,混合确实是算法的一部分。 – kaerimasu

回答

1

在预乘alpha颜色空间中进行计算是很自然的。它更适合于气体现象的排放吸收。相应公式是:

C = Cs + (1 - As)*Cd 
A = 1 - (1 - As)*(1 - Ad) = As + (1 - As)*Ad 

虽然可以做在非预乘alpha颜色空间的计算,将需要除以阿尔法值和大体上更加复杂。 (你的代码在非预乘,不考虑到这一点......)

因此,要建立OpenGL的混合使用:

glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); 

,你在着色器使用这个公式:

accColor = sampleColor + accColor*(1-sampleColor.a); 

您在生成3D纹理时也必须考虑到这一点。例如,对于所有像素R = G = B = A对应于白色雾状物质的纹理,因此您必须在黑暗背景下查看它。

相关问题