我在 C++ 20 中将 OpenGL 4.5 与 GLFW 和 GLAD 一起使用,我正在尝试制作一个着色器,使用 Blinn-Phong 算法计算不同功能(点、方向、点)的多个光源,但每次我尝试计算不止一个,它只是行不通(统一位置搞砸了,它再也找不到任何东西)。 这是片段着色器:
#version 330
in vec3 fragNormal;
in vec2 fragTexCoord;
in vec3 fragPos;
uniform vec3 viewPos;
uniform sampler2D ourTexture;
out vec4 outColor;
struct DirLight {
vec3 direction;
vec3 color;
float ambient;
float diffuse;
float specular;
};
struct PointLight {
vec3 position;
vec3 direction;
vec3 color;
float ambient;
float diffuse;
float specular;
float constant;
float linear;
float quadratic;
};
struct SpotLight {
vec3 position;
vec3 direction;
vec3 color;
float ambient;
float diffuse;
float specular;
float constant;
float linear;
float quadratic;
float cutOff;
float outerCutOff;
};
struct Material {
vec3 diffuse;
vec3 ambient;
vec3 specular;
float shininess;
};
#define NB_MAX_LIGHT 50
uniform DirLight dirLights[NB_MAX_LIGHT];
uniform PointLight pointLights[NB_MAX_LIGHT];
uniform SpotLight spotLights[NB_MAX_LIGHT];
uniform Material material;
uniform int nbDirLight;
uniform int nbPointLight;
uniform int nbSpotLight;
vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir)
{
vec3 lightDir = normalize(-light.direction);
float diffuse = max(dot(lightDir, normal), 0.0) * light.diffuse;
vec3 haflwaydir = normalize(lightDir + viewDir);
float spec = pow(max(dot(viewDir, haflwaydir), 0.0), material.shininess);
float specular = spec * light.specular;
return ((light.ambient * material.ambient) + (diffuse * material.diffuse) + (specular * material.specular)) * light.color;
}
vec3 CalcSpotLight(SpotLight light, vec3 normal, vec3 fragPos, vec3 viewDir)
{
//cal point
vec3 lightDir = normalize(light.position - fragPos);
float dist = length(light.position - fragPos);
float attenuation = 1.0 / (light.constant + light.linear * dist + light.quadratic * (dist * dist));
float diffuse = max(dot(lightDir, normal), 0.0) * light.diffuse * attenuation;
vec3 haflwaydir = normalize(lightDir + viewDir);
float spec = pow(max(dot(viewDir, haflwaydir), 0.0), material.shininess);
float specular = spec * light.specular * attenuation;
//spot part
float theta = dot(lightDir, normalize(-light.direction));
float epsilon = (light.cutOff - light.outerCutOff);
float intensity = clamp((theta - light.outerCutOff) / epsilon, 0.0, 1.0);
float ambient = light.ambient * intensity;
diffuse *= intensity;
specular *= intensity;
return ((ambient * material.ambient) + (diffuse * material.diffuse) + (specular * material.specular)) * light.color;
}
vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir)
{
vec3 lightDir = normalize(light.position - fragPos);
float dist = length(light.position - fragPos);
float attenuation = 1.0 / (light.constant + light.linear * dist + light.quadratic * (dist * dist));
float diffuse = max(dot(lightDir, normal), 0.0) * light.diffuse * attenuation;
vec3 haflwaydir = normalize(lightDir + viewDir);
float spec = pow(max(dot(viewDir, haflwaydir), 0.0), material.shininess);
float specular = spec * light.specular * attenuation;
return ((light.ambient * material.ambient) + (diffuse * material.diffuse) + (specular * material.specular)) * light.color;
}
void main() {
vec3 norm = normalize(fragNormal);
vec3 viewDir = normalize(viewPos - fragPos);
vec3 result = vec3(0);
for(int i = 0; i < nbDirLight; i++)
result += CalcDirLight(dirLights[i], norm, viewDir);
for(int j = 0; j < nbPointLight; j++)
result += CalcPointLight(pointLights[j], norm, fragPos, viewDir);
for(int k = 0; k < nbSpotLight; k++)
result += CalcSpotLight(spotLights[k], norm, fragPos, viewDir);
outColor = vec4(result, 1.0) * texture(ourTexture, fragTexCoord);
}
对于顶点着色器:
#version 330
layout(location = 0) in vec3 inPosition;
layout(location = 1) in vec3 inNormal;
layout(location = 2) in vec2 inTexCoord;
out vec3 fragNormal;
out vec2 fragTexCoord;
out vec3 fragPos;
out vec3 fragViewPos;
uniform mat4 model;
uniform mat4 viewProj;
void main() {
gl_Position = viewProj * model * vec4(inPosition, 1.0);
fragNormal = mat3(transpose(inverse(model))) * inNormal;
fragTexCoord = inTexCoord;
fragPos = vec3(model * vec4(inPosition, 1.0));
}
当我尝试使用 CalcSpotLight 时,“着色器”再也找不到任何制服了。
GetUniform 的代码是:
{
unsigned int result = RENDERER.GetUniformLocation(shaderProgram, name);
if (result == -1)
std::cout << name << " not found in uniform" << std::endl;
return result;
}
,
int Renderer::GetUniformLocation(unsigned int pProgram, const char* pName)
{
return glGetUniformLocation(pProgram, pName);
}
我尝试只使用 2 盏灯,它工作,我尝试只将 1.0f 添加到 vec4 结果并且它工作,但是当我尝试在函数中计算时它不再工作了。
嘿,我正在和他一起做这个项目,非常感谢帮助!