环境贴图
撰写于 2016-11-15 修改于 2018-01-29 分类 OpenGL
接上一节的天空盒子。天空已经展示出来了,但是里面的物体显示的还是有问题,物体显的很违和,并没有反射出周围的环境光,并没有融合的到周围的环境中,这就需要环境贴图了,涉及到 反射 和 折射。
反射
反射很简单,还是借教程中的图片一用(^ __ ^)
如图所示,根据法线和摄影机(即图中的人眼)的位置,就可以计算出反射向量,立方体贴图可以根据向量就可以得到颜色信息(是不是很方便!),当然这一切只用在片段着色器和顶点着色器中修改即可。
顶点着色器要传入物体的法线向量,此处有一个关键:顶点着色器处理的坐标都是基于世界坐标系,所以法线向量也要转化为世界坐标系,但是向量只有方向和大小,并没有位置这一说,所以一定要把变换矩阵中位移去除,还有一点,就是物体的不等比缩放,会导致法线向量的偏差,这一点在基础光照教程中有说,所以这里的向量要特殊处理,需要把变换换矩阵转转换为正规矩阵(Normal Matrix),正规矩阵被定义为“模型矩阵左上角的逆矩阵的转置矩阵”,具体的计算方法在此处。核心源码如下:
1 |
|
片段着色器中,会把传入的相机坐标和物体坐标组成向量并格式化,然后根据法线向量算出反射向量。核心源码如下:1
2
3
4
5
6
7
8
9
10
11
12
in vec3 Normal;
in vec3 Position;
out vec4 color;
uniform vec3 cameraPos;
uniform samplerCube skybox;
void main()
{
vec3 I = normalize(Position - cameraPos);
vec3 R = reflect(I, normalize(Normal));
color = texture(skybox, R);
}
渲染时,把相机位置和贴图纹理传入即可:1
2
3glBindTexture(GL_TEXTURE_CUBE_MAP, this->skyBoxTextureID);
glUniform3fv(glGetUniformLocation(cubeShader->getProgram(), "cameraPos"),1, value_ptr(Camera::cameraPos));
glUniform1i(glGetUniformLocation(cubeShader->getProgram(), "skybox"), 0);
运行效果图如下:
反射就是这样,下面就是折射。
折射
如果你学过物理,折射也很简单,没学过,也很简单,看图简单明了
跟计算反射的原理差不错,我们只要找出折射后的向量即可。折射后,视线的折射角度跟材质的折射率有关,我们假设物体是玻璃(折射率是1.52),光线是从空气进入玻璃中的。当然这不需要我们手动去计算,glsl已经提供了API给我们:refract,只需要把入射向量,法线,折射指数比率。折射指数比率是指两种材质的折射率之比。
顶点着色器不变,片段着色器修改如下:
1 | ... |
运行效果图如下:
立方体贴图到此为止,下面是高级数据!
参考教程:https://learnopengl-cn.github.io/
学习交流:我的OpenGL工程