openGL系列文章目录

前言

Bui Tuong Phong 在犹他大学的研究生期间开发了一种平滑的着色算法,在1973 年的论文[PH73]中对其进行了描述,并在[PH75]中发表。该算法的结构类似于Gouraud 着色的算法,其不同之处在于光照计算是按像素而非顶点完成。由于光照计算需要法向量N 和光向量L,但在模型中仅顶点包含这些信息,因此Phong 着色通常使用巧妙的“技巧”来实现,其中N和L 在顶点着色器中进行计算,并在光栅化期间插值。图1概述了此策略。

图1
C++/OpenGL 代码完全如前。之前部分在顶点着色器中完成的过程现在回放入片段着色器中进行。法向量插值的效果如图2 所示。现在我们已经准备好使用Phong 着色实现位置光照射下的环面了。大多数代码与实现Gouraud 着色的代码相同。由于C++/OpenGL 代码完全没有改变,在此我们只展示修改过的顶点着色器和片段着色器,如图3所示,Phong 着色修正了Gouraud 着色中出现的伪影。

图2

图3

顶点着色器

#version 430
layout (location=0) in vec3 vertPos;
layout (location=1) in vec3 vertNormal;
out vec3 varyingNormal; // 视觉空间顶点法向量
out vec3 varyingLightDir; // 指向光源的向量
out vec3 varyingVertPos; // 视觉空间中的顶点位置
// 结构体和统一变量与Gouraud 着色相同
. . .
void main(void)
{ // 输出顶点位置、光照方向和法向量到光栅器以进行插值
varyingVertPos=(mv_matrix * vec4(vertPos,1.0)).xyz;
varyingLightDir = light.position - varyingVertPos;
varyingNormal=(norm_matrix * vec4(vertNormal,1.0)).xyz;
gl_Position=proj_matrix * mv_matrix * vec4(vertPos,1.0);
}

片元着色器

