Rudimentary lighting palette and memory test

This commit is contained in:
Goodlyay 2022-06-27 04:48:08 -07:00
parent d3d31a874c
commit f03b538abb
4 changed files with 224 additions and 15 deletions

View File

@ -7,6 +7,11 @@
#include "Logger.h"
#include "Event.h"
#include "Game.h"
#include "String.h"
#include "Chat.h"
#include "ExtMath.h"
#include "Options.h"
cc_bool Lighting_Modern;
struct _Lighting Lighting;
#define Lighting_Pack(x, z) ((x) + World.Width * (z))
@ -99,6 +104,156 @@ static void ClassicLighting_Refresh(void) {
}
/*########################################################################################################################*
*----------------------------------------------------Modern lighting------------------------------------------------------*
*#########################################################################################################################*/
/* TODO: Evil goodly hack, move chunk variables to World.h */
int ModernLighting_ChunkCount;
int ModernLighting_ChunksX;
int ModernLighting_ChunksY;
int ModernLighting_ChunksZ;
/* A 16x16 palette of sun and block light colors. */
/* It is indexed by a byte where the leftmost 4 bits represent sunlight level and the rightmost 4 bits represent blocklight level */
/* E.G. modernLighting_palette[0b_0010_0001] will give us the color for sun level 2 and block level 1 (lowest level is 0) */
static PackedCol modernLighting_palette[MODERN_LIGHTING_LEVELS * MODERN_LIGHTING_LEVELS];
typedef cc_uint8* LightingChunk;
static cc_uint8* chunkLightingDataFlags;
#define CHUNK_UNCALCULATED 0
#define CHUNK_CALCULATED 1
#define CHUNK_ALL_DARK 2
static LightingChunk* chunkLightingData;
static cc_uint8 allDarkChunkLightingData[CHUNK_SIZE_3];
#define Modern_MakePaletteIndex(sun, block) ((sun << MODERN_LIGHTING_SUN_SHIFT) | block)
/* Fill in modernLighting_palette with values based on the current environment colors in lieu of recieving a palette from the server */
static void ModernLighting_InitPalette(void) {
PackedCol darkestShadow, defaultBlockLight, blockColor, sunColor, invertedBlockColor, invertedSunColor, finalColor;
int sunLevel, blockLevel;
float blockLerp;
cc_uint8 R, G, B;
defaultBlockLight = PackedCol_Make(255, 238, 204, 255); /* A very mildly orange tinted light color */
darkestShadow = PackedCol_Lerp(Env.ShadowCol, 0, 0.75f); /* Use a darkened version of shadow color as the darkest color in sun ramp */
for (sunLevel = 0; sunLevel < MODERN_LIGHTING_LEVELS; sunLevel++) {
for (blockLevel = 0; blockLevel < MODERN_LIGHTING_LEVELS; blockLevel++) {
/* We want the brightest light level to be the sun env color, with all other 15 levels being interpolation */
/* between shadow color and darkest shadow color */
if (sunLevel == MODERN_LIGHTING_LEVELS-1) {
sunColor = Env.SunCol;
}
else {
sunColor = PackedCol_Lerp(darkestShadow, Env.ShadowCol, sunLevel / (float)(MODERN_LIGHTING_LEVELS - 2) );
}
blockLerp = blockLevel / (float)(MODERN_LIGHTING_LEVELS-1);
blockLerp *= blockLerp;
blockLerp *= (MATH_PI / 2);
blockLerp = Math_Cos(blockLerp);
blockColor = PackedCol_Lerp(0, defaultBlockLight, 1 - blockLerp);
/* With Screen blend mode, the values of the pixels in the two layers are inverted, multiplied, and then inverted again. */
R = 255 - PackedCol_R(sunColor);
G = 255 - PackedCol_G(sunColor);
B = 255 - PackedCol_B(sunColor);
invertedSunColor = PackedCol_Make(R, G, B, 255);
R = 255 - PackedCol_R(blockColor);
G = 255 - PackedCol_G(blockColor);
B = 255 - PackedCol_B(blockColor);
invertedBlockColor = PackedCol_Make(R, G, B, 255);
finalColor = PackedCol_Tint(invertedSunColor, invertedBlockColor);
R = 255 - PackedCol_R(finalColor);
G = 255 - PackedCol_G(finalColor);
B = 255 - PackedCol_B(finalColor);
modernLighting_palette[Modern_MakePaletteIndex(sunLevel, blockLevel)] = PackedCol_Make(R, G, B, 255);
}
}
}
static void ModernLighting_AllocState(void) {
ModernLighting_InitPalette();
ModernLighting_ChunksX = (World.Width + CHUNK_MAX) >> CHUNK_SHIFT;
ModernLighting_ChunksY = (World.Height + CHUNK_MAX) >> CHUNK_SHIFT;
ModernLighting_ChunksZ = (World.Length + CHUNK_MAX) >> CHUNK_SHIFT;
ModernLighting_ChunkCount = ModernLighting_ChunksX * ModernLighting_ChunksY * ModernLighting_ChunksZ;
chunkLightingDataFlags = (cc_uint8*)Mem_TryAllocCleared(ModernLighting_ChunkCount, sizeof(cc_uint8));
chunkLightingData = (LightingChunk*)Mem_TryAllocCleared(ModernLighting_ChunkCount, sizeof(LightingChunk));
}
static void ModernLighting_FreeState(void) {
int i;
/* This function can be called multiple times without calling ModernLighting_AllocState, so... */
if (chunkLightingDataFlags == NULL) { return; }
for (i = 0; i < ModernLighting_ChunkCount; i++) {
if (chunkLightingDataFlags[i] > CHUNK_CALCULATED || chunkLightingDataFlags[i] == CHUNK_UNCALCULATED) { continue; }
Mem_Free(chunkLightingData[i]);
}
Mem_Free(chunkLightingDataFlags);
Mem_Free(chunkLightingData);
chunkLightingDataFlags = NULL;
chunkLightingData = NULL;
}
/* Gives the index into array of chunk pointers based on chunk x y z */
#define ChunkIndex(x, y, z) (((y) * ModernLighting_ChunksZ + (z)) * ModernLighting_ChunksX + (x))
/* Gives the index into array of chunk data */
#define ChunkDataIndex(x, y, z) (((y) * CHUNK_SIZE + (z)) * CHUNK_SIZE + (x))
static void CalculateChunkLighting(int chunkIndex) {
int i;
chunkLightingData[chunkIndex] = (cc_uint8*)Mem_TryAlloc(CHUNK_SIZE_3, sizeof(cc_uint8));
for (i = 0; i < CHUNK_SIZE_3; i++) {
chunkLightingData[chunkIndex][i] = i % 256;
}
}
static void ModernLighting_LightHint(void) { } /* ??? */
static void ModernLighting_OnBlockChanged(void) { }
static void ModernLighting_Refresh(void) {
ModernLighting_InitPalette();
/* Set all the chunk lighting data flags to CHUNK_UNCALCULATED? */
}
static cc_bool ModernLighting_IsLit(int x, int y, int z) { return true; }
static cc_bool ModernLighting_IsLit_Fast(int x, int y, int z) { return true; }
static PackedCol ModernLighting_Color(int x, int y, int z) {
if (!World_Contains(x, y, z)) return Env.SunCol;
//cc_uint8 thing = y % MODERN_LIGHTING_LEVELS;
//cc_uint8 thing2 = z % MODERN_LIGHTING_LEVELS;
//return y * z * x;
int cx, cy, cz;
int dx, dy, dz;
int chunkIndex;
int chunkDataIndex;
cx = x / CHUNK_SIZE;
cy = y / CHUNK_SIZE;
cz = z / CHUNK_SIZE;
chunkIndex = ChunkIndex(cx, cy, cz);
//cc_string msg; char msgBuffer[STRING_SIZE * 2]; String_InitArray(msg, msgBuffer);
//String_Format3(&msg, "Hi x %i, y %i, z %i", &cx, &cy, &cz);
//Logger_Log(&msg);
if (chunkLightingDataFlags[chunkIndex] == CHUNK_UNCALCULATED) {
CalculateChunkLighting(chunkIndex);
chunkLightingDataFlags[chunkIndex] = CHUNK_CALCULATED;
}
/* Get coordinates into the chunk data*/
dx = x % CHUNK_SIZE;
dy = y % CHUNK_SIZE;
dz = z % CHUNK_SIZE;
chunkDataIndex = ChunkDataIndex(dx, dy, dz);
cc_uint8 lightData = chunkLightingData[chunkIndex]
[chunkDataIndex];
return modernLighting_palette[lightData];
}
/*########################################################################################################################*
*----------------------------------------------------Lighting update------------------------------------------------------*
*#########################################################################################################################*/
@ -392,13 +547,46 @@ static void ClassicLighting_SetActive(void) {
Lighting.AllocState = ClassicLighting_AllocState;
Lighting.LightHint = ClassicLighting_LightHint;
}
static void ModernLighting_SetActive(void) {
Lighting.OnBlockChanged = ModernLighting_OnBlockChanged;
Lighting.Refresh = ModernLighting_Refresh;
Lighting.IsLit = ModernLighting_IsLit;
Lighting.Color = ModernLighting_Color;
Lighting.Color_XSide = ModernLighting_Color;
Lighting.IsLit_Fast = ModernLighting_IsLit_Fast;
Lighting.Color_Sprite_Fast = ModernLighting_Color;
Lighting.Color_YMax_Fast = ModernLighting_Color;
Lighting.Color_YMin_Fast = ModernLighting_Color;
Lighting.Color_XSide_Fast = ModernLighting_Color;
Lighting.Color_ZSide_Fast = ModernLighting_Color;
Lighting.FreeState = ModernLighting_FreeState;
Lighting.AllocState = ModernLighting_AllocState;
Lighting.LightHint = ModernLighting_LightHint;
}
static void Lighting_ApplyActive(void) {
if (Lighting_Modern) {
ModernLighting_SetActive();
}
else {
ClassicLighting_SetActive();
}
}
void Lighting_SwitchActive(void) {
Lighting.FreeState();
Lighting_ApplyActive();
Lighting.AllocState();
}
/*########################################################################################################################*
*---------------------------------------------------Lighting component----------------------------------------------------*
*#########################################################################################################################*/
static void OnInit(void) { ClassicLighting_SetActive(); }
static void OnInit(void) {
if (!Game_ClassicMode) Lighting_Modern = Options_GetBool(OPT_MODERN_LIGHTING, false);
Lighting_ApplyActive();
}
static void OnReset(void) { Lighting.FreeState(); }
static void OnNewMapLoaded(void) { Lighting.AllocState(); }

