OpenGL 笔记

OpenGL笔记十五:GLSL光照计算

2019-06-19  本文已影响45人  御雪飞斐

前言

期待您移步上篇:OpenGL笔记十四:GLSL语法

顶点着色器

1.矩阵变换位置
2.计算光照公式⽣成逐顶点颜⾊
3.⽣成/变换纹理坐标

gl_VertexID ,是一个输入变量。用于保存顶点的整数索引。gl_VertexID 是整数型变量,用 highp 精度限定修饰符声明。
gl_InstanceID ,是一个输入变量。用于保存实例化绘图调用中图元的实例编号。对于常规的绘图调用,该值为0;gl_InstanceID 是整数型变量,用 highp 精度限定修饰符声明。
gl_Position ,用于输出顶点位置的裁剪坐标。该值在裁剪和视口变换用于执行相应的图元裁剪以及从裁剪坐标到屏幕坐标的顶点位置转换。如果顶点着色器位写入 gl_Position ,则 gl_Position 的值未定义。 gl_Position 是浮点型变量,用 highp 精度限定修饰符声明。
gl_PointSize ,可以写入像素标识点精灵(即像素点)的尺寸,在渲染点精灵时使用。顶点着色器输出的 gl_PointSize 值被限定在 OpenGL ES 3.0 实现支持的费平滑点大小范围之内。gl_PointSize 是浮点型变量,用 highp 精度限定修饰符声明。
gl_FrontFacing ,是一个特殊变量,但不是由顶点着色器直接写入的,而是根据顶点着色器生成的位置值和渲染图元的类型生成的。gl_FrontFacing 是一个布尔值类型。

在顶点着色器内可用的唯一内键 Uniform 状态是窗口坐标中的深度范围。这些由内建统一变量名 gl_DepthRange 给出。

struct gl_DepthRangeParameters 
{
  highp float near; //near z
  highp float far; //near far
  highp float diff; //far - near 
}
uniform gl_DepthRangeParameters gl_DepthRange;
 const mediump int gl_MaxVertexAttribs = 16;
 const mediump int gl_MaxVertexUniformVectors = 256;
 const mediump int gl_MaxVertexOutputVectors = 16;
 const mediump int gl_MaxVertexTextureImageUnits = 16;
 const mediump int gl_MaxCombinedTextureImageUnits = 32;

gl_MaxVertexAttribs :可以指定得顶点数据的最大数量。
gl_MaxVertexUniformVectors :顶点着色器可以使用的 vect4 Uniform 变量的最大数量。
gl_MaxVertexOutputVectors :输出向量的最大数量。
gl_MaxVertexTextureImageUnits :顶点着色器可用纹理单元的最大数量。
gl_MaxCombinedTextureImageUnits :顶点/片元着色器中的可用纹理单元的最大数量的总和。

组成MVP矩阵的每个单独矩阵执行的变换如下

  • 模型矩阵 -- 将物体坐标变换为世界坐标
  • 视图矩阵 -- 将世界坐标变换为眼睛坐标(观察坐标)
  • 投影矩阵 -- 讲眼睛坐标(观察者坐标)变换为裁剪坐标

片元着色器

1.计算颜⾊
2.获取纹理值
3.往像素点中填充颜⾊值(纹理值/颜⾊值)

gl_FragCoord :片元着色器中一个只读变量,这个变量保存片元的窗口相对坐标。
gl_FrontFacing :片元着色器中额的一个只读变量,为布尔类型变量,正面图元时为true,否则为false。
gl_PointCoord :只读变量,可以在渲染点精灵使用,保存点精灵的纹理坐标,这个坐标在点精灵光栅化期间自动生成,处于(0,1)区间。
gl_FragDepth :一个只写输出变量,在片元着色器写入时,覆盖片元的固定功能深度值。尽量减少手动实现深度值写入。这个功能需要谨慎使用,因为它可能禁用许多GPU的深度优化。例如:许多GPU都有"Early -Z"的功能,在执行片元着色器之前进行深度测试,使用"Early -Z"的好处就是不能通过深度测试的片元就不会被着色(从而减少了着色器调用次数,提高性能),但是使用 gl_FragDepth 就必须禁用该功能,因为GPU在执行着色器之前不知道深度值。

