opengl光照之聚光灯软化边缘

聚光灯软化边缘的关键:

	float diffuseIntensity=0.0;
	//计算聚光灯的入射光线和中心线的夹角的余弦
	float currentCosThta=max(0.0,dot(L,spotLightDirection));
	if(currentCosThta>cosThta)
	{
		//-----聚光灯软化边缘的关键步骤 计算 currentCosThta的幂
		diffuseIntensity=pow(currentCosThta,U_LightDirection.w);
	}
	//--漫反射光的最终值
	vec4 diffuseColor=U_DiffuseLightColor*U_DiffuseMaterial*diffuseIntensity*attenuation*4.0;

边缘软化后的效果图

opengl光照之聚光灯软化边缘_第1张图片

未软化边缘的效果图


opengl光照之聚光灯软化边缘_第2张图片


顶点shader实现

attribute vec3 pos;
attribute vec2 texcoord;
attribute vec3 normal;

uniform mat4 M;
uniform mat4 P;
uniform mat4 V;
uniform mat4 NM;

varying vec3 V_Normal;
varying vec3 V_WorldPos;

void main()
{
	V_Normal=mat3(NM)*normal; //法线坐标转换到世界空间
	vec4 worldPos=M*vec4(pos,1.0);
	V_WorldPos=worldPos.xyz;

	gl_Position=P*V*worldPos;
}

片元shader


uniform vec4 U_LightPos;//光源位置
uniform vec3 U_EyePos;//眼睛的位置
uniform vec4 U_LightDirection; //聚光灯中心线的方向
uniform float U_Cutoff;//聚光灯中心线和入射光的最大夹角,超过此夹角不能被照射
uniform vec4 U_AmbientLightColor;//环境光颜色
uniform vec4 U_AmbientMaterial;//环境光材质
uniform vec4 U_DiffuseLightColor;//漫反射光颜色
uniform vec4 U_DiffuseMaterial;//漫反射光材质
uniform vec4 U_SpecularLightColor;//镜面光颜色
uniform vec4 U_SpecularMaterial;//镜面光材质 

varying vec3 V_Normal;//转换到世界空间的法线坐标
varying vec3 V_WorldPos;//转换到世界空间的顶点坐标

void main()
{
	//角度转弧度--聚光灯中心线和入射光的最大夹角
	float radianCutoff=U_Cutoff*3.14/180.0;
	float cosThta=cos(radianCutoff);
	//聚光灯中心线的方向  
	vec3 spotLightDirection=normalize(U_LightDirection.xyz);

	//--环境光的计算
	vec4 ambientColor=U_AmbientLightColor*U_AmbientMaterial;

	//--漫反射光的计算
	//入射光向量
	vec3 L=vec3(0.0);
	float distance=0.0;
	float attenuation=1.0;
	//计算聚光灯衰减因子的一些参数
	float constantFactor=0.5;
	float linearFactor=0.3;
	float expFactor=0.1;

	//计算入射光向量
	if(U_LightPos.w==0.0)//如果是方向光,方向光的光线是平行的
	{
		L=U_LightPos.xyz;
	}
	else  //否则光线是发散的,需要跟进跟进被照射点的坐标和光源位置计算入射光向量
	{
		L=U_LightPos.xyz-V_WorldPos;
		//计算被照射点到光源的距离 ,聚光灯会根据距离衰减
		distance=length(L);
		//计算衰减因子
		attenuation=1.0/(constantFactor+linearFactor*distance+expFactor*distance*distance);
	}

	L=normalize(-L);

	//法向量归一化
	vec3 n=normalize(V_Normal);

	float diffuseIntensity=0.0;
	//计算聚光灯的入射光线和中心线的夹角的余弦
	float currentCosThta=max(0.0,dot(L,spotLightDirection));
	if(currentCosThta>cosThta)
	{
		//-----聚光灯软化边缘的关键步骤 计算 currentCosThta的幂
		diffuseIntensity=pow(currentCosThta,U_LightDirection.w);
	}
	//--漫反射光的最终值
	vec4 diffuseColor=U_DiffuseLightColor*U_DiffuseMaterial*diffuseIntensity*attenuation*4.0;
	
	//----计算镜面光
	//--眼睛的位置-模型上被观察的位置就是视线的方向向量,当模型上被照射点的反射光和视线向量重合时,就会产生高光效果,也就是镜面光
	vec3 viewDir=U_EyePos-V_WorldPos;
	viewDir=normalize(viewDir);

	//根据blin-phone模型计算镜面光的反射光
	vec3 halfVector=L+viewDir;
	halfVector=normalize(halfVector);

	float specularIntensity=0.0;
	//根据漫反射光的强度来过滤镜面光,减少计算量
	if(diffuseIntensity==0.0)
	{
		specularIntensity=0.0;
	}
	else
	{
		//镜面光强度
		specularIntensity=pow(max(0.0,dot(n,halfVector)),128.0);
	}

	vec4 specularColor=U_SpecularLightColor*U_SpecularMaterial*specularIntensity*attenuation;

	gl_FragColor=ambientColor+diffuseColor;//+specularColor;
}


你可能感兴趣的:(opengl_shader专题)