[英]Point light move with the camera
我目前正在使用 OpenGL 在我的場景中添加一些燈光(定向光、點光源和聚光燈)。 我的定向光和聚光燈似乎工作,但我的點光源仍然跟隨相機。 我想在任意位置設置該點光源的位置,例如 (10, 5, 2)。 因此,我創建了一個片段着色器來管理具有此結構的點光源的多個燈光:
struct PointLight {
vec3 position;
vec3 color;
float constant;
float linear;
float quadratic; };
這里是我將數據發送到片段着色器的代碼:
glm::vec3 pos(-10.f, 5.f, 0.f);
pos = glm::normalize(glm::vec3(viewMatrix * glm::vec4(pos, 1.)));
glUniform3f(pointLightPositionLocation, pos.x, pos.y, pos.z);
glUniform3f(pointLightColorLocation, 0.0f, 1.0f, 0.0f);
glUniform1f(pointLightConstantLocation, 1.0f);
glUniform1f(pointLightLinearLocation, 0.09f);
glUniform1f(pointLightQuadraticLocation, 0.032f);
點的光位置在視圖空間中表示。
頂點着色器:
#version 330
layout(location = 0) in vec3 aPosition;
layout(location = 1) in vec3 aNormal;
layout(location = 2) in vec2 aTexCoords;
out vec3 vViewSpacePosition;
out vec3 vViewSpaceNormal;
out vec2 vTexCoords;
out vec3 vFragPos;
uniform mat4 uModelViewProjMatrix;
uniform mat4 uModelViewMatrix;
uniform mat4 uNormalMatrix;
void main()
{
vViewSpacePosition = vec3(uModelViewMatrix * vec4(aPosition, 1));
vViewSpaceNormal = normalize(vec3(uNormalMatrix * vec4(aNormal, 0)));
vTexCoords = aTexCoords;
gl_Position = uModelViewProjMatrix * vec4(aPosition, 1);
}
最后,我從點光源計算片段顏色的函數:
vec3 calculatePointLight(PointLight light) {
vec3 N = normalize(vViewSpaceNormal);
vec3 L = normalize(light.position - vViewSpacePosition);
vec3 V = normalize(-vViewSpacePosition);
vec3 H = normalize(L + V);
vec4 baseColorFromTexture = SRGBtoLINEAR(texture(uBaseColorTexture, vTexCoords));
vec4 baseColor = baseColorFromTexture * uBaseColorFactor;
float NdotL = clamp(dot(N, L), 0, 1);
float NdotV = clamp(dot(N, V), 0, 1);
float NdotH = clamp(dot(N, H), 0, 1);
float VdotH = clamp(dot(V, H), 0, 1);
float metallic = texture(uMetallicRoughnessTexture, vTexCoords).z * uMetallicFactor;
float roughness = texture(uMetallicRoughnessTexture, vTexCoords).y * uRoughnessFactor;
vec3 cDiff = mix(baseColor.rgb * (1 - dielectricSpecular.r), black, metallic);
vec3 f0 = mix(dielectricSpecular, baseColor.rgb, metallic);
float a = uRoughnessFactor * roughness;
float a2 = a * a;
// You need to compute baseShlickFactor first
float baseShlickFactor = (1 - VdotH);
float shlickFactor = baseShlickFactor * baseShlickFactor; // power 2
shlickFactor *= shlickFactor; // power 4
shlickFactor *= baseShlickFactor; // power 5
vec3 F = f0 + (1 - f0) * shlickFactor;
float deno = NdotL * sqrt(NdotV * NdotV * (1 - a2) + a2) + NdotV * sqrt(NdotL* NdotL * (1 - a2) + a2);
float Vis;
if (deno == 0.) {
Vis = 0;
}
else {
Vis = 0.5 / deno;
}
deno = M_PI * (NdotH * NdotH * (a2 - 1) + 1) * (NdotH * NdotH * (a2 - 1) + 1);
float D;
if (deno == 0.) {
D = 0;
}
else {
D = a2 / deno;
}
vec3 diffuse = cDiff * M_1_PI;
vec3 f_diffuse = (1 - F) * diffuse;
vec3 f_specular = F * Vis * D;
vec4 emissive = texture(uEmissiveTexture, vTexCoords) * vec4(uEmissiveFactor, 1);
vec4 occlusion = texture(uOcclusionTexture, vTexCoords);
// attenuation
float distance = length(light.position - vViewSpacePosition);
float attenuation = 1.0 / (light.constant + light.linear * distance +
light.quadratic * (distance * distance));
f_diffuse *= attenuation;
f_specular *= attenuation;
vec3 color = (f_diffuse + f_specular) * light.color * NdotL + emissive.xyz;
color = mix(color, color * occlusion.x, uOcclusionStrength);
color = LINEARtoSRGB(color);
return color;
}
這個功能有點復雜,因為金屬粗糙度和很多線條與問題無關。 綜上所述,這個函數與calcDirectionalLight(可以工作)非常相似,但不同的是我加了一個衰減,L是light.position - FragPos而不是light.direction。 我不明白問題出在哪里,看起來數據沒有在正確的空間中表達或者我忘記了一些東西。
我找到了解決方案,而且非常簡單。 我復制了這一行: pos = glm::normalize(glm::vec3(viewMatrix * glm::vec4(pos, 1.)));
來自定向光(我用 1 替換了 0,用位置替換了 dirLight) 不幸的是我忘記移除歸一化,所以點光源接近 (0, 0, 0) :相機位置。 這個結果讓我確信數據表達在錯誤的空間中,但事實並非如此。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.