OpenGL point sprites rotation in fragment shader

前端 未结 3 1550
感动是毒
感动是毒 2021-02-04 20:17

I\'m following this tutorial to learn something more about OpenGL and in particular point sprites. But I\'m stuck on one of the exercises at the end of the page:

相关标签:
3条回答
  • 2021-02-04 20:51

    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,

    0 讨论(0)
  • 2021-02-04 20:54

    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.

    0 讨论(0)
  • 2021-02-04 20:56

    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.

    0 讨论(0)
提交回复
热议问题