多光源(定向光、点光源、聚光灯)
前篇学习了单个的光源,现在在一个场景中放置多个不同的光源,包括一个定向光源、4个点光源、一个聚光灯。
GLSL代码如下(片段着色器):
#version 430 core out vec4 color; in VS_OUT{ vec3 FragPos; vec3 Normal; vec2 TexCoords; }vs_in; struct Material{ sampler2D diffuse; sampler2D specular; float shininess; }; struct DirLight{ vec3 ambient; vec3 diffuse; vec3 specular; vec3 direction; }; struct PointLight{ vec3 ambient; vec3 diffuse; vec3 specular; float constant; float linear; float quadratic; vec3 position; }; struct SpotLight{ vec3 ambient; vec3 diffuse; vec3 specular; float constant; float linear; float quadratic; vec3 position; vec3 direction; float cutOff; float outerCutOff; }; #define NR_POINT_LIGHTS 4 uniform Material material; uniform DirLight dirLight; uniform PointLight pointLights[NR_POINT_LIGHTS]; uniform SpotLight spotLight; uniform vec3 viewPos; vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir) { vec3 lightDir=normalize(-light.direction); vec3 ambient=light.ambient * vec3(texture(material.diffuse, vs_in.TexCoords)); float diff=max(dot(normal,lightDir),0.0f); vec3 diffuse=light.diffuse * diff * vec3(texture(material.diffuse, vs_in.TexCoords)); vec3 reflectDir=reflect(-lightDir,normal); float spec=pow(max(dot(viewDir,reflectDir),0.0f),material.shininess); vec3 specular=light.specular * spec * vec3(texture(material.specular, vs_in.TexCoords)); return (ambient+diffuse+specular); } vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir) { vec3 lightDir = normalize(light.position - fragPos); // 漫反射着色 float diff = max(dot(normal, lightDir), 0.0); // 镜面光着色 vec3 reflectDir = reflect(-lightDir, normal); float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess); // 衰减 float distance = length(light.position - fragPos); float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance)); // 合并结果 vec3 ambient = light.ambient * vec3(texture(material.diffuse, vs_in.TexCoords)); vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, vs_in.TexCoords)); vec3 specular = light.specular * spec * vec3(texture(material.specular, vs_in.TexCoords)); ambient *= attenuation; diffuse *= attenuation; specular *= attenuation; return (ambient + diffuse + specular); } vec3 CalcSpotLight(SpotLight light, vec3 normal, vec3 fragPos, vec3 viewDir) { vec3 lightDir = normalize(light.position - fragPos); // 漫反射着色 float diff = max(dot(normal, lightDir), 0.0); // 镜面光着色 vec3 reflectDir = reflect(-lightDir, normal); float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess); // 衰减 float distance = length(light.position - fragPos); float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance)); // 合并结果 vec3 ambient = light.ambient * vec3(texture(material.diffuse, vs_in.TexCoords)); vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, vs_in.TexCoords)); vec3 specular = light.specular * spec * vec3(texture(material.specular, vs_in.TexCoords)); //ambient *= attenuation; //diffuse *= attenuation; //specular *= attenuation; float theta=dot(lightDir,normalize(-light.direction)); float epsilon=light.cutOff-light.outerCutOff; float intensity=clamp((theta-light.outerCutOff)/epsilon,0.0,1.0); ambient*=intensity; diffuse*=intensity; specular*=intensity; return (ambient + diffuse + specular); } void main() { vec3 norm=normalize(vs_in.Normal); vec3 viewDir=normalize(viewPos-vs_in.FragPos); //定向光 vec3 result=CalcDirLight(dirLight, norm, viewDir); //点光源 for(int i=0;i<NR_POINT_LIGHTS;i++){ result+=CalcPointLight(pointLights[i], norm, vs_in.FragPos, viewDir); } //聚光灯 result+=CalcSpotLight(spotLight, norm, vs_in.FragPos, viewDir); color=vec4(result,1.0f); }
渲染代码如下:
void SceneRendering::CubeRendering() { //update uniform buffer cube->setViewMat(phc->getViewMatrix()); cube->setProjectionMat(phc->getProjectionMatrix()); shader_multiLights->use(); shader_multiLights->setInt("material.diffuse", 0); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, container); shader_multiLights->setInt("material.specular", 1); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, container_specular); shader_multiLights->setFloat("material.shininess", 500); shader_multiLights->setVec3("viewPos", phc->getPos()); glm::vec3 pointLightPositions[] = { glm::vec3(0.7f, 0.2f, 2.0f), glm::vec3(2.3f, -3.3f, -4.0f), glm::vec3(-4.0f, 2.0f, -12.0f), glm::vec3(0.0f, 0.0f, -3.0f) }; glm::vec3 pointLightColors[] = { glm::vec3(1.0f, 0.6f, 0.0f), glm::vec3(1.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0, 0.0), glm::vec3(0.2f, 0.2f, 1.0f) }; // Directional light shader_multiLights->setVec3("dirLight.direction", -0.2f, -1.0f, -0.3f); shader_multiLights->setVec3("dirLight.ambient", 0.3f, 0.24f, 0.14f); shader_multiLights->setVec3("dirLight.diffuse", 0.7f, 0.42f, 0.26f); shader_multiLights->setVec3("dirLight.specular", 0.5f, 0.5f, 0.5f); // Point light 1 shader_multiLights->setVec3("pointLights[0].position", pointLightPositions[0].x, pointLightPositions[0].y, pointLightPositions[0].z); shader_multiLights->setVec3("pointLights[0].ambient", pointLightColors[0].x * 0.1, pointLightColors[0].y * 0.1, pointLightColors[0].z * 0.1); shader_multiLights->setVec3("pointLights[0].diffuse", pointLightColors[0].x, pointLightColors[0].y, pointLightColors[0].z); shader_multiLights->setVec3("pointLights[0].specular", pointLightColors[0].x, pointLightColors[0].y, pointLightColors[0].z); shader_multiLights->setFloat("pointLights[0].constant", 1.0f); shader_multiLights->setFloat("pointLights[0].linear", 0.09f); shader_multiLights->setFloat("pointLights[0].quadratic", 0.032f); // Point light 2 shader_multiLights->setVec3("pointLights[1].position", pointLightPositions[1].x, pointLightPositions[1].y, pointLightPositions[1].z); shader_multiLights->setVec3("pointLights[1].ambient", pointLightColors[1].x * 0.1, pointLightColors[1].y * 0.1, pointLightColors[1].z * 0.1); shader_multiLights->setVec3("pointLights[1].diffuse", pointLightColors[1].x, pointLightColors[1].y, pointLightColors[1].z); shader_multiLights->setVec3("pointLights[1].specular", pointLightColors[1].x, pointLightColors[1].y, pointLightColors[1].z); shader_multiLights->setFloat("pointLights[1].constant", 1.0f); shader_multiLights->setFloat("pointLights[1].linear", 0.09f); shader_multiLights->setFloat("pointLights[1].quadratic", 0.032f); // Point light 3 shader_multiLights->setVec3("pointLights[2].position", pointLightPositions[2].x, pointLightPositions[2].y, pointLightPositions[2].z); shader_multiLights->setVec3("pointLights[2].ambient", pointLightColors[2].x * 0.1, pointLightColors[2].y * 0.1, pointLightColors[2].z * 0.1); shader_multiLights->setVec3("pointLights[2].diffuse", pointLightColors[2].x, pointLightColors[2].y, pointLightColors[2].z); shader_multiLights->setVec3("pointLights[2].specular", pointLightColors[2].x, pointLightColors[2].y, pointLightColors[2].z); shader_multiLights->setFloat("pointLights[2].constant", 1.0f); shader_multiLights->setFloat("pointLights[2].linear", 0.09f); shader_multiLights->setFloat("pointLights[2].quadratic", 0.032f); // Point light 4 shader_multiLights->setVec3("pointLights[3].position", pointLightPositions[3].x, pointLightPositions[3].y, pointLightPositions[3].z); shader_multiLights->setVec3("pointLights[3].ambient", pointLightColors[3].x * 0.1, pointLightColors[3].y * 0.1, pointLightColors[3].z * 0.1); shader_multiLights->setVec3("pointLights[3].diffuse", pointLightColors[3].x, pointLightColors[3].y, pointLightColors[3].z); shader_multiLights->setVec3("pointLights[3].specular", pointLightColors[3].x, pointLightColors[3].y, pointLightColors[3].z); shader_multiLights->setFloat("pointLights[3].constant", 1.0f); shader_multiLights->setFloat("pointLights[3].linear", 0.9f); shader_multiLights->setFloat("pointLights[3].quadratic", 0.032f); // Spot light shader_multiLights->setVec3("spotLight.position", phc->getPos()); shader_multiLights->setVec3("spotLight.direction", phc->GetForwardVec()); shader_multiLights->setVec3("spotLight.ambient", 0.0f, 0.0f, 0.0f); shader_multiLights->setVec3("spotLight.diffuse", 1.0f, 1.0f, 0.0f); shader_multiLights->setVec3("spotLight.specular", 1.0f, 1.0f, 0.0f); shader_multiLights->setFloat("spotLight.constant", 1.0f); shader_multiLights->setFloat("spotLight.linear", 0.9f); shader_multiLights->setFloat("spotLight.quadratic", 0.032f); shader_multiLights->setFloat("spotLight.cutOff", glm::cos(glm::radians(12.5f))); shader_multiLights->setFloat("spotLight.outerCutOff", glm::cos(glm::radians(14.5f))); // draw cubes for (unsigned int i = 0; i < 10; i++) { glm::mat4 model; model = glm::scale(model, glm::vec3(5)); model = glm::translate(model, cube->cubePositions[i]); float angle = 20.0f * i; model = glm::rotate(model, glm::radians(angle), glm::vec3(1.0f, 0.3f, 0.5f)); shader_multiLights->setMat4("model", model); cube->DrawCube(); } }
效果图:
1、定向光+点光源
2、定向光+点光源+聚光灯(软影)