Move entity name rendering into more general EntityRenderers module

This commit is contained in:
UnknownShadow200 2023-11-03 18:34:05 +11:00
parent a81d9d7ee9
commit 776906ebce
17 changed files with 285 additions and 249 deletions

View File

@ -34,7 +34,7 @@ void AxisLinesRenderer_Render(void) {
if (!AxisLinesRenderer_Enabled) return;
/* Don't do it in a ContextRecreated handler, because we only want VB recreated if ShowAxisLines in on. */
if (!axisLines_vb) {
Gfx_RecreateDynamicVb(&axisLines_vb, VERTEX_FORMAT_COLOURED, AXISLINES_NUM_VERTICES);
axisLines_vb = Gfx_CreateDynamicVb(VERTEX_FORMAT_COLOURED, AXISLINES_NUM_VERTICES);
}
if (Camera.Active->isThirdPerson) {

View File

@ -9,8 +9,6 @@
#include "Funcs.h"
#include "Graphics.h"
#include "Lighting.h"
#include "Drawer2D.h"
#include "Particle.h"
#include "Http.h"
#include "Chat.h"
#include "Model.h"
@ -22,6 +20,7 @@
#include "Options.h"
#include "Errors.h"
#include "Utils.h"
#include "EntityRenderers.h"
const char* const NameMode_Names[NAME_MODE_COUNT] = { "None", "Hovered", "All", "AllHovered", "AllUnscaled" };
const char* const ShadowMode_Names[SHADOW_MODE_COUNT] = { "None", "SnapToBlock", "Circle", "CircleAll" };
@ -47,6 +46,11 @@ void Entity_Init(struct Entity* e) {
Entity_SetModel(e, &model);
}
void Entity_SetName(struct Entity* e, const cc_string* name) {
EntityNames_Delete(e);
String_CopyToRawArray(e->NameRaw, name);
}
Vec3 Entity_GetEyePosition(struct Entity* e) {
Vec3 pos = e->Position; pos.Y += Entity_GetEyeHeight(e); return pos;
}
@ -191,107 +195,6 @@ cc_bool Entity_TouchesAnyWater(struct Entity* e) {
}
/*########################################################################################################################*
*-----------------------------------------------------Entity nametag------------------------------------------------------*
*#########################################################################################################################*/
#define NAME_IS_EMPTY -30000
#define NAME_OFFSET 3 /* offset of back layer of name above an entity */
static void MakeNameTexture(struct Entity* e) {
cc_string colorlessName; char colorlessBuffer[STRING_SIZE];
BitmapCol shadowColor = BitmapCol_Make(80, 80, 80, 255);
BitmapCol origWhiteColor;
struct DrawTextArgs args;
struct FontDesc font;
struct Context2D ctx;
int width, height;
cc_string name;
/* Names are always drawn using default.png font */
Font_MakeBitmapped(&font, 24, FONT_FLAGS_NONE);
/* Don't want DPI scaling or padding */
font.size = 24; font.height = 24;
name = String_FromRawArray(e->NameRaw);
DrawTextArgs_Make(&args, &name, &font, false);
width = Drawer2D_TextWidth(&args);
if (!width) {
e->NameTex.ID = 0;
e->NameTex.X = NAME_IS_EMPTY;
} else {
String_InitArray(colorlessName, colorlessBuffer);
width += NAME_OFFSET;
height = Drawer2D_TextHeight(&args) + NAME_OFFSET;
Context2D_Alloc(&ctx, width, height);
{
origWhiteColor = Drawer2D.Colors['f'];
Drawer2D.Colors['f'] = shadowColor;
Drawer2D_WithoutColors(&colorlessName, &name);
args.text = colorlessName;
Context2D_DrawText(&ctx, &args, NAME_OFFSET, NAME_OFFSET);
Drawer2D.Colors['f'] = origWhiteColor;
args.text = name;
Context2D_DrawText(&ctx, &args, 0, 0);
}
Context2D_MakeTexture(&e->NameTex, &ctx);
Context2D_Free(&ctx);
}
}
static void DrawName(struct Entity* e) {
struct VertexTextured* vertices;
struct Model* model;
struct Matrix mat;
Vec3 pos;
float scale;
Vec2 size;
if (e->NameTex.X == NAME_IS_EMPTY) return;
if (!e->NameTex.ID) MakeNameTexture(e);
Gfx_BindTexture(e->NameTex.ID);
model = e->Model;
Vec3_TransformY(&pos, model->GetNameY(e), &e->Transform);
scale = model->nameScale * e->ModelScale.Y;
scale = scale > 1.0f ? (1.0f/70.0f) : (scale/70.0f);
size.X = e->NameTex.Width * scale; size.Y = e->NameTex.Height * scale;
if (Entities.NamesMode == NAME_MODE_ALL_UNSCALED && LocalPlayer_Instance.Hacks.CanSeeAllNames) {
Matrix_Mul(&mat, &Gfx.View, &Gfx.Projection); /* TODO: This mul is slow, avoid it */
/* Get W component of transformed position */
scale = pos.X * mat.row1.W + pos.Y * mat.row2.W + pos.Z * mat.row3.W + mat.row4.W;
size.X *= scale * 0.2f; size.Y *= scale * 0.2f;
}
Gfx_SetVertexFormat(VERTEX_FORMAT_TEXTURED);
vertices = (struct VertexTextured*)Gfx_LockDynamicVb(Gfx_texVb, VERTEX_FORMAT_TEXTURED, 4);
Particle_DoRender(&size, &pos, &e->NameTex.uv, PACKEDCOL_WHITE, vertices);
Gfx_UnlockDynamicVb(Gfx_texVb);
Gfx_DrawVb_IndexedTris(4);
}
/* Deletes the texture containing the entity's nametag */
CC_NOINLINE static void DeleteNameTex(struct Entity* e) {
Gfx_DeleteTexture(&e->NameTex.ID);
e->NameTex.X = 0; /* X is used as an 'empty name' flag */
}
void Entity_SetName(struct Entity* e, const cc_string* name) {
DeleteNameTex(e);
String_CopyToRawArray(e->NameRaw, name);
/* name texture redraw deferred until necessary */
}
/*########################################################################################################################*
*------------------------------------------------------Entity skins-------------------------------------------------------*
*#########################################################################################################################*/
@ -531,7 +434,6 @@ void Entity_LerpAngles(struct Entity* e, float t) {
*--------------------------------------------------------Entities---------------------------------------------------------*
*#########################################################################################################################*/
struct _EntitiesData Entities;
static EntityID entities_closestId;
void Entities_Tick(struct ScheduledTask* task) {
int i;
@ -551,83 +453,17 @@ void Entities_RenderModels(double delta, float t) {
}
Gfx_SetAlphaTest(false);
}
void Entities_RenderNames(void) {
struct LocalPlayer* p = &LocalPlayer_Instance;
cc_bool hadFog;
int i;
if (Entities.NamesMode == NAME_MODE_NONE) return;
entities_closestId = Entities_GetClosest(&p->Base);
if (!p->Hacks.CanSeeAllNames || Entities.NamesMode != NAME_MODE_ALL) return;
Gfx_SetAlphaTest(true);
hadFog = Gfx_GetFog();
if (hadFog) Gfx_SetFog(false);
for (i = 0; i < ENTITIES_MAX_COUNT; i++) {
if (!Entities.List[i]) continue;
if (i != entities_closestId || i == ENTITIES_SELF_ID) {
Entities.List[i]->VTABLE->RenderName(Entities.List[i]);
}
}
Gfx_SetAlphaTest(false);
if (hadFog) Gfx_SetFog(true);
}
void Entities_RenderHoveredNames(void) {
struct LocalPlayer* p = &LocalPlayer_Instance;
cc_bool allNames, hadFog;
int i;
if (Entities.NamesMode == NAME_MODE_NONE) return;
allNames = !(Entities.NamesMode == NAME_MODE_HOVERED || Entities.NamesMode == NAME_MODE_ALL)
&& p->Hacks.CanSeeAllNames;
Gfx_SetAlphaTest(true);
Gfx_SetDepthTest(false);
hadFog = Gfx_GetFog();
if (hadFog) Gfx_SetFog(false);
for (i = 0; i < ENTITIES_MAX_COUNT; i++) {
if (!Entities.List[i]) continue;
if ((i == entities_closestId || allNames) && i != ENTITIES_SELF_ID) {
Entities.List[i]->VTABLE->RenderName(Entities.List[i]);
}
}
Gfx_SetAlphaTest(false);
Gfx_SetDepthTest(true);
if (hadFog) Gfx_SetFog(true);
}
static void Entity_ContextLost(struct Entity* e) { DeleteNameTex(e); }
static void Entities_ContextLost(void* obj) {
int i;
for (i = 0; i < ENTITIES_MAX_COUNT; i++) {
if (!Entities.List[i]) continue;
Entity_ContextLost(Entities.List[i]);
}
if (Gfx.ManagedTextures) return;
for (i = 0; i < ENTITIES_MAX_COUNT; i++) {
if (!Entities.List[i]) continue;
DeleteSkin(Entities.List[i]);
}
}
/* No OnContextCreated, names/skin textures remade when needed */
static void Entities_ChatFontChanged(void* obj) {
int i;
for (i = 0; i < ENTITIES_MAX_COUNT; i++) {
if (!Entities.List[i]) continue;
DeleteNameTex(Entities.List[i]);
/* name redraw is deferred until rendered */
}
}
/* No OnContextCreated, skin textures remade when needed */
void Entities_Remove(EntityID id) {
struct Entity* e = Entities.List[id];
@ -749,7 +585,7 @@ struct IGameComponent TabList_Component = {
static void Player_Despawn(struct Entity* e) {
DeleteSkin(e);
Entity_ContextLost(e);
EntityNames_Delete(e);
}
@ -870,9 +706,8 @@ static void LocalPlayer_RenderModel(struct Entity* e, double deltaTime, float t)
Model_Render(e->Model, e);
}
static void LocalPlayer_RenderName(struct Entity* e) {
if (!Camera.Active->isThirdPerson) return;
DrawName(e);
static cc_bool LocalPlayer_ShouldRenderName(struct Entity* e) {
return Camera.Active->isThirdPerson;
}
static void LocalPlayer_CheckJumpVelocity(void* obj) {
@ -896,7 +731,7 @@ static void LocalPlayer_GetMovement(float* xMoving, float* zMoving) {
static const struct EntityVTABLE localPlayer_VTABLE = {
LocalPlayer_Tick, Player_Despawn, LocalPlayer_SetLocation, Entity_GetColor,
LocalPlayer_RenderModel, LocalPlayer_RenderName
LocalPlayer_RenderModel, LocalPlayer_ShouldRenderName
};
static void LocalPlayer_Init(void) {
struct LocalPlayer* p = &LocalPlayer_Instance;
@ -1152,19 +987,19 @@ static void NetPlayer_RenderModel(struct Entity* e, double deltaTime, float t) {
if (e->ShouldRender) Model_Render(e->Model, e);
}
static void NetPlayer_RenderName(struct Entity* e) {
static cc_bool NetPlayer_ShouldRenderName(struct Entity* e) {
float distance;
int threshold;
if (!e->ShouldRender) return;
if (!e->ShouldRender) return false;
distance = Model_RenderDistance(e);
threshold = Entities.NamesMode == NAME_MODE_ALL_UNSCALED ? 8192 * 8192 : 32 * 32;
if (distance <= (float)threshold) DrawName(e);
return distance <= (float)threshold;
}
static const struct EntityVTABLE netPlayer_VTABLE = {
NetPlayer_Tick, Player_Despawn, NetPlayer_SetLocation, Entity_GetColor,
NetPlayer_RenderModel, NetPlayer_RenderName
NetPlayer_RenderModel, NetPlayer_ShouldRenderName
};
void NetPlayer_Init(struct NetPlayer* p) {
Mem_Set(p, 0, sizeof(struct NetPlayer));
@ -1177,10 +1012,9 @@ void NetPlayer_Init(struct NetPlayer* p) {
*---------------------------------------------------Entities component----------------------------------------------------*
*#########################################################################################################################*/
static void Entities_Init(void) {
Event_Register_(&GfxEvents.ContextLost, NULL, Entities_ContextLost);
Event_Register_(&ChatEvents.FontChanged, NULL, Entities_ChatFontChanged);
Event_Register_(&InputEvents.Down, NULL, LocalPlayer_InputDown);
Event_Register_(&InputEvents.Up, NULL, LocalPlayer_InputUp);
Event_Register_(&GfxEvents.ContextLost, NULL, Entities_ContextLost);
Event_Register_(&InputEvents.Down, NULL, LocalPlayer_InputDown);
Event_Register_(&InputEvents.Up, NULL, LocalPlayer_InputUp);
Entities.NamesMode = Options_GetEnum(OPT_NAMES_MODE, NAME_MODE_HOVERED,
NameMode_Names, Array_Elems(NameMode_Names));

View File

@ -71,7 +71,7 @@ struct EntityVTABLE {
void (*SetLocation)(struct Entity* e, struct LocationUpdate* update);
PackedCol (*GetCol)(struct Entity* e);
void (*RenderModel)(struct Entity* e, double deltaTime, float t);
void (*RenderName)(struct Entity* e);
cc_bool (*ShouldRenderName)(struct Entity* e);
};
/* Skin is still being downloaded asynchronously */
@ -155,10 +155,6 @@ CC_VAR extern struct _EntitiesData {
void Entities_Tick(struct ScheduledTask* task);
/* Renders all entities */
void Entities_RenderModels(double delta, float t);
/* Renders the name tags of entities, depending on Entities.NamesMode */
void Entities_RenderNames(void);
/* Renders hovered entity name tags (these appears through blocks) */
void Entities_RenderHoveredNames(void);
/* Removes the given entity, raising EntityEvents.Removed event */
void Entities_Remove(EntityID id);
/* Gets the ID of the closest entity to the given entity */

View File

@ -9,15 +9,29 @@
#include "Graphics.h"
#include "Model.h"
#include "World.h"
#include "Particle.h"
#include "Drawer2D.h"
/*########################################################################################################################*
*------------------------------------------------------Entity Shadow------------------------------------------------------*
*#########################################################################################################################*/
static cc_bool shadows_boundTex;
static GfxResourceID shadows_VB;
static GfxResourceID shadows_tex;
static float shadow_radius, shadow_uvScale;
struct ShadowData { float Y; BlockID Block; cc_uint8 A; };
/* Circle shadows extend at most 4 blocks vertically */
#define SHADOW_MAX_RANGE 4
/* Circle shadows on blocks underneath the top block can be chopped up into at most 4 pieces */
#define SHADOW_MAX_PER_SUB_BLOCK (4 * 4)
/* Circle shadows use at most:
- 4 vertices for top most block
- MAX_PER_SUB_BLOCK for everyblock underneath the top block */
#define SHADOW_MAX_PER_COLUMN (4 + SHADOW_MAX_PER_SUB_BLOCK * (SHADOW_MAX_RANGE - 1))
/* Circle shadows may be split across (x,z), (x,z+1), (x+1,z), (x+1,z+1) */
#define SHADOW_MAX_VERTS 4 * SHADOW_MAX_PER_COLUMN
static cc_bool lequal(float a, float b) { return a < b || Math_AbsF(a - b) < 0.001f; }
static void EntityShadow_DrawCoords(struct VertexTextured** vertices, struct Entity* e, struct ShadowData* data, float x1, float z1, float x2, float z2) {
PackedCol col;
@ -72,7 +86,8 @@ static void EntityShadow_DrawCircle(struct VertexTextured** vertices, struct Ent
min = Blocks.MinBB[data[0].Block]; max = Blocks.MaxBB[data[0].Block];
EntityShadow_DrawCoords(vertices, e, &data[0], x + min.X, z + min.Z, x + max.X, z + max.Z);
for (i = 1; i < 4; i++) {
for (i = 1; i < 4; i++)
{
if (data[i].Block == BLOCK_AIR) return;
nMin = Blocks.MinBB[data[i].Block]; nMax = Blocks.MaxBB[data[i].Block];
@ -112,7 +127,8 @@ static cc_bool EntityShadow_GetBlocks(struct Entity* e, int x, int y, int z, str
posY = e->Position.Y;
outside = !World_ContainsXZ(x, z);
for (i = 0; y >= 0 && i < 4; y--) {
for (i = 0; y >= 0 && i < 4; y--)
{
if (!outside) {
block = World_GetBlock(x, y, z);
} else if (y == Env.EdgeHeight - 1) {
@ -146,10 +162,9 @@ static cc_bool EntityShadow_GetBlocks(struct Entity* e, int x, int y, int z, str
}
static void EntityShadow_Draw(struct Entity* e) {
struct VertexTextured vertices[128];
struct VertexTextured vertices[128]; /* TODO this is less than maxVertes */
struct VertexTextured* ptr;
struct ShadowData data[4];
GfxResourceID vb;
Vec3 pos;
float radius;
int y, count;
@ -163,16 +178,13 @@ static void EntityShadow_Draw(struct Entity* e) {
shadow_radius = radius / 16.0f;
shadow_uvScale = 16.0f / (radius * 2.0f);
/* TODO: Should shadow component use its own VB? */
ptr = vertices;
if (Entities.ShadowsMode == SHADOW_MODE_SNAP_TO_BLOCK) {
vb = Gfx_texVb;
x1 = Math_Floor(pos.X); z1 = Math_Floor(pos.Z);
if (!EntityShadow_GetBlocks(e, x1, y, z1, data)) return;
EntityShadow_DrawSquareShadow(&ptr, data[0].Y, x1, z1);
} else {
vb = Models.Vb;
x1 = Math_Floor(pos.X - shadow_radius); z1 = Math_Floor(pos.Z - shadow_radius);
x2 = Math_Floor(pos.X + shadow_radius); z2 = Math_Floor(pos.Z + shadow_radius);
@ -198,7 +210,7 @@ static void EntityShadow_Draw(struct Entity* e) {
}
count = (int)(ptr - vertices);
Gfx_SetDynamicVbData(vb, vertices, count);
Gfx_SetDynamicVbData(shadows_VB, vertices, count);
Gfx_DrawVb_IndexedTris(count);
}
@ -226,7 +238,7 @@ static void EntityShadows_MakeTexture(void) {
row[x] = dist < sh_half * sh_half ? color : 0;
}
}
Gfx_RecreateTexture(&shadows_tex, &bmp, 0, false);
shadows_tex = Gfx_CreateTexture(&bmp, 0, false);
}
void EntityShadows_Render(void) {
@ -234,7 +246,10 @@ void EntityShadows_Render(void) {
if (Entities.ShadowsMode == SHADOW_MODE_NONE) return;
shadows_boundTex = false;
if (!shadows_tex) EntityShadows_MakeTexture();
if (!shadows_tex)
EntityShadows_MakeTexture();
if (!shadows_VB)
shadows_VB = Gfx_CreateDynamicVb(VERTEX_FORMAT_TEXTURED, SHADOW_MAX_VERTS);
Gfx_SetAlphaArgBlend(true);
Gfx_SetDepthWrite(false);
@ -257,19 +272,193 @@ void EntityShadows_Render(void) {
}
/*########################################################################################################################*
*-----------------------------------------------------Entity nametag------------------------------------------------------*
*#########################################################################################################################*/
static GfxResourceID names_VB;
#define NAME_IS_EMPTY -30000
#define NAME_OFFSET 3 /* offset of back layer of name above an entity */
static void MakeNameTexture(struct Entity* e) {
cc_string colorlessName; char colorlessBuffer[STRING_SIZE];
BitmapCol shadowColor = BitmapCol_Make(80, 80, 80, 255);
BitmapCol origWhiteColor;
struct DrawTextArgs args;
struct FontDesc font;
struct Context2D ctx;
int width, height;
cc_string name;
/* Names are always drawn using default.png font */
Font_MakeBitmapped(&font, 24, FONT_FLAGS_NONE);
/* Don't want DPI scaling or padding */
font.size = 24; font.height = 24;
name = String_FromRawArray(e->NameRaw);
DrawTextArgs_Make(&args, &name, &font, false);
width = Drawer2D_TextWidth(&args);
if (!width) {
e->NameTex.ID = 0;
e->NameTex.X = NAME_IS_EMPTY;
} else {
String_InitArray(colorlessName, colorlessBuffer);
width += NAME_OFFSET;
height = Drawer2D_TextHeight(&args) + NAME_OFFSET;
Context2D_Alloc(&ctx, width, height);
{
origWhiteColor = Drawer2D.Colors['f'];
Drawer2D.Colors['f'] = shadowColor;
Drawer2D_WithoutColors(&colorlessName, &name);
args.text = colorlessName;
Context2D_DrawText(&ctx, &args, NAME_OFFSET, NAME_OFFSET);
Drawer2D.Colors['f'] = origWhiteColor;
args.text = name;
Context2D_DrawText(&ctx, &args, 0, 0);
}
Context2D_MakeTexture(&e->NameTex, &ctx);
Context2D_Free(&ctx);
}
}
static void DrawName(struct Entity* e) {
struct VertexTextured* vertices;
struct Model* model;
struct Matrix mat;
Vec3 pos;
float scale;
Vec2 size;
if (!e->VTABLE->ShouldRenderName(e)) return;
if (e->NameTex.X == NAME_IS_EMPTY) return;
if (!e->NameTex.ID) MakeNameTexture(e);
Gfx_BindTexture(e->NameTex.ID);
if (!names_VB)
names_VB = Gfx_CreateDynamicVb(VERTEX_FORMAT_TEXTURED, 4);
model = e->Model;
Vec3_TransformY(&pos, model->GetNameY(e), &e->Transform);
scale = model->nameScale * e->ModelScale.Y;
scale = scale > 1.0f ? (1.0f/70.0f) : (scale/70.0f);
size.X = e->NameTex.Width * scale; size.Y = e->NameTex.Height * scale;
if (Entities.NamesMode == NAME_MODE_ALL_UNSCALED && LocalPlayer_Instance.Hacks.CanSeeAllNames) {
Matrix_Mul(&mat, &Gfx.View, &Gfx.Projection); /* TODO: This mul is slow, avoid it */
/* Get W component of transformed position */
scale = pos.X * mat.row1.W + pos.Y * mat.row2.W + pos.Z * mat.row3.W + mat.row4.W;
size.X *= scale * 0.2f; size.Y *= scale * 0.2f;
}
Gfx_SetVertexFormat(VERTEX_FORMAT_TEXTURED);
vertices = (struct VertexTextured*)Gfx_LockDynamicVb(names_VB, VERTEX_FORMAT_TEXTURED, 4);
Particle_DoRender(&size, &pos, &e->NameTex.uv, PACKEDCOL_WHITE, vertices);
Gfx_UnlockDynamicVb(names_VB);
Gfx_DrawVb_IndexedTris(4);
}
void EntityNames_Delete(struct Entity* e) {
Gfx_DeleteTexture(&e->NameTex.ID);
e->NameTex.X = 0; /* X is used as an 'empty name' flag */
}
/*########################################################################################################################*
*-----------------------------------------------------Names rendering-----------------------------------------------------*
*#########################################################################################################################*/
static EntityID closestEntityId;
void EntityNames_Render(void) {
struct LocalPlayer* p = &LocalPlayer_Instance;
cc_bool hadFog;
int i;
if (Entities.NamesMode == NAME_MODE_NONE) return;
closestEntityId = Entities_GetClosest(&p->Base);
if (!p->Hacks.CanSeeAllNames || Entities.NamesMode != NAME_MODE_ALL) return;
Gfx_SetAlphaTest(true);
hadFog = Gfx_GetFog();
if (hadFog) Gfx_SetFog(false);
for (i = 0; i < ENTITIES_MAX_COUNT; i++)
{
if (!Entities.List[i]) continue;
if (i != closestEntityId || i == ENTITIES_SELF_ID) {
DrawName(Entities.List[i]);
}
}
Gfx_SetAlphaTest(false);
if (hadFog) Gfx_SetFog(true);
}
void EntityNames_RenderHovered(void) {
struct LocalPlayer* p = &LocalPlayer_Instance;
cc_bool allNames, hadFog;
int i;
if (Entities.NamesMode == NAME_MODE_NONE) return;
allNames = !(Entities.NamesMode == NAME_MODE_HOVERED || Entities.NamesMode == NAME_MODE_ALL)
&& p->Hacks.CanSeeAllNames;
Gfx_SetAlphaTest(true);
Gfx_SetDepthTest(false);
hadFog = Gfx_GetFog();
if (hadFog) Gfx_SetFog(false);
for (i = 0; i < ENTITIES_MAX_COUNT; i++)
{
if (!Entities.List[i]) continue;
if ((i == closestEntityId || allNames) && i != ENTITIES_SELF_ID) {
DrawName(Entities.List[i]);
}
}
Gfx_SetAlphaTest(false);
Gfx_SetDepthTest(true);
if (hadFog) Gfx_SetFog(true);
}
static void DeleteAllNameTextures(void) {
int i;
for (i = 0; i < ENTITIES_MAX_COUNT; i++)
{
if (!Entities.List[i]) continue;
EntityNames_Delete(Entities.List[i]);
}
}
static void EntityNames_ChatFontChanged(void* obj) {
DeleteAllNameTextures();
}
/*########################################################################################################################*
*-----------------------------------------------Entity renderers component------------------------------------------------*
*#########################################################################################################################*/
static void EntityRenderers_ContextLost(void* obj) {
Gfx_DeleteTexture(&shadows_tex);
Gfx_DeleteDynamicVb(&shadows_VB);
Gfx_DeleteDynamicVb(&names_VB);
DeleteAllNameTextures();
}
static void EntityRenderers_Init(void) {
Event_Register_(&GfxEvents.ContextLost, NULL, EntityRenderers_ContextLost);
Event_Register_(&GfxEvents.ContextLost, NULL, EntityRenderers_ContextLost);
Event_Register_(&ChatEvents.FontChanged, NULL, EntityNames_ChatFontChanged);
}
static void EntityRenderers_Free(void) {
Gfx_DeleteTexture(&shadows_tex);
EntityRenderers_ContextLost(NULL);
}
struct IGameComponent EntityRenderers_Component = {

View File

@ -1,13 +1,21 @@
#ifndef CC_ENTITYRENDERERS_H
#define CC_ENTITYRENDERERS_H
#include "Core.h"
/* Renders supporting objects for entities (shadows)
/* Renders supporting objects for entities (shadows and names)
Copyright 2014-2023 ClassiCube | Licensed under BSD-3
*/
struct IGameComponent;
extern struct IGameComponent EntityRenderers_Component;
struct Entity;
/* Draws shadows under entities, depending on Entities.ShadowsMode */
void EntityShadows_Render(void);
/* Deletes the texture containing the entity's nametag */
void EntityNames_Delete(struct Entity* e);
/* Renders the name tags of entities, depending on Entities.NamesMode */
void EntityNames_Render(void);
/* Renders hovered entity name tags (these appears through blocks) */
void EntityNames_RenderHovered(void);
#endif

View File

@ -272,11 +272,42 @@ static GfxResourceID skybox_tex, skybox_vb;
#define SKYBOX_COUNT (6 * 4)
cc_bool EnvRenderer_ShouldRenderSkybox(void) { return skybox_tex && !EnvRenderer_Minimal; }
static void AllocateSkyboxVB(void) {
static const struct VertexTextured vertices[SKYBOX_COUNT] = {
/* Front quad */
{ -1, -1, -1, 0, 0.25f, 1.00f }, { 1, -1, -1, 0, 0.50f, 1.00f },
{ 1, 1, -1, 0, 0.50f, 0.50f }, { -1, 1, -1, 0, 0.25f, 0.50f },
/* Left quad */
{ -1, -1, 1, 0, 0.00f, 1.00f }, { -1, -1, -1, 0, 0.25f, 1.00f },
{ -1, 1, -1, 0, 0.25f, 0.50f }, { -1, 1, 1, 0, 0.00f, 0.50f },
/* Back quad */
{ 1, -1, 1, 0, 0.75f, 1.00f }, { -1, -1, 1, 0, 1.00f, 1.00f },
{ -1, 1, 1, 0, 1.00f, 0.50f }, { 1, 1, 1, 0, 0.75f, 0.50f },
/* Right quad */
{ 1, -1, -1, 0, 0.50f, 1.00f }, { 1, -1, 1, 0, 0.75f, 1.00f },
{ 1, 1, 1, 0, 0.75f, 0.50f }, { 1, 1, -1, 0, 0.50f, 0.50f },
/* Top quad */
{ 1, 1, -1, 0, 0.50f, 0.50f }, { 1, 1, 1, 0, 0.50f, 0.00f },
{ -1, 1, 1, 0, 0.25f, 0.00f }, { -1, 1, -1, 0, 0.25f, 0.50f },
/* Bottom quad */
{ 1, -1, -1, 0, 0.75f, 0.50f }, { 1, -1, 1, 0, 0.75f, 0.00f },
{ -1, -1, 1, 0, 0.50f, 0.00f }, { -1, -1, -1, 0, 0.50f, 0.50f },
};
struct VertexTextured* data;
int i;
data = (struct VertexTextured*)Gfx_RecreateAndLockVb(&skybox_vb,
VERTEX_FORMAT_TEXTURED, SKYBOX_COUNT);
Mem_Copy(data, vertices, sizeof(vertices));
for (i = 0; i < SKYBOX_COUNT; i++) { data[i].Col = Env.SkyboxCol; }
Gfx_UnlockVb(skybox_vb);
}
void EnvRenderer_RenderSkybox(void) {
struct Matrix m, rotX, rotY, view;
float rotTime;
Vec3 pos;
if (!skybox_vb) return;
if (!skybox_vb) AllocateSkyboxVB();
Gfx_SetDepthWrite(false);
Gfx_BindTexture(skybox_tex);
@ -302,42 +333,6 @@ void EnvRenderer_RenderSkybox(void) {
Gfx_SetDepthWrite(true);
}
static void UpdateSkybox(void) {
static const struct VertexTextured vertices[SKYBOX_COUNT] = {
/* Front quad */
{ -1, -1, -1, 0, 0.25f, 1.00f }, { 1, -1, -1, 0, 0.50f, 1.00f },
{ 1, 1, -1, 0, 0.50f, 0.50f }, { -1, 1, -1, 0, 0.25f, 0.50f },
/* Left quad */
{ -1, -1, 1, 0, 0.00f, 1.00f }, { -1, -1, -1, 0, 0.25f, 1.00f },
{ -1, 1, -1, 0, 0.25f, 0.50f }, { -1, 1, 1, 0, 0.00f, 0.50f },
/* Back quad */
{ 1, -1, 1, 0, 0.75f, 1.00f }, { -1, -1, 1, 0, 1.00f, 1.00f },
{ -1, 1, 1, 0, 1.00f, 0.50f }, { 1, 1, 1, 0, 0.75f, 0.50f },
/* Right quad */
{ 1, -1, -1, 0, 0.50f, 1.00f }, { 1, -1, 1, 0, 0.75f, 1.00f },
{ 1, 1, 1, 0, 0.75f, 0.50f }, { 1, 1, -1, 0, 0.50f, 0.50f },
/* Top quad */
{ 1, 1, -1, 0, 0.50f, 0.50f }, { 1, 1, 1, 0, 0.50f, 0.00f },
{ -1, 1, 1, 0, 0.25f, 0.00f }, { -1, 1, -1, 0, 0.25f, 0.50f },
/* Bottom quad */
{ 1, -1, -1, 0, 0.75f, 0.50f }, { 1, -1, 1, 0, 0.75f, 0.00f },
{ -1, -1, 1, 0, 0.50f, 0.00f }, { -1, -1, -1, 0, 0.50f, 0.50f },
};
struct VertexTextured* data;
int i;
Gfx_DeleteVb(&skybox_vb);
if (Gfx.LostContext) return;
if (EnvRenderer_Minimal) return;
data = (struct VertexTextured*)Gfx_RecreateAndLockVb(&skybox_vb,
VERTEX_FORMAT_TEXTURED, SKYBOX_COUNT);
Mem_Copy(data, vertices, sizeof(vertices));
for (i = 0; i < SKYBOX_COUNT; i++) { data[i].Col = Env.SkyboxCol; }
Gfx_UnlockVb(skybox_vb);
}
/*########################################################################################################################*
*----------------------------------------------------------Weather--------------------------------------------------------*
*#########################################################################################################################*/
@ -834,7 +829,7 @@ static void UpdateAll(void) {
UpdateMapEdges();
UpdateClouds();
UpdateSky();
UpdateSkybox();
Gfx_DeleteVb(&skybox_vb);
EnvRenderer_UpdateFog();
Gfx_DeleteDynamicVb(&weather_vb);
@ -898,7 +893,7 @@ static void OnEnvVariableChanged(void* obj, int envVar) {
UpdateSky();
UpdateClouds();
} else if (envVar == ENV_VAR_SKYBOX_COLOR) {
UpdateSkybox();
Gfx_DeleteVb(&skybox_vb);
}
}

View File

@ -463,7 +463,7 @@ static void Game_Render3D(double delta, float t) {
AxisLinesRenderer_Render();
Entities_RenderModels(delta, t);
Entities_RenderNames();
EntityNames_Render();
Particles_Render(t);
Camera.Active->GetPickedBlock(&Game_SelectedPos); /* TODO: only pick when necessary */
@ -496,7 +496,7 @@ static void Game_Render3D(double delta, float t) {
}
Selections_Render();
Entities_RenderHoveredNames();
EntityNames_RenderHovered();
Camera_KeyLookUpdate();
InputHandler_Tick();
if (!Game_HideGui) HeldBlockRenderer_Render(delta);
@ -573,6 +573,7 @@ static void Game_RenderFrame(double delta) {
Gfx_RecreateContext();
/* all good, context is back */
} else {
Game.Time += delta; /* TODO: Not set in two places? */
Server.Tick(NULL);
Thread_Sleep(16);
return;

View File

@ -56,7 +56,6 @@ CC_VAR extern struct _GfxData {
} Gfx;
extern GfxResourceID Gfx_defaultIb;
extern GfxResourceID Gfx_quadVb, Gfx_texVb;
extern const cc_string Gfx_LowPerfMessage;
#define ICOUNT(verticesCount) (((verticesCount) >> 2) * 6)

View File

@ -434,6 +434,8 @@ static GfxResourceID Gfx_AllocDynamicVb(VertexFormat fmt, int maxVertices) {
return AllocBuffer(maxVertices, strideSizes[fmt]);
}
void Gfx_BindDynamicVb(GfxResourceID vb) { Gfx_BindVb(vb); }
void* Gfx_LockDynamicVb(GfxResourceID vb, VertexFormat fmt, int count) {
return vb;
}

View File

@ -190,6 +190,8 @@ static GfxResourceID Gfx_AllocDynamicVb(VertexFormat fmt, int maxVertices) {
return memalign(16, maxVertices * strideSizes[fmt]);
}
void Gfx_BindDynamicVb(GfxResourceID vb) { Gfx_BindVb(vb); }
void* Gfx_LockDynamicVb(GfxResourceID vb, VertexFormat fmt, int count) {
vb_size = count * strideSizes[fmt];
return vb;

View File

@ -320,6 +320,8 @@ static GfxResourceID Gfx_AllocDynamicVb(VertexFormat fmt, int maxVertices) {
return memalign(16, maxVertices * strideSizes[fmt]);
}
void Gfx_BindDynamicVb(GfxResourceID vb) { Gfx_BindVb(vb); }
void* Gfx_LockDynamicVb(GfxResourceID vb, VertexFormat fmt, int count) {
vb_size = count * strideSizes[fmt];
return vb;

View File

@ -538,6 +538,8 @@ static GfxResourceID Gfx_AllocDynamicVb(VertexFormat fmt, int maxVertices)
return rsxMemalign(128, maxVertices * strideSizes[fmt]);
}
void Gfx_BindDynamicVb(GfxResourceID vb) { Gfx_BindVb(vb); }
void* Gfx_LockDynamicVb(GfxResourceID vb, VertexFormat fmt, int count) {
vb_size = count * strideSizes[fmt];
return vb;

View File

@ -311,6 +311,8 @@ static GfxResourceID Gfx_AllocDynamicVb(VertexFormat fmt, int maxVertices) {
return memalign(16, maxVertices * strideSizes[fmt]);
}
void Gfx_BindDynamicVb(GfxResourceID vb) { Gfx_BindVb(vb); }
void* Gfx_LockDynamicVb(GfxResourceID vb, VertexFormat fmt, int count) {
vb_size = count * strideSizes[fmt];
return vb;

View File

@ -915,6 +915,8 @@ static GfxResourceID Gfx_AllocDynamicVb(VertexFormat fmt, int maxVertices) {
return GPUBuffer_Alloc(maxVertices * strideSizes[fmt]);
}
void Gfx_BindDynamicVb(GfxResourceID vb) { Gfx_BindVb(vb); }
void* Gfx_LockDynamicVb(GfxResourceID vb, VertexFormat fmt, int count) {
struct GPUBuffer* buffer = (struct GPUBuffer*)vb;
return buffer->data;

View File

@ -453,6 +453,8 @@ static GfxResourceID Gfx_AllocDynamicVb(VertexFormat fmt, int maxVertices) {
return AllocBuffer(maxVertices, strideSizes[fmt]);
}
void Gfx_BindDynamicVb(GfxResourceID vb) { Gfx_BindVb(vb); }
void* Gfx_LockDynamicVb(GfxResourceID vb, VertexFormat fmt, int count) {
return vb;
}

View File

@ -77,8 +77,8 @@ static int RunProgram(int argc, char** argv) {
#ifdef _MSC_VER
/* NOTE: Make sure to comment this out before pushing a commit */
//cc_string rawArgs = String_FromConst("UnknownShadow200 fffff 127.0.0.1 25565");
cc_string rawArgs = String_FromConst("UnknownShadow200");
argsCount = String_UNSAFE_Split(&rawArgs, ' ', args, 4);
//cc_string rawArgs = String_FromConst("UnknownShadow200");
//argsCount = String_UNSAFE_Split(&rawArgs, ' ', args, 4);
#endif
if (argsCount == 0) {

View File

@ -13,7 +13,7 @@
struct _GfxData Gfx;
GfxResourceID Gfx_defaultIb;
GfxResourceID Gfx_quadVb, Gfx_texVb;
static GfxResourceID Gfx_quadVb, Gfx_texVb;
const cc_string Gfx_LowPerfMessage = String_FromConst("&eRunning in reduced performance mode (game minimised or hidden)");
static const int strideSizes[] = { SIZEOF_VERTEX_COLOURED, SIZEOF_VERTEX_TEXTURED };