From 00fcf4bc06d1af43990bb08ca51c5fa1f3986f05 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 13 Jul 2014 13:25:42 +0200 Subject: [PATCH] - for some reason using world coordinates for clipping in the shader is somewhat imprecise so the clip plane heights have to be adjusted a bit for it. --- src/gl/renderer/gl_renderstate.cpp | 6 ++++-- src/gl/renderer/gl_renderstate.h | 20 +++++++++++++++----- src/gl/scene/gl_portal.cpp | 16 ++++++++++------ src/gl/shaders/gl_shader.cpp | 22 +++++++++++++++------- src/gl/shaders/gl_shader.h | 5 +++-- wadsrc/static/shaders/glsl/fogboundary.fp | 4 ++-- wadsrc/static/shaders/glsl/main.fp | 4 ++-- wadsrc/static/shaders/glsl/shaderdefs.i | 2 +- 8 files changed, 52 insertions(+), 27 deletions(-) diff --git a/src/gl/renderer/gl_renderstate.cpp b/src/gl/renderer/gl_renderstate.cpp index 83b630c91..6a510f85a 100644 --- a/src/gl/renderer/gl_renderstate.cpp +++ b/src/gl/renderer/gl_renderstate.cpp @@ -83,7 +83,8 @@ void FRenderState::Reset() mColormapState = CM_DEFAULT; mLightParms[3] = -1.f; mSpecialEffect = EFF_NONE; - mClipHeight = 0.f; + mClipHeightTop = 65536.f; + mClipHeightBottom = -65536.f; } @@ -145,7 +146,8 @@ bool FRenderState::ApplyShader() activeShader->muObjectColor.Set(mObjectColor); activeShader->muDynLightColor.Set(mDynColor.vec); activeShader->muInterpolationFactor.Set(mInterpolationFactor); - activeShader->muClipHeight.Set(mClipHeight); + activeShader->muClipHeightTop.Set(mClipHeightTop); + activeShader->muClipHeightBottom.Set(mClipHeightBottom); if (mGlowEnabled) { diff --git a/src/gl/renderer/gl_renderstate.h b/src/gl/renderer/gl_renderstate.h index 6653a7c0d..815974d97 100644 --- a/src/gl/renderer/gl_renderstate.h +++ b/src/gl/renderer/gl_renderstate.h @@ -57,7 +57,7 @@ class FRenderState int mBlendEquation; bool m2D; float mInterpolationFactor; - float mClipHeight; + float mClipHeightTop, mClipHeightBottom; FVertexBuffer *mVertexBuffer, *mCurrentVertexBuffer; FStateVec4 mColor; @@ -101,14 +101,24 @@ public: mCurrentVertexBuffer = NULL; } - void SetClipHeight(float clip) + void SetClipHeightTop(float clip) { - mClipHeight = clip; + mClipHeightTop = clip; } - float GetClipHeight() + float GetClipHeightTop() { - return mClipHeight; + return mClipHeightTop; + } + + void SetClipHeightBottom(float clip) + { + mClipHeightBottom = clip; + } + + float GetClipHeightBottom() + { + return mClipHeightBottom; } void SetColor(float r, float g, float b, float a = 1.f, int desat = 0) diff --git a/src/gl/scene/gl_portal.cpp b/src/gl/scene/gl_portal.cpp index 276679b74..28b9a1282 100644 --- a/src/gl/scene/gl_portal.cpp +++ b/src/gl/scene/gl_portal.cpp @@ -287,8 +287,10 @@ bool GLPortal::Start(bool usestencil, bool doquery) glDisable(GL_DEPTH_TEST); } } - planestack.Push(gl_RenderState.GetClipHeight()); - gl_RenderState.SetClipHeight(0.f); + planestack.Push(gl_RenderState.GetClipHeightTop()); + planestack.Push(gl_RenderState.GetClipHeightBottom()); + gl_RenderState.SetClipHeightTop(65536.f); + gl_RenderState.SetClipHeightBottom(-65536.f); // save viewpoint savedviewx=viewx; @@ -351,7 +353,9 @@ void GLPortal::End(bool usestencil) float f; planestack.Pop(f); - gl_RenderState.SetClipHeight(f); + gl_RenderState.SetClipHeightBottom(f); + planestack.Pop(f); + gl_RenderState.SetClipHeightTop(f); if (usestencil) { @@ -790,9 +794,9 @@ 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); + // the coordinate fudging is needed because for some reason this is nowhere near precise and leaves gaps. Strange... + if (PlaneMirrorMode < 0) gl_RenderState.SetClipHeightTop(f+0.3f); // ceiling mirror: clip everytihng with a z lower than the portal's ceiling + else gl_RenderState.SetClipHeightBottom(f-0.3f); // floor mirror: clip everything with a z higher than the portal's floor PlaneMirrorFlag++; GLRenderer->SetupView(viewx, viewy, viewz, viewangle, !!(MirrorFlag&1), !!(PlaneMirrorFlag&1)); diff --git a/src/gl/shaders/gl_shader.cpp b/src/gl/shaders/gl_shader.cpp index f3b483461..50b67c4ca 100644 --- a/src/gl/shaders/gl_shader.cpp +++ b/src/gl/shaders/gl_shader.cpp @@ -200,7 +200,8 @@ 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"); + muClipHeightTop.Init(hShader, "uClipHeightTop"); + muClipHeightBottom.Init(hShader, "uClipHeightBottom"); timer_index = glGetUniformLocation(hShader, "timer"); lights_index = glGetUniformLocation(hShader, "lights"); @@ -249,16 +250,18 @@ bool FShader::Bind() // //========================================================================== -FShader *FShaderManager::Compile (const char *ShaderName, const char *ShaderPath) +FShader *FShaderManager::Compile (const char *ShaderName, const char *ShaderPath, bool usediscard) { + FString defines; // this can't be in the shader code due to ATI strangeness. - const char *str = (gl.MaxLights() == 128)? "#define MAXLIGHTS128\n" : ""; + if (gl.MaxLights() == 128) defines += "#define MAXLIGHTS128\n"; + if (!usediscard) defines += "#define NO_DISCARD\n"; FShader *shader = NULL; try { shader = new FShader(ShaderName); - if (!shader->Load(ShaderName, "shaders/glsl/main.vp", "shaders/glsl/main.fp", ShaderPath, str)) + if (!shader->Load(ShaderName, "shaders/glsl/main.vp", "shaders/glsl/main.fp", ShaderPath, defines.GetChars())) { I_FatalError("Unable to load shader %s\n", ShaderName); } @@ -352,11 +355,16 @@ FShaderManager::~FShaderManager() void FShaderManager::CompileShaders() { - mActiveShader = mEffectShaders[0] = mEffectShaders[1] = NULL; + mActiveShader = NULL; + + for (int i = 0; i < MAX_EFFECTS; i++) + { + mEffectShaders[i] = NULL; + } for(int i=0;defaultshaders[i].ShaderName != NULL;i++) { - FShader *shc = Compile(defaultshaders[i].ShaderName, defaultshaders[i].gettexelfunc); + FShader *shc = Compile(defaultshaders[i].ShaderName, defaultshaders[i].gettexelfunc, true); mTextureEffects.Push(shc); } @@ -365,7 +373,7 @@ void FShaderManager::CompileShaders() FString name = ExtractFileBase(usershaders[i]); FName sfn = name; - FShader *shc = Compile(sfn, usershaders[i]); + FShader *shc = Compile(sfn, usershaders[i], true); mTextureEffects.Push(shc); } diff --git a/src/gl/shaders/gl_shader.h b/src/gl/shaders/gl_shader.h index eea46c8c8..da3be18cb 100644 --- a/src/gl/shaders/gl_shader.h +++ b/src/gl/shaders/gl_shader.h @@ -193,7 +193,8 @@ class FShader FUniform4f muGlowBottomPlane; FUniform4f muGlowTopPlane; FBufferedUniform1f muInterpolationFactor; - FBufferedUniform1f muClipHeight; + FBufferedUniform1f muClipHeightTop; + FBufferedUniform1f muClipHeightBottom; int timer_index; int lights_index; @@ -244,7 +245,7 @@ class FShaderManager public: FShaderManager(); ~FShaderManager(); - FShader *Compile(const char *ShaderName, const char *ShaderPath); + FShader *Compile(const char *ShaderName, const char *ShaderPath, bool usediscard); int Find(const char *mame); FShader *BindEffect(int effect); void SetActiveShader(FShader *sh); diff --git a/wadsrc/static/shaders/glsl/fogboundary.fp b/wadsrc/static/shaders/glsl/fogboundary.fp index 264f8e8cd..edf9384c6 100644 --- a/wadsrc/static/shaders/glsl/fogboundary.fp +++ b/wadsrc/static/shaders/glsl/fogboundary.fp @@ -11,8 +11,8 @@ 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; + if (pixelpos.y > uClipHeightTop) discard; + if (pixelpos.y < uClipHeightBottom) discard; #endif float fogdist; diff --git a/wadsrc/static/shaders/glsl/main.fp b/wadsrc/static/shaders/glsl/main.fp index 467723330..5655493bd 100644 --- a/wadsrc/static/shaders/glsl/main.fp +++ b/wadsrc/static/shaders/glsl/main.fp @@ -218,8 +218,8 @@ 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; + if (pixelpos.y > uClipHeightTop) discard; + if (pixelpos.y < uClipHeightBottom) discard; #endif vec4 frag = ProcessTexel(); diff --git a/wadsrc/static/shaders/glsl/shaderdefs.i b/wadsrc/static/shaders/glsl/shaderdefs.i index 198992fe6..d281ee231 100644 --- a/wadsrc/static/shaders/glsl/shaderdefs.i +++ b/wadsrc/static/shaders/glsl/shaderdefs.i @@ -1,7 +1,7 @@ // This file contains common data definitions for both vertex and fragment shader uniform vec4 uCameraPos; -uniform float uClipHeight; +uniform float uClipHeightTop, uClipHeightBottom; uniform int uTextureMode;