OpenGL教程:15. 最简单的阴影生成算法——硬阴影生成

硬阴影是最暴力的一种求阴影的方法,比较逆天,但很简单,原理如下:

image-20221118221557814

设光位置为$(x_l,y_l,z_l)$,片元位置为$(x,y,z)$,片元的投影位置为$(x_k,y_k,z_k)$。

由几何关系:

解得:

同理解得:

$y_k$是我们设的投影的高度位置,于是可以写成如下的投影矩阵:

在着色器中,我们要除以$w_k$分量,保证阴影正确(这是因为矩阵中将分母$y-y_l$处理到$w_k$处了,这里跟透视除法的原因是类似的)。于是着色器可以这样写:

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
// vertex shader
#verison 330 core
layout(location = 0) in vec3 aPos;
layout(location = 1) in vec2 aTexcoord;

out vec2 Texcoord;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
uniform mat4 shadowMatrix; //这里就是硬阴影矩阵的uniform变量
uniform int isShadow; //传递isShadow变量,1表示要渲染阴影了

void main() {
vec4 position = vec4(aPos, 1.0f);
if(isShadow) {
position = shadowMatrix * position; //获得阴影位置
position.xyz /= position.w; //做除法,原因已经解释过了
} else {
position = model * position;
}
position = projection * view * position;
gl_Position = position;
Texcoord = aTexcoord;
}

// fragment shader
#version 330 core
in vec2 Texcoord;
out vec4 FragColor;

uniform int isShadow; //传递isShadow变量,1表示要渲染阴影了
uniform sampler2D tex; //片元的材质采样器

void main() {
if(isShadow) {
FragColor = vec4(0.0f); //阴影为黑色
} else {
FragColor = texture2D(tex, Texcoord);
}
}

image-20230119113043589

OpenGL教程:15. 最简单的阴影生成算法——硬阴影生成

http://blog.inverseda.top/2022/11/14/ComputerGraphics/OpenGL/15.硬阴影/

Author

InverseDa

Posted on

2022-11-14

Updated on

2023-03-30

Licensed under

Comments

Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×