1
0
mirror of https://github.com/XProger/OpenLara.git synced 2025-08-11 15:45:05 +02:00

fixed #214 use scissor test for portals clipping

This commit is contained in:
XProger
2019-10-12 04:35:43 +03:00
parent fb962ec7b9
commit 1b46961a61
7 changed files with 115 additions and 85 deletions

View File

@@ -794,8 +794,8 @@ struct WaterCache {
Texture* getScreenTex() {
int w = Core::viewportDef.width;
int h = Core::viewportDef.height;
int w = Core::viewportDef.z;
int h = Core::viewportDef.w;
// get refraction texture
if (!refract || w != refract->origWidth || h != refract->origHeight) {
PROFILE_MARKER("WATER_REFRACT_INIT");
@@ -829,7 +829,7 @@ struct WaterCache {
blitTexture(screen, flip);
Core::setTarget(screen, NULL, RT_LOAD_COLOR | RT_LOAD_DEPTH | RT_STORE_COLOR);
} else {
Core::copyTarget(refract, 0, 0, x, y, Core::viewportDef.width, Core::viewportDef.height); // copy framebuffer into refraction texture
Core::copyTarget(refract, 0, 0, x, y, Core::viewportDef.z, Core::viewportDef.w); // copy framebuffer into refraction texture
}
}

View File

@@ -398,22 +398,23 @@ namespace GAPI {
enum RenderState {
RS_TARGET = 1 << 0,
RS_VIEWPORT = 1 << 1,
RS_DEPTH_TEST = 1 << 2,
RS_DEPTH_WRITE = 1 << 3,
RS_COLOR_WRITE_R = 1 << 4,
RS_COLOR_WRITE_G = 1 << 5,
RS_COLOR_WRITE_B = 1 << 6,
RS_COLOR_WRITE_A = 1 << 7,
RS_SCISSOR = 1 << 2,
RS_DEPTH_TEST = 1 << 3,
RS_DEPTH_WRITE = 1 << 4,
RS_COLOR_WRITE_R = 1 << 5,
RS_COLOR_WRITE_G = 1 << 6,
RS_COLOR_WRITE_B = 1 << 7,
RS_COLOR_WRITE_A = 1 << 8,
RS_COLOR_WRITE = RS_COLOR_WRITE_R | RS_COLOR_WRITE_G | RS_COLOR_WRITE_B | RS_COLOR_WRITE_A,
RS_CULL_BACK = 1 << 8,
RS_CULL_FRONT = 1 << 9,
RS_CULL_BACK = 1 << 9,
RS_CULL_FRONT = 1 << 10,
RS_CULL = RS_CULL_BACK | RS_CULL_FRONT,
RS_BLEND_ALPHA = 1 << 10,
RS_BLEND_ADD = 1 << 11,
RS_BLEND_MULT = 1 << 12,
RS_BLEND_PREMULT = 1 << 13,
RS_BLEND_ALPHA = 1 << 11,
RS_BLEND_ADD = 1 << 12,
RS_BLEND_MULT = 1 << 13,
RS_BLEND_PREMULT = 1 << 14,
RS_BLEND = RS_BLEND_ALPHA | RS_BLEND_ADD | RS_BLEND_MULT | RS_BLEND_PREMULT,
RS_DISCARD = 1 << 14,
RS_DISCARD = 1 << 15,
};
// Texture image format
@@ -571,20 +572,10 @@ const char *UniformName[uMAX] = { SHADER_UNIFORMS(DECL_STR) };
enum CullMode { cmNone, cmBack, cmFront, cmMAX };
enum BlendMode { bmNone, bmAlpha, bmAdd, bmMult, bmPremult, bmMAX };
struct Viewport {
int x, y, width, height;
Viewport() : x(0), y(0), width(0), height(0) {}
Viewport(int x, int y, int width, int height) : x(x), y(y), width(width), height(height) {}
inline bool operator == (const Viewport &vp) const { return x == vp.x && y == vp.y && width == vp.width && height == vp.height; }
inline bool operator != (const Viewport &vp) const { return !(*this == vp); }
};
namespace Core {
float eye;
Texture *eyeTex[2];
Viewport viewport, viewportDef;
short4 viewport, viewportDef, scissor;
mat4 mModel, mView, mProj, mViewProj, mViewInv;
mat4 mLightProj;
Basis basis;
@@ -617,7 +608,8 @@ namespace Core {
int32 renderState;
uint32 targetFace;
uint32 targetOp;
Viewport viewport; // TODO: ivec4
short4 viewport; // x, y, width, height
short4 scissor; // x, y, width, height
vec4 material;
#ifdef _GAPI_GL
@@ -1008,6 +1000,14 @@ namespace Core {
renderState &= ~RS_VIEWPORT;
}
if (mask & RS_SCISSOR) {
if (scissor != active.scissor) {
active.scissor = scissor;
GAPI::setScissor(scissor);
}
renderState &= ~RS_SCISSOR;
}
if (mask & RS_DEPTH_TEST)
GAPI::setDepthTest((renderState & RS_DEPTH_TEST) != 0);
@@ -1038,19 +1038,18 @@ namespace Core {
GAPI::setClearColor(color);
}
void setViewport(const Viewport &vp) {
viewport = vp;
void setViewport(const short4 &v) {
viewport = v;
renderState |= RS_VIEWPORT;
}
void setViewport(int x, int y, int width, int height) {
setViewport(Viewport(x, y, width, height));
setViewport(short4(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 setScissor(const short4 &s) {
scissor = s;
renderState |= RS_SCISSOR;
}
void setCullMode(CullMode mode) {
@@ -1113,6 +1112,8 @@ namespace Core {
else
setViewport(0, 0, color->origWidth, color->origHeight);
setScissor(viewport);
reqTarget.texture = color;
reqTarget.op = op;
reqTarget.face = face;
@@ -1177,6 +1178,7 @@ namespace Core {
setViewport(Core::x, Core::y, Core::width, Core::height);
viewportDef = viewport;
scissor = viewport;
setCullMode(cmFront);
setBlendMode(bmAlpha);

View File

@@ -649,6 +649,7 @@ namespace GAPI {
{
D3D11_RASTERIZER_DESC desc;
memset(&desc, 0, sizeof(desc));
desc.ScissorEnable = TRUE;
desc.FrontCounterClockwise = TRUE;
desc.FillMode = D3D11_FILL_SOLID;
desc.CullMode = D3D11_CULL_NONE;
@@ -873,7 +874,7 @@ namespace GAPI {
deviceContext->OMSetRenderTargets(1, &RTV, DSV);
Core::active.viewport = Viewport(0, 0, 0, 0); // forcing viewport reset
Core::active.viewport = short4(0, 0, 0, 0); // forcing viewport reset
}
void discardTarget(bool color, bool depth) {}
@@ -925,7 +926,7 @@ namespace GAPI {
clearColor = color;
}
void setViewport(const Viewport &vp) {
void setViewport(const short4 &v) {
D3D11_VIEWPORT viewport;
viewport.TopLeftX = (FLOAT)x;
viewport.TopLeftY = (FLOAT)y;
@@ -933,9 +934,20 @@ namespace GAPI {
viewport.Height = (FLOAT)height;
viewport.MinDepth = 0.0f;
viewport.MaxDepth = 1.0f;
deviceContext->RSSetViewports(1, &viewport);
}
void setScissor(const short4 &s) {
D3D11_RECT scissor;
scissor.left = s.x;
scissor.top = active.viewport.w - (s.y + s.w);
scissor.right = s.x + s.z;
scissor.bottom = active.viewport.w - s.y;
deviceContext->RSSetScissorRects(1, &scissor);
}
void setDepthTest(bool enable) {
depthTest = enable;
dirtyDepthState = true;

View File

@@ -646,7 +646,8 @@ namespace GAPI {
surface->Release();
}
Core::active.viewport = Viewport(0, 0, 0, 0); // forcing viewport reset
Core::active.viewport = short4(0, 0, 0, 0); // forcing viewport reset
Core::active.scissor = short4(0, 0, 0, 0);
}
void discardTarget(bool color, bool depth) {}
@@ -684,23 +685,26 @@ namespace GAPI {
(int(color.w * 255) << 24);
}
void setViewport(const Viewport &vp) {
D3DVIEWPORT9 dv;
dv.X = vp.x;
dv.Y = vp.y;
dv.Width = vp.width;
dv.Height = vp.height;
dv.MinZ = 0.0f;
dv.MaxZ = 1.0f;
void setViewport(const short4 &v) {
D3DVIEWPORT9 viewport;
viewport.X = v.x;
viewport.Y = v.y;
viewport.Width = v.z;
viewport.Height = v.w;
viewport.MinZ = 0.0f;
viewport.MaxZ = 1.0f;
RECT ds;
ds.left = vp.x;
ds.top = vp.y;
ds.right = vp.x + vp.width;
ds.bottom = vp.y + vp.height;
device->SetViewport(&viewport);
}
device->SetViewport(&dv);
device->SetScissorRect(&ds);
void setScissor(const short4 &s) {
RECT scissor;
scissor.left = s.x;
scissor.top = active.viewport.w - (s.y + s.w);
scissor.right = s.x + s.z;
scissor.bottom = active.viewport.w - s.y;
device->SetScissorRect(&scissor);
}
void setDepthTest(bool enable) {

View File

@@ -1474,9 +1474,12 @@ namespace GAPI {
glClearColor(color.x, color.y, color.z, color.w);
}
void setViewport(const Viewport &vp) {
glViewport(vp.x, vp.y, vp.width, vp.height);
glScissor(vp.x, vp.y, vp.width, vp.height);
void setViewport(const short4 &v) {
glViewport(v.x, v.y, v.z, v.w);
}
void setScissor(const short4 &s) {
glScissor(s.x, s.y, s.z, s.w);
}
void setDepthTest(bool enable) {

View File

@@ -287,11 +287,13 @@ namespace GAPI {
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 setViewport(const short4 &v) {}
void setScissor(const short4 &s) {
swClipRect.x = s.x;
swClipRect.y = Core::active.viewport.w - (s.y + s.w);
swClipRect.z = s.x + s.z;
swClipRect.w = Core::active.viewport.w - s.y;
}
void setDepthTest(bool enable) {}
@@ -365,7 +367,7 @@ namespace GAPI {
x1 = swClipRect.x - x1;
S.z += dS.z * x1;
step(S, dS, x1);
x1 = Core::viewport.x;
x1 = swClipRect.x;
}
if (x2 > swClipRect.z) x2 = swClipRect.z;

View File

@@ -1846,6 +1846,19 @@ struct Level : IGame {
setMainLight(player);
}
short4 getPortalRect(const vec4 &v, int width, int height) {
//vec4 s = vec4(v.x, -v.w, v.z, -v.y);
vec4 s = v;
s = (s * 0.5 + 0.5) * vec4(float(width), float(height), float(width), float(height));
s.z -= s.x;
s.w -= s.y;
s.x = clamp(s.x, -16383.0f, 16383.0f);
s.y = clamp(s.y, -16383.0f, 16383.0f);
s.z = clamp(s.z, -16383.0f, 16383.0f);
s.w = clamp(s.w, -16383.0f, 16383.0f);
return short4(short(s.x), short(s.y), short(s.z), short(s.w));
}
void renderRooms(RoomDesc *roomsList, int roomsCount, int transp) {
PROFILE_MARKER("ROOMS");
@@ -1875,7 +1888,7 @@ struct Level : IGame {
atlasRooms->bind(sDiffuse);
Viewport vp = Core::viewport;
short4 vp = Core::scissor;
while (i != end) {
int roomIndex = roomsList[i].index;
@@ -1886,9 +1899,7 @@ struct Level : IGame {
continue;
}
#ifdef _GAPI_SW
Core::setViewport(roomsList[i].portal, vp.width, vp.height);
#endif
Core::setScissor(getPortalRect(roomsList[i].portal, vp.z, vp.w));
const TR::Room &room = level.rooms[roomIndex];
@@ -1930,9 +1941,7 @@ struct Level : IGame {
if (!range.sprites.iCount)
continue;
#ifdef _GAPI_SW
Core::setViewport(roomsList[i].portal, vp.width, vp.height);
#endif
Core::setScissor(getPortalRect(roomsList[i].portal, vp.z, vp.w));
setRoomParams(roomIndex, Shader::SPRITE, 1.0f, 1.0f, 0.0f, 1.0f, true);
@@ -1943,7 +1952,7 @@ struct Level : IGame {
}
}
Core::setViewport(vp);
Core::setScissor(vp);
Core::setBlendMode(bmNone);
}
@@ -2387,13 +2396,11 @@ struct Level : IGame {
TR::Room &room = level.rooms[to];
if (!room.flags.visible) {
if (Core::pass == Core::passCompose && water && waterCache && from != TR::NO_ROOM && (level.rooms[from].flags.water ^ level.rooms[to].flags.water))
waterCache->setVisible(from, to);
if (Core::pass == Core::passCompose && water && waterCache && from != TR::NO_ROOM && (level.rooms[from].flags.water ^ level.rooms[to].flags.water))
waterCache->setVisible(from, to);
room.flags.visible = true;
roomsList[roomsCount++] = RoomDesc(to, viewPort);
}
room.flags.visible = true;
roomsList[roomsCount++] = RoomDesc(to, viewPort);
vec4 clipPort;
for (int i = 0; i < room.portalsCount; i++) {
@@ -2947,11 +2954,11 @@ struct Level : IGame {
vH = Core::defaultTarget->height;
}
Viewport &vp = Core::viewportDef;
vp = Viewport(vX, vY, vW, vH);
short4 &vp = Core::viewportDef;
vp = short4(vX, vY, vW, vH);
if (players[1] != NULL && view >= 0) {
vp = Viewport(vX + vW / 2 * view, vY, vW / 2, vH);
vp = short4(vX + vW / 2 * view, vY, vW / 2, vH);
if (Core::settings.detail.stereo != Core::Settings::STEREO_SPLIT) {
aspect *= 0.5f;
@@ -2960,12 +2967,12 @@ struct Level : IGame {
if (Core::settings.detail.stereo == Core::Settings::STEREO_SBS) {
switch (eye) {
case -1 : vp = Viewport(vX + vp.x - vp.x / 2, vY + vp.y, vp.width / 2, vp.height); break;
case +1 : vp = Viewport(vX + vW / 2 + vp.x / 2, vY + vp.y, vp.width / 2, vp.height); break;
case -1 : vp = short4(vX + vp.x - vp.x / 2, vY + vp.y, vp.z / 2, vp.w); break;
case +1 : vp = short4(vX + vW / 2 + vp.x / 2, vY + vp.y, vp.z / 2, vp.w); break;
}
}
Core::setViewport(vp.x, vp.y, vp.width, vp.height);
Core::setViewport(vp.x, vp.y, vp.z, vp.w);
return aspect;
}
@@ -3056,7 +3063,7 @@ struct Level : IGame {
void renderEye(int eye, bool showUI, bool invBG) {
float oldEye = Core::eye;
Viewport oldViewport = Core::viewportDef;
short4 oldViewport = Core::viewportDef;
GAPI::Texture *oldTarget = Core::defaultTarget;
Core::eye = float(eye);
@@ -3104,7 +3111,7 @@ struct Level : IGame {
}
void renderGame(bool showUI, bool invBG) {
Viewport oldViewport = Core::viewportDef;
short4 oldViewport = Core::viewportDef;
GAPI::Texture *oldTarget = Core::defaultTarget;
bool upscale = !invBG && Core::settings.detail.scale != Core::Settings::SCALE_100;
@@ -3118,7 +3125,7 @@ struct Level : IGame {
scaleTex = new Texture(w, h, 1, FMT_RGBA, OPT_TARGET);
}
Core::defaultTarget = scaleTex;
Core::viewportDef = Viewport(0, 0, w, h);
Core::viewportDef = short4(0, 0, w, h);
}
if (Core::eye == 0.0f && Core::settings.detail.isStereo()) {