1
0
mirror of https://github.com/XProger/OpenLara.git synced 2025-08-12 16:14:25 +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() { Texture* getScreenTex() {
int w = Core::viewportDef.width; int w = Core::viewportDef.z;
int h = Core::viewportDef.height; int h = Core::viewportDef.w;
// get refraction texture // get refraction texture
if (!refract || w != refract->origWidth || h != refract->origHeight) { if (!refract || w != refract->origWidth || h != refract->origHeight) {
PROFILE_MARKER("WATER_REFRACT_INIT"); PROFILE_MARKER("WATER_REFRACT_INIT");
@@ -829,7 +829,7 @@ struct WaterCache {
blitTexture(screen, flip); blitTexture(screen, flip);
Core::setTarget(screen, NULL, RT_LOAD_COLOR | RT_LOAD_DEPTH | RT_STORE_COLOR); Core::setTarget(screen, NULL, RT_LOAD_COLOR | RT_LOAD_DEPTH | RT_STORE_COLOR);
} else { } 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 { enum RenderState {
RS_TARGET = 1 << 0, RS_TARGET = 1 << 0,
RS_VIEWPORT = 1 << 1, RS_VIEWPORT = 1 << 1,
RS_DEPTH_TEST = 1 << 2, RS_SCISSOR = 1 << 2,
RS_DEPTH_WRITE = 1 << 3, RS_DEPTH_TEST = 1 << 3,
RS_COLOR_WRITE_R = 1 << 4, RS_DEPTH_WRITE = 1 << 4,
RS_COLOR_WRITE_G = 1 << 5, RS_COLOR_WRITE_R = 1 << 5,
RS_COLOR_WRITE_B = 1 << 6, RS_COLOR_WRITE_G = 1 << 6,
RS_COLOR_WRITE_A = 1 << 7, 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_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_BACK = 1 << 9,
RS_CULL_FRONT = 1 << 9, RS_CULL_FRONT = 1 << 10,
RS_CULL = RS_CULL_BACK | RS_CULL_FRONT, RS_CULL = RS_CULL_BACK | RS_CULL_FRONT,
RS_BLEND_ALPHA = 1 << 10, RS_BLEND_ALPHA = 1 << 11,
RS_BLEND_ADD = 1 << 11, RS_BLEND_ADD = 1 << 12,
RS_BLEND_MULT = 1 << 12, RS_BLEND_MULT = 1 << 13,
RS_BLEND_PREMULT = 1 << 13, RS_BLEND_PREMULT = 1 << 14,
RS_BLEND = RS_BLEND_ALPHA | RS_BLEND_ADD | RS_BLEND_MULT | RS_BLEND_PREMULT, 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 // Texture image format
@@ -571,20 +572,10 @@ const char *UniformName[uMAX] = { SHADER_UNIFORMS(DECL_STR) };
enum CullMode { cmNone, cmBack, cmFront, cmMAX }; enum CullMode { cmNone, cmBack, cmFront, cmMAX };
enum BlendMode { bmNone, bmAlpha, bmAdd, bmMult, bmPremult, bmMAX }; 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 { namespace Core {
float eye; float eye;
Texture *eyeTex[2]; Texture *eyeTex[2];
Viewport viewport, viewportDef; short4 viewport, viewportDef, scissor;
mat4 mModel, mView, mProj, mViewProj, mViewInv; mat4 mModel, mView, mProj, mViewProj, mViewInv;
mat4 mLightProj; mat4 mLightProj;
Basis basis; Basis basis;
@@ -617,7 +608,8 @@ namespace Core {
int32 renderState; int32 renderState;
uint32 targetFace; uint32 targetFace;
uint32 targetOp; uint32 targetOp;
Viewport viewport; // TODO: ivec4 short4 viewport; // x, y, width, height
short4 scissor; // x, y, width, height
vec4 material; vec4 material;
#ifdef _GAPI_GL #ifdef _GAPI_GL
@@ -1008,6 +1000,14 @@ namespace Core {
renderState &= ~RS_VIEWPORT; 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) if (mask & RS_DEPTH_TEST)
GAPI::setDepthTest((renderState & RS_DEPTH_TEST) != 0); GAPI::setDepthTest((renderState & RS_DEPTH_TEST) != 0);
@@ -1038,19 +1038,18 @@ namespace Core {
GAPI::setClearColor(color); GAPI::setClearColor(color);
} }
void setViewport(const Viewport &vp) { void setViewport(const short4 &v) {
viewport = vp; viewport = v;
renderState |= RS_VIEWPORT; renderState |= RS_VIEWPORT;
} }
void setViewport(int x, int y, int width, int height) { 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) { void setScissor(const short4 &s) {
vec4 s = vec4(vp.x, -vp.w, vp.z, -vp.y); scissor = s;
s = (s * 0.5 + 0.5) * vec4(float(width), float(height), float(width), float(height)); renderState |= RS_SCISSOR;
setViewport(int(s.x), int(s.y), int(s.z) - int(s.x), int(s.w) - int(s.y));
} }
void setCullMode(CullMode mode) { void setCullMode(CullMode mode) {
@@ -1113,6 +1112,8 @@ namespace Core {
else else
setViewport(0, 0, color->origWidth, color->origHeight); setViewport(0, 0, color->origWidth, color->origHeight);
setScissor(viewport);
reqTarget.texture = color; reqTarget.texture = color;
reqTarget.op = op; reqTarget.op = op;
reqTarget.face = face; reqTarget.face = face;
@@ -1177,6 +1178,7 @@ namespace Core {
setViewport(Core::x, Core::y, Core::width, Core::height); setViewport(Core::x, Core::y, Core::width, Core::height);
viewportDef = viewport; viewportDef = viewport;
scissor = viewport;
setCullMode(cmFront); setCullMode(cmFront);
setBlendMode(bmAlpha); setBlendMode(bmAlpha);

View File

@@ -649,6 +649,7 @@ namespace GAPI {
{ {
D3D11_RASTERIZER_DESC desc; D3D11_RASTERIZER_DESC desc;
memset(&desc, 0, sizeof(desc)); memset(&desc, 0, sizeof(desc));
desc.ScissorEnable = TRUE;
desc.FrontCounterClockwise = TRUE; desc.FrontCounterClockwise = TRUE;
desc.FillMode = D3D11_FILL_SOLID; desc.FillMode = D3D11_FILL_SOLID;
desc.CullMode = D3D11_CULL_NONE; desc.CullMode = D3D11_CULL_NONE;
@@ -873,7 +874,7 @@ namespace GAPI {
deviceContext->OMSetRenderTargets(1, &RTV, DSV); 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) {} void discardTarget(bool color, bool depth) {}
@@ -925,7 +926,7 @@ namespace GAPI {
clearColor = color; clearColor = color;
} }
void setViewport(const Viewport &vp) { void setViewport(const short4 &v) {
D3D11_VIEWPORT viewport; D3D11_VIEWPORT viewport;
viewport.TopLeftX = (FLOAT)x; viewport.TopLeftX = (FLOAT)x;
viewport.TopLeftY = (FLOAT)y; viewport.TopLeftY = (FLOAT)y;
@@ -933,9 +934,20 @@ namespace GAPI {
viewport.Height = (FLOAT)height; viewport.Height = (FLOAT)height;
viewport.MinDepth = 0.0f; viewport.MinDepth = 0.0f;
viewport.MaxDepth = 1.0f; viewport.MaxDepth = 1.0f;
deviceContext->RSSetViewports(1, &viewport); 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) { void setDepthTest(bool enable) {
depthTest = enable; depthTest = enable;
dirtyDepthState = true; dirtyDepthState = true;

View File

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

View File

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

View File

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

View File

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