1
0
mirror of https://github.com/XProger/OpenLara.git synced 2025-08-16 10:04:28 +02:00

render to screen texture for iOS

This commit is contained in:
XProger
2018-08-26 20:34:52 +03:00
parent 6f8752238f
commit c68bd5f2fb
3 changed files with 82 additions and 28 deletions

View File

@@ -357,6 +357,7 @@ struct WaterCache {
IGame *game;
TR::Level *level;
Texture *screen;
Texture *refract;
Texture *reflect;
@@ -482,11 +483,12 @@ struct WaterCache {
Drop(const vec3 &pos, float radius, float strength) : pos(pos), radius(radius), strength(strength) {}
} drops[MAX_DROPS];
WaterCache(IGame *game) : game(game), level(game->getLevel()), refract(NULL), count(0), dropCount(0) {
WaterCache(IGame *game) : game(game), level(game->getLevel()), screen(NULL), refract(NULL), count(0), dropCount(0) {
reflect = new Texture(512, 512, FMT_RGBA, OPT_TARGET);
}
~WaterCache() {
~WaterCache() {
delete screen;
delete refract;
delete reflect;
for (int i = 0; i < count; i++)
@@ -702,27 +704,34 @@ struct WaterCache {
Core::setCullMode(cmFront);
}
void getTargetSize(int &w, int &h) {
if (Core::active.target != NULL) {
w = Core::active.target->width;
h = Core::active.target->height;
} else {
w = Core::viewportDef.width;
h = Core::viewportDef.height;
}
}
void getRefract() {
if (!visible) return;
PROFILE_MARKER("WATER_REFRACT");
int w, h;
getTargetSize(w, h);
Texture* getScreenTex() {
int w = Core::viewportDef.width;
int h = Core::viewportDef.height;
// get refraction texture
if (!refract || w > refract->origWidth || h > refract->origHeight) {
if (!refract || w != refract->origWidth || h != refract->origHeight) {
PROFILE_MARKER("WATER_REFRACT_INIT");
delete refract;
refract = new Texture(w, h, FMT_RGBA, OPT_TARGET);
#ifdef _OS_IOS
delete screen;
screen = new Texture(w, h, FMT_RGBA, OPT_TARGET);
#endif
}
Core::copyTarget(refract, 0, 0, int(Core::viewportDef.x), int(Core::viewportDef.y), w, h); // copy framebuffer into refraction texture
return screen;
}
void copyScreenToRefract() {
PROFILE_MARKER("WATER_REFRACT_COPY");
// get refraction texture
int x, y;
if (!screen) {
x = Core::viewportDef.x;
y = Core::viewportDef.y;
} else
x = y = 0;
Core::copyTarget(refract, 0, 0, x, y, Core::viewportDef.width, Core::viewportDef.height); // copy framebuffer into refraction texture
}
void simulate() {
@@ -828,9 +837,7 @@ struct WaterCache {
Core::active.shader->setParam(uLightPos, Core::lightPos[0], 1);
Core::active.shader->setParam(uLightColor, Core::lightColor[0], 1);
int w, h;
getTargetSize(w, h);
Core::active.shader->setParam(uParam, vec4(float(w) / refract->width, float(h) / refract->height, 0.05f, 0.03f));
Core::active.shader->setParam(uParam, vec4(float(refract->origWidth) / refract->width, float(refract->origHeight) / 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);
@@ -858,6 +865,44 @@ struct WaterCache {
dropCount = 0;
}
void blitScreen() {
ASSERT(screen);
Core::setDepthTest(false);
Core::setBlendMode(bmNone);
game->setShader(Core::passGUI, Shader::DEFAULT);
Core::mView.identity();
Core::mProj = GAPI::ortho(0.0f, float(screen->origWidth), 0.0f, float(screen->origHeight), 0.0f, 1.0f);
Core::setViewProj(Core::mView, Core::mProj);
Core::active.shader->setParam(uViewProj, Core::mViewProj);
Core::active.shader->setParam(uMaterial, vec4(1.0f));
screen->bind(0);
int w = screen->width;
int h = screen->height;
Index indices[6] = { 0, 1, 2, 0, 2, 3 };
Vertex vertices[4];
vertices[0].coord = short4(0, h, 0, 0);
vertices[1].coord = short4(w, h, 0, 0);
vertices[2].coord = short4(w, 0, 0, 0);
vertices[3].coord = short4(0, 0, 0, 0);
vertices[0].light =
vertices[1].light =
vertices[2].light =
vertices[3].light = ubyte4(255, 255, 255, 255);
vertices[0].texCoord = short4( 0, 32767, 0, 0);
vertices[1].texCoord = short4(32767, 32767, 0, 0);
vertices[2].texCoord = short4(32767, 0, 0, 0);
vertices[3].texCoord = short4( 0, 0, 0, 0);
game->getMesh()->renderBuffer(indices, COUNT(indices), vertices, COUNT(vertices));
Core::setDepthTest(true);
}
#undef MAX_WATER_SURFACES
#undef MAX_WATER_INVISIBLE_TIME
#undef WATER_SIMULATE_TIMESTEP

View File

@@ -894,7 +894,7 @@ namespace Core {
if (target == defaultTarget) // backbuffer
setViewport(viewportDef);
else
setViewport(0, 0, target->width, target->height);
setViewport(0, 0, target->origWidth, target->origHeight);
reqTarget.texture = target;
reqTarget.op = op;

View File

@@ -2002,8 +2002,10 @@ struct Level : IGame {
controller->flags.rendered = false;
}
Texture *screen = NULL;
if (water) {
Core::setTarget(NULL, RT_CLEAR_COLOR | RT_CLEAR_DEPTH | RT_STORE_COLOR); // render to back buffer
screen = (waterCache && waterCache->visible) ? waterCache->getScreenTex() : NULL;
Core::setTarget(screen, RT_CLEAR_COLOR | RT_CLEAR_DEPTH | RT_STORE_COLOR); // render to screen texture (FUCK YOU iOS!) or back buffer
setupBinding();
}
@@ -2027,9 +2029,10 @@ struct Level : IGame {
if (water && waterCache && waterCache->visible) {
Core::Pass pass = Core::pass;
waterCache->renderMask();
waterCache->getRefract();
waterCache->copyScreenToRefract();
setMainLight(player);
waterCache->render();
Core::pass = pass;
setupBinding();
}
@@ -2039,11 +2042,17 @@ struct Level : IGame {
Core::setBlendMode(bmNone);
if (showUI) {
Core::Pass pass = Core::pass;
renderUI();
Core::pass = pass;
Core::Pass pass = Core::pass;
if (water && waterCache && waterCache->visible && screen) {
Core::setTarget(NULL, RT_CLEAR_COLOR | RT_CLEAR_DEPTH | RT_STORE_COLOR);
waterCache->blitScreen();
}
if (showUI)
renderUI();
Core::pass = pass;
}
void setupCubeCamera(const vec3 &pos, int face) {