LearnOpengl_LightCaster

太阳光,即平行光,我们假设太阳光的位置离我们无限远,但是它的光照方向对于每个顶点都是相同的。

//方向光着色器代码
struct DirLight{
	vec3 direction;
	
	vec3 ambient;
	vec3 diffuse;
	vec3 specular;
};

vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir)
{
	vec3 lightDir = normalize(-light.direction);//平行光的光照方向取反 就是光源到片元的方向
	
	float diff = max(dot(normal, lightDir), 0.0);//漫反射因子
	
	vec3 reflectDir = reflect(-lightDir, normal);//通过光的方向和法线计算出反射光方向
	float spec = pow(max(dot(reflectDir, viewDir), 0.0), material.shininess);//镜面光因子
	
	vec3 ambient = light.ambient * texture(material.diffuse, TexCoords).rgb;
	vec3 diffuse = light.diffuse * diff * texture(material.diffuse, TexCoords).rgb;
	vec3 specular = light.specular * spec * texture(material.specular, TexCoords).rgb;
	
	return (ambient + diffuse + specular);
}

点光源,如火把、灯泡等,点光源的位置是固定的,光照方向对于每个顶点来说,都需要计算得出,点光源最重要的一点是,随着与点光源距离的增加,光的强度存在衰减。

//点光源着色器代码
struct PointLight {
    vec3 position;
  
    vec3 ambient;
    vec3 diffuse;
    vec3 specular;
	
    float constant;
    float linear;
    float quadratic;
};

vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir)
{
	//漫反射因子
	//先得到从片元指向光源的方向向量
	vec3 lightDir = normalize(light.position - fragPos);
	float diff = max(dot(lightDir, normal), 0.0);
	
	
	//镜面光因子
	vec3 reflectDir = reflect(-lightDir, normal);
	float spec = pow(max(dot(reflectDir, viewDir), 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 * texture(material.diffuse, TexCoords).rgb;
	vec3 diffuse = light.diffuse * diff * texture(material.diffuse, TexCoords).rgb;
	vec3 specular = light.specular * spec * texture(material.specular, TexCoords).rgb;
	
	ambient  *= attenuation;
    diffuse  *= attenuation;
    specular *= attenuation;
	
    return (ambient + diffuse + specular);
}

聚光灯,如手电筒,我们经常在恐怖游戏中使用。聚光灯最重要的是存在内圆锥和外圆锥,外圆锥之外的物体不会被聚光灯照亮,其次聚光灯边缘需要进行软化处理。

//聚光灯着色器代码
struct SpotLight {
    vec3 position;  
    vec3 direction;
    float cutOff;//聚光灯内圆锥余弦值
    float outerCutOff;//聚光灯外圆锥余弦值
  
    vec3 ambient;
    vec3 diffuse;
    vec3 specular;
	
    float constant;
    float linear;
    float quadratic;
};

vec3 CalcSpotLight(SpotLight light, vec3 normal, vec3 fragPos, vec3 viewDir)
{
    vec3 lightDir = normalize(light.position - fragPos);
    
    // diffuse shading
    float diff = max(dot(normal, lightDir), 0.0);
    
    // specular shading
    vec3 reflectDir = reflect(-lightDir, normal);
    float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
    
    // attenuation
    float distance = length(light.position - fragPos);
    float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance));    
    
    // spotlight intensity
    float theta = dot(lightDir, normalize(-light.direction)); 
    float epsilon = light.cutOff - light.outerCutOff;
    float intensity = clamp((theta - light.outerCutOff) / epsilon, 0.0, 1.0);
    
    // combine results
    vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords));
    vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords));
    vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords));
    
    ambient *= attenuation * intensity;
    diffuse *= attenuation * intensity;
    specular *= attenuation * intensity;
    
    return (ambient + diffuse + specular);
}

我们需要在cpu程序中给着色器的光进行赋值

