mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-09 07:18:34 -04:00
Merge pull request #1090 from UnknownShadow200/GfxRewrite
Graphics rendering backend related changes
This commit is contained in:
commit
8a20397b6e
@ -61,8 +61,8 @@ build_win64() {
|
||||
|
||||
# ----------------------------- compile linux
|
||||
# I installed gcc and gcc-multilib packages
|
||||
NIX32_FLAGS="-no-pie -fno-pie -m32 -fvisibility=hidden -rdynamic -DCC_BUILD_ICON"
|
||||
NIX64_FLAGS="-no-pie -fno-pie -m64 -fvisibility=hidden -rdynamic -DCC_BUILD_ICON"
|
||||
NIX32_FLAGS="-no-pie -fno-pie -m32 -fvisibility=hidden -fcf-protection=none -rdynamic -DCC_BUILD_ICON"
|
||||
NIX64_FLAGS="-no-pie -fno-pie -m64 -fvisibility=hidden -fcf-protection=none -rdynamic -DCC_BUILD_ICON"
|
||||
|
||||
build_nix32() {
|
||||
echo "Building linux32.."
|
||||
|
@ -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) {
|
||||
|
200
src/Entity.c
200
src/Entity.c
@ -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,103 +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[4];
|
||||
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;
|
||||
}
|
||||
|
||||
Particle_DoRender(&size, &pos, &e->NameTex.uv, PACKEDCOL_WHITE, vertices);
|
||||
Gfx_SetVertexFormat(VERTEX_FORMAT_TEXTURED);
|
||||
Gfx_UpdateDynamicVb_IndexedTris(Gfx_texVb, vertices, 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-------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
@ -529,7 +436,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;
|
||||
@ -549,83 +455,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];
|
||||
@ -747,7 +587,7 @@ struct IGameComponent TabList_Component = {
|
||||
|
||||
static void Player_Despawn(struct Entity* e) {
|
||||
DeleteSkin(e);
|
||||
Entity_ContextLost(e);
|
||||
EntityNames_Delete(e);
|
||||
}
|
||||
|
||||
|
||||
@ -868,9 +708,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) {
|
||||
@ -894,7 +733,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;
|
||||
@ -1150,19 +989,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));
|
||||
@ -1175,10 +1014,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));
|
||||
|
@ -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 */
|
||||
|
@ -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,8 @@ static void EntityShadow_Draw(struct Entity* e) {
|
||||
}
|
||||
|
||||
count = (int)(ptr - vertices);
|
||||
Gfx_UpdateDynamicVb_IndexedTris(vb, vertices, count);
|
||||
Gfx_SetDynamicVbData(shadows_VB, vertices, count);
|
||||
Gfx_DrawVb_IndexedTris(count);
|
||||
}
|
||||
|
||||
|
||||
@ -225,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) {
|
||||
@ -233,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);
|
||||
@ -256,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 = {
|
||||
|
@ -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
|
||||
|
@ -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--------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
@ -347,7 +342,10 @@ static double weather_accumulator;
|
||||
static IVec3 lastPos;
|
||||
|
||||
#define WEATHER_EXTENT 4
|
||||
#define WEATHER_VERTS_COUNT 8 * (WEATHER_EXTENT * 2 + 1) * (WEATHER_EXTENT * 2 + 1)
|
||||
#define WEATHER_VERTS 8 /* 2 quads per tile */
|
||||
#define WEATHER_RANGE (WEATHER_EXTENT * 2 + 1)
|
||||
|
||||
#define WEATHER_VERTS_COUNT WEATHER_RANGE * WEATHER_RANGE * WEATHER_VERTS
|
||||
#define Weather_Pack(x, z) ((x) * World.Length + (z))
|
||||
|
||||
static void InitWeatherHeightmap(void) {
|
||||
@ -428,26 +426,31 @@ static float CalcRainAlphaAt(float x) {
|
||||
return 178 + falloff * Env.WeatherFade;
|
||||
}
|
||||
|
||||
struct RainCoord { int dx, dz; float y; };
|
||||
static RNGState snowDirRng;
|
||||
|
||||
void EnvRenderer_RenderWeather(double deltaTime) {
|
||||
struct VertexTextured vertices[WEATHER_VERTS_COUNT];
|
||||
struct RainCoord coords[WEATHER_RANGE * WEATHER_RANGE];
|
||||
int i, weather, numCoords = 0;
|
||||
struct VertexTextured* v;
|
||||
int weather, vCount;
|
||||
IVec3 pos;
|
||||
cc_bool moved, particles;
|
||||
float speed, vOffsetBase, vOffset;
|
||||
IVec3 pos;
|
||||
|
||||
PackedCol col;
|
||||
PackedCol color;
|
||||
int dist, dx, dz, x, z;
|
||||
float alpha, y, height;
|
||||
float uOffset1, uOffset2;
|
||||
float uOffset1, uOffset2, uSpeed;
|
||||
float worldV, v1, v2, vPlane1Offset;
|
||||
float x1,y1,z1, x2,y2,z2;
|
||||
|
||||
weather = Env.Weather;
|
||||
if (weather == WEATHER_SUNNY) return;
|
||||
if (!Weather_Heightmap) InitWeatherHeightmap();
|
||||
Gfx_BindTexture(weather == WEATHER_RAINY ? rain_tex : snow_tex);
|
||||
|
||||
if (!Weather_Heightmap)
|
||||
InitWeatherHeightmap();
|
||||
if (!weather_vb)
|
||||
weather_vb = Gfx_CreateDynamicVb(VERTEX_FORMAT_TEXTURED, WEATHER_VERTS_COUNT);
|
||||
|
||||
IVec3_Floor(&pos, &Camera.CurrentPos);
|
||||
moved = pos.X != lastPos.X || pos.Y != lastPos.Y || pos.Z != lastPos.Z;
|
||||
@ -457,75 +460,93 @@ void EnvRenderer_RenderWeather(double deltaTime) {
|
||||
pos.Y += 64;
|
||||
pos.Y = max(World.Height, pos.Y);
|
||||
|
||||
speed = (weather == WEATHER_RAINY ? 1.0f : 0.2f) * Env.WeatherSpeed;
|
||||
vOffsetBase = (float)Game.Time * speed;
|
||||
vPlane1Offset = weather == WEATHER_RAINY ? 0 : 0.25f; /* Offset v on 1 plane while snowing to avoid the unnatural mirrored texture effect */
|
||||
particles = weather == WEATHER_RAINY;
|
||||
weather_accumulator += deltaTime;
|
||||
|
||||
v = vertices;
|
||||
col = Env.SunCol;
|
||||
particles = weather == WEATHER_RAINY && (weather_accumulator >= 0.25 || moved);
|
||||
|
||||
for (dx = -WEATHER_EXTENT; dx <= WEATHER_EXTENT; dx++) {
|
||||
for (dz = -WEATHER_EXTENT; dz <= WEATHER_EXTENT; dz++) {
|
||||
x = pos.X + dx; z = pos.Z + dz;
|
||||
|
||||
y = GetRainHeight(x, z);
|
||||
height = pos.Y - y;
|
||||
if (height <= 0) continue;
|
||||
if (pos.Y <= y) continue;
|
||||
if (particles) Particles_RainSnowEffect((float)x, y, (float)z);
|
||||
|
||||
if (particles && (weather_accumulator >= 0.25 || moved)) {
|
||||
Particles_RainSnowEffect((float)x, y, (float)z);
|
||||
}
|
||||
|
||||
dist = dx * dx + dz * dz;
|
||||
alpha = CalcRainAlphaAt((float)dist);
|
||||
Math_Clamp(alpha, 0.0f, 255.0f);
|
||||
col = (col & PACKEDCOL_RGB_MASK) | PackedCol_A_Bits(alpha);
|
||||
|
||||
uOffset1 = 0;
|
||||
uOffset2 = 0;
|
||||
if (weather == WEATHER_SNOWY) {
|
||||
Random_Seed(&snowDirRng, (x + 1217 * z) & 0x7fffffff);
|
||||
/* Multiply horizontal speed by a random float from -1 to 1 */
|
||||
uOffset1 = ((float)Game.Time * (Random_Float(&snowDirRng) * 2 + -1)) * Env.WeatherSpeed * 0.5f;
|
||||
uOffset2 = ((float)Game.Time * (Random_Float(&snowDirRng) * 2 + -1)) * Env.WeatherSpeed * 0.5f;
|
||||
/* Multiply vertical speed by a random float from 1.0 to 0.25 */
|
||||
vOffset = vOffsetBase * (float)(Random_Float(&snowDirRng) * (1.0f - 0.25f) + 0.25f);
|
||||
} else {
|
||||
vOffset = vOffsetBase;
|
||||
}
|
||||
|
||||
worldV = vOffset + (z & 1) / 2.0f - (x & 0x0F) / 16.0f;
|
||||
v1 = y / 6.0f + worldV;
|
||||
v2 = (y + height) / 6.0f + worldV;
|
||||
x1 = (float)x; y1 = (float)y; z1 = (float)z;
|
||||
x2 = (float)(x + 1); y2 = (float)(y + height); z2 = (float)(z + 1);
|
||||
|
||||
v->X = x1; v->Y = y1; v->Z = z1; v->Col = col; v->U = 0.0f + uOffset1; v->V = v1+vPlane1Offset; v++;
|
||||
v->X = x1; v->Y = y2; v->Z = z1; v->Col = col; v->U = 0.0f + uOffset1; v->V = v2+vPlane1Offset; v++;
|
||||
v->X = x2; v->Y = y2; v->Z = z2; v->Col = col; v->U = 1.0f + uOffset1; v->V = v2+vPlane1Offset; v++;
|
||||
v->X = x2; v->Y = y1; v->Z = z2; v->Col = col; v->U = 1.0f + uOffset1; v->V = v1+vPlane1Offset; v++;
|
||||
|
||||
v->X = x2; v->Y = y1; v->Z = z1; v->Col = col; v->U = 1.0f + uOffset2; v->V = v1; v++;
|
||||
v->X = x2; v->Y = y2; v->Z = z1; v->Col = col; v->U = 1.0f + uOffset2; v->V = v2; v++;
|
||||
v->X = x1; v->Y = y2; v->Z = z2; v->Col = col; v->U = 0.0f + uOffset2; v->V = v2; v++;
|
||||
v->X = x1; v->Y = y1; v->Z = z2; v->Col = col; v->U = 0.0f + uOffset2; v->V = v1; v++;
|
||||
coords[numCoords].dx = dx;
|
||||
coords[numCoords].y = y;
|
||||
coords[numCoords].dz = dz;
|
||||
numCoords++;
|
||||
}
|
||||
}
|
||||
|
||||
if (particles && (weather_accumulator >= 0.25f || moved)) {
|
||||
weather_accumulator = 0;
|
||||
}
|
||||
if (v == vertices) return;
|
||||
Gfx_BindTexture(weather == WEATHER_RAINY ? rain_tex : snow_tex);
|
||||
if (particles) weather_accumulator = 0;
|
||||
if (!numCoords) return;
|
||||
|
||||
Gfx_SetAlphaTest(false);
|
||||
Gfx_SetDepthWrite(false);
|
||||
Gfx_SetAlphaArgBlend(true);
|
||||
|
||||
Gfx_SetVertexFormat(VERTEX_FORMAT_TEXTURED);
|
||||
vCount = (int)(v - vertices);
|
||||
Gfx_UpdateDynamicVb_IndexedTris(weather_vb, vertices, vCount);
|
||||
v = (struct VertexTextured*)Gfx_LockDynamicVb(weather_vb,
|
||||
VERTEX_FORMAT_TEXTURED, numCoords * WEATHER_VERTS);
|
||||
|
||||
color = Env.SunCol;
|
||||
speed = (weather == WEATHER_RAINY ? 1.0f : 0.2f) * Env.WeatherSpeed;
|
||||
|
||||
vOffsetBase = (float)Game.Time * speed;
|
||||
vPlane1Offset = weather == WEATHER_RAINY ? 0 : 0.25f; /* Offset v on 1 plane while snowing to avoid the unnatural mirrored texture effect */
|
||||
|
||||
for (i = 0; i < numCoords; i++)
|
||||
{
|
||||
dx = coords[i].dx;
|
||||
y = coords[i].y;
|
||||
dz = coords[i].dz;
|
||||
|
||||
height = pos.Y - y;
|
||||
|
||||
dist = dx * dx + dz * dz;
|
||||
alpha = CalcRainAlphaAt((float)dist);
|
||||
Math_Clamp(alpha, 0.0f, 255.0f);
|
||||
color = (color & PACKEDCOL_RGB_MASK) | PackedCol_A_Bits(alpha);
|
||||
|
||||
x = dx + pos.X;
|
||||
z = dz + pos.Z;
|
||||
|
||||
uOffset1 = 0;
|
||||
uOffset2 = 0;
|
||||
if (weather == WEATHER_SNOWY) {
|
||||
Random_Seed(&snowDirRng, (x + 1217 * z) & 0x7fffffff);
|
||||
|
||||
/* Multiply horizontal speed by a random float from -1 to 1 */
|
||||
uSpeed = (float)Game.Time * Env.WeatherSpeed * 0.5f;
|
||||
uOffset1 = uSpeed * (Random_Float(&snowDirRng) * 2 + -1);
|
||||
uOffset2 = uSpeed * (Random_Float(&snowDirRng) * 2 + -1);
|
||||
|
||||
/* Multiply vertical speed by a random float from 1.0 to 0.25 */
|
||||
vOffset = vOffsetBase * (float)(Random_Float(&snowDirRng) * (1.0f - 0.25f) + 0.25f);
|
||||
} else {
|
||||
vOffset = vOffsetBase;
|
||||
}
|
||||
|
||||
worldV = vOffset + (z & 1) / 2.0f - (x & 0x0F) / 16.0f;
|
||||
v1 = y / 6.0f + worldV;
|
||||
v2 = (y + height) / 6.0f + worldV;
|
||||
x1 = (float)x; y1 = (float)y; z1 = (float)z;
|
||||
x2 = (float)(x + 1); y2 = (float)(y + height); z2 = (float)(z + 1);
|
||||
|
||||
v->X = x1; v->Y = y1; v->Z = z1; v->Col = color; v->U = uOffset1; v->V = v1 + vPlane1Offset; v++;
|
||||
v->X = x1; v->Y = y2; v->Z = z1; v->Col = color; v->U = uOffset1; v->V = v2 + vPlane1Offset; v++;
|
||||
v->X = x2; v->Y = y2; v->Z = z2; v->Col = color; v->U = uOffset1 + 1.0f; v->V = v2 + vPlane1Offset; v++;
|
||||
v->X = x2; v->Y = y1; v->Z = z2; v->Col = color; v->U = uOffset1 + 1.0f; v->V = v1 + vPlane1Offset; v++;
|
||||
|
||||
v->X = x2; v->Y = y1; v->Z = z1; v->Col = color; v->U = uOffset2 + 1.0f; v->V = v1; v++;
|
||||
v->X = x2; v->Y = y2; v->Z = z1; v->Col = color; v->U = uOffset2 + 1.0f; v->V = v2; v++;
|
||||
v->X = x1; v->Y = y2; v->Z = z2; v->Col = color; v->U = uOffset2; v->V = v2; v++;
|
||||
v->X = x1; v->Y = y1; v->Z = z2; v->Col = color; v->U = uOffset2; v->V = v1; v++;
|
||||
}
|
||||
|
||||
Gfx_UnlockDynamicVb(weather_vb);
|
||||
Gfx_DrawVb_IndexedTris(numCoords * WEATHER_VERTS);
|
||||
|
||||
Gfx_SetAlphaArgBlend(false);
|
||||
Gfx_SetDepthWrite(true);
|
||||
@ -808,13 +829,12 @@ static void UpdateAll(void) {
|
||||
UpdateMapEdges();
|
||||
UpdateClouds();
|
||||
UpdateSky();
|
||||
UpdateSkybox();
|
||||
Gfx_DeleteVb(&skybox_vb);
|
||||
EnvRenderer_UpdateFog();
|
||||
|
||||
Gfx_DeleteDynamicVb(&weather_vb);
|
||||
/* TODO: Unnecessary to delete the weather VB? */
|
||||
if (Gfx.LostContext) return;
|
||||
/* TODO: Don't allocate unless used? */
|
||||
Gfx_RecreateDynamicVb(&weather_vb, VERTEX_FORMAT_TEXTURED, WEATHER_VERTS_COUNT);
|
||||
/* TODO: Don't need to do this on every new map */
|
||||
UpdateBorderTextures();
|
||||
}
|
||||
@ -873,7 +893,7 @@ static void OnEnvVariableChanged(void* obj, int envVar) {
|
||||
UpdateSky();
|
||||
UpdateClouds();
|
||||
} else if (envVar == ENV_VAR_SKYBOX_COLOR) {
|
||||
UpdateSkybox();
|
||||
Gfx_DeleteVb(&skybox_vb);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
162
src/Graphics.h
162
src/Graphics.h
@ -25,14 +25,14 @@ typedef enum MatrixType_ {
|
||||
#define SIZEOF_VERTEX_TEXTURED 24
|
||||
|
||||
#if defined CC_BUILD_PSP
|
||||
/* 3 floats for position (XYZ), 4 bytes for colour. */
|
||||
/* 3 floats for position (XYZ), 4 bytes for colour */
|
||||
struct VertexColoured { PackedCol Col; float X, Y, Z; };
|
||||
/* 3 floats for position (XYZ), 2 floats for texture coordinates (UV), 4 bytes for colour. */
|
||||
/* 3 floats for position (XYZ), 2 floats for texture coordinates (UV), 4 bytes for colour */
|
||||
struct VertexTextured { float U, V; PackedCol Col; float X, Y, Z; };
|
||||
#else
|
||||
/* 3 floats for position (XYZ), 4 bytes for colour. */
|
||||
/* 3 floats for position (XYZ), 4 bytes for colour */
|
||||
struct VertexColoured { float X, Y, Z; PackedCol Col; };
|
||||
/* 3 floats for position (XYZ), 2 floats for texture coordinates (UV), 4 bytes for colour. */
|
||||
/* 3 floats for position (XYZ), 2 floats for texture coordinates (UV), 4 bytes for colour */
|
||||
struct VertexTextured { float X, Y, Z; PackedCol Col; float U, V; };
|
||||
#endif
|
||||
|
||||
@ -45,9 +45,9 @@ CC_VAR extern struct _GfxData {
|
||||
float _unused;
|
||||
/* Whether context graphics has been lost (all creation/render calls fail) */
|
||||
cc_bool LostContext;
|
||||
/* Whether some textures are created with mipmaps. */
|
||||
/* Whether some textures are created with mipmaps */
|
||||
cc_bool Mipmaps;
|
||||
/* Whether managed textures are actually supported. */
|
||||
/* Whether managed textures are actually supported */
|
||||
/* If not, you must free/create them just like normal textures */
|
||||
cc_bool ManagedTextures;
|
||||
/* Whether graphics context has been created */
|
||||
@ -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)
|
||||
@ -77,58 +76,58 @@ void* Gfx_RecreateAndLockVb(GfxResourceID* vb, VertexFormat fmt, int count);
|
||||
/* Creates a new texture. (and also generates mipmaps if mipmaps) */
|
||||
/* Supported flags: TEXTURE_FLAG_MANAGED, TEXTURE_FLAG_DYNAMIC */
|
||||
/* NOTE: Only set mipmaps to true if Gfx_Mipmaps is also true, because whether textures
|
||||
use mipmapping may be either a per-texture or global state depending on the backend. */
|
||||
use mipmapping may be either a per-texture or global state depending on the backend */
|
||||
CC_API GfxResourceID Gfx_CreateTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps);
|
||||
/* Updates a region of the given texture. (and mipmapped regions if mipmaps) */
|
||||
CC_API void Gfx_UpdateTexturePart(GfxResourceID texId, int x, int y, struct Bitmap* part, cc_bool mipmaps);
|
||||
/* Updates a region of the given texture. (and mipmapped regions if mipmaps) */
|
||||
/* NOTE: rowWidth is in pixels (so for normal bitmaps, rowWidth equals width) */ /* OBSOLETE */
|
||||
void Gfx_UpdateTexture(GfxResourceID texId, int x, int y, struct Bitmap* part, int rowWidth, cc_bool mipmaps);
|
||||
/* Sets the currently active texture. */
|
||||
/* Sets the currently active texture */
|
||||
CC_API void Gfx_BindTexture(GfxResourceID texId);
|
||||
/* Deletes the given texture, then sets it to 0. */
|
||||
/* Deletes the given texture, then sets it to 0 */
|
||||
CC_API void Gfx_DeleteTexture(GfxResourceID* texId);
|
||||
/* NOTE: Completely useless now, and does nothing in all graphics backends */
|
||||
/* (used to set whether texture colour is used when rendering vertices) */
|
||||
CC_API void Gfx_SetTexturing(cc_bool enabled);
|
||||
/* Turns on mipmapping. (if Gfx_Mipmaps is enabled) */
|
||||
/* NOTE: You must have created textures with mipmaps true for this to work. */
|
||||
/* NOTE: You must have created textures with mipmaps true for this to work */
|
||||
CC_API void Gfx_EnableMipmaps(void);
|
||||
/* Turns off mipmapping. (if Gfx_Mipmaps is enabled) */
|
||||
/* NOTE: You must have created textures with mipmaps true for this to work. */
|
||||
/* NOTE: You must have created textures with mipmaps true for this to work */
|
||||
CC_API void Gfx_DisableMipmaps(void);
|
||||
|
||||
/* Returns whether fog blending is enabled. */
|
||||
/* Returns whether fog blending is enabled */
|
||||
CC_API cc_bool Gfx_GetFog(void);
|
||||
/* Sets whether fog blending is enabled. */
|
||||
/* Sets whether fog blending is enabled */
|
||||
CC_API void Gfx_SetFog(cc_bool enabled);
|
||||
/* Sets the colour of the blended fog. */
|
||||
/* Sets the colour of the blended fog */
|
||||
CC_API void Gfx_SetFogCol(PackedCol col);
|
||||
/* Sets thickness of fog for FOG_EXP/FOG_EXP2 modes. */
|
||||
/* Sets thickness of fog for FOG_EXP/FOG_EXP2 modes */
|
||||
CC_API void Gfx_SetFogDensity(float value);
|
||||
/* Sets extent/end of fog for FOG_LINEAR mode. */
|
||||
/* Sets extent/end of fog for FOG_LINEAR mode */
|
||||
CC_API void Gfx_SetFogEnd(float value);
|
||||
/* Sets in what way fog is blended. */
|
||||
/* Sets in what way fog is blended */
|
||||
CC_API void Gfx_SetFogMode(FogFunc func);
|
||||
|
||||
/* Sets whether backface culling is performed. */
|
||||
/* Sets whether backface culling is performed */
|
||||
CC_API void Gfx_SetFaceCulling(cc_bool enabled);
|
||||
/* Sets whether pixels with an alpha of less than 128 are discarded. */
|
||||
/* Sets whether pixels with an alpha of less than 128 are discarded */
|
||||
CC_API void Gfx_SetAlphaTest(cc_bool enabled);
|
||||
/* Sets whether existing and new pixels are blended together. */
|
||||
/* Sets whether existing and new pixels are blended together */
|
||||
CC_API void Gfx_SetAlphaBlending(cc_bool enabled);
|
||||
/* Sets whether blending between the alpha components of texture and vertex colour is performed. */
|
||||
/* Sets whether blending between the alpha components of texture and vertex colour is performed */
|
||||
CC_API void Gfx_SetAlphaArgBlend(cc_bool enabled);
|
||||
|
||||
/* Clears the colour and depth buffer to default. */
|
||||
/* Clears the colour and depth buffer to default */
|
||||
CC_API void Gfx_Clear(void);
|
||||
/* Sets the colour that the colour buffer is cleared to. */
|
||||
/* Sets the colour that the colour buffer is cleared to */
|
||||
CC_API void Gfx_ClearCol(PackedCol col);
|
||||
/* Sets whether pixels may be discard based on z/depth. */
|
||||
/* Sets whether pixels may be discard based on z/depth */
|
||||
CC_API void Gfx_SetDepthTest(cc_bool enabled);
|
||||
/* Sets whether R/G/B/A of pixels are actually written to the colour buffer channels. */
|
||||
/* Sets whether R/G/B/A of pixels are actually written to the colour buffer channels */
|
||||
CC_API void Gfx_SetColWriteMask(cc_bool r, cc_bool g, cc_bool b, cc_bool a);
|
||||
/* Sets whether z/depth of pixels is actually written to the depth buffer. */
|
||||
/* Sets whether z/depth of pixels is actually written to the depth buffer */
|
||||
CC_API void Gfx_SetDepthWrite(cc_bool enabled);
|
||||
/* Sets whether the game should only write output to depth buffer */
|
||||
/* NOTE: Implicitly calls Gfx_SetColWriteMask */
|
||||
@ -136,25 +135,25 @@ CC_API void Gfx_DepthOnlyRendering(cc_bool depthOnly);
|
||||
|
||||
/* Callback function to initialise/fill out the contents of an index buffer */
|
||||
typedef void (*Gfx_FillIBFunc)(cc_uint16* indices, int count, void* obj);
|
||||
/* Creates a new index buffer and fills out its contents. */
|
||||
/* Creates a new index buffer and fills out its contents */
|
||||
CC_API GfxResourceID Gfx_CreateIb2(int count, Gfx_FillIBFunc fillFunc, void* obj);
|
||||
/* Sets the currently active index buffer. */
|
||||
/* Sets the currently active index buffer */
|
||||
CC_API void Gfx_BindIb(GfxResourceID ib);
|
||||
/* Deletes the given index buffer, then sets it to 0. */
|
||||
/* Deletes the given index buffer, then sets it to 0 */
|
||||
CC_API void Gfx_DeleteIb(GfxResourceID* ib);
|
||||
|
||||
/* Creates a new vertex buffer. */
|
||||
/* Creates a new vertex buffer */
|
||||
CC_API GfxResourceID Gfx_CreateVb(VertexFormat fmt, int count);
|
||||
/* Sets the currently active vertex buffer. */
|
||||
/* Sets the currently active vertex buffer */
|
||||
CC_API void Gfx_BindVb(GfxResourceID vb);
|
||||
/* Deletes the given vertex buffer, then sets it to 0. */
|
||||
/* Deletes the given vertex buffer, then sets it to 0 */
|
||||
CC_API void Gfx_DeleteVb(GfxResourceID* vb);
|
||||
/* Acquires temp memory for changing the contents of a vertex buffer. */
|
||||
/* Acquires temp memory for changing the contents of a vertex buffer */
|
||||
CC_API void* Gfx_LockVb(GfxResourceID vb, VertexFormat fmt, int count);
|
||||
/* Submits the changed contents of a vertex buffer. */
|
||||
/* Submits the changed contents of a vertex buffer */
|
||||
CC_API void Gfx_UnlockVb(GfxResourceID vb);
|
||||
|
||||
/* TODO: How to make LockDynamicVb work with OpenGL 1.1 Builder stupidity.. */
|
||||
/* TODO: How to make LockDynamicVb work with OpenGL 1.1 Builder stupidity. */
|
||||
#ifdef CC_BUILD_GL11
|
||||
/* Special case of Gfx_Create/LockVb for building chunks in Builder.c */
|
||||
GfxResourceID Gfx_CreateVb2(void* vertices, VertexFormat fmt, int count);
|
||||
@ -166,39 +165,34 @@ void Gfx_BindVb_Textured(GfxResourceID vb);
|
||||
#define Gfx_BindVb_Textured Gfx_BindVb
|
||||
#endif
|
||||
|
||||
/* Creates a new dynamic vertex buffer, whose contents can be updated later. */
|
||||
/* Creates a new dynamic vertex buffer, whose contents can be updated later */
|
||||
CC_API GfxResourceID Gfx_CreateDynamicVb(VertexFormat fmt, int maxVertices);
|
||||
#ifndef CC_BUILD_GL11
|
||||
/* Static and dynamic vertex buffers are drawn in the same way */
|
||||
#define Gfx_BindDynamicVb Gfx_BindVb
|
||||
#define Gfx_DeleteDynamicVb Gfx_DeleteVb
|
||||
#else
|
||||
/* OpenGL 1.1 draws static vertex buffers completely differently. */
|
||||
void Gfx_BindDynamicVb(GfxResourceID vb);
|
||||
void Gfx_DeleteDynamicVb(GfxResourceID* vb);
|
||||
#endif
|
||||
/* Acquires temp memory for changing the contents of a dynamic vertex buffer. */
|
||||
/* Sets the active vertex buffer to the given dynamic vertex buffer */
|
||||
CC_API void Gfx_BindDynamicVb(GfxResourceID vb);
|
||||
/* Deletes the given dynamic vertex buffer, then sets it to 0 */
|
||||
CC_API void Gfx_DeleteDynamicVb(GfxResourceID* vb);
|
||||
/* Acquires temp memory for changing the contents of a dynamic vertex buffer */
|
||||
CC_API void* Gfx_LockDynamicVb(GfxResourceID vb, VertexFormat fmt, int count);
|
||||
/* Binds then submits the changed contents of a dynamic vertex buffer. */
|
||||
/* Binds then submits the changed contents of a dynamic vertex buffer */
|
||||
CC_API void Gfx_UnlockDynamicVb(GfxResourceID vb);
|
||||
|
||||
/* Sets the format of the rendered vertices. */
|
||||
/* Sets the format of the rendered vertices */
|
||||
CC_API void Gfx_SetVertexFormat(VertexFormat fmt);
|
||||
/* Updates the data of a dynamic vertex buffer. */
|
||||
/* Updates the data of a dynamic vertex buffer */
|
||||
CC_API void Gfx_SetDynamicVbData(GfxResourceID vb, void* vertices, int vCount);
|
||||
/* Renders vertices from the currently bound vertex buffer as lines. */
|
||||
/* Renders vertices from the currently bound vertex buffer as lines */
|
||||
CC_API void Gfx_DrawVb_Lines(int verticesCount);
|
||||
/* Renders vertices from the currently bound vertex and index buffer as triangles. */
|
||||
/* NOTE: Offsets each index by startVertex. */
|
||||
/* Renders vertices from the currently bound vertex and index buffer as triangles */
|
||||
/* NOTE: Offsets each index by startVertex */
|
||||
CC_API void Gfx_DrawVb_IndexedTris_Range(int verticesCount, int startVertex);
|
||||
/* Renders vertices from the currently bound vertex and index buffer as triangles. */
|
||||
/* Renders vertices from the currently bound vertex and index buffer as triangles */
|
||||
CC_API void Gfx_DrawVb_IndexedTris(int verticesCount);
|
||||
/* Special case Gfx_DrawVb_IndexedTris_Range for map renderer */
|
||||
void Gfx_DrawIndexedTris_T2fC4b(int verticesCount, int startVertex);
|
||||
|
||||
/* Loads the given matrix over the currently active matrix. */
|
||||
/* Loads the given matrix over the currently active matrix */
|
||||
CC_API void Gfx_LoadMatrix(MatrixType type, const struct Matrix* matrix);
|
||||
/* Loads the identity matrix over the currently active matrix. */
|
||||
/* Loads the identity matrix over the currently active matrix */
|
||||
CC_API void Gfx_LoadIdentityMatrix(MatrixType type);
|
||||
CC_API void Gfx_EnableTextureOffset(float x, float y);
|
||||
CC_API void Gfx_DisableTextureOffset(void);
|
||||
@ -210,56 +204,52 @@ void Gfx_CalcPerspectiveMatrix(struct Matrix* matrix, float fov, float aspect, f
|
||||
/* NOTE: Projection matrix calculation is here because it can depend the graphics backend */
|
||||
/* (e.g. OpenGL uses a Z clip space range of [-1, 1], whereas Direct3D9 uses [0, 1]) */
|
||||
|
||||
/* Outputs a .png screenshot of the backbuffer. */
|
||||
/* Outputs a .png screenshot of the backbuffer */
|
||||
cc_result Gfx_TakeScreenshot(struct Stream* output);
|
||||
/* Warns in chat if the backend has problems with the user's GPU. */
|
||||
/* Returns whether legacy rendering mode for borders/sky/clouds is needed. */
|
||||
/* Warns in chat if the backend has problems with the user's GPU */
|
||||
/* Returns whether legacy rendering mode for borders/sky/clouds is needed */
|
||||
cc_bool Gfx_WarnIfNecessary(void);
|
||||
/* Sets up state for rendering a new frame. */
|
||||
/* Sets up state for rendering a new frame */
|
||||
void Gfx_BeginFrame(void);
|
||||
/* Finishes rendering a frame, and swaps it with the back buffer. */
|
||||
/* Finishes rendering a frame, and swaps it with the back buffer */
|
||||
void Gfx_EndFrame(void);
|
||||
/* Sets whether to synchronise with monitor refresh to avoid tearing, and maximum frame rate. */
|
||||
/* NOTE: VSync setting may be unsupported or just ignored. */
|
||||
/* Sets whether to synchronise with monitor refresh to avoid tearing, and maximum frame rate */
|
||||
/* NOTE: VSync setting may be unsupported or just ignored */
|
||||
void Gfx_SetFpsLimit(cc_bool vsync, float minFrameMillis);
|
||||
/* Updates state when the window's dimensions have changed. */
|
||||
/* NOTE: This may require recreating the context depending on the backend. */
|
||||
/* Updates state when the window's dimensions have changed */
|
||||
/* NOTE: This may require recreating the context depending on the backend */
|
||||
void Gfx_OnWindowResize(void);
|
||||
/* Gets information about the user's GPU and current backend state. */
|
||||
/* Backend state may include depth buffer bits, free memory, etc. */
|
||||
/* NOTE: Each line is separated by \n. */
|
||||
/* Gets information about the user's GPU and current backend state */
|
||||
/* Backend state may include depth buffer bits, free memory, etc */
|
||||
/* NOTE: Each line is separated by \n */
|
||||
void Gfx_GetApiInfo(cc_string* info);
|
||||
|
||||
/* Raises ContextLost event and updates state for lost contexts. */
|
||||
/* Raises ContextLost event and updates state for lost contexts */
|
||||
void Gfx_LoseContext(const char* reason);
|
||||
/* Raises ContextRecreated event and restores internal state. */
|
||||
/* Raises ContextRecreated event and restores internal state */
|
||||
void Gfx_RecreateContext(void);
|
||||
/* Attempts to restore a lost context. */
|
||||
/* Attempts to restore a lost context */
|
||||
cc_bool Gfx_TryRestoreContext(void);
|
||||
|
||||
/* Binds and draws the specified subset of the vertices in the current dynamic vertex buffer. */
|
||||
/* NOTE: This replaces the dynamic vertex buffer's data first with the given vertices before drawing. */
|
||||
void Gfx_UpdateDynamicVb_IndexedTris(GfxResourceID vb, void* vertices, int vCount);
|
||||
|
||||
/* Renders a 2D flat coloured rectangle. */
|
||||
/* Renders a 2D flat coloured rectangle */
|
||||
void Gfx_Draw2DFlat(int x, int y, int width, int height, PackedCol color);
|
||||
/* Renders a 2D flat vertical gradient rectangle. */
|
||||
/* Renders a 2D flat vertical gradient rectangle */
|
||||
void Gfx_Draw2DGradient(int x, int y, int width, int height, PackedCol top, PackedCol bottom);
|
||||
/* Renders a 2D coloured texture. */
|
||||
/* Renders a 2D coloured texture */
|
||||
void Gfx_Draw2DTexture(const struct Texture* tex, PackedCol color);
|
||||
/* Fills out the vertices for rendering a 2D coloured texture. */
|
||||
/* Fills out the vertices for rendering a 2D coloured texture */
|
||||
void Gfx_Make2DQuad(const struct Texture* tex, PackedCol color, struct VertexTextured** vertices);
|
||||
|
||||
/* Switches state to be suitable for drawing 2D graphics. */
|
||||
/* Switches state to be suitable for drawing 2D graphics */
|
||||
/* NOTE: This means turning off fog/depth test, changing matrices, etc.*/
|
||||
void Gfx_Begin2D(int width, int height);
|
||||
/* Switches state to be suitable for drawing 3D graphics. */
|
||||
/* NOTE: This means restoring fog/depth test, restoring matrices, etc. */
|
||||
/* Switches state to be suitable for drawing 3D graphics */
|
||||
/* NOTE: This means restoring fog/depth test, restoring matrices, etc */
|
||||
void Gfx_End2D(void);
|
||||
|
||||
/* Sets appropriate alpha test/blending for given block draw type. */
|
||||
/* Sets appropriate alpha test/blending for given block draw type */
|
||||
void Gfx_SetupAlphaState(cc_uint8 draw);
|
||||
/* Undoes changes to alpha test/blending state by Gfx_SetupAlphaState. */
|
||||
/* Undoes changes to alpha test/blending state by Gfx_SetupAlphaState */
|
||||
void Gfx_RestoreAlphaState(cc_uint8 draw);
|
||||
|
||||
/* Statically initialises the position and dimensions of this texture */
|
||||
@ -272,8 +262,8 @@ void Gfx_RestoreAlphaState(cc_uint8 draw);
|
||||
/* Useful to only draw a sub-region of the texture's pixels */
|
||||
#define Tex_SetUV(tex, u1,v1, u2,v2) tex.uv.U1 = u1; tex.uv.V1 = v1; tex.uv.U2 = u2; tex.uv.V2 = v2;
|
||||
|
||||
/* Binds then renders the given texture. */
|
||||
/* Binds then renders the given texture */
|
||||
void Texture_Render(const struct Texture* tex);
|
||||
/* Binds then renders the given texture. */
|
||||
/* Binds then renders the given texture */
|
||||
void Texture_RenderShaded(const struct Texture* tex, PackedCol shadeColor);
|
||||
#endif
|
||||
|
@ -228,7 +228,7 @@ static void ToMortonTexture(C3D_Tex* tex, int originX, int originY,
|
||||
}
|
||||
|
||||
|
||||
GfxResourceID Gfx_CreateTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps) {
|
||||
static GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps) {
|
||||
C3D_Tex* tex = Mem_Alloc(1, sizeof(C3D_Tex), "GPU texture desc");
|
||||
bool success = C3D_TexInit(tex, bmp->width, bmp->height, GPU_RGBA8);
|
||||
//if (!success) Logger_Abort("Failed to create 3DS texture");
|
||||
@ -379,12 +379,9 @@ static cc_uint8* gfx_vertices;
|
||||
static cc_uint16* gfx_indices;
|
||||
|
||||
static void* AllocBuffer(int count, int elemSize) {
|
||||
void* ptr = linearAlloc(count * elemSize);
|
||||
return linearAlloc(count * elemSize);
|
||||
//cc_uintptr addr = ptr;
|
||||
//Platform_Log3("BUFFER CREATE: %i X %i = %x", &count, &elemSize, &addr);
|
||||
|
||||
if (!ptr) Logger_Abort("Failed to allocate memory for buffer");
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static void FreeBuffer(GfxResourceID* buffer) {
|
||||
@ -396,6 +393,8 @@ static void FreeBuffer(GfxResourceID* buffer) {
|
||||
|
||||
GfxResourceID Gfx_CreateIb2(int count, Gfx_FillIBFunc fillFunc, void* obj) {
|
||||
void* ib = AllocBuffer(count, sizeof(cc_uint16));
|
||||
if (!ib) Logger_Abort("Failed to allocate memory for index buffer");
|
||||
|
||||
fillFunc(ib, count, obj);
|
||||
return ib;
|
||||
}
|
||||
@ -405,7 +404,7 @@ void Gfx_BindIb(GfxResourceID ib) { gfx_indices = ib; }
|
||||
void Gfx_DeleteIb(GfxResourceID* ib) { FreeBuffer(ib); }
|
||||
|
||||
|
||||
GfxResourceID Gfx_CreateVb(VertexFormat fmt, int count) {
|
||||
static GfxResourceID Gfx_AllocStaticVb(VertexFormat fmt, int count) {
|
||||
return AllocBuffer(count, strideSizes[fmt]);
|
||||
}
|
||||
|
||||
@ -431,10 +430,12 @@ void* Gfx_LockVb(GfxResourceID vb, VertexFormat fmt, int count) {
|
||||
void Gfx_UnlockVb(GfxResourceID vb) { gfx_vertices = vb; }
|
||||
|
||||
|
||||
GfxResourceID Gfx_CreateDynamicVb(VertexFormat fmt, int maxVertices) {
|
||||
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;
|
||||
}
|
||||
|
@ -2,7 +2,6 @@
|
||||
#ifdef CC_BUILD_D3D11
|
||||
#include "_GraphicsBase.h"
|
||||
#include "Errors.h"
|
||||
#include "Logger.h"
|
||||
#include "Window.h"
|
||||
#include "_D3D11Shaders.h"
|
||||
|
||||
@ -202,16 +201,11 @@ static void D3D11_DoMipmaps(ID3D11Resource* texture, int x, int y, struct Bitmap
|
||||
if (prev != bmp->scan0) Mem_Free(prev);
|
||||
}
|
||||
|
||||
GfxResourceID Gfx_CreateTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps) {
|
||||
static GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps) {
|
||||
ID3D11Texture2D* tex = NULL;
|
||||
ID3D11ShaderResourceView* view = NULL;
|
||||
HRESULT hr;
|
||||
|
||||
if (!Math_IsPowOf2(bmp->width) || !Math_IsPowOf2(bmp->height)) {
|
||||
Logger_Abort("Textures must have power of two dimensions");
|
||||
}
|
||||
if (Gfx.LostContext) return 0;
|
||||
|
||||
D3D11_TEXTURE2D_DESC desc = { 0 };
|
||||
desc.Width = bmp->width;
|
||||
desc.Height = bmp->height;
|
||||
@ -343,11 +337,11 @@ static ID3D11Buffer* CreateVertexBuffer(VertexFormat fmt, int count, cc_bool dyn
|
||||
/* TODO set data initially */
|
||||
|
||||
HRESULT hr = ID3D11Device_CreateBuffer(device, &desc, NULL, &buffer);
|
||||
if (hr) Logger_Abort2(hr, "Failed to create index buffer");
|
||||
if (hr) Logger_Abort2(hr, "Failed to create vertex buffer");
|
||||
return buffer;
|
||||
}
|
||||
|
||||
GfxResourceID Gfx_CreateVb(VertexFormat fmt, int count) {
|
||||
static GfxResourceID Gfx_AllocStaticVb(VertexFormat fmt, int count) {
|
||||
/* TODO immutable? */
|
||||
return CreateVertexBuffer(fmt, count, false);
|
||||
}
|
||||
@ -371,6 +365,46 @@ void Gfx_UnlockVb(GfxResourceID vb) {
|
||||
tmp = NULL;
|
||||
}
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*--------------------------------------------------Dynamic vertex buffers-------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
static GfxResourceID Gfx_AllocDynamicVb(VertexFormat fmt, int maxVertices) {
|
||||
return CreateVertexBuffer(fmt, maxVertices, true);
|
||||
}
|
||||
|
||||
void Gfx_DeleteDynamicVb(GfxResourceID* vb) {
|
||||
ID3D11Buffer* buffer = (ID3D11Buffer*)(*vb);
|
||||
if (buffer) ID3D11Buffer_Release(buffer);
|
||||
*vb = NULL;
|
||||
}
|
||||
|
||||
static D3D11_MAPPED_SUBRESOURCE mapDesc;
|
||||
void* Gfx_LockDynamicVb(GfxResourceID vb, VertexFormat fmt, int count) {
|
||||
ID3D11Buffer* buffer = (ID3D11Buffer*)vb;
|
||||
mapDesc.pData = NULL;
|
||||
|
||||
HRESULT hr = ID3D11DeviceContext_Map(context, buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapDesc);
|
||||
if (hr) Logger_Abort2(hr, "Failed to lock dynamic VB");
|
||||
return mapDesc.pData;
|
||||
}
|
||||
|
||||
void Gfx_UnlockDynamicVb(GfxResourceID vb) {
|
||||
ID3D11Buffer* buffer = (ID3D11Buffer*)vb;
|
||||
ID3D11DeviceContext_Unmap(context, buffer, 0);
|
||||
Gfx_BindDynamicVb(vb);
|
||||
}
|
||||
|
||||
void Gfx_SetDynamicVbData(GfxResourceID vb, void* vertices, int vCount) {
|
||||
void* data = Gfx_LockDynamicVb(vb, gfx_format, vCount);
|
||||
Mem_Copy(data, vertices, vCount * gfx_stride);
|
||||
Gfx_UnlockDynamicVb(vb);
|
||||
}
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*-----------------------------------------------------Vertex rendering----------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
void Gfx_SetVertexFormat(VertexFormat fmt) {
|
||||
if (fmt == gfx_format) return;
|
||||
gfx_format = fmt;
|
||||
@ -400,37 +434,6 @@ void Gfx_DrawIndexedTris_T2fC4b(int verticesCount, int startVertex) {
|
||||
}
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*--------------------------------------------------Dynamic vertex buffers-------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
GfxResourceID Gfx_CreateDynamicVb(VertexFormat fmt, int maxVertices) {
|
||||
// TODO pass true instead
|
||||
return CreateVertexBuffer(fmt, maxVertices, true);
|
||||
}
|
||||
|
||||
static D3D11_MAPPED_SUBRESOURCE mapDesc;
|
||||
void* Gfx_LockDynamicVb(GfxResourceID vb, VertexFormat fmt, int count) {
|
||||
ID3D11Buffer* buffer = (ID3D11Buffer*)vb;
|
||||
mapDesc.pData = NULL;
|
||||
|
||||
HRESULT hr = ID3D11DeviceContext_Map(context, buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapDesc);
|
||||
if (hr) Logger_Abort2(hr, "Failed to lock dynamic VB");
|
||||
return mapDesc.pData;
|
||||
}
|
||||
|
||||
void Gfx_UnlockDynamicVb(GfxResourceID vb) {
|
||||
ID3D11Buffer* buffer = (ID3D11Buffer*)vb;
|
||||
ID3D11DeviceContext_Unmap(context, buffer, 0);
|
||||
Gfx_BindVb(vb);
|
||||
}
|
||||
|
||||
void Gfx_SetDynamicVbData(GfxResourceID vb, void* vertices, int vCount) {
|
||||
void* data = Gfx_LockDynamicVb(vb, gfx_format, vCount);
|
||||
Mem_Copy(data, vertices, vCount * gfx_stride);
|
||||
Gfx_UnlockDynamicVb(vb);
|
||||
}
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*---------------------------------------------------------Matrices--------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
@ -517,6 +520,12 @@ void Gfx_BindVb(GfxResourceID vb) {
|
||||
ID3D11DeviceContext_IASetVertexBuffers(context, 0, 1, &buffer, &gfx_stride, offset);
|
||||
}
|
||||
|
||||
void Gfx_BindDynamicVb(GfxResourceID vb) {
|
||||
ID3D11Buffer* buffer = (ID3D11Buffer*)vb;
|
||||
static UINT32 offset[] = { 0 };
|
||||
ID3D11DeviceContext_IASetVertexBuffers(context, 0, 1, &buffer, &gfx_stride, offset);
|
||||
}
|
||||
|
||||
|
||||
//########################################################################################################################
|
||||
//--------------------------------------------------------Vertex shader---------------------------------------------------
|
||||
|
@ -2,7 +2,6 @@
|
||||
#ifdef CC_BUILD_D3D9
|
||||
#include "_GraphicsBase.h"
|
||||
#include "Errors.h"
|
||||
#include "Logger.h"
|
||||
#include "Window.h"
|
||||
|
||||
/* Avoid pointless includes */
|
||||
@ -19,7 +18,7 @@
|
||||
/* https://docs.microsoft.com/en-us/windows/win32/dxtecharts/the-direct3d-transformation-pipeline */
|
||||
|
||||
/* https://docs.microsoft.com/en-us/windows/win32/direct3d9/d3dfvf-texcoordsizen */
|
||||
static DWORD d3d9_formatMappings[2] = { D3DFVF_XYZ | D3DFVF_DIFFUSE, D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1 };
|
||||
static DWORD d3d9_formatMappings[] = { D3DFVF_XYZ | D3DFVF_DIFFUSE, D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1 };
|
||||
/* Current format and size of vertices */
|
||||
static int gfx_stride, gfx_format = -1;
|
||||
|
||||
@ -247,17 +246,6 @@ static void Gfx_RestoreState(void) {
|
||||
D3D9_RestoreRenderStates();
|
||||
}
|
||||
|
||||
static cc_bool D3D9_CheckResult(cc_result res, const char* func) {
|
||||
if (!res) return true;
|
||||
|
||||
if (res == D3DERR_OUTOFVIDEOMEMORY || res == E_OUTOFMEMORY) {
|
||||
if (!Game_ReduceVRAM()) Logger_Abort("Out of video memory!");
|
||||
} else {
|
||||
Logger_Abort2(res, func);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*---------------------------------------------------------Textures--------------------------------------------------------*
|
||||
@ -320,6 +308,17 @@ static void D3D9_DoMipmaps(IDirect3DTexture9* texture, int x, int y, struct Bitm
|
||||
if (prev != bmp->scan0) Mem_Free(prev);
|
||||
}
|
||||
|
||||
static cc_bool D3D9_CheckResult(cc_result res, const char* func) {
|
||||
if (!res) return true;
|
||||
|
||||
if (res == D3DERR_OUTOFVIDEOMEMORY || res == E_OUTOFMEMORY) {
|
||||
if (!Game_ReduceVRAM()) Logger_Abort("Out of video memory!");
|
||||
} else {
|
||||
Logger_Abort2(res, func);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static IDirect3DTexture9* DoCreateTexture(struct Bitmap* bmp, int levels, int pool) {
|
||||
IDirect3DTexture9* tex;
|
||||
cc_result res;
|
||||
@ -332,18 +331,13 @@ static IDirect3DTexture9* DoCreateTexture(struct Bitmap* bmp, int levels, int po
|
||||
return tex;
|
||||
}
|
||||
|
||||
GfxResourceID Gfx_CreateTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps) {
|
||||
static GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps) {
|
||||
IDirect3DTexture9* tex;
|
||||
IDirect3DTexture9* sys;
|
||||
cc_result res;
|
||||
|
||||
int mipmapsLevels = CalcMipmapsLevels(bmp->width, bmp->height);
|
||||
int levels = 1 + (mipmaps ? mipmapsLevels : 0);
|
||||
|
||||
if (!Math_IsPowOf2(bmp->width) || !Math_IsPowOf2(bmp->height)) {
|
||||
Logger_Abort("Textures must have power of two dimensions");
|
||||
}
|
||||
if (Gfx.LostContext) return 0;
|
||||
|
||||
if (flags & TEXTURE_FLAG_MANAGED) {
|
||||
while ((res = IDirect3DDevice9_CreateTexture(device, bmp->width, bmp->height, levels,
|
||||
@ -596,14 +590,16 @@ void Gfx_DeleteIb(GfxResourceID* ib) { D3D9_FreeResource(ib); }
|
||||
*#########################################################################################################################*/
|
||||
static IDirect3DVertexBuffer9* D3D9_AllocVertexBuffer(VertexFormat fmt, int count, DWORD usage) {
|
||||
IDirect3DVertexBuffer9* vbuffer;
|
||||
cc_result res;
|
||||
int size = count * strideSizes[fmt];
|
||||
cc_result res;
|
||||
|
||||
for (;;) {
|
||||
res = IDirect3DDevice9_CreateVertexBuffer(device, size, usage,
|
||||
d3d9_formatMappings[fmt], D3DPOOL_DEFAULT, &vbuffer, NULL);
|
||||
if (D3D9_CheckResult(res, "D3D9_CreateVb failed")) break;
|
||||
}
|
||||
res = IDirect3DDevice9_CreateVertexBuffer(device, size, usage,
|
||||
d3d9_formatMappings[fmt], D3DPOOL_DEFAULT, &vbuffer, NULL);
|
||||
|
||||
if (res == D3DERR_OUTOFVIDEOMEMORY || res == E_OUTOFMEMORY)
|
||||
return NULL;
|
||||
|
||||
if (res) Logger_Abort2(res, "D3D9_AllocVertexBuffer failed");
|
||||
return vbuffer;
|
||||
}
|
||||
|
||||
@ -627,17 +623,18 @@ static void* D3D9_LockVb(GfxResourceID vb, VertexFormat fmt, int count, int lock
|
||||
return dst;
|
||||
}
|
||||
|
||||
GfxResourceID Gfx_CreateVb(VertexFormat fmt, int count) {
|
||||
static GfxResourceID Gfx_AllocStaticVb(VertexFormat fmt, int count) {
|
||||
return D3D9_AllocVertexBuffer(fmt, count, D3DUSAGE_WRITEONLY);
|
||||
}
|
||||
|
||||
void Gfx_DeleteVb(GfxResourceID* vb) { D3D9_FreeResource(vb); }
|
||||
|
||||
void Gfx_BindVb(GfxResourceID vb) {
|
||||
IDirect3DVertexBuffer9* vbuffer = (IDirect3DVertexBuffer9*)vb;
|
||||
cc_result res = IDirect3DDevice9_SetStreamSource(device, 0, vbuffer, 0, gfx_stride);
|
||||
if (res) Logger_Abort2(res, "D3D9_BindVb");
|
||||
}
|
||||
|
||||
void Gfx_DeleteVb(GfxResourceID* vb) { D3D9_FreeResource(vb); }
|
||||
void* Gfx_LockVb(GfxResourceID vb, VertexFormat fmt, int count) {
|
||||
return D3D9_LockVb(vb, fmt, count, 0);
|
||||
}
|
||||
@ -649,6 +646,43 @@ void Gfx_UnlockVb(GfxResourceID vb) {
|
||||
}
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*--------------------------------------------------Dynamic vertex buffers-------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
static GfxResourceID Gfx_AllocDynamicVb(VertexFormat fmt, int maxVertices) {
|
||||
return D3D9_AllocVertexBuffer(fmt, maxVertices, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY);
|
||||
}
|
||||
|
||||
void Gfx_DeleteDynamicVb(GfxResourceID* vb) { D3D9_FreeResource(vb); }
|
||||
|
||||
void Gfx_BindDynamicVb(GfxResourceID vb) {
|
||||
IDirect3DVertexBuffer9* vbuffer = (IDirect3DVertexBuffer9*)vb;
|
||||
cc_result res = IDirect3DDevice9_SetStreamSource(device, 0, vbuffer, 0, gfx_stride);
|
||||
if (res) Logger_Abort2(res, "D3D9_BindDynamicVb");
|
||||
}
|
||||
|
||||
void* Gfx_LockDynamicVb(GfxResourceID vb, VertexFormat fmt, int count) {
|
||||
return D3D9_LockVb(vb, fmt, count, D3DLOCK_DISCARD);
|
||||
}
|
||||
|
||||
void Gfx_UnlockDynamicVb(GfxResourceID vb) {
|
||||
Gfx_UnlockVb(vb);
|
||||
Gfx_BindDynamicVb(vb); /* TODO: Inline this? */
|
||||
}
|
||||
|
||||
void Gfx_SetDynamicVbData(GfxResourceID vb, void* vertices, int vCount) {
|
||||
int size = vCount * gfx_stride;
|
||||
IDirect3DVertexBuffer9* buffer = (IDirect3DVertexBuffer9*)vb;
|
||||
D3D9_SetVbData(buffer, vertices, size, D3DLOCK_DISCARD);
|
||||
|
||||
cc_result res = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, gfx_stride);
|
||||
if (res) Logger_Abort2(res, "D3D9_SetDynamicVbData - Bind");
|
||||
}
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*-----------------------------------------------------Vertex rendering----------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
void Gfx_SetVertexFormat(VertexFormat fmt) {
|
||||
cc_result res;
|
||||
if (fmt == gfx_format) return;
|
||||
@ -689,33 +723,6 @@ void Gfx_DrawIndexedTris_T2fC4b(int verticesCount, int startVertex) {
|
||||
}
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*--------------------------------------------------Dynamic vertex buffers-------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
GfxResourceID Gfx_CreateDynamicVb(VertexFormat fmt, int maxVertices) {
|
||||
if (Gfx.LostContext) return 0;
|
||||
return D3D9_AllocVertexBuffer(fmt, maxVertices, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY);
|
||||
}
|
||||
|
||||
void* Gfx_LockDynamicVb(GfxResourceID vb, VertexFormat fmt, int count) {
|
||||
return D3D9_LockVb(vb, fmt, count, D3DLOCK_DISCARD);
|
||||
}
|
||||
|
||||
void Gfx_UnlockDynamicVb(GfxResourceID vb) {
|
||||
Gfx_UnlockVb(vb);
|
||||
Gfx_BindVb(vb); /* TODO: Inline this? */
|
||||
}
|
||||
|
||||
void Gfx_SetDynamicVbData(GfxResourceID vb, void* vertices, int vCount) {
|
||||
int size = vCount * gfx_stride;
|
||||
IDirect3DVertexBuffer9* buffer = (IDirect3DVertexBuffer9*)vb;
|
||||
D3D9_SetVbData(buffer, vertices, size, D3DLOCK_DISCARD);
|
||||
|
||||
cc_result res = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, gfx_stride);
|
||||
if (res) Logger_Abort2(res, "D3D9_SetDynamicVbData - Bind");
|
||||
}
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*---------------------------------------------------------Matrices--------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
|
@ -127,11 +127,8 @@ void Gfx_DeleteIb(GfxResourceID* ib) { }
|
||||
/*########################################################################################################################*
|
||||
*------------------------------------------------------Vertex buffers-----------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
GfxResourceID Gfx_CreateVb(VertexFormat fmt, int count) {
|
||||
void* data = memalign(16, count * strideSizes[fmt]);
|
||||
if (!data) Logger_Abort("Failed to allocate memory for GFX VB");
|
||||
return data;
|
||||
//return Mem_Alloc(count, strideSizes[fmt], "gfx VB");
|
||||
static GfxResourceID Gfx_AllocStaticVb(VertexFormat fmt, int count) {
|
||||
return memalign(16, count * strideSizes[fmt]);
|
||||
}
|
||||
|
||||
void Gfx_BindVb(GfxResourceID vb) { gfx_vertices = vb; }
|
||||
@ -153,13 +150,12 @@ void Gfx_UnlockVb(GfxResourceID vb) {
|
||||
}
|
||||
|
||||
|
||||
GfxResourceID Gfx_CreateDynamicVb(VertexFormat fmt, int maxVertices) {
|
||||
void* data = memalign(16, maxVertices * strideSizes[fmt]);
|
||||
if (!data) Logger_Abort("Failed to allocate memory for GFX VB");
|
||||
return data;
|
||||
//return Mem_Alloc(maxVertices, strideSizes[fmt], "gfx VB");
|
||||
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;
|
||||
@ -283,12 +279,9 @@ static void ConvertTexture(cc_uint16* dst, struct Bitmap* bmp) {
|
||||
}
|
||||
}
|
||||
|
||||
GfxResourceID Gfx_CreateTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps) {
|
||||
static GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps) {
|
||||
GLuint texId = gldcGenTexture();
|
||||
gldcBindTexture(texId);
|
||||
if (!Math_IsPowOf2(bmp->width) || !Math_IsPowOf2(bmp->height)) {
|
||||
Logger_Abort("Textures must have power of two dimensions");
|
||||
}
|
||||
|
||||
gldcAllocTexture(bmp->width, bmp->height, GL_RGBA,
|
||||
GL_UNSIGNED_SHORT_4_4_4_4_REV_TWID_KOS);
|
||||
@ -299,6 +292,7 @@ GfxResourceID Gfx_CreateTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipm
|
||||
ConvertTexture(pixels, bmp);
|
||||
return texId;
|
||||
}
|
||||
|
||||
// TODO: struct GPUTexture ??
|
||||
static void ConvertSubTexture(cc_uint16* dst, int texWidth, int texHeight,
|
||||
int originX, int originY,
|
||||
|
@ -136,7 +136,7 @@ static void ReorderPixels(CCTexture* tex, struct Bitmap* bmp,
|
||||
}
|
||||
}
|
||||
|
||||
GfxResourceID Gfx_CreateTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps) {
|
||||
static GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps) {
|
||||
if (bmp->width < 4 || bmp->height < 4) {
|
||||
Platform_LogConst("ERROR: Tried to create texture smaller than 4x4");
|
||||
return 0;
|
||||
@ -293,10 +293,8 @@ void Gfx_DeleteIb(GfxResourceID* ib) { }
|
||||
static cc_uint8* gfx_vertices;
|
||||
static int vb_size;
|
||||
|
||||
GfxResourceID Gfx_CreateVb(VertexFormat fmt, int count) {
|
||||
void* data = memalign(16, count * strideSizes[fmt]);
|
||||
if (!data) Logger_Abort("Failed to allocate memory for GFX VB");
|
||||
return data;
|
||||
static GfxResourceID Gfx_AllocStaticVb(VertexFormat fmt, int count) {
|
||||
return memalign(16, count * strideSizes[fmt]);
|
||||
}
|
||||
|
||||
void Gfx_BindVb(GfxResourceID vb) { gfx_vertices = vb; }
|
||||
@ -318,12 +316,12 @@ void Gfx_UnlockVb(GfxResourceID vb) {
|
||||
}
|
||||
|
||||
|
||||
GfxResourceID Gfx_CreateDynamicVb(VertexFormat fmt, int maxVertices) {
|
||||
void* data = memalign(16, maxVertices * strideSizes[fmt]);
|
||||
if (!data) Logger_Abort("Failed to allocate memory for GFX VB");
|
||||
return data;
|
||||
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;
|
||||
|
@ -2,7 +2,6 @@
|
||||
#if defined CC_BUILD_GL && !defined CC_BUILD_GLMODERN
|
||||
#include "_GraphicsBase.h"
|
||||
#include "Errors.h"
|
||||
#include "Logger.h"
|
||||
#include "Window.h"
|
||||
/* The OpenGL backend is a bit of a mess, since it's really 2 backends in one:
|
||||
* - OpenGL 1.1 (completely lacking GPU, fallbacks to say Windows built-in software rasteriser)
|
||||
@ -243,18 +242,19 @@ void Gfx_DeleteIb(GfxResourceID* ib) { }
|
||||
*------------------------------------------------------Vertex buffers-----------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
#ifndef CC_BUILD_GL11
|
||||
GfxResourceID Gfx_CreateVb(VertexFormat fmt, int count) {
|
||||
static GfxResourceID Gfx_AllocStaticVb(VertexFormat fmt, int count) {
|
||||
GfxResourceID id = _genBuffer();
|
||||
_glBindBuffer(GL_ARRAY_BUFFER, id);
|
||||
return id;
|
||||
}
|
||||
|
||||
void Gfx_BindVb(GfxResourceID vb) { _glBindBuffer(GL_ARRAY_BUFFER, vb); }
|
||||
void Gfx_BindVb(GfxResourceID vb) {
|
||||
_glBindBuffer(GL_ARRAY_BUFFER, vb);
|
||||
}
|
||||
|
||||
void Gfx_DeleteVb(GfxResourceID* vb) {
|
||||
GfxResourceID id = *vb;
|
||||
if (!id) return;
|
||||
_delBuffer(id);
|
||||
if (id) _delBuffer(id);
|
||||
*vb = 0;
|
||||
}
|
||||
|
||||
@ -266,7 +266,9 @@ void Gfx_UnlockVb(GfxResourceID vb) {
|
||||
_glBufferData(GL_ARRAY_BUFFER, tmpSize, tmpData, GL_STATIC_DRAW);
|
||||
}
|
||||
#else
|
||||
GfxResourceID Gfx_CreateVb(VertexFormat fmt, int count) { return glGenLists(1); }
|
||||
static GfxResourceID Gfx_AllocStaticVb(VertexFormat fmt, int count) {
|
||||
return glGenLists(1);
|
||||
}
|
||||
void Gfx_BindVb(GfxResourceID vb) { activeList = (GLuint)vb; }
|
||||
|
||||
void Gfx_DeleteVb(GfxResourceID* vb) {
|
||||
@ -317,19 +319,25 @@ GfxResourceID Gfx_CreateVb2(void* vertices, VertexFormat fmt, int count) {
|
||||
*--------------------------------------------------Dynamic vertex buffers-------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
#ifndef CC_BUILD_GL11
|
||||
GfxResourceID Gfx_CreateDynamicVb(VertexFormat fmt, int maxVertices) {
|
||||
GfxResourceID id;
|
||||
cc_uint32 size;
|
||||
if (Gfx.LostContext) return 0;
|
||||
|
||||
id = _genBuffer();
|
||||
size = maxVertices * strideSizes[fmt];
|
||||
static GfxResourceID Gfx_AllocDynamicVb(VertexFormat fmt, int maxVertices) {
|
||||
GfxResourceID id = _genBuffer();
|
||||
cc_uint32 size = maxVertices * strideSizes[fmt];
|
||||
|
||||
_glBindBuffer(GL_ARRAY_BUFFER, id);
|
||||
_glBufferData(GL_ARRAY_BUFFER, size, NULL, GL_DYNAMIC_DRAW);
|
||||
return id;
|
||||
}
|
||||
|
||||
void Gfx_BindDynamicVb(GfxResourceID vb) {
|
||||
_glBindBuffer(GL_ARRAY_BUFFER, vb);
|
||||
}
|
||||
|
||||
void Gfx_DeleteDynamicVb(GfxResourceID* vb) {
|
||||
GfxResourceID id = *vb;
|
||||
if (id) _delBuffer(id);
|
||||
*vb = 0;
|
||||
}
|
||||
|
||||
void* Gfx_LockDynamicVb(GfxResourceID vb, VertexFormat fmt, int count) {
|
||||
return FastAllocTempMem(count * strideSizes[fmt]);
|
||||
}
|
||||
@ -345,8 +353,8 @@ void Gfx_SetDynamicVbData(GfxResourceID vb, void* vertices, int vCount) {
|
||||
_glBufferSubData(GL_ARRAY_BUFFER, 0, size, vertices);
|
||||
}
|
||||
#else
|
||||
GfxResourceID Gfx_CreateDynamicVb(VertexFormat fmt, int maxVertices) {
|
||||
return (GfxResourceID)Mem_Alloc(maxVertices, strideSizes[fmt], "creating dynamic vb");
|
||||
static GfxResourceID Gfx_AllocDynamicVb(VertexFormat fmt, int maxVertices) {
|
||||
return (GfxResourceID)Mem_TryAlloc(maxVertices, strideSizes[fmt]);
|
||||
}
|
||||
|
||||
void Gfx_BindDynamicVb(GfxResourceID vb) {
|
||||
@ -370,6 +378,97 @@ void Gfx_SetDynamicVbData(GfxResourceID vb, void* vertices, int vCount) {
|
||||
#endif
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*----------------------------------------------------------Drawing--------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
#ifdef CC_BUILD_GL11
|
||||
/* point to client side dynamic array */
|
||||
#define VB_PTR ((cc_uint8*)dynamicListData)
|
||||
#define IB_PTR gl_indices
|
||||
#else
|
||||
/* no client side array, use vertex buffer object */
|
||||
#define VB_PTR 0
|
||||
#define IB_PTR NULL
|
||||
#endif
|
||||
|
||||
static void GL_SetupVbColoured(void) {
|
||||
_glVertexPointer(3, GL_FLOAT, SIZEOF_VERTEX_COLOURED, (void*)(VB_PTR + 0));
|
||||
_glColorPointer(4, GL_UNSIGNED_BYTE, SIZEOF_VERTEX_COLOURED, (void*)(VB_PTR + 12));
|
||||
}
|
||||
|
||||
static void GL_SetupVbTextured(void) {
|
||||
_glVertexPointer(3, GL_FLOAT, SIZEOF_VERTEX_TEXTURED, (void*)(VB_PTR + 0));
|
||||
_glColorPointer(4, GL_UNSIGNED_BYTE, SIZEOF_VERTEX_TEXTURED, (void*)(VB_PTR + 12));
|
||||
_glTexCoordPointer(2, GL_FLOAT, SIZEOF_VERTEX_TEXTURED, (void*)(VB_PTR + 16));
|
||||
}
|
||||
|
||||
static void GL_SetupVbColoured_Range(int startVertex) {
|
||||
cc_uint32 offset = startVertex * SIZEOF_VERTEX_COLOURED;
|
||||
_glVertexPointer(3, GL_FLOAT, SIZEOF_VERTEX_COLOURED, (void*)(VB_PTR + offset));
|
||||
_glColorPointer(4, GL_UNSIGNED_BYTE, SIZEOF_VERTEX_COLOURED, (void*)(VB_PTR + offset + 12));
|
||||
}
|
||||
|
||||
static void GL_SetupVbTextured_Range(int startVertex) {
|
||||
cc_uint32 offset = startVertex * SIZEOF_VERTEX_TEXTURED;
|
||||
_glVertexPointer(3, GL_FLOAT, SIZEOF_VERTEX_TEXTURED, (void*)(VB_PTR + offset));
|
||||
_glColorPointer(4, GL_UNSIGNED_BYTE, SIZEOF_VERTEX_TEXTURED, (void*)(VB_PTR + offset + 12));
|
||||
_glTexCoordPointer(2, GL_FLOAT, SIZEOF_VERTEX_TEXTURED, (void*)(VB_PTR + offset + 16));
|
||||
}
|
||||
|
||||
void Gfx_SetVertexFormat(VertexFormat fmt) {
|
||||
if (fmt == gfx_format) return;
|
||||
gfx_format = fmt;
|
||||
gfx_stride = strideSizes[fmt];
|
||||
|
||||
if (fmt == VERTEX_FORMAT_TEXTURED) {
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
gfx_setupVBFunc = GL_SetupVbTextured;
|
||||
gfx_setupVBRangeFunc = GL_SetupVbTextured_Range;
|
||||
} else {
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
gfx_setupVBFunc = GL_SetupVbColoured;
|
||||
gfx_setupVBRangeFunc = GL_SetupVbColoured_Range;
|
||||
}
|
||||
}
|
||||
|
||||
void Gfx_DrawVb_Lines(int verticesCount) {
|
||||
gfx_setupVBFunc();
|
||||
glDrawArrays(GL_LINES, 0, verticesCount);
|
||||
}
|
||||
|
||||
void Gfx_DrawVb_IndexedTris_Range(int verticesCount, int startVertex) {
|
||||
#ifdef CC_BUILD_GL11
|
||||
if (activeList != gl_DYNAMICLISTID) { glCallList(activeList); return; }
|
||||
#endif
|
||||
gfx_setupVBRangeFunc(startVertex);
|
||||
_glDrawElements(GL_TRIANGLES, ICOUNT(verticesCount), GL_UNSIGNED_SHORT, IB_PTR);
|
||||
}
|
||||
|
||||
void Gfx_DrawVb_IndexedTris(int verticesCount) {
|
||||
#ifdef CC_BUILD_GL11
|
||||
if (activeList != gl_DYNAMICLISTID) { glCallList(activeList); return; }
|
||||
#endif
|
||||
gfx_setupVBFunc();
|
||||
_glDrawElements(GL_TRIANGLES, ICOUNT(verticesCount), GL_UNSIGNED_SHORT, IB_PTR);
|
||||
}
|
||||
|
||||
#ifdef CC_BUILD_GL11
|
||||
void Gfx_DrawIndexedTris_T2fC4b(int verticesCount, int startVertex) { glCallList(activeList); }
|
||||
#else
|
||||
void Gfx_DrawIndexedTris_T2fC4b(int verticesCount, int startVertex) {
|
||||
cc_uint32 offset = startVertex * SIZEOF_VERTEX_TEXTURED;
|
||||
_glVertexPointer(3, GL_FLOAT, SIZEOF_VERTEX_TEXTURED, (void*)(VB_PTR + offset));
|
||||
_glColorPointer(4, GL_UNSIGNED_BYTE, SIZEOF_VERTEX_TEXTURED, (void*)(VB_PTR + offset + 12));
|
||||
_glTexCoordPointer(2, GL_FLOAT, SIZEOF_VERTEX_TEXTURED, (void*)(VB_PTR + offset + 16));
|
||||
_glDrawElements(GL_TRIANGLES, ICOUNT(verticesCount), GL_UNSIGNED_SHORT, IB_PTR);
|
||||
}
|
||||
#endif /* !CC_BUILD_GL11 */
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*---------------------------------------------------------Textures--------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
@ -612,95 +711,4 @@ static void GLBackend_Init(void) {
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*----------------------------------------------------------Drawing--------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
#ifdef CC_BUILD_GL11
|
||||
/* point to client side dynamic array */
|
||||
#define VB_PTR ((cc_uint8*)dynamicListData)
|
||||
#define IB_PTR gl_indices
|
||||
#else
|
||||
/* no client side array, use vertex buffer object */
|
||||
#define VB_PTR 0
|
||||
#define IB_PTR NULL
|
||||
#endif
|
||||
|
||||
static void GL_SetupVbColoured(void) {
|
||||
_glVertexPointer(3, GL_FLOAT, SIZEOF_VERTEX_COLOURED, (void*)(VB_PTR + 0));
|
||||
_glColorPointer(4, GL_UNSIGNED_BYTE, SIZEOF_VERTEX_COLOURED, (void*)(VB_PTR + 12));
|
||||
}
|
||||
|
||||
static void GL_SetupVbTextured(void) {
|
||||
_glVertexPointer(3, GL_FLOAT, SIZEOF_VERTEX_TEXTURED, (void*)(VB_PTR + 0));
|
||||
_glColorPointer(4, GL_UNSIGNED_BYTE, SIZEOF_VERTEX_TEXTURED, (void*)(VB_PTR + 12));
|
||||
_glTexCoordPointer(2, GL_FLOAT, SIZEOF_VERTEX_TEXTURED, (void*)(VB_PTR + 16));
|
||||
}
|
||||
|
||||
static void GL_SetupVbColoured_Range(int startVertex) {
|
||||
cc_uint32 offset = startVertex * SIZEOF_VERTEX_COLOURED;
|
||||
_glVertexPointer(3, GL_FLOAT, SIZEOF_VERTEX_COLOURED, (void*)(VB_PTR + offset));
|
||||
_glColorPointer(4, GL_UNSIGNED_BYTE, SIZEOF_VERTEX_COLOURED, (void*)(VB_PTR + offset + 12));
|
||||
}
|
||||
|
||||
static void GL_SetupVbTextured_Range(int startVertex) {
|
||||
cc_uint32 offset = startVertex * SIZEOF_VERTEX_TEXTURED;
|
||||
_glVertexPointer(3, GL_FLOAT, SIZEOF_VERTEX_TEXTURED, (void*)(VB_PTR + offset));
|
||||
_glColorPointer(4, GL_UNSIGNED_BYTE, SIZEOF_VERTEX_TEXTURED, (void*)(VB_PTR + offset + 12));
|
||||
_glTexCoordPointer(2, GL_FLOAT, SIZEOF_VERTEX_TEXTURED, (void*)(VB_PTR + offset + 16));
|
||||
}
|
||||
|
||||
void Gfx_SetVertexFormat(VertexFormat fmt) {
|
||||
if (fmt == gfx_format) return;
|
||||
gfx_format = fmt;
|
||||
gfx_stride = strideSizes[fmt];
|
||||
|
||||
if (fmt == VERTEX_FORMAT_TEXTURED) {
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
gfx_setupVBFunc = GL_SetupVbTextured;
|
||||
gfx_setupVBRangeFunc = GL_SetupVbTextured_Range;
|
||||
} else {
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
gfx_setupVBFunc = GL_SetupVbColoured;
|
||||
gfx_setupVBRangeFunc = GL_SetupVbColoured_Range;
|
||||
}
|
||||
}
|
||||
|
||||
void Gfx_DrawVb_Lines(int verticesCount) {
|
||||
gfx_setupVBFunc();
|
||||
glDrawArrays(GL_LINES, 0, verticesCount);
|
||||
}
|
||||
|
||||
void Gfx_DrawVb_IndexedTris_Range(int verticesCount, int startVertex) {
|
||||
#ifdef CC_BUILD_GL11
|
||||
if (activeList != gl_DYNAMICLISTID) { glCallList(activeList); return; }
|
||||
#endif
|
||||
gfx_setupVBRangeFunc(startVertex);
|
||||
_glDrawElements(GL_TRIANGLES, ICOUNT(verticesCount), GL_UNSIGNED_SHORT, IB_PTR);
|
||||
}
|
||||
|
||||
void Gfx_DrawVb_IndexedTris(int verticesCount) {
|
||||
#ifdef CC_BUILD_GL11
|
||||
if (activeList != gl_DYNAMICLISTID) { glCallList(activeList); return; }
|
||||
#endif
|
||||
gfx_setupVBFunc();
|
||||
_glDrawElements(GL_TRIANGLES, ICOUNT(verticesCount), GL_UNSIGNED_SHORT, IB_PTR);
|
||||
}
|
||||
|
||||
#ifdef CC_BUILD_GL11
|
||||
void Gfx_DrawIndexedTris_T2fC4b(int verticesCount, int startVertex) { glCallList(activeList); }
|
||||
#else
|
||||
void Gfx_DrawIndexedTris_T2fC4b(int verticesCount, int startVertex) {
|
||||
cc_uint32 offset = startVertex * SIZEOF_VERTEX_TEXTURED;
|
||||
_glVertexPointer(3, GL_FLOAT, SIZEOF_VERTEX_TEXTURED, (void*)(VB_PTR + offset));
|
||||
_glColorPointer(4, GL_UNSIGNED_BYTE, SIZEOF_VERTEX_TEXTURED, (void*)(VB_PTR + offset + 12));
|
||||
_glTexCoordPointer(2, GL_FLOAT, SIZEOF_VERTEX_TEXTURED, (void*)(VB_PTR + offset + 16));
|
||||
_glDrawElements(GL_TRIANGLES, ICOUNT(verticesCount), GL_UNSIGNED_SHORT, IB_PTR);
|
||||
}
|
||||
#endif /* !CC_BUILD_GL11 */
|
||||
#endif
|
||||
|
@ -2,7 +2,6 @@
|
||||
#if defined CC_BUILD_GL && defined CC_BUILD_GLMODERN
|
||||
#include "_GraphicsBase.h"
|
||||
#include "Errors.h"
|
||||
#include "Logger.h"
|
||||
#include "Window.h"
|
||||
/* OpenGL 2.0 backend (alternative modern-ish backend) */
|
||||
|
||||
@ -125,16 +124,17 @@ void Gfx_DeleteIb(GfxResourceID* ib) {
|
||||
/*########################################################################################################################*
|
||||
*------------------------------------------------------Vertex buffers-----------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
GfxResourceID Gfx_CreateVb(VertexFormat fmt, int count) {
|
||||
static GfxResourceID Gfx_AllocStaticVb(VertexFormat fmt, int count) {
|
||||
return GL_GenAndBind(GL_ARRAY_BUFFER);
|
||||
}
|
||||
|
||||
void Gfx_BindVb(GfxResourceID vb) { glBindBuffer(GL_ARRAY_BUFFER, (GLuint)vb); }
|
||||
void Gfx_BindVb(GfxResourceID vb) {
|
||||
glBindBuffer(GL_ARRAY_BUFFER, (GLuint)vb);
|
||||
}
|
||||
|
||||
void Gfx_DeleteVb(GfxResourceID* vb) {
|
||||
GLuint id = (GLuint)(*vb);
|
||||
if (!id) return;
|
||||
glDeleteBuffers(1, &id);
|
||||
if (id) glDeleteBuffers(1, &id);
|
||||
*vb = 0;
|
||||
}
|
||||
|
||||
@ -150,17 +150,24 @@ void Gfx_UnlockVb(GfxResourceID vb) {
|
||||
/*########################################################################################################################*
|
||||
*--------------------------------------------------Dynamic vertex buffers-------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
GfxResourceID Gfx_CreateDynamicVb(VertexFormat fmt, int maxVertices) {
|
||||
GLuint id;
|
||||
cc_uint32 size;
|
||||
if (Gfx.LostContext) return 0;
|
||||
static GfxResourceID Gfx_AllocDynamicVb(VertexFormat fmt, int maxVertices) {
|
||||
GLuint id = GL_GenAndBind(GL_ARRAY_BUFFER);
|
||||
cc_uint32 size = maxVertices * strideSizes[fmt];
|
||||
|
||||
id = GL_GenAndBind(GL_ARRAY_BUFFER);
|
||||
size = maxVertices * strideSizes[fmt];
|
||||
glBufferData(GL_ARRAY_BUFFER, size, NULL, GL_DYNAMIC_DRAW);
|
||||
return id;
|
||||
}
|
||||
|
||||
void Gfx_BindDynamicVb(GfxResourceID vb) {
|
||||
glBindBuffer(GL_ARRAY_BUFFER, (GLuint)vb);
|
||||
}
|
||||
|
||||
void Gfx_DeleteDynamicVb(GfxResourceID* vb) {
|
||||
GLuint id = (GLuint)(*vb);
|
||||
if (id) glDeleteBuffers(1, &id);
|
||||
*vb = 0;
|
||||
}
|
||||
|
||||
void* Gfx_LockDynamicVb(GfxResourceID vb, VertexFormat fmt, int count) {
|
||||
return FastAllocTempMem(count * strideSizes[fmt]);
|
||||
}
|
||||
|
@ -494,10 +494,8 @@ void Gfx_DeleteIb(GfxResourceID* ib) { }
|
||||
/*########################################################################################################################*
|
||||
*------------------------------------------------------Vertex buffers-----------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
GfxResourceID Gfx_CreateVb(VertexFormat fmt, int count) {
|
||||
void* data = rsxMemalign(128, count * strideSizes[fmt]);
|
||||
if (!data) Logger_Abort("Failed to allocate memory for GFX VB");
|
||||
return data;
|
||||
static GfxResourceID Gfx_AllocStaticVb(VertexFormat fmt, int count) {
|
||||
return rsxMemalign(128, count * strideSizes[fmt]);
|
||||
}
|
||||
|
||||
void Gfx_BindVb(GfxResourceID vb) {
|
||||
@ -536,12 +534,12 @@ void Gfx_UnlockVb(GfxResourceID vb) {
|
||||
}
|
||||
|
||||
|
||||
GfxResourceID Gfx_CreateDynamicVb(VertexFormat fmt, int maxVertices) {
|
||||
void* data = rsxMemalign(128, maxVertices * strideSizes[fmt]);
|
||||
if (!data) Logger_Abort("Failed to allocate memory for GFX VB");
|
||||
return data;
|
||||
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;
|
||||
@ -568,7 +566,7 @@ typedef struct CCTexture_ {
|
||||
cc_uint32 pixels[];
|
||||
} CCTexture;
|
||||
|
||||
GfxResourceID Gfx_CreateTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps) {
|
||||
static GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps) {
|
||||
int size = bmp->width * bmp->height * 4;
|
||||
CCTexture* tex = (CCTexture*)rsxMemalign(128, 128 + size);
|
||||
|
||||
|
@ -114,7 +114,7 @@ typedef struct CCTexture_ {
|
||||
cc_uint32 pixels[];
|
||||
} CCTexture;
|
||||
|
||||
GfxResourceID Gfx_CreateTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps) {
|
||||
static GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps) {
|
||||
int size = bmp->width * bmp->height * 4;
|
||||
CCTexture* tex = (CCTexture*)memalign(16, 16 + size);
|
||||
|
||||
@ -284,11 +284,8 @@ void Gfx_BindIb(GfxResourceID ib) { }
|
||||
void Gfx_DeleteIb(GfxResourceID* ib) { }
|
||||
|
||||
|
||||
GfxResourceID Gfx_CreateVb(VertexFormat fmt, int count) {
|
||||
void* data = memalign(16, count * strideSizes[fmt]);
|
||||
if (!data) Logger_Abort("Failed to allocate memory for GFX VB");
|
||||
return data;
|
||||
//return Mem_Alloc(count, strideSizes[fmt], "gfx VB");
|
||||
static GfxResourceID Gfx_AllocStaticVb(VertexFormat fmt, int count) {
|
||||
return memalign(16, count * strideSizes[fmt]);
|
||||
}
|
||||
|
||||
void Gfx_BindVb(GfxResourceID vb) { gfx_vertices = vb; }
|
||||
@ -310,13 +307,12 @@ void Gfx_UnlockVb(GfxResourceID vb) {
|
||||
}
|
||||
|
||||
|
||||
GfxResourceID Gfx_CreateDynamicVb(VertexFormat fmt, int maxVertices) {
|
||||
void* data = memalign(16, maxVertices * strideSizes[fmt]);
|
||||
if (!data) Logger_Abort("Failed to allocate memory for GFX VB");
|
||||
return data;
|
||||
//return Mem_Alloc(maxVertices, strideSizes[fmt], "gfx VB");
|
||||
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;
|
||||
|
@ -661,7 +661,7 @@ static void GPUTextures_DeleteUnreferenced(void) {
|
||||
/*########################################################################################################################*
|
||||
*---------------------------------------------------------Textures--------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
GfxResourceID Gfx_CreateTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps) {
|
||||
static GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps) {
|
||||
int size = bmp->width * bmp->height * 4;
|
||||
struct GPUTexture* tex = GPUTexture_Alloc(size);
|
||||
Mem_Copy(tex->data, bmp->scan0, size);
|
||||
@ -891,7 +891,7 @@ void Gfx_DeleteIb(GfxResourceID* ib) { GPUBuffer_Unref(ib); }
|
||||
/*########################################################################################################################*
|
||||
*-------------------------------------------------------Vertex buffers----------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
GfxResourceID Gfx_CreateVb(VertexFormat fmt, int count) {
|
||||
static GfxResourceID Gfx_AllocStaticVb(VertexFormat fmt, int count) {
|
||||
return GPUBuffer_Alloc(count * strideSizes[fmt]);
|
||||
}
|
||||
|
||||
@ -911,10 +911,12 @@ void* Gfx_LockVb(GfxResourceID vb, VertexFormat fmt, int count) {
|
||||
void Gfx_UnlockVb(GfxResourceID vb) { Gfx_BindVb(vb); }
|
||||
|
||||
|
||||
GfxResourceID Gfx_CreateDynamicVb(VertexFormat fmt, int maxVertices) {
|
||||
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;
|
||||
|
@ -198,7 +198,7 @@ static void ConvertTexture(cc_uint32* dst, struct Bitmap* bmp) {
|
||||
}
|
||||
}
|
||||
|
||||
GfxResourceID Gfx_CreateTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps) {
|
||||
static GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps) {
|
||||
int size = 16 + bmp->width * bmp->height * 4;
|
||||
CCTexture* tex = MmAllocateContiguousMemoryEx(size, 0, MAX_RAM_ADDR, 0, 0x404);
|
||||
|
||||
@ -394,10 +394,7 @@ static cc_uint8* gfx_vertices;
|
||||
static cc_uint16* gfx_indices;
|
||||
|
||||
static void* AllocBuffer(int count, int elemSize) {
|
||||
void* ptr = MmAllocateContiguousMemoryEx(count * elemSize, 0, MAX_RAM_ADDR, 0, PAGE_WRITECOMBINE | PAGE_READWRITE);
|
||||
|
||||
if (!ptr) Logger_Abort("Failed to allocate memory for buffer");
|
||||
return ptr;
|
||||
return MmAllocateContiguousMemoryEx(count * elemSize, 0, MAX_RAM_ADDR, 0, PAGE_WRITECOMBINE | PAGE_READWRITE);
|
||||
}
|
||||
|
||||
static void FreeBuffer(GfxResourceID* buffer) {
|
||||
@ -409,6 +406,8 @@ static void FreeBuffer(GfxResourceID* buffer) {
|
||||
|
||||
GfxResourceID Gfx_CreateIb2(int count, Gfx_FillIBFunc fillFunc, void* obj) {
|
||||
void* ib = AllocBuffer(count, sizeof(cc_uint16));
|
||||
if (!ib) Logger_Abort("Failed to allocate memory for index buffer");
|
||||
|
||||
fillFunc(ib, count, obj);
|
||||
return ib;
|
||||
}
|
||||
@ -418,7 +417,7 @@ void Gfx_BindIb(GfxResourceID ib) { gfx_indices = ib; }
|
||||
void Gfx_DeleteIb(GfxResourceID* ib) { FreeBuffer(ib); }
|
||||
|
||||
|
||||
GfxResourceID Gfx_CreateVb(VertexFormat fmt, int count) {
|
||||
static GfxResourceID Gfx_AllocStaticVb(VertexFormat fmt, int count) {
|
||||
return AllocBuffer(count, strideSizes[fmt]);
|
||||
}
|
||||
|
||||
@ -450,10 +449,12 @@ void* Gfx_LockVb(GfxResourceID vb, VertexFormat fmt, int count) { return vb; }
|
||||
void Gfx_UnlockVb(GfxResourceID vb) { }
|
||||
|
||||
|
||||
GfxResourceID Gfx_CreateDynamicVb(VertexFormat fmt, int maxVertices) {
|
||||
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;
|
||||
}
|
||||
|
@ -144,7 +144,9 @@ void Model_SetupState(struct Model* model, struct Entity* e) {
|
||||
|
||||
void Model_UpdateVB(void) {
|
||||
struct Model* model = Models.Active;
|
||||
Gfx_UpdateDynamicVb_IndexedTris(Models.Vb, Models.Vertices, model->index);
|
||||
|
||||
Gfx_SetDynamicVbData(Models.Vb, Models.Vertices, model->index);
|
||||
Gfx_DrawVb_IndexedTris(model->index);
|
||||
model->index = 0;
|
||||
}
|
||||
|
||||
|
@ -108,7 +108,6 @@ static int selections_count;
|
||||
static struct SelectionBox selections_list[SELECTIONS_MAX];
|
||||
static cc_uint8 selections_ids[SELECTIONS_MAX];
|
||||
static GfxResourceID selections_VB, selections_LineVB;
|
||||
static cc_bool selections_used;
|
||||
|
||||
void Selections_Add(cc_uint8 id, const IVec3* p1, const IVec3* p2, PackedCol color) {
|
||||
struct SelectionBox sel;
|
||||
@ -142,10 +141,9 @@ static void Selections_ContextLost(void* obj) {
|
||||
Gfx_DeleteDynamicVb(&selections_LineVB);
|
||||
}
|
||||
|
||||
static void Selections_ContextRecreated(void* obj) {
|
||||
if (!selections_used) return;
|
||||
Gfx_RecreateDynamicVb(&selections_VB, VERTEX_FORMAT_COLOURED, SELECTIONS_MAX_VERTICES);
|
||||
Gfx_RecreateDynamicVb(&selections_LineVB, VERTEX_FORMAT_COLOURED, SELECTIONS_MAX_VERTICES);
|
||||
static void AllocateVertexBuffers(void) {
|
||||
selections_VB = Gfx_CreateDynamicVb(VERTEX_FORMAT_COLOURED, SELECTIONS_MAX_VERTICES);
|
||||
selections_LineVB = Gfx_CreateDynamicVb(VERTEX_FORMAT_COLOURED, SELECTIONS_MAX_VERTICES);
|
||||
}
|
||||
|
||||
static void Selections_QuickSort(int left, int right) {
|
||||
@ -181,10 +179,9 @@ void Selections_Render(void) {
|
||||
}
|
||||
Selections_QuickSort(0, selections_count - 1);
|
||||
|
||||
if (!selections_VB) { /* lazy init as most servers don't use this */
|
||||
selections_used = true;
|
||||
Selections_ContextRecreated(NULL);
|
||||
}
|
||||
/* lazy init as most servers don't use this */
|
||||
if (!selections_VB) AllocateVertexBuffers();
|
||||
|
||||
count = selections_count * SELECTIONS_VERTICES;
|
||||
Gfx_SetVertexFormat(VERTEX_FORMAT_COLOURED);
|
||||
|
||||
@ -215,8 +212,7 @@ void Selections_Render(void) {
|
||||
*--------------------------------------------------Selections component---------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
static void OnInit(void) {
|
||||
Event_Register_(&GfxEvents.ContextLost, NULL, Selections_ContextLost);
|
||||
Event_Register_(&GfxEvents.ContextRecreated, NULL, Selections_ContextRecreated);
|
||||
Event_Register_(&GfxEvents.ContextLost, NULL, Selections_ContextLost);
|
||||
}
|
||||
|
||||
static void OnReset(void) { selections_count = 0; }
|
||||
|
@ -102,17 +102,12 @@ static void Gfx_DoMipmaps(int x, int y, struct Bitmap* bmp, int rowWidth, cc_boo
|
||||
if (prev != bmp->scan0) Mem_Free(prev);
|
||||
}
|
||||
|
||||
GfxResourceID Gfx_CreateTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps) {
|
||||
static GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps) {
|
||||
GLuint texId;
|
||||
glGenTextures(1, &texId);
|
||||
glBindTexture(GL_TEXTURE_2D, texId);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
|
||||
if (!Math_IsPowOf2(bmp->width) || !Math_IsPowOf2(bmp->height)) {
|
||||
Logger_Abort("Textures must have power of two dimensions");
|
||||
}
|
||||
if (Gfx.LostContext) return 0;
|
||||
|
||||
if (mipmaps) {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
|
||||
if (customMipmapsLevels) {
|
||||
@ -163,8 +158,7 @@ void Gfx_UpdateTexturePart(GfxResourceID texId, int x, int y, struct Bitmap* par
|
||||
|
||||
void Gfx_DeleteTexture(GfxResourceID* texId) {
|
||||
GLuint id = (GLuint)(*texId);
|
||||
if (!id) return;
|
||||
glDeleteTextures(1, &id);
|
||||
if (id) glDeleteTextures(1, &id);
|
||||
*texId = 0;
|
||||
}
|
||||
|
||||
|
@ -9,13 +9,14 @@
|
||||
#include "Options.h"
|
||||
#include "Bitmap.h"
|
||||
#include "Chat.h"
|
||||
#include "Logger.h"
|
||||
|
||||
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[2] = { SIZEOF_VERTEX_COLOURED, SIZEOF_VERTEX_TEXTURED };
|
||||
static const int strideSizes[] = { SIZEOF_VERTEX_COLOURED, SIZEOF_VERTEX_TEXTURED };
|
||||
/* Whether mipmaps must be created for all dimensions down to 1x1 or not */
|
||||
static cc_bool customMipmapsLevels;
|
||||
|
||||
@ -142,44 +143,47 @@ void* Gfx_RecreateAndLockVb(GfxResourceID* vb, VertexFormat fmt, int count) {
|
||||
return Gfx_LockVb(*vb, fmt, count);
|
||||
}
|
||||
|
||||
void Gfx_UpdateDynamicVb_IndexedTris(GfxResourceID vb, void* vertices, int vCount) {
|
||||
Gfx_SetDynamicVbData(vb, vertices, vCount);
|
||||
Gfx_DrawVb_IndexedTris(vCount);
|
||||
}
|
||||
|
||||
#ifndef CC_BUILD_3DS
|
||||
void Gfx_Draw2DFlat(int x, int y, int width, int height, PackedCol color) {
|
||||
struct VertexColoured verts[4];
|
||||
struct VertexColoured* v = verts;
|
||||
struct VertexColoured* v;
|
||||
|
||||
Gfx_SetVertexFormat(VERTEX_FORMAT_COLOURED);
|
||||
v = (struct VertexColoured*)Gfx_LockDynamicVb(Gfx_quadVb, VERTEX_FORMAT_COLOURED, 4);
|
||||
|
||||
v->X = (float)x; v->Y = (float)y; v->Z = 0; v->Col = color; v++;
|
||||
v->X = (float)(x + width); v->Y = (float)y; v->Z = 0; v->Col = color; v++;
|
||||
v->X = (float)(x + width); v->Y = (float)(y + height); v->Z = 0; v->Col = color; v++;
|
||||
v->X = (float)x; v->Y = (float)(y + height); v->Z = 0; v->Col = color; v++;
|
||||
|
||||
Gfx_SetVertexFormat(VERTEX_FORMAT_COLOURED);
|
||||
Gfx_UpdateDynamicVb_IndexedTris(Gfx_quadVb, verts, 4);
|
||||
Gfx_UnlockDynamicVb(Gfx_quadVb);
|
||||
Gfx_DrawVb_IndexedTris(4);
|
||||
}
|
||||
|
||||
void Gfx_Draw2DGradient(int x, int y, int width, int height, PackedCol top, PackedCol bottom) {
|
||||
struct VertexColoured verts[4];
|
||||
struct VertexColoured* v = verts;
|
||||
struct VertexColoured* v;
|
||||
|
||||
Gfx_SetVertexFormat(VERTEX_FORMAT_COLOURED);
|
||||
v = (struct VertexColoured*)Gfx_LockDynamicVb(Gfx_quadVb, VERTEX_FORMAT_COLOURED, 4);
|
||||
|
||||
v->X = (float)x; v->Y = (float)y; v->Z = 0; v->Col = top; v++;
|
||||
v->X = (float)(x + width); v->Y = (float)y; v->Z = 0; v->Col = top; v++;
|
||||
v->X = (float)(x + width); v->Y = (float)(y + height); v->Z = 0; v->Col = bottom; v++;
|
||||
v->X = (float)x; v->Y = (float)(y + height); v->Z = 0; v->Col = bottom; v++;
|
||||
|
||||
Gfx_SetVertexFormat(VERTEX_FORMAT_COLOURED);
|
||||
Gfx_UpdateDynamicVb_IndexedTris(Gfx_quadVb, verts, 4);
|
||||
Gfx_UnlockDynamicVb(Gfx_quadVb);
|
||||
Gfx_DrawVb_IndexedTris(4);
|
||||
}
|
||||
|
||||
void Gfx_Draw2DTexture(const struct Texture* tex, PackedCol color) {
|
||||
struct VertexTextured texVerts[4];
|
||||
struct VertexTextured* ptr = texVerts;
|
||||
Gfx_Make2DQuad(tex, color, &ptr);
|
||||
struct VertexTextured* ptr;
|
||||
|
||||
Gfx_SetVertexFormat(VERTEX_FORMAT_TEXTURED);
|
||||
Gfx_UpdateDynamicVb_IndexedTris(Gfx_texVb, texVerts, 4);
|
||||
ptr = (struct VertexTextured*)Gfx_LockDynamicVb(Gfx_texVb, VERTEX_FORMAT_TEXTURED, 4);
|
||||
|
||||
Gfx_Make2DQuad(tex, color, &ptr);
|
||||
|
||||
Gfx_UnlockDynamicVb(Gfx_texVb);
|
||||
Gfx_DrawVb_IndexedTris(4);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -333,6 +337,17 @@ static CC_NOINLINE int CalcMipmapsLevels(int width, int height) {
|
||||
}
|
||||
}
|
||||
|
||||
static GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps);
|
||||
|
||||
GfxResourceID Gfx_CreateTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps) {
|
||||
if (!Math_IsPowOf2(bmp->width) || !Math_IsPowOf2(bmp->height)) {
|
||||
Logger_Abort("Textures must have power of two dimensions");
|
||||
}
|
||||
if (Gfx.LostContext) return 0;
|
||||
|
||||
return Gfx_AllocTexture(bmp, flags, mipmaps);
|
||||
}
|
||||
|
||||
void Texture_Render(const struct Texture* tex) {
|
||||
Gfx_BindTexture(tex->ID);
|
||||
Gfx_Draw2DTexture(tex, PACKEDCOL_WHITE);
|
||||
@ -344,6 +359,37 @@ void Texture_RenderShaded(const struct Texture* tex, PackedCol shadeColor) {
|
||||
}
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*------------------------------------------------------Vertex buffers-----------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
static GfxResourceID Gfx_AllocStaticVb( VertexFormat fmt, int count);
|
||||
static GfxResourceID Gfx_AllocDynamicVb(VertexFormat fmt, int maxVertices);
|
||||
|
||||
GfxResourceID Gfx_CreateVb(VertexFormat fmt, int count) {
|
||||
GfxResourceID vb;
|
||||
/* if (Gfx.LostContext) return 0; TODO check this ???? probably breaks things */
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if ((vb = Gfx_AllocStaticVb(fmt, count))) return vb;
|
||||
|
||||
if (!Game_ReduceVRAM()) Logger_Abort("Out of video memory! (allocating static VB)");
|
||||
}
|
||||
}
|
||||
|
||||
GfxResourceID Gfx_CreateDynamicVb(VertexFormat fmt, int maxVertices) {
|
||||
GfxResourceID vb;
|
||||
if (Gfx.LostContext) return 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if ((vb = Gfx_AllocDynamicVb(fmt, maxVertices))) return vb;
|
||||
|
||||
if (!Game_ReduceVRAM()) Logger_Abort("Out of video memory! (allocating dynamic VB)");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*----------------------------------------------------Graphics component---------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
|
Loading…
x
Reference in New Issue
Block a user