Qt 中使用 OpenGL 实现光照效果主要基于 OpenGL 的光照模型和着色器编程。以下是 Qt OpenGL 光照实现的核心原理:
OpenGL 使用 Phong 光照模型,包含三个主要光照分量:
环境光(Ambient):场景中的基础光照,没有方向性
漫反射光(Diffuse):与表面法线和光线方向相关的散射光
镜面光(Specular):在特定角度可见的高光反射
cpp
// 启用光照
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0); // 启用0号光源
// 设置光源属性
GLfloat lightPosition[] = {1.0f, 1.0f, 1.0f, 1.0f};
GLfloat lightAmbient[] = {0.2f, 0.2f, 0.2f, 1.0f};
GLfloat lightDiffuse[] = {0.8f, 0.8f, 0.8f, 1.0f};
GLfloat lightSpecular[] = {1.0f, 1.0f, 1.0f, 1.0f};
glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
glLightfv(GL_LIGHT0, GL_AMBIENT, lightAmbient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDiffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, lightSpecular);
// 设置材质属性
GLfloat materialAmbient[] = {0.7f, 0.7f, 0.7f, 1.0f};
GLfloat materialDiffuse[] = {0.8f, 0.8f, 0.8f, 1.0f};
GLfloat materialSpecular[] = {1.0f, 1.0f, 1.0f, 1.0f};
GLfloat materialShininess = 100.0f;
glMaterialfv(GL_FRONT, GL_AMBIENT, materialAmbient);
glMaterialfv(GL_FRONT, GL_DIFFUSE, materialDiffuse);
glMaterialfv(GL_FRONT, GL_SPECULAR, materialSpecular);
glMaterialf(GL_FRONT, GL_SHININESS, materialShininess);
使用着色器实现光照效果:
glsl
#version 330 core
layout(location = 0) in vec3 position;
layout(location = 1) in vec3 normal;
out vec3 FragPos;
out vec3 Normal;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
FragPos = vec3(model * vec4(position, 1.0));
Normal = mat3(transpose(inverse(model))) * normal;
gl_Position = projection * view * vec4(FragPos, 1.0);
}
glsl
#version 330 core
in vec3 FragPos;
in vec3 Normal;
out vec4 FragColor;
uniform vec3 lightPos;
uniform vec3 viewPos;
uniform vec3 lightColor;
uniform vec3 objectColor;
void main()
{
// 环境光
float ambientStrength = 0.1;
vec3 ambient = ambientStrength * lightColor;
// 漫反射
vec3 norm = normalize(Normal);
vec3 lightDir = normalize(lightPos - FragPos);
float diff = max(dot(norm, lightDir), 0.0);
vec3 diffuse = diff * lightColor;
// 镜面光
float specularStrength = 0.5;
vec3 viewDir = normalize(viewPos - FragPos);
vec3 reflectDir = reflect(-lightDir, norm);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32);
vec3 specular = specularStrength * spec * lightColor;
vec3 result = (ambient + diffuse + specular) * objectColor;
FragColor = vec4(result, 1.0);
}
<