From fb962ec7b9187206936f3bf4761c76e81030c2d0 Mon Sep 17 00:00:00 2001 From: XProger Date: Sat, 5 Oct 2019 07:21:16 +0300 Subject: [PATCH] software rasterizer (triangles, quads, textured, color palette, lightmap) --- src/cache.h | 2 +- src/camera.h | 11 +- src/controller.h | 12 +- src/core.h | 17 +- src/format.h | 38 +- src/gapi/gl.h | 5 +- src/gapi/sw.h | 708 ++++++++++++++++++------------ src/inventory.h | 4 +- src/level.h | 96 ++-- src/mesh.h | 15 +- src/platform/win/OpenLara.vcxproj | 4 +- src/platform/win/main.cpp | 2 +- src/texture.h | 18 +- src/utils.h | 41 +- 14 files changed, 592 insertions(+), 381 deletions(-) diff --git a/src/cache.h b/src/cache.h index 75b0b68..b1f14b0 100644 --- a/src/cache.h +++ b/src/cache.h @@ -870,7 +870,7 @@ struct WaterCache { game->setupBinding(); // merge visible rooms for all items - int roomsList[256]; + RoomDesc roomsList[256]; int roomsCount = 0; for (int i = 0; i < level->roomsCount; i++) diff --git a/src/camera.h b/src/camera.h index f5cdb15..d45cecc 100644 --- a/src/camera.h +++ b/src/camera.h @@ -6,9 +6,6 @@ #include "controller.h" #include "character.h" -#define CAM_OFFSET_COMBAT (2048.0f + 512.0f) -#define CAM_OFFSET_LOOK (512.0f) - #define CAM_SPEED_FOLLOW 12 #define CAM_SPEED_COMBAT 8 @@ -21,6 +18,14 @@ #define CAM_OFFSET_FOLLOW (1024.0f + 512.0f) #endif +#ifdef _OS_BITTBOY + #define CAM_OFFSET_COMBAT CAM_OFFSET_FOLLOW +#else + #define CAM_OFFSET_COMBAT (2048.0f + 512.0f) +#endif + +#define CAM_OFFSET_LOOK (512.0f) + #define CAM_FOLLOW_ANGLE 0.0f #define CAM_LOOK_ANGLE_XMAX ( 55.0f * DEG2RAD) #define CAM_LOOK_ANGLE_XMIN (-75.0f * DEG2RAD) diff --git a/src/controller.h b/src/controller.h index 95bdf42..6596176 100644 --- a/src/controller.h +++ b/src/controller.h @@ -46,6 +46,14 @@ struct ICamera { } }; +struct RoomDesc { + int32 index; + vec4 portal; + + RoomDesc() {} + RoomDesc(int32 index, const vec4 &portal) : index(index), portal(portal) {} +}; + struct IGame { virtual ~IGame() {} virtual void loadLevel(TR::LevelID id) {} @@ -68,11 +76,11 @@ struct IGame { virtual void setShader(Core::Pass pass, Shader::Type type, bool underwater = false, bool alphaTest = false) {} virtual void setRoomParams(int roomIndex, Shader::Type type, float diffuse, float ambient, float specular, float alpha, bool alphaTest = false) {} virtual void setupBinding() {} - virtual void getVisibleRooms(int *roomsList, int &roomsCount, int from, int to, const vec4 &viewPort, bool water, int count = 0) {} + virtual void getVisibleRooms(RoomDesc *roomsList, int &roomsCount, int from, int to, const vec4 &viewPort, bool water, int count = 0) {} virtual void renderEnvironment(int roomIndex, const vec3 &pos, Texture **targets, int stride = 0, Core::Pass pass = Core::passAmbient) {} virtual void renderModelFull(int modelIndex, bool underwater, Basis *joints) {} virtual void renderCompose(int roomIndex) {} - virtual void renderView(int roomIndex, bool water, bool showUI, int roomsCount = 0, int *roomsList = NULL) {} + virtual void renderView(int roomIndex, bool water, bool showUI, int roomsCount = 0, RoomDesc *roomsList = NULL) {} virtual void renderGame(bool showUI, bool invBG) {} virtual void setEffect(Controller *controller, TR::Effect::Type effect) {} diff --git a/src/core.h b/src/core.h index 19e3cfe..9402167 100644 --- a/src/core.h +++ b/src/core.h @@ -6,6 +6,8 @@ #endif #include +#include +#include #define OS_FILEIO_CACHE #define OS_PTHREAD_MT @@ -59,8 +61,9 @@ #define DYNGEOM_NO_VBO #elif __BITTBOY__ - #define _OS_LINUX 1 - #define _GAPI_SW 1 + #define _OS_BITTBOY 1 + #define _OS_LINUX 1 + #define _GAPI_SW 1 #elif __linux__ #define _OS_LINUX 1 #define _GAPI_GL 1 @@ -122,7 +125,7 @@ #ifdef FFP #define SPLIT_BY_TILE - #if defined(_GAPI_GU) || defined(_GAPI_SW) + #if defined(_GAPI_GU) #define SPLIT_BY_CLUT #endif #else @@ -461,7 +464,7 @@ struct Edge { struct Vertex { short4 coord; // xyz - position, w - joint index (for entities only) - short4 normal; // xyz - vertex normal, w - unused + short4 normal; // xyz - vertex normal, w - quad(0) or triangle (1) short4 texCoord; // xy - texture coordinates, zw - trapezoid warping ubyte4 color; // for non-textured geometry ubyte4 light; // xyz - color, w - use premultiplied alpha @@ -1044,6 +1047,12 @@ namespace Core { setViewport(Viewport(x, y, width, height)); } + void setViewport(const vec4 &vp, int width, int height) { + vec4 s = vec4(vp.x, -vp.w, vp.z, -vp.y); + s = (s * 0.5 + 0.5) * vec4(float(width), float(height), float(width), float(height)); + setViewport(int(s.x), int(s.y), int(s.z) - int(s.x), int(s.w) - int(s.y)); + } + void setCullMode(CullMode mode) { renderState &= ~RS_CULL; switch (mode) { diff --git a/src/format.h b/src/format.h index cc87122..84fc166 100644 --- a/src/format.h +++ b/src/format.h @@ -1752,30 +1752,6 @@ namespace TR { #define FACE4_SIZE (sizeof(uint16) + sizeof(uint16) * 4) // flags + vertices[4] #define FACE3_SIZE (FACE4_SIZE - sizeof(uint16)) - struct ColorIndex4 { - uint8 a:4, b:4; - }; - - struct Tile4 { - ColorIndex4 index[256 * 256 / 2]; - }; - - struct Tile8 { - uint8 index[256 * 256]; - }; - - struct Tile16 { - Color16 color[256 * 256]; - }; - - struct Tile32 { - Color32 color[256 * 256]; // + 128 for mips data - }; - - struct CLUT { - Color16 color[16]; - }; - struct Room { struct Info { @@ -2986,6 +2962,7 @@ namespace TR { int32 entitiesCount; Entity *entities; + uint8 lightmap[32 * 256]; // color indices table for 32 shades Color24 *palette; Color32 *palette32; @@ -2999,6 +2976,7 @@ namespace TR { Tile32 *tiles32; Tile32 *tilesMisc; + uint16 cameraFramesCount; CameraFrame *cameraFrames; @@ -3848,7 +3826,10 @@ namespace TR { } void readLightMap(Stream &stream) { - stream.seek(32 * 256); // unused + stream.raw(lightmap, 32 * 256); + for (int i = 0; i < 32; i++) { + lightmap[i * 256] = 0; + } } void readCameraFrames(Stream &stream) { @@ -6443,7 +6424,12 @@ namespace TR { Color32 getColor(int texture) const { switch (version) { case VER_TR1_SAT : return Color16((uint16)texture); - case VER_TR1_PC : return palette[texture & 0xFF]; + case VER_TR1_PC : + #ifdef _GAPI_SW + return Color32(texture & 0xFF, 0, 0, 142); + #else + return palette[texture & 0xFF]; + #endif case VER_TR2_PC : case VER_TR3_PC : return palette32[(texture >> 8) & 0xFF]; case VER_TR1_PSX : diff --git a/src/gapi/gl.h b/src/gapi/gl.h index 560a327..7e2c064 100644 --- a/src/gapi/gl.h +++ b/src/gapi/gl.h @@ -494,6 +494,7 @@ namespace GAPI { void init(Core::Pass pass, int type, int *def, int defCount) {} void deinit() {} void bind() {} + void validate() {} void setParam(UniformType uType, const vec4 &value, int count = 1) {} void setParam(UniformType uType, const mat4 &value, int count = 1) {} #else @@ -1257,8 +1258,7 @@ namespace GAPI { glScalef(1.0f / 32767.0f, 1.0f / 32767.0f, 1.0f / 32767.0f); glClearColor(0, 0, 0, 0); - #endif - + #else char extHeader[256]; GLSL_HEADER_VERT[0] = GLSL_HEADER_FRAG[0] = extHeader[0] = 0; if (_GL_OES_standard_derivatives) { @@ -1322,6 +1322,7 @@ namespace GAPI { #endif ASSERT(strlen(GLSL_HEADER_VERT) < COUNT(GLSL_HEADER_VERT)); ASSERT(strlen(GLSL_HEADER_FRAG) < COUNT(GLSL_HEADER_FRAG)); + #endif // FFP } void deinit() { diff --git a/src/gapi/sw.h b/src/gapi/sw.h index da95837..d70fdaa 100644 --- a/src/gapi/sw.h +++ b/src/gapi/sw.h @@ -11,6 +11,19 @@ #define COLOR_16 #endif +#ifdef COLOR_16 + #ifdef _OS_LINUX + #define COLOR_FMT_565 + #define CONV_COLOR(r,g,b) (((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3)) + #else + #define COLOR_FMT_555 + #define CONV_COLOR(r,g,b) (((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3)) + #endif +#else + #define COLOR_FMT_888 + #define CONV_COLOR(r,g,b) ((r << 16) | (g << 8) | b) +#endif + namespace GAPI { using namespace Core; @@ -24,6 +37,16 @@ namespace GAPI { #endif typedef uint16 DepthSW; + uint8 *swLightmap; // 32 * 256 + ColorSW *swPalette; + ColorSW swPaletteColor[256]; + ColorSW swPaletteWater[256]; + ColorSW swPaletteGray[256]; + uint8 swGradient[256]; + Tile8 *curTile; + + uint8 ambient; + // Shader struct Shader { void init(Pass pass, int type, int *def, int defCount) {} @@ -71,17 +94,11 @@ namespace GAPI { if (!this || (opt & OPT_PROXY)) return; ASSERT(memory); -// sceGuTexMode(GU_PSM_8888, 0, 0, getSwizzle()); -// sceGuTexImage(0, width, height, width, memory); + curTile = NULL; } - void bindTileCLUT(void *tile, void *clut) { - ASSERT(tile); - ASSERT(clut); - -// sceGuTexMode(GU_PSM_T4, 0, 0, getSwizzle()); -// sceGuClutLoad(1, clut); -// sceGuTexImage(0, width, height, width, tile); + void bindTileIndices(Tile8 *tile) { + curTile = (Tile8*)tile; } void unbind(int sampler) {} @@ -124,7 +141,7 @@ namespace GAPI { if (indices) { memcpy(iBuffer, indices, iCount * sizeof(indices[0])); } - + if (vertices) { memcpy(vBuffer, vertices, vCount * sizeof(vertices[0])); } @@ -142,76 +159,81 @@ namespace GAPI { ColorSW *swColor; DepthSW *swDepth; + short4 swClipRect; - mat4 swMatrix; - vec4 swViewport; + mat4 swMatrix; + vec2 swScale; struct VertexSW { - float w; - short2 coord; - ubyte4 color; - short2 uv; - DepthSW z; + int32 x, y, z, w; + int32 u, v, l; + + inline VertexSW operator + (const VertexSW &p) const { + VertexSW ret; + ret.x = x + p.x; + ret.y = y; + ret.z = z + p.z; + ret.w = w + p.w; + ret.u = u + p.u; + ret.v = v + p.v; + ret.l = l + p.l; + return ret; + } + + inline VertexSW operator - (const VertexSW &p) const { + VertexSW ret; + ret.x = x - p.x; + ret.y = y; + ret.z = z - p.z; + ret.w = w - p.w; + ret.u = u - p.u; + ret.v = v - p.v; + ret.l = l - p.l; + return ret; + } + + inline VertexSW operator * (const int32 s) const { + VertexSW ret; + ret.x = x * s; + ret.y = y; + ret.z = z * s; + ret.w = w * s; + ret.u = u * s; + ret.v = v * s; + ret.l = l * s; + return ret; + } + + inline VertexSW operator / (const int32 s) const { + VertexSW ret; + ret.x = x / s; + ret.y = y; + ret.z = z / s; + ret.w = w / s; + ret.u = u / s; + ret.v = v / s; + ret.l = l / s; + return ret; + } }; - VertexSW *swVertices; - int32 swVerticesCount; - - Index *swIndices; - int32 swIndicesCount; - + Array swVertices; + Array swIndices; + Array swTriangles; + Array swQuads; void init() { LOG("Renderer : %s\n", "Software"); LOG("Version : %s\n", "0.1"); - /* - sceGuEnable(GU_TEXTURE_2D); - sceGuDepthFunc(GU_LEQUAL); - sceGuDepthRange(0x0000, 0xFFFF); - sceGuClearDepth(0xFFFF); - - sceGuShadeModel(GU_SMOOTH); - sceGuAlphaFunc(GU_GREATER, 127, 255); - - int swizzle = GU_FALSE; - #ifdef TEX_SWIZZLE - swizzle = GU_TRUE; - #endif - - sceGuClutMode(GU_PSM_5551, 0, 0xFF, 0); - sceGuTexMode(GU_PSM_T4, 0, 0, swizzle); - sceGuTexFunc(GU_TFX_MODULATE, GU_TCC_RGBA); - sceGuTexScale(1.0f, 1.0f); - sceGuTexOffset(0.0f, 0.0f); - sceGuTexFilter(GU_LINEAR, GU_LINEAR); - //sceGuTexFilter(GU_NEAREST, GU_NEAREST); - sceGuEnable(GU_CLIP_PLANES); - - const ScePspIMatrix4 dith = - { {-4, 0, -3, 1}, - { 2, -2, 3, -1}, - {-3, 1, -4, 0}, - { 3, -1, 2, -2} }; - sceGuSetDither(&dith); - sceGuEnable(GU_DITHER); - - sceGuAmbientColor(0xFFFFFFFF); - sceGuColor(0xFFFFFFFF); - sceGuClearColor(0x00000000); - sceGuColorMaterial(GU_AMBIENT | GU_DIFFUSE); - */ - swDepth = NULL; - swVertices = NULL; - swIndices = NULL; - - swVerticesCount = 0; - swIndicesCount = 0; + swDepth = NULL; } void deinit() { delete[] swDepth; - delete[] swVertices; - delete[] swIndices; + swVertices.clear(); + swIndices.clear(); + swTriangles.clear(); + swQuads.clear(); } void resize() { @@ -220,7 +242,7 @@ namespace GAPI { } inline mat4::ProjRange getProjRange() { - return mat4::PROJ_NEG_POS; + return mat4::PROJ_ZERO_POS; } mat4 ortho(float l, float r, float b, float t, float znear, float zfar) { @@ -239,20 +261,11 @@ namespace GAPI { return true; } - void endFrame() { - // - } + void endFrame() {} void resetState() {} - void bindTarget(Texture *texture, int face) { -/* - if (!target) - sceGuDrawBufferList(GU_PSM_5650, GAPI::curBackBuffer, 512); - else - sceGuDrawBufferList(GU_PSM_5650, target->offset, target->width); -*/ - } + void bindTarget(Texture *texture, int face) {} void discardTarget(bool color, bool depth) {} @@ -260,13 +273,11 @@ namespace GAPI { void setVSync(bool enable) {} - void waitVBlank() { - //sceDisplayWaitVblankStart(); - } + void waitVBlank() {} void clear(bool color, bool depth) { if (color) { - memset(swColor, 0, Core::width * Core::height * sizeof(ColorSW)); + // memset(swColor, 0x00, Core::width * Core::height * sizeof(ColorSW)); } if (depth) { @@ -274,270 +285,387 @@ namespace GAPI { } } - void setClearColor(const vec4 &color) { - // - } + void setClearColor(const vec4 &color) {} void setViewport(const Viewport &vp) { - // + swClipRect.x = vp.x; + swClipRect.y = vp.y; + swClipRect.z = vp.x + vp.width; + swClipRect.w = vp.y + vp.height; } - void setDepthTest(bool enable) { - // - } + void setDepthTest(bool enable) {} - void setDepthWrite(bool enable) { - // - } + void setDepthWrite(bool enable) {} - void setColorWrite(bool r, bool g, bool b, bool a) { - // - } + void setColorWrite(bool r, bool g, bool b, bool a) {} - void setAlphaTest(bool enable) { - // - } + void setAlphaTest(bool enable) {} - void setCullMode(int rsMask) { - cullMode = rsMask; - //switch (rsMask) { - // case RS_CULL_BACK : sceGuFrontFace(GU_CCW); break; - // case RS_CULL_FRONT : sceGuFrontFace(GU_CW); break; - // default : sceGuDisable(GU_CULL_FACE); return; - //} - //sceGuEnable(GU_CULL_FACE); - } + void setCullMode(int rsMask) {} - void setBlendMode(int rsMask) { - blendMode = rsMask; - //switch (rsMask) { - // case RS_BLEND_ALPHA : sceGuBlendFunc(GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0); break; - // case RS_BLEND_ADD : sceGuBlendFunc(GU_ADD, GU_FIX, GU_FIX, 0xffffffff, 0xffffffff); break; - // case RS_BLEND_MULT : sceGuBlendFunc(GU_ADD, GU_DST_COLOR, GU_FIX, 0, 0); break; - // case RS_BLEND_PREMULT : sceGuBlendFunc(GU_ADD, GU_FIX, GU_ONE_MINUS_SRC_ALPHA, 0xffffffff, 0); break; - // default : sceGuDisable(GU_BLEND); return; - //} - //sceGuEnable(GU_BLEND); - } + void setBlendMode(int rsMask) {} - void setViewProj(const mat4 &mView, const mat4 &mProj) { - // - } + void setViewProj(const mat4 &mView, const mat4 &mProj) {} void updateLights(vec4 *lightPos, vec4 *lightColor, int count) { int lightsCount = 0; - ubyte4 amb; - amb.x = amb.y = amb.z = clamp(int(active.material.y * 255), 0, 255); - amb.w = 255; - /* - sceGuAmbient(*(uint32*)&amb); + ambient = clamp(int32(active.material.y * 255), 0, 255); for (int i = 0; i < MAX_LIGHTS; i++) { - if (lightColor[i].w != 1.0f) { - sceGuEnable(GU_LIGHT0 + i); - lightsCount++; - } else { - sceGuDisable(GU_LIGHT0 + i); - continue; - } - - ScePspFVector3 pos; - pos.x = lightPos[i].x; - pos.y = lightPos[i].y; - pos.z = lightPos[i].z; - - sceGuLight(i, GU_POINTLIGHT, GU_DIFFUSE, &pos); - - ubyte4 color; - color.x = clamp(int(lightColor[i].x * 255), 0, 255); - color.y = clamp(int(lightColor[i].y * 255), 0, 255); - color.z = clamp(int(lightColor[i].z * 255), 0, 255); - color.w = 255; - - sceGuLightColor(i, GU_DIFFUSE, *(uint32*)&color); - sceGuLightAtt(i, 1.0f, 0.0f, lightColor[i].w * lightColor[i].w); + // TODO } - - if (lightsCount) { - sceGuEnable(GU_LIGHTING); - } else { - sceGuDisable(GU_LIGHTING); - } - */ - } - - struct Edge { - float A, B, C; - - Edge(const vec3 &a, const vec3 &b) { - A = a.y - b.y; - B = b.x - a.x; - C = -(A * (a.x + b.x) + B * (a.y + b.y)) * 0.5f; - } - - float evaluate(float x, float y) const { - return A*x + B*y + C; - } - }; - - #define VERTEX_CACHE_MAX 4 - - Index vertexCache[2][VERTEX_CACHE_MAX]; - - void vcacheClear() { - memset(vertexCache, 0xFF, sizeof(vertexCache)); } - void vcacheSet(int in, int out) { - int i = in % VERTEX_CACHE_MAX; - vertexCache[0][i] = in; - vertexCache[1][i] = out; + bool checkBackface(const VertexSW *a, const VertexSW *b, const VertexSW *c) { + return ((b->x - a->x) >> 16) * (c->y - a->y) - + ((c->x - a->x) >> 16) * (b->y - a->y) <= 0; } - Index vcacheGet(int in) { - int i = in % VERTEX_CACHE_MAX; - if (vertexCache[0][i] == in) { - return vertexCache[1][i]; + inline void sortVertices(VertexSW *&t, VertexSW *&m, VertexSW *&b) { + if (t->y > m->y) swap(t, m); + if (t->y > b->y) swap(t, b); + if (m->y > b->y) swap(m, b); + } + + inline void sortVertices(VertexSW *&t, VertexSW *&m, VertexSW *&b, VertexSW *&o) { + if (t->y > m->y) swap(t, m); + if (o->y > b->y) swap(o, b); + if (t->y > o->y) swap(t, o); + if (m->y > b->y) swap(m, b); + if (m->y > o->y) swap(m, o); + } + + inline void step(VertexSW &v, const VertexSW &d) { + //v.w += d.w; + v.u += d.u; + v.v += d.v; + v.l += d.l; + } + + inline void step(VertexSW &v, const VertexSW &d, int32 count) { + //v.w += d.w * count; + v.u += d.u * count; + v.v += d.v * count; + v.l += d.l * count; + } + + void drawLine(const VertexSW &L, const VertexSW &R, int32 y) { + int32 x1 = L.x >> 16; + int32 x2 = R.x >> 16; + + int32 f = x2 - x1; + if (f == 0) return; + + VertexSW dS = (R - L) / f; + VertexSW S = L; + + if (x1 < swClipRect.x) { + x1 = swClipRect.x - x1; + S.z += dS.z * x1; + step(S, dS, x1); + x1 = Core::viewport.x; } - return 0xFFFF; - } - - void DrawLine(int x1, int x2, int y, DepthSW z, ColorSW color) { - if (x2 - x1 == 0) return; - - if (x1 < 0) x1 = 0; - if (x2 > Core::width - 1) x2 = Core::width - 1; - if (x2 < x1) return; + if (x2 > swClipRect.z) x2 = swClipRect.z; int32 i = y * Core::width; for (int x = i + x1; x < i + x2; x++) { + S.z += dS.z; + + DepthSW z = DepthSW(uint32(S.z) >> 16); + if (swDepth[x] >= z) { - swDepth[x] = z; - swColor[x] = color; + uint32 u = uint32(S.u) >> 16; + uint32 v = uint32(S.v) >> 16; + + uint8 index = curTile->index[(v << 8) + u]; + + if (index != 0) { + index = swLightmap[((S.l >> (16 + 3)) << 8) + index]; + + swColor[x] = swPalette[index]; + swDepth[x] = z; + } } + + step(S, dS); } } - void DrawTriangle(Index *indices) { - VertexSW a = swVertices[indices[0]]; - VertexSW b = swVertices[indices[1]]; - VertexSW c = swVertices[indices[2]]; + void drawPart(const VertexSW &a, const VertexSW &b, const VertexSW &c, const VertexSW &d) { + VertexSW L, R, dL, dR; + int32 minY, maxY; - if (a.w < 0.0f || b.w < 0.0f || c.w < 0.0f) return; + int32 f = c.y - a.y; + dL = (c - a) / f; + dR = (d - b) / f; - short2 &ia = a.coord; - short2 &ib = b.coord; - short2 &ic = c.coord; + L = a; + R = b; - if ((ib.x - ia.x) * (ic.y - ia.y) - - (ib.y - ia.y) * (ic.x - ia.x) <= 0) return; + minY = a.y; + maxY = c.y; - DepthSW z = DepthSW((uint32(a.z) + uint32(b.z) + uint32(c.z)) / 3.0f); // 16-bit depth range + if (maxY < swClipRect.y || minY >= swClipRect.w) return; - if (a.coord.y > b.coord.y) swap(a, b); - if (a.coord.y > c.coord.y) swap(a, c); - if (b.coord.y > c.coord.y) swap(b, c); + if (minY < swClipRect.y) { + minY = swClipRect.y - minY; + L.x += dL.x * minY; + L.z += dL.z * minY; + R.x += dR.x * minY; + R.z += dR.z * minY; + step(L, dL, minY); + step(R, dR, minY); + minY = swClipRect.y; + } - ColorSW color = a.color.value; + if (maxY > swClipRect.w) maxY = swClipRect.w; - int16 minY = ia.y; - int16 maxY = ic.y; - if (minY < 0) minY = 0; - if (maxY > Core::height - 1) maxY = Core::height - 1; - if (minY > maxY) return; + for (int y = minY; y < maxY; y++) { + drawLine(L, R, y); + L.x += dL.x; + L.z += dL.z; + R.x += dR.x; + R.z += dR.z; + step(L, dL); + step(R, dR); + } + } - int16 midY = clamp(ib.y, minY, maxY); + void drawTriangle(Index *indices) { + /* + t + /\ <----- top triangle + m /__\/ n + \ /\ + \ \ <-- bottom triangle + \ \ + \\ + \ + b + */ + VertexSW _n; + VertexSW *t = swVertices + indices[0]; + VertexSW *m = swVertices + indices[1]; + VertexSW *b = swVertices + indices[2]; + VertexSW *n = &_n; - int32 f = ((ic.x - ia.x) << 16) / (ic.y - ia.y); + if (t->w <= 0 || m->w <= 0 || b->w <= 0) + return; - if (ia.y != ib.y) { - int32 f1 = f; - int32 f2 = ((ib.x - ia.x) << 16) / (ib.y - ia.y); - int32 x1 = (ia.x << 16) + (minY - ia.y) * f1; - int32 x2 = (ia.x << 16) + (minY - ia.y) * f2; + if (checkBackface(t, m, b)) + return; - if (f1 > f2) { - swap(x1, x2); - swap(f1, f2); + int32 cx1 = swClipRect.x << 16; + int32 cx2 = swClipRect.z << 16; + + if (t->x < cx1 && m->x < cx1 && b->x < cx1) + return; + + if (t->x > cx2 && m->x > cx2 && b->x > cx2) + return; + + sortVertices(t, m, b); + + if (b->y < swClipRect.y || t->y > swClipRect.w) + return; + + *n = ((*b - *t) / (b->y - t->y) * (m->y - t->y)) + *t; + n->y = m->y; + + if (m->x > n->x) { + swap(m, n); + } + + if (m->y != t->y) drawPart(*t, *t, *m, *n); + if (m->y != b->y) drawPart(*m, *n, *b, *b); + } + + void drawQuad(Index *indices) { + /* + t + /\ <----- top triangle + m /__\/ n + \ /\ + \ \ <-- quad + p \/__\ o + /\ / + \/ <-- bottom triangle + b + */ + VertexSW _n; + VertexSW _p; + VertexSW *t = swVertices + indices[0]; + VertexSW *m = swVertices + indices[1]; + VertexSW *b = swVertices + indices[2]; + VertexSW *o = swVertices + indices[3]; + VertexSW *n = &_n; + VertexSW *p = &_p; + + if (t->w <= 0 || m->w <= 0 || o->w <= 0 || b->w <= 0) + return; + + if (checkBackface(t, m, b)) + return; + + int32 cx1 = swClipRect.x << 16; + int32 cx2 = swClipRect.z << 16; + + if (t->x < cx1 && m->x < cx1 && o->x < cx1 && b->x < cx1) + return; + + if (t->x > cx2 && m->x > cx2 && o->x > cx2 && b->x > cx2) + return; + + sortVertices(t, m, b, o); + + if (b->y < swClipRect.y || t->y > swClipRect.w) + return; + + if (checkBackface(t, b, m) == checkBackface(t, b, o)) { + + VertexSW d = (*b - *t) / (b->y - t->y); + + *n = *t + d * (m->y - t->y); + *p = *t + d * (o->y - t->y); + + n->y = m->y; + p->y = o->y; + + } else { + + if (o->y != t->y) { + *n = *t + ((*o - *t) / (o->y - t->y) * (m->y - t->y)); + n->y = m->y; } - for (int16 y = minY; y < midY; y++) { - DrawLine(x1 >> 16, x2 >> 16, y, z, color); - x1 += f1; - x2 += f2; + if (m->y != b->y) { + *p = *b + ((*m - *b) / (m->y - b->y) * (o->y - b->y)); + p->y = o->y; + } + + } + + if (o->y != t->y && m->x > n->x) swap(m, n); + if (m->y != b->y && p->x > o->x) swap(p, o); + + if (t->y != m->y) drawPart(*t, *t, *m, *n); + if (m->y != o->y) drawPart(*m, *n, *p, *o); + if (o->y != b->y) drawPart(*p, *o, *b, *b); + } + + bool transform(const Index *indices, const Vertex *vertices, int iStart, int iCount, int vStart) { + swVertices.reset(); + swIndices.reset(); + swTriangles.reset(); + swQuads.reset(); + + int vIndex = 0; + bool isTriangle = false; + bool colored = false; + + for (int i = 0; i < iCount; i++) { + const Index index = indices[iStart + i]; + const Vertex &vertex = vertices[vStart + index]; + + vIndex++; + + if (vIndex == 1) { + isTriangle = vertex.normal.w == 1; + } + + if (vertex.color.w == 142) { + colored = true; + } + + if (!isTriangle && (vIndex == 4 || vIndex == 5)) { // loader splits quads to two triangles with indices 012[02]3, we ignore [02] to make it quad again! + continue; + } + + vec4 c; + c = swMatrix * vec4(vertex.coord.x, vertex.coord.y, vertex.coord.z, 1.0f); + + c.x /= c.w; + c.y /= c.w; + c.z /= c.w; + c.x = clamp(c.x, -16384.0f, 16384.0f); + c.y = clamp(c.y, -16384.0f, 16384.0f); + + VertexSW result; + result.x = int32(c.x) << 16; + result.y = int32(c.y); + result.z = uint32(clamp(c.z, 0.0f, 1.0f) * 65535.0f) << 16; + result.w = int32(c.w); + + if (colored) { + result.u = vertex.color.x << 16; + result.v = 0; + } else { + result.u = (vertex.texCoord.x << 16);// / result.w; + result.v = (vertex.texCoord.y << 16);// / result.w; + } + result.w = result.w << 16; + result.l = (255 - ((vertex.light.x * ambient) >> 8)) << 16; + + swIndices.push(swVertices.push(result)); + + ASSERT(!(isTriangle && vIndex > 3)); + + if (isTriangle && vIndex == 3) { + swTriangles.push(swIndices.length - 3); + vIndex = 0; + } else if (vIndex == 6) { + swQuads.push(swIndices.length - 4); + vIndex = 0; } } - if (ib.y != ic.y) { - int32 f1 = f; - int32 f2 = ((ic.x - ib.x) << 16) / (ic.y - ib.y); - int32 x1 = (ia.x << 16) + (midY - ia.y) * f1; - int32 x2 = (ib.x << 16) + (midY - ib.y) * f2; - - if (x1 > x2) { - swap(x1, x2); - swap(f1, f2); - } - - for (int16 y = midY; y < maxY; y++) { - DrawLine(x1 >> 16, x2 >> 16, y, z, color); - x1 += f1; - x2 += f2; - } - } + return colored; } void DIP(Mesh *mesh, const MeshRange &range) { - swMatrix = mViewProj * mModel; - swViewport = vec4(float(Core::width / 2), float(Core::height / 2), 0, 0); - - if (swVerticesCount < mesh->vCount) { - delete[] swVertices; - swVerticesCount = mesh->vCount; - swVertices = new VertexSW[swVerticesCount]; + if (curTile == NULL) { + //uint32 *tex = (uint32*)Core::active.textures[0]->memory; // TODO + return; } - if (swIndicesCount < mesh->iCount) { - delete[] swIndices; - swIndicesCount = mesh->iCount; - swIndices = new Index[swIndicesCount]; + swMatrix.viewport(0.0f, (float)Core::height, (float)Core::width, -(float)Core::height, 0.0f, 1.0f); + swMatrix = swMatrix * mViewProj * mModel; + + bool colored = transform(mesh->iBuffer, mesh->vBuffer, range.iStart, range.iCount, range.vStart); + + Tile8 *oldTile = curTile; + + if (colored) { + curTile = (Tile8*)swGradient; } - vcacheClear(); - - uint32 vCount = 0; - - for (int i = 0; i < range.iCount; i++) { - Index in = mesh->iBuffer[range.iStart + i]; - Index out = vcacheGet(in); - - if (out == 0xFFFF) { - out = vCount++; - VertexSW &result = swVertices[out]; - Vertex &vertex = mesh->vBuffer[range.vStart + in]; - - vec4 c; - c = swMatrix * vec4(vertex.coord.x, vertex.coord.y, vertex.coord.z, 1.0f); \ - c.x = clamp( swViewport.x * ( c.x / c.w + 1.0f), -16384.0f, 16384.0f); \ - c.y = clamp( swViewport.y * (-c.y / c.w + 1.0f), -16384.0f, 16384.0f); \ - c.z /= c.w; - - result.w = c.w; - result.coord = short2( int16(c.x), int16(c.y) ); - result.z = DepthSW(clamp(c.z, 0.0f, 1.0f) * 0xFFFF); - result.color = vertex.light; - - vcacheSet(in, out); - } - - swIndices[i] = out; + for (int i = 0; i < swQuads.length; i++) { + drawQuad(&swIndices[swQuads[i]]); } - for (int i = 0; i < range.iCount; i += 3) { - DrawTriangle(swIndices + i); + for (int i = 0; i < swTriangles.length; i++) { + drawTriangle(&swIndices[swTriangles[i]]); } + + curTile = oldTile; + } + + void initPalette(Color24 *palette, uint8 *lightmap) { + swLightmap = lightmap; + for (uint32 i = 0; i < 256; i++) { + const Color24 &p = palette[i]; + swPaletteColor[i] = CONV_COLOR(p.r, p.g, p.b); + swPaletteWater[i] = CONV_COLOR((uint32(p.r) * 150) >> 8, (uint32(p.g) * 230) >> 8, (uint32(p.b) * 230) >> 8); + swPaletteGray[i] = CONV_COLOR((i * 57) >> 8, (i * 29) >> 8, (i * 112) >> 8); + swGradient[i] = i; + } + } + + void setPalette(ColorSW *palette) { + swPalette = palette; } vec4 copyPixel(int x, int y) { diff --git a/src/inventory.h b/src/inventory.h index e178e39..0a0df6e 100644 --- a/src/inventory.h +++ b/src/inventory.h @@ -157,7 +157,9 @@ static const OptionItem optSound[] = { OptionItem( OptionItem::TYPE_PARAM, STR_EMPTY, SETTINGS( audio.sound ), 0xFFFF8000, 102, SND_MAX_VOLUME, true ), OptionItem( OptionItem::TYPE_PARAM, STR_REVERBERATION, SETTINGS( audio.reverb ), STR_OFF, 0, 1 ), OptionItem( OptionItem::TYPE_PARAM, STR_OPT_SUBTITLES, SETTINGS( audio.subtitles ), STR_OFF, 0, 1 ), +#ifndef FFP OptionItem( OptionItem::TYPE_PARAM, STR_OPT_LANGUAGE, SETTINGS( audio.language ), STR_LANG_EN, 0, 10 ), +#endif }; #if defined(_OS_CLOVER) || defined(_OS_PSC) @@ -1836,7 +1838,7 @@ struct Inventory { m.identity(); Core::setViewProj(m, m); Core::mModel.identity(); - Core::mModel.scale(vec3(1.0f / 32767.0f)); + #else if (Core::settings.detail.stereo == Core::Settings::STEREO_VR || !background[0]) { backTex = Core::blackTex; // black background diff --git a/src/level.h b/src/level.h index eb9a563..3739511 100644 --- a/src/level.h +++ b/src/level.h @@ -565,6 +565,10 @@ struct Level : IGame { setShader(Core::pass, type, (Core::pass == Core::passAmbient) ? false : room.flags.water, alphaTest); + #ifdef _GAPI_SW + GAPI::setPalette(room.flags.water ? GAPI::swPaletteWater : GAPI::swPaletteColor); + #endif + Core::setMaterial(material.x, material.y, material.z, material.w); if (room.flags.water) { @@ -598,6 +602,9 @@ struct Level : IGame { } virtual void renderEnvironment(int roomIndex, const vec3 &pos, Texture **targets, int stride = 0, Core::Pass pass = Core::passAmbient) { + #ifdef _GAPI_SW + return; + #endif PROFILE_MARKER("ENVIRONMENT"); setupBinding(); float tmpEye = Core::eye; @@ -1240,7 +1247,7 @@ struct Level : IGame { #define ATLAS_PAGE_BARS 4096 #define ATLAS_PAGE_GLYPHS 8192 - TR::Tile32 *tileData; + Tile32 *tileData; uint8 *glyphsRU; uint8 *glyphsJA; uint8 *glyphsGR; @@ -1451,7 +1458,7 @@ struct Level : IGame { for (int y = 0; y < h; y++) for (int x = 0; x < w; x++) { - TR::Tile8 &tile = level.tiles8[sprite.tile]; + Tile8 &tile = level.tiles8[sprite.tile]; data[pos.x + x + (pos.y + y) * size.x] = level.getColor(tile.index[sprite.texCoord[0].x + x + (sprite.texCoord[0].y + y) * 256]); } @@ -1465,17 +1472,17 @@ struct Level : IGame { void dumpKanji() { Stream stream("DATA/KANJI.PSX"); int size = stream.readLE32() / 2; - TR::ColorIndex4 *buffer = new TR::ColorIndex4[size]; + ColorIndex4 *buffer = new ColorIndex4[size]; stream.raw(buffer, size); int width = 256; int height = size / width * 2; Color32 *image = new Color32[width * height]; - TR::Tile4 *tile = (TR::Tile4*)buffer; - TR::CLUT &clut = level.cluts[level.spriteTextures[level.kanjiSprite].clut]; + Tile4 *tile = (Tile4*)buffer; + CLUT &clut = level.cluts[level.spriteTextures[level.kanjiSprite].clut]; - TR::ColorIndex4 *idx = buffer; + ColorIndex4 *idx = buffer; Color32 *ptr = image; for (int y = 0; y < height; y++) { @@ -1585,7 +1592,7 @@ struct Level : IGame { } // get result texture - tileData = new TR::Tile32(); + tileData = new Tile32(); atlasRooms = rAtlas->pack(true); atlasObjects = oAtlas->pack(true); @@ -1630,7 +1637,14 @@ struct Level : IGame { #else ASSERT(level.tilesCount); - #if defined(_GAPI_SW) || defined(_GAPI_GU) + #if defined(_GAPI_SW) + atlasRooms = + atlasObjects = + atlasSprites = + atlasGlyphs = new Texture(level.tiles8, level.tilesCount); + GAPI::initPalette(level.palette, level.lightmap); + GAPI::setPalette(GAPI::swPaletteColor); + #elif defined(_GAPI_GU) atlasRooms = atlasObjects = atlasSprites = @@ -1647,7 +1661,7 @@ struct Level : IGame { short4 uv = t.getMinMax(); uv.z++; uv.w++; - level.fillObjectTexture((TR::Tile32*)tiles[t.tile].data, uv, &t); + level.fillObjectTexture((Tile32*)tiles[t.tile].data, uv, &t); } for (int i = 0; i < level.spriteTexturesCount; i++) { @@ -1655,7 +1669,7 @@ struct Level : IGame { short4 uv = t.getMinMax(); uv.z++; uv.w++; - level.fillObjectTexture((TR::Tile32*)tiles[t.tile].data, uv, &t); + level.fillObjectTexture((Tile32*)tiles[t.tile].data, uv, &t); } for (int i = 0; i < level.tilesCount; i++) { @@ -1667,7 +1681,10 @@ struct Level : IGame { } } - atlas = new Texture(tiles, level.tilesCount); + atlasRooms = + atlasObjects = + atlasSprites = + atlasGlyphs = new Texture(tiles, level.tilesCount); for (int i = 0; i < level.tilesCount; i++) delete[] tiles[i].data; @@ -1800,14 +1817,14 @@ struct Level : IGame { Core::pass = pass; } - void prepareRooms(int *roomsList, int roomsCount) { + void prepareRooms(RoomDesc *roomsList, int roomsCount) { skyIsVisible = (level.version & TR::VER_TR1); for (int i = 0; i < level.roomsCount; i++) level.rooms[i].flags.visible = false; for (int i = 0; i < roomsCount; i++) { - TR::Room &r = level.rooms[roomsList[i]]; + TR::Room &r = level.rooms[roomsList[i].index]; skyIsVisible |= r.flags.sky; r.flags.visible = true; } @@ -1829,7 +1846,7 @@ struct Level : IGame { setMainLight(player); } - void renderRooms(int *roomsList, int roomsCount, int transp) { + void renderRooms(RoomDesc *roomsList, int roomsCount, int transp) { PROFILE_MARKER("ROOMS"); if (Core::pass == Core::passShadow) @@ -1858,8 +1875,10 @@ struct Level : IGame { atlasRooms->bind(sDiffuse); + Viewport vp = Core::viewport; + while (i != end) { - int roomIndex = roomsList[i]; + int roomIndex = roomsList[i].index; MeshBuilder::RoomRange &range = mesh->rooms[roomIndex]; if (!range.geometry[transp].count && !range.dynamic[transp].count) { @@ -1867,6 +1886,10 @@ struct Level : IGame { continue; } + #ifdef _GAPI_SW + Core::setViewport(roomsList[i].portal, vp.width, vp.height); + #endif + const TR::Room &room = level.rooms[roomIndex]; vec3 center = room.getCenter(); @@ -1899,14 +1922,18 @@ struct Level : IGame { #endif for (int i = 0; i < roomsCount; i++) { - level.rooms[roomsList[i]].flags.visible = true; + int roomIndex = roomsList[i].index; + level.rooms[roomIndex].flags.visible = true; - int roomIndex = roomsList[i]; MeshBuilder::RoomRange &range = mesh->rooms[roomIndex]; if (!range.sprites.iCount) continue; + #ifdef _GAPI_SW + Core::setViewport(roomsList[i].portal, vp.width, vp.height); + #endif + setRoomParams(roomIndex, Shader::SPRITE, 1.0f, 1.0f, 0.0f, 1.0f, true); basis.pos = level.rooms[roomIndex].getOffset(); @@ -1916,6 +1943,7 @@ struct Level : IGame { } } + Core::setViewport(vp); Core::setBlendMode(bmNone); } @@ -2259,10 +2287,7 @@ struct Level : IGame { Core::setBlendMode(bmPremult); renderEntitiesTransp(transp); - #ifdef FFP - Core::whiteTex->bind(0); - #endif - + #ifndef FFP Core::whiteTex->bind(sDiffuse); Core::setBlendMode(bmMult); for (int i = 0; i < level.entitiesCount; i++) { @@ -2272,10 +2297,7 @@ struct Level : IGame { controller->renderShadow(mesh); } Core::setBlendMode(bmNone); - - #ifdef FFP - atlasRooms->bind(0); - #endif + #endif } if (transp == 2) { @@ -2357,7 +2379,7 @@ struct Level : IGame { return true; } - virtual void getVisibleRooms(int *roomsList, int &roomsCount, int from, int to, const vec4 &viewPort, bool water, int count = 0) { + virtual void getVisibleRooms(RoomDesc *roomsList, int &roomsCount, int from, int to, const vec4 &viewPort, bool water, int count = 0) { if (count > 16) { //ASSERT(false); return; @@ -2370,7 +2392,7 @@ struct Level : IGame { waterCache->setVisible(from, to); room.flags.visible = true; - roomsList[roomsCount++] = to; + roomsList[roomsCount++] = RoomDesc(to, viewPort); } vec4 clipPort; @@ -2385,7 +2407,7 @@ struct Level : IGame { } } - void renderOpaque(int *roomsList, int roomsCount) { + void renderOpaque(RoomDesc *roomsList, int roomsCount) { renderRooms(roomsList, roomsCount, 0); renderEntities(0); if (Core::pass != Core::passShadow && skyIsVisible) { @@ -2393,12 +2415,12 @@ struct Level : IGame { } } - void renderTransparent(int *roomsList, int roomsCount) { + void renderTransparent(RoomDesc *roomsList, int roomsCount) { renderRooms(roomsList, roomsCount, 1); renderEntities(1); } - void renderAdditive(int *roomsList, int roomsCount) { + void renderAdditive(RoomDesc *roomsList, int roomsCount) { vec4 oldFog = Core::fogParams; Core::fogParams = FOG_BLACK; // don't apply fog for additive renderRooms(roomsList, roomsCount, 2); @@ -2406,13 +2428,13 @@ struct Level : IGame { Core::fogParams = oldFog; } - virtual void renderView(int roomIndex, bool water, bool showUI, int roomsCount = 0, int *roomsList = NULL) { + virtual void renderView(int roomIndex, bool water, bool showUI, int roomsCount = 0, RoomDesc *roomsList = NULL) { PROFILE_MARKER("VIEW"); if (water && waterCache) waterCache->reset(); - int rList[256]; + RoomDesc rList[256]; if (!roomsList) { roomsList = rList; @@ -2435,21 +2457,21 @@ struct Level : IGame { // add other non-alternative rooms for (int i = 0; i < level.roomsCount; i++) if (!level.rooms[i].flags.visible) - roomsList[roomsCount++] = i; + roomsList[roomsCount++] = RoomDesc(i, vec4(-1.0f, -1.0f, 1.0f, 1.0f)); // refresh visible flag for (int i = 0; i < level.roomsCount; i++) level.rooms[i].flags.visible = false; for (int i = 0; i < roomsCount; i++) - level.rooms[roomsList[i]].flags.visible = true; + level.rooms[roomsList[i].index].flags.visible = true; } else getVisibleRooms(roomsList, roomsCount, TR::NO_ROOM, roomIndex, vec4(-1.0f, -1.0f, 1.0f, 1.0f), water); } if (water && waterCache) { for (int i = 0; i < roomsCount; i++) - waterCache->setVisible(roomsList[i]); + waterCache->setVisible(roomsList[i].index); waterCache->renderReflection(); @@ -3153,6 +3175,10 @@ struct Level : IGame { void renderUI() { if (inventory->titleTimer > 1.0f || level.isTitle()) return; + #ifdef _GAPI_SW + GAPI::setPalette(GAPI::swPaletteColor); + #endif + Core::pushLights(); UI::begin(camera->aspect); diff --git a/src/mesh.h b/src/mesh.h index 23224a0..039224b 100644 --- a/src/mesh.h +++ b/src/mesh.h @@ -70,7 +70,7 @@ struct Mesh : GAPI::Mesh { TR::Room::Data::Vertex &v = d.vertices[f.vertices[k]];\ Vertex &rv = _vertices[vCount++];\ rv.coord = short4( v.pos.x, v.pos.y, v.pos.z, 0 );\ - rv.normal = short4( f.normal.x, f.normal.y, f.normal.z, 0 );\ + rv.normal = short4( f.normal.x, f.normal.y, f.normal.z, f.triangle ? 1 : 0 );\ rv.color = ubyte4( 255, 255, 255, 255 );\ rv.light = ubyte4( v.color.r, v.color.g, v.color.b, 255 );\ } @@ -462,7 +462,7 @@ struct MeshBuilder { shadowBlob.iCount = 8 * 3 * 3; for (int i = 0; i < 9; i++) { Vertex &v0 = vertices[vCount + i * 2 + 0]; - v0.normal = short4( 0, -1, 0, 32767 ); + v0.normal = short4( 0, -1, 0, 1 ); v0.texCoord = short4( whiteObject.texCoordAtlas[0].x, whiteObject.texCoordAtlas[0].y, 32767, 32767 ); v0.color = v0.light = ubyte4( 0, 0, 0, 0 ); @@ -538,7 +538,7 @@ struct MeshBuilder { Vertex &v = vertices[vCount + i]; pos.rotate(cs); v.coord = short4( short(pos.x), short(pos.y), 0, 1 ); - v.normal = short4( 0, 0, 0, 32767 ); + v.normal = short4( 0, 0, 0, 1 ); v.texCoord = short4( whiteSprite.texCoordAtlas[0].x, whiteSprite.texCoordAtlas[0].y, 32767, 32767 ); v.color = ubyte4( 255, 255, 255, 255 ); v.light = ubyte4( 255, 255, 255, 255 ); @@ -564,7 +564,7 @@ struct MeshBuilder { for (int i = 0; i < COUNT(boxCoords); i++) { Vertex &v = vertices[vCount++]; v.coord = boxCoords[i]; - v.normal = short4(0, 0, 0, 32767); + v.normal = short4(0, 0, 0, 0); v.texCoord = short4(0, 0, 0, 0); v.color = ubyte4(255, 255, 255, 255); v.light = ubyte4(255, 255, 255, 255); @@ -1092,9 +1092,9 @@ struct MeshBuilder { vertices[vCount].coord = transform(v.coord, joint, x, y, z, dir); vec3 n = vec3(v.normal.x, v.normal.y, v.normal.z).normal() * 32767.0f; - v.normal = short4(short(n.x), short(n.y), short(n.z), 0); + v.normal = short4(short(n.x), short(n.y), short(n.z), f.triangle ? 1 : 0); vertices[vCount].normal = rotate(v.normal, dir); - vertices[vCount].color = ubyte4( c.r, c.g, c.b, 255 ); + vertices[vCount].color = ubyte4( c.r, c.g, c.b, c.a ); vertices[vCount].light = ubyte4( light.r, light.g, light.b, 255 ); vCount++; @@ -1525,7 +1525,8 @@ struct MeshBuilder { TR::Room::Data &d = level->rooms[roomIndex].data; for (int j = 0; j < d.sCount; j++) { TR::Room::Data::Sprite &f = d.sprites[j]; - addDynSprite(f.texture, d.vertices[f.vertexIndex].pos, false, false, COLOR_WHITE, COLOR_WHITE); + TR::Room::Data::Vertex &v = d.vertices[f.vertexIndex]; + addDynSprite(f.texture, d.vertices[f.vertexIndex].pos, false, false, v.color, v.color); } dynEnd(); diff --git a/src/platform/win/OpenLara.vcxproj b/src/platform/win/OpenLara.vcxproj index 3961acf..8954a79 100644 --- a/src/platform/win/OpenLara.vcxproj +++ b/src/platform/win/OpenLara.vcxproj @@ -135,13 +135,13 @@ MultiThreaded Strict false - Size + Speed /d2noftol3 %(AdditionalOptions) true Console - false + true true true wcrt.lib;wsock32.lib;opengl32.lib;d3d11.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) diff --git a/src/platform/win/main.cpp b/src/platform/win/main.cpp index 047318b..c5e609b 100644 --- a/src/platform/win/main.cpp +++ b/src/platform/win/main.cpp @@ -923,7 +923,7 @@ int main(int argc, char** argv) { #else int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { int argc = (lpCmdLine && strlen(lpCmdLine)) ? 2 : 1; - char *argv[] = { "", lpCmdLine }; + const char *argv[] = { "", lpCmdLine }; #endif cacheDir[0] = saveDir[0] = contentDir[0] = 0; diff --git a/src/texture.h b/src/texture.h index 42934ac..6741a8f 100644 --- a/src/texture.h +++ b/src/texture.h @@ -8,11 +8,17 @@ struct Texture : GAPI::Texture { #ifdef SPLIT_BY_TILE - #if defined(_GAPI_SW) || defined(_GAPI_GU) - TR::Tile4 *tiles; - TR::CLUT *cluts; + #if defined(_GAPI_SW) + Tile8 *tiles; - Texture(TR::Tile4 *tiles, int tilesCount, TR::CLUT *cluts, int clutsCount) : GAPI::Texture(256, 256, 1, OPT_PROXY) { + Texture(Tile8 *tiles, int tilesCount) : GAPI::Texture(256, 256, 1, OPT_PROXY) { + this->tiles = tiles; + } + #elif defined(_GAPI_GU) + Tile4 *tiles; + CLUT *cluts; + + Texture(Tile4 *tiles, int tilesCount, CLUT *cluts, int clutsCount) : GAPI::Texture(256, 256, 1, OPT_PROXY) { #ifdef EDRAM_TEX this->tiles = (TR::Tile4*)GAPI::allocEDRAM(tilesCount * sizeof(tiles[0])); this->cluts = (TR::CLUT*)GAPI::allocEDRAM(clutsCount * sizeof(cluts[0])); @@ -47,7 +53,9 @@ struct Texture : GAPI::Texture { #endif void bindTile(uint16 tile, uint16 clut) { - #if defined(_GAPI_SW) || defined(_GAPI_GU) + #if defined(_GAPI_SW) + bindTileIndices(tiles + tile); + #elif defined(_GAPI_GU) bindTileCLUT(tiles + tile, cluts + clut); #else tiles[tile]->bind(0); diff --git a/src/utils.h b/src/utils.h index 2533729..d168537 100644 --- a/src/utils.h +++ b/src/utils.h @@ -737,6 +737,16 @@ struct mat4 { frustum(range, -x - eyeX, x - eyeX, -y - eyeY, y - eyeY, znear, zfar, rotate90); } + void viewport(float x, float y, float width, float height, float n, float f) { + identity(); + e00 = width * 0.5f; + e11 = height * 0.5f; + e22 = (f - n) * 0.5f; + e23 = (f + n) * 0.5f; + e03 = x + e00; + e13 = y + e11; + } + mat4(const vec3 &from, const vec3 &at, const vec3 &up) { vec3 r, u, d; d = (from - at).normal(); @@ -1444,6 +1454,29 @@ union Color16 { // RGBA5551 operator Color32() const { return Color32((r << 3) | (r >> 2), (g << 3) | (g >> 2), (b << 3) | (b >> 2), -a); } }; +struct ColorIndex4 { + uint8 a:4, b:4; +}; + +struct Tile4 { + ColorIndex4 index[256 * 256 / 2]; +}; + +struct Tile8 { + uint8 index[256 * 256]; +}; + +struct Tile16 { + Color16 color[256 * 256]; +}; + +struct Tile32 { + Color32 color[256 * 256]; // + 128 for mips data +}; + +struct CLUT { + Color16 color[16]; +}; namespace String { @@ -2053,8 +2086,12 @@ struct Array { this->length = length; } - void clear() { + void reset() { length = 0; + } + + void clear() { + reset(); free(items); items = NULL; } @@ -2068,7 +2105,7 @@ struct Array { return items[index]; }; - operator T*() const { return items; }; + inline operator T*() const { return items; }; };