2012-03-20 3 views
16

Пиксельное освещение является распространенной проблемой во многих приложениях OpenGL, поскольку стандартное освещение OpenGL имеет очень низкое качество.Generic GLSL Lighting Shader

Я хочу использовать программу GLSL для освещения на пикселе в моей программе OpenGL вместо per-vertex. Просто Диффузное освещение, но с туманом, текстурой и текстурой-альфа, по крайней мере.

Я начал с 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 прекрасно работает, кроме того, что он выглядит уродливым на очень больших поверхностях. Я triple проверил мои нормали, они в порядке.

В коде выше есть что-то неправильное? OR Скажите, почему нет генераторного освещения Shader для этой актуальной задачи (свет на основе точки с удалением расстояния: свеча, если хотите) - не должно быть только одного правильного способа сделать это? Я не хочу bump/normal/parallax/toon/blur/любые эффекты. Я просто хочу, чтобы мое освещение лучше работало с большими полигонами.

Все найденные учебники полезны только для освещения одного объекта, когда камера находится на 0,0,0, обращенной к ортогональному объекту. Вышеупомянутое единственное, что было найдено, по крайней мере, похоже на то, что я хочу сделать.

+1

Очевидное первое: вы связали сэмплер, правильны ли ваши текстурные коорды и нормали, показывает ли он геометрию, если вы установите gl_FragColor на фиксированный цвет?С шейдерами мне легче обвести голову, используя и добавляя небольшие функции по одному за раз, не имея возможности войти в них и проследить их: стр. – Robinson

+0

Sampler - TEXTURE_2D, и он связан с рендерингом polys. Текстурные координаты правильны, поскольку нормальное освещение openGL работает безупречно. Нормали идеальны (как уже было сказано). Да, это показывает Геометрию при установке gl_FragColor на фиксированный цвет или только на texColor. – Rock

ответ

10

Я настоятельно рекомендую вам прочитать this article, чтобы увидеть, как стандарт ADS молнии осуществляется в пределах GLSL.That является GL 4.0, но не проблема, чтобы приспособиться к вашей версии:

Также вы действуете в представлении (камеры) пространство так, DON "T отрицает вектор глаза:

vec3 eyeDir = normalize(-position); 

я имел довольно схожие проблемы с вашим, потому что я также отрицается вектор глаз забывание, что она превращается в вид space.Your диффузного и зеркального отражения расчетов, как представляется, неправильно в текущем сценарии. На вашем месте я бы вообще не использовал данные из фиксированного конвейера, а насколько бы это ни было в шейдере? Вот метод для расчета диффузного и зеркального в на фрагменте 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. 
} 

Кроме того, я не хотел бы предложить вам, используя уравнение затухания у вас есть здесь, это трудно control.If вы хотите добавить ослабление на основе радиуса света there is this nice blog post: