mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-13 01:26:50 -04:00
Refactor isometric block drawing to only update the vertex buffer once
This commit is contained in:
parent
654ce2079b
commit
e2798dcebe
@ -10,7 +10,8 @@
|
|||||||
static float iso_scale;
|
static float iso_scale;
|
||||||
static struct VertexTextured* iso_vertices;
|
static struct VertexTextured* iso_vertices;
|
||||||
static struct VertexTextured* iso_vertices_base;
|
static struct VertexTextured* iso_vertices_base;
|
||||||
static GfxResourceID iso_vb;
|
static int* iso_state;
|
||||||
|
static int* iso_state_base;
|
||||||
|
|
||||||
static cc_bool iso_cacheInited;
|
static cc_bool iso_cacheInited;
|
||||||
static PackedCol iso_color = PACKEDCOL_WHITE;
|
static PackedCol iso_color = PACKEDCOL_WHITE;
|
||||||
@ -23,7 +24,6 @@ static PackedCol iso_colorXSide, iso_colorZSide, iso_colorYBottom;
|
|||||||
|
|
||||||
static struct Matrix iso_transform;
|
static struct Matrix iso_transform;
|
||||||
static Vec3 iso_pos;
|
static Vec3 iso_pos;
|
||||||
static int iso_lastTexIndex, iso_texIndex;
|
|
||||||
|
|
||||||
static void IsometricDrawer_RotateX(float cosA, float sinA) {
|
static void IsometricDrawer_RotateX(float cosA, float sinA) {
|
||||||
float y = cosA * iso_pos.Y + sinA * iso_pos.Z;
|
float y = cosA * iso_pos.Y + sinA * iso_pos.Z;
|
||||||
@ -50,35 +50,22 @@ static void IsometricDrawer_InitCache(void) {
|
|||||||
Matrix_Mul(&iso_transform, &rotY, &rotX);
|
Matrix_Mul(&iso_transform, &rotY, &rotX);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void IsometricDrawer_Flush(void) {
|
|
||||||
int count;
|
|
||||||
if (iso_lastTexIndex != -1) {
|
|
||||||
Gfx_BindTexture(Atlas1D.TexIds[iso_lastTexIndex]);
|
|
||||||
count = (int)(iso_vertices - iso_vertices_base);
|
|
||||||
Gfx_UpdateDynamicVb_IndexedTris(iso_vb, iso_vertices_base, count);
|
|
||||||
}
|
|
||||||
|
|
||||||
iso_lastTexIndex = iso_texIndex;
|
|
||||||
iso_vertices = iso_vertices_base;
|
|
||||||
}
|
|
||||||
|
|
||||||
static TextureLoc IsometricDrawer_GetTexLoc(BlockID block, Face face) {
|
static TextureLoc IsometricDrawer_GetTexLoc(BlockID block, Face face) {
|
||||||
TextureLoc loc = Block_Tex(block, face);
|
TextureLoc loc = Block_Tex(block, face);
|
||||||
iso_texIndex = Atlas1D_Index(loc);
|
*iso_state++ = Atlas1D_Index(loc);
|
||||||
|
|
||||||
if (iso_lastTexIndex != iso_texIndex) IsometricDrawer_Flush();
|
|
||||||
return loc;
|
return loc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void IsometricDrawer_SpriteZQuad(BlockID block, cc_bool firstPart) {
|
static void IsometricDrawer_SpriteZQuad(BlockID block, cc_bool firstPart) {
|
||||||
|
int texIndex;
|
||||||
TextureLoc loc = Block_Tex(block, FACE_ZMAX);
|
TextureLoc loc = Block_Tex(block, FACE_ZMAX);
|
||||||
TextureRec rec = Atlas1D_TexRec(loc, 1, &iso_texIndex);
|
TextureRec rec = Atlas1D_TexRec(loc, 1, &texIndex);
|
||||||
|
|
||||||
struct VertexTextured v;
|
struct VertexTextured v;
|
||||||
float minX, maxX, minY, maxY;
|
float minX, maxX, minY, maxY;
|
||||||
float x1, x2;
|
float x1, x2;
|
||||||
|
|
||||||
if (iso_lastTexIndex != iso_texIndex) IsometricDrawer_Flush();
|
*iso_state++ = texIndex;
|
||||||
v.Col = iso_color;
|
v.Col = iso_color;
|
||||||
Block_Tint(v.Col, block);
|
Block_Tint(v.Col, block);
|
||||||
|
|
||||||
@ -100,14 +87,15 @@ static void IsometricDrawer_SpriteZQuad(BlockID block, cc_bool firstPart) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void IsometricDrawer_SpriteXQuad(BlockID block, cc_bool firstPart) {
|
static void IsometricDrawer_SpriteXQuad(BlockID block, cc_bool firstPart) {
|
||||||
|
int texIndex;
|
||||||
TextureLoc loc = Block_Tex(block, FACE_XMAX);
|
TextureLoc loc = Block_Tex(block, FACE_XMAX);
|
||||||
TextureRec rec = Atlas1D_TexRec(loc, 1, &iso_texIndex);
|
TextureRec rec = Atlas1D_TexRec(loc, 1, &texIndex);
|
||||||
|
|
||||||
struct VertexTextured v;
|
struct VertexTextured v;
|
||||||
float minY, maxY, minZ, maxZ;
|
float minY, maxY, minZ, maxZ;
|
||||||
float z1, z2;
|
float z1, z2;
|
||||||
|
|
||||||
if (iso_lastTexIndex != iso_texIndex) IsometricDrawer_Flush();
|
*iso_state++ = texIndex;
|
||||||
v.Col = iso_color;
|
v.Col = iso_color;
|
||||||
Block_Tint(v.Col, block);
|
Block_Tint(v.Col, block);
|
||||||
|
|
||||||
@ -128,17 +116,17 @@ static void IsometricDrawer_SpriteXQuad(BlockID block, cc_bool firstPart) {
|
|||||||
v.Y = minY; v.V = rec.V2; *iso_vertices++ = v;
|
v.Y = minY; v.V = rec.V2; *iso_vertices++ = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IsometricDrawer_BeginBatch(struct VertexTextured* vertices, GfxResourceID vb) {
|
void IsometricDrawer_BeginBatch(struct VertexTextured* vertices, int* state) {
|
||||||
IsometricDrawer_InitCache();
|
IsometricDrawer_InitCache();
|
||||||
iso_lastTexIndex = -1;
|
iso_vertices = vertices;
|
||||||
iso_vertices = vertices;
|
|
||||||
iso_vertices_base = vertices;
|
iso_vertices_base = vertices;
|
||||||
iso_vb = vb;
|
iso_state = state;
|
||||||
|
iso_state_base = state;
|
||||||
|
|
||||||
Gfx_LoadMatrix(MATRIX_VIEW, &iso_transform);
|
Gfx_LoadMatrix(MATRIX_VIEW, &iso_transform);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IsometricDrawer_DrawBatch(BlockID block, float size, float x, float y) {
|
void IsometricDrawer_AddBatch(BlockID block, float size, float x, float y) {
|
||||||
cc_bool bright = Blocks.FullBright[block];
|
cc_bool bright = Blocks.FullBright[block];
|
||||||
Vec3 min, max;
|
Vec3 min, max;
|
||||||
if (Blocks.Draw[block] == DRAW_GAS) return;
|
if (Blocks.Draw[block] == DRAW_GAS) return;
|
||||||
@ -185,12 +173,38 @@ void IsometricDrawer_DrawBatch(BlockID block, float size, float x, float y) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IsometricDrawer_EndBatch(void) {
|
static void IsometricDrawer_Render(GfxResourceID vb) {
|
||||||
if (iso_vertices != iso_vertices_base) {
|
int curIdx, batchBeg, batchLen;
|
||||||
iso_lastTexIndex = iso_texIndex;
|
int count, i;
|
||||||
IsometricDrawer_Flush();
|
|
||||||
|
count = (int)(iso_vertices - iso_vertices_base);
|
||||||
|
Gfx_SetDynamicVbData(vb, iso_vertices_base, count);
|
||||||
|
|
||||||
|
curIdx = iso_state_base[0];
|
||||||
|
batchLen = 0;
|
||||||
|
batchBeg = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < count / 4; i++, batchLen += 4)
|
||||||
|
{
|
||||||
|
if (iso_state_base[i] == curIdx) continue;
|
||||||
|
|
||||||
|
/* Flush previous batch */
|
||||||
|
Gfx_BindTexture(Atlas1D.TexIds[curIdx]);
|
||||||
|
Gfx_DrawVb_IndexedTris_Range(batchLen, batchBeg);
|
||||||
|
|
||||||
|
/* Reset for next batch */
|
||||||
|
curIdx = iso_state_base[i];
|
||||||
|
batchBeg = i * 4;
|
||||||
|
batchLen = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
iso_lastTexIndex = -1;
|
Gfx_BindTexture(Atlas1D.TexIds[curIdx]);
|
||||||
|
Gfx_DrawVb_IndexedTris_Range(batchLen, batchBeg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IsometricDrawer_EndBatch(GfxResourceID vb) {
|
||||||
|
if (iso_state != iso_state_base) {
|
||||||
|
IsometricDrawer_Render(vb);
|
||||||
|
}
|
||||||
Gfx_LoadIdentityMatrix(MATRIX_VIEW);
|
Gfx_LoadIdentityMatrix(MATRIX_VIEW);
|
||||||
}
|
}
|
||||||
|
@ -8,10 +8,11 @@ struct VertexTextured;
|
|||||||
|
|
||||||
/* Maximum number of vertices used to draw a block in isometric way. */
|
/* Maximum number of vertices used to draw a block in isometric way. */
|
||||||
#define ISOMETRICDRAWER_MAXVERTICES 16
|
#define ISOMETRICDRAWER_MAXVERTICES 16
|
||||||
|
|
||||||
/* Sets up state to begin drawing blocks isometrically. */
|
/* Sets up state to begin drawing blocks isometrically. */
|
||||||
void IsometricDrawer_BeginBatch(struct VertexTextured* vertices, GfxResourceID vb);
|
void IsometricDrawer_BeginBatch(struct VertexTextured* vertices, int* state);
|
||||||
/* Buffers the vertices needed to draw the given block at the given position. */
|
/* Buffers the vertices needed to draw the given block at the given position. */
|
||||||
void IsometricDrawer_DrawBatch(BlockID block, float size, float x, float y);
|
void IsometricDrawer_AddBatch(BlockID block, float size, float x, float y);
|
||||||
/* Flushes buffered vertices to the GPU, then restores state. */
|
/* Flushes buffered vertices to the GPU, then restores state. */
|
||||||
void IsometricDrawer_EndBatch(void);
|
void IsometricDrawer_EndBatch(GfxResourceID vb);
|
||||||
#endif
|
#endif
|
||||||
|
@ -403,13 +403,15 @@ static void HotbarWidget_RenderHotbarOutline(struct HotbarWidget* w) {
|
|||||||
Gfx_Draw2DTexture(&w->selTex, PACKEDCOL_WHITE);
|
Gfx_Draw2DTexture(&w->selTex, PACKEDCOL_WHITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define HOTBAR_MAX_VERTICES (INVENTORY_BLOCKS_PER_HOTBAR * ISOMETRICDRAWER_MAXVERTICES)
|
||||||
static void HotbarWidget_RenderHotbarBlocks(struct HotbarWidget* w) {
|
static void HotbarWidget_RenderHotbarBlocks(struct HotbarWidget* w) {
|
||||||
/* TODO: Should hotbar use its own VB? */
|
/* TODO: Should hotbar use its own VB? */
|
||||||
struct VertexTextured vertices[INVENTORY_BLOCKS_PER_HOTBAR * ISOMETRICDRAWER_MAXVERTICES];
|
struct VertexTextured vertices[HOTBAR_MAX_VERTICES];
|
||||||
|
int state[HOTBAR_MAX_VERTICES / 4];
|
||||||
float scale;
|
float scale;
|
||||||
int i, x, y;
|
int i, x, y;
|
||||||
|
|
||||||
IsometricDrawer_BeginBatch(vertices, Models.Vb);
|
IsometricDrawer_BeginBatch(vertices, state);
|
||||||
scale = w->elemSize / 2.0f;
|
scale = w->elemSize / 2.0f;
|
||||||
|
|
||||||
for (i = 0; i < INVENTORY_BLOCKS_PER_HOTBAR; i++) {
|
for (i = 0; i < INVENTORY_BLOCKS_PER_HOTBAR; i++) {
|
||||||
@ -419,9 +421,9 @@ static void HotbarWidget_RenderHotbarBlocks(struct HotbarWidget* w) {
|
|||||||
#ifdef CC_BUILD_TOUCH
|
#ifdef CC_BUILD_TOUCH
|
||||||
if (i == HOTBAR_MAX_INDEX && Input_TouchMode) continue;
|
if (i == HOTBAR_MAX_INDEX && Input_TouchMode) continue;
|
||||||
#endif
|
#endif
|
||||||
IsometricDrawer_DrawBatch(Inventory_Get(i), scale, x, y);
|
IsometricDrawer_AddBatch(Inventory_Get(i), scale, x, y);
|
||||||
}
|
}
|
||||||
IsometricDrawer_EndBatch();
|
IsometricDrawer_EndBatch(Models.Vb);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int HotbarWidget_ScrolledIndex(struct HotbarWidget* w, float delta, int index, int dir) {
|
static int HotbarWidget_ScrolledIndex(struct HotbarWidget* w, float delta, int index, int dir) {
|
||||||
@ -700,6 +702,7 @@ void TableWidget_RecreateBlocks(struct TableWidget* w) {
|
|||||||
static void TableWidget_Render(void* widget, double delta) {
|
static void TableWidget_Render(void* widget, double delta) {
|
||||||
struct TableWidget* w = (struct TableWidget*)widget;
|
struct TableWidget* w = (struct TableWidget*)widget;
|
||||||
struct VertexTextured vertices[TABLE_MAX_VERTICES];
|
struct VertexTextured vertices[TABLE_MAX_VERTICES];
|
||||||
|
int state[TABLE_MAX_VERTICES / 4];
|
||||||
int cellSizeX, cellSizeY, size;
|
int cellSizeX, cellSizeY, size;
|
||||||
float off;
|
float off;
|
||||||
int i, x, y;
|
int i, x, y;
|
||||||
@ -732,14 +735,14 @@ static void TableWidget_Render(void* widget, double delta) {
|
|||||||
}
|
}
|
||||||
Gfx_SetVertexFormat(VERTEX_FORMAT_TEXTURED);
|
Gfx_SetVertexFormat(VERTEX_FORMAT_TEXTURED);
|
||||||
|
|
||||||
IsometricDrawer_BeginBatch(vertices, w->vb);
|
IsometricDrawer_BeginBatch(vertices, state);
|
||||||
for (i = 0; i < w->blocksCount; i++) {
|
for (i = 0; i < w->blocksCount; i++) {
|
||||||
if (!TableWidget_GetCoords(w, i, &x, &y)) continue;
|
if (!TableWidget_GetCoords(w, i, &x, &y)) continue;
|
||||||
|
|
||||||
/* We want to always draw the selected block on top of others */
|
/* We want to always draw the selected block on top of others */
|
||||||
/* TODO: Need two size arguments, in case X/Y dpi differs */
|
/* TODO: Need two size arguments, in case X/Y dpi differs */
|
||||||
if (i == w->selectedIndex) continue;
|
if (i == w->selectedIndex) continue;
|
||||||
IsometricDrawer_DrawBatch(w->blocks[i],
|
IsometricDrawer_AddBatch(w->blocks[i],
|
||||||
w->normBlockSize, x + cellSizeX / 2, y + cellSizeY / 2);
|
w->normBlockSize, x + cellSizeX / 2, y + cellSizeY / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -747,10 +750,10 @@ static void TableWidget_Render(void* widget, double delta) {
|
|||||||
if (i != -1) {
|
if (i != -1) {
|
||||||
TableWidget_GetCoords(w, i, &x, &y);
|
TableWidget_GetCoords(w, i, &x, &y);
|
||||||
|
|
||||||
IsometricDrawer_DrawBatch(w->blocks[i],
|
IsometricDrawer_AddBatch(w->blocks[i],
|
||||||
w->selBlockSize, x + cellSizeX / 2, y + cellSizeY / 2);
|
w->selBlockSize, x + cellSizeX / 2, y + cellSizeY / 2);
|
||||||
}
|
}
|
||||||
IsometricDrawer_EndBatch();
|
IsometricDrawer_EndBatch(w->vb);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void TableWidget_Free(void* widget) {
|
static void TableWidget_Free(void* widget) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user