本项目基于OpenGL、GLEW、GLM、GLFW以及SOLI2库,实现了一个模拟水面效果的3D场景。该场景具有以下主要特性:
- 基于Phong反射模型的ADS光照效果。
- 玩家控制摄像机的移动。
- 水面反射和折射效果。
- OpenGL: 用于实现图形渲染。
- GLEW: OpenGL扩展加载库,用于加载OpenGL扩展。
- GLM: 3D数学库,用于处理矩阵变换和向量运算。
- GLFW: 用于创建窗口并管理用户输入。
- SOLI2: 用于加载和渲染3D模型,不过本项目仅用其读取图片并生成天空盒。
在场景中实现了基于Phong反射模型的光照计算,包括环境光(Ambient)、漫反射光(Diffuse)和镜面反射光(Specular)三部分。通过计算光照与表面法线的角度、反射向量与视线向量的角度来调整光照效果,使得物体的表面呈现出真实的光照反应。
通过欧拉角计算相机的朝向变动,用户可以根据鼠标移动、WASDQE控制相机位置和朝向 用户可按住Shift加速运动,键盘1、2控制鼠标灵敏度
大体思路创建反射缓冲区和折射缓冲区,反射缓冲区的填充方法是在水面下方生成一个虚拟相机(与主相机关于水平面对称),剔除不必要的渲染目标后将其目标输出放入反射缓冲区,折射缓冲区同理。 将需要使用纹理贴图的目标物体的屏幕坐标作为访问反射和折射缓冲区中的纹理坐标。由于顶点着色器中已经计算过屏幕坐标(gl_Position),故只需要将gl_Position.xy传给片段着色器使用即可(本人的Unity Portal项目也是采用了这个思路,相关的应用场景还有的镜子等)
用基于Perlin噪声的平滑噪声(三线性插值)+湍流(turbulence)理念(核心思想是通过将多层次的噪声(不同频率和振幅)叠加在一起,来模拟自然界中复杂、无规则的现象)完成了3D噪声纹理贴图(其实本项目用2D噪声纹理贴图也完全可行),并将其传给FragmentShader,在片段着色器中使用相邻三个点的高度信息计算出表面法线(这正是波浪等动态表面效果中常见的法向量计算方法)。
1.水面下的物体在水面上方观察时会轻微扭曲: *与4的处理基本一致,用噪声图模拟高度贴图再估算出法向量,但是高度的乘法因子需要很小
2.在水面下方观察光照时会发生扭曲 *同上
3.在水面上方添加菲涅尔效应(反射角越大反射越强,折射越弱) *需要计算水面顶点法向量与视线向量的夹角,根据此夹角Clamp处理后进行线性插值,混合反射和折射
4.添加雾效 *需要定义fogStart和fogEnd的值,根据vertice的pos确定雾效因子
实际上是用3D纹理贴图的y方向分量的变化,模拟出水面的动态效果。

