OpenGL踩坑总结2----光照篇

  • 踩坑系列2,学习教程:LearnOpenGL 我的:代码仓库,以下是与光照篇的学习中我感到迷惑的地方,算是坑吧:

1. 法线矩阵为什么是顶点变换矩阵的逆转置矩阵?

  • A空间与B空间的法线N与切线T分别设为Na和Ta,Nb和Tb,一定满足Na · Ta = 0,Nb · Tb = 0。A到B空间的顶点变换矩阵为Ma->b,设法线矩阵为G,则有:
    • (其中:"·"表示点乘,"t()"表示转置,"*"表示矩阵乘法,"-"表示逆矩阵,"E"表示单位矩阵)
    • Nb · Tb = (G * Na) · (Ma->b * Ta)
    • = (G*Na) · t(Ma->b * Ta) (点乘转化为矩阵乘法,稍微动脑可自证)
    • = Na * (G * t(Ma->b)) * t(Ta) = 0
    • 由于 Na · Ta = Na * t(Ta) = Na * E * t(Ta) = 0
    • 可知当G * t(Ma->b) = E的时候,Nb · Tb = 0成立
    • 因此G = - t(Ma->b)
  • 也就是说,法线矩阵是顶点变换矩阵的逆转置矩阵!
  • 值得一提的是,当Ma->b为正交矩阵的时候,t(Ma->b) = - Ma->b,此时G = Ma->b
  • 注意:当Ma->b为等比缩放或旋转矩阵的时候,Ma->b为正交矩阵
  • 这也正是为什么非等比缩放矩阵变换法线会出现错误的结果,此时G != Ma->b,需要求Ma->b的逆转置矩阵才能得到G

2. 坐标点相减相加得到的向量方向怎么判断?

  • 首先弄清一个概念,点和向量的表示方法是一样的,所以点的加减结果可以是点也可以是向量,讨论表示向量的情况,设点a点b(画个图就好懂了):
    • a-b :把b看作(0,0,0) a看作(1,1,1),减后还是(1,1,1) 可知方向是b->a
    • a+b :把b看作(1,0,0) a看作(0,1,0),加后变成(1,1,0) 此三点与(0,0,0)围成平行四边形,向量方向就是从(0,0,0)出发的对角线方向

3. phong光照公式的向量方向总是搞错??

  • 漫反射部分:因为法向量的方向是固定的,为了得到正确的法向量与光照方向的夹角余弦值,光照方向要做出调整,因此其方向与现实相反
    图片说明
  • 高光部分:说到底还是因为法向量是固定的,glsl的reflect函数可以计算光照的反射向量,reflect函数计算的反射如图所示"↘↑↗",reflect传入的参数是"↘"(入射光向)与"↑"(反射轴即法向量),返回值是"↗"(反射方向)。因为参数"↑"的位置固定,为了返回值是"↗",所以"↘"是由一些处理得到的:由于前面计算漫反射的时候把光照方向反过来了("↖"),-"↖"="↘",以此来纠正光向。由于reflect计算出的"↗"是从片段指向外面,为了得到正确的反射方向与视角方向的夹角余弦值,视角方向也会与现实相反
    图片说明

4. imgui 1.60版本的坑

  • 本来想用imgui去显示相机的各种参数和调整材质,但使用imgui 1.60会使glfw的鼠标滚轮回调(glfwSetScrollCallback)失效,然后就会发现滚轮不能拉近相机,没怎么研究过imgui的源码,所以不太懂这个bug该怎么解决......

5. 法线矩阵必须与顶点变换矩阵同步

  • 法线矩阵可以通过两种方式计算出来:
    • 直接在着色器计算顶点变换矩阵的逆转置矩阵来得到法线矩阵,但GPU做这个运算开销有些大,在要求性能的情况下最好不要这么做。
    • 在OpenGL渲染循环中先算好法线矩阵,然后再传到着色器中,CPU比较适合做这个运算。
  • 如果用第二种方法计算法线矩阵的话,要注意,如果顶点变换矩阵发生改变,那么法线矩阵也需要跟着变,因为法线矩阵毕竟是由顶点变换矩阵得来的
全部评论

相关推荐

ResourceUtilization:四六级不愧是大学最有用的证之一
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务