Start texturing
This commit is contained in:
parent
67567e210a
commit
d02b8b4ec3
5 changed files with 752 additions and 728 deletions
|
@ -144,7 +144,7 @@ int main(void)
|
||||||
|
|
||||||
for (int i = 0; i < 8; ++i)
|
for (int i = 0; i < 8; ++i)
|
||||||
{
|
{
|
||||||
unsigned int color = palette[j * 32 + i];
|
unsigned int color = palette[j * 8 + i];
|
||||||
printf("0x%02x,0x%02x,",color & 0xff,color >> 8);
|
printf("0x%02x,0x%02x,",color & 0xff,color >> 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,79 +0,0 @@
|
||||||
import sys
|
|
||||||
from PIL import Image
|
|
||||||
|
|
||||||
def rgbTo565(rgb):
|
|
||||||
return ((rgb[0] >> 3) << 11) | ((rgb[1] >> 2) << 5) | ((rgb[2] >> 3))
|
|
||||||
|
|
||||||
def colorDist(c1,c2):
|
|
||||||
return abs((c1 & 0x1f) - (c2 & 0x1f)) + abs(((c1 >> 5) & 0x3f) - ((c2 >> 5) & 0x3f)) + abs((c1 >> 11) - (c2 >> 11))
|
|
||||||
|
|
||||||
FILENAME = sys.argv[1]
|
|
||||||
|
|
||||||
image = Image.open(FILENAME).convert("RGB")
|
|
||||||
|
|
||||||
IMG_SIZE = image.size[0]
|
|
||||||
|
|
||||||
pixels = image.load()
|
|
||||||
|
|
||||||
outArray = []
|
|
||||||
|
|
||||||
if IMG_SIZE == 64: # normal texture
|
|
||||||
for y in range(IMG_SIZE):
|
|
||||||
for x in range(IMG_SIZE):
|
|
||||||
outArray.append(rgbTo565(pixels[(x,y)]))
|
|
||||||
else: # sky texture
|
|
||||||
hist = [0 for i in range(65536)]
|
|
||||||
|
|
||||||
for y in range(IMG_SIZE):
|
|
||||||
for x in range(IMG_SIZE):
|
|
||||||
hist[rgbTo565(pixels[(x,y)])] += 1
|
|
||||||
|
|
||||||
for i in range(256): # make the palette from 256 most common colors
|
|
||||||
histMaxIndex = 0
|
|
||||||
|
|
||||||
for j in range(65536):
|
|
||||||
if hist[j] > hist[histMaxIndex]:
|
|
||||||
histMaxIndex = j
|
|
||||||
|
|
||||||
outArray.append(histMaxIndex)
|
|
||||||
|
|
||||||
hist[histMaxIndex] = -1
|
|
||||||
|
|
||||||
odd = True
|
|
||||||
|
|
||||||
for y in range(IMG_SIZE):
|
|
||||||
for x in range(IMG_SIZE):
|
|
||||||
pixel = rgbTo565(pixels[(x,y)])
|
|
||||||
|
|
||||||
closestIndex = 0
|
|
||||||
closestDist = 1000
|
|
||||||
|
|
||||||
for i in range(256):
|
|
||||||
dist = colorDist(pixel,outArray[i])
|
|
||||||
|
|
||||||
if dist < closestDist:
|
|
||||||
closestDist = dist
|
|
||||||
closestIndex = i
|
|
||||||
|
|
||||||
if closestDist == 0:
|
|
||||||
break
|
|
||||||
|
|
||||||
if odd:
|
|
||||||
outArray.append(closestIndex)
|
|
||||||
odd = False
|
|
||||||
else:
|
|
||||||
outArray[-1] = outArray[-1] | (closestIndex << 8)
|
|
||||||
odd = True
|
|
||||||
|
|
||||||
outStr = ""
|
|
||||||
|
|
||||||
for i in range(len(outArray)):
|
|
||||||
if i % 16 == 0:
|
|
||||||
outStr += "\n "
|
|
||||||
|
|
||||||
outStr += "{0:#0{1}x}".format(outArray[i],6)
|
|
||||||
|
|
||||||
if i != len(outArray) - 1:
|
|
||||||
outStr += ","
|
|
||||||
|
|
||||||
print(outStr)
|
|
15
game.h
15
game.h
|
@ -112,6 +112,9 @@ void LCR_gameInit(void)
|
||||||
LCR_mapLoad(map1);
|
LCR_mapLoad(map1);
|
||||||
|
|
||||||
LCR_rendererInit();
|
LCR_rendererInit();
|
||||||
|
|
||||||
|
|
||||||
|
LCR_loadImage(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LCR_gameEnd(void)
|
void LCR_gameEnd(void)
|
||||||
|
@ -127,18 +130,8 @@ uint8_t LCR_gameStep(uint32_t time)
|
||||||
|
|
||||||
if (time >= LCR_nextRenderFrameTime)
|
if (time >= LCR_nextRenderFrameTime)
|
||||||
{
|
{
|
||||||
int skyOffsetV = LCR_EFFECTIVE_RESOLUTION_Y / 2 +
|
LCR_drawBackground(0);
|
||||||
((LCR_EFFECTIVE_RESOLUTION_Y / 2) *
|
|
||||||
LCR_rendererGetCameraPitch()) /
|
|
||||||
(LCR_SQUARE_SIDE_LEN / LCR_SETTING_SKY_ROLL_MULTIPLIER_V);
|
|
||||||
|
|
||||||
int skyOffsetH = LCR_SKY_IMAGE_SIZE - 1 -
|
|
||||||
(LCR_rendererGetCameraYaw() * LCR_SKY_IMAGE_SIZE) /
|
|
||||||
(LCR_SQUARE_SIDE_LEN / LCR_SETTING_SKY_ROLL_MULTIPLIER_H);
|
|
||||||
|
|
||||||
LCR_drawBackground(skyOffsetV);
|
|
||||||
LCR_rendererDraw();
|
LCR_rendererDraw();
|
||||||
LCR_drawSkyStrip(skyOffsetV,skyOffsetH);
|
|
||||||
|
|
||||||
LCR_nextRenderFrameTime += 1000 / LCR_SETTING_FPS;
|
LCR_nextRenderFrameTime += 1000 / LCR_SETTING_FPS;
|
||||||
|
|
||||||
|
|
219
renderer.h
219
renderer.h
|
@ -9,6 +9,9 @@
|
||||||
#define S3L_RESOLUTION_Y LCR_SETTING_RESOLUTION_Y
|
#define S3L_RESOLUTION_Y LCR_SETTING_RESOLUTION_Y
|
||||||
#define S3L_PIXEL_FUNCTION LCR_pixelFunc3D
|
#define S3L_PIXEL_FUNCTION LCR_pixelFunc3D
|
||||||
|
|
||||||
|
#define S3L_PERSPECTIVE_CORRECTION 2
|
||||||
|
#define S3L_NEAR_CROSS_STRATEGY 0
|
||||||
|
|
||||||
#define S3L_Z_BUFFER 2
|
#define S3L_Z_BUFFER 2
|
||||||
|
|
||||||
#include "small3dlib.h"
|
#include "small3dlib.h"
|
||||||
|
@ -28,9 +31,78 @@ S3L_Model3D *LCR_mapModel;
|
||||||
S3L_Unit LCR_mapVertices[LCR_SETTING_MAX_MAP_VERTICES * 3];
|
S3L_Unit LCR_mapVertices[LCR_SETTING_MAX_MAP_VERTICES * 3];
|
||||||
S3L_Index LCR_mapTriangles[LCR_SETTING_MAX_MAP_TRIANGLES * 3];
|
S3L_Index LCR_mapTriangles[LCR_SETTING_MAX_MAP_TRIANGLES * 3];
|
||||||
|
|
||||||
|
|
||||||
|
int _LCR_rendererPreviousTriangleID;
|
||||||
|
int _LCR_rendererTriangleUVs[6];
|
||||||
|
|
||||||
|
uint16_t _LCR_triangleShadingMask;
|
||||||
|
|
||||||
void LCR_pixelFunc3D(S3L_PixelInfo *pixel)
|
void LCR_pixelFunc3D(S3L_PixelInfo *pixel)
|
||||||
{
|
{
|
||||||
LCR_drawPixelXYSafe(pixel->x,pixel->y,0xff00 + (pixel->triangleID % 16) * 16 );
|
// once we get a new triangle, we precompute things for it:
|
||||||
|
if (pixel->triangleIndex != _LCR_rendererPreviousTriangleID)
|
||||||
|
{
|
||||||
|
S3L_Index *t = LCR_mapTriangles + 3 * pixel->triangleIndex;
|
||||||
|
|
||||||
|
S3L_Unit *v[3];
|
||||||
|
|
||||||
|
v[0] = LCR_mapVertices + 3 * t[0];
|
||||||
|
v[1] = LCR_mapVertices + 3 * t[1];
|
||||||
|
v[2] = LCR_mapVertices + 3 * t[2];
|
||||||
|
|
||||||
|
uint8_t type = // 0: floor, 1: wall, 2: wall 90 degrees
|
||||||
|
(v[0][0] == v[1][0] && v[1][0] == v[2][0]) +
|
||||||
|
2 * (v[0][2] == v[1][2] && v[1][2] == v[2][2]);
|
||||||
|
|
||||||
|
if (type == 0)
|
||||||
|
{
|
||||||
|
LCR_loadImage(1);
|
||||||
|
_LCR_triangleShadingMask = 0xffff;
|
||||||
|
|
||||||
|
for (int i = 0; i < 6; ++i)
|
||||||
|
_LCR_rendererTriangleUVs[i] = ((
|
||||||
|
(v[i / 2][(i % 2) * 2]) *
|
||||||
|
LCR_IMAGE_SIZE) / LCR_RENDERER_UNIT);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LCR_loadImage(0);
|
||||||
|
|
||||||
|
for (int i = 0; i < 6; ++i)
|
||||||
|
{
|
||||||
|
_LCR_rendererTriangleUVs[i] = ((
|
||||||
|
(v[i / 2][i % 2 ? 1 : (type == 1 ? 2 : 0)]) *
|
||||||
|
LCR_IMAGE_SIZE) / LCR_RENDERER_UNIT);
|
||||||
|
|
||||||
|
if (i % 2)
|
||||||
|
_LCR_rendererTriangleUVs[i] = LCR_IMAGE_SIZE -
|
||||||
|
_LCR_rendererTriangleUVs[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
_LCR_triangleShadingMask = type == 1 ? 0xf7de : 0xe79c;
|
||||||
|
}
|
||||||
|
|
||||||
|
_LCR_rendererPreviousTriangleID = pixel->triangleIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
int barycentric[3];
|
||||||
|
|
||||||
|
barycentric[0] = pixel->barycentric[0] / 8;
|
||||||
|
barycentric[1] = pixel->barycentric[1] / 8;
|
||||||
|
barycentric[2] = pixel->barycentric[2] / 8;
|
||||||
|
|
||||||
|
uint16_t color = LCR_sampleImage(
|
||||||
|
(barycentric[0] * _LCR_rendererTriangleUVs[0] +
|
||||||
|
barycentric[1] * _LCR_rendererTriangleUVs[2] +
|
||||||
|
barycentric[2] * _LCR_rendererTriangleUVs[4])
|
||||||
|
/ (S3L_FRACTIONS_PER_UNIT / 8),
|
||||||
|
(barycentric[0] * _LCR_rendererTriangleUVs[1] +
|
||||||
|
barycentric[1] * _LCR_rendererTriangleUVs[3] +
|
||||||
|
barycentric[2] * _LCR_rendererTriangleUVs[5])
|
||||||
|
/ (S3L_FRACTIONS_PER_UNIT / 8)
|
||||||
|
) & _LCR_triangleShadingMask;
|
||||||
|
|
||||||
|
LCR_drawPixelXYUnsafe(pixel->x,pixel->y,color);
|
||||||
}
|
}
|
||||||
|
|
||||||
S3L_Index _LCR_addMapVertex(S3L_Unit x, S3L_Unit y, S3L_Unit z)
|
S3L_Index _LCR_addMapVertex(S3L_Unit x, S3L_Unit y, S3L_Unit z)
|
||||||
|
@ -91,6 +163,45 @@ void _LCR_rendererSwapTriangles(S3L_Index *t1, S3L_Index *t2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int _LCR_quadCoversTriangle(const S3L_Unit quad[8], const S3L_Unit tri[6])
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 3; ++i) // for each triangle point
|
||||||
|
{
|
||||||
|
int covered = 0;
|
||||||
|
|
||||||
|
for (int j = 0; j < 3; ++j) // for each quad subtriangle
|
||||||
|
{
|
||||||
|
uint8_t winds = 0;
|
||||||
|
|
||||||
|
for (int k = 0; k < 3; ++k) // for each subtriangle side
|
||||||
|
{
|
||||||
|
S3L_Unit w = // triangle winding
|
||||||
|
(quad[(2 * (j + ((k + 1) % 3))) % 8 + 1] -
|
||||||
|
quad[(2 * (j + k)) % 8 + 1]) *
|
||||||
|
(tri[2 * i] - quad[(2 * (j + (k + 1) % 3)) % 8]) -
|
||||||
|
(quad[(2 * (j + ((k + 1) % 3))) % 8] - quad[(2 * (j + k)) % 8])
|
||||||
|
* (tri[2 * i + 1] - quad[(2 * (j + (k + 1) % 3)) % 8 + 1]);
|
||||||
|
|
||||||
|
if (w > 0)
|
||||||
|
winds |= 1;
|
||||||
|
else if (w < 0)
|
||||||
|
winds |= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (winds != 3) // no opposite winds?
|
||||||
|
{
|
||||||
|
covered = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!covered)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Checks whether two triangles (and potenrially their neighbors) cover each
|
Checks whether two triangles (and potenrially their neighbors) cover each
|
||||||
other, in return values lowest bit means whether t1 is covered and the second
|
other, in return values lowest bit means whether t1 is covered and the second
|
||||||
|
@ -194,45 +305,6 @@ uint8_t _LCR_rendererCheckMapTriangleCover(const S3L_Index *t1,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
int _LCR_quadCoversTriangle(const S3L_Unit quad[8], const S3L_Unit tri[6])
|
|
||||||
{
|
|
||||||
for (int i = 0; i < 3; ++i) // for each triangle point
|
|
||||||
{
|
|
||||||
int covered = 0;
|
|
||||||
|
|
||||||
for (int j = 0; j < 3; ++j) // for each quad subtriangle
|
|
||||||
{
|
|
||||||
uint8_t winds = 0;
|
|
||||||
|
|
||||||
for (int k = 0; k < 3; ++k) // for each subtriangle side
|
|
||||||
{
|
|
||||||
S3L_Unit w = // triangle winding
|
|
||||||
(quad[(2 * (j + ((k + 1) % 3))) % 8 + 1] -
|
|
||||||
quad[(2 * (j + k)) % 8 + 1]) *
|
|
||||||
(tri[2 * i] - quad[(2 * (j + (k + 1) % 3)) % 8]) -
|
|
||||||
(quad[(2 * (j + ((k + 1) % 3))) % 8] - quad[(2 * (j + k)) % 8])
|
|
||||||
* (tri[2 * i + 1] - quad[(2 * (j + (k + 1) % 3)) % 8 + 1]);
|
|
||||||
|
|
||||||
if (w > 0)
|
|
||||||
winds |= 1;
|
|
||||||
else if (w < 0)
|
|
||||||
winds |= 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (winds != 3) // no opposite winds?
|
|
||||||
{
|
|
||||||
covered = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!covered)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Removes map triangles that are covered by other triangles (and also vertices
|
Removes map triangles that are covered by other triangles (and also vertices
|
||||||
that by this become unused). This makes the map model smaller, faster and
|
that by this become unused). This makes the map model smaller, faster and
|
||||||
|
@ -344,7 +416,6 @@ uint8_t _LCR_rendererBuildMapModel(void)
|
||||||
blockShapeBytes,&blockShapeByteCount);
|
blockShapeBytes,&blockShapeByteCount);
|
||||||
|
|
||||||
uint8_t vx, vy, vz, vi = 0;
|
uint8_t vx, vy, vz, vi = 0;
|
||||||
uint8_t *bytes = blockShapeBytes;
|
|
||||||
S3L_Index triangleIndices[3];
|
S3L_Index triangleIndices[3];
|
||||||
|
|
||||||
S3L_Unit originOffset = -1 * LCR_MAP_SIZE_BLOCKS / 2 * LCR_RENDERER_UNIT;
|
S3L_Unit originOffset = -1 * LCR_MAP_SIZE_BLOCKS / 2 * LCR_RENDERER_UNIT;
|
||||||
|
@ -421,6 +492,7 @@ void LCR_rendererMoveCamera(LCR_SpaceUnit forwRightUpOffset[3],
|
||||||
|
|
||||||
void LCR_rendererDraw(void)
|
void LCR_rendererDraw(void)
|
||||||
{
|
{
|
||||||
|
_LCR_rendererPreviousTriangleID = -1;
|
||||||
S3L_newFrame();
|
S3L_newFrame();
|
||||||
S3L_drawScene(LCR_scene3D);
|
S3L_drawScene(LCR_scene3D);
|
||||||
}
|
}
|
||||||
|
@ -428,81 +500,16 @@ void LCR_rendererDraw(void)
|
||||||
void LCR_drawBackground(int verticalOffset)
|
void LCR_drawBackground(int verticalOffset)
|
||||||
{
|
{
|
||||||
|
|
||||||
// TODO
|
|
||||||
|
|
||||||
for (int y = 0; y < LCR_EFFECTIVE_RESOLUTION_Y; ++y)
|
for (int y = 0; y < LCR_EFFECTIVE_RESOLUTION_Y; ++y)
|
||||||
for (int x = 0; x < LCR_EFFECTIVE_RESOLUTION_X; ++x)
|
for (int x = 0; x < LCR_EFFECTIVE_RESOLUTION_X; ++x)
|
||||||
LCR_drawPixelXYUnsafe(x,y,0xffff);
|
LCR_drawPixelXYUnsafe(x,y,0xffff);
|
||||||
|
|
||||||
/*
|
|
||||||
uint16_t color = LCR_skyImages[LCR_skyImages[256] & 0x00ff] ; // TODO
|
|
||||||
int limit = verticalOffset - LCR_SETTING_SKY_SIZE * LCR_SKY_IMAGE_SIZE / 2;
|
|
||||||
|
|
||||||
if (limit >= LCR_EFFECTIVE_RESOLUTION_Y)
|
|
||||||
limit = LCR_EFFECTIVE_RESOLUTION_Y - 1;
|
|
||||||
|
|
||||||
for (int y = 0; y <= limit; ++y)
|
|
||||||
for (int x = 0; x < LCR_EFFECTIVE_RESOLUTION_X; ++x)
|
|
||||||
LCR_drawPixelUnsafe(x,y,color);
|
|
||||||
|
|
||||||
color = LCR_skyImages[LCR_skyImages[255 + (128 * 128) / 2] >> 8]; // TODO
|
|
||||||
limit = verticalOffset + LCR_SETTING_SKY_SIZE * LCR_SKY_IMAGE_SIZE / 2 -
|
|
||||||
LCR_SETTING_SKY_SIZE;
|
|
||||||
|
|
||||||
if (limit < 0)
|
|
||||||
limit = 0;
|
|
||||||
|
|
||||||
for (int y = LCR_EFFECTIVE_RESOLUTION_Y - 1; y >= limit; --y)
|
|
||||||
for (int x = 0; x < LCR_EFFECTIVE_RESOLUTION_X; ++x)
|
|
||||||
LCR_drawPixelUnsafe(x,y,color);
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LCR_drawSkyStrip(int verticalOffset, uint8_t horizontalOffset)
|
void LCR_drawSkyStrip(int verticalOffset, uint8_t horizontalOffset)
|
||||||
{
|
{
|
||||||
#if LCR_SETTING_SKY_SIZE != 0
|
#if LCR_SETTING_SKY_SIZE != 0
|
||||||
/*
|
|
||||||
verticalOffset -= (LCR_SETTING_SKY_SIZE * LCR_SKY_IMAGE_SIZE) / 2;
|
|
||||||
|
|
||||||
int finalY = verticalOffset + LCR_SETTING_SKY_SIZE * LCR_SKY_IMAGE_SIZE;
|
|
||||||
|
|
||||||
finalY = (finalY / LCR_SETTING_SKY_SIZE) * LCR_SETTING_SKY_SIZE;
|
|
||||||
|
|
||||||
if (finalY >= LCR_EFFECTIVE_RESOLUTION_Y)
|
|
||||||
finalY = LCR_EFFECTIVE_RESOLUTION_Y - 1;
|
|
||||||
|
|
||||||
const uint16_t *skyLine = LCR_skyImages + 256;
|
|
||||||
|
|
||||||
if (verticalOffset < 0)
|
|
||||||
{
|
|
||||||
skyLine += (-1 * verticalOffset / LCR_SETTING_SKY_SIZE) * (LCR_SKY_IMAGE_SIZE / 2);
|
|
||||||
verticalOffset = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (verticalOffset < finalY)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < LCR_EFFECTIVE_RESOLUTION_X; ++i)
|
|
||||||
{
|
|
||||||
// only diraw background on empty pixels
|
|
||||||
if (S3L_zBufferRead(i,verticalOffset) == S3L_MAX_DEPTH)
|
|
||||||
{
|
|
||||||
int offsetX = (i / LCR_SETTING_SKY_SIZE + horizontalOffset)
|
|
||||||
% LCR_SKY_IMAGE_SIZE;
|
|
||||||
|
|
||||||
uint16_t pixel = *(skyLine + offsetX / 2);
|
|
||||||
|
|
||||||
pixel = offsetX % 2 ? (pixel >> 8) : (pixel & 0x00ff);
|
|
||||||
|
|
||||||
LCR_drawPixelUnsafe(i,verticalOffset,LCR_skyImages[pixel]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
verticalOffset++;
|
|
||||||
|
|
||||||
if (verticalOffset % LCR_SETTING_SKY_SIZE == 0)
|
|
||||||
skyLine += LCR_SKY_IMAGE_SIZE / 2;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue