一、简单光照原理
平行光(正常光)
光照效果= 环境颜色 + 漫反射颜色 + 镜面反射颜色
点光源
光照效果= 环境颜色 + (漫反射颜色 + 镜面反射颜色)× 衰减因子
聚光灯
光照效果= 环境颜色 + (漫反射颜色 + 镜面反射颜色)× 衰减因子 × 聚光灯效果
二、IOS光照
1、导入系统库
- GLKit
- OpenGLES
- CoreGraphics
- QuartzCore
2、光照类
#import <GLKit/GLKit.h> //基础光 @interface BaseLight : NSObject{ @public GLKVector4 Color; float AmbientIntensity;//周围无光照的区域亮度 float DiffuseIntensity;//漫反射 float SpecularIntensity;//镜面反射 } @end //点光源 @interface PointLight : BaseLight{ @public GLKVector3 DestPos; GLKVector3 SourcePos;//光照源位置 float Shininess; struct { float Constant; float Linear; float Exp; } Attenuation; } @end //聚光灯 @interface SpotLight : PointLight{ @public GLKVector3 Direction; float Cutoff;//最小夹角cos值 float Exponent;//聚光灯角度 } @end
3、实现光源属性槽位获取及更新
@interface BaseLight : NSObject{ @public GLKVector4 Color; float AmbientIntensity;//周围无光照的区域亮度 float DiffuseIntensity;//漫反射 float SpecularIntensity;//镜面反射 } @end @interface PointLight : BaseLight{ @public GLKVector3 DestPos; GLKVector3 SourcePos;//光照源位置 float Shininess; struct { float Constant; float Linear; float Exp; } Attenuation; } @end @interface SpotLight : PointLight{ @public GLKVector3 Direction; float Cutoff;//最小夹角cos值 float Exponent;//聚光灯角度 } @end
在实际项目中调用,初始化,设置,然后更新。。。。
4、GLSL实现
//基础光 struct BaseLight { vec4 Color; float AmbientIntensity; float DiffuseIntensity; float SpecularIntensity; }; //点光源 struct PointLight{ BaseLight Base; vec3 SourcePos; vec3 DestPos; float Shininess; //亮度 struct { float Constant; float Linear; float Exp; } Attenuation; }; //聚光灯 struct SpotLight{ PointLight Base; vec3 Direction; float Cutoff; float Exponent; }; vec3 vPos; vec3 vEyePos; uniform SpotLight u_spotLight; //基础光计算 vec4 CalcLightInternal(BaseLight Light, vec3 LightDirection, vec3 Normal) { float DiffuseFactor = dot(Normal, LightDirection); vec4 DiffuseColor = vec4(0, 0, 0, 0); vec4 SpecularColor = vec4(0, 0, 0, 0); if (DiffuseFactor > 0.0) { DiffuseColor = Light.Color * Light.DiffuseIntensity * DiffuseFactor; vec3 VertexToEye = normalize(vEyePos - vPos); vec3 LightReflect = normalize(reflect(LightDirection, Normal)); vec3 H = normalize(LightDirection + VertexToEye); float SpecularFactor = max(0.0, dot(Normal, H)); SpecularFactor = pow(SpecularFactor, 10.0); if (SpecularFactor > 0.0) { SpecularColor = Light.Color * Light.SpecularIntensity * SpecularFactor; } } return DiffuseColor + SpecularColor; } //pointlight 点光源计算 vec4 CalcPointLight(PointLight l,vec3 Normal) { vec3 LightDirection = normalize(l.SourcePos-l.DestPos); float Distance =length(vPos - l.DestPos); vec4 Color = CalcLightInternal(l.Base, LightDirection, Normal); //衰减因子 float Attenuation = l.Attenuation.Constant +l.Attenuation.Linear * Distance + l.Attenuation.Exp* Distance * Distance; Color=Color*l.Shininess/Attenuation; return Color; } //spotlight实现 vec4 CalcSpotLight(SpotLight l, vec3 Normal) { vec3 LightToPixel = normalize(vPos - l.Base.DestPos); vec3 LightDirection = normalize(LightToPixel-l.Direction); //聚光灯因子 float SpotFactor =pow(max(0.0, dot(LightToPixel, LightDirection)),l.Exponent); if (SpotFactor > l.Cutoff) { vec4 Color = CalcPointLight(l.Base, Normal); return Color * clamp((1.0 - (1.0 - SpotFactor) * 1.0/(1.0 - l.Cutoff)),0.0,1.0); } else { return vec4(0.0,0.0,0.0,0.0); } } void main() { lowp vec4 topColor = texture2D(Texture, TexCoordOut); vec3 vNormal=vec3(0, 0, 1); vec3 N = normalMatrix * vNormal; vPos=vec3(TexCoordOut,0.0) ; //取光照点 vEyePos=vec3(0.0,0.0,1.0);//观察点 vec4 AmbientColor = u_spotLight.Base.Base.Color * u_spotLight.Base.Base.AmbientIntensity; lowp vec4 lightColor =CalcSpotLight(u_spotLight,N)+CalcSpotLight(u_spotLight1,N)+AmbientColor; gl_FragColor =lightColor* topColor; }