diff --git a/src/gl/renderer/gl_renderstate.cpp b/src/gl/renderer/gl_renderstate.cpp index 8913504c..5ab55408 100644 --- a/src/gl/renderer/gl_renderstate.cpp +++ b/src/gl/renderer/gl_renderstate.cpp @@ -47,6 +47,7 @@ FRenderState gl_RenderState; int FStateAttr::ChangeCounter; extern FShader *FogboundaryShader; +extern FShader *SpheremapShader; @@ -118,14 +119,23 @@ bool FRenderState::ApplyShader() bool useshaders = false; FShader *activeShader = NULL; - - if (mFogboundaryEnabled) // the fog boundary shader is special + switch (mSpecialEffect) { + case EFF_FOGBOUNDARY: FogboundaryShader->Bind(0); activeShader = FogboundaryShader; - } - else - { + break; + + case EFF_SPHEREMAP: + if (gl.shadermodel == 4 || (gl.shadermodel == 3 && gl_fog_shader)) + { + SpheremapShader->Bind(0); + activeShader = SpheremapShader; + } + break; + + default: + switch (gl.shadermodel) { case 2: @@ -142,7 +152,6 @@ bool FRenderState::ApplyShader() break; case 4: - // useshaders = true; useshaders = ( mEffectState != 0 || // special shaders (mFogEnabled && gl_fogmode != 0) || // fog requires a shader @@ -167,6 +176,7 @@ bool FRenderState::ApplyShader() } } } + if (activeShader) { int fogset = 0; @@ -262,6 +272,33 @@ void FRenderState::Apply(bool forcenoshader) ffFogDensity=mFogDensity; } } + if (mSpecialEffect != ffSpecialEffect) + { + switch (ffSpecialEffect) + { + case EFF_SPHEREMAP: + gl.Disable(GL_TEXTURE_GEN_T); + gl.Disable(GL_TEXTURE_GEN_S); + + default: + break; + } + switch (mSpecialEffect) + { + case EFF_SPHEREMAP: + // Use sphere mapping for this + gl.Enable(GL_TEXTURE_GEN_T); + gl.Enable(GL_TEXTURE_GEN_S); + gl.TexGeni(GL_S,GL_TEXTURE_GEN_MODE,GL_SPHERE_MAP); + gl.TexGeni(GL_T,GL_TEXTURE_GEN_MODE,GL_SPHERE_MAP); + break; + + default: + break; + } + ffSpecialEffect = mSpecialEffect; + } } + } diff --git a/src/gl/renderer/gl_renderstate.h b/src/gl/renderer/gl_renderstate.h index 8a9c0abe..46aac048 100644 --- a/src/gl/renderer/gl_renderstate.h +++ b/src/gl/renderer/gl_renderstate.h @@ -37,6 +37,14 @@ struct FStateVec3 : public FStateAttr } }; + +enum EEffect +{ + EFF_NONE, + EFF_FOGBOUNDARY, + EFF_SPHEREMAP, +}; + class FRenderState { bool mTextureEnabled; @@ -44,7 +52,7 @@ class FRenderState bool mGlowEnabled; bool mLightEnabled; bool mBrightmapEnabled; - bool mFogboundaryEnabled; + int mSpecialEffect; int mTextureMode; float mLightParms[2]; @@ -60,6 +68,7 @@ class FRenderState bool ffTextureEnabled; bool ffFogEnabled; int ffTextureMode; + int ffSpecialEffect; PalEntry ffFogColor; float ffFogDensity; @@ -73,8 +82,9 @@ public: void Reset() { - mFogboundaryEnabled = mTextureEnabled = mBrightmapEnabled = mFogEnabled = mGlowEnabled = mLightEnabled = false; + mTextureEnabled = mBrightmapEnabled = mFogEnabled = mGlowEnabled = mLightEnabled = false; ffTextureEnabled = ffFogEnabled = false; + mSpecialEffect = ffSpecialEffect = EFF_NONE; mFogColor.d = ffFogColor.d = -1; mFogDensity = ffFogDensity = 0; mTextureMode = ffTextureMode = -1; @@ -98,9 +108,9 @@ public: mFogEnabled = on; } - void EnableFogboundary(bool on) + void SetEffect(int eff) { - mFogboundaryEnabled = on; + mSpecialEffect = eff; } void EnableGlow(bool on) diff --git a/src/gl/scene/gl_walls_draw.cpp b/src/gl/scene/gl_walls_draw.cpp index 6365a575..3cbe24cb 100644 --- a/src/gl/scene/gl_walls_draw.cpp +++ b/src/gl/scene/gl_walls_draw.cpp @@ -203,11 +203,11 @@ void GLWall::RenderFogBoundary() { int rel = rellight + (extralight * gl_weaponlight); gl_SetFog(lightlevel, rel, &Colormap, false); - gl_RenderState.EnableFogboundary(true); + gl_RenderState.SetEffect(EFF_FOGBOUNDARY); gl.Disable(GL_ALPHA_TEST); RenderWall(0, NULL); gl.Enable(GL_ALPHA_TEST); - gl_RenderState.EnableFogboundary(false); + gl_RenderState.SetEffect(EFF_NONE); } else { @@ -254,11 +254,12 @@ void GLWall::RenderMirrorSurface() { if (GLRenderer->mirrortexture == NULL) return; + Vector v(glseg.y2-glseg.y1, 0 ,-glseg.x2+glseg.x1); + v.Normalize(); + glNormal3fv(&v[0]); + // Use sphere mapping for this - gl.Enable(GL_TEXTURE_GEN_T); - gl.Enable(GL_TEXTURE_GEN_S); - gl.TexGeni(GL_S,GL_TEXTURE_GEN_MODE,GL_SPHERE_MAP); - gl.TexGeni(GL_T,GL_TEXTURE_GEN_MODE,GL_SPHERE_MAP); + gl_RenderState.SetEffect(EFF_SPHEREMAP); gl_SetColor(lightlevel, 0, &Colormap ,0.1f); gl.BlendFunc(GL_SRC_ALPHA,GL_ONE); @@ -270,11 +271,10 @@ void GLWall::RenderMirrorSurface() pat->BindPatch(Colormap.colormap, 0); flags &= ~GLWF_GLOW; - flags |= GLWF_NOSHADER; + //flags |= GLWF_NOSHADER; RenderWall(0,NULL); - gl.Disable(GL_TEXTURE_GEN_T); - gl.Disable(GL_TEXTURE_GEN_S); + gl_RenderState.SetEffect(EFF_NONE); // Restore the defaults for the translucent pass gl.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); diff --git a/src/gl/shaders/gl_shader.cpp b/src/gl/shaders/gl_shader.cpp index 23e45412..9cc4afc4 100644 --- a/src/gl/shaders/gl_shader.cpp +++ b/src/gl/shaders/gl_shader.cpp @@ -369,6 +369,7 @@ static FDefaultShader defaultshaders[]= static TArray AllContainers; FShader *FogboundaryShader; +FShader *SpheremapShader; //========================================================================== // @@ -428,6 +429,13 @@ void GLShader::Initialize() delete FogboundaryShader; FogboundaryShader = NULL; } + + SpheremapShader = new FShader(); + if (!SpheremapShader->Load("spheremap", "shaders/glsl/main_spheremap.vp", "shaders/glsl/main.fp", "shaders/glsl/func_normal.fp", "#define NO_GLOW\n#define NO_DESATURATE\n")) + { + delete SpheremapShader; + SpheremapShader = NULL; + } } void GLShader::Clear() @@ -443,6 +451,7 @@ void GLShader::Clear() AllContainers.Clear(); AllShaders.Clear(); delete FogboundaryShader; + delete SpheremapShader; } GLShader *GLShader::Find(const char * shn) diff --git a/wadsrc/static/shaders/glsl/main_spheremap.vp b/wadsrc/static/shaders/glsl/main_spheremap.vp new file mode 100644 index 00000000..9ad097dd --- /dev/null +++ b/wadsrc/static/shaders/glsl/main_spheremap.vp @@ -0,0 +1,35 @@ +#ifndef NO_FOG + varying vec4 pixelpos; +#endif +#ifndef NO_GLOW + varying vec2 glowdist; + attribute vec2 glowdistance; +#endif + + +void main() +{ + vec4 eyeCoordPos = gl_ModelViewMatrix * gl_Vertex; + + gl_FrontColor = gl_Color; + + #ifndef NO_FOG + pixelpos.xyz = gl_Vertex.xyz; + pixelpos.w = -eyeCoordPos.z/eyeCoordPos.w; + #endif + + #ifndef NO_GLOW + glowdist = glowdistance; + #endif + + vec3 u = normalize(eyeCoordPos.xyz); + vec3 n = normalize(gl_NormalMatrix * gl_Normal); + vec3 r = reflect(u, n); + float m = 2.0 * sqrt( r.x*r.x + r.y*r.y + (r.z+1.0)*(r.z+1.0) ); + gl_TexCoord[0].st = vec2(r.x/m + 0.5, r.y/m + 0.5); + + gl_Position = ftransform(); + #ifdef __GLSL_CG_DATA_TYPES + gl_ClipVertex = eyeCoordPos; + #endif +}