1
0
mirror of https://github.com/XProger/OpenLara.git synced 2025-08-11 23:54:09 +02:00

fix stereo render; add anaglyph

This commit is contained in:
XProger
2019-05-23 01:32:04 +03:00
parent 7f7e2a7b09
commit 1067386e65
7 changed files with 381 additions and 267 deletions

View File

@@ -284,6 +284,11 @@ struct AmbientCache {
// second pass - downsample it // second pass - downsample it
Core::setDepthTest(false); Core::setDepthTest(false);
mat4 mProj, mView;
mView.identity();
mProj.identity();
mProj.scale(vec3(1.0f / 32767.0f));
Core::setViewProj(mView, mProj);
game->setShader(Core::passFilter, Shader::FILTER_DOWNSAMPLE); game->setShader(Core::passFilter, Shader::FILTER_DOWNSAMPLE);
for (int i = 1; i < 4; i++) { for (int i = 1; i < 4; i++) {
@@ -445,9 +450,6 @@ struct WaterCache {
vec3 pos, size; vec3 pos, size;
Texture *mask; Texture *mask;
Texture *caustics; Texture *caustics;
#ifdef BLUR_CAUSTICS
Texture *caustics_tmp;
#endif
Texture *data[2]; Texture *data[2];
Item() { Item() {
@@ -531,9 +533,6 @@ struct WaterCache {
delete[] mf; delete[] mf;
caustics = Core::settings.detail.water > Core::Settings::MEDIUM ? new Texture(512, 512, 1, FMT_RGBA, OPT_TARGET | OPT_DEPEND) : NULL; caustics = Core::settings.detail.water > Core::Settings::MEDIUM ? new Texture(512, 512, 1, FMT_RGBA, OPT_TARGET | OPT_DEPEND) : NULL;
#ifdef BLUR_CAUSTICS
caustics_tmp = Core::settings.detail.water > Core::Settings::MEDIUM ? new Texture(512, 512, 1, Texture::RGBA) : NULL;
#endif
blank = false; blank = false;
} }
@@ -542,9 +541,6 @@ struct WaterCache {
delete data[0]; delete data[0];
delete data[1]; delete data[1];
delete caustics; delete caustics;
#ifdef BLUR_CAUSTICS
delete caustics_tmp;
#endif
delete mask; delete mask;
mask = caustics = data[0] = data[1] = NULL; mask = caustics = data[0] = data[1] = NULL;
} }
@@ -739,23 +735,6 @@ struct WaterCache {
Core::validateRenderState(); // force clear color for borders Core::validateRenderState(); // force clear color for borders
Core::setViewport(1, 1, item.caustics->width - 1, item.caustics->width - 1); // leave 2px for black border Core::setViewport(1, 1, item.caustics->width - 1, item.caustics->width - 1); // leave 2px for black border
game->getMesh()->renderPlane(); game->getMesh()->renderPlane();
#ifdef BLUR_CAUSTICS
// v blur
Core::setTarget(item.caustics_tmp, CLEAR_ALL);
game->setShader(Core::passFilter, Shader::FILTER_BLUR, false, false);
Core::active.shader->setParam(uParam, vec4(0, 1, 1.0f / item.caustics->width, 0));;
item.caustics->bind(sDiffuse);
game->getMesh()->renderQuad();
Core::invalidateTarget(false, true);
// h blur
Core::setTarget(item.caustics, CLEAR_ALL);
game->setShader(Core::passFilter, Shader::FILTER_BLUR, false, false);
Core::active.shader->setParam(uParam, vec4(1, 0, 1.0f / item.caustics->width, 0));;
item.caustics_tmp->bind(sDiffuse);
game->getMesh()->renderQuad();
Core::invalidateTarget(false, true);
#endif
} }
void renderRays() { void renderRays() {

View File

@@ -75,7 +75,7 @@ struct IGame {
virtual void renderModelFull(int modelIndex, bool underwater, Basis *joints) {} virtual void renderModelFull(int modelIndex, bool underwater, Basis *joints) {}
virtual void renderCompose(int roomIndex) {} 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, int *roomsList = NULL) {}
virtual void renderGame(bool showUI) {} virtual void renderGame(bool showUI, bool invBG) {}
virtual void setEffect(Controller *controller, TR::Effect::Type effect) {} virtual void setEffect(Controller *controller, TR::Effect::Type effect) {}
virtual void checkTrigger(Controller *controller, bool heavy) {} virtual void checkTrigger(Controller *controller, bool heavy) {}

View File

@@ -351,6 +351,7 @@ namespace Core {
#include "napi_dummy.h" #include "napi_dummy.h"
#endif #endif
#define LIGHT_STACK_SIZE 1
#define MAX_LIGHTS 4 #define MAX_LIGHTS 4
#define MAX_RENDER_BUFFERS 32 #define MAX_RENDER_BUFFERS 32
#define MAX_CONTACTS 15 #define MAX_CONTACTS 15
@@ -567,6 +568,12 @@ namespace Core {
vec4 fogParams; vec4 fogParams;
vec4 contacts[MAX_CONTACTS]; vec4 contacts[MAX_CONTACTS];
struct LightStack {
vec4 pos[MAX_LIGHTS];
vec4 color[MAX_LIGHTS];
} lightStack[LIGHT_STACK_SIZE];
int lightStackCount;
Texture *whiteTex, *whiteCube, *blackTex, *ditherTex, *noiseTex, *perlinTex; Texture *whiteTex, *whiteCube, *blackTex, *ditherTex, *noiseTex, *perlinTex;
enum Pass { passCompose, passShadow, passAmbient, passSky, passWater, passFilter, passGUI, passMAX } pass; enum Pass { passCompose, passShadow, passAmbient, passSky, passWater, passFilter, passGUI, passMAX } pass;
@@ -707,6 +714,7 @@ namespace Core {
x = y = 0; x = y = 0;
eyeTex[0] = eyeTex[1] = NULL; eyeTex[0] = eyeTex[1] = NULL;
lightStackCount = 0;
memset(&support, 0, sizeof(support)); memset(&support, 0, sizeof(support));
support.texMinSize = 1; support.texMinSize = 1;
@@ -1101,6 +1109,21 @@ namespace Core {
updateLights(); updateLights();
} }
void pushLights() {
ASSERT(lightStackCount < LIGHT_STACK_SIZE);
memcpy(lightStack[lightStackCount].pos, lightPos, sizeof(lightPos));
memcpy(lightStack[lightStackCount].color, lightColor, sizeof(lightColor));
lightStackCount++;
}
void popLights() {
ASSERT(lightStackCount > 0);
lightStackCount--;
memcpy(lightPos, lightStack[lightStackCount].pos, sizeof(lightPos));
memcpy(lightColor, lightStack[lightStackCount].color, sizeof(lightColor));
updateLights();
}
void copyTarget(Texture *dst, int xOffset, int yOffset, int x, int y, int width, int height) { void copyTarget(Texture *dst, int xOffset, int yOffset, int x, int y, int width, int height) {
validateRenderState(); validateRenderState();
GAPI::copyTarget(dst, xOffset, yOffset, x, y, width, height); GAPI::copyTarget(dst, xOffset, yOffset, x, y, width, height);

View File

@@ -13,59 +13,104 @@
#elif _OS_ANDROID #elif _OS_ANDROID
#include <dlfcn.h> #include <dlfcn.h>
#include <GLES3/gl3.h> // #define _GAPI_GLES2 // for old devices
#include <GLES3/gl3ext.h>
#include <GLES2/gl2ext.h> #ifdef _GAPI_GLES2
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#define GL_CLAMP_TO_BORDER 0x812D
#define GL_TEXTURE_BORDER_COLOR 0x1004
#define GL_TEXTURE_COMPARE_MODE 0x884C
#define GL_TEXTURE_COMPARE_FUNC 0x884D
#define GL_COMPARE_REF_TO_TEXTURE 0x884E
#undef GL_RG
#undef GL_RG32F
#undef GL_RG16F
#undef GL_RGBA32F
#undef GL_RGBA16F
#undef GL_HALF_FLOAT
#define GL_RG GL_RGBA
#define GL_RGBA32F GL_RGBA
#define GL_RGBA16F GL_RGBA
#define GL_RG32F GL_RGBA
#define GL_RG16F GL_RGBA
#define GL_HALF_FLOAT GL_HALF_FLOAT_OES
#define GL_TEXTURE_3D 0
#define GL_TEXTURE_WRAP_R 0
#define GL_DEPTH_STENCIL GL_DEPTH_STENCIL_OES
#define GL_UNSIGNED_INT_24_8 GL_UNSIGNED_INT_24_8_OES
#define glTexImage3D(...) 0
#define glGenVertexArrays(...)
#define glDeleteVertexArrays(...)
#define glBindVertexArray(...)
#define GL_PROGRAM_BINARY_LENGTH GL_PROGRAM_BINARY_LENGTH_OES
#define glGetProgramBinary(...)
#define glProgramBinary(...)
#define glInvalidateFramebuffer(...)
#else
#include <GLES3/gl3.h>
#include <GLES3/gl3ext.h>
#include <GLES2/gl2ext.h>
#endif
#elif defined(__SDL2__) #elif defined(__SDL2__)
#include <SDL2/SDL.h> #include <SDL2/SDL.h>
#if defined(_GAPI_GLES) #if defined(_GAPI_GLES)
#define GL_GLEXT_PROTOTYPES 1 #define GL_GLEXT_PROTOTYPES 1
#include <SDL2/SDL_opengles2.h> #include <SDL2/SDL_opengles2.h>
#include <SDL2/SDL_opengles2_gl2ext.h> #include <SDL2/SDL_opengles2_gl2ext.h>
#define GL_CLAMP_TO_BORDER 0x812D #define GL_CLAMP_TO_BORDER 0x812D
#define GL_TEXTURE_BORDER_COLOR 0x1004 #define GL_TEXTURE_BORDER_COLOR 0x1004
#define GL_TEXTURE_COMPARE_MODE 0x884C #define GL_TEXTURE_COMPARE_MODE 0x884C
#define GL_TEXTURE_COMPARE_FUNC 0x884D #define GL_TEXTURE_COMPARE_FUNC 0x884D
#define GL_COMPARE_REF_TO_TEXTURE 0x884E #define GL_COMPARE_REF_TO_TEXTURE 0x884E
#undef GL_RG #undef GL_RG
#undef GL_RG32F #undef GL_RG32F
#undef GL_RG16F #undef GL_RG16F
#undef GL_RGBA32F #undef GL_RGBA32F
#undef GL_RGBA16F #undef GL_RGBA16F
#undef GL_HALF_FLOAT #undef GL_HALF_FLOAT
#define GL_RG GL_RGBA #define GL_RG GL_RGBA
#define GL_RGBA32F GL_RGBA #define GL_RGBA32F GL_RGBA
#define GL_RGBA16F GL_RGBA #define GL_RGBA16F GL_RGBA
#define GL_RG32F GL_RGBA #define GL_RG32F GL_RGBA
#define GL_RG16F GL_RGBA #define GL_RG16F GL_RGBA
#define GL_HALF_FLOAT GL_HALF_FLOAT_OES #define GL_HALF_FLOAT GL_HALF_FLOAT_OES
#define GL_TEXTURE_WRAP_R 0 #define GL_TEXTURE_WRAP_R 0
#define GL_DEPTH_STENCIL GL_DEPTH_STENCIL_OES #define GL_DEPTH_STENCIL GL_DEPTH_STENCIL_OES
#define GL_UNSIGNED_INT_24_8 GL_UNSIGNED_INT_24_8_OES #define GL_UNSIGNED_INT_24_8 GL_UNSIGNED_INT_24_8_OES
#define glTexImage3D(...) 0 #define glTexImage3D(...) 0
#ifndef GL_TEXTURE_3D // WUUUUUT!? #ifndef GL_TEXTURE_3D // WUUUUUT!?
#define GL_TEXTURE_3D GL_TEXTURE_3D_OES #define GL_TEXTURE_3D GL_TEXTURE_3D_OES
#endif #endif
#define glGenVertexArrays(...) #define glGenVertexArrays(...)
#define glDeleteVertexArrays(...) #define glDeleteVertexArrays(...)
#define glBindVertexArray(...) #define glBindVertexArray(...)
#define GL_PROGRAM_BINARY_LENGTH GL_PROGRAM_BINARY_LENGTH_OES #define GL_PROGRAM_BINARY_LENGTH GL_PROGRAM_BINARY_LENGTH_OES
#define glGetProgramBinary(...) #define glGetProgramBinary(...)
#define glProgramBinary(...) #define glProgramBinary(...)
#else #else
#define GL_GLEXT_PROTOTYPES 1 #define GL_GLEXT_PROTOTYPES 1
#include <SDL2/SDL_opengl.h> #include <SDL2/SDL_opengl.h>
#include <SDL2/SDL_opengl_glext.h> #include <SDL2/SDL_opengl_glext.h>
#endif #endif
#elif defined(_OS_PSC) #elif defined(_OS_PSC)
@@ -811,7 +856,7 @@ namespace GAPI {
glGenerateMipmap(target); glGenerateMipmap(target);
if ((opt & (OPT_VOLUME | OPT_CUBEMAP | OPT_NEAREST)) == 0 && (Core::support.maxAniso > 0)) { if ((opt & (OPT_VOLUME | OPT_CUBEMAP | OPT_NEAREST)) == 0 && (Core::support.maxAniso > 0)) {
glTexParameteri(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, min(int(Core::support.maxAniso), 8)); glTexParameteri(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, min(int(Core::support.maxAniso), 8));
#if !defined(_OS_RPI) && !defined(_OS_CLOVER) // TODO #if !defined(_OS_RPI) && !defined(_OS_CLOVER) && !defined(_GAPI_GLES2) // TODO
glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, 3); glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, 3);
#endif #endif
} }
@@ -998,14 +1043,12 @@ namespace GAPI {
GLuint FBO, defaultFBO; GLuint FBO, defaultFBO;
struct RenderTargetCache { struct RenderTargetCacheItem {
int count; GLuint ID;
struct Item { int width;
GLuint ID; int height;
int width; };
int height; Array<RenderTargetCacheItem> rtCache[2];
} items[MAX_RENDER_BUFFERS];
} rtCache[2];
bool extSupport(const char *str, const char *ext) { bool extSupport(const char *str, const char *ext) {
if (!str) return false; if (!str) return false;
@@ -1013,10 +1056,8 @@ namespace GAPI {
} }
void init() { void init() {
memset(rtCache, 0, sizeof(rtCache));
#ifdef _OS_ANDROID #ifdef _OS_ANDROID
void *libGL = dlopen("libGLESv2.so", RTLD_LAZY); //void *libGL = dlopen("libGLESv2.so", RTLD_LAZY);
#endif #endif
#if defined(_OS_WIN) || defined(_OS_LINUX) #if defined(_OS_WIN) || defined(_OS_LINUX)
@@ -1125,7 +1166,7 @@ namespace GAPI {
#ifdef _OS_WEB #ifdef _OS_WEB
GLES3 = WEBGL_VERSION != 1; GLES3 = WEBGL_VERSION != 1;
#else #else
#ifdef _GAPI_GLES #if defined(_GAPI_GLES) && !defined(_GAPI_GLES2)
int GLES_VERSION = 1; int GLES_VERSION = 1;
#if defined(__SDL2__) #if defined(__SDL2__)
SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &GLES_VERSION); SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &GLES_VERSION);
@@ -1151,6 +1192,12 @@ namespace GAPI {
support.discardFrame = extSupport(ext, "_discard_framebuffer"); support.discardFrame = extSupport(ext, "_discard_framebuffer");
support.texNPOT = GLES3 || extSupport(ext, "_texture_npot") || extSupport(ext, "_texture_non_power_of_two"); support.texNPOT = GLES3 || extSupport(ext, "_texture_npot") || extSupport(ext, "_texture_non_power_of_two");
support.texRG = GLES3 || extSupport(ext, "_texture_rg "); // hope that isn't last extension in string ;) support.texRG = GLES3 || extSupport(ext, "_texture_rg "); // hope that isn't last extension in string ;)
#ifdef _GAPI_GLES2 // TODO
support.shaderBinary = false;
support.VAO = false;
support.texRG = false;
support.discardFrame = false;
#endif
#ifdef _GAPI_GLES #ifdef _GAPI_GLES
support.derivatives = GLES3 || _GL_OES_standard_derivatives; support.derivatives = GLES3 || _GL_OES_standard_derivatives;
support.tex3D = GLES3; support.tex3D = GLES3;
@@ -1282,9 +1329,12 @@ namespace GAPI {
glDeleteFramebuffers(1, &FBO); glDeleteFramebuffers(1, &FBO);
glBindRenderbuffer(GL_RENDERBUFFER, 0); glBindRenderbuffer(GL_RENDERBUFFER, 0);
for (int b = 0; b < 2; b++) for (int b = 0; b < 2; b++) {
for (int i = 0; i < rtCache[b].count; i++) for (int i = 0; i < rtCache[b].length; i++) {
glDeleteRenderbuffers(1, &rtCache[b].items[i].ID); glDeleteRenderbuffers(1, &rtCache[b][i].ID);
}
rtCache[b].clear();
}
} }
mat4 ortho(float l, float r, float b, float t, float znear, float zfar) { mat4 ortho(float l, float r, float b, float t, float znear, float zfar) {
@@ -1315,15 +1365,21 @@ namespace GAPI {
} }
int cacheRenderTarget(bool depth, int width, int height) { int cacheRenderTarget(bool depth, int width, int height) {
RenderTargetCache &cache = rtCache[depth]; Array<RenderTargetCacheItem> &items = rtCache[depth];
for (int i = 0; i < cache.count; i++) for (int i = 0; i < items.length; i++)
if (cache.items[i].width == width && cache.items[i].height == height) if (items[i].width == width && items[i].height == height) {
return i; RenderTargetCacheItem item = items[i];
items.remove(i);
return items.push(item);
}
ASSERT(cache.count < MAX_RENDER_BUFFERS); if (items.length >= MAX_RENDER_BUFFERS) {
glDeleteRenderbuffers(1, &items[0].ID);
items.remove(0);
}
RenderTargetCache::Item &item = cache.items[cache.count]; RenderTargetCacheItem item;
item.width = width; item.width = width;
item.height = height; item.height = height;
@@ -1331,7 +1387,7 @@ namespace GAPI {
glBindRenderbuffer(GL_RENDERBUFFER, item.ID); glBindRenderbuffer(GL_RENDERBUFFER, item.ID);
glRenderbufferStorage(GL_RENDERBUFFER, depth ? GL_DEPTH_COMPONENT16 : GL_RGB565, width, height); glRenderbufferStorage(GL_RENDERBUFFER, depth ? GL_DEPTH_COMPONENT16 : GL_RGB565, width, height);
glBindRenderbuffer(GL_RENDERBUFFER, 0); glBindRenderbuffer(GL_RENDERBUFFER, 0);
return cache.count++; return items.push(item);
} }
void bindTarget(Texture *target, int face) { void bindTarget(Texture *target, int face) {

View File

@@ -14,16 +14,16 @@
#define INV_BG_SIZE 512 #define INV_BG_SIZE 512
#endif #endif
#define INV_HEIGHT 2048.0f #define INV_HEIGHT 2048.0f
#define TITLE_LOADING 64.0f #define INV_EYE_SEPARATION 8.0f
#define LINE_HEIGHT 20.0f #define INV_EYE_FOCAL_LENGTH 512.0f
#define INV_EYE_SEPARATION 16.0f
#define INV_EYE_FOCAL_LENGTH 256.0f
#define INV_ZNEAR 32.0f #define INV_ZNEAR 32.0f
#define INV_ZFAR 2048.0f #define INV_ZFAR 2048.0f
#define INV_FOV 70.0f #define INV_FOV 70.0f
#define TITLE_LOADING 64.0f
#define LINE_HEIGHT 20.0f
static const struct OptionItem *waitForKey = NULL; static const struct OptionItem *waitForKey = NULL;
struct OptionItem { struct OptionItem {
@@ -202,7 +202,7 @@ struct Inventory {
}; };
IGame *game; IGame *game;
Texture *background[2]; Texture *background[3]; // [LEFT EYE or SINGLE, RIGHT EYE, TEMP]
Video *video; Video *video;
bool playLogo; bool playLogo;
@@ -1351,7 +1351,7 @@ struct Inventory {
return false; return false;
} }
Texture* getBackgroundTarget() { Texture* getBackgroundTarget(int view) {
if (background[0] && (background[0]->origWidth != INV_BG_SIZE || background[0]->origHeight != INV_BG_SIZE)) { if (background[0] && (background[0]->origWidth != INV_BG_SIZE || background[0]->origHeight != INV_BG_SIZE)) {
delete background[0]; delete background[0];
background[0] = NULL; background[0] = NULL;
@@ -1361,7 +1361,36 @@ struct Inventory {
if (!background[i]) if (!background[i])
background[i] = new Texture(INV_BG_SIZE, INV_BG_SIZE, 1, FMT_RGBA, OPT_TARGET); background[i] = new Texture(INV_BG_SIZE, INV_BG_SIZE, 1, FMT_RGBA, OPT_TARGET);
return background[0]; return background[view];
}
void blur(Texture *texInOut, Texture *tmp) {
#ifdef FFP
return; // TODO
#endif
game->setShader(Core::passFilter, Shader::FILTER_BLUR, false, false);
// vertical
Core::setTarget(tmp, NULL, RT_STORE_COLOR);
Core::active.shader->setParam(uParam, vec4(0, 1.0f / INV_BG_SIZE, 0, 0));
texInOut->bind(sDiffuse);
game->getMesh()->renderQuad();
// horizontal
Core::setTarget(texInOut, NULL, RT_STORE_COLOR);
game->setShader(Core::passFilter, Shader::FILTER_BLUR, false, false);
Core::active.shader->setParam(uParam, vec4(1.0f / INV_BG_SIZE, 0, 0, 0));
tmp->bind(sDiffuse);
game->getMesh()->renderQuad();
}
void grayscale(Texture *texIn, Texture *texOut) {
#ifdef FFP
return; // TODO
#endif
game->setShader(Core::passFilter, Shader::FILTER_GRAYSCALE, false, false);
Core::setTarget(texOut, NULL, RT_STORE_COLOR);
Core::active.shader->setParam(uParam, vec4(0.75f, 0.75f, 1.0f, 1.0f));
texIn->bind(sDiffuse);
game->getMesh()->renderQuad();
} }
void prepareBackground() { void prepareBackground() {
@@ -1371,9 +1400,8 @@ struct Inventory {
#ifdef _OS_PSP #ifdef _OS_PSP
return; return;
#endif #endif
Core::defaultTarget = getBackgroundTarget();
game->renderGame(false); game->renderGame(false, true);
Core::defaultTarget = NULL;
Core::setDepthTest(false); Core::setDepthTest(false);
Core::setBlendMode(bmNone); Core::setBlendMode(bmNone);
@@ -1385,36 +1413,27 @@ struct Inventory {
Core::mModel.identity(); Core::mModel.identity();
#endif #endif
#ifdef _OS_PSP int viewsCount = (Core::settings.detail.stereo == Core::Settings::STEREO_OFF) ? 1 : 2;
//
#else
// vertical blur
Core::setTarget(background[1], NULL, RT_STORE_COLOR);
game->setShader(Core::passFilter, Shader::FILTER_BLUR, false, false);
Core::active.shader->setParam(uParam, vec4(0, 1.0f / INV_BG_SIZE, 0, 0));
background[0]->bind(sDiffuse);
game->getMesh()->renderQuad();
// horizontal blur mat4 mProj, mView;
Core::setTarget(background[0], NULL, RT_STORE_COLOR); mView.identity();
game->setShader(Core::passFilter, Shader::FILTER_BLUR, false, false); mProj.identity();
Core::active.shader->setParam(uParam, vec4(1.0f / INV_BG_SIZE, 0, 0, 0)); mProj.scale(vec3(1.0f / 32767.0f));
background[1]->bind(sDiffuse); Core::setViewProj(mView, mProj);
game->getMesh()->renderQuad();
// grayscale for (int view = 0; view < viewsCount; view++) {
Core::setTarget(background[1], NULL, RT_STORE_COLOR); blur(background[view], background[2]);
game->setShader(Core::passFilter, Shader::FILTER_GRAYSCALE, false, false); grayscale(background[view], background[2]);
Core::active.shader->setParam(uParam, vec4(0.75f, 0.75f, 1.0f, 1.0f)); swap(background[view], background[2]);
background[0]->bind(sDiffuse); }
game->getMesh()->renderQuad();
swap(background[0], background[1]);
#endif
Core::setDepthTest(true); Core::setDepthTest(true);
} }
float getEyeOffset() {
return -Core::eye * INV_EYE_SEPARATION * 0.75f;
}
void renderItemCount(const Item *item, const vec2 &pos, float width) { void renderItemCount(const Item *item, const vec2 &pos, float width) {
char spec; char spec;
switch (item->type) { switch (item->type) {
@@ -1446,11 +1465,13 @@ struct Inventory {
if (item->value == 2) str = STR_EXIT_TO_TITLE; if (item->value == 2) str = STR_EXIT_TO_TITLE;
} }
UI::textOut(vec2(0, 480 - 32), str, UI::aCenter, UI::width); float eye = getEyeOffset();
UI::textOut(vec2(eye, 480 - 32), str, UI::aCenter, UI::width);
int tw = UI::getTextSize(STR[str]).x; int tw = UI::getTextSize(STR[str]).x;
if (item->value > 0) UI::specOut(vec2((UI::width - tw) * 0.5f - 32.0f, 480 - 32), 108); if (item->value > 0) UI::specOut(vec2((UI::width - tw) * 0.5f - 32.0f + eye, 480 - 32), 108);
if (item->value < 2) UI::specOut(vec2((UI::width + tw) * 0.5f + 16.0f, 480 - 32), 109); if (item->value < 2) UI::specOut(vec2((UI::width + tw) * 0.5f + 16.0f + eye, 480 - 32), 109);
if (item->value != 0) return; if (item->value != 0) return;
@@ -1473,7 +1494,7 @@ struct Inventory {
if (item->type == TR::Entity::INV_CONTROLS || item->type == TR::Entity::INV_DETAIL) if (item->type == TR::Entity::INV_CONTROLS || item->type == TR::Entity::INV_DETAIL)
width += 80; width += 80;
float x = ( UI::width - width ) * 0.5f; float x = ( UI::width - width ) * 0.5f + getEyeOffset();
float y = ( UI::height - height ) * 0.5f + LINE_HEIGHT; float y = ( UI::height - height ) * 0.5f + LINE_HEIGHT;
// background // background
@@ -1540,11 +1561,13 @@ struct Inventory {
} }
void renderItemText(Item *item) { void renderItemText(Item *item) {
float eye = getEyeOffset() * 0.5f;
if (item->type == TR::Entity::INV_PASSPORT && phaseChoose == 1.0f) { if (item->type == TR::Entity::INV_PASSPORT && phaseChoose == 1.0f) {
// //
} else { } else {
StringID str = getItemName(item->desc.str, game->getLevel()->id, item->type); StringID str = getItemName(item->desc.str, game->getLevel()->id, item->type);
UI::textOut(vec2(0, 480 - 32), str, UI::aCenter, UI::width); UI::textOut(vec2(eye, 480 - 32), str, UI::aCenter, UI::width);
} }
renderItemCount(item, vec2(UI::width / 2 - 160, 480 - 96), 320); renderItemCount(item, vec2(UI::width / 2 - 160, 480 - 96), 320);
@@ -1644,7 +1667,7 @@ struct Inventory {
} }
void renderTitleBG(float sx = 1.0f, float sy = 1.0f, uint8 alpha = 255, float cropW = 1.0f, float cropH = 1.0f) { void renderTitleBG(float sx = 1.0f, float sy = 1.0f, uint8 alpha = 255, float cropW = 1.0f, float cropH = 1.0f) {
float aspectSrc, aspectDst, aspectImg, ax, ay, tx, ty; float aspectSrc, ax, ay, tx, ty;
if (background[0]) { if (background[0]) {
Texture *tex = background[0]; Texture *tex = background[0];
@@ -1655,15 +1678,15 @@ struct Inventory {
float ox = sx * origW; float ox = sx * origW;
float oy = sy * origH; float oy = sy * origH;
aspectSrc = ox / oy; aspectSrc = ox / oy;
aspectDst = float(Core::width) / float(Core::height);
ax = origW / tex->width; ax = origW / tex->width;
ay = origH / tex->height; ay = origH / tex->height;
} else { } else {
tx = ty = 0.0f; tx = ty = 0.0f;
aspectSrc = ax = ay = 1.0f; aspectSrc = ax = ay = 1.0f;
aspectDst = float(Core::width) / float(Core::height);
} }
aspectImg = aspectSrc / aspectDst;
float aspectDst = float(Core::width) / float(Core::height);
float aspectImg = aspectSrc / aspectDst;
#ifdef FFP #ifdef FFP
mat4 m; mat4 m;
@@ -1673,46 +1696,41 @@ struct Inventory {
Core::mModel.scale(vec3(1.0f / 32767.0f)); Core::mModel.scale(vec3(1.0f / 32767.0f));
#endif #endif
Index indices[6 * 3] = { 0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, 8, 9, 10, 8, 10, 11 }; short o_frame = 32767;
Vertex vertices[4 * 3]; short i_frame = 16384;
short2 size; short2 size = short2(short(i_frame * aspectImg), i_frame);
if (aspectImg < 1.0f) { if (aspectImg < 1.0f) {
size.x = short(32767 * aspectImg); size.x = short(i_frame * aspectImg);
size.y = 32767; size.y = i_frame;
vertices[ 4].coord = short4( -32767, size.y, 0, 0);
vertices[ 5].coord = short4(-size.x, size.y, 0, 0);
vertices[ 6].coord = short4(-size.x, -size.y, 0, 0);
vertices[ 7].coord = short4( -32767, -size.y, 0, 0);
vertices[ 8].coord = short4( size.x, size.y, 0, 0);
vertices[ 9].coord = short4( 32767, size.y, 0, 0);
vertices[10].coord = short4( 32767, -size.y, 0, 0);
vertices[11].coord = short4( size.x, -size.y, 0, 0);
} else { } else {
size.x = 32767; size.x = i_frame;
size.y = short(32767 / aspectImg); size.y = short(i_frame / aspectImg);
vertices[ 4].coord = short4(-size.x, 32767, 0, 0);
vertices[ 5].coord = short4( size.x, 32767, 0, 0);
vertices[ 6].coord = short4( size.x, size.y, 0, 0);
vertices[ 7].coord = short4(-size.x, size.y, 0, 0);
vertices[ 8].coord = short4(-size.x, -size.y, 0, 0);
vertices[ 9].coord = short4( size.x, -size.y, 0, 0);
vertices[10].coord = short4( size.x, -32767, 0, 0);
vertices[11].coord = short4(-size.x, -32767, 0, 0);
} }
short2 t0(short(tx * 32767), short(ty * 32767)); float eye = -getEyeOffset() * size.x / 320.0f;
short2 t1(t0.x + short(ax * 32767), t0.y + short(ay * 32767)); if (titleTimer > 0.0f || video) {
eye = 0.0f;
}
Index indices[10 * 3] = { 0,1,2, 0,2,3, 8,9,5, 8,5,4, 9,10,6, 9,6,5, 10,11,7, 10,7,6, 11,8,4, 11,4,7 };
Vertex vertices[4 * 3];
vertices[ 0].coord = short4(-size.x, size.y, 0, 0); vertices[ 0].coord = short4(-size.x, size.y, 0, 0);
vertices[ 1].coord = short4( size.x, size.y, 0, 0); vertices[ 1].coord = short4( size.x, size.y, 0, 0);
vertices[ 2].coord = short4( size.x, -size.y, 0, 0); vertices[ 2].coord = short4( size.x, -size.y, 0, 0);
vertices[ 3].coord = short4(-size.x, -size.y, 0, 0); vertices[ 3].coord = short4(-size.x, -size.y, 0, 0);
vertices[ 4].coord = vertices[0].coord;
vertices[ 5].coord = vertices[1].coord;
vertices[ 6].coord = vertices[2].coord;
vertices[ 7].coord = vertices[3].coord;
vertices[ 8].coord = short4(-o_frame, o_frame, 0, 0);
vertices[ 9].coord = short4( o_frame, o_frame, 0, 0);
vertices[10].coord = short4( o_frame, -o_frame, 0, 0);
vertices[11].coord = short4(-o_frame, -o_frame, 0, 0);
vertices[ 0].light = vertices[ 0].light =
vertices[ 1].light = vertices[ 1].light =
vertices[ 2].light = vertices[ 2].light =
@@ -1726,6 +1744,9 @@ struct Inventory {
vertices[10].light = vertices[10].light =
vertices[11].light = ubyte4(0, 0, 0, alpha); vertices[11].light = ubyte4(0, 0, 0, alpha);
short2 t0(short(tx * 32767), short(ty * 32767));
short2 t1(t0.x + short(ax * 32767), t0.y + short(ay * 32767));
vertices[ 0].texCoord = short4(t0.x, t0.y, 0, 0); vertices[ 0].texCoord = short4(t0.x, t0.y, 0, 0);
vertices[ 1].texCoord = short4(t1.x, t0.y, 0, 0); vertices[ 1].texCoord = short4(t1.x, t0.y, 0, 0);
vertices[ 2].texCoord = short4(t1.x, t1.y, 0, 0); vertices[ 2].texCoord = short4(t1.x, t1.y, 0, 0);
@@ -1747,12 +1768,19 @@ struct Inventory {
Core::setBlendMode(alpha < 255 ? bmAlpha : bmNone); Core::setBlendMode(alpha < 255 ? bmAlpha : bmNone);
mat4 mProj, mView;
mView.identity();
mProj.identity();
mProj.scale(vec3(1.0f / max(size.x, size.y)));
mProj.translate(vec3(eye, 0.0f, 0.0f));
Core::setViewProj(mView, mProj);
game->setShader(Core::passFilter, Shader::FILTER_UPSCALE, false, false); game->setShader(Core::passFilter, Shader::FILTER_UPSCALE, false, false);
Core::active.shader->setParam(uParam, vec4(float(Core::active.textures[sDiffuse]->width), float(Core::active.textures[sDiffuse]->height), Core::getTime() * 0.001f, 0.0f)); Core::active.shader->setParam(uParam, vec4(float(Core::active.textures[sDiffuse]->width), float(Core::active.textures[sDiffuse]->height), Core::getTime() * 0.001f, 0.0f));
game->getMesh()->renderBuffer(indices, COUNT(indices), vertices, COUNT(vertices)); game->getMesh()->renderBuffer(indices, COUNT(indices), vertices, COUNT(vertices));
} }
void renderGameBG() { void renderGameBG(int view) {
Index indices[6] = { 0, 1, 2, 0, 2, 3 }; Index indices[6] = { 0, 1, 2, 0, 2, 3 };
Vertex vertices[4]; Vertex vertices[4];
vertices[0].coord = short4(-32767, 32767, 0, 0); vertices[0].coord = short4(-32767, 32767, 0, 0);
@@ -1780,11 +1808,23 @@ struct Inventory {
#else #else
if (Core::settings.detail.stereo == Core::Settings::STEREO_VR || !background[0]) { if (Core::settings.detail.stereo == Core::Settings::STEREO_VR || !background[0]) {
backTex = Core::blackTex; // black background backTex = Core::blackTex; // black background
} else } else {
backTex = background[0]; // blured grayscale image // blured grayscale image
if (Core::settings.detail.stereo == Core::Settings::STEREO_SPLIT) {
backTex = background[view];
} else {
backTex = background[Core::eye <= 0.0f ? 0 : 1];
}
}
#endif #endif
backTex->bind(sDiffuse); backTex->bind(sDiffuse);
mat4 mProj, mView;
mView.identity();
mProj.identity();
mProj.scale(vec3(1.0f / 32767.0f));
Core::setViewProj(mView, mProj);
game->setShader(Core::passFilter, Shader::FILTER_UPSCALE, false, false); game->setShader(Core::passFilter, Shader::FILTER_UPSCALE, false, false);
Core::active.shader->setParam(uParam, vec4(float(Core::active.textures[sDiffuse]->width), float(Core::active.textures[sDiffuse]->height), 0.0f, 0.0f)); Core::active.shader->setParam(uParam, vec4(float(Core::active.textures[sDiffuse]->width), float(Core::active.textures[sDiffuse]->height), 0.0f, 0.0f));
@@ -1792,7 +1832,7 @@ struct Inventory {
game->getMesh()->renderBuffer(indices, COUNT(indices), vertices, COUNT(vertices)); game->getMesh()->renderBuffer(indices, COUNT(indices), vertices, COUNT(vertices));
} }
void renderBackground() { void renderBackground(int view) {
if (!isActive() && titleTimer == 0.0f) if (!isActive() && titleTimer == 0.0f)
return; return;
@@ -1813,10 +1853,10 @@ struct Inventory {
if (game->getLevel()->isTitle()) if (game->getLevel()->isTitle())
renderTitleBG(1.0f, sy, alpha); renderTitleBG(1.0f, sy, alpha);
else else
renderGameBG(); renderGameBG(view);
} else { } else {
if (background[1]) if (background[1])
renderGameBG(); renderGameBG(view);
else else
renderTitleBG(1.0f, sy, alpha); renderTitleBG(1.0f, sy, alpha);
} }
@@ -1947,6 +1987,8 @@ struct Inventory {
Core::active.shader->setParam(uViewProj, Core::mViewProj); Core::active.shader->setParam(uViewProj, Core::mViewProj);
} }
float eye = getEyeOffset() * 0.5f;
if (page == PAGE_SAVEGAME) { if (page == PAGE_SAVEGAME) {
UI::renderBar(CTEX_OPTION, vec2(UI::width / 2 - 120, 240 - 14), vec2(240, LINE_HEIGHT - 6), 1.0f, 0x802288FF, 0, 0, 0); UI::renderBar(CTEX_OPTION, vec2(UI::width / 2 - 120, 240 - 14), vec2(240, LINE_HEIGHT - 6), 1.0f, 0x802288FF, 0, 0, 0);
UI::textOut(vec2(0, 240), pageTitle[page], UI::aCenter, UI::width); UI::textOut(vec2(0, 240), pageTitle[page], UI::aCenter, UI::width);
@@ -1962,7 +2004,7 @@ struct Inventory {
} }
if (!game->getLevel()->isTitle()) if (!game->getLevel()->isTitle())
UI::textOut(vec2(0, 32), pageTitle[page], UI::aCenter, UI::width); UI::textOut(vec2(eye, 32), pageTitle[page], UI::aCenter, UI::width);
if (canFlipPage(-1)) { if (canFlipPage(-1)) {
UI::textOut(vec2(16, 32), "[", UI::aLeft, UI::width); UI::textOut(vec2(16, 32), "[", UI::aLeft, UI::width);
@@ -1974,9 +2016,6 @@ struct Inventory {
UI::textOut(vec2( 0, 480 - 16), "]", UI::aRight, UI::width - 20); UI::textOut(vec2( 0, 480 - 16), "]", UI::aRight, UI::width - 20);
} }
if (index == targetIndex && page == targetPage)
renderItemText(items[getGlobalIndex(page, index)]);
// inventory controls help // inventory controls help
if (page == targetPage && Input::touchTimerVis <= 0.0f) { if (page == targetPage && Input::touchTimerVis <= 0.0f) {
float dx = 32.0f; float dx = 32.0f;
@@ -1990,12 +2029,16 @@ struct Inventory {
#endif #endif
sprintf(buf, STR[STR_HELP_SELECT], bSelect); sprintf(buf, STR[STR_HELP_SELECT], bSelect);
UI::textOut(vec2(dx, 480 - 64), buf, UI::aLeft, UI::width); UI::textOut(vec2(eye + dx, 480 - 64), buf, UI::aLeft, UI::width);
if (chosen) { if (chosen) {
sprintf(buf, STR[STR_HELP_BACK], bBack); sprintf(buf, STR[STR_HELP_BACK], bBack);
UI::textOut(vec2(0, 480 - 64), buf, UI::aRight, UI::width - dx); UI::textOut(vec2(eye, 480 - 64), buf, UI::aRight, UI::width - dx);
} }
} }
if (index == targetIndex && page == targetPage) {
renderItemText(items[getGlobalIndex(page, index)]);
}
} }
}; };

View File

@@ -63,6 +63,7 @@ struct Level : IGame {
bool needRedrawTitleBG; bool needRedrawTitleBG;
bool needRedrawReflections; bool needRedrawReflections;
bool needRenderGame; bool needRenderGame;
bool needRenderInventory;
bool showStats; bool showStats;
bool skyIsVisible; bool skyIsVisible;
@@ -2512,7 +2513,7 @@ struct Level : IGame {
Core::mViewInv = mat4(pos, pos + dir, up); Core::mViewInv = mat4(pos, pos + dir, up);
Core::mView = Core::mViewInv.inverseOrtho(); Core::mView = Core::mViewInv.inverseOrtho();
Core::mProj = GAPI::perspective(90, 1.0f, camera->znear, camera->zfar, 0.0f); Core::mProj = GAPI::perspective(90, 1.0f, 32.0f, 45.0f * 1024.0f, 0.0f);
Core::mViewProj = Core::mProj * Core::mView; Core::mViewProj = Core::mProj * Core::mView;
Core::viewPos = Core::mViewInv.offset().xyz(); Core::viewPos = Core::mViewInv.offset().xyz();
@@ -2889,7 +2890,7 @@ struct Level : IGame {
} }
#endif #endif
void setViewport(int view, int eye, bool isUI) { float setViewport(int view, int eye) {
int vX = Core::x; int vX = Core::x;
int vY = Core::y; int vY = Core::y;
int vW = Core::width; int vW = Core::width;
@@ -2905,13 +2906,15 @@ struct Level : IGame {
} }
Viewport &vp = Core::viewportDef; Viewport &vp = Core::viewportDef;
vp = Viewport(vX, vY, vW, vH);
if (players[1] != NULL) { if (players[1] != NULL && view >= 0) {
vp = Viewport(vX + vW / 2 * view, vY, vW / 2, vH); vp = Viewport(vX + vW / 2 * view, vY, vW / 2, vH);
if (Core::settings.detail.stereo != Core::Settings::STEREO_SPLIT)
if (Core::settings.detail.stereo != Core::Settings::STEREO_SPLIT) {
aspect *= 0.5f; aspect *= 0.5f;
} else }
vp = Viewport(vX, vY, vW, vH); }
if (Core::settings.detail.stereo == Core::Settings::STEREO_SBS) { if (Core::settings.detail.stereo == Core::Settings::STEREO_SBS) {
switch (eye) { switch (eye) {
@@ -2922,10 +2925,7 @@ struct Level : IGame {
Core::setViewport(vp.x, vp.y, vp.width, vp.height); Core::setViewport(vp.x, vp.y, vp.width, vp.height);
if (isUI) return aspect;
UI::updateAspect(aspect);
else
camera->aspect = aspect;
} }
void renderPrepare() { void renderPrepare() {
@@ -2948,20 +2948,14 @@ struct Level : IGame {
} }
needRenderGame = !inventory->video && !level.isTitle() && ((inventory->phaseRing < 1.0f && inventory->titleTimer <= 1.0f) || needRedrawTitleBG); needRenderGame = !inventory->video && !level.isTitle() && ((inventory->phaseRing < 1.0f && inventory->titleTimer <= 1.0f) || needRedrawTitleBG);
needRenderInventory = inventory->video || level.isTitle() || inventory->phaseRing > 0.0f || inventory->titleTimer > 0.0f;
if (inventory->video) { bool title = inventory->isActive() || level.isTitle();
inventory->render(1.0); bool copyBg = title && (lastTitle != title || needRedrawTitleBG);
lastTitle = title;
needRedrawTitleBG = false;
if (UI::subsStr != STR_EMPTY) { if (!needRenderGame && !copyBg)
UI::begin();
UI::updateAspect(float(Core::width) / float(Core::height));
atlasGlyphs->bind(sDiffuse);
UI::renderSubs();
UI::end();
}
}
if (!needRenderGame)
return; return;
if (needRedrawReflections) { if (needRedrawReflections) {
@@ -2986,39 +2980,44 @@ struct Level : IGame {
renderShadows(player->getRoomIndex(), shadow[1]); renderShadows(player->getRoomIndex(), shadow[1]);
} }
} }
if (copyBg) {
inventory->prepareBackground();
}
} }
void renderEye(int eye, bool showUI) { void setDefaultTarget(int eye, int view, bool invBG) {
int texIndex = eye <= 0 ? 0 : 1;
#ifdef _OS_3DS
Core::eye *= osGet3DSliderState() / 3.0f;
GAPI::curTarget = GAPI::defTarget[texIndex];
C3D_FrameDrawOn(GAPI::curTarget);
#else
if (invBG) {
if (Core::settings.detail.stereo == Core::Settings::STEREO_SPLIT) {
Core::defaultTarget = inventory->getBackgroundTarget(view);
} else {
Core::defaultTarget = inventory->getBackgroundTarget(texIndex);
}
} else {
if (Core::settings.detail.stereo == Core::Settings::STEREO_ANAGLYPH || Core::settings.detail.stereo == Core::Settings::STEREO_VR) {
Core::defaultTarget = invBG ? inventory->getBackgroundTarget(texIndex) : Core::eyeTex[texIndex];
}
}
#endif
}
void renderEye(int eye, bool showUI, bool invBG) {
float oldEye = Core::eye; float oldEye = Core::eye;
Viewport oldViewport = Core::viewportDef; Viewport oldViewport = Core::viewportDef;
GAPI::Texture *oldTarget = Core::defaultTarget; GAPI::Texture *oldTarget = Core::defaultTarget;
Core::eye = float(eye); Core::eye = float(eye);
#ifdef _OS_3DS if (needRenderGame || invBG) {
Core::eye *= osGet3DSliderState() / 3.0f;
if (eye <= 0) {
GAPI::curTarget = GAPI::defTarget[0];
} else {
GAPI::curTarget = GAPI::defTarget[1];
}
C3D_FrameDrawOn(GAPI::curTarget);
#else
if (Core::settings.detail.stereo == Core::Settings::STEREO_ANAGLYPH || Core::settings.detail.stereo == Core::Settings::STEREO_VR) {
if (eye <= 0) {
Core::defaultTarget = Core::eyeTex[0];
} else {
Core::defaultTarget = Core::eyeTex[1];
}
}
#endif
if (Core::lightColor[1].x > 0.5f) {
LOG("hello");
}
if (needRenderGame) {
int viewsCount = players[1] ? 2 : 1; int viewsCount = players[1] ? 2 : 1;
for (int view = 0; view < viewsCount; view++) { for (int view = 0; view < viewsCount; view++) {
player = players[view]; player = players[view];
@@ -3029,22 +3028,27 @@ struct Level : IGame {
Core::pass = Core::passCompose; Core::pass = Core::passCompose;
setViewport(view, eye, false); setDefaultTarget(eye, view, invBG);
if (Core::settings.detail.stereo == Core::Settings::STEREO_SPLIT) {
camera->aspect = setViewport(invBG ? -1 : view, invBG ? 0 : eye);
} else {
camera->aspect = setViewport(view, invBG ? 0 : eye);
}
setup(); setup();
renderView(camera->getRoomIndex(), true, showUI); renderView(camera->getRoomIndex(), true, showUI);
} }
} else {
Core::setTarget(NULL, NULL, RT_CLEAR_DEPTH | RT_STORE_COLOR);
} }
Core::pushLights();
Core::resetLights();
if (!(level.isTitle() || inventory->titleTimer > 0.0f)) if (needRenderInventory && !invBG) {
inventory->renderBackground(); if (players[1] && Core::settings.detail.stereo == Core::Settings::STEREO_SPLIT) {
renderInventoryEye(eye, 0);
renderInventoryEye(eye); renderInventoryEye(eye, 1);
Core::popLights(); } else {
renderInventoryEye(eye, -1);
}
}
Core::defaultTarget = oldTarget; Core::defaultTarget = oldTarget;
Core::viewportDef = oldViewport; Core::viewportDef = oldViewport;
@@ -3056,15 +3060,21 @@ struct Level : IGame {
} }
} }
void renderGame(bool showUI) { void renderGame(bool showUI, bool invBG) {
if (Core::eye == 0.0f && Core::settings.detail.isStereo()) { if (Core::eye == 0.0f && Core::settings.detail.isStereo()) {
renderEye(-1, showUI); renderEye(-1, showUI, invBG);
renderEye(+1, showUI); renderEye(+1, showUI, invBG);
} else { } else {
renderEye(int(Core::eye), showUI); renderEye(int(Core::eye), showUI, invBG);
} }
if (Core::settings.detail.stereo == Core::Settings::STEREO_ANAGLYPH) { if (Core::settings.detail.stereo == Core::Settings::STEREO_ANAGLYPH && !invBG) {
mat4 mProj, mView;
mView.identity();
mProj.identity();
mProj.scale(vec3(1.0f / 32767.0f));
Core::setViewProj(mView, mProj);
Core::setTarget(NULL, NULL, RT_STORE_COLOR); Core::setTarget(NULL, NULL, RT_STORE_COLOR);
setShader(Core::passFilter, Shader::FILTER_ANAGLYPH, false, false); setShader(Core::passFilter, Shader::FILTER_ANAGLYPH, false, false);
Core::eyeTex[0]->bind(sDiffuse); Core::eyeTex[0]->bind(sDiffuse);
@@ -3133,24 +3143,32 @@ struct Level : IGame {
Core::popLights(); Core::popLights();
} }
void renderInventoryEye(int eye) { void renderInventoryEye(int eye, int view) {
float aspect = float(Core::width) / float(Core::height); setDefaultTarget(eye, view, false);
if (Core::settings.detail.stereo == Core::Settings::STEREO_SBS) { Core::setTarget(NULL, NULL, RT_CLEAR_DEPTH | RT_STORE_COLOR);
switch (eye) {
case -1 : Core::setViewport(Core::x, Core::y, Core::width / 2, Core::height); break; float aspect = setViewport(view, eye);
case 0 : Core::setViewport(Core::x, Core::y, Core::width, Core::height); break;
case +1 : Core::setViewport(Core::x + Core::width / 2, Core::y, Core::width / 2, Core::height); break; Core::pushLights();
Core::resetLights();
if (inventory->video) {
inventory->render(1.0);
if (UI::subsStr != STR_EMPTY) {
UI::begin();
UI::updateAspect(float(Core::width) / float(Core::height));
atlasGlyphs->bind(sDiffuse);
UI::renderSubs();
UI::end();
} }
} }
if (Core::settings.detail.stereo == Core::Settings::STEREO_ANAGLYPH) { if (!inventory->video) {
Core::setViewport(Core::x, Core::y, Core::width, Core::height); inventory->renderBackground(max(0, view));
} }
if (level.isTitle() || inventory->titleTimer > 0.0f)
inventory->renderBackground();
setupBinding(); setupBinding();
atlasObjects->bind(sDiffuse); atlasObjects->bind(sDiffuse);
inventory->render(aspect); inventory->render(aspect);
@@ -3158,20 +3176,18 @@ struct Level : IGame {
UI::begin(); UI::begin();
UI::updateAspect(aspect); UI::updateAspect(aspect);
atlasGlyphs->bind(sDiffuse); atlasGlyphs->bind(sDiffuse);
inventory->renderUI(); if (!inventory->video) {
inventory->renderUI();
} else {
UI::renderSubs();
}
UI::end(); UI::end();
Core::popLights();
} }
void render() { void render() {
if (inventory->video) if (isEnded && !inventory->video) {
return;
bool title = inventory->isActive() || level.isTitle();
bool copyBg = title && (lastTitle != title || needRedrawTitleBG);
lastTitle = title;
needRedrawTitleBG = false;
if (isEnded) {
Core::setTarget(NULL, NULL, RT_CLEAR_COLOR | RT_STORE_COLOR); Core::setTarget(NULL, NULL, RT_CLEAR_COLOR | RT_STORE_COLOR);
UI::begin(); UI::begin();
UI::updateAspect(float(Core::width) / float(Core::height)); UI::updateAspect(float(Core::width) / float(Core::height));
@@ -3181,11 +3197,7 @@ struct Level : IGame {
return; return;
} }
if (copyBg) { renderGame(true, false);
inventory->prepareBackground();
}
renderGame(true);
} }
}; };

View File

@@ -2,6 +2,7 @@ R"====(
varying vec2 vTexCoord; varying vec2 vTexCoord;
varying vec4 vColor; varying vec4 vColor;
uniform vec4 uParam; uniform vec4 uParam;
uniform mat4 uViewProj;
#ifdef VERTEX #ifdef VERTEX
attribute vec4 aCoord; attribute vec4 aCoord;
@@ -9,9 +10,9 @@ uniform vec4 uParam;
attribute vec4 aLight; attribute vec4 aLight;
void main() { void main() {
vTexCoord = aTexCoord.xy; vTexCoord = aTexCoord.xy;
vColor = aLight; vColor = aLight;
gl_Position = vec4(aCoord.xy * (1.0 / 32767.0), 0.0, 1.0); gl_Position = uViewProj * vec4(aCoord.xy, 0.0, 1.0);
} }
#else #else
uniform sampler2D sDiffuse; uniform sampler2D sDiffuse;