GLES2: Get sin/cos out of vertex shader
authorAndreas Müller <schnitzeltony@gmail.com>
Tue, 28 Aug 2018 12:57:51 -0700
changeset 12156e5a666405750
parent 12155 751cdc74d55c
child 12158 ee7f3955c9fb
GLES2: Get sin/cos out of vertex shader
The only place angle is activated and causes effect is RenderCopyEx. All other
methods which use vertex shader, leave angle disabled and cause useless sin/cos
calculation in shader.

To get around shader's interface is changed to a vector that contains results
of sin and cos. To behave properly when disabled, cos value is set with offset
-1.0 making 0.0 default when deactivated.

As nice side effect it simplifies GLES2_UpdateVertexBuffer: All attributes are
vectors now.

Additional background:

* On RaspberryPi it gives a performace win for operations. Tested with
[1] numbers go down for 5-10% (not easy to estimate due to huge variation).
* SDL_RenderCopyEx was tested with [2]
* It works around left rotated display caused by low accuracy sin implemetation
in RaspberryPi/VC4 [3]

[1] https://github.com/schnitzeltony/sdl2box
[2] https://github.com/schnitzeltony/sdl2rendercopyex
[3] https://github.com/anholt/mesa/issues/110

Signed-off-by: Andreas Müller <schnitzeltony@gmail.com>
src/render/opengles2/SDL_render_gles2.c
src/render/opengles2/SDL_shaders_gles2.c
     1.1 --- a/src/render/opengles2/SDL_render_gles2.c	Mon Aug 27 11:51:05 2018 -0700
     1.2 +++ b/src/render/opengles2/SDL_render_gles2.c	Tue Aug 28 12:57:51 2018 -0700
     1.3 @@ -1534,7 +1534,7 @@
     1.4      GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
     1.5  
     1.6  #if !SDL_GLES2_USE_VBOS
     1.7 -    data->glVertexAttribPointer(attr, attr == GLES2_ATTRIBUTE_ANGLE ? 1 : 2, GL_FLOAT, GL_FALSE, 0, vertexData);
     1.8 +    data->glVertexAttribPointer(attr, 2, GL_FLOAT, GL_FALSE, 0, vertexData);
     1.9  #else
    1.10      if (!data->vertex_buffers[attr]) {
    1.11          data->glGenBuffers(1, &data->vertex_buffers[attr]);
    1.12 @@ -1549,7 +1549,7 @@
    1.13          data->glBufferSubData(GL_ARRAY_BUFFER, 0, dataSizeInBytes, vertexData);
    1.14      }
    1.15  
    1.16 -    data->glVertexAttribPointer(attr, attr == GLES2_ATTRIBUTE_ANGLE ? 1 : 2, GL_FLOAT, GL_FALSE, 0, 0);
    1.17 +    data->glVertexAttribPointer(attr, 2, GL_FLOAT, GL_FALSE, 0, 0);
    1.18  #endif
    1.19  
    1.20      return 0;
    1.21 @@ -1857,6 +1857,8 @@
    1.22      return GL_CheckError("", renderer);
    1.23  }
    1.24  
    1.25 +#define PI 3.14159265f
    1.26 +
    1.27  static int
    1.28  GLES2_RenderCopyEx(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *srcrect,
    1.29                   const SDL_FRect *dstrect, const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
    1.30 @@ -1865,8 +1867,9 @@
    1.31      GLfloat vertices[8];
    1.32      GLfloat texCoords[8];
    1.33      GLfloat translate[8];
    1.34 -    GLfloat fAngle[4];
    1.35 +    GLfloat fAngle[8];
    1.36      GLfloat tmp;
    1.37 +    float radian_angle;
    1.38  
    1.39      GLES2_ActivateRenderer(renderer);
    1.40  
    1.41 @@ -1876,7 +1879,11 @@
    1.42  
    1.43      data->glEnableVertexAttribArray(GLES2_ATTRIBUTE_CENTER);
    1.44      data->glEnableVertexAttribArray(GLES2_ATTRIBUTE_ANGLE);
    1.45 -    fAngle[0] = fAngle[1] = fAngle[2] = fAngle[3] = (GLfloat)(360.0f - angle);
    1.46 +
    1.47 +    radian_angle = PI * (360.0f - angle) / 180.f;
    1.48 +    fAngle[0] = fAngle[2] = fAngle[4] = fAngle[6] = (GLfloat)sin(radian_angle);
    1.49 +    /* render expects cos value - 1 (see GLES2_VertexSrc_Default_) */
    1.50 +    fAngle[1] = fAngle[3] = fAngle[5] = fAngle[7] = (GLfloat)cos(radian_angle) - 1.0f;
    1.51      /* Calculate the center of rotation */
    1.52      translate[0] = translate[2] = translate[4] = translate[6] = (center->x + dstrect->x);
    1.53      translate[1] = translate[3] = translate[5] = translate[7] = (center->y + dstrect->y);
    1.54 @@ -1905,7 +1912,7 @@
    1.55      data->glVertexAttribPointer(GLES2_ATTRIBUTE_CENTER, 2, GL_FLOAT, GL_FALSE, 0, translate);
    1.56      data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);*/
    1.57  
    1.58 -    GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_ANGLE, fAngle, 4 * sizeof(GLfloat));
    1.59 +    GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_ANGLE, fAngle, 8 * sizeof(GLfloat));
    1.60      GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_CENTER, translate, 8 * sizeof(GLfloat));
    1.61      GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_POSITION, vertices, 8 * sizeof(GLfloat));
    1.62  
     2.1 --- a/src/render/opengles2/SDL_shaders_gles2.c	Mon Aug 27 11:51:05 2018 -0700
     2.2 +++ b/src/render/opengles2/SDL_shaders_gles2.c	Tue Aug 28 12:57:51 2018 -0700
     2.3 @@ -30,20 +30,24 @@
     2.4  /*************************************************************************************************
     2.5   * Vertex/fragment shader source                                                                 *
     2.6   *************************************************************************************************/
     2.7 -
     2.8 +/* Notes on a_angle:
     2.9 +   * It is a vector containing sin and cos for rotation matrix
    2.10 +   * To get correct rotation for most cases when a_angle is disabled cos
    2.11 +     value is decremented by 1.0 to get proper output with 0.0 which is
    2.12 +     default value
    2.13 +*/
    2.14  static const Uint8 GLES2_VertexSrc_Default_[] = " \
    2.15      uniform mat4 u_projection; \
    2.16      attribute vec2 a_position; \
    2.17      attribute vec2 a_texCoord; \
    2.18 -    attribute float a_angle; \
    2.19 +    attribute vec2 a_angle; \
    2.20      attribute vec2 a_center; \
    2.21      varying vec2 v_texCoord; \
    2.22      \
    2.23      void main() \
    2.24      { \
    2.25 -        float angle = radians(a_angle); \
    2.26 -        float c = cos(angle); \
    2.27 -        float s = sin(angle); \
    2.28 +        float s = a_angle[0]; \
    2.29 +        float c = a_angle[1] + 1.0; \
    2.30          mat2 rotationMatrix = mat2(c, -s, s, c); \
    2.31          vec2 position = rotationMatrix * (a_position - a_center) + a_center; \
    2.32          v_texCoord = a_texCoord; \