Shader中的光照计算空间以及参数坐标转换问题

与坐标空间有关的一些光照计算参数

  1. 顶点位置(Vertex Position):顶点在世界空间或视图空间中的位置。

  2. 法线向量(Normal Vector):顶点表面的法线向量,表示表面的方向。通常需要归一化。

  3. 光源位置(Light Position):光源在空间中的位置,可以是世界空间坐标或视图空间坐标。

  4. 光线向量(Light Vector):一个表示从顶点位置指向光源方向的向量,其长度表示顶点到光源的距离。

  5. 视线向量(View Vector):从顶点指向观察者(相机)的方向,用于计算光照效果,如镜面反射。

光照计算的坐标空间

在3D图形渲染中,光照计算可以在不同的坐标系中进行,这些坐标系包括模型空间(Model Space)、世界空间(World Space)、视图空间(View Space,也称为相机空间 Camera Space)、裁剪空间(Clip Space)以及屏幕空间(Screen Space)。选择在哪个坐标系中进行光照计算取决于具体的渲染需求和性能考虑:

  1. 模型空间(Model Space)

    • 在这个坐标系中,每个模型都有自己的原点,通常用于定义模型的局部变换,如旋转、缩放和局部平移。
    • 光照计算在模型空间中进行时,光源和物体的位置都是相对于模型的局部坐标系。通常涉及到模型的局部属性,例如局部光源或模型内部的光照效果。
  2. 世界空间(World Space)

    1. 世界空间是一个全局坐标系,所有模型和光源的位置都是相对于这个坐标系定义的。
    2. 在世界空间中进行光照计算时,光源和物体的位置是相对于场景的全局坐标系,这有助于处理场景中的全局光照效果。
  3. 视图空间(View Space / Camera Space)

    • 视图空间是以相机为中心的坐标系,相机的位置是原点,通常用于计算从物体表面指向相机的方向(视向量)。
    • 在视图空间中进行光照计算可以简化计算,因为可以直接使用相机的位置和方向来计算光照,这在实时渲染中非常常见。
  4. 裁剪空间(Clip Space)

    • 裁剪空间是经过透视除法后的坐标系,用于最终的光栅化阶段。在这个阶段,顶点的位置被裁剪到视锥体(Frustum)内。
    • 光照计算通常不会在裁剪空间中直接进行,因为这个阶段更多地关注于几何变换和屏幕坐标的转换,但某些高级光照技术(如阴影映射)可能会使用裁剪空间中的坐标。
  5. 屏幕空间(Screen Space)

    • 屏幕空间是最终渲染到屏幕上的坐标系。
    • 在屏幕空间中进行光照计算通常涉及到后处理效果,如屏幕空间环境光遮蔽(Screen Space Ambient Occlusion, SSAO)、屏幕空间反射(Screen Space Reflections, SSR)等。

在实际的图形渲染管线中,光照计算通常在世界空间或视图空间中进行。

通常会在顶点着色器中将光照计算参数转换到模型空间或视图空间,然后在片段着色器中进行光照计算。

例如,直接光照(如点光源、聚光灯和平行光)通常在视图空间中计算,因为这样可以利用相机的视图矩阵来简化计算。

而间接光照(如环境光遮蔽 Ambient Occlusion)可能会在世界空间中计算,因为它们涉及到场景的全局属性。