//这是在一个渲染帧中 使用一个着色器程序对象 设置好他的着色器参数 进行渲染物体的代码
		objShader.use();
		objShader.setVec3("viewPos", myCamera.Position);//观察者位置

		//给光结构体赋值
		//平行光
		objShader.setVec3("dirLight.direction", glm::vec3(-1.0f));//聚光灯方向
		objShader.setVec3("dirLight.ambient", glm::vec3(0.1f));//环境光
		objShader.setVec3("dirLight.diffuse", glm::vec3(0.8f));//漫反射光照
		objShader.setVec3("dirLight.specular", glm::vec3(1.0f));//镜面光

		//点光源
		objShader.setVec3("pointLights[0].position", pointLightPositions[0]);
		objShader.setVec3("pointLights[0].ambient", glm::vec3(0.1f));//环境光
		objShader.setVec3("pointLights[0].diffuse", glm::vec3(0.8f));//漫反射光照
		objShader.setVec3("pointLights[0].specular", glm::vec3(1.0f));//镜面光
		objShader.setFloat("pointLights[0].constant", 1.0f);
		objShader.setFloat("pointLights[0].linear", 0.09f);
		objShader.setFloat("pointLights[0].quadratic", 0.032f);

		objShader.setVec3("pointLights[1].position", pointLightPositions[1]);
		objShader.setVec3("pointLights[1].ambient", glm::vec3(0.1f));//环境光
		objShader.setVec3("pointLights[1].diffuse", glm::vec3(0.8f));//漫反射光照
		objShader.setVec3("pointLights[1].specular", glm::vec3(1.0f));//镜面光
		objShader.setFloat("pointLights[1].constant", 1.0f);
		objShader.setFloat("pointLights[1].linear", 0.09f);
		objShader.setFloat("pointLights[1].quadratic", 0.032f);

		objShader.setVec3("pointLights[2].position", pointLightPositions[2]);
		objShader.setVec3("pointLights[2].ambient", glm::vec3(0.1f));//环境光
		objShader.setVec3("pointLights[2].diffuse", glm::vec3(0.8f));//漫反射光照
		objShader.setVec3("pointLights[2].specular", glm::vec3(1.0f));//镜面光
		objShader.setFloat("pointLights[2].constant", 1.0f);
		objShader.setFloat("pointLights[2].linear", 0.09f);
		objShader.setFloat("pointLights[2].quadratic", 0.032f);

		objShader.setVec3("pointLights[3].position", pointLightPositions[3]);
		objShader.setVec3("pointLights[3].ambient", glm::vec3(0.1f));//环境光
		objShader.setVec3("pointLights[3].diffuse", glm::vec3(0.8f));//漫反射光照
		objShader.setVec3("pointLights[3].specular", glm::vec3(1.0f));//镜面光
		objShader.setFloat("pointLights[3].constant", 1.0f);
		objShader.setFloat("pointLights[3].linear", 0.09f);
		objShader.setFloat("pointLights[3].quadratic", 0.032f);

		//聚光灯
		objShader.setVec3("spotLight.position", myCamera.Position);//聚光灯光源位置
		objShader.setVec3("spotLight.direction", myCamera.Front);//聚光灯方向
		objShader.setFloat("spotLight.cutOff", glm::cos(glm::radians(12.5f)));//聚光灯内圆锥余弦值
		objShader.setFloat("spotLight.outerCutOff", glm::cos(glm::radians(17.5f)));//聚光灯内圆锥余弦值
		objShader.setVec3("spotLight.ambient", glm::vec3(0.1f));//环境光
		objShader.setVec3("spotLight.diffuse", glm::vec3(0.8f));//漫反射光照
		objShader.setVec3("spotLight.specular", glm::vec3(1.0f));//镜面光
		objShader.setFloat("spotLight.constant", 1.0f);
		objShader.setFloat("spotLight.linear", 0.09f);
		objShader.setFloat("spotLight.quadratic", 0.032f);

		//给材质结构体赋值
		objShader.setFloat("material.shininess", 32.0f);
		
		//每帧设置观察矩阵 每一帧因为我们用户的输入 会导致摄像机位置、角度发生变化 所以每帧都要重新生成LookAt矩阵
		glm::mat4 view = myCamera.GetViewMatrix();//位置 目标 上向量
		objShader.setMatrix4("view", view);

		//每帧设置透视投影矩阵
		glm::mat4 projection = glm::perspective(glm::radians(myCamera.Fov), 800.0f / 600.0f, 0.1f, 100.0f);
		objShader.setMatrix4("projection", projection);

		glBindVertexArray(cubeVAO);//绑定顶点数组对象

		glm::mat4 model = glm::mat4(1.0f);
		for (unsigned int i = 0; i < 10; i++)
		{
			model = glm::mat4(1.0f);
			model = glm::translate(model, cubePositions[i]);
			float angle = 20.0f * i;
			model = glm::rotate(model, glm::radians(angle), glm::vec3(1.0f, 0.3f, 0.5f));
			objShader.setMatrix4("model", model);

			glDrawArrays(GL_TRIANGLES, 0, 36);
		}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值