【问题标题】:multitexture additive blending in openglopengl中的多纹理添加剂混合
【发布时间】:2013-02-09 22:26:02
【问题描述】:

我想要一种效果,即具有强烈阳光反射的金属表面在光线下实际上会变成白色。它在两遍渲染和第二遍渲染(具有近乎白色的纹理和最高的镜面光)在第一遍(金属)上的添加混合时效果很好。

但是,为了性能,我想切换到 MultiTexturing,但是那里没有加法混合之类的东西,只有

glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,  GL_BLEND);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);

这些都不能用作添加剂混合物。 :-(

我的第二个问题:是否有可能让第二个纹理比同一个三角形上的第一个纹理更亮?似乎使用 glMaterial 会覆盖其他纹理的材质。

解决方案可能是一个很好的 glTexEnvi - hack,可以模拟具有强烈光泽的纹理效果?

【问题讨论】:

  • 目前尚不清楚您要在这里实现什么。你想要做的数学是什么?
  • 数学是颜色 = tex1 + tex2,甚至颜色 = tex1 + tex2*2
  • 您是否考虑过使用可编程管线(着色器)?像你这样的问题是它首先被创建的原因@Kenobi。如果您只想添加颜色,GL_ADD 应该是一个可用的操作。
  • @Kenobi:那不是 Alpha 混合。
  • @BartekBanachewicz ,真正的 GL_ADD 有效,但添加的纹理不会受到任何光照的影响。所以它是全白的,而不仅仅是高光。着色器会很棒 - 刚刚学会了如何编译它们 - 但我不知道如何编写一个简单地执行此操作并传递所有照明信息的着色器。

标签: c++ opengl alpha blending


【解决方案1】:

伙计们,我终于为此目的编写了一个着色器!奇怪的是,我最终没有使用加法混合(只是在着色器中改变一条线来实现这一点),而是扩展了这个想法,使第二个纹理成为高光贴图 - 这样它的纹理只有在高光时才能看到光照射它!

大部分效果可以通过我自己的着色器可以简单地处理 远高于 1 的高光度值来实现 - 邪恶的 OpenGL 会在不询问的情况下将其剪切为 1 :-( p>

GLfloat mat_specular[] ={ 2, 2, 2, 1 }; glMaterialfv(GL_FRONT, GL_SPECULAR,mat_specular); //works here :-)

顶点着色器:

   vs = const_cast<char *>(
     "varying vec4 diffuse, ambient;"
     "varying vec3 normal, lightDir, halfVector;"
     "uniform float time;"
     "void main(void){"
       "normal = normalize(gl_NormalMatrix * gl_Normal);"  //Transform Normal into Eye Space
       "lightDir = normalize(vec3(gl_LightSource[0].position));"
       "halfVector = normalize(gl_LightSource[0].halfVector.xyz);"
       "diffuse = gl_FrontMaterial.diffuse * gl_LightSource[0].diffuse;"
       "ambient = gl_FrontMaterial.ambient * gl_LightSource[0].ambient + gl_FrontMaterial.ambient * gl_LightModel.ambient;"
       "gl_TexCoord[0]  = gl_MultiTexCoord0;"
       "gl_Position = ftransform();"     //Apply Changes
     "}") ; 

片段着色器:

fs =const_cast<char *>( 
  "uniform sampler2D tex1;"
  "uniform sampler2D tex2;"      
  "varying vec4 diffuse,ambient;"
  "varying vec3 normal, lightDir, halfVector;"
  "void main() {"
    "vec3 n,halfV,colortexel,colorfragment;"
    "vec4 texel,specularmap;"
    "float NdotL,NdotHV,alphatexel,alphafragment;\n"
    "colorfragment = ambient.rgb;"    //initialize color with ambient part
    "alphafragment = gl_FrontMaterial.diffuse.a;"
    "n = normalize(normal);"   //copy to write
    "NdotL = max(dot(normal, lightDir), -0.1);"
    "specularmap = texture2D(tex2,gl_TexCoord[0].st);"   //MUST Be started first!
    "texel = texture2D(tex1,gl_TexCoord[0].st*2.0);" 

    "if (NdotL>=-0.1) {"
        "colorfragment += diffuse.rgb * NdotL;"
        "halfV = normalize(halfVector);"
        "NdotHV = max (dot(n,halfV),0.0);"
        "colorfragment += gl_FrontMaterial.specular.rgb * specularmap.rgb * gl_LightSource[0].specular.rgb * pow(NdotHV, gl_FrontMaterial.shininess);"            
    "}"         

    "colortexel = texel.rgb; alphatexel = texel.a;"         
    "gl_FragColor = vec4(colortexel * colorfragment, alphatexel * alphafragment);"
    "}");

它根本没有优化,目前只是一个没有艺术技巧的概念验​​证,但结果如下:

在没有任何着色器的情况下进行渲染,但在“调制”上使用多纹理。您可以看到容器上有一些污垢,但镜面光很差:

使用着色器渲染 - 虽然在这张照片上看不清楚,但污垢在那里。重镜面光,甚至可以通过增加 glMaterialfv 中的镜面值来加强:

以夸张的 4 倍光泽度渲染。您现在可以在辉光中看到污垢纹理:

还有一个问题 - 为什么我不能使用 gl_TexCoord(1) - 结果是没有纹理,但像素渲染伪影虽然多纹理在没有着色器的情况下工作正常。任何帮助表示赞赏。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多