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:
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
66
src/core.h
66
src/core.h
@@ -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);
|
||||
|
@@ -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;
|
||||
|
@@ -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) {
|
||||
|
@@ -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) {
|
||||
|
@@ -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;
|
||||
|
||||
|
53
src/level.h
53
src/level.h
@@ -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()) {
|
||||
|
Reference in New Issue
Block a user