OpenGL point sprites rotation in fragment shader

我是研究僧i 提交于 2019-12-03 04:44:31

The traditional method is to pass a matrix to the shader, whether vertex or fragment. If you don't know how to fill in a rotation matrix, Google and Wikipedia can help.

The main thing is that you're going to run into is the simple fact that a 2D rotation is not enough. gl_PointCoord goes from [0, 1]. A pure rotation matrix rotates around the origin, which is the bottom-left in point-coord space. So you need more than a pure rotation matrix.

You need a 3x3 matrix, which has part rotation and part translation. This matrix should be generated as follows (using GLM for math stuff):

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));

You then pass currMat to the shader as a 4x4 matrix. Your shader does this:

vec2 texCoord = (rotMatrix * vec4(gl_PointCoord, 0, 1)).xy
gl_FragColor = texture2D(texture, texCoord) * f_color;

I'll leave it as an exercise for you as to how to move the translation from the fourth column into the third, and how to pass it as a 3x3 matrix. Of course, in that case, you'll do vec3(gl_PointCoord, 1) for the matrix multiply.

I was stuck in the same problem too, but I found a tutorial that explain how to perform a 2d texture rotation in the same fragment shader with only with passing the rotate value (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;
}

Maybe this method is slow but is only to prove/show that you have an alternative to perform a texture 2D rotation inside fragment shader instead of passing a Matrix.

Note: vRotation should be in Radians.

Cheers,

You're right - a 2x2 rotation matrix will do what you want.

This page: http://www.cg.info.hiroshima-cu.ac.jp/~miyazaki/knowledge/teche31.html shows how to compute the elements. Note that you will be rotating the texture coordinates, not the vertex positions - the result will probably not be what you're expecting - it will rotate around the 0,0 texture coordinate, for example.

You may alse need to multiply the point_size by 2 and shrink the gl_PointCoord by 2 to ensure the whole texture fits into the point sprite when it's rotated. But do that as a second change. Note that a straight scale of texture coordinates move them towards the texture coordinate origin, not the middle of the sprite.

If you use a higher dimension matrix (3x3) then you will be able to combine the offset, scale and rotation into one operation.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!