#version 430
in vec3 varyingNormal;
in vec3 varyingLightDir;
in vec3 varyingVertPos;
out vec4 fragColor;
// 结构体和统一变量与Gouraud 着色相同
. . .
void main(void)
{ // 正规化光照向量、法向量、视觉向量
vec3 L = normalize(varyingLightDir);
vec3 N = normalize(varyingNormal);
vec3 V = normalize(-varyingVertPos);
// 计算光照向量基于N 的反射向量
vec3 R = normalize(reflect(-L, N));
// 计算光照与平面法向量间的角度
float cosTheta = dot(L,N);
// 计算视觉向量与反射光向量的角度
float cosPhi = dot(V,R);
// 计算ADS 分量(按像素),并合并以构建输出颜色
```cpp
vec3 ambient = ((globalAmbient * material.ambient) + (light.ambient * material.ambient)).xyz;
vec3 diffuse = light.diffuse.xyz * material.diffuse.xyz * max(cosTheta,0.0);
vec3 specular =
light.specular.xyz * material.specular.xyz * pow(max(cosPhi,0.0), material.shininess);
fragColor = vec4((ambient + diffuse + specular), 1.0);
}

虽然Phong 着色有着比Gouraud 着色更真实的效果,但这是建立在增大性能消耗的基础上的。James Blinn 在1977 年提出了一种对于Phong 着色的优化方法[BL77],被称为Blinn-Phong反射模型。这种优化是基于观察到Phong 着色中消耗最大的计算之一是解出反射向量R。Blinn 发现向量R 在计算过程中并不是必需的——R 只是用来计算角φ 的手段。角φ 的计算可以不用向量R,而通过L 与V 的角平分线向量H 得到。如图4 所示,H 和N 之间的角α 刚好等于1⁄2(φ)。虽然α 与φ 不同,但Blinn 展示了使用α 代替φ 就已经可以获得足够好的结果。角平分线向量可以简单地使用L+V 得到(见图5),之后cos(α)可以通过•) )H N的点积计算。


图4

图5
这些计算可以在片段着色器中进行,甚至为了性能考虑(经过一些调整)也可以在顶点着色器中进行。图6 展示了使用Blinn-Phong 着色的环面。它在图形质量上几乎与Phong渲染相同,同时节省了大量性能损耗。

图6
程序3 中展示了修改后顶点着色器和片段着色器,它们用来将程序7.2 中的Phong 着色示例转换为Blinn-Phong 着色。C++ / OpenGL 代码与之前一样没有变化。
程序3 Blinn-Phong 着色的环面

顶点着色器

#version 430layout (location = 0) in vec3 vertPos;
layout (location = 1) in vec3 vertNormal;
out vec4 varyingColor;struct PositionalLight
{   vec4 ambient;vec4 diffuse;vec4 specular;vec3 position;
};
struct Material
{   vec4 ambient;vec4 diffuse;vec4 specular;float shininess;
};uniform vec4 globalAmbient;
uniform PositionalLight light;
uniform Material material;
uniform mat4 mv_matrix;
uniform mat4 proj_matrix;
uniform mat4 norm_matrix;void main(void)
{   vec4 color;// convert vertex position to view spacevec4 P = mv_matrix * vec4(vertPos,1.0);// convert normal to view spacevec3 N = normalize((norm_matrix * vec4(vertNormal,1.0)).xyz);// calculate view-space light vector (from point to light)vec3 L = normalize(light.position - P.xyz);//  view vector is negative of view space positionvec3 V = normalize(-P.xyz);//  R is reflection of -L around the plane defined by Nvec3 R = reflect(-L,N);// ambient, diffuse, and specular contributionsvec3 ambient =((globalAmbient * material.ambient)+ (light.ambient * material.ambient)).xyz;vec3 diffuse =light.diffuse.xyz * material.diffuse.xyz* max(dot(N,L), 0.0);vec3 specular =pow(max(dot(R,V), 0.0f), material.shininess)* material.specular.xyz * light.specular.xyz;// send the color output to the fragment shadervaryingColor = vec4((ambient + diffuse + specular), 1.0);// send the position to the fragment shader, as beforegl_Position = proj_matrix * mv_matrix * vec4(vertPos,1.0);
}

片元着色器

#version 430in vec4 varyingColor;
out vec4 fragColor;//  uniforms match those in the vertex shader,
//  but aren’t used directly in this fragment shaderstruct PositionalLight
{   vec4 ambient;  vec4 diffuse;  vec4 specular;  vec3 position;
};struct Material
{   vec4 ambient;  vec4 diffuse;  vec4 specular;  float shininess;
};uniform vec4 globalAmbient;
uniform PositionalLight light;
uniform Material material;
uniform mat4 mv_matrix;
uniform mat4 proj_matrix;
uniform mat4 norm_matrix;//  interpolate lighted color
// (interpolation of gl_Position is automatic)void main(void)
{   fragColor = varyingColor;
}


图7

参考

计算机图形学编程 使用OpenGL和C++

openGL中Phong 着色相关推荐

  1. Learn OpenGL(七)——OpenGL中使用着色器的基本步骤及GLSL渲染简单示例

    OpenGL着色语言(OpenGL Shading Language,GLSL)是用来在OpenGL中着色编程的语言,是一种具有C/C++风格的高级过程语言,同样也以main函数开始,只不过执行过程是 ...

  2. OpenGL中phong光照模型详解

    版权 cesuolidec4 https://blog.csdn.net/xiewenzhao123/article/details/54600191 引言 现实世界的光照是极其复杂的,而且会受到诸多 ...

  3. OpenGL中的着色模式GL_SMOOTH与GL_FLAT

    glShadeModel void glShadeModel ( GLenum mode)是OpenGL1.0提供的接口.作用是设置着色模式. 参数mode可以是GL_SMOOTH(默认值)或GL_F ...

  4. Opengl ES之着色器

    前言 在前面我们介绍了 OpenglEs之EGL环境搭建 ,在后面的例子中,我们将无可避免地需要使用到着色器.而着色器才是Opengl的灵魂所在,有了着色器才有了Opengl天马行空的世界. 图形渲染 ...

  5. OpenGL中环境光、漫反射、镜面反射对光的影响(如何被抽象成向量进行着色的)

    文章目录 Phong算法中影响光照的三个因素 环境光(Ambient)对光线的影响 漫反射(Diffuse)对光的影响 镜面反射(Specular)对光的影响 衰减(Attenuation) Phon ...

  6. OpenGL在frag着色器中模拟手电筒效果

    在[OpenGL在frag着色器中模拟点光源]的基础上进行修改,得到手电筒效果(https://blog.csdn.net/qq_37340753/article/details/105029079) ...

  7. OpenGL中的曲面细分和几何着色器

    [摘要]本文我们先介绍OpenGL中的曲面细分的一些基本概念,然后给两个例子说明不得不用这项技术的理由. 曲面细分是OpenGL 4.0之后才定义的功能,使用之前请确认你的显卡驱动支持OpenGL4. ...

  8. OpenGL ES像素着色器

    OpenGL ES像素着色器 原文   http://www.tairan.com/archives/7509 目 录 准备开始 像素着色器 vs 顶点/片段着色器 像素着色器101:渐变 像素着色器 ...

  9. OpenGL ES像素着色器教程

    OpenGL ES像素着色器教程 时间 2014-08-27 09:54:51   泰然 原文   http://www.tairan.com/archives/7509 主题  OpenGL ES ...

最新文章

  1. 微信小程序绑定数据以及自定义指令
  2. 一致性hash算法简介
  3. 【数据竞赛】长文本竞赛上分的三种策略。
  4. docker-compose部署常用服务
  5. django 2.0 url匹配
  6. dbscan论文_论文分享 :Linkage Based Face Clustering via GCN
  7. 【招聘(深圳)】TCL通讯科技控股有限公司
  8. 【HDU - 5873】Football Games(兰道定理,知识点总结)
  9. 如何读入一个多行的txt文件,给每行的数据加双引号并保存为一行输出
  10. 集成电路总设计(Ⅴ)
  11. 自定义微信小程序弹框
  12. matepadpro升级鸿蒙,鸿蒙OS下月推出!MatePad Pro升级EMUI 11,提前预演
  13. ASCLL UTF-8 GBK URL编码
  14. 信息安全快讯丨一起为亚运健儿加油!
  15. 全国计算机王牌专业的一本大学,全国大学最牛专业排行,报考必读!
  16. 【鸡啄米】VC++串口通信编程详解
  17. 余压监控系统在高层民用建筑的应用
  18. 请谨慎使用预训练的深度学习模型
  19. 利用python爬取实习僧网站上的数据
  20. 3t硬盘分区 Linux win,3TB使用大难题 得先学会怎么分区_内存硬盘行情-中关村在线...

热门文章

  1. 3DsMax游戏模型制作技巧,掌握这些技术你也能接私活啦
  2. Win10无法开机修复方法
  3. [抄袭]年薪五万程序员的生活及他的理财梦
  4. ISP各个模块功能介绍
  5. 【TED ON FLEX】支持flashplayer的RIBBIT系统
  6. iOS 中设置下划线失效不显示
  7. java之Mybatis(实训笔记)
  8. python 扩展c extention
  9. 阿里云centos7配置php mysql_阿里云centos7安装NGINX+MYSQL+PHP-FPM环境
  10. CAT1模块EC200S 4G物联网模块串口透传MQTT协议 快速入门指导资料