Begin draft imeplementation of batched rendering
Render all entities with the same texture in one call. Currently only implemented for humanoid entities. Since we are rendering using triangle strips, between entities there is invalid rastered data between entities. Using degenerate triangles this may be mitigated, by indicating to OGL which triangles it can skip in the rendering process.
This commit is contained in:
parent
7cb13b3cf8
commit
ec7a9e41ff
@ -10,13 +10,39 @@
|
|||||||
|
|
||||||
#define RENDER_BOUNDING_BOX FALSE
|
#define RENDER_BOUNDING_BOX FALSE
|
||||||
|
|
||||||
typedef struct RenderQuad
|
INTERNAL addToRenderGroup(Renderer *renderer, Texture *texture,
|
||||||
|
RenderQuad renderQuad)
|
||||||
{
|
{
|
||||||
// Vertex composition
|
/* Find vacant/matching render group */
|
||||||
// x, y: Coordinates
|
RenderGroup *targetGroup = NULL;
|
||||||
// z, w: Texture Coords
|
for (i32 i = 0; i < ARRAY_COUNT(renderer->groups); i++)
|
||||||
v4 vertex[4];
|
{
|
||||||
} RenderQuad;
|
RenderGroup *group = &renderer->groups[i];
|
||||||
|
if (group->tex == NULL || group->tex->id == texture->id)
|
||||||
|
{
|
||||||
|
if (!group->tex) group->tex = texture;
|
||||||
|
targetGroup = &renderer->groups[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Valid group, add to the render group for rendering */
|
||||||
|
if (targetGroup)
|
||||||
|
{
|
||||||
|
if (targetGroup->quadIndex < ARRAY_COUNT(targetGroup->quads))
|
||||||
|
{
|
||||||
|
targetGroup->quads[targetGroup->quadIndex++] = renderQuad;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// TODO(doyle): Log no remaining render quad slots in group
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// TODO(doyle): Log no remaining render groups
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
INTERNAL inline void flipTexCoord(v4 *texCoords, b32 flipX, b32 flipY)
|
INTERNAL inline void flipTexCoord(v4 *texCoords, b32 flipX, b32 flipY)
|
||||||
{
|
{
|
||||||
@ -48,6 +74,11 @@ INTERNAL void updateBufferObject(Renderer *const renderer,
|
|||||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
INTERNAL void bufferRenderGroupToGL(Renderer *renderer, RenderGroup *group)
|
||||||
|
{
|
||||||
|
updateBufferObject(renderer, group->quads, group->quadIndex);
|
||||||
|
}
|
||||||
|
|
||||||
INTERNAL RenderQuad createTexQuad(Renderer *renderer, v4 quadRect,
|
INTERNAL RenderQuad createTexQuad(Renderer *renderer, v4 quadRect,
|
||||||
RenderTex renderTex)
|
RenderTex renderTex)
|
||||||
{
|
{
|
||||||
@ -204,9 +235,7 @@ void renderer_string(Renderer *const renderer, MemoryArena *arena, Rect camera,
|
|||||||
pos.y = baseline - (charMetric.offset.y);
|
pos.y = baseline - (charMetric.offset.y);
|
||||||
|
|
||||||
const v4 charRectOnScreen =
|
const v4 charRectOnScreen =
|
||||||
math_getRect(pos, V2(CAST(f32) font->maxSize.w,
|
math_getRect(pos, font->maxSize);
|
||||||
CAST(f32) font->maxSize.h));
|
|
||||||
|
|
||||||
pos.x += charMetric.advance;
|
pos.x += charMetric.advance;
|
||||||
|
|
||||||
/* Get texture out */
|
/* Get texture out */
|
||||||
@ -254,7 +283,6 @@ void renderer_entity(Renderer *renderer, Rect camera, Entity *entity,
|
|||||||
char *frameName = anim->frameList[entityAnim->currFrame];
|
char *frameName = anim->frameList[entityAnim->currFrame];
|
||||||
SubTexture animRect = asset_getAtlasSubTex(anim->atlas, frameName);
|
SubTexture animRect = asset_getAtlasSubTex(anim->atlas, frameName);
|
||||||
|
|
||||||
// TODO(doyle): Switch to rect
|
|
||||||
v4 animTexRect = {0};
|
v4 animTexRect = {0};
|
||||||
animTexRect.vec2[0] = animRect.rect.pos;
|
animTexRect.vec2[0] = animRect.rect.pos;
|
||||||
animTexRect.vec2[1] = v2_add(animRect.rect.pos, animRect.rect.size);
|
animTexRect.vec2[1] = v2_add(animRect.rect.pos, animRect.rect.size);
|
||||||
@ -267,13 +295,44 @@ void renderer_entity(Renderer *renderer, Rect camera, Entity *entity,
|
|||||||
}
|
}
|
||||||
|
|
||||||
RenderTex renderTex = {entity->tex, animTexRect};
|
RenderTex renderTex = {entity->tex, animTexRect};
|
||||||
RenderQuad entityQuad =
|
|
||||||
createDefaultTexQuad(renderer, renderTex);
|
|
||||||
updateBufferObject(renderer, &entityQuad, 1);
|
|
||||||
|
|
||||||
|
#if RENDERER_USE_RENDER_GROUPS
|
||||||
|
// TODO(doyle): getRect needs a better name
|
||||||
|
v2 posInCameraSpace = v2_sub(entity->pos, camera.pos);
|
||||||
|
v4 entityVertexOnScreen = math_getRect(posInCameraSpace, entity->size);
|
||||||
|
RenderQuad entityQuad =
|
||||||
|
createTexQuad(renderer, entityVertexOnScreen, renderTex);
|
||||||
|
|
||||||
|
addToRenderGroup(renderer, entity->tex, entityQuad);
|
||||||
|
#else
|
||||||
|
RenderQuad entityQuad = createDefaultTexQuad(renderer, renderTex);
|
||||||
|
// TODO(doyle): getRect needs a better name
|
||||||
|
updateBufferObject(renderer, &entityQuad, 1);
|
||||||
v2 posInCameraSpace = v2_sub(entity->pos, camera.pos);
|
v2 posInCameraSpace = v2_sub(entity->pos, camera.pos);
|
||||||
renderObject(renderer, posInCameraSpace,
|
renderObject(renderer, posInCameraSpace,
|
||||||
entity->size, pivotPoint,
|
entity->size, pivotPoint,
|
||||||
entity->rotation + rotate, color, entity->tex);
|
entity->rotation + rotate, color, entity->tex);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void renderer_renderGroups(Renderer *renderer)
|
||||||
|
{
|
||||||
|
for (i32 i = 0; i < ARRAY_COUNT(renderer->groups); i++)
|
||||||
|
{
|
||||||
|
RenderGroup *currGroup = &renderer->groups[i];
|
||||||
|
if (currGroup->tex)
|
||||||
|
{
|
||||||
|
bufferRenderGroupToGL(renderer, currGroup);
|
||||||
|
|
||||||
|
v2 pivotPoint = V2(0, 0);
|
||||||
|
f32 rotate = 0;
|
||||||
|
v4 color = V4(1, 1, 1, 1);
|
||||||
|
renderObject(renderer, V2(0.0f, 0.0f), renderer->size, pivotPoint,
|
||||||
|
rotate, color, currGroup->tex);
|
||||||
|
|
||||||
|
RenderGroup clear = {0};
|
||||||
|
*currGroup = clear;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -640,7 +640,7 @@ INTERNAL void entityInit(GameState *state, v2 windowSize)
|
|||||||
entity_addAnim(assetManager, hero, "claudeRipperBlast");
|
entity_addAnim(assetManager, hero, "claudeRipperBlast");
|
||||||
entity_addAnim(assetManager, hero, "claudeAirSlash");
|
entity_addAnim(assetManager, hero, "claudeAirSlash");
|
||||||
|
|
||||||
entity_setActiveAnim(eventQueue, hero, "claudeBattleIdle");
|
entity_setActiveAnim(eventQueue, hero, "claudeIdle");
|
||||||
|
|
||||||
/* Create a NPC */
|
/* Create a NPC */
|
||||||
pos = V2(hero->pos.x * 3, CAST(f32) state->tileSize);
|
pos = V2(hero->pos.x * 3, CAST(f32) state->tileSize);
|
||||||
@ -2071,22 +2071,15 @@ void worldTraveller_gameUpdateAndRender(GameState *state, f32 dt)
|
|||||||
{
|
{
|
||||||
entity_updateAnim(eventQueue, entity, dt);
|
entity_updateAnim(eventQueue, entity, dt);
|
||||||
/* Calculate region to render */
|
/* Calculate region to render */
|
||||||
|
renderer_entity(renderer, camera, entity,
|
||||||
if (entity->type == entitytype_weapon)
|
v2_scale(entity->size, 0.5f), 0, V4(1, 1, 1, 1.0f));
|
||||||
{
|
|
||||||
renderer_entity(renderer, camera, entity,
|
|
||||||
v2_scale(entity->size, 0.5f), 0,
|
|
||||||
V4(1, 1, 1, 1.0f));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
renderer_entity(renderer, camera, entity,
|
|
||||||
v2_scale(entity->size, 0.5f), 0,
|
|
||||||
V4(1, 1, 1, 1));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if RENDERER_USE_RENDER_GROUPS
|
||||||
|
renderer_renderGroups(renderer);
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*****************************************
|
*****************************************
|
||||||
* Process Events From Entity Update Loop
|
* Process Events From Entity Update Loop
|
||||||
|
@ -12,6 +12,28 @@ typedef struct MemoryArena MemoryArena;
|
|||||||
typedef struct Shader Shader;
|
typedef struct Shader Shader;
|
||||||
typedef struct Texture Texture;
|
typedef struct Texture Texture;
|
||||||
|
|
||||||
|
typedef struct RenderQuad
|
||||||
|
{
|
||||||
|
// Vertex composition
|
||||||
|
// x, y: Coordinates - of entity on screen
|
||||||
|
// z, w: Texture Coords - of texture for this quad
|
||||||
|
v4 vertex[4];
|
||||||
|
} RenderQuad;
|
||||||
|
|
||||||
|
typedef struct RenderTex
|
||||||
|
{
|
||||||
|
Texture *tex;
|
||||||
|
// TODO(doyle): Switch to rect
|
||||||
|
v4 texRect;
|
||||||
|
} RenderTex;
|
||||||
|
|
||||||
|
typedef struct RenderGroup
|
||||||
|
{
|
||||||
|
Texture *tex;
|
||||||
|
RenderQuad quads[100];
|
||||||
|
i32 quadIndex;
|
||||||
|
} RenderGroup;
|
||||||
|
|
||||||
typedef struct Renderer
|
typedef struct Renderer
|
||||||
{
|
{
|
||||||
Shader *shader;
|
Shader *shader;
|
||||||
@ -20,15 +42,11 @@ typedef struct Renderer
|
|||||||
i32 numVertexesInVbo;
|
i32 numVertexesInVbo;
|
||||||
v2 vertexNdcFactor;
|
v2 vertexNdcFactor;
|
||||||
v2 size;
|
v2 size;
|
||||||
|
|
||||||
|
RenderGroup groups[100];
|
||||||
} Renderer;
|
} Renderer;
|
||||||
|
|
||||||
typedef struct RenderTex
|
#define RENDERER_USE_RENDER_GROUPS TRUE
|
||||||
{
|
|
||||||
Texture *tex;
|
|
||||||
|
|
||||||
// TODO(doyle): Switch to rect
|
|
||||||
v4 texRect;
|
|
||||||
} RenderTex;
|
|
||||||
|
|
||||||
// TODO(doyle): Use z-index occluding for rendering
|
// TODO(doyle): Use z-index occluding for rendering
|
||||||
RenderTex renderer_createNullRenderTex(AssetManager *const assetManager);
|
RenderTex renderer_createNullRenderTex(AssetManager *const assetManager);
|
||||||
@ -64,4 +82,6 @@ inline void renderer_staticString(Renderer *const renderer, MemoryArena *arena,
|
|||||||
void renderer_entity(Renderer *renderer, Rect camera, Entity *entity,
|
void renderer_entity(Renderer *renderer, Rect camera, Entity *entity,
|
||||||
v2 pivotPoint, f32 rotate, v4 color);
|
v2 pivotPoint, f32 rotate, v4 color);
|
||||||
|
|
||||||
|
void renderer_renderGroups(Renderer *renderer);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user