GAMES202第二课

基本渲染管线

  1. 体在空间中的表示 – 点,点和点之间的连接关系
  • 顶点处理 MVP
  • 图元装配和光栅化
  • 片元处理
  • 输出合并
  1. 型(Blinn-Phong等等)在光线的弹射和阴影的表现上并不是很好(并不是100%真实,在全局和间接光照上处理的不好)

    好处是GPU上跑很快

  2. 纹理映射和插值–重心坐标

OpenGL(GLSL)

OpenGL介绍

OpenGL是一个API的集合,是CPU运行的负责调用GPU工作任务的。

优势:

  • 语言无关
  • 跨平台

坏处:

  • 版本特别碎片化
  • C语言风格,不方便使用

在每个pass中进行的过程

  1. 放置物体和模型
    1. 模型声明
    2. 模型摆放 – model transformation
    3. VBO:GPU中的一块区域用于存储模型与.obj文件特别相似
  2. 设置相机位置
    1. 视口变换 – view transformation
    2. 在OpenGL中创建framebuffer
  3. 设置画布
    1. 这里OpenGL可以multiple render target
    2. 垂直同步,双重缓冲,三重缓冲,目的都是为了防止画面撕裂,撕裂原因是在帧缓冲中上一帧画面渲染到一般又渲染了下一帧
  4. 画 – shading
    1. vertex
      1. 对顶点进行插值
    2. 图元装配光栅化
    3. fragment
      1. 片段着色
      2. lighting
  5. 接着画,画多次 – multiple passes
    1. shadowmap的作法
      1. 计算光源能看到什么
      2. 再通过camera来计算这些物体能不能被light看到,不能就是在阴影中

Shader setup步骤

  1. 创建shader
  2. 编译shader
  3. 将shader加载到程序中(attach program)
  4. 连接程序(link program)
  5. 使用程序(use program)

Vertex Shader(顶点着色器)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// attribute这个只可能在vertex shader中出现,fragment shader中没有
// 顶点位置
attribute vec3 aVertexPosition;
// 法线位置
attribute vec3 aNormalPosition;
// 纹理坐标
attribute vec3 aTextureCoord;

// uniform关键字指定全局变量,vertex和fragment shader都可以用
uniform mat4 uModeViewMatrix;
uniform mat4 uProjectionMatrix;

// 通过varying关键字指定fragment shader中需要插值的量
// highp指定计算精度
varying highp vec2 vTextureCoord;
varying highp vec3 vFragPos;
varying highp vec3 vNormal;

void main(void){
// 设置要传给frag的属性
vFragPos = aVertexPosition;
vNormal = aNormalPosition;

// 转换成齐次坐标再进行MVP
gl_Position = uProjectionMatrix * uModelViewMatrix * vec4(aVertexPosition, 1.0);

vTextureCoord = aTextureCoord;
}

Fragment shader

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
// uniform关键字指定全局变量,vertex和fragment shader都可以用
uniform sampler2D uSampler;
// binn
uniform vec3 uKd;
uniform vec3 uKs;
uniform vec3 uLightPos;
uniform vec3 uCameraPos;
uniform float uLightIntensity;
uniform int uTextureSample;

// 通过varying关键字指定fragment shader中需要插值的量
varying highp vec2 vTextureCoord;
varying highp vec3 vFragPos;
varying highp vec3 vNormal;

void main(void){
vec3 color;
if(uTextureSample == 1){
// vec3(2.2)表示伽马矫正
color = pow(texture2D(uSampler, vTextureCoord).rgb, vec3(2.2));
}else{
color = uKd;
}

// 环境光
vec3 ambient = 0.05 * color;

// 光线方向由光源位置-点位置得到
vec3 lightDir = normalize(uLightPos - vFragPos);
vec3 normal = normalize(vNormal);
// 兰伯特
float diff = max(dot(lightDir, normal), 0.0);
// 光照强度系数
float light_atten_coff = uLightIntensity / length(uLightPos - vFragPos);
// 漫反射
vec3 diffuse = diff * light_atten_coff * color;

// 视线方向
vec3 viewDir = normalize(uCameraPos - vFragPos);
float spec = 0.0;
// 反射方向,需要从点出发,光源方向也是从点出发表示,因此为-lightDir
vec3 reflectDir = reflect(-lightDir, normal);
// 高光
spec = pow(max(dot(viewDir, reflectDir), 0.0), 35.0);
// 加上高光强度
vec3 specular = uKs * light_atten_coff * spec;

// blinn-phong
gl_FragColor = vec4(pow((ambient + diffuse + specular), vec3(1.0/2.2)), 1.0);
}

渲染方程

在渲染中是最为重要的

  • 描述了光线的传播

渲染方程

意思解释:

  1. outgoing radiance:当前点发出的radiance
  2. emission:点的自发光
  3. BRDF * cosθ * dw:BRDF乘上cosθ然后乘以其他地方打到这个点上的radiance
    1. cosθ * dw: 是将radiance转换成irradiance

渲染方程

V(p, w):表示点是否可以接收到当前传过来的那束光