diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index fad134fc38..efbeab3b55 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1046,6 +1046,7 @@ add_executable( zdoom WIN32 gl/data/gl_data.cpp gl/data/gl_portaldata.cpp gl/data/gl_setup.cpp + gl/data/gl_matrix.cpp gl/data/gl_vertexbuffer.cpp gl/dynlights/a_dynlight.cpp gl/utility/gl_clock.cpp diff --git a/src/gl/data/gl_matrix.cpp b/src/gl/data/gl_matrix.cpp new file mode 100644 index 0000000000..589cfb8ccf --- /dev/null +++ b/src/gl/data/gl_matrix.cpp @@ -0,0 +1,496 @@ +/* -------------------------------------------------- + +Lighthouse3D + +VSMatrix - Very Simple Matrix Library + +http://www.lighthouse3d.com/very-simple-libs + +This is a simplified version of VSMatrix that has been adjusted for GZDoom's needs. + +----------------------------------------------------*/ + +#include "gl/system/gl_system.h" +#include +#include +#include +#include +#include "doomtype.h" +#include "gl/data/gl_matrix.h" + +static inline double +DegToRad(double degrees) +{ + return (double)(degrees * (M_PI / 180.0f)); +}; + +// sets the square matrix mat to the identity matrix, +// size refers to the number of rows (or columns) +void +VSMatrix::setIdentityMatrix( double *mat, int size) { + + // fill matrix with 0s + for (int i = 0; i < size * size; ++i) + mat[i] = 0.0f; + + // fill diagonal with 1s + for (int i = 0; i < size; ++i) + mat[i + i * size] = 1.0f; +} + + + +// glLoadIdentity implementation +void +VSMatrix::loadIdentity() +{ + // fill matrix with 0s + for (int i = 0; i < 16; ++i) + mMatrix[i] = 0.0f; + + // fill diagonal with 1s + for (int i = 0; i < 4; ++i) + mMatrix[i + i * 4] = 1.0f; +} + + +// glMultMatrix implementation +void +VSMatrix::multMatrix(const double *aMatrix) +{ + + double res[16]; + + for (int i = 0; i < 4; ++i) + { + for (int j = 0; j < 4; ++j) + { + res[j*4 + i] = 0.0f; + for (int k = 0; k < 4; ++k) + { + res[j*4 + i] += mMatrix[k*4 + i] * aMatrix[j*4 + k]; + } + } + } + memcpy(mMatrix, res, 16 * sizeof(double)); +} + +// glMultMatrix implementation +void +VSMatrix::multMatrix(const float *aMatrix) +{ + + double res[16]; + + for (int i = 0; i < 4; ++i) + { + for (int j = 0; j < 4; ++j) + { + res[j * 4 + i] = 0.0f; + for (int k = 0; k < 4; ++k) + { + res[j*4 + i] += mMatrix[k*4 + i] * aMatrix[j*4 + k]; + } + } + } + memcpy(mMatrix, res, 16 * sizeof(double)); +} + + + +// glLoadMatrix implementation +void +VSMatrix::loadMatrix(const double *aMatrix) +{ + memcpy(mMatrix, aMatrix, 16 * sizeof(double)); +} + +// glLoadMatrix implementation +void +VSMatrix::loadMatrix(const float *aMatrix) +{ + for (int i = 0; i < 16; ++i) + { + mMatrix[i] = aMatrix[i]; + } +} + + +// gl Translate implementation with matrix selection +void +VSMatrix::translate(double x, double y, double z) +{ + double mat[16]; + + setIdentityMatrix(mat); + mat[12] = x; + mat[13] = y; + mat[14] = z; + + multMatrix(mat); +} + + +// gl Scale implementation with matrix selection +void +VSMatrix::scale(double x, double y, double z) +{ + double mat[16]; + + setIdentityMatrix(mat,4); + mat[0] = x; + mat[5] = y; + mat[10] = z; + + multMatrix(mat); +} + + +// gl Rotate implementation with matrix selection +void +VSMatrix::rotate(double angle, double x, double y, double z) +{ + double mat[16]; + double v[3]; + + v[0] = x; + v[1] = y; + v[2] = z; + + double radAngle = DegToRad(angle); + double co = cos(radAngle); + double si = sin(radAngle); + normalize(v); + double x2 = v[0]*v[0]; + double y2 = v[1]*v[1]; + double z2 = v[2]*v[2]; + +// mat[0] = x2 + (y2 + z2) * co; + mat[0] = co + x2 * (1 - co);// + (y2 + z2) * co; + mat[4] = v[0] * v[1] * (1 - co) - v[2] * si; + mat[8] = v[0] * v[2] * (1 - co) + v[1] * si; + mat[12]= 0.0f; + + mat[1] = v[0] * v[1] * (1 - co) + v[2] * si; +// mat[5] = y2 + (x2 + z2) * co; + mat[5] = co + y2 * (1 - co); + mat[9] = v[1] * v[2] * (1 - co) - v[0] * si; + mat[13]= 0.0f; + + mat[2] = v[0] * v[2] * (1 - co) - v[1] * si; + mat[6] = v[1] * v[2] * (1 - co) + v[0] * si; +// mat[10]= z2 + (x2 + y2) * co; + mat[10]= co + z2 * (1 - co); + mat[14]= 0.0f; + + mat[3] = 0.0f; + mat[7] = 0.0f; + mat[11]= 0.0f; + mat[15]= 1.0f; + + multMatrix(mat); +} + + +// gluLookAt implementation +void +VSMatrix::lookAt(double xPos, double yPos, double zPos, + double xLook, double yLook, double zLook, + double xUp, double yUp, double zUp) +{ + double dir[3], right[3], up[3]; + + up[0] = xUp; up[1] = yUp; up[2] = zUp; + + dir[0] = (xLook - xPos); + dir[1] = (yLook - yPos); + dir[2] = (zLook - zPos); + normalize(dir); + + crossProduct(dir,up,right); + normalize(right); + + crossProduct(right,dir,up); + normalize(up); + + double m1[16],m2[16]; + + m1[0] = right[0]; + m1[4] = right[1]; + m1[8] = right[2]; + m1[12] = 0.0f; + + m1[1] = up[0]; + m1[5] = up[1]; + m1[9] = up[2]; + m1[13] = 0.0f; + + m1[2] = -dir[0]; + m1[6] = -dir[1]; + m1[10] = -dir[2]; + m1[14] = 0.0f; + + m1[3] = 0.0f; + m1[7] = 0.0f; + m1[11] = 0.0f; + m1[15] = 1.0f; + + setIdentityMatrix(m2,4); + m2[12] = -xPos; + m2[13] = -yPos; + m2[14] = -zPos; + + multMatrix(m1); + multMatrix(m2); +} + + +// gluPerspective implementation +void +VSMatrix::perspective(double fov, double ratio, double nearp, double farp) +{ + double projMatrix[16]; + + double f = 1.0f / tan (fov * (M_PI / 360.0f)); + + setIdentityMatrix(projMatrix,4); + + projMatrix[0] = f / ratio; + projMatrix[1 * 4 + 1] = f; + projMatrix[2 * 4 + 2] = (farp + nearp) / (nearp - farp); + projMatrix[3 * 4 + 2] = (2.0f * farp * nearp) / (nearp - farp); + projMatrix[2 * 4 + 3] = -1.0f; + projMatrix[3 * 4 + 3] = 0.0f; + + multMatrix(projMatrix); +} + + +// glOrtho implementation +void +VSMatrix::ortho(double left, double right, + double bottom, double top, + double nearp, double farp) +{ + double m[16]; + + setIdentityMatrix(m,4); + + m[0 * 4 + 0] = 2 / (right - left); + m[1 * 4 + 1] = 2 / (top - bottom); + m[2 * 4 + 2] = -2 / (farp - nearp); + m[3 * 4 + 0] = -(right + left) / (right - left); + m[3 * 4 + 1] = -(top + bottom) / (top - bottom); + m[3 * 4 + 2] = -(farp + nearp) / (farp - nearp); + + multMatrix(m); +} + + +// glFrustum implementation +void +VSMatrix::frustum(double left, double right, + double bottom, double top, + double nearp, double farp) +{ + double m[16]; + + setIdentityMatrix(m,4); + + m[0 * 4 + 0] = 2 * nearp / (right-left); + m[1 * 4 + 1] = 2 * nearp / (top - bottom); + m[2 * 4 + 0] = (right + left) / (right - left); + m[2 * 4 + 1] = (top + bottom) / (top - bottom); + m[2 * 4 + 2] = - (farp + nearp) / (farp - nearp); + m[2 * 4 + 3] = -1.0f; + m[3 * 4 + 2] = - 2 * farp * nearp / (farp-nearp); + m[3 * 4 + 3] = 0.0f; + + multMatrix(m); +} + + +/* +// returns a pointer to the requested matrix +double * +VSMatrix::get(MatrixTypes aType) +{ + return mMatrix[aType]; +} +*/ + + +/* ----------------------------------------------------- + SEND MATRICES TO OPENGL +------------------------------------------------------*/ + + + + +// universal +void +VSMatrix::matrixToGL(int loc) +{ + float copyto[16]; + copy(copyto); + glUniformMatrix4fv(loc, 1, false, copyto); +} + +// ----------------------------------------------------- +// AUX functions +// ----------------------------------------------------- + + +// Compute res = M * point +void +VSMatrix::multMatrixPoint(const double *point, double *res) +{ + + for (int i = 0; i < 4; ++i) + { + + res[i] = 0.0f; + + for (int j = 0; j < 4; j++) { + + res[i] += point[j] * mMatrix[j*4 + i]; + } + } +} + +// res = a cross b; +void +VSMatrix::crossProduct(const double *a, const double *b, double *res) { + + res[0] = a[1] * b[2] - b[1] * a[2]; + res[1] = a[2] * b[0] - b[2] * a[0]; + res[2] = a[0] * b[1] - b[0] * a[1]; +} + + +// returns a . b +double +VSMatrix::dotProduct(const double *a, const double *b) { + + double res = a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; + + return res; +} + + +// Normalize a vec3 +void +VSMatrix::normalize(double *a) { + + double mag = sqrt(a[0] * a[0] + a[1] * a[1] + a[2] * a[2]); + + a[0] /= mag; + a[1] /= mag; + a[2] /= mag; +} + + +// res = b - a +void +VSMatrix::subtract(const double *a, const double *b, double *res) { + + res[0] = b[0] - a[0]; + res[1] = b[1] - a[1]; + res[2] = b[2] - a[2]; +} + + +// res = a + b +void +VSMatrix::add(const double *a, const double *b, double *res) { + + res[0] = b[0] + a[0]; + res[1] = b[1] + a[1]; + res[2] = b[2] + a[2]; +} + + +// returns |a| +double +VSMatrix::length(const double *a) { + + return(sqrt(a[0] * a[0] + a[1] * a[1] + a[2] * a[2])); + +} + + +static inline int +M3(int i, int j) +{ + return (i*3+j); +}; + + + +// computes the derived normal matrix for the view matrix +void +VSMatrix::computeNormalMatrix(const double *aMatrix) +{ + + double mMat3x3[9]; + + mMat3x3[0] = aMatrix[0]; + mMat3x3[1] = aMatrix[1]; + mMat3x3[2] = aMatrix[2]; + + mMat3x3[3] = aMatrix[4]; + mMat3x3[4] = aMatrix[5]; + mMat3x3[5] = aMatrix[6]; + + mMat3x3[6] = aMatrix[8]; + mMat3x3[7] = aMatrix[9]; + mMat3x3[8] = aMatrix[10]; + + double det, invDet; + + det = mMat3x3[0] * (mMat3x3[4] * mMat3x3[8] - mMat3x3[5] * mMat3x3[7]) + + mMat3x3[1] * (mMat3x3[5] * mMat3x3[6] - mMat3x3[8] * mMat3x3[3]) + + mMat3x3[2] * (mMat3x3[3] * mMat3x3[7] - mMat3x3[4] * mMat3x3[6]); + + invDet = 1.0f/det; + + mMatrix[0] = (mMat3x3[4] * mMat3x3[8] - mMat3x3[5] * mMat3x3[7]) * invDet; + mMatrix[1] = (mMat3x3[5] * mMat3x3[6] - mMat3x3[8] * mMat3x3[3]) * invDet; + mMatrix[2] = (mMat3x3[3] * mMat3x3[7] - mMat3x3[4] * mMat3x3[6]) * invDet; + mMatrix[3] = 0.0f; + mMatrix[4] = (mMat3x3[2] * mMat3x3[7] - mMat3x3[1] * mMat3x3[8]) * invDet; + mMatrix[5] = (mMat3x3[0] * mMat3x3[8] - mMat3x3[2] * mMat3x3[6]) * invDet; + mMatrix[6] = (mMat3x3[1] * mMat3x3[6] - mMat3x3[7] * mMat3x3[0]) * invDet; + mMatrix[7] = 0.0f; + mMatrix[8] = (mMat3x3[1] * mMat3x3[5] - mMat3x3[4] * mMat3x3[2]) * invDet; + mMatrix[9] = (mMat3x3[2] * mMat3x3[3] - mMat3x3[0] * mMat3x3[5]) * invDet; + mMatrix[10] =(mMat3x3[0] * mMat3x3[4] - mMat3x3[3] * mMat3x3[1]) * invDet; + mMatrix[11] = 0.0; + mMatrix[12] = 0.0; + mMatrix[13] = 0.0; + mMatrix[14] = 0.0; + mMatrix[15] = 1.0; + +} + + +// aux function resMat = resMat * aMatrix +void +VSMatrix::multMatrix(double *resMat, const double *aMatrix) +{ + + double res[16]; + + for (int i = 0; i < 4; ++i) + { + for (int j = 0; j < 4; ++j) + { + res[j*4 + i] = 0.0f; + for (int k = 0; k < 4; ++k) + { + res[j*4 + i] += resMat[k*4 + i] * aMatrix[j*4 + k]; + } + } + } + memcpy(resMat, res, 16 * sizeof(double)); +} diff --git a/src/gl/data/gl_matrix.h b/src/gl/data/gl_matrix.h new file mode 100644 index 0000000000..1ccbc5c378 --- /dev/null +++ b/src/gl/data/gl_matrix.h @@ -0,0 +1,93 @@ + +// Matrix class based on code from VSML: + +/** ---------------------------------------------------------- + * \class VSMathLib + * + * Lighthouse3D + * + * VSMathLib - Very Simple Matrix Library + * + * Full documentation at + * http://www.lighthouse3d.com/very-simple-libs + * + * This class aims at easing geometric transforms, camera + * placement and projection definition for programmers + * working with OpenGL core versions. + * + * + ---------------------------------------------------------------*/ +#ifndef __VSMatrix__ +#define __VSMatrix__ + +#include + +class VSMatrix { + + public: + + VSMatrix() + { + } + + VSMatrix(int) + { + loadIdentity(); + } + + void translate(double x, double y, double z); + void scale(double x, double y, double z); + void rotate(double angle, double x, double y, double z); + void loadIdentity(); + void multMatrix(const float *aMatrix); + void multMatrix(const double *aMatrix); + void multMatrix(const VSMatrix &aMatrix) + { + multMatrix(aMatrix.mMatrix); + } + void loadMatrix(const double *aMatrix); + void loadMatrix(const float *aMatrix); + void lookAt(double xPos, double yPos, double zPos, double xLook, double yLook, double zLook, double xUp, double yUp, double zUp); + void perspective(double fov, double ratio, double nearp, double farp); + void ortho(double left, double right, double bottom, double top, double nearp=-1.0f, double farp=1.0f); + void frustum(double left, double right, double bottom, double top, double nearp, double farp); + void copy(double * pDest) + { + memcpy(pDest, mMatrix, 16 * sizeof(double)); + } + + void copy(float * pDest) + { + for (int i = 0; i < 16; i++) + { + pDest[i] = (float)mMatrix[i]; + } + } + + void matrixToGL(int location); + void multMatrixPoint(const double *point, double *res); + + void computeNormalMatrix(const float *aMatrix); + void computeNormalMatrix(const double *aMatrix); + void computeNormalMatrix(const VSMatrix &aMatrix) + { + computeNormalMatrix(aMatrix.mMatrix); + } + + protected: + static void crossProduct(const double *a, const double *b, double *res); + static double dotProduct(const double *a, const double * b); + static void normalize(double *a); + static void subtract(const double *a, const double *b, double *res); + static void add(const double *a, const double *b, double *res); + static double length(const double *a); + static void multMatrix(double *resMatrix, const double *aMatrix); + + static void setIdentityMatrix(double *mat, int size = 4); + + /// The storage for matrices + double mMatrix[16]; + +}; + +#endif \ No newline at end of file diff --git a/src/gl/renderer/gl_renderstate.cpp b/src/gl/renderer/gl_renderstate.cpp index 64647b6700..83b630c915 100644 --- a/src/gl/renderer/gl_renderstate.cpp +++ b/src/gl/renderer/gl_renderstate.cpp @@ -83,6 +83,7 @@ void FRenderState::Reset() mColormapState = CM_DEFAULT; mLightParms[3] = -1.f; mSpecialEffect = EFF_NONE; + mClipHeight = 0.f; } @@ -114,12 +115,13 @@ bool FRenderState::ApplyShader() } else { + // todo: check how performance is affected by using 'discard' in a shader and if necessary create a separate set of discard-less shaders. activeShader = GLRenderer->mShaderManager->Get(mTextureEnabled ? mEffectState : 4); activeShader->Bind(); } int fogset = 0; - //glColor4fv(mColor.vec); + if (mFogEnabled) { if ((mFogColor & 0xffffff) == 0) @@ -143,6 +145,7 @@ bool FRenderState::ApplyShader() activeShader->muObjectColor.Set(mObjectColor); activeShader->muDynLightColor.Set(mDynColor.vec); activeShader->muInterpolationFactor.Set(mInterpolationFactor); + activeShader->muClipHeight.Set(mClipHeight); if (mGlowEnabled) { diff --git a/src/gl/renderer/gl_renderstate.h b/src/gl/renderer/gl_renderstate.h index f569c3eab5..6653a7c0d9 100644 --- a/src/gl/renderer/gl_renderstate.h +++ b/src/gl/renderer/gl_renderstate.h @@ -57,6 +57,7 @@ class FRenderState int mBlendEquation; bool m2D; float mInterpolationFactor; + float mClipHeight; FVertexBuffer *mVertexBuffer, *mCurrentVertexBuffer; FStateVec4 mColor; @@ -100,6 +101,16 @@ public: mCurrentVertexBuffer = NULL; } + void SetClipHeight(float clip) + { + mClipHeight = clip; + } + + float GetClipHeight() + { + return mClipHeight; + } + void SetColor(float r, float g, float b, float a = 1.f, int desat = 0) { mColor.Set(r, g, b, a); diff --git a/src/gl/scene/gl_portal.cpp b/src/gl/scene/gl_portal.cpp index a7400ec226..276679b74c 100644 --- a/src/gl/scene/gl_portal.cpp +++ b/src/gl/scene/gl_portal.cpp @@ -79,6 +79,7 @@ EXTERN_CVAR(Bool, gl_noquery) EXTERN_CVAR(Int, r_mirror_recursions) TArray GLPortal::portals; +TArray GLPortal::planestack; int GLPortal::recursion; int GLPortal::MirrorFlag; int GLPortal::PlaneMirrorFlag; @@ -200,6 +201,7 @@ bool GLPortal::Start(bool usestencil, bool doquery) glStencilFunc(GL_EQUAL,recursion,~0); // create stencil glStencilOp(GL_KEEP,GL_KEEP,GL_INCR); // increment stencil of valid pixels glColorMask(0,0,0,0); // don't write to the graphics buffer + gl_RenderState.SetEffect(EFF_STENCIL); gl_RenderState.EnableTexture(false); gl_RenderState.ResetColor(); glDepthFunc(GL_LESS); @@ -235,7 +237,8 @@ bool GLPortal::Start(bool usestencil, bool doquery) gl_RenderState.EnableTexture(true); glDepthFunc(GL_LESS); glColorMask(1,1,1,1); - glDepthRange(0,1); + gl_RenderState.SetEffect(EFF_NONE); + glDepthRange(0, 1); GLuint sampleCount; @@ -264,6 +267,7 @@ bool GLPortal::Start(bool usestencil, bool doquery) glStencilOp(GL_KEEP,GL_KEEP,GL_KEEP); // this stage doesn't modify the stencil gl_RenderState.EnableTexture(true); glColorMask(1,1,1,1); + gl_RenderState.SetEffect(EFF_NONE); glDisable(GL_DEPTH_TEST); glDepthMask(false); // don't write to Z-buffer! } @@ -283,9 +287,8 @@ bool GLPortal::Start(bool usestencil, bool doquery) glDisable(GL_DEPTH_TEST); } } - // The clip plane from the previous portal must be deactivated for this one. - clipsave = glIsEnabled(GL_CLIP_PLANE0+renderdepth-1); - if (clipsave) glDisable(GL_CLIP_PLANE0+renderdepth-1); + planestack.Push(gl_RenderState.GetClipHeight()); + gl_RenderState.SetClipHeight(0.f); // save viewpoint savedviewx=viewx; @@ -345,7 +348,11 @@ void GLPortal::End(bool usestencil) PortalAll.Clock(); GLRenderer->mCurrentPortal = NextPortal; - if (clipsave) glEnable (GL_CLIP_PLANE0+renderdepth-1); + + float f; + planestack.Pop(f); + gl_RenderState.SetClipHeight(f); + if (usestencil) { if (needdepth) FDrawInfo::EndDrawInfo(); @@ -360,6 +367,7 @@ void GLPortal::End(bool usestencil) GLRenderer->SetupView(viewx, viewy, viewz, viewangle, !!(MirrorFlag&1), !!(PlaneMirrorFlag&1)); glColorMask(0,0,0,0); // no graphics + gl_RenderState.SetEffect(EFF_NONE); gl_RenderState.ResetColor(); gl_RenderState.EnableTexture(false); gl_RenderState.Apply(); @@ -386,7 +394,8 @@ void GLPortal::End(bool usestencil) gl_RenderState.EnableTexture(true); - glColorMask(1,1,1,1); + gl_RenderState.SetEffect(EFF_NONE); + glColorMask(1, 1, 1, 1); recursion--; // restore old stencil op. @@ -421,8 +430,10 @@ void GLPortal::End(bool usestencil) glDepthFunc(GL_LEQUAL); glDepthRange(0,1); glColorMask(0,0,0,0); // no graphics + gl_RenderState.SetEffect(EFF_STENCIL); gl_RenderState.EnableTexture(false); DrawPortalStencil(); + gl_RenderState.SetEffect(EFF_NONE); gl_RenderState.EnableTexture(true); glColorMask(1,1,1,1); glDepthFunc(GL_LESS); @@ -778,18 +789,16 @@ void GLPlaneMirrorPortal::DrawContents() validcount++; + float f = FIXED2FLOAT(planez); + if (PlaneMirrorMode < 0) f -= 65536.f; // ceiling mirror: clip everytihng with a z lower than the portal's ceiling + else f += 65536.f; // floor mirror: clip everything with a z higher than the portal's floor + gl_RenderState.SetClipHeight(f); + PlaneMirrorFlag++; GLRenderer->SetupView(viewx, viewy, viewz, viewangle, !!(MirrorFlag&1), !!(PlaneMirrorFlag&1)); ClearClipper(); - glEnable(GL_CLIP_PLANE0+renderdepth); - // This only works properly for non-sloped planes so don't bother with the math. - //double d[4]={origin->a/65536., origin->c/65536., origin->b/65536., FIXED2FLOAT(origin->d)}; - double d[4]={0, static_cast(PlaneMirrorMode), 0, FIXED2FLOAT(origin->d)}; - glClipPlane(GL_CLIP_PLANE0+renderdepth, d); - GLRenderer->DrawScene(); - glDisable(GL_CLIP_PLANE0+renderdepth); PlaneMirrorFlag--; PlaneMirrorMode=old_pm; } @@ -988,12 +997,12 @@ void GLHorizonPortal::DrawContents() gltexture->Bind(); + bool pushed = gl_SetPlaneTextureRotation(sp, gltexture); gl_RenderState.EnableAlphaTest(false); gl_RenderState.BlendFunc(GL_ONE,GL_ZERO); gl_RenderState.Apply(); - bool pushed = gl_SetPlaneTextureRotation(sp, gltexture); float vx=FIXED2FLOAT(viewx); float vy=FIXED2FLOAT(viewy); diff --git a/src/gl/scene/gl_portal.h b/src/gl/scene/gl_portal.h index 970fc3523b..ccc6d174d9 100644 --- a/src/gl/scene/gl_portal.h +++ b/src/gl/scene/gl_portal.h @@ -82,6 +82,7 @@ class GLPortal static int recursion; static unsigned int QueryObject; protected: + static TArray planestack; static int MirrorFlag; static int PlaneMirrorFlag; static int renderdepth; @@ -101,7 +102,6 @@ private: angle_t savedviewangle; AActor * savedviewactor; area_t savedviewarea; - unsigned char clipsave; GLPortal *NextPortal; TArray savedmapsection; TArray mPrimIndices; diff --git a/src/gl/shaders/gl_shader.cpp b/src/gl/shaders/gl_shader.cpp index a15d5a1068..f3b4834615 100644 --- a/src/gl/shaders/gl_shader.cpp +++ b/src/gl/shaders/gl_shader.cpp @@ -200,6 +200,7 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char * muGlowTopPlane.Init(hShader, "uGlowTopPlane"); muFixedColormap.Init(hShader, "uFixedColormap"); muInterpolationFactor.Init(hShader, "uInterpolationFactor"); + muClipHeight.Init(hShader, "uClipHeight"); timer_index = glGetUniformLocation(hShader, "timer"); lights_index = glGetUniformLocation(hShader, "lights"); diff --git a/src/gl/shaders/gl_shader.h b/src/gl/shaders/gl_shader.h index 833f97fbb3..eea46c8c80 100644 --- a/src/gl/shaders/gl_shader.h +++ b/src/gl/shaders/gl_shader.h @@ -193,6 +193,7 @@ class FShader FUniform4f muGlowBottomPlane; FUniform4f muGlowTopPlane; FBufferedUniform1f muInterpolationFactor; + FBufferedUniform1f muClipHeight; int timer_index; int lights_index; diff --git a/wadsrc/static/shaders/glsl/fogboundary.fp b/wadsrc/static/shaders/glsl/fogboundary.fp index 0d4fb9a0d9..264f8e8cd6 100644 --- a/wadsrc/static/shaders/glsl/fogboundary.fp +++ b/wadsrc/static/shaders/glsl/fogboundary.fp @@ -9,6 +9,12 @@ in vec2 glowdist; void main() { +#ifndef NO_DISCARD + // clip plane emulation for plane reflections. These are always perfectly horizontal so a simple check of the pixelpos's y coordinate is sufficient. + if (pixelpos.y > uClipHeight + 65536.0) discard; + if (pixelpos.y < uClipHeight - 65536.0) discard; +#endif + float fogdist; float fogfactor; diff --git a/wadsrc/static/shaders/glsl/main.fp b/wadsrc/static/shaders/glsl/main.fp index afd075984f..4677233305 100644 --- a/wadsrc/static/shaders/glsl/main.fp +++ b/wadsrc/static/shaders/glsl/main.fp @@ -216,6 +216,12 @@ vec4 applyFog(vec4 frag, float fogfactor) void main() { +#ifndef NO_DISCARD + // clip plane emulation for plane reflections. These are always perfectly horizontal so a simple check of the pixelpos's y coordinate is sufficient. + if (pixelpos.y > uClipHeight + 65536.0) discard; + if (pixelpos.y < uClipHeight - 65536.0) discard; +#endif + vec4 frag = ProcessTexel(); switch (uFixedColormap) diff --git a/wadsrc/static/shaders/glsl/shaderdefs.i b/wadsrc/static/shaders/glsl/shaderdefs.i index 5a36473bf3..198992fe6d 100644 --- a/wadsrc/static/shaders/glsl/shaderdefs.i +++ b/wadsrc/static/shaders/glsl/shaderdefs.i @@ -1,6 +1,7 @@ // This file contains common data definitions for both vertex and fragment shader uniform vec4 uCameraPos; +uniform float uClipHeight; uniform int uTextureMode; diff --git a/wadsrc/static/shaders/glsl/stencil.fp b/wadsrc/static/shaders/glsl/stencil.fp index 9e4afec041..7cc579d9ef 100644 --- a/wadsrc/static/shaders/glsl/stencil.fp +++ b/wadsrc/static/shaders/glsl/stencil.fp @@ -2,6 +2,12 @@ in vec4 pixelpos; void main() { +#ifndef NO_DISCARD + // clip plane emulation for plane reflections. These are always perfectly horizontal so a simple check of the pixelpos's y coordinate is sufficient. + if (pixelpos.y > uClipHeight + 65536.0) discard; + if (pixelpos.y < uClipHeight - 65536.0) discard; +#endif + gl_FragColor = vec4(1.0); }