OpenGL点精灵在片段着色器中旋转
OpenGL point sprites rotation in fragment shader
我将按照本教程学习更多关于OpenGL的知识,尤其是点精灵。但我被困在了页面末尾的一个练习上:
尝试通过更改片段着色器将点精灵旋转45度。
这一章和前几章都没有关于这类事情的暗示。我没有找到任何关于如何做到这一点的文档。这些是我的顶点和碎片着色器:
顶点着色器
#version 140
attribute vec2 coord2d;
varying vec4 f_color;
uniform float offset_x;
uniform float scale_x;
uniform float point_size;
void main(void) {
gl_Position = vec4((coord2d.x + offset_x) * scale_x, coord2d.y, 0.0, 1.0);
f_color = vec4(coord2d.xy / 2.0 + 0.5, 1.0, 1.0);
gl_PointSize = point_size;
}
片段着色器
#version 140
varying vec4 f_color;
uniform sampler2D texture;
void main(void) {
gl_FragColor = texture2D(texture, gl_PointCoord) * f_color;
}
我曾想过在FS中使用2x2矩阵来旋转gl_PointCoord
,但我不知道如何填充矩阵来完成它。我应该将其作为统一传递给FS吗?
传统方法是将矩阵传递给着色器,无论是顶点还是片段。如果你不知道如何填写轮换矩阵,谷歌和维基百科可以提供帮助。
最重要的是,你将遇到一个简单的事实,即2D旋转是不够的。gl_PointCoord
从[0,1]开始。纯旋转矩阵绕原点旋转,原点是点坐标空间的左下角。所以你需要的不仅仅是一个纯旋转矩阵。
你需要一个3x3矩阵,它有部分旋转和部分平移。这个矩阵应该如下生成(使用GLM进行数学运算):
glm::mat4 currMat(1.0f);
currMat = glm::translate(currMat, glm::vec3(0.5f, 0.5f, 0.0f));
currMat = glm::rotate(currMat, angle, glm::vec3(0.0f, 0.0f, 1.0f));
currMat = glm::translate(currMat, glm::vec3(-0.5f, -0.5f, 0.0f));
然后将currMat
作为4x4矩阵传递给着色器。您的着色器执行以下操作:
vec2 texCoord = (rotMatrix * vec4(gl_PointCoord, 0, 1)).xy
gl_FragColor = texture2D(texture, texCoord) * f_color;
我将把它留给你一个练习,学习如何将翻译从第四列移到第三列,以及如何将其作为3x3矩阵传递。当然,在这种情况下,您将对矩阵乘法执行vec3(gl_PointCoord, 1)
。
我也遇到了同样的问题,但我找到了一个教程,解释了如何在相同的片段着色器中执行2d纹理旋转,只需传递旋转值(vRotation)。
#version 130
uniform sampler2D tex;
varying float vRotation;
void main(void)
{
float mid = 0.5;
vec2 rotated = vec2(cos(vRotation) * (gl_PointCoord.x - mid) + sin(vRotation) * (gl_PointCoord.y - mid) + mid,
cos(vRotation) * (gl_PointCoord.y - mid) - sin(vRotation) * (gl_PointCoord.x - mid) + mid);
vec4 rotatedTexture=texture2D(tex, rotated);
gl_FragColor = gl_Color * rotatedTexture;
}
也许这种方法很慢,但只是为了证明/表明您可以在片段着色器内执行纹理2D旋转,而不是传递矩阵。
注:vRotation应以弧度为单位。
干杯,
你是对的,2x2旋转矩阵可以满足你的需要。
本页:http://www.cg.info.hiroshima-cu.ac.jp/~miyazaki/nknowledge/teche31.html展示了如何计算元素。请注意,您将旋转纹理坐标,而不是顶点位置-结果可能不是您所期望的-例如,它将围绕0,0纹理坐标旋转。
您可能还需要将point_size乘以2,并将gl_PointCoord缩小2,以确保旋转时整个纹理适合点精灵。但这是第二次改变。请注意,纹理坐标的直比例会将它们移向纹理坐标原点,而不是精灵的中间。
如果使用更高维度的矩阵(3x3),则可以将偏移、缩放和旋转组合为一个操作。
- 与互斥锁相比,旋转锁可以保证上下文切换
- 绘制旋转的三角形
- 旋转模型矩阵时的形状失真
- 四边形的 2D 旋转
- 垂直方向的 Gtk3+ 旋转按钮 (c/c++)
- 发布旋转矩阵(openGL/glm)
- 顺时针迭代旋转 3 位数字
- 这个带有模板<类 Vector 的C++代码片段有什么问题>
- Opengl 3.1 GLSL 140 在 C++ 年输出白色在片段着色器中
- 形状对象的旋转和缩放不正确C++
- 如何在 OpenSceneGraph 中缩放/旋转/移动资产
- 如何有效地计算将单位立方体映射到自身的反射和旋转?
- 子轴围绕父轴而不是他自己的轴旋转
- 将使用太多的纹理插值器 - 带旋转的着色器
- 这两个代码片段相似,但显示的结果不同
- 如何替换此示例代码片段中已弃用的handler_type_t或 boost::asio::handler_type?
- SFML 向下移动时如何围绕屏幕中心旋转?
- 如何在OpenGL中正确旋转和缩放对象?
- 使用 C++在 OpenGL 中移动自动旋转的 3D 多边形
- OpenGL点精灵在片段着色器中旋转