我正在关注this tutorial以了解更多关于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吗?
答案 0 :(得分:8)
传统的方法是将矩阵传递给着色器,无论是顶点还是片段。如果您不知道如何填写轮换矩阵,Google和Wikipedia可以提供帮助。
主要的是你要碰到的是一个简单的事实,即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)
做。{/ p>
答案 1 :(得分:2)
我也遇到了同样的问题,但是我找到了一个教程,解释了如何在同一片段着色器中执行2d纹理旋转,只传递旋转值( vRotation )。 / p>
#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应该是Radians。
干杯,
答案 2 :(得分:1)
你是对的 - 一个2x2旋转矩阵可以做你想要的。
此页面:http://www.cg.info.hiroshima-cu.ac.jp/~miyazaki/knowledge/teche31.html显示了如何计算元素。请注意,您将旋转纹理坐标,而不是顶点位置 - 结果可能不是您所期望的 - 例如,它将围绕0,0纹理坐标旋转。
您可能还需要将point_size乘以2并将gl_PointCoord缩小2以确保整个纹理在旋转时适合点精灵。但这样做是第二次改变。请注意,纹理坐标的直线比例将它们移向纹理坐标原点,而不是精灵的中间。
如果使用更高维矩阵(3x3),则可以将偏移,缩放和旋转组合到一个操作中。