光照计算的世界空间和视图空间提供了不同的视角、便利性和优势:

  1. 世界空间(World Space)

    • 全局性:世界空间提供了一个全局的坐标系统,所有对象的位置都是相对于这个坐标系定义的。这使得光源的位置可以独立于相机和观察者的位置。
    • 静态场景:在静态场景中,物体和光源的位置通常是固定的,因此在世界空间中计算光照可以简化问题,因为不需要考虑相机的视图变换。
    • 光照贴图(Lightmaps):在一些离线渲染或预渲染技术中,光照信息(如光照贴图)是在世界空间中预先计算的,这样可以在运行时快速应用光照效果。
  2. 视图空间(View Space)

    • 相机中心:视图空间是以相机为中心的坐标系统,其中相机的位置是原点。这种空间使得计算从物体表面指向相机的方向(视向量)变得简单,因为相机总是位于原点。
    • 性能优化:在视图空间中计算光照可以减少计算量,因为不需要为每个顶点单独计算世界空间中的光源位置。这在实时渲染中尤其重要,因为它可以提高渲染效率。
    • 阴影和光照一致性:在视图空间中计算光照可以确保阴影和光照效果与相机的视图一致。这对于实现逼真的渲染效果非常重要。

在实际的图形应用程序中,开发者会根据具体的需求和性能考虑来选择在哪种空间中进行光照计算。例如,在实时渲染的游戏中,通常会在视图空间中计算光照,以提高性能。而在离线渲染或某些特定的视觉效果中,可能会选择在世界空间中进行光照计算。

在OpenGL和其他图形API中,通常会提供矩阵变换功能,允许开发者在这两种空间之间转换坐标,以便在不同的渲染阶段使用最合适的计算方法。

Shader中的参数坐标转换

世界空间

	gl_Position = ubo.projection * ubo.model * vec4(inPos.xyz, 1.0);

    vec4 pos = ubo.model * vec4(inPos, 1.0);
	outNormal = mat3(inverse(transpose(ubo.model))) * inNormal;
	vec3 lightPos = vec3(0.0);
	vec3 lPos = mat3(ubo.model) * lightPos.xyz;
    outLightVec = lPos - pos.xyz;
    outViewVec = ubo.viewPos.xyz - pos.xyz;		

光线向量及视线向量都使用世界空间的顶点、光源、视点位置进行计算。

法线的模型空间到世界空间的坐标变换,可以学习参考这篇:法线坐标变换

视图空间

	gl_Position = ubo.projection * ubo.view * ubo.model * inPos;

	vec3 lightPos = vec3(-5.0, -5.0, 0.0);
	vec4 pos = ubo.view * ubo.model * inPos;
	outNormal = mat3(ubo.view * ubo.model) * inNormal;
	outLightVec = lightPos - pos.xyz;
	outViewVec = -pos.xyz;	

光线向量及视线向量使用视图空间的顶点位置进行计算。

法线需要转换到视图空间。


这里,视点位置在原点,光源位置在世界坐标系中,没有转换到视图空间。

  • 在视图空间中,光源位置实际上是相对于相机的,因为相机的位置在视图矩阵中被隐含地表示为原点。所以,即使光源位置是在世界空间中定义的,它在视图空间中的位置也是固定的,可以直接用来计算光线向量。
  • 当相机移动时,光源在世界空间中的位置仍然是固定的。在这种情况下,你可以继续使用世界空间中的光源位置来计算光照向量。视图矩阵(ubo.view)需要更新以反映相机的新位置和方向。这样,顶点位置(pos)在视图空间中的表示也会相应地更新,确保了从顶点到光源的方向计算是准确的。
  • 如果光源是动态的,你需要在渲染循环中更新lightPos变量。在计算光照向量时,你需要确保光源位置和顶点位置都在相同的坐标系中。如果光源位置在世界空间中给出,而顶点位置在视图空间中,那么你需要将光源位置转换到视图空间,或者将顶点位置转换到世界空间,以确保两者在同一坐标系中进行计算。
  • 在大多数情况下,如果光源是动态的,你可能会希望在世界空间中处理光源位置,因为这样可以更容易地管理和更新光源的位置。
  • 在多视口渲染(Multiview Rendering)的情况下,如果你的应用程序支持多个视口,每个视口可能有自己的视图矩阵。在这种情况下,你需要为每个视口分别计算光照向量,确保每个视口的光照效果都是正确的。
  • 24
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值