渲染时如何使 SDL2 0,0 定位在窗口的中心?

Posted

技术标签:

【中文标题】渲染时如何使 SDL2 0,0 定位在窗口的中心?【英文标题】:How to make SDL2 0,0 position the center of the window when rendering? 【发布时间】:2020-04-18 15:26:57 【问题描述】:

我们正在“移植/更新”一个使用 SDL 进行渲染的旧项目,并且我们正在更改代码以使用矩阵变换等。

主要问题是 SDL 坐标系在左上角 (0,0),我们希望它是窗口的中心。

我们正在使用它来渲染:

const auto modelMatrix = (Matrix3::translation(tr.position) * Matrix3::rotation(Magnum::Deg(tr.rotation))) * Matrix3::scaling(tr.scale);
const auto mvpMatrix = viewProjectionMatrix * modelMatrix;

SDL_SetRenderDrawColor(renderer, 0xFF, 0x0, 0x0, 0xFF);
Magnum::Vector2i winSize;
SDL_GetWindowSize(window, &winSize.x(), &winSize.y());
SDL_RenderDrawPointF(renderer, mvpMatrix.translation().x() + (winSize.x() /2), mvpMatrix.translation().y() + (winSize.y() /2));

这是我们尝试过并且似乎“有效”的方法,因为当我们在 mvpMatrix.translation() 中获得正确的世界位置时,我们会使用 (winSize / 2) 来抵消它,让 SDL 将其渲染到屏幕的中心.

我们对这个解决方案不满意,我们不确定它是否适用于所有场景。还有另一种方法可以使它起作用吗?修改投影矩阵?

【问题讨论】:

【参考方案1】:

我们结束了这个转换:

(重要提示:我们在这里也反转了 Y 轴)!

Magnum::Vector2 convertHomogenousCoordsToSDL(SDL_Window* window, const Matrix3& MVP, Magnum::Vector2 vertex) 

  // get vertex in homogenous coords
  vertex = MVP.transformPoint(vertex);

  // now convert from homogenous coords 0,0 center and y-axis up to SDL screen coords 
  Vector2i winSize;
  SDL_GetWindowSize(window, &winSize.x(), &winSize.y());
  auto winSizeHalf = Vector2(winSize) / 2.f;
  auto matrixChangeCoords = Matrix3::translation(winSizeHalf) * Matrix3::scaling( winSizeHalf.x(), -winSizeHalf.y() );
  vertex = matrixChangeCoords.transformPoint(vertex);
  return vertex;

现在我们可以像这样将空间中的任何点转换为 SDL 窗口空间:

const auto modelMatrix = (Matrix3::translation(tr.position) * Matrix3::rotation(Magnum::Deg(tr.rotation))) * Matrix3::scaling(tr.scale);
const auto mvpMatrix = viewProjectionMatrix * modelMatrix;

SDL_SetRenderDrawColor(renderer, 0xFF, 0x0, 0x0, 0xFF);
const auto vertexPosition = helpers::convertHomogenousCoordsToSDL(window, mvpMatrix,  0,0 );
SDL_RenderDrawPointF(renderer, vertexPosition.x(), vertexPosition.y());

我不会接受这个答案,看看这里是否可以改进!

(编辑) 封装它并像@keltar在cmets中所说的那样在ProjectionMatrix中设置转换

Magnum::Vector2i framebufferSize(SDL_Window* window) 
    Vector2i winSize;
    SDL_GetWindowSize(window, &winSize.x(), &winSize.y());
    return winSize;


Magnum::Matrix3 projectionMatrixToSDLSpace(SDL_Window* window, const Vector2& cameraSize) 
    const Vector2 winSizeHalf = Vector2(framebufferSize(window)) / 2.f;
    return Matrix3::translation(winSizeHalf) * Matrix3::scaling( winSizeHalf.x(), -winSizeHalf.y() ) * Magnum::Matrix3::projection(cameraSize);

【讨论】:

这种转换只有一个正确的公式,所以这里没有错。但是您不必为每个点应用额外的变换或生成矩阵 - 只需将此 matrixChangeCoords 乘以一次投影矩阵,即可免费获得该变换。 谢谢@keltar 我在答案中添加了您的建议。

以上是关于渲染时如何使 SDL2 0,0 定位在窗口的中心?的主要内容,如果未能解决你的问题,请参考以下文章

C ++ SDL2:如何将矩形渲染到多个视口中

带有 OpenGL 4.4 的 SDL2:三角形未正确渲染

SDL2纹理渲染

SDL2/表面/纹理/渲染

sdl2 opengl d3d9的mipmap和各项异性过滤渲染

重新渲染 HTML 元素定位在 Javascript 幻灯片动画内的窗口调整大小