我正在尝试将平铺渲染从SDL2转换为OpenGL。这是来自SDL2的图像;
使用OpenGL渲染的相同图像没有纹理在Y轴上翻转;
这是来自OpenGL渲染的图像,纹理在Y轴上翻转;
我应该在哪里用Y翻转纹理补偿坐标并在OpenGL坐标系中正确渲染?这是我用来获取纹理uv以在OpenGL中渲染第二张图片(纹理未翻转)和第三张图片(翻转纹理)的代码;
glm::vec4 srcRect;
srcRect.x = (float)((tileLayer->GetTileId(x, y) - (tileY * tilesPerRow))* (tileWidth+ spacing) )/imageWidth;
srcRect.y = (float)(tileY * (tileHeight + spacing)+ margin)/imageHeight;
srcRect.z = (float)tileWidth/imageWidth;
srcRect.w = (float)tileHeight/imageHeight ;
答案 0 :(得分:0)
如果我没有正确理解问题,请忽略这篇文章。如果我正确地理解了问题,而不是在工作代码中调整现成的图形和计算,我会改变OpenGL透视转换以匹配SDL。 OpenGL对坐标系没有任何偏好,因此您可以自由调整它以适合您的目的。
我假设你使用的是现代OpenGL(可编程着色器,没有固定管道)和一些OpenGL数学库(例如glm for C ++)。大多数库都有ortho()来创建具有坐标变换的正交透视图。语法是:
glm::ortho(left, right, bottom, top, near, far)
只需翻转底部和顶部,就可以翻转y。对于2D图形,近场和远场可以是任意点,因为对象的z坐标都为零:
glm::ortho(
-1, 1, // X goes -1 to 1
1, -1, // Y goes 1 (at bottom!) to -1 (at top!)
-1, 1) // -1 < 0 < 1
但你可以变得更好。使用窗口大小参数,您可以使用常规的基于像素的坐标(而不是-1 ... 1范围):
glm::ortho(
0, width, // X goes 0 to width
height, 0, // Y goes 0 (top) to height (bottom)
-1, 1) // near & far
要使用固定管道(旧OpenGL)制作它,请使用glOrtho()。
希望这是问题,如果是,希望这会有所帮助。
编辑:以防万一...你可以更加调整透视转换,以适应更好的基于平铺的2D游戏。让我们说你的对象的“单位大小”就像是32x32(精灵,背景瓷砖等)。摆脱sprite width&amp;的乘法和除法。 length(将地图数组索引转换为屏幕坐标,反之亦然),只需将坐标“单位大小”与切片大小匹配:
glm::ortho(
0, width / tile.width, // +1 X is +tile.width
height / tile.height, 0, // +1 Y is +tile.height
-1, 1) // near & far
编辑(参见注释):让我们假设您使用ortho(0,width,height,0)来获得“传统”屏幕坐标(以像素为单位)。要将32x32位图blit到窗口,您可以使用以下两个三角形构建的跟随矩形:
uv (0, 0) uv( 1, 0)
pos(0, 0) pos(32, 0)
+-----------------+
|A D|
| |
|B C|
+-----------------+
pos(0,32) pos(32, 32)
uv (0, 1) uv ( 1, 1)
默认绕组是逆时针方向(三角形ABC,CDA)。使用矩形(-16,-16) - (16,16),“参考”点也可以更改为居中。此外:您可以使用“unitbox”(0,0) - (1,1)或(-0.5,-05) - (0.5,0.5),并使用传递给着色器的模型矩阵将其缩放到正确的尺寸。这使您可以轻松地使用相同的框来以任何尺寸进行blit纹理。
如果你不喜欢改变透视,你也可以通过将你使用的矩形翻转为“倒置”来进行翻转,并将位置缩小到32 /宽度和32 /高度(例如在模型矩阵中) 。这会影响缠绕,因此您可能需要调整面部剔除参数(glCullFace,glFrontFace,glPolygonMode)。
但IMO对于2D图形调整透视并继续使用您以前使用的“默认”窗口坐标更为方便。 3D方是不同的野兽。