diff --git a/src/cache.h b/src/cache.h index 63071d4..2f544e5 100644 --- a/src/cache.h +++ b/src/cache.h @@ -773,11 +773,6 @@ struct WaterCache { item.init(game); } - if (!count) { - visible = false; - return; - } - // render mirror reflection Core::setTarget(reflect, CLEAR_ALL); Camera *camera = (Camera*)game->getCamera(); @@ -787,25 +782,49 @@ struct WaterCache { mat4 mView = Core::mView; mat4 mViewInv = Core::mViewInv; + // merge visible rooms for all items + int roomsList[256]; + int roomsCount = 0; + + for (int i = 0; i < level->roomsCount; i++) + level->rooms[i].flags.visible = false; + + bool underwater = level->rooms[camera->getRoomIndex()].flags.water; + vec4 reflectPlane; + for (int i = 0; i < count; i++) { Item &item = items[i]; if (!item.visible) continue; - vec3 p = item.pos; - vec3 n = vec3(0, 1, 0); - - vec4 reflectPlane = vec4(n.x, n.y, n.z, -n.dot(p)); - bool underwater = level->rooms[camera->getRoomIndex()].flags.water; - - //bool underwater = camera->eye.pos.y > item.pos.y; - + reflectPlane = vec4(0, 1, 0, -item.pos.y); camera->reflectPlane = &reflectPlane; camera->setup(true); - float sign = underwater ? -1.0f : 1.0f; - game->setClipParams(sign, item.pos.y * sign); - game->renderView(underwater ? item.from : item.to, false, false); + game->getVisibleRooms(roomsList, roomsCount, TR::NO_ROOM, underwater ? item.from : item.to, vec4(-1.0f, -1.0f, 1.0f, 1.0f), false); } + + if (roomsCount) { + // select optimal water plane + float waterLevel = -INF; + + for (int i = 0; i < count; i++) { + Item &item = items[i]; + if (!item.visible) continue; + + if (item.pos.y > waterLevel) + waterLevel = item.pos.y; + } + + reflectPlane = vec4(0, 1, 0, -waterLevel); + camera->reflectPlane = &reflectPlane; + camera->setup(true); + + // render reflections frame + float sign = underwater ? -1.0f : 1.0f; + game->setClipParams(sign, waterLevel * sign); + game->renderView(TR::NO_ROOM, false, false, roomsCount, roomsList); + } + Core::invalidateTarget(false, true); game->setClipParams(1.0f, NO_CLIP_PLANE); @@ -831,7 +850,7 @@ struct WaterCache { int w, h; getTargetSize(w, h); - Core::active.shader->setParam(uParam, vec4(float(w) / refract->width, float(h) / refract->height, 0.05f, 0.02f)); + Core::active.shader->setParam(uParam, vec4(float(w) / refract->width, float(h) / refract->height, 0.05f, 0.03f)); float sx = item.size.x * DETAIL / (item.data[0]->width / 2); float sz = item.size.z * DETAIL / (item.data[0]->height / 2); diff --git a/src/controller.h b/src/controller.h index c3312f7..1011185 100644 --- a/src/controller.h +++ b/src/controller.h @@ -71,9 +71,10 @@ 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 renderEnvironment(int roomIndex, const vec3 &pos, Texture **targets, int stride = 0, Core::Pass pass = Core::passAmbient) {} virtual void renderCompose(int roomIndex) {} - virtual void renderView(int roomIndex, bool water, bool showUI) {} + virtual void renderView(int roomIndex, bool water, bool showUI, int roomsCount = 0, int *roomsList = NULL) {} virtual void renderGame(bool showUI) {} virtual void setEffect(Controller *controller, TR::Effect::Type effect) {} diff --git a/src/level.h b/src/level.h index 45b783f..09d4b60 100644 --- a/src/level.h +++ b/src/level.h @@ -1756,7 +1756,7 @@ struct Level : IGame { return true; } - void getVisibleRooms(int *roomsList, int &roomsCount, int from, int to, const vec4 &viewPort, bool water, int count = 0) { + virtual void getVisibleRooms(int *roomsList, int &roomsCount, int from, int to, const vec4 &viewPort, bool water, int count = 0) { if (count > 16) { //ASSERT(false); return; @@ -1781,48 +1781,51 @@ struct Level : IGame { } } - virtual void renderView(int roomIndex, bool water, bool showUI) { + virtual void renderView(int roomIndex, bool water, bool showUI, int roomsCount = 0, int *roomsList = NULL) { PROFILE_MARKER("VIEW"); - if (water && waterCache) { + + if (water && waterCache) waterCache->reset(); - } - int roomsList[256]; - int roomsCount = 0; + int rList[256]; - if (level.isCutsceneLevel()) { // render all rooms except flipped - for (int i = 0; i < level.roomsCount; i++) - level.rooms[i].flags.visible = true; + if (!roomsList) { + roomsList = rList; - for (int i = 0; i < level.roomsCount; i++) { - int flipIndex = level.rooms[i].alternateRoom; - if (flipIndex > 0) - level.rooms[flipIndex].flags.visible = false; - } - - for (int i = 0; i < level.roomsCount; i++) - if (level.rooms[i].flags.visible) { - roomsList[roomsCount++] = i; - if (Core::pass == Core::passCompose && water && waterCache) { - TR::Room &r = level.rooms[i]; - for (int j = 0; j < r.portalsCount; j++) { - int to = r.portals[j].roomIndex; - if (level.rooms[to].flags.visible && (level.rooms[to].flags.water ^ r.flags.water)) - waterCache->setVisible(i, to); - } - } - } - - } else { + // mark all rooms as invisible for (int i = 0; i < level.roomsCount; i++) level.rooms[i].flags.visible = false; - getVisibleRooms(roomsList, roomsCount, TR::NO_ROOM, roomIndex, vec4(-1.0f, -1.0f, 1.0f, 1.0f), water); + if (level.isCutsceneLevel()) { // render all rooms except flipped + // hide alternative rooms from getVisibleRooms + for (int i = 0; i < level.roomsCount; i++) { + int flipIndex = level.rooms[i].alternateRoom; + if (flipIndex > -1) + level.rooms[flipIndex].flags.visible = true; + } + + // get room list through portals (it will change room visible flag) + getVisibleRooms(roomsList, roomsCount, TR::NO_ROOM, roomIndex, vec4(-1.0f, -1.0f, 1.0f, 1.0f), water); + + // add other non-alternative rooms + for (int i = 0; i < level.roomsCount; i++) + if (!level.rooms[i].flags.visible) + roomsList[roomsCount++] = i; + + // 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; + } 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->renderReflect(); Core::Pass pass = Core::pass; @@ -1830,7 +1833,7 @@ struct Level : IGame { Core::pass = pass; } - // clear visibility flag for rooms + // clear entity rendered flag (used for blob shadows) if (Core::pass != Core::passAmbient) for (int i = 0; i < level.entitiesCount; i++) { Controller *controller = (Controller*)level.entities[i].controller; diff --git a/src/texture.h b/src/texture.h index 04ea8f4..91d2472 100644 --- a/src/texture.h +++ b/src/texture.h @@ -84,7 +84,7 @@ struct Texture { #endif Texture(int width, int height, Format format, uint32 opt = 0, void *data = NULL) : opt(opt) { - LOG("create texture %d x %d (%d)\n", width, height, format); +// LOG("create texture %d x %d (%d)\n", width, height, format); #ifndef _PSP #ifdef SPLIT_BY_TILE