使用OpenGL着色器扭曲图像

3
为了减轻我的艺术家的工作量,我正在为图像制作一个简单的骨骼动画系统。我已经构思了所有部分的工作方式。但是为了使它按照我的意愿进行动画处理,我需要能够实时扭曲图像。(如果我不能做到这一点,我仍然知道如何使其工作,但如果我能扭曲图像以增加透视效果,那将更美观)。
我使用SFML,但它不支持图像扭曲。有人告诉我需要在图像上使用OpenGL着色器,但我得到的所有建议都是“学习GLSL”。所以我想也许在这里有人可以帮我一下。
有人知道我应该从哪里开始吗?或者怎样做?
基本上,我想能够扭曲图像以赋予它透视效果(如下面的模拟图所示)
左边的图像在顶部和底部被扭曲。右边的图像在左侧和右侧被扭曲。

1
我对SFML不熟悉。但是,根据您所倾斜的对象,这可能非常容易。如果您需要渲染整个场景然后再倾斜,您将不得不学习如何渲染纹理。如果您只需要一些已经倾斜的股票纹理,则只需根据倾斜转换矩阵在着色器中调整纹理矩阵即可,有人在这里问了一个问题:https://dev59.com/WXRB5IYBdhLWcg3wSVYI。学习着色器,您应该在这里研究如何编写它们:http://www.lighthouse3d.com/tutorials/glsl-core-tutorial/。 - zero298
你不需要着色器来扭曲图像。渲染到纹理,然后定位即可。 - BЈовић
@BЈовић SFML 无法在三维空间中定位。因此,我不确定该怎么做。 - Legacyblade
SFML只是创建一个窗口。你需要在OpenGL中完成它。 - BЈовић
@BЈовић,你有什么推荐的教程吗?(是的,我也在谷歌上搜索,但我认为你比我更了解openGL,所以你会知道在哪里寻找更好的资源) - Legacyblade
显示剩余3条评论
2个回答

3
以下是如何在GLSL中扭曲纹理的示例(代码虽然不太优化)。理想情况下,您应该在常规程序中实际预先计算变换矩阵,并将其作为统一变量传递,以便您不需要在每次通过着色器时重新计算变换。如果您仍然想在着色器中计算变换,则将扭曲因子作为统一变量传入。否则,您必须打开着色器并在每次更改扭曲因子时进行编辑。
这是针对屏幕对齐的四边形的。
Vertex Shader:
attribute vec3 aVertexPosition;

varying vec2 texCoord;

void main(void){
   // Set regular texture coords
   texCoord = ((vec2(aVertexPosition.xy) + 1.0) / 2.0);

   // How much we want to skew each axis by
   float xSkew = 0.0;
   float ySkew = 0.0;

   // Create a transform that will skew our texture coords
   mat3 trans = mat3(
      1.0       , tan(xSkew), 0.0,
      tan(ySkew), 1.0,        0.0,
      0.0       , 0.0,        1.0
   );

   // Apply the transform to our tex coords
   texCoord = (trans * (vec3(texCoord.xy, 0.0))).xy;

   // Set vertex position
   gl_Position = (vec4(aVertexPosition, 1.0));
}

Frag

precision highp float;

uniform sampler2D sceneTexture;

varying vec2 texCoord;

void main(void){
   gl_FragColor = texture2D(sceneTexture, texCoord);
}

2

这个问题的解决比我想象的要简单得多。SFML有一个vertexArray类,允许绘制自定义四边形而无需使用openGL。

以下是我最终采用的代码(供其他遇到同样问题的人参考):

sf::Texture texture;
texture.loadFromFile("texture.png");
sf::Vector2u size = texture.getSize();

sf::VertexArray box(sf::Quads, 4);


box[0].position = sf::Vector2f(0, 0);      // top left corner position
box[1].position = sf::Vector2f(0, 100);    // bottom left corner position
box[2].position = sf::Vector2f(100, 100);  // bottom right corner position
box[3].position = sf::Vector2f(100, 100);  // top right corner position

box[0].texCoords = sf::Vector2f(0,0);
box[1].texCoords = sf::Vector2f(0,size.y-1);
box[2].texCoords = sf::Vector2f(size.x-1,size.y-1);
box[3].texCoords = sf::Vector2f(size.x-1,0);

要画它,您需要在通常绘制窗口内容的位置调用以下代码。
window.draw(lines,&texture);

如果你想倾斜图片,只需更改角落的位置即可。效果很好。有了这些信息,您应该能够创建自定义的可绘制类。您需要编写一些代码(例如 set_position、rotate、skew 等),但您只需要更改角落的位置并进行绘制。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接