OpenGL - 如何在不旋转物体的情况下同时旋转光源?
OpenGL - How to rotate light source without rotating object at the same time?
我正在学习 learnopengl 教程,并且正在尝试基本照明教程中的练习之一 -
Try to move the light source around the scene over time using either
sin or cos.
虽然在我的例子中,我使用的是 SDL,这意味着我不能使用以下等式来旋转我的光源:
lightPos.x = 1.0f + sin(glfwGetTime()) * 2.0f;
lightPos.y = sin(glfwGetTime() / 2.0f) * 1.0f;
现在,当我旋转我的物体时,我的光源也随之旋转,但是我希望我的光源与我的物体分开旋转。这就是我在处理光线和物体旋转的渲染循环中所拥有的:
void OpenGLWindow::render()
{
lightPos.x = 1.0f + sin(SDL_GetTicks()/1000.0f) * 2.0f;
lightPos.y = sin((SDL_GetTicks()/1000.0f) / 2.0f) * 1.0f;
glm::mat4 model(1.0f);
//model = glm::translate(model, lightPos);
model = glm::rotate(model, lightPos.z, glm::vec3(0.0f, 0.0f, 1.0f));
//model = glm::rotate(model, lightPos.y, glm::vec3(0.0f, 1.0f, 0.0f));
model = glm::rotate(model, lightPos.x, glm::vec3(1.0f, 0.0f, 0.0f));
int modelMatLocation = glGetUniformLocation(shader, "lightMatrix");
glUniformMatrix4fv(modelMatLocation, 1, false, &model[0][0]);
// NOTE: glm::translate/rotate/scale apply the transformation by right-multiplying by the
// corresponding transformation matrix (T). IE glm::translate(M, v) = M * T, not T*M
// This means that the transformation you apply last, will effectively occur first
glm::mat4 modelMat(1.0f);
modelMat = glm::translate(modelMat, parentEntity.position);
modelMat = glm::rotate(modelMat, parentEntity.rotation.z, glm::vec3(0.0f, 0.0f, 1.0f));
modelMat = glm::rotate(modelMat, parentEntity.rotation.y, glm::vec3(0.0f, 1.0f, 0.0f));
modelMat = glm::rotate(modelMat, parentEntity.rotation.x, glm::vec3(1.0f, 0.0f, 0.0f));
modelMat = glm::scale(modelMat, parentEntity.scale);
int modelMatrixLoc = glGetUniformLocation(shader, "modelMatrix");
glUniformMatrix4fv(modelMatrixLoc, 1, false, &modelMat[0][0]);
}
这就是我的顶点着色器:
in vec3 position;
out vec3 FragPos;
out vec3 Normal;
uniform mat4 projectionMatrix;
uniform mat4 viewingMatrix;
uniform mat4 modelMatrix;
uniform mat4 lightMatrix;
void main()
{
vec4 transformedPosition = projectionMatrix * viewingMatrix * modelMatrix * lightMatrix * vec4(position, 1.0f);
gl_Position = transformedPosition;
FragPos = vec3(modelMatrix * vec4(position, 1.0));
Normal = mat3(transpose(inverse(modelMatrix))) * position;
}
片段着色器:
out vec4 outColor;
in vec3 Normal;
in vec3 FragPos;
uniform vec3 lightPos;
uniform vec3 objectColor;
uniform vec3 lightColor;
uniform vec3 viewPos;
void main()
{
float ambientStrength = 0.06;
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.6;
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;
outColor = vec4(result, 1.0);
}
如何只旋转光源,而不旋转物体?
如果要旋转光源,则必须变换 lightPos
而不是旋转模型。这也更有效,因为它每帧只需要一个矩阵变换(而不是每个顶点一个)。代码应如下所示:
// C++
glm::vec4 lightPos(...) // <-- The light position you currently use
glm::mat4 lightM(1.0f);
lightM = glm::rotate(lightM, lightRotation.z, glm::vec3(0.0f, 0.0f, 1.0f));
lightM = glm::rotate(lightM, lightRotation.y, glm::vec3(0.0f, 1.0f, 0.0f));
lightM = glm::rotate(lightM, lightRotation.x, glm::vec3(1.0f, 0.0f, 0.0f));
glm::vec4 rotatedLightPos = lightM * lightPos;
glUniform3f(lightPosLocation, rotatedLightPos.x, rotatedLightPos.y, rotatedLightPos.z);
顶点着色器:
// GLSL
in vec3 position;
out vec3 FragPos;
out vec3 Normal;
uniform mat4 projectionMatrix;
uniform mat4 viewingMatrix;
uniform mat4 modelMatrix;
void main()
{
vec4 transformedPosition = projectionMatrix * viewingMatrix * modelMatrix * vec4(position, 1.0f);
gl_Position = transformedPosition;
FragPos = vec3(modelMatrix * vec4(position, 1.0));
Normal = mat3(transpose(inverse(modelMatrix))) * position;
}
片段着色器保持原样。
我正在学习 learnopengl 教程,并且正在尝试基本照明教程中的练习之一 -
Try to move the light source around the scene over time using either sin or cos.
虽然在我的例子中,我使用的是 SDL,这意味着我不能使用以下等式来旋转我的光源:
lightPos.x = 1.0f + sin(glfwGetTime()) * 2.0f;
lightPos.y = sin(glfwGetTime() / 2.0f) * 1.0f;
现在,当我旋转我的物体时,我的光源也随之旋转,但是我希望我的光源与我的物体分开旋转。这就是我在处理光线和物体旋转的渲染循环中所拥有的:
void OpenGLWindow::render()
{
lightPos.x = 1.0f + sin(SDL_GetTicks()/1000.0f) * 2.0f;
lightPos.y = sin((SDL_GetTicks()/1000.0f) / 2.0f) * 1.0f;
glm::mat4 model(1.0f);
//model = glm::translate(model, lightPos);
model = glm::rotate(model, lightPos.z, glm::vec3(0.0f, 0.0f, 1.0f));
//model = glm::rotate(model, lightPos.y, glm::vec3(0.0f, 1.0f, 0.0f));
model = glm::rotate(model, lightPos.x, glm::vec3(1.0f, 0.0f, 0.0f));
int modelMatLocation = glGetUniformLocation(shader, "lightMatrix");
glUniformMatrix4fv(modelMatLocation, 1, false, &model[0][0]);
// NOTE: glm::translate/rotate/scale apply the transformation by right-multiplying by the
// corresponding transformation matrix (T). IE glm::translate(M, v) = M * T, not T*M
// This means that the transformation you apply last, will effectively occur first
glm::mat4 modelMat(1.0f);
modelMat = glm::translate(modelMat, parentEntity.position);
modelMat = glm::rotate(modelMat, parentEntity.rotation.z, glm::vec3(0.0f, 0.0f, 1.0f));
modelMat = glm::rotate(modelMat, parentEntity.rotation.y, glm::vec3(0.0f, 1.0f, 0.0f));
modelMat = glm::rotate(modelMat, parentEntity.rotation.x, glm::vec3(1.0f, 0.0f, 0.0f));
modelMat = glm::scale(modelMat, parentEntity.scale);
int modelMatrixLoc = glGetUniformLocation(shader, "modelMatrix");
glUniformMatrix4fv(modelMatrixLoc, 1, false, &modelMat[0][0]);
}
这就是我的顶点着色器:
in vec3 position;
out vec3 FragPos;
out vec3 Normal;
uniform mat4 projectionMatrix;
uniform mat4 viewingMatrix;
uniform mat4 modelMatrix;
uniform mat4 lightMatrix;
void main()
{
vec4 transformedPosition = projectionMatrix * viewingMatrix * modelMatrix * lightMatrix * vec4(position, 1.0f);
gl_Position = transformedPosition;
FragPos = vec3(modelMatrix * vec4(position, 1.0));
Normal = mat3(transpose(inverse(modelMatrix))) * position;
}
片段着色器:
out vec4 outColor;
in vec3 Normal;
in vec3 FragPos;
uniform vec3 lightPos;
uniform vec3 objectColor;
uniform vec3 lightColor;
uniform vec3 viewPos;
void main()
{
float ambientStrength = 0.06;
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.6;
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;
outColor = vec4(result, 1.0);
}
如何只旋转光源,而不旋转物体?
如果要旋转光源,则必须变换 lightPos
而不是旋转模型。这也更有效,因为它每帧只需要一个矩阵变换(而不是每个顶点一个)。代码应如下所示:
// C++
glm::vec4 lightPos(...) // <-- The light position you currently use
glm::mat4 lightM(1.0f);
lightM = glm::rotate(lightM, lightRotation.z, glm::vec3(0.0f, 0.0f, 1.0f));
lightM = glm::rotate(lightM, lightRotation.y, glm::vec3(0.0f, 1.0f, 0.0f));
lightM = glm::rotate(lightM, lightRotation.x, glm::vec3(1.0f, 0.0f, 0.0f));
glm::vec4 rotatedLightPos = lightM * lightPos;
glUniform3f(lightPosLocation, rotatedLightPos.x, rotatedLightPos.y, rotatedLightPos.z);
顶点着色器:
// GLSL
in vec3 position;
out vec3 FragPos;
out vec3 Normal;
uniform mat4 projectionMatrix;
uniform mat4 viewingMatrix;
uniform mat4 modelMatrix;
void main()
{
vec4 transformedPosition = projectionMatrix * viewingMatrix * modelMatrix * vec4(position, 1.0f);
gl_Position = transformedPosition;
FragPos = vec3(modelMatrix * vec4(position, 1.0));
Normal = mat3(transpose(inverse(modelMatrix))) * position;
}
片段着色器保持原样。