Zet*_*zer 5 c++ opengl qt glsl light
我正在尝试为我的硕士学位(以及我的技能)制作一个小型 3D 引擎。我对镜面反射有疑问。(我很抱歉插图图像的链接,但我还没有足够的声誉)。所有来源都可以在我的 GitHub 上找到:DWRenderer
在这里,我们正对着物体,但相机和灯光都在前面。正如我们所看到的,物体后面有一个反射。
为了描述实际参数,所有计算都是在世界空间中进行的(通常......对于这个问题,我有疑问)。我将相机放在位置 vec3(0, 0, 3) 进行测试,光线只是 vec3(1.2, 1, 2) 处由立方体表示的点。我在 Ubuntu 下使用 Qt 5.4 和 OpenGL 4.1 以及 Nvidia 驱动程序。
这是我的顶点着色器:
#version 410 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 normal;
out vec3 Normal;
out vec3 FragPos;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
uniform mat3 normalMatrix;
void main()
{
gl_Position = projection * view * model * vec4(position, 1.0f);
FragPos = vec3(model * vec4(position, 1.0f));
Normal = normalMatrix * normal;
}
Run Code Online (Sandbox Code Playgroud)
还有我的片段着色器:
#version 410 core
out vec4 color;
in vec3 Normal;
in vec3 FragPos;
struct Material {
vec3 ambient;
vec3 diffuse;
vec3 specular;
float shininess;
};
struct Light {
vec3 position;
vec3 ambient;
vec3 diffuse;
vec3 specular;
};
uniform Material material;
uniform Light light;
uniform vec3 viewPos;
void main()
{
// Vectors
vec3 norm = normalize(Normal);
vec3 lightDir = normalize(light.position - FragPos);
vec3 viewDir = normalize(viewPos - FragPos);
vec3 reflectDir = reflect(-lightDir, norm);
// Ambient
vec3 ambient = material.ambient * light.ambient;
// Diffuse
float diff = clamp(dot(lightDir, norm), 0.0, 1.0);
vec3 diffuse = diff * material.diffuse * light.diffuse;
// Specular - The bug seems only here
float spec = pow(clamp(dot(viewDir, reflectDir), 0.0, 1.0), material.shininess);
vec3 specular = spec * material.specular * light.specular;
vec3 result = (diffuse + specular + ambient);
color = vec4(result, 1.0f);
// For test vectors
//color = vec4(specular, 1.0f);
}
Run Code Online (Sandbox Code Playgroud)
游戏循环中的代码(实时绘制GL,时间间隔为16毫秒)用于初始化统一变量(着色器的相机位置是固定的,我可以转动我的立方体来检查错误。灯光的位置在“initializeGL”中并且也是固定的):
// Draw cube
m_cubeShader->useShaderProgram();
GLint lightPosLoc = glGetUniformLocation(m_cubeShader->getId(), "light.position");
GLint viewPosLoc = glGetUniformLocation(m_cubeShader->getId(), "viewPos");
GLint matAmbientLoc = glGetUniformLocation(m_cubeShader->getId(), "material.ambient");
GLint matDiffuseLoc = glGetUniformLocation(m_cubeShader->getId(), "material.diffuse");
GLint matSpecularLoc = glGetUniformLocation(m_cubeShader->getId(), "material.specular");
GLint matShineLoc = glGetUniformLocation(m_cubeShader->getId(), "material.shininess");
GLint lightAmbientLoc = glGetUniformLocation(m_cubeShader->getId(), "light.ambient");
GLint lightDiffuseLoc = glGetUniformLocation(m_cubeShader->getId(), "light.diffuse");
GLint lightSpecularLoc = glGetUniformLocation(m_cubeShader->getId(), "light.specular");
glUniform3f(lightAmbientLoc, 0.2f, 0.2f, 0.2f);
glUniform3f(lightDiffuseLoc, 0.5f, 0.5f, 0.5f);
glUniform3f(lightSpecularLoc, 1.0f, 1.0f, 1.0f);
glUniform3f(matAmbientLoc, 1.0f, 0.5f, 0.31f);
glUniform3f(matDiffuseLoc, 1.0f, 0.5f, 0.31f);
glUniform3f(matSpecularLoc, 0.5f, 0.5f, 0.5f);
glUniform1f(matShineLoc, 32.0f);
glUniform3f(viewPosLoc, 0.0f, 0.0f, 3.0f); // For testing a bug - Unresolved
//glUniform3f(viewPosLoc, m_camera->getPosition().x, m_camera->getPosition().y, m_camera->getPosition().z);
glUniform3f(lightPosLoc, m_lightPos.x, m_lightPos.y, m_lightPos.z);
glm::mat4 model;
glm::mat4 view;
glm::mat4 projection;
glm::mat3 normalMatrix;
normalMatrix = glm::mat3(glm::transpose(glm::inverse(model)));
view = m_camera->getViewMatrix();
projection = glm::perspective(glm::radians(m_camera->getFov()), (GLfloat)m_screenWidth / (GLfloat)m_screenHeight, 0.1f, 100.0f);
GLint normalMatrixLoc = glGetUniformLocation(m_cubeShader->getId(), "normalMatrix");
GLint modelLoc = glGetUniformLocation(m_cubeShader->getId(), "model");
GLint viewLoc = glGetUniformLocation(m_cubeShader->getId(), "view");
GLint projectionLoc = glGetUniformLocation(m_cubeShader->getId(), "projection");
glUniformMatrix3fv(normalMatrixLoc, 1, GL_FALSE, glm::value_ptr(normalMatrix));
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, glm::value_ptr(projection));
glBindVertexArray(m_cubeVAO);
glDrawArrays(GL_TRIANGLES, 0, 36);
glBindVertexArray(0);
// Draw light
m_lightShader->useShaderProgram();
model = glm::mat4();
model = glm::translate(model, m_lightPos);
model = glm::scale(model, glm::vec3(0.2f));
modelLoc = glGetUniformLocation(m_lightShader->getId(), "model");
viewLoc = glGetUniformLocation(m_lightShader->getId(), "view");
projectionLoc = glGetUniformLocation(m_lightShader->getId(), "projection");
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, glm::value_ptr(projection));
glBindVertexArray(m_lightVAO);
glDrawArrays(GL_TRIANGLES, 0, 36);
glBindVertexArray(0);
Run Code Online (Sandbox Code Playgroud)
我尝试对视图空间进行计算,但它不起作用。我尝试修改/规范化/使用 max() 而不是钳制(),但在问题上几个小时后。我没有任何想法。
lightDir
如果(从片段到光的方向)沿(片段的法线向量)方向,则只有norm
漫反射光和镜面反射光。如果它们是针对您的,则可以不用漫射光和镜面光。换句话说,如果没有任何漫射光(因为diff
)0.0
,那么也就不存在任何镜面反射光。像这样调整你的代码:
void main()
{
// Vectors
vec3 norm = normalize(Normal);
vec3 lightDir = normalize(light.position - FragPos);
vec3 viewDir = normalize(viewPos - FragPos);
vec3 reflectDir = reflect(-lightDir, norm);
// Ambient
vec3 ambient = material.ambient * light.ambient;
vec3 result = ambient;
float dotNvLd = dot( norm, lightDir );
if ( dotNvLd > 0.0 ) // test if normal vector not directed against vector to light position
{
// Diffuse
float diff = min( dotNvLd, 1.0 );
vec3 diffuse = diff * material.diffuse * light.diffuse;
// Specular - The bug seems only here
float spec = pow(clamp(dot(viewDir, reflectDir), 0.0, 1.0), material.shininess);
vec3 specular = spec * material.specular * light.specular;
result = (diffuse + specular + ambient);
}
color = vec4(result, 1.0f);
// For test vectors
//color = vec4(specular, 1.0f);
}
Run Code Online (Sandbox Code Playgroud)