Last active
March 23, 2021 13:22
-
-
Save chrisdill/7c174db8d82859db471b140f43fc510c to your computer and use it in GitHub Desktop.
DrawTexturePro and DrawRectanglePro optimizations
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Updated with bug fixes etc | |
// Draw a part of a texture (defined by a rectangle) with 'pro' parameters | |
// NOTE: origin is relative to destination rectangle size | |
void DrawTexturePro(Texture2D texture, Rectangle source, Rectangle dest, Vector2 origin, float rotation, Color tint) | |
{ | |
// Check if texture is valid | |
if (texture.id > 0) | |
{ | |
float width = (float)texture.width; | |
float height = (float)texture.height; | |
bool flipX = false; | |
if (source.width < 0) { flipX = true; source.width *= -1; } | |
if (source.height < 0) source.y -= source.height; | |
Vector2 topLeft = { 0 }; | |
Vector2 topRight = { 0 }; | |
Vector2 bottomLeft = { 0 }; | |
Vector2 bottomRight = { 0 }; | |
// Only calculate rotation if needed | |
if (rotation == 0.0f) | |
{ | |
float x = dest.x - origin.x; | |
float y = dest.y - origin.y; | |
topLeft = (Vector2){ x, y }; | |
topRight = (Vector2){ x + dest.width, y }; | |
bottomLeft = (Vector2){ x, y + dest.height }; | |
bottomRight = (Vector2){ x + dest.width, y + dest.height }; | |
} | |
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; | |
topLeft.x = x + dx*cosRotation - dy*sinRotation; | |
topLeft.y = y + dx*sinRotation + dy*cosRotation; | |
topRight.x = x + (dx + dest.width)*cosRotation - dy*sinRotation; | |
topRight.y = y + (dx + dest.width)*sinRotation + dy*cosRotation; | |
bottomLeft.x = x + dx*cosRotation - (dy + dest.height)*sinRotation; | |
bottomLeft.y = y + dx*sinRotation + (dy + dest.height)*cosRotation; | |
bottomRight.x = x + (dx + dest.width)*cosRotation - (dy + dest.height)*sinRotation; | |
bottomRight.y = y + (dx + dest.width)*sinRotation + (dy + dest.height)*cosRotation; | |
} | |
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 | |
// Top-left corner for texture and quad | |
if (flipX) rlTexCoord2f((source.x + source.width)/width, source.y/height); | |
else rlTexCoord2f(source.x/width, source.y/height); | |
rlVertex2f(topLeft.x, topLeft.y); | |
// Bottom-left 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(bottomLeft.x, bottomLeft.y); | |
// Bottom-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(bottomRight.x, bottomRight.y); | |
// Top-right 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(topRight.x, topRight.y); | |
rlEnd(); | |
rlDisableTexture(); | |
// NOTE: Vertex position can be transformed using matrices | |
// but the process is way more costly than just calculating | |
// the vertex positions manually, like done above. | |
// I leave here the old implementation for educational pourposes, | |
// just in case someone wants to do some performance test | |
/* | |
rlEnableTexture(texture.id); | |
rlPushMatrix(); | |
rlTranslatef(dest.x, dest.y, 0.0f); | |
if (rotation != 0.0f) rlRotatef(rotation, 0.0f, 0.0f, 1.0f); | |
rlTranslatef(-origin.x, -origin.y, 0.0f); | |
rlBegin(RL_QUADS); | |
rlColor4ub(tint.r, tint.g, tint.b, tint.a); | |
rlNormal3f(0.0f, 0.0f, 1.0f); // Normal vector pointing towards viewer | |
// Bottom-left corner for texture and quad | |
if (flipX) rlTexCoord2f((source.x + source.width)/width, source.y/height); | |
else rlTexCoord2f(source.x/width, source.y/height); | |
rlVertex2f(0.0f, 0.0f); | |
// 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(); | |
rlDisableTexture(); | |
*/ | |
} | |
} | |
// Draw a color-filled rectangle with pro parameters | |
void DrawRectanglePro(Rectangle rec, Vector2 origin, float rotation, Color color) | |
{ | |
rlCheckRenderBatchLimit(4); | |
Vector2 topLeft = { 0 }; | |
Vector2 topRight = { 0 }; | |
Vector2 bottomLeft = { 0 }; | |
Vector2 bottomRight = { 0 }; | |
// Only calculate rotation if needed | |
if (rotation == 0.0f) | |
{ | |
float x = rec.x - origin.x; | |
float y = rec.y - origin.y; | |
topLeft = (Vector2){ x, y }; | |
topRight = (Vector2){ x + rec.width, y }; | |
bottomLeft = (Vector2){ x, y + rec.height }; | |
bottomRight = (Vector2){ x + rec.width, y + rec.height }; | |
} | |
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; | |
topLeft.x = x + dx*cosRotation - dy*sinRotation; | |
topLeft.y = y + dx*sinRotation + dy*cosRotation; | |
topRight.x = x + (dx + rec.width)*cosRotation - dy*sinRotation; | |
topRight.y = y + (dx + rec.width)*sinRotation + dy*cosRotation; | |
bottomLeft.x = x + dx*cosRotation - (dy + rec.height)*sinRotation; | |
bottomLeft.y = y + dx*sinRotation + (dy + rec.height)*cosRotation; | |
bottomRight.x = x + (dx + rec.width)*cosRotation - (dy + rec.height)*sinRotation; | |
bottomRight.y = y + (dx + rec.width)*sinRotation + (dy + rec.height)*cosRotation; | |
} | |
rlEnableTexture(rlGetShapesTexture().id); | |
rlBegin(RL_QUADS); | |
rlNormal3f(0.0f, 0.0f, 1.0f); | |
rlColor4ub(color.r, color.g, color.b, color.a); | |
rlTexCoord2f(rlGetShapesTextureRec().x/rlGetShapesTexture().width, rlGetShapesTextureRec().y/rlGetShapesTexture().height); | |
rlVertex2f(topLeft.x, topLeft.y); | |
rlTexCoord2f(rlGetShapesTextureRec().x/rlGetShapesTexture().width, (rlGetShapesTextureRec().y + rlGetShapesTextureRec().height)/rlGetShapesTexture().height); | |
rlVertex2f(bottomLeft.x, bottomLeft.y); | |
rlTexCoord2f((rlGetShapesTextureRec().x + rlGetShapesTextureRec().width)/rlGetShapesTexture().width, (rlGetShapesTextureRec().y + rlGetShapesTextureRec().height)/rlGetShapesTexture().height); | |
rlVertex2f(bottomRight.x, bottomRight.y); | |
rlTexCoord2f((rlGetShapesTextureRec().x + rlGetShapesTextureRec().width)/rlGetShapesTexture().width, rlGetShapesTextureRec().y/rlGetShapesTexture().height); | |
rlVertex2f(topRight.x, topRight.y); | |
rlEnd(); | |
rlDisableTexture(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Update. The previous numbers were using the default debug build.
Testing with a optimized release build can reach around 150k bunnies.
![image](https://user-images.githubusercontent.com/7503113/109968261-62666000-7cea-11eb-9e92-efd60e6b105a.png)
The original matrix version reaches around 80k. If I change it so it only applies rotation if rotation != 0.0f then it can reach 130k.