View File

@ -10,6 +10,12 @@ Copyright 2014-2022 ClassiCube | Licensed under BSD-3
*/
struct IGameComponent;
extern struct IGameComponent Lighting_Component;
/* Whether MC-style 16-level lighting should be used. */
extern cc_bool Lighting_Modern;
/* How many unique "levels" of light there are when modern lighting is used. */
#define MODERN_LIGHTING_LEVELS 16
/* How many bits to shift sunlight level to the left when storing it in a byte along with blocklight level*/
#define MODERN_LIGHTING_SUN_SHIFT 4
CC_VAR extern struct _Lighting {
/* Releases/Frees the per-level lighting state */
@ -49,4 +55,6 @@ CC_VAR extern struct _Lighting {
PackedCol (*Color_XSide_Fast)(int x, int y, int z);
PackedCol (*Color_ZSide_Fast)(int x, int y, int z);
} Lighting;
void Lighting_SwitchActive(void);
#endif

View File

@ -27,6 +27,7 @@
#include "Deflate.h"
#include "Stream.h"
#include "Builder.h"
#include "Lighting.h"
#include "Logger.h"
#include "Options.h"
#include "Input.h"
@ -2739,6 +2740,13 @@ static void GraphicsOptionsScreen_SetSmooth(const cc_string* v) {
Builder_ApplyActive();
MapRenderer_Refresh();
}
static void GraphicsOptionsScreen_GetModernLighting(cc_string* v) { Menu_GetBool(v, Lighting_Modern); }
static void GraphicsOptionsScreen_SetModernLighting(const cc_string* v) {
Lighting_Modern = Menu_SetBool(v, OPT_MODERN_LIGHTING);
Lighting_SwitchActive();
Builder_ApplyActive();
MapRenderer_Refresh();
}
static void GraphicsOptionsScreen_GetCamera(cc_string* v) { Menu_GetBool(v, Camera.Smooth); }
static void GraphicsOptionsScreen_SetCamera(const cc_string* v) { Camera.Smooth = Menu_SetBool(v, OPT_CAMERA_SMOOTH); }
@ -2767,34 +2775,37 @@ static void GraphicsOptionsScreen_SetCameraMass(const cc_string* c) {
Options_Set(OPT_CAMERA_MASS, c);
}
#define GraphicsOptionsButtonCount 9
static void GraphicsOptionsScreen_InitWidgets(struct MenuOptionsScreen* s) {
static const struct MenuOptionDesc buttons[8] = {
{ -1, -100, "Camera Mass", MenuOptionsScreen_Input,
static const struct MenuOptionDesc buttons[GraphicsOptionsButtonCount] = {
{ -1, -150, "Camera Mass", MenuOptionsScreen_Input,
GraphicsOptionsScreen_GetCameraMass, GraphicsOptionsScreen_SetCameraMass },
{ -1, -50, "FPS mode", MenuOptionsScreen_Enum,
{ -1, -100, "FPS mode", MenuOptionsScreen_Enum,
MenuOptionsScreen_GetFPS, MenuOptionsScreen_SetFPS },
{ -1, 0, "View distance", MenuOptionsScreen_Input,
{ -1, -50, "View distance", MenuOptionsScreen_Input,
GraphicsOptionsScreen_GetViewDist, GraphicsOptionsScreen_SetViewDist },
{ -1, 50, "Advanced lighting", MenuOptionsScreen_Bool,
{ -1, 0, "Smooth lighting", MenuOptionsScreen_Bool,
GraphicsOptionsScreen_GetSmooth, GraphicsOptionsScreen_SetSmooth },
{ -1, 50, "Modern lighting", MenuOptionsScreen_Bool,
GraphicsOptionsScreen_GetModernLighting, GraphicsOptionsScreen_SetModernLighting },
{ 1, -100, "Smooth camera", MenuOptionsScreen_Bool,
{ 1, -150, "Smooth camera", MenuOptionsScreen_Bool,
GraphicsOptionsScreen_GetCamera, GraphicsOptionsScreen_SetCamera },
{ 1, -50, "Names", MenuOptionsScreen_Enum,
{ 1, -100, "Names", MenuOptionsScreen_Enum,
GraphicsOptionsScreen_GetNames, GraphicsOptionsScreen_SetNames },
{ 1, 0, "Shadows", MenuOptionsScreen_Enum,
{ 1, -50, "Shadows", MenuOptionsScreen_Enum,
GraphicsOptionsScreen_GetShadows, GraphicsOptionsScreen_SetShadows },
{ 1, 50, "Mipmaps", MenuOptionsScreen_Bool,
{ 1, 0, "Mipmaps", MenuOptionsScreen_Bool,
GraphicsOptionsScreen_GetMipmaps, GraphicsOptionsScreen_SetMipmaps }
};
s->numCore = 8;
s->maxVertices += 8 * BUTTONWIDGET_MAX;
s->numCore = GraphicsOptionsButtonCount;
s->maxVertices += GraphicsOptionsButtonCount * BUTTONWIDGET_MAX;
MenuOptionsScreen_InitButtons(s, buttons, Array_Elems(buttons), Menu_SwitchOptions);
}
void GraphicsOptionsScreen_Show(void) {
static struct MenuInputDesc descs[8];
static struct MenuInputDesc descs[GraphicsOptionsButtonCount];
static const char* extDescs[Array_Elems(descs)];
extDescs[0] = "&eChange the smoothness of the smooth camera.";
@ -2804,13 +2815,14 @@ void GraphicsOptionsScreen_Show(void) {
"&eNoLimit: &fRenders as many frames as possible each second.\n" \
"&cNoLimit is pointless - it wastefully renders frames that you don't even see!";
extDescs[3] = "&cNote: &eSmooth lighting is still experimental and can heavily reduce performance.";
extDescs[5] = \
extDescs[4] = "&cNote: &eModern lighting will reduce performance and increase memory usage.";
extDescs[6] = \
"&eNone: &fNo names of players are drawn.\n" \
"&eHovered: &fName of the targeted player is drawn see-through.\n" \
"&eAll: &fNames of all other players are drawn normally.\n" \
"&eAllHovered: &fAll names of players are drawn see-through.\n" \
"&eAllUnscaled: &fAll names of players are drawn see-through without scaling.";
extDescs[6] = \
extDescs[7] = \
"&eNone: &fNo entity shadows are drawn.\n" \
"&eSnapToBlock: &fA square shadow is shown on block you are directly above.\n" \
"&eCircle: &fA circular shadow is shown across the blocks you are above.\n" \

View File

@ -23,6 +23,7 @@ Copyright 2014-2022 ClassiCube | Licensed under BSD-3
#define OPT_ENTITY_SHADOW "entityshadow"
#define OPT_RENDER_TYPE "normal"
#define OPT_SMOOTH_LIGHTING "gfx-smoothlighting"
#define OPT_MODERN_LIGHTING "gfx-modernlighting"
#define OPT_MIPMAPS "gfx-mipmaps"
#define OPT_CHAT_LOGGING "chat-logging"
#define OPT_WINDOW_WIDTH "window-width"