OpenGL ES(五) 光照

在OpenGL ES中光照模型主要结构由3个元素组成:环境(Ambient)光照、漫反射(Diffuse)光照和镜面(Specular)光照

  • 环境光照:来自散落于我们周围的很多光源,这些来自四周的光源总会为物体的表面着色
  • 漫反射光照:漫反射光照是让物体产生视觉影响的主要光照,它特点是面向光源的一面比其他面会更亮
  • 镜面光照:镜面光照根据光的反射特性,让有光泽的物体出现亮点

在OpenGL中,我们会在自定义shader中,自己写这3种光照计算算法,但是在OpenGL ES,我们使用GLKit会简化很多,下面就是一个使用光照的简单例子:

-(void)setupGL{
    // 设置设备上下文
    GLKView *view = (GLKView *)self.view;
    view.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
    view.drawableDepthFormat = GLKViewDrawableDepthFormat24;
    [EAGLContext setCurrentContext:view.context];
    
    // case 1:设置环境光
    self.effect = [[GLKBaseEffect alloc] init];
    // 开启light0光照,light0默认是关闭的
    self.effect.light0.enabled = GL_TRUE;
    // 设置为绿色的环境光,如果这样运行Demo,可以看到的是绿色的球体
    self.effect.light0.ambientColor = GLKVector4Make(0.0f, 1.0f, 0.0f, 1.0f);

    // case 2: 添加散射光
    self.effect = [[GLKBaseEffect alloc] init];
    self.effect.light0.enabled = GL_TRUE;
    self.effect.light0.ambientColor = GLKVector4Make(0.0f, 1.0f, 0.0f, 1.0f);
    // 这时可以看到,面向光照的一面是红色的,而背向光照的一面是深绿色
    self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.0f, 0.0f, 1.0f);

    // case 3:添加镜面光
    self.effect = [[GLKBaseEffect alloc] init];
    self.effect.light0.enabled = GL_TRUE;
    self.effect.light0.ambientColor = GLKVector4Make(0.0f, 1.0f, 0.0f, 1.0f);
    self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.0f, 0.0f, 1.0f);
    // 这里需要注意,而在GLKit中材质的镜面光默认值是{0.0f, 0.0f, 0.0f, 1.0f},这样设置光照的镜面光是没有效果的
    // 所以这里我们需要设置材质的镜面光
    self.effect.material.specularColor = GLKVector4Make(0.8f, 0.8f, 0.8f, 0.0f);
    // 材质的发光值,发光值越高,聚光效果越好
    self.effect.material.shininess = 32;
    // 设置光照的镜面光
    self.effect.light0.specularColor = GLKVector4Make(0.0f, 0.0f, 1.0f, 0.0f);

    // case 4:多光源
    self.effect = [[GLKBaseEffect alloc] init];
    // 材质镜面光
    self.effect.material.specularColor = GLKVector4Make(0.8f, 0.8f, 0.8f, 0.0f);
    self.effect.material.shininess = 32;
    // 第一个光源
    self.effect.light0.enabled = GL_TRUE;
    self.effect.light0.ambientColor = GLKVector4Make(0.0f, 1.0f, 0.0f, 1.0f);
    self.effect.light0.diffuseColor = GLKVector4Make(1.0f, 0.0f, 0.0f, 1.0f);
    self.effect.light0.specularColor = GLKVector4Make(0.0f, 0.0f, 1.0f, 0.0f);
    // 第二个光源
    self.effect.light1.enabled = GL_TRUE;
    self.effect.light1.position = GLKVector4Make(1.0f, 0.0f, 1.0f, 0.0f);
    self.effect.light1.ambientColor = GLKVector4Make(0.0f, 0.0f, 0.0f, 1.0f);
    self.effect.light1.diffuseColor = GLKVector4Make(0.0f, 1.0f, 1.0f, 1.0f);
    self.effect.light1.specularColor = GLKVector4Make(1.0f, 0.0f, 0.0f, 0.0f);
    
    关于材质
    在case 3中,我们设置了材质的镜面光,材质还有环境光和散射光,那么它们和光源的环境光、散射光和镜面光有什么不同呢?
    材质的这些光就是材质的属性,一个物体,它之所以会有颜色,是因为它反射了有颜色的光。例如一个蓝色的物体,当太阳光照到它时,它吸收了其他颜色的光,只反射了蓝色光。
    举个例子:
    如果我们设置材质镜面光为{0.0f, 0.0f, 0.8f, 0.0f},
    此时,当材质受到镜面光照射时,它会反射0倍的红色,0倍的绿色,0.8倍的红色
    此时,再设置光照的镜面光为{1.0f, 1.0f, 0.0f, 0.0f},那么将毫无镜面光效果,因为此时的材质根本不会反射红色和绿色。
    这也就解释了case 3中,我们为什么要设置材质的镜面光了,因为材质的镜面光默认都是0,我们无论怎么设置光照的镜面光,都是没有效果的
    我们也可以设置材质环境光和散射光,它们和镜面光同理

    glEnable(GL_DEPTH_TEST);
}
case 1 截图
case 2 截图
case 3 截图
case 4 截图
// 绘制3个球体的方法
-(void)glkView:(GLKView *)view drawInRect:(CGRect)rect{
    glClearColor(0xeb/255.f, 0xf5/255.f, 0xff/255.f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
    for (int i = 0 ; i < 3; i ++) {
        [self.effect prepareToDraw];
        
        float aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height);
        GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 100.0f);
        self.effect.transform.projectionMatrix = projectionMatrix;
        self.effect.transform.modelviewMatrix = GLKMatrix4MakeTranslation(0.0f, 3*i-2, -(i+8));
        
        glGenBuffers(1, &_vertexID);
        glBindBuffer(GL_ARRAY_BUFFER, _vertexID);
        glBufferData(GL_ARRAY_BUFFER, sizeof(sphereVerts), sphereVerts, GL_STATIC_DRAW);
        
        glGenBuffers(1, &_normalID);
        glBindBuffer(GL_ARRAY_BUFFER, _normalID);
        glBufferData(GL_ARRAY_BUFFER, sizeof(sphereNormals), sphereNormals, GL_STATIC_DRAW);
        
        glEnableVertexAttribArray(GLKVertexAttribPosition);
        glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 3*sizeof(GLfloat), 0);
        
        glEnableVertexAttribArray(GLKVertexAttribNormal);
        glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 3*sizeof(GLfloat), 0);
        
        glDrawArrays(GL_TRIANGLES, 0, sphereNumVerts);
        
        glDeleteBuffers(1, &_vertexID);
        _vertexID = 0;
        glDeleteBuffers(1,&_normalID);
        _normalID = 0;
    }
}
// 删除缓存
- (void)dealloc
{
    [EAGLContext setCurrentContext:((GLKView *)self.view).context];
    if (_vertexID != 0){
        glDeleteBuffers (1,&_vertexID);
        _vertexID = 0;
    }
    if (_normalID != 0){
        glDeleteBuffers (1,&_normalID);
        _normalID = 0;
    }
    [EAGLContext setCurrentContext:nil];
}

Demo下载地址:https://github.com/cdcyd/CCOpenGLES

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,961评论 5 473
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,444评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,009评论 0 333
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,082评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,101评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,271评论 1 278
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,738评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,395评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,539评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,434评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,481评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,160评论 3 317
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,749评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,816评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,038评论 1 256
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,548评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,140评论 2 341

推荐阅读更多精彩内容