Освещение на основе пикселей является распространенной проблемой во многих приложениях OpenGL, поскольку стандартное освещение OpenGL имеет очень низкое качество.
Я хочу использовать программу GLSL, чтобы вместо освещения на основе пикселей в моей программе OpenGLиз каждой вершины.Просто диффузное освещение, но с туманом, текстурой и текстурой-альфа как минимум.
Я начал с этого шейдера :
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 прекрасно работает, за исключением того факта, что оно выглядит некрасиво на очень больших поверхностях.Я трижды проверил свои нормали, они в порядке.
Что-то не так в приведенном выше коде?ИЛИ Скажите, почему для этой задачи не существует универсального шейдера освещения (точечный свет с уменьшением расстояния: свеча, если хотите) - разве не должен быть только один правильный способ сделать это?Я не хочу удар / нормальный / параллакс / toon / blur / любые эффекты.Я просто хочу, чтобы мое освещение работало лучше с более крупными полигонами.
Все найденные мною учебные пособия полезны только для освещения одного объекта, когда камера находится на уровне 0,0,0 лицом, перпендикулярным к объекту.Выше приведено только то, что, по крайней мере, похоже на то, что я хочу сделать.