const mediump int gl_MaxFragmentInputVectors = 15;
 const mediump int gl_MaxTextureImageUnits = 16;
 const mediump int gl_MaxFragmentUniformVectors = 224;
 const mediump int gl_MaxDrawBuffers = 4;
 const mediump int gl_MinProgramTexelOffset = -8;
 const mediump int gl_MaxProgramTexelOffset = 7;

gl_MaxFragmentInputVectors :片元着色器输入的最大数量
gl_MaxFragmentUniformVectors :可用纹理图像单元的最大数量
gl_MaxFragmentUniformVectors :片元着色器可用vec4 Uniform变量的最大数量
gl_MaxDrawBuffers :多重渲染目标最大支持数量

 attribute vec2 v_texCoord;
 uniform sampler2D s_baseMap;
 uniform sampler2D s_SecondMap;
 void main() {
 vec4 baseColor;
 vec4 secondColor;
 baseColor = texture(s_baseMap,v_texCoord);
 secondColor = texture(s_SecondMap,v_texCoord);
 gl_FragColor = baseColor * secondColor;
}
//将各个纹理对象绑定到纹理单元0和1,为采样器设置数 值,将采集器绑定到对应的纹理单元
glActiveTexutre(GL_TEXTURE0);
glBindTeture(GL_TEXTURE_2D,baseMapTexId);
glUniformli(baseMapTexId,0);
glActiveTexutre(GL_TEXTURE1);
glBindTeture(GL_TEXTURE_2D,secondMapTexId);
glUniformli(secondMapTexId,1);

dot :点乘
cross :叉乘
texture2D :⽤于对纹理采样
normalize :对⼀个向量规格化
clamp :将⼀个向量固定在⼀个最⼩值和最⼤值之间

光照特性

材质属性

光照计算

1.环境光的计算

环境光 = 环境因子 * 物体的材质颜⾊

2.发射光的计算

发射颜⾊ = 物体的反射材质颜⾊

3.漫反射光计算

漫反射颜⾊ = 光源的漫反射颜⾊ * 物体的漫发射材质颜⾊ * DiffuseFactor

DiffuseFactor = max(0,dot(N,L))

漫反射因⼦DiffuseFactor 是光线 与顶点法线向量的点积

4.镜⾯光计算

镜⾯反射颜⾊ = 光源的镜⾯光的颜⾊ * 物体的镜⾯材质颜⾊ * SpecularFactor

SpecularFactor = power(max(0,dot(N,H)),shininess)

H :视线向量E 与 光线向量L 的半向量
dot(N,H) :H,N的点积⼏何意义,平⽅线与法线夹⻆角的cos值
shiniess : ⾼光的反光度

光照计算

光照颜⾊ = (环境颜⾊ + 漫反射颜⾊ + 镜⾯反射颜⾊) * 衰减因⼦

衰减因⼦

衰减因⼦ = 1.0/(距离衰减常量 + 线性衰减常量 * 距离 + ⼆次衰减常量 * 距离的平⽅)

注:

  • 距离衰减常量,线性衰减常量和⼆次衰减常量均为常量值
  • 环境光,漫反射光和镜⾯光的强度都会受距离的增⼤⽽衰减,只有发射光和全局环境光的强度不会受影响

聚光灯因⼦

聚光灯夹⻆角cos值 = power(max(0,dot(单位光源位置,单位光线向量)),聚光灯指数)

  • 单位光线向量是从光源指向顶点的单位向量
  • 聚光灯指数,表示聚光灯的亮度程度
  • 公式解读:单位光源位置 * 单位光线向量 点积 的 聚光灯指数次⽅

增加过渡计算

聚光灯因⼦ = clamp((外环的聚光灯⻆角度cos值 - 当前顶点的聚光灯⻆角度cos值)/ (外环的聚光灯⻆角度cos值- 内环聚光灯的⻆角度的cos值),0,1)

光照计算终极公式

光照颜⾊ = 发射颜⾊ + 全局环境颜⾊ + (环境颜⾊ + 漫反射颜⾊ + 镜⾯反 射颜⾊) * 聚光灯效果 * 衰减因⼦

上一篇下一篇

猜你喜欢

热点阅读