首页 文章

通用GLSL照明着色器

提问于
浏览
17

基于像素的照明是许多OpenGL应用中的常见问题,因为标准的OpenGL照明质量非常差 .

我想使用一个GLSL程序在我的OpenGL程序中使用基于每个像素的照明,而不是每个顶点 . 只是漫射光,但至少有雾,纹理和纹理-α .

我从this shader开始:

texture.vert:

varying vec3 position;
varying vec3 normal; 

void main(void) 
{
  gl_Position       = gl_ModelViewProjectionMatrix * gl_Vertex;
  gl_FrontColor     = gl_Color;
  gl_TexCoord[0]    = gl_MultiTexCoord0; 
  normal        = normalize(gl_NormalMatrix * gl_Normal);
  position      = vec3(gl_ModelViewMatrix * gl_Vertex);
}

texture.frag:

uniform sampler2D Texture0;
uniform int ActiveLights;

varying vec3 position;
varying vec3 normal; 

void main(void) 
{
  vec3 lightDir;
  float  attenFactor;
  vec3 eyeDir           = normalize(-position); // camera is at (0,0,0) in ModelView space
  vec4 lightAmbientDiffuse  = vec4(0.0,0.0,0.0,0.0);
  vec4 lightSpecular        = vec4(0.0,0.0,0.0,0.0);    

  // iterate all lights
  for (int i=0; i<ActiveLights; ++i)
  {
    // attenuation and light direction
    if (gl_LightSource[i].position.w != 0.0)
    {
        // positional light source
        float dist  = distance(gl_LightSource[i].position.xyz, position);
        attenFactor = 1.0/( gl_LightSource[i].constantAttenuation + 
                    gl_LightSource[i].linearAttenuation * dist +
                    gl_LightSource[i].quadraticAttenuation * dist * dist );
        lightDir    = normalize(gl_LightSource[i].position.xyz - position);
    }       
    else 
    {           
        // directional light source         
        attenFactor = 1.0;          
        lightDir    = gl_LightSource[i].position.xyz;       
    }       
    // ambient + diffuse        
    lightAmbientDiffuse     += gl_FrontLightProduct[i].ambient*attenFactor;     
    lightAmbientDiffuse     += gl_FrontLightProduct[i].diffuse * max(dot(normal, lightDir), 0.0) * attenFactor; 
    // specular     
    vec3 r      = normalize(reflect(-lightDir, normal));
    lightSpecular   += gl_FrontLightProduct[i].specular * 
                  pow(max(dot(r, eyeDir), 0.0), gl_FrontMaterial.shininess) *
                  attenFactor;  
  }     
  // compute final color    
  vec4 texColor = gl_Color * texture2D(Texture0, gl_TexCoord[0].xy);    
  gl_FragColor  = texColor * (gl_FrontLightModelProduct.sceneColor + lightAmbientDiffuse) + lightSpecular;

  float fog = (gl_Fog.end - gl_FogFragCoord) * gl_Fog.scale;    // Intensität berechnen 
  fog       = clamp(fog, 0.0, 1.0);                 // Beschneiden 
  gl_FragColor  = mix(gl_Fog.color, gl_FragColor, fog);         // Nebelfarbe einmischen 
}

评论是德语,因为它是发布此代码的德国站点,抱歉 .

但是所有这些着色器都会让一切都变得非常黑暗 . 根本没有灯光效果 - 但着色器代码编译 . 如果我只在片段着色器中使用GL_LIGHT0,那么它似乎可以工作,但只适用于面向相机的多边形,而我的地板多边形只是非常暗 . 具有RGBA纹理的四边形也没有显示透明度的迹象 . 我对Modelview矩阵使用标准glRotate / Translate,对我的多边形使用glVertex / Normal . 除了在非常大的表面上看起来很丑的事实之外,OpenGL照明工作得很好 . 我检查了我的法线,他们很好 .

上面的代码有什么问题吗?或者告诉我为什么没有通用照明着色器用于这个实际任务(基于点的光与距离衰减:蜡烛,如果你愿意) - 不应该有一个正确的方法来做到这一点?我不想要碰撞/正常/视差/香椿/模糊/任何影响 . 我只是希望我的灯光在更大的多边形上表现得更好 .

我发现的所有教程仅在相机处于与对象正交的0,0,0时对单个对象进行照明 . 以上是唯一一个发现至少看起来像我想做的事情 .

1 回答

  • 11

    我强烈建议你阅读this article以了解标准ADS闪电是如何在GLSL中完成的 . 这是GL 4.0,但不是要调整到你的版本的问题:

    你也在视图(相机)空间中操作,所以DON“T否定眼睛矢量:

    vec3 eyeDir  = normalize(-position);
    

    我的问题与你的问题非常类似,因为我也否定了眼睛向量,忘记了它被转换为视图空间 . 在当前场景中,你的漫反射和镜面反射计算似乎也是错误的 . 在你的位置我不会使用来自根本修复管道,否则在着色器中做什么呢?这是计算每个片段ADS点闪电中的漫反射和镜面反射的方法:

    void ads( int lightIndex,out vec3 ambAndDiff, out vec3 spec )
    {
    
    
    vec3 s =  vec3(lights[lightIndex].Position -  posOut) ;
    vec3 v = normalize( posOut.xyz );
    vec3 n = normalize(normOut); 
    vec3 h = normalize(v+s) ;// half vector (read in the web on what it is )
    
    
        vec3 diffuse =  ((Ka+ lights[lightIndex].Ld) * Kd *  max( 0.0,dot(n, v) )) ;
         spec =  Ks *  pow( max(0.0, dot(n,h) ), Shininess ) ;  
    
    
     ambAndDiff =   diffuse ;
    
    /// Ka-material ambient factor
    /// Kd-material diffuse factor
    /// Ks-material specular factor.
    /// lights[lightIndex].Ld-lights diffuse factor;you may also add La and Ls if you want to have even more control of the light shading.
    }
    

    另外我不建议你使用你在这里的衰减方程,它很难控制 . 如果你想添加基于光半径的衰减there is this nice blog post:

相关问题