Skip to content

Commit

Permalink
GLES2: Get sin/cos out of vertex shader
Browse files Browse the repository at this point in the history
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] anholt/mesa#110

Signed-off-by: Andreas M?ller <schnitzeltony@gmail.com>
  • Loading branch information
schnitzeltony committed Aug 28, 2018
1 parent 044b00d commit 87bc1fb
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 10 deletions.
17 changes: 12 additions & 5 deletions src/render/opengles2/SDL_render_gles2.c
Expand Up @@ -1534,7 +1534,7 @@ GLES2_UpdateVertexBuffer(SDL_Renderer *renderer, GLES2_Attribute attr,
GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;

#if !SDL_GLES2_USE_VBOS
data->glVertexAttribPointer(attr, attr == GLES2_ATTRIBUTE_ANGLE ? 1 : 2, GL_FLOAT, GL_FALSE, 0, vertexData);
data->glVertexAttribPointer(attr, 2, GL_FLOAT, GL_FALSE, 0, vertexData);
#else
if (!data->vertex_buffers[attr]) {
data->glGenBuffers(1, &data->vertex_buffers[attr]);
Expand All @@ -1549,7 +1549,7 @@ GLES2_UpdateVertexBuffer(SDL_Renderer *renderer, GLES2_Attribute attr,
data->glBufferSubData(GL_ARRAY_BUFFER, 0, dataSizeInBytes, vertexData);
}

data->glVertexAttribPointer(attr, attr == GLES2_ATTRIBUTE_ANGLE ? 1 : 2, GL_FLOAT, GL_FALSE, 0, 0);
data->glVertexAttribPointer(attr, 2, GL_FLOAT, GL_FALSE, 0, 0);
#endif

return 0;
Expand Down Expand Up @@ -1857,6 +1857,8 @@ GLES2_RenderCopy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *s
return GL_CheckError("", renderer);
}

#define PI 3.14159265f

static int
GLES2_RenderCopyEx(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *srcrect,
const SDL_FRect *dstrect, const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
Expand All @@ -1865,8 +1867,9 @@ GLES2_RenderCopyEx(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect
GLfloat vertices[8];
GLfloat texCoords[8];
GLfloat translate[8];
GLfloat fAngle[4];
GLfloat fAngle[8];
GLfloat tmp;
float radian_angle;

GLES2_ActivateRenderer(renderer);

Expand All @@ -1876,7 +1879,11 @@ GLES2_RenderCopyEx(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect

data->glEnableVertexAttribArray(GLES2_ATTRIBUTE_CENTER);
data->glEnableVertexAttribArray(GLES2_ATTRIBUTE_ANGLE);
fAngle[0] = fAngle[1] = fAngle[2] = fAngle[3] = (GLfloat)(360.0f - angle);

radian_angle = PI * (360.0f - angle) / 180.f;
fAngle[0] = fAngle[2] = fAngle[4] = fAngle[6] = (GLfloat)sin(radian_angle);
/* render expects cos value - 1 (see GLES2_VertexSrc_Default_) */
fAngle[1] = fAngle[3] = fAngle[5] = fAngle[7] = (GLfloat)cos(radian_angle) - 1.0f;
/* Calculate the center of rotation */
translate[0] = translate[2] = translate[4] = translate[6] = (center->x + dstrect->x);
translate[1] = translate[3] = translate[5] = translate[7] = (center->y + dstrect->y);
Expand Down Expand Up @@ -1905,7 +1912,7 @@ GLES2_RenderCopyEx(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect
data->glVertexAttribPointer(GLES2_ATTRIBUTE_CENTER, 2, GL_FLOAT, GL_FALSE, 0, translate);
data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);*/

GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_ANGLE, fAngle, 4 * sizeof(GLfloat));
GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_ANGLE, fAngle, 8 * sizeof(GLfloat));
GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_CENTER, translate, 8 * sizeof(GLfloat));
GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_POSITION, vertices, 8 * sizeof(GLfloat));

Expand Down
14 changes: 9 additions & 5 deletions src/render/opengles2/SDL_shaders_gles2.c
Expand Up @@ -30,20 +30,24 @@
/*************************************************************************************************
* Vertex/fragment shader source *
*************************************************************************************************/

/* Notes on a_angle:
* It is a vector containing sin and cos for rotation matrix
* To get correct rotation for most cases when a_angle is disabled cos
value is decremented by 1.0 to get proper output with 0.0 which is
default value
*/
static const Uint8 GLES2_VertexSrc_Default_[] = " \
uniform mat4 u_projection; \
attribute vec2 a_position; \
attribute vec2 a_texCoord; \
attribute float a_angle; \
attribute vec2 a_angle; \
attribute vec2 a_center; \
varying vec2 v_texCoord; \
\
void main() \
{ \
float angle = radians(a_angle); \
float c = cos(angle); \
float s = sin(angle); \
float s = a_angle[0]; \
float c = a_angle[1] + 1.0; \
mat2 rotationMatrix = mat2(c, -s, s, c); \
vec2 position = rotationMatrix * (a_position - a_center) + a_center; \
v_texCoord = a_texCoord; \
Expand Down

0 comments on commit 87bc1fb

Please sign in to comment.