简体   繁体   中英

multitexture additive blending in opengl

I want an effect that a metal surface that has a strong sun reflection virtually turns white in the light. It worked pretty well with two pass rendering and additive blending the second pass (with a nearly white texture and highmost specularlight) over the first one (metallic).

However, for performance, I want to switch to MultiTexturing, but there is no such thing as additive blending there, only

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);

none of these works as an additive blend. :-(

My second question: is there a possibility to have the second texture be more shiny than the first texture on the same triangle? It seems that using glMaterial overrides the material of the other texture.

could the solution probably be a good glTexEnvi - hack that would simulate the effect of a texture with strong shininess?

guys, I finally made it by writing a shader for that purpose! Oddly enough, I finally didn't use additive blending (just change one line in the shader to achieve that seriously) but extended the idea so that the second texture would be a specular map - so that its texture would only be seen when the specular light hits it!

Most of the effect could be achieved through the fact that my own shader can simply process a value for specularity of much above 1 - evil OpenGL would clip it to 1 without asking :-(

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

The Vertex Shader:

   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
     "}") ; 

And the Fragment Shader:

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);"
    "}");

It is not at all optimised and at the moment just a proof-of-concept without artistic skill, but here is the result:

Render without any shaders, but multitexture on "modulate". You can see some dirt on the vessel, but poor specular light:

http://i.stack.imgur.com/8whUC.jpg

Rendered with shaders - the dirt is there although not clearly to be seen on this shot. Heavy specular light, that can even be strenghtened by rising the specularity-value in glMaterialfv :

http://i.stack.imgur.com/IpnTa.jpg

Rendered with an exaggerated 4x shininess. You can see the dirt texture now in the glow:

http://i.stack.imgur.com/MPAm3.jpg

One question remains - why on earth I cannot use gl_TexCoord(1) - the result is no texture but pixel render artefacts although multitexturing works fine without the shader. Any help appreciated.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM