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:
87
src/cache.h
87
src/cache.h
@@ -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
|
||||
|
@@ -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;
|
||||
|
21
src/level.h
21
src/level.h
@@ -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) {
|
||||
|
Reference in New Issue
Block a user