use more efficient bitmapcol

This commit is contained in:
UnknownShadow200 2018-11-16 15:05:51 +11:00
parent ad78ab8d0d
commit e7738b50fa
27 changed files with 307 additions and 302 deletions

View File

@ -23,10 +23,9 @@ static float L_flameHeat[LIQUID_ANIM_MAX * LIQUID_ANIM_MAX];
static RNGState L_rnd;
static bool L_rndInitalised;
static void LavaAnimation_Tick(uint32_t* ptr, int size) {
static void LavaAnimation_Tick(BitmapCol* ptr, int size) {
int mask = size - 1, shift = Math_Log2(size);
float soupHeat, potHeat, col;
uint8_t r, g, b;
int x, y, i = 0;
if (!L_rndInitalised) {
@ -74,10 +73,10 @@ static void LavaAnimation_Tick(uint32_t* ptr, int size) {
col = 2.0f * L_soupHeat[i];
Math_Clamp(col, 0.0f, 1.0f);
r = (uint8_t)(col * 100.0f + 155.0f);
g = (uint8_t)(col * col * 255.0f);
b = (uint8_t)(col * col * col * col * 128.0f);
*ptr = PackedCol_ARGB(r, g, b, 255);
ptr->R = (uint8_t)(col * 100.0f + 155.0f);
ptr->G = (uint8_t)(col * col * 255.0f);
ptr->B = (uint8_t)(col * col * col * col * 128.0f);
ptr->A = 255;
ptr++; i++;
}
@ -94,10 +93,9 @@ static float W_flameHeat[LIQUID_ANIM_MAX * LIQUID_ANIM_MAX];
static RNGState W_rnd;
static bool W_rndInitalised;
static void WaterAnimation_Tick(uint32_t* ptr, int size) {
static void WaterAnimation_Tick(BitmapCol* ptr, int size) {
int mask = size - 1, shift = Math_Log2(size);
float soupHeat, col;
uint8_t r, g, a;
int x, y, i = 0;
if (!W_rndInitalised) {
@ -126,10 +124,10 @@ static void WaterAnimation_Tick(uint32_t* ptr, int size) {
Math_Clamp(col, 0.0f, 1.0f);
col = col * col;
r = (uint8_t)(32.0f + col * 32.0f);
g = (uint8_t)(50.0f + col * 64.0f);
a = (uint8_t)(146.0f + col * 50.0f);
*ptr = PackedCol_ARGB(r, g, 255, a);
ptr->R = (uint8_t)(32.0f + col * 32.0f);
ptr->G = (uint8_t)(50.0f + col * 64.0f);
ptr->A = (uint8_t)(146.0f + col * 50.0f);
ptr->B = 255;
ptr++; i++;
}
@ -230,9 +228,9 @@ static void Animations_Draw(struct AnimationData* data, TextureLoc texLoc, int s
if (!data) {
if (texLoc == 30) {
LavaAnimation_Tick((uint32_t*)frame.Scan0, size);
LavaAnimation_Tick((BitmapCol*)frame.Scan0, size);
} else if (texLoc == 14) {
WaterAnimation_Tick((uint32_t*)frame.Scan0, size);
WaterAnimation_Tick((BitmapCol*)frame.Scan0, size);
}
} else {
srcX = data->FrameX + data->State * size;

View File

@ -37,7 +37,11 @@ void AxisLinesRenderer_Render(double delta) {
1,2,2, 1,2,4, 3,2,4, 3,2,2, /* Z arrow */
1,2,3, 1,4,3, 3,4,1, 3,2,1, /* Y arrow */
};
static PackedCol cols[3] = { PACKEDCOL_RED, PACKEDCOL_BLUE, PACKEDCOL_GREEN };
static PackedCol cols[3] = {
PACKEDCOL_CONST(255, 0, 0, 255), /* Red */
PACKEDCOL_CONST( 0, 255, 0, 255), /* Green */
PACKEDCOL_CONST( 0, 0, 255, 255), /* Blue */
};
Vector3 coords[5], pos;
VertexP3fC4b vertices[AXISLINES_NUM_VERTICES];

View File

@ -7,6 +7,13 @@
#include "Stream.h"
#include "Errors.h"
BitmapCol BitmapCol_Scale(BitmapCol value, float t) {
value.R = (uint8_t)(value.R * t);
value.G = (uint8_t)(value.G * t);
value.B = (uint8_t)(value.B * t);
return value;
}
void Bitmap_Create(Bitmap* bmp, int width, int height, uint8_t* scan0) {
bmp->Width = width; bmp->Height = height; bmp->Scan0 = scan0;
}
@ -14,11 +21,9 @@ void Bitmap_Create(Bitmap* bmp, int width, int height, uint8_t* scan0) {
void Bitmap_CopyBlock(int srcX, int srcY, int dstX, int dstY, Bitmap* src, Bitmap* dst, int size) {
int x, y;
for (y = 0; y < size; y++) {
uint32_t* srcRow = Bitmap_GetRow(src, srcY + y);
uint32_t* dstRow = Bitmap_GetRow(dst, dstY + y);
for (x = 0; x < size; x++) {
dstRow[dstX + x] = srcRow[srcX + x];
}
BitmapCol* srcRow = Bitmap_GetRow(src, srcY + y) + srcX;
BitmapCol* dstRow = Bitmap_GetRow(dst, dstY + y) + dstX;
for (x = 0; x < size; x++) { dstRow[x] = srcRow[x]; }
}
}
@ -54,7 +59,7 @@ enum PngFilter {
PNG_FILTER_NONE, PNG_FILTER_SUB, PNG_FILTER_UP, PNG_FILTER_AVERAGE, PNG_FILTER_PAETH
};
typedef void (*Png_RowExpander)(int width, uint32_t* palette, uint8_t* src, uint32_t* dst);
typedef void (*Png_RowExpander)(int width, BitmapCol* palette, uint8_t* src, BitmapCol* dst);
static uint8_t png_sig[PNG_SIG_SIZE] = { 137, 80, 78, 71, 13, 10, 26, 10 };
bool Png_Detect(const uint8_t* data, uint32_t len) {
@ -118,58 +123,60 @@ static void Png_Reconstruct(uint8_t type, uint8_t bytesPerPixel, uint8_t* line,
}
}
static void Png_Expand_GRAYSCALE_1(int width, uint32_t* palette, uint8_t* src, uint32_t* dst) {
int i; /* NOTE: not optimised*/
#define PNG_Do_Grayscale(tmp, dstI, srcI, scale) tmp = src[srcI] * scale; dst[dstI] = PackedCol_ARGB(tmp, tmp, tmp, 255);
for (i = 0; i < width; i++) {
int mask = (7 - (i & 7)); uint8_t rgb;
PNG_Do_Grayscale(rgb, i, (src[i >> 3] >> mask) & 1, 255);
}
#define Bitmap_Set(dst, r,g,b,a) dst.B = b; dst.G = g; dst.R = r; dst.A = a;
#define PNG_Do_Grayscale(dstI, srcI, scale) rgb = src[srcI] * scale; Bitmap_Set(dst[dstI], rgb, rgb, rgb, 255);
#define PNG_Do_Grayscale_8(dstI, srcI) rgb = src[srcI]; Bitmap_Set(dst[dstI], rgb, rgb, rgb, 255);
#define PNG_Do_Grayscale_A__8(dstI, srcI) rgb = src[srcI]; Bitmap_Set(dst[dstI], rgb, rgb, rgb, src[srcI + 1]);
#define PNG_Do_RGB__8(dstI, srcI) Bitmap_Set(dst[dstI], src[srcI], src[srcI + 1], src[srcI + 2], 255);
#define PNG_Do_RGB_A__8(dstI, srcI) Bitmap_Set(dst[dstI], src[srcI], src[srcI + 1], src[srcI + 2], src[srcI + 3]);
#define PNG_Mask_1(i) (7 - (i & 7))
#define PNG_Mask_2(i) ((3 - (i & 3)) * 2)
#define PNG_Mask_4(i) ((1 - (i & 1)) * 4)
#define PNG_Get__1(i) ((src[i >> 3] >> PNG_Mask_1(i)) & 1)
#define PNG_Get__2(i) ((src[i >> 2] >> PNG_Mask_2(i)) & 3)
static void Png_Expand_GRAYSCALE_1(int width, BitmapCol* palette, uint8_t* src, BitmapCol* dst) {
int i; uint8_t rgb; /* NOTE: not optimised*/
for (i = 0; i < width; i++) { PNG_Do_Grayscale(i, PNG_Get__1(i), 255); }
}
static void Png_Expand_GRAYSCALE_2(int width, uint32_t* palette, uint8_t* src, uint32_t* dst) {
int i; /* NOTE: not optimised */
for (i = 0; i < width; i++) {
int mask = (3 - (i & 3)) * 2; uint8_t rgb;
PNG_Do_Grayscale(rgb, i, (src[i >> 3] >> mask) & 3, 85);
}
static void Png_Expand_GRAYSCALE_2(int width, BitmapCol* palette, uint8_t* src, BitmapCol* dst) {
int i; uint8_t rgb; /* NOTE: not optimised */
for (i = 0; i < width; i++) { PNG_Do_Grayscale(i, PNG_Get__2(i), 85); }
}
static void Png_Expand_GRAYSCALE_4(int width, uint32_t* palette, uint8_t* src, uint32_t* dst) {
int i, j, mask; uint8_t cur, rgb1, rgb2;
static void Png_Expand_GRAYSCALE_4(int width, BitmapCol* palette, uint8_t* src, BitmapCol* dst) {
int i, j; uint8_t rgb;
for (i = 0, j = 0; i < (width & ~0x1); i += 2, j++) {
cur = src[j];
PNG_Do_Grayscale(rgb1, i, cur >> 4, 17); PNG_Do_Grayscale(rgb2, i + 1, cur & 0x0F, 17);
PNG_Do_Grayscale(i, src[j] >> 4, 17); PNG_Do_Grayscale(i + 1, src[j] & 0x0F, 17);
}
for (; i < width; i++) {
mask = (1 - (i & 1)) * 4;
PNG_Do_Grayscale(rgb1, i, (src[j] >> mask) & 15, 17);
PNG_Do_Grayscale(i, (src[j] >> PNG_Mask_4(i)) & 15, 17);
}
}
static void Png_Expand_GRAYSCALE_8(int width, uint32_t* palette, uint8_t* src, uint32_t* dst) {
int i; uint8_t rgb1, rgb2, rgb3, rgb4;
#define PNG_Do_Grayscale_8(tmp, dstI, srcI) tmp = src[srcI]; dst[dstI] = PackedCol_ARGB(tmp, tmp, tmp, 255);
static void Png_Expand_GRAYSCALE_8(int width, BitmapCol* palette, uint8_t* src, BitmapCol* dst) {
int i; uint8_t rgb;
for (i = 0; i < (width & ~0x3); i += 4) {
PNG_Do_Grayscale_8(rgb1, i , i ); PNG_Do_Grayscale_8(rgb2, i + 1, i + 1);
PNG_Do_Grayscale_8(rgb3, i + 2, i + 2); PNG_Do_Grayscale_8(rgb4, i + 3, i + 3);
PNG_Do_Grayscale_8(i , i ); PNG_Do_Grayscale_8(i + 1, i + 1);
PNG_Do_Grayscale_8(i + 2, i + 2); PNG_Do_Grayscale_8(i + 3, i + 3);
}
for (; i < width; i++) { PNG_Do_Grayscale_8(rgb1, i, i); }
for (; i < width; i++) { PNG_Do_Grayscale_8(i, i); }
}
static void Png_Expand_GRAYSCALE_16(int width, uint32_t* palette, uint8_t* src, uint32_t* dst) {
int i;
static void Png_Expand_GRAYSCALE_16(int width, BitmapCol* palette, uint8_t* src, BitmapCol* dst) {
int i; uint8_t rgb; /* NOTE: not optimised */
for (i = 0; i < width; i++) {
uint8_t rgb = src[i * 2];
dst[i] = PackedCol_ARGB(rgb, rgb, rgb, 255);
rgb = src[i * 2]; Bitmap_Set(dst[i], rgb, rgb, rgb, 255);
}
}
static void Png_Expand_RGB_8(int width, uint32_t* palette, uint8_t* src, uint32_t* dst) {
static void Png_Expand_RGB_8(int width, BitmapCol* palette, uint8_t* src, BitmapCol* dst) {
int i, j;
#define PNG_Do_RGB__8(dstI, srcI) dst[dstI] = PackedCol_ARGB(src[srcI], src[srcI + 1], src[srcI + 2], 255);
for (i = 0, j = 0; i < (width & ~0x03); i += 4, j += 12) {
PNG_Do_RGB__8(i , j ); PNG_Do_RGB__8(i + 1, j + 3);
@ -178,75 +185,64 @@ static void Png_Expand_RGB_8(int width, uint32_t* palette, uint8_t* src, uint32_
for (; i < width; i++, j += 3) { PNG_Do_RGB__8(i, j); }
}
static void Png_Expand_RGB_16(int width, uint32_t* palette, uint8_t* src, uint32_t* dst) {
int i, j;
static void Png_Expand_RGB_16(int width, BitmapCol* palette, uint8_t* src, BitmapCol* dst) {
int i, j; /* NOTE: not optimised */
for (i = 0, j = 0; i < width; i++, j += 6) {
dst[i] = PackedCol_ARGB(src[j], src[j + 2], src[j + 4], 255);
Bitmap_Set(dst[i], src[j], src[j + 2], src[j + 4], 255);
}
}
static void Png_Expand_INDEXED_1(int width, uint32_t* palette, uint8_t* src, uint32_t* dst) {
int i; /* NOTE: not optimised*/
for (i = 0; i < width; i++) {
int mask = (7 - (i & 7));
dst[i] = palette[(src[i >> 3] >> mask) & 1];
}
static void Png_Expand_INDEXED_1(int width, BitmapCol* palette, uint8_t* src, BitmapCol* dst) {
int i; /* NOTE: not optimised */
for (i = 0; i < width; i++) { dst[i] = palette[PNG_Get__1(i)]; }
}
static void Png_Expand_INDEXED_2(int width, uint32_t* palette, uint8_t* src, uint32_t* dst) {
int i; /* NOTE: not optimised*/
for (i = 0; i < width; i++) {
int mask = (3 - (i & 3)) * 2;
dst[i] = palette[(src[i >> 3] >> mask) & 3];
}
static void Png_Expand_INDEXED_2(int width, BitmapCol* palette, uint8_t* src, BitmapCol* dst) {
int i; /* NOTE: not optimised */
for (i = 0; i < width; i++) { dst[i] = palette[PNG_Get__2(i)]; }
}
static void Png_Expand_INDEXED_4(int width, uint32_t* palette, uint8_t* src, uint32_t* dst) {
int i, j, mask; uint8_t cur;
#define PNG_Do_Indexed(dstI, srcI) dst[dstI] = palette[srcI];
static void Png_Expand_INDEXED_4(int width, BitmapCol* palette, uint8_t* src, BitmapCol* dst) {
int i, j; uint8_t cur;
for (i = 0, j = 0; i < (width & ~0x1); i += 2, j++) {
cur = src[j];
PNG_Do_Indexed(i, cur >> 4); PNG_Do_Indexed(i + 1, cur & 0x0F);
dst[i] = palette[cur >> 4]; dst[i + 1] = palette[cur & 0x0F];
}
for (; i < width; i++) {
mask = (1 - (i & 1)) * 4;
PNG_Do_Indexed(i, (src[j] >> mask) & 15);
dst[i] = palette[(src[j] >> PNG_Mask_4(i)) & 15];
}
}
static void Png_Expand_INDEXED_8(int width, uint32_t* palette, uint8_t* src, uint32_t* dst) {
static void Png_Expand_INDEXED_8(int width, BitmapCol* palette, uint8_t* src, BitmapCol* dst) {
int i;
for (i = 0; i < (width & ~0x3); i += 4) {
PNG_Do_Indexed(i , src[i] ); PNG_Do_Indexed(i + 1, src[i + 1]);
PNG_Do_Indexed(i + 2, src[i + 2]); PNG_Do_Indexed(i + 3, src[i + 3]);
dst[i] = palette[src[i]]; dst[i + 1] = palette[src[i + 1]];
dst[i + 2] = palette[src[i + 2]]; dst[i + 3] = palette[src[i + 3]];
}
for (; i < width; i++) { PNG_Do_Indexed(i, src[i]); }
for (; i < width; i++) { dst[i] = palette[src[i]]; }
}
static void Png_Expand_GRAYSCALE_A_8(int width, uint32_t* palette, uint8_t* src, uint32_t* dst) {
int i, j; uint8_t rgb1, rgb2, rgb3, rgb4;
#define PNG_Do_Grayscale_A__8(tmp, dstI, srcI) tmp = src[srcI]; dst[dstI] = PackedCol_ARGB(tmp, tmp, tmp, src[srcI + 1]);
static void Png_Expand_GRAYSCALE_A_8(int width, BitmapCol* palette, uint8_t* src, BitmapCol* dst) {
int i, j; uint8_t rgb;
for (i = 0, j = 0; i < (width & ~0x3); i += 4, j += 8) {
PNG_Do_Grayscale_A__8(rgb1, i , j ); PNG_Do_Grayscale_A__8(rgb2, i + 1, j + 2);
PNG_Do_Grayscale_A__8(rgb3, i + 2, j + 4); PNG_Do_Grayscale_A__8(rgb4, i + 3, j + 6);
PNG_Do_Grayscale_A__8(i , j ); PNG_Do_Grayscale_A__8(i + 1, j + 2);
PNG_Do_Grayscale_A__8(i + 2, j + 4); PNG_Do_Grayscale_A__8(i + 3, j + 6);
}
for (; i < width; i++, j += 2) { PNG_Do_Grayscale_A__8(rgb1, i, j); }
for (; i < width; i++, j += 2) { PNG_Do_Grayscale_A__8(i, j); }
}
static void Png_Expand_GRAYSCALE_A_16(int width, uint32_t* palette, uint8_t* src, uint32_t* dst) {
int i, j; /* NOTE: not optimised*/
for (i = 0, j = 0; i < width; i++, j += 4) {
uint8_t rgb = src[j];
dst[i] = PackedCol_ARGB(rgb, rgb, rgb, src[j + 2]);
static void Png_Expand_GRAYSCALE_A_16(int width, BitmapCol* palette, uint8_t* src, BitmapCol* dst) {
int i; uint8_t rgb; /* NOTE: not optimised*/
for (i = 0; i < width; i++) {
rgb = src[i * 4]; Bitmap_Set(dst[i], rgb, rgb, rgb, src[i * 4 + 2]);
}
}
static void Png_Expand_RGB_A_8(int width, uint32_t* palette, uint8_t* src, uint32_t* dst) {
static void Png_Expand_RGB_A_8(int width, BitmapCol* palette, uint8_t* src, BitmapCol* dst) {
int i, j;
#define PNG_Do_RGB_A__8(dstI, srcI) dst[dstI] = PackedCol_ARGB(src[srcI], src[srcI + 1], src[srcI + 2], src[srcI + 3]);
for (i = 0, j = 0; i < (width & ~0x3); i += 4, j += 16) {
PNG_Do_RGB_A__8(i , j ); PNG_Do_RGB_A__8(i + 1, j + 4 );
@ -255,10 +251,10 @@ static void Png_Expand_RGB_A_8(int width, uint32_t* palette, uint8_t* src, uint3
for (; i < width; i++, j += 4) { PNG_Do_RGB_A__8(i, j); }
}
static void Png_Expand_RGB_A_16(int width, uint32_t* palette, uint8_t* src, uint32_t* dst) {
static void Png_Expand_RGB_A_16(int width, BitmapCol* palette, uint8_t* src, BitmapCol* dst) {
int i, j; /* NOTE: not optimised*/
for (i = 0, j = 0; i < width; i++, j += 8) {
dst[i] = PackedCol_ARGB(src[j], src[j + 2], src[j + 4], src[j + 6]);
Bitmap_Set(dst[i], src[j], src[j + 2], src[j + 4], src[j + 6]);
}
}
@ -307,12 +303,12 @@ Png_RowExpander Png_GetExpander(uint8_t col, uint8_t bitsPerSample) {
return NULL;
}
static void Png_ComputeTransparency(Bitmap* bmp, uint32_t transparentCol) {
uint32_t trnsRGB = transparentCol & PNG_RGB_MASK;
static void Png_ComputeTransparency(Bitmap* bmp, BitmapCol col) {
uint32_t trnsRGB = col.B | (col.G << 8) | (col.R << 16); /* TODO: Remove this!! */
int x, y, width = bmp->Width, height = bmp->Height;
for (y = 0; y < height; y++) {
uint32_t* row = Bitmap_GetRow(bmp, y);
uint32_t* row = Bitmap_RawRow(bmp, y);
for (x = 0; x < width; x++) {
uint32_t rgb = row[x] & PNG_RGB_MASK;
row[x] = (rgb == trnsRGB) ? trnsRGB : row[x];
@ -335,8 +331,9 @@ ReturnCode Png_Decode(Bitmap* bmp, struct Stream* stream) {
uint32_t scanlineSize, scanlineBytes;
/* palette data */
uint32_t transparentCol = PackedCol_ARGB(0, 0, 0, 255);
uint32_t palette[PNG_PALETTE];
BitmapCol black = BITMAPCOL_CONST(0, 0, 0, 255);
BitmapCol transparentCol;
BitmapCol palette[PNG_PALETTE];
uint32_t i;
/* idat state */
@ -355,15 +352,13 @@ ReturnCode Png_Decode(Bitmap* bmp, struct Stream* stream) {
if (res) return res;
if (!Png_Detect(tmp, PNG_SIG_SIZE)) return PNG_ERR_INVALID_SIG;
for (i = 0; i < PNG_PALETTE; i++) {
palette[i] = PackedCol_ARGB(0, 0, 0, 255);
}
bool readingChunks = true;
transparentCol = black;
for (i = 0; i < PNG_PALETTE; i++) { palette[i] = black; }
Inflate_MakeStream(&compStream, &inflate, stream);
ZLibHeader_Init(&zlibHeader);
while (readingChunks) {
for (;;) {
res = Stream_Read(stream, tmp, 8);
if (res) return res;
dataSize = Stream_GetU32_BE(&tmp[0]);
@ -407,7 +402,9 @@ ReturnCode Png_Decode(Bitmap* bmp, struct Stream* stream) {
if (res) return res;
for (i = 0; i < dataSize; i += 3) {
palette[i / 3] = PackedCol_ARGB(tmp[i], tmp[i + 1], tmp[i + 2], 255);
palette[i / 3].R = tmp[i];
palette[i / 3].G = tmp[i + 1];
palette[i / 3].B = tmp[i + 2];
}
} break;
@ -418,8 +415,8 @@ ReturnCode Png_Decode(Bitmap* bmp, struct Stream* stream) {
if (res) return res;
/* RGB is 16 bits big endian, ignore least significant 8 bits */
uint8_t palRGB = tmp[0];
transparentCol = PackedCol_ARGB(palRGB, palRGB, palRGB, 0);
transparentCol.B = tmp[0]; transparentCol.G = tmp[0];
transparentCol.R = tmp[0]; transparentCol.A = 0;
} else if (col == PNG_COL_INDEXED) {
if (dataSize > PNG_PALETTE) return PNG_ERR_TRANS_COUNT;
res = Stream_Read(stream, tmp, dataSize);
@ -427,8 +424,7 @@ ReturnCode Png_Decode(Bitmap* bmp, struct Stream* stream) {
/* set alpha component of palette*/
for (i = 0; i < dataSize; i++) {
palette[i] &= PNG_RGB_MASK;
palette[i] |= (uint32_t)tmp[i] << 24;
palette[i].A = tmp[i];
}
} else if (col == PNG_COL_RGB) {
if (dataSize != 6) return PNG_ERR_TRANS_COUNT;
@ -436,8 +432,8 @@ ReturnCode Png_Decode(Bitmap* bmp, struct Stream* stream) {
if (res) return res;
/* R,G,B is 16 bits big endian, ignore least significant 8 bits */
uint8_t palR = tmp[0], palG = tmp[2], palB = tmp[4];
transparentCol = PackedCol_ARGB(palR, palG, palB, 0);
transparentCol.B = tmp[4]; transparentCol.G = tmp[2];
transparentCol.R = tmp[0]; transparentCol.A = 0;
} else {
return PNG_ERR_TRANS_INVALID;
}
@ -491,8 +487,9 @@ ReturnCode Png_Decode(Bitmap* bmp, struct Stream* stream) {
} break;
case PNG_FourCC('I','E','N','D'): {
readingChunks = false;
if (dataSize) return PNG_ERR_INVALID_END_SIZE;
if (!transparentCol.A) Png_ComputeTransparency(bmp, transparentCol);
return bmp->Scan0 ? 0 : PNG_ERR_NO_DATA;
} break;
default:
@ -502,11 +499,6 @@ ReturnCode Png_Decode(Bitmap* bmp, struct Stream* stream) {
if ((res = stream->Skip(stream, 4))) return res; /* Skip CRC32 */
}
if (transparentCol <= PNG_RGB_MASK) {
Png_ComputeTransparency(bmp, transparentCol);
}
return bmp->Scan0 ? 0 : PNG_ERR_NO_DATA;
}
@ -589,14 +581,14 @@ static void Png_Filter(uint8_t filter, uint8_t* cur, uint8_t* prior, uint8_t* be
}
}
static void Png_EncodeRow(const uint8_t* src, uint8_t* cur, uint8_t* prior, uint8_t* best, int lineLen) {
static void Png_EncodeRow(const BitmapCol* src, uint8_t* cur, uint8_t* prior, uint8_t* best, int lineLen) {
uint8_t* dst = cur;
int bestFilter, bestEstimate = Int32_MaxValue;
int x, filter, estimate;
for (x = 0; x < lineLen; x += 3) {
dst[0] = src[2]; dst[1] = src[1]; dst[2] = src[0];
src += 4; dst += 3;
dst[0] = src->R; dst[1] = src->G; dst[2] = src->B;
src++; dst += 3;
}
dst = best + 1;
@ -665,7 +657,7 @@ ReturnCode Png_Encode(Bitmap* bmp, struct Stream* stream, Png_RowSelector select
for (y = 0; y < bmp->Height; y++) {
int row = selectRow(bmp, y);
uint8_t* src = (uint8_t*)Bitmap_GetRow(bmp, row);
BitmapCol* src = Bitmap_GetRow(bmp, row);
uint8_t* prev = (y & 1) == 0 ? prevLine : curLine;
uint8_t* cur = (y & 1) == 0 ? curLine : prevLine;

View File

@ -6,12 +6,26 @@
*/
struct Stream;
/* Represents an ARGB colour, suitable for native graphics API texture pixels. */
typedef CC_ALIGN_HINT(4) struct BitmapCol_ {
uint8_t B, G, R, A;
} BitmapCol;
/* Represents an ARGB colour, suitable for native graphics API texture pixels. */
/* Unioned with Packed member for efficient equality comparison */
typedef union BitmapColUnion_ { BitmapCol C; uint32_t Raw; } BitmapColUnion;
typedef struct Bitmap_ { uint8_t* Scan0; int Width, Height; } Bitmap;
#define PNG_MAX_DIMS 0x8000
#define BITMAPCOL_CONST(r, g, b, a) { b, g, r, a }
#define BITMAP_SIZEOF_PIXEL 4 /* 32 bit ARGB */
#define Bitmap_DataSize(width, height) ((uint32_t)(width) * (uint32_t)(height) * (uint32_t)BITMAP_SIZEOF_PIXEL)
#define Bitmap_GetRow(bmp, y) ((uint32_t*)((bmp)->Scan0 + ((y) * ((bmp)->Width << 2))))
#define Bitmap_RawRow(bmp, y) ((uint32_t*)((bmp)->Scan0 + ((y) * ((bmp)->Width << 2))))
#define Bitmap_GetRow(bmp, y) ((BitmapCol*)((bmp)->Scan0 + ((y) * ((bmp)->Width << 2))))
#define Bitmap_GetPixel(bmp, x, y) (Bitmap_GetRow(bmp, y)[x])
BitmapCol BitmapCol_Scale(BitmapCol value, float t);
void Bitmap_Create(Bitmap* bmp, int width, int height, uint8_t* scan0);
void Bitmap_CopyBlock(int srcX, int srcY, int dstX, int dstY, Bitmap* src, Bitmap* dst, int size);
/* Allocates a new bitmap of the given dimensions. You are responsible for freeing its memory! */

View File

@ -89,7 +89,7 @@ void Block_SetCustomDefined(BlockID block, bool defined) {
}
void Block_DefineCustom(BlockID block) {
PackedCol black = PACKEDCOL_BLACK;
PackedCol black = PACKEDCOL_CONST(0, 0, 0, 255);
String name = Block_UNSAFE_GetName(block);
Block_Tinted[block] = !PackedCol_Equals(Block_FogCol[block], black) && String_IndexOf(&name, '#', 0) >= 0;
@ -283,60 +283,52 @@ void Block_RecalculateSpriteBB(void) {
}
static float Block_GetSpriteBB_MinX(int size, int tileX, int tileY, Bitmap* bmp) {
uint32_t* row;
BitmapCol* row;
int x, y;
for (x = 0; x < size; x++) {
for (y = 0; y < size; y++) {
row = Bitmap_GetRow(bmp, tileY * size + y) + (tileX * size);
if (PackedCol_ARGB_A(row[x]) != 0) {
return (float)x / size;
}
if (row[x].A) { return (float)x / size; }
}
}
return 1.0f;
}
static float Block_GetSpriteBB_MinY(int size, int tileX, int tileY, Bitmap* bmp) {
uint32_t* row;
BitmapCol* row;
int x, y;
for (y = size - 1; y >= 0; y--) {
row = Bitmap_GetRow(bmp, tileY * size + y) + (tileX * size);
for (x = 0; x < size; x++) {
if (PackedCol_ARGB_A(row[x]) != 0) {
return 1.0f - (float)(y + 1) / size;
}
if (row[x].A) { return 1.0f - (float)(y + 1) / size; }
}
}
return 1.0f;
}
static float Block_GetSpriteBB_MaxX(int size, int tileX, int tileY, Bitmap* bmp) {
uint32_t* row;
BitmapCol* row;
int x, y;
for (x = size - 1; x >= 0; x--) {
for (y = 0; y < size; y++) {
row = Bitmap_GetRow(bmp, tileY * size + y) + (tileX * size);
if (PackedCol_ARGB_A(row[x]) != 0) {
return (float)(x + 1) / size;
}
if (row[x].A) { return (float)(x + 1) / size; }
}
}
return 0.0f;
}
static float Block_GetSpriteBB_MaxY(int size, int tileX, int tileY, Bitmap* bmp) {
uint32_t* row;
BitmapCol* row;
int x, y;
for (y = 0; y < size; y++) {
row = Bitmap_GetRow(bmp, tileY * size + y) + (tileX * size);
for (x = 0; x < size; x++) {
if (PackedCol_ARGB_A(row[x]) != 0) {
return 1.0f - (float)y / size;
}
if (row[x].A) { return 1.0f - (float)y / size; }
}
}
return 0.0f;

View File

@ -508,7 +508,7 @@ static PackedCol Normal_LightCol(int x, int y, int z, Face face, BlockID block)
return y >= World_MaxY ? Env_SunCol : Lighting_Col_YMax_Fast(x, (y + 1) - offset, z);
}
PackedCol black = PACKEDCOL_BLACK; return black;
PackedCol invalid = PACKEDCOL_CONST(0, 0, 0, 0); return invalid;
}
static bool Normal_CanStretch(BlockID initial, int chunkIndex, int x, int y, int z, Face face) {

View File

@ -270,25 +270,28 @@ static int ChunkUpdater_UpdateChunksStill(int* chunkUpdates) {
return j;
}
void ChunkUpdater_UpdateChunks(double delta) {
static void ChunkUpdater_UpdateChunks(double delta) {
struct LocalPlayer* p;
bool samePos;
int chunkUpdates = 0;
cu_chunksTarget += delta < cu_targetTime ? 1 : -1; /* build more chunks if 30 FPS or over, otherwise slowdown. */
/* Build more chunks if 30 FPS or over, otherwise slowdown */
cu_chunksTarget += delta < cu_targetTime ? 1 : -1;
Math_Clamp(cu_chunksTarget, 4, Game_MaxChunkUpdates);
struct LocalPlayer* p = &LocalPlayer_Instance;
Vector3 pos = Camera_CurrentPos;
float headX = p->Base.HeadX;
float headY = p->Base.HeadY;
p = &LocalPlayer_Instance;
samePos = Vector3_Equals(&Camera_CurrentPos, &cu_lastCamPos)
&& p->Base.HeadX == cu_lastHeadX && p->Base.HeadY == cu_lastHeadY;
bool samePos = Vector3_Equals(&pos, &cu_lastCamPos) && headX == cu_lastHeadX && headY == cu_lastHeadY;
MapRenderer_RenderChunksCount = samePos ?
ChunkUpdater_UpdateChunksStill(&chunkUpdates) :
ChunkUpdater_UpdateChunksAndVisibility(&chunkUpdates);
cu_lastCamPos = pos;
cu_lastHeadX = headX; cu_lastHeadY = headY;
cu_lastCamPos = Camera_CurrentPos;
cu_lastHeadX = p->Base.HeadX;
cu_lastHeadY = p->Base.HeadY;
if (!samePos || chunkUpdates != 0) {
if (!samePos || chunkUpdates) {
ChunkUpdater_ResetPartFlags();
}
}

View File

@ -72,7 +72,6 @@ typedef struct Point2D_ { int X, Y; } Point2D;
typedef struct Size2D_ { int Width, Height; } Size2D;
typedef struct FontDesc_ { void* Handle; uint16_t Size, Style; } FontDesc;
typedef struct TextureRec_ { float U1, V1, U2, V2; } TextureRec;
typedef struct Bitmap_ { uint8_t* Scan0; int Width, Height; } Bitmap;
/*#define CC_BUILD_GL11*/
/*#define CC_BUILD_SOLARIS*/

View File

@ -38,7 +38,7 @@ static int Drawer2D_Widths[256];
static void Drawer2D_CalculateTextWidths(void) {
int width = Drawer2D_FontBitmap.Width, height = Drawer2D_FontBitmap.Height;
uint32_t* row;
BitmapCol* row;
int i, x, y, xx, tileX, tileY;
for (i = 0; i < Array_Elems(Drawer2D_Widths); i++) {
@ -55,9 +55,7 @@ static void Drawer2D_CalculateTextWidths(void) {
/* Iterate through each pixel of the given character, on the current scanline */
for (xx = Drawer2D_TileSize - 1; xx >= 0; xx--) {
uint32_t pixel = row[x + xx];
uint8_t a = PackedCol_ARGB_A(pixel);
if (a < 127) continue;
if (row[x + xx].A < 127) continue;
/* Check if this is the pixel furthest to the right, for the current character */
Drawer2D_Widths[i] = max(Drawer2D_Widths[i], xx + 1);
@ -82,15 +80,14 @@ void Drawer2D_SetFontBitmap(Bitmap* bmp) {
void Drawer2D_HexEncodedCol(int i, int hex, uint8_t lo, uint8_t hi) {
PackedCol* col = &Drawer2D_Cols[i];
col->R = (uint8_t)(lo * ((hex >> 2) & 1) + hi * (hex >> 3));
col->G = (uint8_t)(lo * ((hex >> 1) & 1) + hi * (hex >> 3));
col->B = (uint8_t)(lo * ((hex >> 0) & 1) + hi * (hex >> 3));
col->A = UInt8_MaxValue;
Drawer2D_Cols[i].R = (uint8_t)(lo * ((hex >> 2) & 1) + hi * (hex >> 3));
Drawer2D_Cols[i].G = (uint8_t)(lo * ((hex >> 1) & 1) + hi * (hex >> 3));
Drawer2D_Cols[i].B = (uint8_t)(lo * ((hex >> 0) & 1) + hi * (hex >> 3));
Drawer2D_Cols[i].A = 255;
}
void Drawer2D_Init(void) {
PackedCol col = PACKEDCOL_CONST(0, 0, 0, 0);
BitmapCol col = BITMAPCOL_CONST(0, 0, 0, 0);
int i;
for (i = 0; i < DRAWER2D_MAX_COLS; i++) {
@ -109,11 +106,10 @@ void Drawer2D_Init(void) {
void Drawer2D_Free(void) { Drawer2D_FreeFontBitmap(); }
/* Draws a 2D flat rectangle. */
void Drawer2D_Rect(Bitmap* bmp, PackedCol col, int x, int y, int width, int height);
void Drawer2D_Rect(Bitmap* bmp, BitmapCol col, int x, int y, int width, int height);
void Drawer2D_Clear(Bitmap* bmp, PackedCol col, int x, int y, int width, int height) {
uint32_t argb = PackedCol_ToARGB(col);
uint32_t* row;
void Drawer2D_Clear(Bitmap* bmp, BitmapCol col, int x, int y, int width, int height) {
BitmapCol* row;
int xx, yy;
if (x < 0 || y < 0 || (x + width) > bmp->Width || (y + height) > bmp->Height) {
@ -122,7 +118,7 @@ void Drawer2D_Clear(Bitmap* bmp, PackedCol col, int x, int y, int width, int hei
for (yy = 0; yy < height; yy++) {
row = Bitmap_GetRow(bmp, y + yy) + x;
for (xx = 0; xx < width; xx++) { row[xx] = argb; }
for (xx = 0; xx < width; xx++) { row[xx] = col; }
}
}
@ -233,9 +229,8 @@ static int Drawer2D_NextPart(int i, STRING_REF String* value, String* part, char
return i;
}
void Drawer2D_Underline(Bitmap* bmp, int x, int y, int width, int height, PackedCol col) {
uint32_t argb = PackedCol_ToARGB(col);
uint32_t* row;
void Drawer2D_Underline(Bitmap* bmp, int x, int y, int width, int height, BitmapCol col) {
BitmapCol* row;
int xx, yy;
for (yy = y; yy < y + height; yy++) {
@ -244,14 +239,14 @@ void Drawer2D_Underline(Bitmap* bmp, int x, int y, int width, int height, Packed
for (xx = x; xx < x + width; xx++) {
if (xx >= bmp->Width) break;
row[xx] = argb;
row[xx] = col;
}
}
}
static void Drawer2D_DrawCore(Bitmap* bmp, struct DrawTextArgs* args, int x, int y, bool shadow) {
PackedCol black = PACKEDCOL_BLACK;
PackedColUnion col;
BitmapCol black = BITMAPCOL_CONST(0, 0, 0, 255);
BitmapColUnion col;
String text = args->Text;
int i, point = args->Font.Size, count = 0;
@ -262,13 +257,16 @@ static void Drawer2D_DrawCore(Bitmap* bmp, struct DrawTextArgs* args, int x, int
int dstHeight, begX, xx, yy;
int cellY, underlineY, underlineHeight;
BitmapCol* srcRow, src;
BitmapCol* dstRow, dst;
uint8_t coords[256];
PackedColUnion cols[256];
BitmapColUnion cols[256];
uint16_t dstWidths[256];
col.C = Drawer2D_Cols['f'];
if (shadow) {
col.C = Drawer2D_BlackTextShadows ? black : PackedCol_Scale(col.C, 0.25f);
col.C = Drawer2D_BlackTextShadows ? black : BitmapCol_Scale(col.C, 0.25f);
}
for (i = 0; i < text.length; i++) {
@ -276,7 +274,7 @@ static void Drawer2D_DrawCore(Bitmap* bmp, struct DrawTextArgs* args, int x, int
if (c == '&' && Drawer2D_ValidColCodeAt(&text, i + 1)) {
col.C = Drawer2D_GetCol(text.buffer[i + 1]);
if (shadow) {
col.C = Drawer2D_BlackTextShadows ? black : PackedCol_Scale(col.C, 0.25f);
col.C = Drawer2D_BlackTextShadows ? black : BitmapCol_Scale(col.C, 0.25f);
}
i++; continue; /* skip over the colour code */
}
@ -297,12 +295,12 @@ static void Drawer2D_DrawCore(Bitmap* bmp, struct DrawTextArgs* args, int x, int
if (dstY >= bmp->Height) break;
fontY = 0 + yy * Drawer2D_TileSize / dstHeight;
uint32_t* dstRow = Bitmap_GetRow(bmp, dstY);
dstRow = Bitmap_GetRow(bmp, dstY);
for (i = 0; i < count; i++) {
srcX = (coords[i] & 0x0F) * Drawer2D_TileSize;
srcY = (coords[i] >> 4) * Drawer2D_TileSize;
uint32_t* fontRow = Bitmap_GetRow(&Drawer2D_FontBitmap, fontY + srcY);
srcRow = Bitmap_GetRow(&Drawer2D_FontBitmap, fontY + srcY);
srcWidth = Drawer2D_Widths[coords[i]];
dstWidth = dstWidths[i];
@ -310,17 +308,17 @@ static void Drawer2D_DrawCore(Bitmap* bmp, struct DrawTextArgs* args, int x, int
for (xx = 0; xx < dstWidth; xx++) {
fontX = srcX + xx * srcWidth / dstWidth;
uint32_t src = fontRow[fontX];
if (PackedCol_ARGB_A(src) == 0) continue;
src = srcRow[fontX];
if (!src.A) continue;
dstX = x + xx;
if (dstX >= bmp->Width) break;
uint32_t pixel = src & ~0xFFFFFF;
pixel |= ((src & 0xFF) * col.C.B / 255);
pixel |= (((src >> 8) & 0xFF) * col.C.G / 255) << 8;
pixel |= (((src >> 16) & 0xFF) * col.C.R / 255) << 16;
dstRow[dstX] = pixel;
dst.B = src.B * col.C.B / 255;
dst.G = src.G * col.C.G / 255;
dst.R = src.R * col.C.R / 255;
dst.A = src.A;
dstRow[dstX] = dst;
}
x += dstWidth + xPadding;
}
@ -382,7 +380,7 @@ static Size2D Drawer2D_MeasureBitmapText(struct DrawTextArgs* args) {
}
void Drawer2D_DrawText(Bitmap* bmp, struct DrawTextArgs* args, int x, int y) {
PackedCol col, backCol, black = PACKEDCOL_BLACK;
BitmapCol col, backCol, black = BITMAPCOL_CONST(0, 0, 0, 255);
Size2D partSize;
String value = args->Text;
char colCode, nextCol = 'f';
@ -398,7 +396,7 @@ void Drawer2D_DrawText(Bitmap* bmp, struct DrawTextArgs* args, int x, int y) {
col = Drawer2D_GetCol(colCode);
if (args->UseShadow) {
backCol = Drawer2D_BlackTextShadows ? black : PackedCol_Scale(col, 0.25f);
backCol = Drawer2D_BlackTextShadows ? black : BitmapCol_Scale(col, 0.25f);
Platform_TextDraw(args, bmp, x + DRAWER2D_OFFSET, y + DRAWER2D_OFFSET, backCol);
}

View File

@ -2,6 +2,7 @@
#define CC_DRAWER2D_H
#include "PackedCol.h"
#include "Constants.h"
#include "Bitmap.h"
/* Responsible for performing drawing operations on bitmaps, and for converting bitmaps into textures.
Copyright 2017 ClassicalSharp | Licensed under BSD-3
*/
@ -18,7 +19,7 @@ CC_NOINLINE void Drawer2D_MakeFont(FontDesc* desc, int size, int style);
bool Drawer2D_BitmappedText;
/* Whether the shadows behind text (that uses shadows) is fully black. */
bool Drawer2D_BlackTextShadows;
PackedCol Drawer2D_Cols[DRAWER2D_MAX_COLS];
BitmapCol Drawer2D_Cols[DRAWER2D_MAX_COLS];
#define DRAWER2D_OFFSET 1
#define Drawer2D_GetCol(c) Drawer2D_Cols[(uint8_t)c]
@ -26,11 +27,11 @@ void Drawer2D_Init(void);
void Drawer2D_Free(void);
/* Draws a 2D flat rectangle. */
void Drawer2D_Rect(Bitmap* bmp, PackedCol col, int x, int y, int width, int height);
void Drawer2D_Rect(Bitmap* bmp, BitmapCol col, int x, int y, int width, int height);
/* Clears the entire given area to the specified colour. */
void Drawer2D_Clear(Bitmap* bmp, PackedCol col, int x, int y, int width, int height);
void Drawer2D_Clear(Bitmap* bmp, BitmapCol col, int x, int y, int width, int height);
void Drawer2D_Underline(Bitmap* bmp, int x, int y, int width, int height, PackedCol col);
void Drawer2D_Underline(Bitmap* bmp, int x, int y, int width, int height, BitmapCol col);
void Drawer2D_DrawText(Bitmap* bmp, struct DrawTextArgs* args, int x, int y);
Size2D Drawer2D_MeasureText(struct DrawTextArgs* args);
int Drawer2D_FontHeight(const FontDesc* font, bool useShadow);

View File

@ -477,6 +477,9 @@ void TabList_MakeComponent(struct IGameComponent* comp) {
static void Player_MakeNameTexture(struct Player* player) {
String colorlessName; char colorlessBuffer[STRING_SIZE];
BitmapCol shadowCol = BITMAPCOL_CONST(80, 80, 80, 255);
BitmapCol origWhiteCol;
struct DrawTextArgs args;
bool bitmapped;
String name;
@ -501,9 +504,9 @@ static void Player_MakeNameTexture(struct Player* player) {
Bitmap_AllocateClearedPow2(&bmp, size.Width, size.Height);
{
PackedCol origWhiteCol = Drawer2D_Cols['f'];
origWhiteCol = Drawer2D_Cols['f'];
Drawer2D_Cols['f'] = PackedCol_Create3(80, 80, 80);
Drawer2D_Cols['f'] = shadowCol;
String_AppendColorless(&colorlessName, &name);
args.Text = colorlessName;
Drawer2D_DrawText(&bmp, &args, NAME_OFFSET, NAME_OFFSET);
@ -653,11 +656,9 @@ static void Player_ClearHat(Bitmap* bmp, uint8_t skinType) {
/* determine if we actually need filtering */
for (y = 0; y < sizeY; y++) {
uint32_t* row = Bitmap_GetRow(bmp, y);
row += sizeX;
BitmapCol* row = Bitmap_GetRow(bmp, y) + sizeX;
for (x = 0; x < sizeX; x++) {
uint8_t alpha = PackedCol_ARGB_A(row[x]);
if (alpha != 255) return;
if (row[x].A != 255) return;
}
}
@ -665,8 +666,7 @@ static void Player_ClearHat(Bitmap* bmp, uint8_t skinType) {
uint32_t fullWhite = PackedCol_ARGB(255, 255, 255, 255);
uint32_t fullBlack = PackedCol_ARGB(0, 0, 0, 255);
for (y = 0; y < sizeY; y++) {
uint32_t* row = Bitmap_GetRow(bmp, y);
row += sizeX;
uint32_t* row = Bitmap_RawRow(bmp, y) + sizeX;
for (x = 0; x < sizeX; x++) {
uint32_t pixel = row[x];
if (pixel == fullWhite || pixel == fullBlack) row[x] = 0;
@ -690,8 +690,8 @@ static void Player_EnsurePow2(struct Player* p, Bitmap* bmp) {
stride = bmp->Width * BITMAP_SIZEOF_PIXEL;
for (y = 0; y < bmp->Height; y++) {
uint32_t* src = Bitmap_GetRow(bmp, y);
uint32_t* dst = Bitmap_GetRow(&scaled, y);
BitmapCol* src = Bitmap_GetRow(bmp, y);
BitmapCol* dst = Bitmap_GetRow(&scaled, y);
Mem_Copy(dst, src, stride);
}

View File

@ -602,14 +602,14 @@ static bool ShadowComponent_GetBlocks(struct Entity* e, int x, int y, int z, str
#define sh_half (sh_size / 2)
static void ShadowComponent_MakeTex(void) {
uint8_t pixels[Bitmap_DataSize(sh_size, sh_size)];
Bitmap bmp; Bitmap_Create(&bmp, sh_size, sh_size, pixels);
uint32_t inPix = PackedCol_ARGB(0, 0, 0, 200);
uint32_t outPix = PackedCol_ARGB(0, 0, 0, 0);
BitmapCol inPix = BITMAPCOL_CONST(0, 0, 0, 200);
BitmapCol outPix = BITMAPCOL_CONST(0, 0, 0, 0);
Bitmap bmp;
uint32_t x, y;
Bitmap_Create(&bmp, sh_size, sh_size, pixels);
for (y = 0; y < sh_size; y++) {
uint32_t* row = Bitmap_GetRow(&bmp, y);
BitmapCol* row = Bitmap_GetRow(&bmp, y);
for (x = 0; x < sh_size; x++) {
double dist =
(sh_half - (x + 0.5)) * (sh_half - (x + 0.5)) +

View File

@ -215,18 +215,21 @@ static GfxResourceID sky_vb;
static int sky_vertices;
void EnvRenderer_RenderSky(double deltaTime) {
struct Matrix m;
float skyY, normY, dy;
if (!sky_vb || EnvRenderer_ShouldRenderSkybox()) return;
Vector3 pos = Camera_CurrentPos;
float normalY = (float)World_Height + 8.0f;
float skyY = max(pos.Y + 8.0f, normalY);
normY = (float)World_Height + 8.0f;
skyY = max(Camera_CurrentPos.Y + 8.0f, normY);
Gfx_SetBatchFormat(VERTEX_FORMAT_P3FC4B);
Gfx_BindVb(sky_vb);
if (skyY == normalY) {
if (skyY == normY) {
Gfx_DrawVb_IndexedTris(sky_vertices);
} else {
struct Matrix m = Gfx_View;
float dy = skyY - normalY; /* inlined Y translation matrix multiply */
m = Gfx_View;
dy = skyY - normY;
/* inlined Y translation matrix multiply */
m.Row3.X += dy * m.Row1.X; m.Row3.Y += dy * m.Row1.Y;
m.Row3.Z += dy * m.Row1.Z; m.Row3.W += dy * m.Row1.W;
@ -445,12 +448,19 @@ static float EnvRenderer_RainAlphaAt(float x) {
}
void EnvRenderer_RenderWeather(double deltaTime) {
int weather = Env_Weather;
VertexP3fT2fC4b vertices[WEATHER_VERTS_COUNT];
VertexP3fT2fC4b* ptr, v;
int weather, vCount;
Vector3I pos;
bool moved, particles;
float speed, vOffset;
float dist, alpha;
int dist, dx, dz, x, z;
float alpha, y, height;
float worldV, v1, v2;
float x1,y1,z1, x2,y2,z2;
weather = Env_Weather;
if (weather == WEATHER_SUNNY) return;
if (!Weather_Heightmap) EnvRenderer_InitWeatherHeightmap();
Gfx_BindTexture(weather == WEATHER_RAINY ? rain_tex : snow_tex);
@ -468,16 +478,15 @@ void EnvRenderer_RenderWeather(double deltaTime) {
particles = weather == WEATHER_RAINY;
weather_accumulator += deltaTime;
VertexP3fT2fC4b v; v.Col = Env_SunCol;
VertexP3fT2fC4b vertices[WEATHER_VERTS_COUNT];
VertexP3fT2fC4b* ptr = vertices;
ptr = vertices;
v.Col = Env_SunCol;
int dx, dz;
for (dx = -WEATHER_EXTENT; dx <= WEATHER_EXTENT; dx++) {
for (dz = -WEATHER_EXTENT; dz <= WEATHER_EXTENT; dz++) {
int x = pos.X + dx, z = pos.Z + dz;
float y = EnvRenderer_RainHeight(x, z);
float height = pos.Y - y;
x = pos.X + dx; z = pos.Z + dz;
y = EnvRenderer_RainHeight(x, z);
height = pos.Y - y;
if (height <= 0) continue;
if (particles && (weather_accumulator >= 0.25 || moved)) {
@ -485,16 +494,17 @@ void EnvRenderer_RenderWeather(double deltaTime) {
Particles_RainSnowEffect(particlePos);
}
dist = (float)dx * (float)dx + (float)dz * (float)dz;
alpha = EnvRenderer_RainAlphaAt(dist);
dist = dx * dx + dz * dz;
alpha = EnvRenderer_RainAlphaAt((float)dist);
Math_Clamp(alpha, 0.0f, 255.0f);
v.Col.A = (uint8_t)alpha;
/* NOTE: Making vertex is inlined since this is called millions of times. */
float worldV = vOffset + (z & 1) / 2.0f - (x & 0x0F) / 16.0f;
float v1 = y / 6.0f + worldV, v2 = (y + height) / 6.0f + worldV;
float x1 = (float)x, y1 = (float)y, z1 = (float)z;
float x2 = (float)(x + 1), y2 = (float)(y + height), z2 = (float)(z + 1);
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.U = 0.0f; v.V = v1; *ptr++ = v;
v.Y = y2; v.V = v2; *ptr++ = v;
@ -518,7 +528,7 @@ void EnvRenderer_RenderWeather(double deltaTime) {
Gfx_SetAlphaArgBlend(true);
Gfx_SetBatchFormat(VERTEX_FORMAT_P3FT2FC4B);
int vCount = (int)(ptr - vertices);
vCount = (int)(ptr - vertices);
GfxCommon_UpdateDynamicVb_IndexedTris(weather_vb, vertices, vCount);
Gfx_SetAlphaArgBlend(false);

View File

@ -445,13 +445,16 @@ typedef struct {
} X11Button;
static void X11Button_Draw(X11Button* b, X11Window* w) {
X11Textbox* t;
int begX, endX, begY, endY;
XSetForeground(dpy, w->gc, w->btnBorder);
XDrawRectangle(dpy, w->win, w->gc, b->X, b->Y,
b->Width, b->Height);
X11Textbox* t = &b->Text;
int begX = b->X + 1, endX = b->X + b->Width - 1;
int begY = b->Y + 1, endY = b->Y + b->Height - 1;
t = &b->Text;
begX = b->X + 1; endX = b->X + b->Width - 1;
begY = b->Y + 1; endY = b->Y + b->Height - 1;
if (b->Clicked) {
XSetForeground(dpy, w->gc, w->highlight);

View File

@ -2,6 +2,7 @@
#define CC_GAME_H
#include "Picking.h"
#include "Options.h"
#include "Bitmap.h"
/* Represents the game.
Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
*/

View File

@ -3,6 +3,7 @@
#include "PackedCol.h"
#include "Vectors.h"
#include "GameStructs.h"
#include "Bitmap.h"
/* Abstracts a 3D graphics rendering API.
Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3

View File

@ -167,52 +167,54 @@ void GfxCommon_RestoreAlphaState(uint8_t draw) {
}
#define alphaMask ((uint32_t)0xFF000000UL)
/* Quoted from http://www.realtimerendering.com/blog/gpus-prefer-premultiplication/
The short version: if you want your renderer to properly handle textures with alphas when using
bilinear interpolation or mipmapping, you need to premultiply your PNG color data by their (unassociated) alphas. */
static uint32_t GfxCommon_Average(uint32_t p1, uint32_t p2) {
uint32_t a1 = ((p1 & alphaMask) >> 24) & 0xFF;
uint32_t a2 = ((p2 & alphaMask) >> 24) & 0xFF;
uint32_t aSum = (a1 + a2);
static BitmapCol GfxCommon_Average(BitmapCol p1, BitmapCol p2) {
uint32_t a1, a2, aSum;
uint32_t b1, g1, r1;
uint32_t b2, g2, r2;
BitmapCol ave;
a1 = p1.A; a2 = p2.A;
aSum = (a1 + a2);
aSum = aSum > 0 ? aSum : 1; /* avoid divide by 0 below */
/* Convert RGB to pre-multiplied form */
uint32_t r1 = ((p1 >> 16) & 0xFF) * a1, g1 = ((p1 >> 8) & 0xFF) * a1, b1 = (p1 & 0xFF) * a1;
uint32_t r2 = ((p2 >> 16) & 0xFF) * a2, g2 = ((p2 >> 8) & 0xFF) * a2, b2 = (p2 & 0xFF) * a2;
b1 = p1.B * a1; g1 = p1.G * a1; r1 = p1.R * a1;
b2 = p1.B * a2; g2 = p2.G * a2; r2 = p2.R * a2;
/* https://stackoverflow.com/a/347376
We need to convert RGB back from the pre-multiplied average into normal form
((r1 + r2) / 2) / ((a1 + a2) / 2)
but we just cancel out the / 2*/
uint32_t aAve = aSum >> 1;
uint32_t rAve = (r1 + r2) / aSum;
uint32_t gAve = (g1 + g2) / aSum;
uint32_t bAve = (b1 + b2) / aSum;
return (aAve << 24) | (rAve << 16) | (gAve << 8) | bAve;
ave.B = (b1 + b2) / aSum;
ave.G = (g1 + g2) / aSum;
ave.R = (r1 + r2) / aSum;
ave.A = aSum >> 1;
return ave;
}
void GfxCommon_GenMipmaps(int width, int height, uint8_t* lvlScan0, uint8_t* scan0) {
uint32_t* baseSrc = (uint32_t*)scan0;
uint32_t* baseDst = (uint32_t*)lvlScan0;
BitmapCol* baseSrc = (BitmapCol*)scan0;
BitmapCol* baseDst = (BitmapCol*)lvlScan0;
int srcWidth = width << 1;
int x, y;
for (y = 0; y < height; y++) {
int srcY = (y << 1);
uint32_t* src0 = baseSrc + srcY * srcWidth;
uint32_t* src1 = src0 + srcWidth;
uint32_t* dst = baseDst + y * width;
BitmapCol* src0 = baseSrc + srcY * srcWidth;
BitmapCol* src1 = src0 + srcWidth;
BitmapCol* dst = baseDst + y * width;
for (x = 0; x < width; x++) {
int srcX = (x << 1);
uint32_t src00 = src0[srcX], src01 = src0[srcX + 1];
uint32_t src10 = src1[srcX], src11 = src1[srcX + 1];
BitmapCol src00 = src0[srcX], src01 = src0[srcX + 1];
BitmapCol src10 = src1[srcX], src11 = src1[srcX + 1];
/* bilinear filter this mipmap */
uint32_t ave0 = GfxCommon_Average(src00, src01);
uint32_t ave1 = GfxCommon_Average(src10, src11);
BitmapCol ave0 = GfxCommon_Average(src00, src01);
BitmapCol ave1 = GfxCommon_Average(src10, src11);
dst[x] = GfxCommon_Average(ave0, ave1);
}
}

View File

@ -13,10 +13,6 @@ bool PackedCol_Equals(PackedCol a, PackedCol b) {
return a.R == b.R && a.G == b.G && a.B == b.B && a.A == b.A;
}
uint32_t PackedCol_ToARGB(PackedCol col) {
return PackedCol_ARGB(col.R, col.G, col.B, col.A);
}
PackedCol PackedCol_Scale(PackedCol value, float t) {
value.R = (uint8_t)(value.R * t);
value.G = (uint8_t)(value.G * t);

View File

@ -1,11 +1,11 @@
#ifndef CC_PACKEDCOL_H
#define CC_PACKEDCOL_H
#include "String.h"
/* Manipulates an ARGB colour, in a format suitable for the native 3d graphics api.
/* Manipulates an ARGB colour, in a format suitable for the native 3D graphics API.
Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
*/
/* Represents an ARGB colour, in a format suitable for the native graphics api. */
/* Represents an ARGB colour, suitable for native graphics API colours. */
typedef CC_ALIGN_HINT(4) struct PackedCol_ {
#ifdef CC_BUILD_D3D9
uint8_t B, G, R, A;
@ -14,25 +14,22 @@
#endif
} PackedCol;
/* Represents an ARGB colour, in a format suitable for the native graphics api. */
/* Represents an ARGB colour, suitable for native graphics API colours. */
/* Unioned with Packed member for efficient equality comparison */
typedef union PackedColUnion_ { PackedCol C; uint32_t Raw; } PackedColUnion;
/* NOTE: can't just use "struct { uint8_t B, G, R, A; };" here,
because unnamed members aren't supported on all compilers) */
#ifdef CC_BUILD_D3D9
#define PACKEDCOL_CONST(r, g, b, a) { b, g, r, a }
#else
#define PACKEDCOL_CONST(r, g, b, a) { r, g, b, a }
#endif
#define PACKEDCOL_WHITE PACKEDCOL_CONST(255, 255, 255, 255)
PackedCol PackedCol_Create4(uint8_t r, uint8_t g, uint8_t b, uint8_t a);
PackedCol PackedCol_Create3(uint8_t r, uint8_t g, uint8_t b);
bool PackedCol_Equals(PackedCol a, PackedCol b);
#define PackedCol_ARGB(r, g, b, a) (((uint32_t)(r) << 16) | ((uint32_t)(g) << 8) | ((uint32_t)(b)) | ((uint32_t)(a) << 24))
#define PackedCol_ARGB_A(col) ((uint8_t)((col) >> 24))
uint32_t PackedCol_ToARGB(PackedCol col);
PackedCol PackedCol_Scale(PackedCol value, float t);
PackedCol PackedCol_Lerp(PackedCol a, PackedCol b, float t);
CC_NOINLINE bool PackedCol_Unhex(char hex, int* value);
@ -44,13 +41,4 @@ CC_NOINLINE bool PackedCol_TryParseHex(const String* str, PackedCol* value);
#define PACKEDCOL_SHADE_YMIN 0.5f
/* Retrieves shaded colours for ambient block face lighting */
void PackedCol_GetShaded(PackedCol normal, PackedCol* xSide, PackedCol* zSide, PackedCol* yMin);
#define PACKEDCOL_WHITE PACKEDCOL_CONST(255, 255, 255, 255)
#define PACKEDCOL_BLACK PACKEDCOL_CONST( 0, 0, 0, 255)
#define PACKEDCOL_RED PACKEDCOL_CONST(255, 0, 0, 255)
#define PACKEDCOL_GREEN PACKEDCOL_CONST( 0, 255, 0, 255)
#define PACKEDCOL_BLUE PACKEDCOL_CONST( 0, 0, 255, 255)
#define PACKEDCOL_YELLOW PACKEDCOL_CONST(255, 255, 0, 255)
#define PACKEDCOL_MAGENTA PACKEDCOL_CONST(255, 0, 255, 255)
#define PACKEDCOL_CYAN PACKEDCOL_CONST( 0, 255, 255, 255)
#endif

View File

@ -1212,7 +1212,7 @@ static void CPE_BulkBlockUpdate(uint8_t* data) {
}
static void CPE_SetTextColor(uint8_t* data) {
PackedCol c;
BitmapCol c;
uint8_t code;
c.R = *data++; c.G = *data++; c.B = *data++; c.A = *data++;

View File

@ -1007,7 +1007,7 @@ Size2D Platform_TextMeasure(struct DrawTextArgs* args) {
return s;
}
Size2D Platform_TextDraw(struct DrawTextArgs* args, Bitmap* bmp, int x, int y, PackedCol col) {
Size2D Platform_TextDraw(struct DrawTextArgs* args, Bitmap* bmp, int x, int y, BitmapCol col) {
FT_Face face = args->Font.Handle;
String text = args->Text;
Size2D s = { x, TEXT_CEIL(face->size->metrics.height) };
@ -1024,18 +1024,18 @@ Size2D Platform_TextDraw(struct DrawTextArgs* args, Bitmap* bmp, int x, int y, P
for (yy = 0; yy < img->rows; yy++) {
if ((y + yy) < 0 || (y + yy) >= bmp->Height) continue;
uint8_t* src = img->buffer + (yy * img->width);
uint8_t* dst = (uint8_t*)Bitmap_GetRow(bmp, y + yy) + (x * BITMAP_SIZEOF_PIXEL);
BitmapCol* dst = Bitmap_GetRow(bmp, y + yy) + x;
for (xx = 0; xx < img->width; xx++) {
if ((x + xx) < 0 || (x + xx) >= bmp->Width) continue;
uint8_t intensity = *src, invIntensity = UInt8_MaxValue - intensity;
dst[0] = ((col.B * intensity) >> 8) + ((dst[0] * invIntensity) >> 8);
dst[1] = ((col.G * intensity) >> 8) + ((dst[1] * invIntensity) >> 8);
dst[2] = ((col.R * intensity) >> 8) + ((dst[2] * invIntensity) >> 8);
//dst[3] = ((col.A * intensity) >> 8) + ((dst[3] * invIntensity) >> 8);
dst[3] = intensity + ((dst[3] * invIntensity) >> 8);
src++; dst += BITMAP_SIZEOF_PIXEL;
dst->B = ((col.B * intensity) >> 8) + ((dst->B * invIntensity) >> 8);
dst->G = ((col.G * intensity) >> 8) + ((dst->G * invIntensity) >> 8);
dst->R = ((col.R * intensity) >> 8) + ((dst->R * invIntensity) >> 8);
//dst[3] = ((col.A * intensity) >> 8) + ((dst->A * invIntensity) >> 8);
dst->A = intensity + ((dst->A * invIntensity) >> 8);
src++; dst++;
}
}

View File

@ -2,6 +2,7 @@
#define CC_PLATFORM_H
#include "Utils.h"
#include "PackedCol.h"
#include "Bitmap.h"
/* Abstracts platform specific memory management, I/O, etc.
Copyright 2017 ClassicalSharp | Licensed under BSD-3
*/
@ -176,7 +177,7 @@ CC_EXPORT void Font_Free(FontDesc* desc);
/* Measures dimensions of the given text, if it was drawn with the given font. */
CC_EXPORT Size2D Platform_TextMeasure(struct DrawTextArgs* args);
/* Draws the given text with the given font onto the given bitmap. */
CC_EXPORT Size2D Platform_TextDraw(struct DrawTextArgs* args, Bitmap* bmp, int x, int y, PackedCol col);
CC_EXPORT Size2D Platform_TextDraw(struct DrawTextArgs* args, Bitmap* bmp, int x, int y, BitmapCol col);
/* Allocates a new socket. */
void Socket_Create(SocketPtr* socket);

View File

@ -1,5 +1,4 @@
#include "TerrainAtlas.h"
#include "Bitmap.h"
#include "Block.h"
#include "ExtMath.h"
#include "Funcs.h"

View File

@ -1,6 +1,6 @@
#ifndef CC_TERRAINATLAS_H
#define CC_TERRAINATLAS_H
#include "Core.h"
#include "Bitmap.h"
/* Represents the 2D texture atlas of terrain.png, and converted into an array of 1D textures.
Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
*/

View File

@ -154,14 +154,13 @@ int Utils_AccumulateWheelDelta(float* accumulator, float delta) {
}
uint8_t Utils_GetSkinType(const Bitmap* bmp) {
int scale;
if (bmp->Width == bmp->Height * 2) return SKIN_64x32;
if (bmp->Width != bmp->Height) return SKIN_INVALID;
/* Minecraft alex skins have this particular pixel with alpha of 0 */
int scale = bmp->Width / 64;
uint32_t pixel = Bitmap_GetPixel(bmp, 54 * scale, 20 * scale);
uint8_t alpha = PackedCol_ARGB_A(pixel);
return alpha >= 127 ? SKIN_64x64 : SKIN_64x64_SLIM;
scale = bmp->Width / 64;
return Bitmap_GetPixel(bmp, 54 * scale, 20 * scale).A >= 127 ? SKIN_64x64 : SKIN_64x64_SLIM;
}
uint32_t Utils_CRC32(const uint8_t* data, uint32_t length) {

View File

@ -1,6 +1,7 @@
#ifndef CC_UTILS_H
#define CC_UTILS_H
#include "String.h"
#include "Bitmap.h"
/* Implements various utility functions.
Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
*/

View File

@ -925,6 +925,7 @@ static char InputWidget_GetLastCol(struct InputWidget* w, int x, int y) {
}
static void InputWidget_UpdateCaret(struct InputWidget* w) {
BitmapCol col;
String line; char lineBuffer[STRING_SIZE];
struct DrawTextArgs args;
int maxChars, lineWidth;
@ -961,7 +962,9 @@ static void InputWidget_UpdateCaret(struct InputWidget* w) {
colCode = InputWidget_GetLastCol(w, w->CaretX, w->CaretY);
if (colCode) {
w->CaretCol = Drawer2D_GetCol(colCode);
col = Drawer2D_GetCol(colCode);
w->CaretCol.B = col.B; w->CaretCol.G = col.G;
w->CaretCol.R = col.R; w->CaretCol.A = col.A;
} else {
PackedCol white = PACKEDCOL_WHITE;
w->CaretCol = PackedCol_Scale(white, 0.8f);
@ -2725,9 +2728,9 @@ static Size2D SpecialInputWidget_MeasureTitles(struct SpecialInputWidget* w) {
}
static void SpecialInputWidget_DrawTitles(struct SpecialInputWidget* w, Bitmap* bmp) {
PackedCol col_selected = PACKEDCOL_CONST(30, 30, 30, 200);
PackedCol col_inactive = PACKEDCOL_CONST( 0, 0, 0, 127);
PackedCol col;
BitmapCol col_selected = BITMAPCOL_CONST(30, 30, 30, 200);
BitmapCol col_inactive = BITMAPCOL_CONST( 0, 0, 0, 127);
BitmapCol col;
struct DrawTextArgs args;
Size2D size;
@ -2788,7 +2791,7 @@ static void SpecialInputWidget_DrawContent(struct SpecialInputWidget* w, struct
}
static void SpecialInputWidget_Make(struct SpecialInputWidget* w, struct SpecialInputTab* tab) {
PackedCol col = PACKEDCOL_CONST(30, 30, 30, 200);
BitmapCol col = PACKEDCOL_CONST(30, 30, 30, 200);
Size2D size, titles, content;
Bitmap bmp;