Optimize DrawTexturePro and DrawRectanglePro transformations (#1632)

* Optimize DrawTexturePro and DrawRectanglePro transformations
- Add check so rotation is only applied if rotation != 0.0f.
- Replace matrix usage by calculating the vertex data directly.

* Fix error with windows build and trim whitespace
This commit is contained in:
Chris 2021-03-19 18:19:10 +00:00 committed by GitHub
parent 2f367a905e
commit 45670fbf2d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 113 additions and 55 deletions

View file

@ -119,11 +119,11 @@ void DrawLineEx(Vector2 startPos, Vector2 endPos, float thick, Color color)
Vector2 delta = {endPos.x-startPos.x, endPos.y-startPos.y}; Vector2 delta = {endPos.x-startPos.x, endPos.y-startPos.y};
float length = sqrtf(delta.x*delta.x + delta.y*delta.y); float length = sqrtf(delta.x*delta.x + delta.y*delta.y);
if (length > 0 && thick > 0) if (length > 0 && thick > 0)
{ {
float scale = thick/(2*length); float scale = thick/(2*length);
Vector2 radius = {-scale*delta.y, scale*delta.x}; Vector2 radius = {-scale*delta.y, scale*delta.x};
Vector2 strip[] = {{startPos.x-radius.x, startPos.y-radius.y}, {startPos.x+radius.x, startPos.y+radius.y}, Vector2 strip[] = {{startPos.x-radius.x, startPos.y-radius.y}, {startPos.x+radius.x, startPos.y+radius.y},
{endPos.x-radius.x, endPos.y-radius.y}, {endPos.x+radius.x, endPos.y+radius.y}}; {endPos.x-radius.x, endPos.y-radius.y}, {endPos.x+radius.x, endPos.y+radius.y}};
DrawTriangleStrip(strip, 4, color); DrawTriangleStrip(strip, 4, color);
@ -157,24 +157,24 @@ void DrawLineBezier(Vector2 startPos, Vector2 endPos, float thick, Color color)
void DrawLineBezierQuad(Vector2 startPos, Vector2 endPos, Vector2 controlPos, float thick, Color color) void DrawLineBezierQuad(Vector2 startPos, Vector2 endPos, Vector2 controlPos, float thick, Color color)
{ {
const float step = 1.0f/BEZIER_LINE_DIVISIONS; const float step = 1.0f/BEZIER_LINE_DIVISIONS;
Vector2 previous = startPos; Vector2 previous = startPos;
Vector2 current = { 0 }; Vector2 current = { 0 };
float t = 0.0f; float t = 0.0f;
for (int i = 0; i <= BEZIER_LINE_DIVISIONS; i++) for (int i = 0; i <= BEZIER_LINE_DIVISIONS; i++)
{ {
t = step*i; t = step*i;
float a = powf(1 - t, 2); float a = powf(1 - t, 2);
float b = 2*(1 - t)*t; float b = 2*(1 - t)*t;
float c = powf(t, 2); float c = powf(t, 2);
// NOTE: The easing functions aren't suitable here because they don't take a control point // NOTE: The easing functions aren't suitable here because they don't take a control point
current.y = a*startPos.y + b*controlPos.y + c*endPos.y; current.y = a*startPos.y + b*controlPos.y + c*endPos.y;
current.x = a*startPos.x + b*controlPos.x + c*endPos.x; current.x = a*startPos.x + b*controlPos.x + c*endPos.x;
DrawLineEx(previous,current,thick,color); DrawLineEx(previous,current,thick,color);
previous = current; previous = current;
} }
} }
@ -619,31 +619,60 @@ void DrawRectanglePro(Rectangle rec, Vector2 origin, float rotation, Color color
{ {
if (rlCheckBufferLimit(4)) rlglDraw(); if (rlCheckBufferLimit(4)) rlglDraw();
Vector2 bl = { 0 };
Vector2 br = { 0 };
Vector2 tr = { 0 };
Vector2 tl = { 0 };
// Only calculate rotation if needed
if (rotation == 0.0f)
{
float x = rec.x - origin.x;
float y = rec.y - origin.y;
bl = (Vector2){ x, y };
br = (Vector2){ x, y + rec.height };
tr = (Vector2){ x + rec.width, y + rec.height };
tl = (Vector2){ x + rec.width, y };
}
else
{
float sinRotation = sinf(rotation * DEG2RAD);
float cosRotation = cosf(rotation * DEG2RAD);
float x = rec.x;
float y = rec.y;
float dx = -origin.x;
float dy = -origin.y;
bl.x = x + dx * cosRotation - (dy + rec.height) * sinRotation;
bl.y = y + dx * sinRotation + (dy + rec.height) * cosRotation;
br.x = x + (dx + rec.width) * cosRotation - (dy + rec.height) * sinRotation;
br.y = y + (dx + rec.width) * sinRotation + (dy + rec.height) * cosRotation;
tr.x = x + (dx + rec.width) * cosRotation - dy * sinRotation;
tr.y = y + (dx + rec.width) * sinRotation + dy * cosRotation;
tl.x = x + dx * cosRotation - dy * sinRotation;
tl.y = y + dx * sinRotation + dy * cosRotation;
}
rlEnableTexture(GetShapesTexture().id); rlEnableTexture(GetShapesTexture().id);
rlBegin(RL_QUADS);
rlNormal3f(0.0f, 0.0f, 1.0f);
rlColor4ub(color.r, color.g, color.b, color.a);
rlPushMatrix(); rlTexCoord2f(GetShapesTextureRec().x/GetShapesTexture().width, GetShapesTextureRec().y/GetShapesTexture().height);
rlTranslatef(rec.x, rec.y, 0.0f); rlVertex2f(bl.x, bl.y);
rlRotatef(rotation, 0.0f, 0.0f, 1.0f);
rlTranslatef(-origin.x, -origin.y, 0.0f);
rlBegin(RL_QUADS); rlTexCoord2f(GetShapesTextureRec().x/GetShapesTexture().width, (GetShapesTextureRec().y + GetShapesTextureRec().height)/GetShapesTexture().height);
rlNormal3f(0.0f, 0.0f, 1.0f); rlVertex2f(br.x, br.y);
rlColor4ub(color.r, color.g, color.b, color.a);
rlTexCoord2f(GetShapesTextureRec().x/GetShapesTexture().width, GetShapesTextureRec().y/GetShapesTexture().height); rlTexCoord2f((GetShapesTextureRec().x + GetShapesTextureRec().width)/GetShapesTexture().width, (GetShapesTextureRec().y + GetShapesTextureRec().height)/GetShapesTexture().height);
rlVertex2f(0.0f, 0.0f); rlVertex2f(tr.x, tr.y);
rlTexCoord2f(GetShapesTextureRec().x/GetShapesTexture().width, (GetShapesTextureRec().y + GetShapesTextureRec().height)/GetShapesTexture().height);
rlVertex2f(0.0f, rec.height);
rlTexCoord2f((GetShapesTextureRec().x + GetShapesTextureRec().width)/GetShapesTexture().width, (GetShapesTextureRec().y + GetShapesTextureRec().height)/GetShapesTexture().height);
rlVertex2f(rec.width, rec.height);
rlTexCoord2f((GetShapesTextureRec().x + GetShapesTextureRec().width)/GetShapesTexture().width, GetShapesTextureRec().y/GetShapesTexture().height);
rlVertex2f(rec.width, 0.0f);
rlEnd();
rlPopMatrix();
rlTexCoord2f((GetShapesTextureRec().x + GetShapesTextureRec().width)/GetShapesTexture().width, GetShapesTextureRec().y/GetShapesTexture().height);
rlVertex2f(tl.x, tl.y);
rlEnd();
rlDisableTexture(); rlDisableTexture();
} }

View file

@ -3200,39 +3200,68 @@ void DrawTexturePro(Texture2D texture, Rectangle source, Rectangle dest, Vector2
if (source.width < 0) { flipX = true; source.width *= -1; } if (source.width < 0) { flipX = true; source.width *= -1; }
if (source.height < 0) source.y -= source.height; if (source.height < 0) source.y -= source.height;
Vector2 bl = { 0 };
Vector2 br = { 0 };
Vector2 tr = { 0 };
Vector2 tl = { 0 };
// Only calculate rotation if needed
if (rotation == 0.0f)
{
float x = dest.x - origin.x;
float y = dest.y - origin.y;
bl = (Vector2){ x, y };
br = (Vector2){ x, y + dest.height };
tr = (Vector2){ x + dest.width, y + dest.height };
tl = (Vector2){ x + dest.width, y };
}
else
{
float sinRotation = sinf(rotation * DEG2RAD);
float cosRotation = cosf(rotation * DEG2RAD);
float x = dest.x;
float y = dest.y;
float dx = -origin.x;
float dy = -origin.y;
bl.x = x + dx * cosRotation - (dy + dest.height) * sinRotation;
bl.y = y + dx * sinRotation + (dy + dest.height) * cosRotation;
br.x = x + (dx + dest.width) * cosRotation - (dy + dest.height) * sinRotation;
br.y = y + (dx + dest.width) * sinRotation + (dy + dest.height) * cosRotation;
tr.x = x + (dx + dest.width) * cosRotation - dy * sinRotation;
tr.y = y + (dx + dest.width) * sinRotation + dy * cosRotation;
tl.x = x + dx * cosRotation - dy * sinRotation;
tl.y = y + dx * sinRotation + dy * cosRotation;
}
rlEnableTexture(texture.id); rlEnableTexture(texture.id);
rlBegin(RL_QUADS);
rlColor4ub(tint.r, tint.g, tint.b, tint.a);
rlNormal3f(0.0f, 0.0f, 1.0f); // Normal vector pointing towards viewer
rlPushMatrix(); // Bottom-left corner for texture and quad
rlTranslatef(dest.x, dest.y, 0.0f); if (flipX) rlTexCoord2f((source.x + source.width)/width, source.y/height);
rlRotatef(rotation, 0.0f, 0.0f, 1.0f); else rlTexCoord2f(source.x/width, source.y/height);
rlTranslatef(-origin.x, -origin.y, 0.0f); rlVertex2f(bl.x, bl.y);
rlBegin(RL_QUADS); // Bottom-right corner for texture and quad
rlColor4ub(tint.r, tint.g, tint.b, tint.a); if (flipX) rlTexCoord2f((source.x + source.width)/width, (source.y + source.height)/height);
rlNormal3f(0.0f, 0.0f, 1.0f); // Normal vector pointing towards viewer else rlTexCoord2f(source.x/width, (source.y + source.height)/height);
rlVertex2f(br.x, br.y);
// Bottom-left corner for texture and quad // Top-right corner for texture and quad
if (flipX) rlTexCoord2f((source.x + source.width)/width, source.y/height); if (flipX) rlTexCoord2f(source.x/width, (source.y + source.height)/height);
else rlTexCoord2f(source.x/width, source.y/height); else rlTexCoord2f((source.x + source.width)/width, (source.y + source.height)/height);
rlVertex2f(0.0f, 0.0f); rlVertex2f(tr.x, tr.y);
// Bottom-right corner for texture and quad
if (flipX) rlTexCoord2f((source.x + source.width)/width, (source.y + source.height)/height);
else rlTexCoord2f(source.x/width, (source.y + source.height)/height);
rlVertex2f(0.0f, dest.height);
// Top-right corner for texture and quad
if (flipX) rlTexCoord2f(source.x/width, (source.y + source.height)/height);
else rlTexCoord2f((source.x + source.width)/width, (source.y + source.height)/height);
rlVertex2f(dest.width, dest.height);
// Top-left corner for texture and quad
if (flipX) rlTexCoord2f(source.x/width, source.y/height);
else rlTexCoord2f((source.x + source.width)/width, source.y/height);
rlVertex2f(dest.width, 0.0f);
rlEnd();
rlPopMatrix();
// Top-left corner for texture and quad
if (flipX) rlTexCoord2f(source.x/width, source.y/height);
else rlTexCoord2f((source.x + source.width)/width, source.y/height);
rlVertex2f(tl.x, tl.y);
rlEnd();
rlDisableTexture(); rlDisableTexture();
} }
} }