@TOC
先叨叨
我在开发的时候发现画出来的图形跟我指定的坐标不一致,在Y轴上是反的。
按照OpenGL的经验,图形采用右手坐标:X轴正方向向右,Y轴正方向向上,Z轴正方向向外。
因此我按照下图的坐标设置了三个点, 描画三角形。
但是画出的图形却不是我期望的。
在调查了原因之后,我觉得有必要向大家介绍一下Vulkan的坐标系统。
归一化的设备坐标系
归一化的设备坐标系(normalized device coordinates, 缩写为NDC), NDC就是我们给Vulkan输入顶点的坐标系。
在Vulkan中NDC与OpenGL基本一致,采用右手坐标系。X轴正方向向右,Y轴正方向向上,Z轴正方向向外。X和Y轴的范围都是[-1.0f, 1.0f]. 但Z轴的坐标范围为[0.0f, 1.0f];
视口坐标系
视口坐标系,是指最终渲染图像的坐标系。
Vulkan的视口坐标系跟OpenGL或其他窗口系统坐标系有所不同。一般的窗口系统(Qt、MFC、SDL、Wayland等)的视口坐标都是以左上角为原点,X轴正方向向右,Y轴正方向向下。
但Vulkan的视口坐标是以左下角为原点,X轴正方向向右,Y轴正方向向上。
归一化坐标与视口坐标结合
综上,Vulkan的坐标系统如下:
Vulkan在向Framebuffer中渲染时是从视口的原点开始渲染,因此Framebuffer中的第一行是视口坐标最底层(Y=0)的像素信息,Framebuffer中的最后一行是视口坐标最顶层(Y = 视口高度)的像素信息。
当我们将Framebuffer交给窗口描画时,窗口按照窗口坐标,从Framebuffer第一行从上到下显示,因此导致Y轴的图像看起来是反过来的。
因此我们将Framebuffer交给窗口系统之前,需要调转一下Framebuffer每行的内存位置。
解决问题
SDL有一个方法SDL_RenderTextureRotated
可以将Framebuffer的Y轴进行反转,因此我们用它代替SDL_RenderTexture
便可以解决Y轴反转的问题。
if (!SDL_RenderTextureRotated(renderer, texture, nullptr, nullptr, 0, NULL, SDL_FLIP_VERTICAL)){SDL_Log("Couldn't render texture: %s", SDL_GetError());return SDL_APP_FAILURE;}// if (!SDL_RenderTexture(renderer, texture, nullptr, nullptr))// {// SDL_Log("Couldn't render texture: %s", SDL_GetError());// return SDL_APP_FAILURE;// }