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

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

我从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纹理的四边形也没有显示透明的迹象。
我将标准glRotate / Translate用于Modelview矩阵,将glVertex / Normal用于我的多边形。除了在非常大的表面上看起来很难看之外,OpenGL照明效果还不错。我三重检查了我的正常情况,它们很好。

上面的代码有问题吗?
要么
告诉我为什么没有用于此实际任务的通用照明明暗器(具有距离衰减的基于点的光源:如果可以的话,可以使用蜡烛)-是否应该只有一种正确的方法?我不想要凹凸/正常/视差/卡通/模糊/任何效果。我只是希望我的照明在使用较大的多边形时能表现更好。

我发现的所有教程仅在相机位于与对象正交的0,0,0时用于照亮单个对象时才有用。以上是唯一发现至少看起来像我想做的事情的事情。

最佳答案

我强烈建议您阅读 this article来查看GLSL中标准ADS闪电的处理方式。那就是GL 4.0,但调整到您的版本不是问题:

另外,您在视图(相机)空间中操作,所以不要忽略眼睛向量:

    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:

关于opengl - 通用GLSL照明明暗器,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9780909/

10-12 16:30