投光物
1、平行光
给出光源的方向向量即可,没有位置(这里不作代码展示了,很简单)。
2、点光源
点光源包含衰减过程。需要给出光源的位置,衰减的三个系数。
片段着色器代码如下:
#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 Light{ vec3 position; vec3 ambient; vec3 diffuse; vec3 specular; float constant; float linear; float quadratic; }; uniform Material material; uniform Light light; uniform vec3 viewPos; void main() { float distance=length(light.position-vs_in.FragPos); float attenuation=10.0f/(light.constant+light.linear*distance+light.quadratic*(distance*distance)); vec3 ambient=light.ambient * vec3(texture(material.diffuse, vs_in.TexCoords)); ambient*=attenuation; vec3 norm=normalize(vs_in.Normal); vec3 lightDir=normalize(light.position-vs_in.FragPos); float diff=max(dot(norm,lightDir),0.0f); vec3 diffuse=light.diffuse * diff * vec3(texture(material.diffuse, vs_in.TexCoords)); diffuse*=attenuation; vec3 viewDir=normalize(viewPos-vs_in.FragPos); vec3 reflectDir=reflect(-lightDir,norm); float spec=pow(max(dot(viewDir,reflectDir),0.0f),material.shininess); vec3 specular=light.specular * spec * vec3(texture(material.specular, vs_in.TexCoords)); specular*=attenuation; color = vec4(ambient+diffuse+specular, 1.0f); }
渲染代码如下:
void SceneRendering::CubeRendering() { //update uniform buffer cube->setViewMat(phc->getViewMatrix()); cube->setProjectionMat(phc->getProjectionMatrix()); shader_cube->use(); shader_cube->setInt("material.diffuse", 0); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, container); shader_cube->setInt("material.specular", 1); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, container_specular); shader_cube->setFloat("material.shininess", 500); shader_cube->setVec3("light.ambient", 0.2f, 0.2f, 0.2f); shader_cube->setVec3("light.diffuse", 0.5f, 0.5f, 0.5f); shader_cube->setVec3("light.specular", 1.0f, 1.0f, 1.0f); shader_cube->setVec3("light.position", 0.0f, 0.0f, 10.0f); shader_cube->setFloat("light.constant", 1.0f); shader_cube->setFloat("light.linear", 0.09f); shader_cube->setFloat("light.quadratic", 0.032f); shader_cube->setVec3("viewPos", phc->getPos()); // 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_cube->setMat4("model", model); cube->DrawCube(); } }
效果图:
3、聚光灯
聚光灯除了衰减以外,加入了照射范围限制,光源有位置、照射方向、cut角。
片段着色器代码如下:
#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 Light{ vec3 ambient; vec3 diffuse; vec3 specular; float constant; float linear; float quadratic; vec3 position; vec3 direction; float cutOff; float outerCutOff; }; uniform Material material; uniform Light light; uniform vec3 viewPos; void main() { float distance=length(light.position-vs_in.FragPos); float attenuation=10.0f/(light.constant+light.linear*distance+light.quadratic*(distance*distance)); vec3 ambient=light.ambient * vec3(texture(material.diffuse, vs_in.TexCoords)); ambient*=attenuation; vec3 norm=normalize(vs_in.Normal); vec3 lightDir=normalize(light.position-vs_in.FragPos); float diff=max(dot(norm,lightDir),0.0f); vec3 diffuse=light.diffuse * diff * vec3(texture(material.diffuse, vs_in.TexCoords)); diffuse*=attenuation; vec3 viewDir=normalize(viewPos-vs_in.FragPos); vec3 reflectDir=reflect(-lightDir,norm); float spec=pow(max(dot(viewDir,reflectDir),0.0f),material.shininess); vec3 specular=light.specular * spec * vec3(texture(material.specular, vs_in.TexCoords)); 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; color = vec4(ambient+diffuse+specular, 1.0f); }
渲染代码如下:
void SceneRendering::CubeRendering() { //update uniform buffer cube->setViewMat(phc->getViewMatrix()); cube->setProjectionMat(phc->getProjectionMatrix()); shader_cube->use(); shader_cube->setInt("material.diffuse", 0); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, container); shader_cube->setInt("material.specular", 1); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, container_specular); shader_cube->setFloat("material.shininess", 500); shader_cube->setVec3("light.ambient", 0.2f, 0.2f, 0.2f); shader_cube->setVec3("light.diffuse", 0.5f, 0.5f, 0.5f); shader_cube->setVec3("light.specular", 1.0f, 1.0f, 1.0f); shader_cube->setFloat("light.constant", 1.0f); shader_cube->setFloat("light.linear", 0.09f); shader_cube->setFloat("light.quadratic", 0.032f); shader_cube->setVec3("light.position", phc->getPos()); shader_cube->setVec3("light.direction", phc->GetForwardVec()); shader_cube->setFloat("light.cutOff", glm::cos(glm::radians(12.5f))); shader_cube->setFloat("light.outerCutOff", glm::cos(glm::radians(17.5f))); shader_cube->setVec3("viewPos", phc->getPos()); // 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_cube->setMat4("model", model); cube->DrawCube(); } }
硬影效果图:
软影效果图: