From b34d7f9e086693e20ec703ceb07d3fe6e3e3c5fd Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 5 Apr 2018 23:08:09 +0200 Subject: [PATCH] - added a software scene drawer to the GL renderer. It still looks like shit and only works on the modern render path but at least the basics are working. --- src/CMakeLists.txt | 1 + src/d_main.cpp | 14 +- src/doomtype.h | 1 + src/g_statusbar/sbar.h | 1 - src/g_statusbar/shared_sbar.cpp | 24 --- src/gl/compatibility/gl_20.cpp | 2 +- src/gl/data/gl_vertexbuffer.cpp | 14 +- src/gl/renderer/gl_renderer.cpp | 215 ++++++++++++++++++---- src/gl/renderer/gl_renderer.h | 3 + src/gl/renderer/gl_renderstate.h | 1 + src/gl/scene/gl_scene.cpp | 144 ++------------- src/gl/scene/gl_swscene.cpp | 127 +++++++++++++ src/gl/shaders/gl_shader.cpp | 1 + src/gl/system/gl_framebuffer.cpp | 4 + src/gl/textures/gl_hwtexture.cpp | 80 +++++++- src/gl/textures/gl_hwtexture.h | 5 + src/gl/textures/gl_material.cpp | 19 +- src/gl/textures/gl_material.h | 10 +- src/polyrenderer/poly_renderer.cpp | 25 +-- src/polyrenderer/poly_renderer.h | 2 +- src/r_renderer.h | 3 +- src/swrenderer/r_swrenderer.cpp | 6 +- src/swrenderer/r_swrenderer.h | 2 +- src/swrenderer/scene/r_scene.cpp | 64 ++++--- src/swrenderer/scene/r_scene.h | 2 +- src/v_2ddrawer.cpp | 1 - src/v_2ddrawer.h | 1 - src/v_video.cpp | 6 + src/v_video.h | 24 +-- wadsrc/static/shaders/glsl/swshader.fp | 31 ++++ wadsrc/static/shaders/swgl/swshadergl2.fp | 32 ++++ wadsrc/static/shaders/swgl/swshadergl2.vp | 6 + 32 files changed, 569 insertions(+), 302 deletions(-) create mode 100644 src/gl/scene/gl_swscene.cpp create mode 100644 wadsrc/static/shaders/glsl/swshader.fp create mode 100644 wadsrc/static/shaders/swgl/swshadergl2.fp create mode 100644 wadsrc/static/shaders/swgl/swshadergl2.vp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b3bf5a2529..1977f1e069 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -852,6 +852,7 @@ set( FASTMATH_SOURCES gl/scene/gl_renderhacks.cpp gl/scene/gl_weapon.cpp gl/scene/gl_scene.cpp + gl/scene/gl_swscene.cpp gl/scene/gl_sky.cpp gl/scene/gl_portal.cpp gl/scene/gl_walls_draw.cpp diff --git a/src/d_main.cpp b/src/d_main.cpp index 6d82111acc..253ea6b8a0 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -794,23 +794,11 @@ void D_Display () break; } - if (StatusBar != NULL) - { - float blend[4] = { 0, 0, 0, 0 }; - StatusBar->BlendView (blend); - } - screen->SetBlendingRect(viewwindowx, viewwindowy, - viewwindowx + viewwidth, viewwindowy + viewheight); - // [ZZ] execute event hook that we just started the frame //E_RenderFrame(); // screen->RenderView(&players[consoleplayer]); - - screen->Begin2D(viewactive); - // todo: These need to go into RenderView. - //Renderer->DrawRemainingPlayerSprites(); - //screen->DrawBlendingRect(); + // returns with 2S mode set. if (automapactive) { AM_Drawer (hud_althud? viewheight : StatusBar->GetTopOfStatusbar()); diff --git a/src/doomtype.h b/src/doomtype.h index 8235e08f3e..da2620a7cb 100644 --- a/src/doomtype.h +++ b/src/doomtype.h @@ -196,6 +196,7 @@ enum class ETextureType : uint8_t SkinGraphic, Null, FirstDefined, + SWCanvas, }; class FTextureID diff --git a/src/g_statusbar/sbar.h b/src/g_statusbar/sbar.h index 31a33a99f1..a0f8edbdaf 100644 --- a/src/g_statusbar/sbar.h +++ b/src/g_statusbar/sbar.h @@ -405,7 +405,6 @@ public: void AttachToPlayer(player_t *player); DVector2 GetHUDScale() const; virtual void FlashCrosshair (); - virtual void BlendView (float blend[4]); void NewGame (); virtual void ScreenSizeChanged (); void CallScreenSizeChanged(); diff --git a/src/g_statusbar/shared_sbar.cpp b/src/g_statusbar/shared_sbar.cpp index 588ee6bf30..535f018565 100644 --- a/src/g_statusbar/shared_sbar.cpp +++ b/src/g_statusbar/shared_sbar.cpp @@ -95,10 +95,6 @@ extern int setblocks; FTexture *CrosshairImage; static int CrosshairNum; -// [RH] Base blending values (for e.g. underwater) -int BaseBlendR, BaseBlendG, BaseBlendB; -float BaseBlendA; - CVAR (Int, paletteflash, 0, CVAR_ARCHIVE) CVAR (Flag, pf_hexenweaps, paletteflash, PF_HEXENWEAPONS) CVAR (Flag, pf_poison, paletteflash, PF_POISON) @@ -1196,26 +1192,6 @@ void DBaseStatusBar::DrawTopStuff (EHudState state) } } -//--------------------------------------------------------------------------- -// -// BlendView -// -//--------------------------------------------------------------------------- - -void DBaseStatusBar::BlendView (float blend[4]) -{ - // [Nash] Allow user to set blend intensity - float cnt = (BaseBlendA * underwater_fade_scalar); - - V_AddBlend (BaseBlendR / 255.f, BaseBlendG / 255.f, BaseBlendB / 255.f, cnt, blend); - V_AddPlayerBlend(CPlayer, blend, 1.0f, 228); - - player_t *player = (CPlayer->camera != NULL && CPlayer->camera->player != NULL) ? CPlayer->camera->player : CPlayer; - V_AddBlend (player->BlendR, player->BlendG, player->BlendB, player->BlendA, blend); - - V_SetBlend ((int)(blend[0] * 255.0f), (int)(blend[1] * 255.0f), - (int)(blend[2] * 255.0f), (int)(blend[3] * 256.0f)); -} void DBaseStatusBar::DrawConsistancy () const { diff --git a/src/gl/compatibility/gl_20.cpp b/src/gl/compatibility/gl_20.cpp index afe9eb8672..ae8037d296 100644 --- a/src/gl/compatibility/gl_20.cpp +++ b/src/gl/compatibility/gl_20.cpp @@ -208,7 +208,7 @@ static bool currentModelMatrixState; void FRenderState::ApplyFixedFunction() { - int thistm = mTextureMode == TM_MODULATE && mTempTM == TM_OPAQUE ? TM_OPAQUE : mTextureMode; + int thistm = mTextureMode == TM_MODULATE && (mTempTM == TM_OPAQUE || mSpecialEffect == EFF_SWQUAD) ? TM_OPAQUE : mTextureMode; if (thistm != ffTextureMode) { ffTextureMode = thistm; diff --git a/src/gl/data/gl_vertexbuffer.cpp b/src/gl/data/gl_vertexbuffer.cpp index 54bb85a039..d40564386e 100644 --- a/src/gl/data/gl_vertexbuffer.cpp +++ b/src/gl/data/gl_vertexbuffer.cpp @@ -169,9 +169,9 @@ FFlatVertexBuffer::FFlatVertexBuffer(int width, int height) // and the second one for the fullscreen quad used for blend overlays. vbo_shadowdata[4].Set(0, 0, 0, 0, 0); - vbo_shadowdata[5].Set(0, (float)height, 0, 0, 0); - vbo_shadowdata[6].Set((float)width, 0, 0, 0, 0); - vbo_shadowdata[7].Set((float)width, (float)height, 0, 0, 0); + vbo_shadowdata[5].Set(0, (float)height, 0, 0, 1); + vbo_shadowdata[6].Set((float)width, 0, 0, 1, 0); + vbo_shadowdata[7].Set((float)width, (float)height, 0, 1, 1); // and this is for the postprocessing copy operation vbo_shadowdata[8].Set(-1.0f, -1.0f, 0, 0.0f, 0.0f); @@ -217,10 +217,10 @@ FFlatVertexBuffer::~FFlatVertexBuffer() void FFlatVertexBuffer::OutputResized(int width, int height) { vbo_shadowdata[4].Set(0, 0, 0, 0, 0); - vbo_shadowdata[5].Set(0, (float)height, 0, 0, 0); - vbo_shadowdata[6].Set((float)width, 0, 0, 0, 0); - vbo_shadowdata[7].Set((float)width, (float)height, 0, 0, 0); - + vbo_shadowdata[5].Set(0, (float)height, 0, 0, 1); + vbo_shadowdata[6].Set((float)width, 0, 0, 1, 0); + vbo_shadowdata[7].Set((float)width, (float)height, 0, 1, 1); + Map(); memcpy(&map[4], &vbo_shadowdata[4], 4 * sizeof(FFlatVertex)); Unmap(); diff --git a/src/gl/renderer/gl_renderer.cpp b/src/gl/renderer/gl_renderer.cpp index 5cadae2eae..c6496102c5 100644 --- a/src/gl/renderer/gl_renderer.cpp +++ b/src/gl/renderer/gl_renderer.cpp @@ -51,6 +51,7 @@ #include "gl/data/gl_vertexbuffer.h" #include "gl/scene/gl_drawinfo.h" #include "gl/scene/gl_scenedrawer.h" +#include "gl/scene/gl_swscene.h" #include "gl/scene/gl_portal.h" #include "gl/shaders/gl_shader.h" #include "gl/shaders/gl_ambientshader.h" @@ -75,6 +76,8 @@ EXTERN_CVAR(Int, screenblocks) EXTERN_CVAR(Bool, cl_capfps) +EXTERN_CVAR(Float, underwater_fade_scalar) +EXTERN_CVAR(Bool, swtruecolor) CVAR(Bool, gl_scale_viewport, true, CVAR_ARCHIVE); extern bool NoInterpolateView; @@ -206,6 +209,7 @@ FGLRenderer::~FGLRenderer() glBindVertexArray(0); glDeleteVertexArrays(1, &mVAOID); } + if (swdrawer) delete swdrawer; if (mBuffers) delete mBuffers; if (mPresentShader) delete mPresentShader; if (mLinearDepthShader) delete mLinearDepthShader; @@ -423,55 +427,63 @@ void FGLRenderer::EndOffscreen() // renders the view // //----------------------------------------------------------------------------- +extern int currentrenderer; void FGLRenderer::RenderView(player_t* player) { - // Todo: This needs to call the software renderer and process the returned image, if so desired. - checkBenchActive(); - gl_RenderState.SetVertexBuffer(mVBO); mVBO->Reset(); - // reset statistics counters - ResetProfilingData(); - - // Get this before everything else - if (cl_capfps || r_NoInterpolate) r_viewpoint.TicFrac = 1.; - else r_viewpoint.TicFrac = I_GetTimeFrac(); - - P_FindParticleSubsectors(); - - if (!gl.legacyMode) mLights->Clear(); - - // NoInterpolateView should have no bearing on camera textures, but needs to be preserved for the main view below. - bool saved_niv = NoInterpolateView; - NoInterpolateView = false; - // prepare all camera textures that have been used in the last frame - FCanvasTextureInfo::UpdateAll(); - NoInterpolateView = saved_niv; - - - // now render the main view - float fovratio; - float ratio = r_viewwindow.WidescreenRatio; - if (r_viewwindow.WidescreenRatio >= 1.3f) + if (currentrenderer == 0) { - fovratio = 1.333333f; + if (swdrawer == nullptr) swdrawer = new SWSceneDrawer; + swdrawer->RenderView(player); } else { - fovratio = ratio; + checkBenchActive(); + + // reset statistics counters + ResetProfilingData(); + + // Get this before everything else + if (cl_capfps || r_NoInterpolate) r_viewpoint.TicFrac = 1.; + else r_viewpoint.TicFrac = I_GetTimeFrac(); + + P_FindParticleSubsectors(); + + if (!gl.legacyMode) mLights->Clear(); + + // NoInterpolateView should have no bearing on camera textures, but needs to be preserved for the main view below. + bool saved_niv = NoInterpolateView; + NoInterpolateView = false; + // prepare all camera textures that have been used in the last frame + FCanvasTextureInfo::UpdateAll(); + NoInterpolateView = saved_niv; + + + // now render the main view + float fovratio; + float ratio = r_viewwindow.WidescreenRatio; + if (r_viewwindow.WidescreenRatio >= 1.3f) + { + fovratio = 1.333333f; + } + else + { + fovratio = ratio; + } + // Check if there's some lights. If not some code can be skipped. + TThinkerIterator it(STAT_DLIGHT); + mLightCount = ((it.Next()) != NULL); + + GLSceneDrawer drawer; + + drawer.SetFixedColormap(player); + + mShadowMap.Update(); + sector_t * viewsector = drawer.RenderViewpoint(player->camera, NULL, r_viewpoint.FieldOfView.Degrees, ratio, fovratio, true, true); } - GLSceneDrawer drawer; - - drawer.SetFixedColormap(player); - - // Check if there's some lights. If not some code can be skipped. - TThinkerIterator it(STAT_DLIGHT); - mLightCount = ((it.Next()) != NULL); - - mShadowMap.Update(); - sector_t * viewsector = drawer.RenderViewpoint(player->camera, NULL, r_viewpoint.FieldOfView.Degrees, ratio, fovratio, true, true); All.Unclock(); } @@ -534,6 +546,127 @@ void FGLRenderer::WriteSavePic(player_t *player, FileWriter *file, int width, in } +void gl_FillScreen() +{ + gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f); + gl_RenderState.EnableTexture(false); + gl_RenderState.Apply(); + // The fullscreen quad is stored at index 4 in the main vertex buffer. + GLRenderer->mVBO->RenderArray(GL_TRIANGLE_STRIP, FFlatVertexBuffer::FULLSCREEN_INDEX, 4); +} + +//========================================================================== +// +// Draws a blend over the entire view +// +//========================================================================== +void FGLRenderer::DrawBlend(sector_t * viewsector, bool FixedColormap, bool docolormap) +{ + float blend[4] = { 0,0,0,0 }; + PalEntry blendv = 0; + float extra_red; + float extra_green; + float extra_blue; + player_t *player = NULL; + + if (players[consoleplayer].camera != NULL) + { + player = players[consoleplayer].camera->player; + } + + // don't draw sector based blends when an invulnerability colormap is active + if (!FixedColormap) + { + if (!viewsector->e->XFloor.ffloors.Size()) + { + if (viewsector->heightsec && !(viewsector->MoreFlags&SECF_IGNOREHEIGHTSEC)) + { + auto s = viewsector->heightsec; + blendv = s->floorplane.PointOnSide(r_viewpoint.Pos) < 0? s->bottommap : s->ceilingplane.PointOnSide(r_viewpoint.Pos) < 0 ? s->topmap : s->midmap; + } + } + else + { + TArray & lightlist = viewsector->e->XFloor.lightlist; + + for (unsigned int i = 0; i < lightlist.Size(); i++) + { + double lightbottom; + if (i < lightlist.Size() - 1) + lightbottom = lightlist[i + 1].plane.ZatPoint(r_viewpoint.Pos); + else + lightbottom = viewsector->floorplane.ZatPoint(r_viewpoint.Pos); + + if (lightbottom < r_viewpoint.Pos.Z && (!lightlist[i].caster || !(lightlist[i].caster->flags&FF_FADEWALLS))) + { + // 3d floor 'fog' is rendered as a blending value + blendv = lightlist[i].blend; + // If this is the same as the sector's it doesn't apply! + if (blendv == viewsector->Colormap.FadeColor) blendv = 0; + // a little hack to make this work for Legacy maps. + if (blendv.a == 0 && blendv != 0) blendv.a = 128; + break; + } + } + } + + if (blendv.a == 0 && docolormap) + { + blendv = R_BlendForColormap(blendv); + } + + if (blendv.a == 255) + { + + extra_red = blendv.r / 255.0f; + extra_green = blendv.g / 255.0f; + extra_blue = blendv.b / 255.0f; + + // If this is a multiplicative blend do it separately and add the additive ones on top of it. + blendv = 0; + + // black multiplicative blends are ignored + if (extra_red || extra_green || extra_blue) + { + gl_RenderState.BlendFunc(GL_DST_COLOR, GL_ZERO); + gl_RenderState.SetColor(extra_red, extra_green, extra_blue, 1.0f); + gl_FillScreen(); + } + } + else if (blendv.a) + { + // [Nash] allow user to set blend intensity + int cnt = blendv.a; + cnt = (int)(cnt * underwater_fade_scalar); + + V_AddBlend(blendv.r / 255.f, blendv.g / 255.f, blendv.b / 255.f, cnt / 255.0f, blend); + } + } + + if (player) + { + V_AddPlayerBlend(player, blend, 0.5, 175); + } + + if (players[consoleplayer].camera != NULL) + { + // except for fadeto effects + player_t *player = (players[consoleplayer].camera->player != NULL) ? players[consoleplayer].camera->player : &players[consoleplayer]; + V_AddBlend(player->BlendR, player->BlendG, player->BlendB, player->BlendA, blend); + } + + gl_RenderState.SetTextureMode(TM_MODULATE); + gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + if (blend[3]>0.0f) + { + gl_RenderState.SetColor(blend[0], blend[1], blend[2], blend[3]); + gl_FillScreen(); + } + gl_RenderState.ResetColor(); + gl_RenderState.EnableTexture(true); +} + + //=========================================================================== // // Vertex buffer for 2D drawer @@ -690,6 +823,11 @@ void FGLRenderer::Draw2D(F2DDrawer *drawer) gl_RenderState.mTextureMatrix.translate(0.f, 1.f, 0.0f); gl_RenderState.EnableTextureMatrix(true); } + if (cmd.mTexture->UseType == ETextureType::SWCanvas) + { + //gl_RenderState.SetTextureMode(swtruecolor ? 0 : 1); + //gl_RenderState.SetEffect(EFF_SWQUAD); + } } else { @@ -717,6 +855,7 @@ void FGLRenderer::Draw2D(F2DDrawer *drawer) break; } + gl_RenderState.SetEffect(EFF_NONE); gl_RenderState.EnableTextureMatrix(false); } glDisable(GL_SCISSOR_TEST); diff --git a/src/gl/renderer/gl_renderer.h b/src/gl/renderer/gl_renderer.h index e372dc05d0..59b18d2f47 100644 --- a/src/gl/renderer/gl_renderer.h +++ b/src/gl/renderer/gl_renderer.h @@ -45,6 +45,7 @@ class FHardwareTexture; class FShadowMapShader; class FCustomPostProcessShaders; class GLSceneDrawer; +class SWSceneDrawer; inline float DEG2RAD(float deg) { @@ -146,6 +147,7 @@ public: FFlatVertexBuffer *mVBO; FSkyVertexBuffer *mSkyVBO; FLightBuffer *mLights; + SWSceneDrawer *swdrawer = nullptr; GL_IRECT mScreenViewport; GL_IRECT mSceneViewport; @@ -191,6 +193,7 @@ public: void RenderTextureView(FCanvasTexture *tex, AActor *Viewpoint, double FOV); void WriteSavePic(player_t *player, FileWriter *file, int width, int height); void RenderView(player_t *player); + void DrawBlend(sector_t * viewsector, bool FixedColormap, bool docolormap); bool StartOffscreen(); diff --git a/src/gl/renderer/gl_renderstate.h b/src/gl/renderer/gl_renderstate.h index f946beafb0..d6b6606509 100644 --- a/src/gl/renderer/gl_renderstate.h +++ b/src/gl/renderer/gl_renderstate.h @@ -59,6 +59,7 @@ enum EEffect EFF_SPHEREMAP, EFF_BURN, EFF_STENCIL, + EFF_SWQUAD, MAX_EFFECTS }; diff --git a/src/gl/scene/gl_scene.cpp b/src/gl/scene/gl_scene.cpp index fc5b281271..67d683aa7b 100644 --- a/src/gl/scene/gl_scene.cpp +++ b/src/gl/scene/gl_scene.cpp @@ -79,7 +79,6 @@ CVAR(Bool, gl_sort_textures, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) EXTERN_CVAR (Bool, cl_capfps) EXTERN_CVAR (Bool, r_deathcamera) -EXTERN_CVAR (Float, underwater_fade_scalar) EXTERN_CVAR (Float, r_visibility) EXTERN_CVAR (Bool, gl_legacy_mode) EXTERN_CVAR (Bool, r_drawvoxels) @@ -515,138 +514,6 @@ void GLSceneDrawer::DrawScene(int drawmode) RenderTranslucent(); } - -void gl_FillScreen() -{ - gl_RenderState.AlphaFunc(GL_GEQUAL, 0.f); - gl_RenderState.EnableTexture(false); - gl_RenderState.Apply(); - // The fullscreen quad is stored at index 4 in the main vertex buffer. - GLRenderer->mVBO->RenderArray(GL_TRIANGLE_STRIP, FFlatVertexBuffer::FULLSCREEN_INDEX, 4); -} - -//========================================================================== -// -// Draws a blend over the entire view -// -//========================================================================== -void GLSceneDrawer::DrawBlend(sector_t * viewsector) -{ - float blend[4]={0,0,0,0}; - PalEntry blendv=0; - float extra_red; - float extra_green; - float extra_blue; - player_t *player = NULL; - - if (players[consoleplayer].camera != NULL) - { - player=players[consoleplayer].camera->player; - } - - // don't draw sector based blends when an invulnerability colormap is active - if (!FixedColormap) - { - if (!viewsector->e->XFloor.ffloors.Size()) - { - if (viewsector->heightsec && !(viewsector->MoreFlags&SECF_IGNOREHEIGHTSEC)) - { - switch (in_area) - { - default: - case area_normal: blendv = viewsector->heightsec->midmap; break; - case area_above: blendv = viewsector->heightsec->topmap; break; - case area_below: blendv = viewsector->heightsec->bottommap; break; - } - } - } - else - { - TArray & lightlist = viewsector->e->XFloor.lightlist; - - for (unsigned int i = 0; i < lightlist.Size(); i++) - { - double lightbottom; - if (i < lightlist.Size() - 1) - lightbottom = lightlist[i + 1].plane.ZatPoint(r_viewpoint.Pos); - else - lightbottom = viewsector->floorplane.ZatPoint(r_viewpoint.Pos); - - if (lightbottom < r_viewpoint.Pos.Z && (!lightlist[i].caster || !(lightlist[i].caster->flags&FF_FADEWALLS))) - { - // 3d floor 'fog' is rendered as a blending value - blendv = lightlist[i].blend; - // If this is the same as the sector's it doesn't apply! - if (blendv == viewsector->Colormap.FadeColor) blendv = 0; - // a little hack to make this work for Legacy maps. - if (blendv.a == 0 && blendv != 0) blendv.a = 128; - break; - } - } - } - - if (blendv.a == 0) - { - blendv = R_BlendForColormap(blendv); - } - - if (blendv.a == 255) - { - - extra_red = blendv.r / 255.0f; - extra_green = blendv.g / 255.0f; - extra_blue = blendv.b / 255.0f; - - // If this is a multiplicative blend do it separately and add the additive ones on top of it. - blendv = 0; - - // black multiplicative blends are ignored - if (extra_red || extra_green || extra_blue) - { - gl_RenderState.BlendFunc(GL_DST_COLOR, GL_ZERO); - gl_RenderState.SetColor(extra_red, extra_green, extra_blue, 1.0f); - gl_FillScreen(); - } - } - else if (blendv.a) - { - // [Nash] allow user to set blend intensity - int cnt = blendv.a; - cnt = (int)(cnt * underwater_fade_scalar); - - V_AddBlend(blendv.r / 255.f, blendv.g / 255.f, blendv.b / 255.f, cnt / 255.0f, blend); - } - } - - // This mostly duplicates the code in shared_sbar.cpp - // When I was writing this the original was called too late so that I - // couldn't get the blend in time. However, since then I made some changes - // here that would get lost if I switched back so I won't do it. - - if (player) - { - V_AddPlayerBlend(player, blend, 0.5, 175); - } - - if (players[consoleplayer].camera != NULL) - { - // except for fadeto effects - player_t *player = (players[consoleplayer].camera->player != NULL) ? players[consoleplayer].camera->player : &players[consoleplayer]; - V_AddBlend (player->BlendR, player->BlendG, player->BlendB, player->BlendA, blend); - } - - gl_RenderState.SetTextureMode(TM_MODULATE); - gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - if (blend[3]>0.0f) - { - gl_RenderState.SetColor(blend[0], blend[1], blend[2], blend[3]); - gl_FillScreen(); - } - gl_RenderState.ResetColor(); - gl_RenderState.EnableTexture(true); -} - - //----------------------------------------------------------------------------- // // Draws player sprites and color blend @@ -786,6 +653,17 @@ void GLSceneDrawer::SetFixedColormap (player_t *player) gl_RenderState.SetFixedColormap(FixedColormap); } +//----------------------------------------------------------------------------- +// +// +// +//----------------------------------------------------------------------------- + +void GLSceneDrawer::DrawBlend(sector_t *viewsector) +{ + GLRenderer->DrawBlend(viewsector, !!FixedColormap, true); +} + //----------------------------------------------------------------------------- // // Renders one viewpoint in a scene diff --git a/src/gl/scene/gl_swscene.cpp b/src/gl/scene/gl_swscene.cpp new file mode 100644 index 0000000000..7d5a21a8d0 --- /dev/null +++ b/src/gl/scene/gl_swscene.cpp @@ -0,0 +1,127 @@ +// +//--------------------------------------------------------------------------- +// +// Copyright(C) 2004-2018 Christoph Oelckers +// All rights reserved. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see http://www.gnu.org/licenses/ +// +//-------------------------------------------------------------------------- +// +/* +** gl_swscene.cpp +** common overlay code for software and hardware renderer +** +*/ + +#include "gl/system/gl_system.h" +#include "gl/system/gl_interface.h" +#include "gl/system/gl_debug.h" +#include "gl/data/gl_vertexbuffer.h" +#include "gl/shaders/gl_shader.h" +#include "gl/renderer/gl_renderstate.h" +#include "v_palette.h" +#include "v_video.h" +#include "gl_swscene.h" +#include "w_wad.h" +#include "d_player.h" +#include "textures/bitmap.h" +#include "swrenderer/scene/r_light.h" + +// [RH] Base blending values (for e.g. underwater) +int BaseBlendR, BaseBlendG, BaseBlendB; +float BaseBlendA; + +EXTERN_CVAR(Bool, swtruecolor) + + +// using FDummyTexture as base because that implements the required software renderer functions. + +class FSWPaletteTexture : public FDummyTexture +{ +public: + FSWPaletteTexture() + { + Width = 256; + Height = 1; + UseType = ETextureType::MiscPatch; + } + + int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate, FCopyInfo *inf) + { + memcpy(bmp->GetPixels(), GPalette.BaseColors, 1024); + return 0; + } +}; + +class FSWSceneTexture : public FDummyTexture +{ +public: + FHardwareTexture *hwtex; + + FSWSceneTexture(int w, int h, int bits) + { + Width = w; + Height = h; + WidthBits = bits; + UseType = ETextureType::SWCanvas; + + hwtex = new FHardwareTexture(true); + new FGLTexture(this, hwtex); + } + + // This is just a wrapper around the hardware texture and should never call the bitmap getters - if it does, something is wrong. +}; + +//========================================================================== +// +// SWSceneDrawer :: CreateResources +// +//========================================================================== + +SWSceneDrawer::SWSceneDrawer() +{ + PaletteTexture = new FSWPaletteTexture; +} + +SWSceneDrawer::~SWSceneDrawer() +{ + if (PaletteTexture != nullptr) delete PaletteTexture; + if (FBTexture != nullptr) delete FBTexture; +} + +void SWSceneDrawer::RenderView(player_t *player) +{ + DCanvas buffer(screen->GetWidth(), screen->GetHeight(), swtruecolor); + if (FBTexture == nullptr || FBTexture->hwtex == nullptr || FBTexture->GetWidth() != screen->GetWidth() || FBTexture->GetHeight() != screen->GetHeight() || (swtruecolor?4:1) != FBTexture->WidthBits) + { + // This manually constructs its own material here. + if (FBTexture != nullptr) delete FBTexture; + FBTexture = new FSWSceneTexture(screen->GetWidth(), screen->GetHeight(), swtruecolor); + FBTexture->hwtex->AllocateBuffer(screen->GetWidth(), screen->GetHeight(), swtruecolor ? 4 : 1); + auto mat = FMaterial::ValidateTexture(FBTexture, false); + mat->AddTextureLayer(PaletteTexture); + } + auto buf = FBTexture->hwtex->MapBuffer(); + if (!buf) I_FatalError("Unable to map buffer for software rendering"); + buffer.SetBuffer(screen->GetWidth(), screen->GetHeight(), screen->GetWidth() * (swtruecolor ? 4 : 1), buf); + SWRenderer->RenderView(player, &buffer); + FBTexture->hwtex->CreateTexture(nullptr, screen->GetWidth(), screen->GetHeight(), 0, false, 0, "swbuffer"); + + auto map = swrenderer::CameraLight::Instance()->ShaderColormap(); + screen->Begin2D(false); + screen->DrawTexture(FBTexture, 0, 0, DTA_SpecialColormap, map, TAG_DONE); + SWRenderer->DrawRemainingPlayerSprites(); + GLRenderer->DrawBlend(r_viewpoint.sector, !!map, swtruecolor); +} diff --git a/src/gl/shaders/gl_shader.cpp b/src/gl/shaders/gl_shader.cpp index 2ae6a8af44..44d1e37a6f 100644 --- a/src/gl/shaders/gl_shader.cpp +++ b/src/gl/shaders/gl_shader.cpp @@ -616,6 +616,7 @@ static const FEffectShader effectshaders[]= { "spheremap", "shaders/glsl/main.vp", "shaders/glsl/main.fp", "shaders/glsl/func_normal.fp", "shaders/glsl/material_normal.fp", "#define SPHEREMAP\n#define NO_ALPHATEST\n" }, { "burn", "shaders/glsl/main.vp", "shaders/glsl/burn.fp", nullptr, nullptr, "#define SIMPLE\n#define NO_ALPHATEST\n" }, { "stencil", "shaders/glsl/main.vp", "shaders/glsl/stencil.fp", nullptr, nullptr, "#define SIMPLE\n#define NO_ALPHATEST\n" }, + { "swrquad", "shaders/glsl/main.vp", "shaders/glsl/swshader.fp", nullptr, nullptr, "#define SIMPLE\n" }, }; FShaderManager::FShaderManager() diff --git a/src/gl/system/gl_framebuffer.cpp b/src/gl/system/gl_framebuffer.cpp index 1556317388..c51bf96f9b 100644 --- a/src/gl/system/gl_framebuffer.cpp +++ b/src/gl/system/gl_framebuffer.cpp @@ -201,6 +201,7 @@ void OpenGLFrameBuffer::RenderTextureView(FCanvasTexture *tex, AActor *Viewpoint { if (currentrenderer == 0) Super::RenderTextureView(tex, Viewpoint, FOV); + else if (GLRenderer != nullptr) { GLRenderer->RenderTextureView(tex, Viewpoint, FOV); @@ -216,6 +217,9 @@ void OpenGLFrameBuffer::RenderTextureView(FCanvasTexture *tex, AActor *Viewpoint void OpenGLFrameBuffer::WriteSavePic(player_t *player, FileWriter *file, int width, int height) { + if (currentrenderer == 0) + Super::WriteSavePic(player, file, width, height); + if (GLRenderer != nullptr) GLRenderer->WriteSavePic(player, file, width, height); } diff --git a/src/gl/textures/gl_hwtexture.cpp b/src/gl/textures/gl_hwtexture.cpp index 577e733902..0ab9457fa4 100644 --- a/src/gl/textures/gl_hwtexture.cpp +++ b/src/gl/textures/gl_hwtexture.cpp @@ -177,11 +177,15 @@ unsigned int FHardwareTexture::CreateTexture(unsigned char * buffer, int w, int FGLDebug::LabelObject(GL_TEXTURE, glTex->glTexID, name); lastbound[texunit] = glTex->glTexID; - if (!buffer) + rw = GetTexDimension(w); + rh = GetTexDimension(h); + if (glBufferID > 0) + { + glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); + buffer = nullptr; + } + else if (!buffer) { - rw = GetTexDimension (w); - rh = GetTexDimension (h); - // The texture must at least be initialized if no data is present. glTex->mipmapped = false; buffer=(unsigned char *)calloc(4,rw * (rh+1)); @@ -190,9 +194,6 @@ unsigned int FHardwareTexture::CreateTexture(unsigned char * buffer, int w, int } else { - rw = GetTexDimension (w); - rh = GetTexDimension (h); - if (rw < w || rh < h) { // The texture is larger than what the hardware can handle so scale it down. @@ -208,9 +209,42 @@ unsigned int FHardwareTexture::CreateTexture(unsigned char * buffer, int w, int // store the physical size. texwidth = rw; texheight = rh; - glTexImage2D(GL_TEXTURE_2D, 0, texformat, rw, rh, 0, GL_BGRA, GL_UNSIGNED_BYTE, buffer); - if (deletebuffer) free(buffer); + int sourcetype; + if (glTextureBytes > 0) + { + if (glTextureBytes < 4) glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + if (gl.legacyMode) + { + // Do not use 2 and 3 here. They won't do anything useful!!! + static const int ITypes[] = { GL_LUMINANCE8, GL_LUMINANCE8_ALPHA8, GL_RGB8, GL_RGBA8 }; + static const int STypes[] = { GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_BGR, GL_BGRA }; + + texformat = ITypes[glTextureBytes - 1]; + sourcetype = STypes[glTextureBytes - 1]; + } + else + { + static const int ITypes[] = { GL_R8, GL_RG8, GL_RGB8, GL_RGBA8 }; + static const int STypes[] = { GL_RED, GL_RG, GL_BGR, GL_BGRA }; + + texformat = ITypes[glTextureBytes - 1]; + sourcetype = STypes[glTextureBytes - 1]; + } + } + else + { + sourcetype = GL_BGRA; + } + + glTexImage2D(GL_TEXTURE_2D, 0, texformat, rw, rh, 0, sourcetype, GL_UNSIGNED_BYTE, buffer); + + if (deletebuffer && buffer) free(buffer); + else if (glBufferID) + { + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + } if (mipmap && TexFilter[gl_texture_filter].mipmapping) { @@ -223,6 +257,33 @@ unsigned int FHardwareTexture::CreateTexture(unsigned char * buffer, int w, int } +//=========================================================================== +// +// +// +//=========================================================================== +void FHardwareTexture::AllocateBuffer(int w, int h, int texelsize) +{ + int rw = GetTexDimension(w); + int rh = GetTexDimension(h); + if (texelsize < 1 || texelsize > 4) texelsize = 4; + glTextureBytes = texelsize; + if (rw == w || rh == h) + { + glGenBuffers(1, &glBufferID); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, glBufferID); + glBufferData(GL_PIXEL_UNPACK_BUFFER, w*h*texelsize, nullptr, GL_DYNAMIC_DRAW); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + } +} + + +uint8_t *FHardwareTexture::MapBuffer() +{ + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, glBufferID); + return (uint8_t*)glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_READ_WRITE); +} + //=========================================================================== // // Creates a texture @@ -313,6 +374,7 @@ void FHardwareTexture::CleanUnused(SpriteHits &usedtranslations) FHardwareTexture::~FHardwareTexture() { Clean(true); + glDeleteBuffers(1, &glBufferID); } diff --git a/src/gl/textures/gl_hwtexture.h b/src/gl/textures/gl_hwtexture.h index 2bbc41f8be..9dac63cbba 100644 --- a/src/gl/textures/gl_hwtexture.h +++ b/src/gl/textures/gl_hwtexture.h @@ -66,6 +66,8 @@ private: TranslatedTexture glDefTex; TArray glTex_Translated; unsigned int glDepthID; // only used by camera textures + unsigned int glBufferID = 0; + int glTextureBytes = 4; TranslatedTexture * GetTexID(int translation); @@ -82,6 +84,9 @@ public: void BindToFrameBuffer(); unsigned int Bind(int texunit, int translation, bool needmipmap); + void AllocateBuffer(int w, int h, int texelsize); + uint8_t *MapBuffer(); + unsigned int CreateTexture(unsigned char * buffer, int w, int h, int texunit, bool mipmap, int translation, const FString &name); unsigned int GetTextureHandle(int translation); diff --git a/src/gl/textures/gl_material.cpp b/src/gl/textures/gl_material.cpp index f67035ed91..561294eae9 100644 --- a/src/gl/textures/gl_material.cpp +++ b/src/gl/textures/gl_material.cpp @@ -73,6 +73,22 @@ FGLTexture::FGLTexture(FTexture * tx, bool expandpatches) tex->gl_info.SystemTexture[expandpatches] = this; } +//=========================================================================== +// +// Constructor 2 for the SW framebuffer which provides its own hardware texture. +// +//=========================================================================== +FGLTexture::FGLTexture(FTexture * tx, FHardwareTexture *hwtex) +{ + assert(tx->gl_info.SystemTexture[0] == NULL); + tex = tx; + + mHwTexture = hwtex; + lastSampler = 254; + lastTranslation = -1; + tex->gl_info.SystemTexture[0] = this; +} + //=========================================================================== // // Destructor @@ -82,6 +98,7 @@ FGLTexture::FGLTexture(FTexture * tx, bool expandpatches) FGLTexture::~FGLTexture() { Clean(true); + for (auto & i : tex->gl_info.SystemTexture) if (i == this) i = nullptr; } //=========================================================================== @@ -174,7 +191,7 @@ const FHardwareTexture *FGLTexture::Bind(int texunit, int clampmode, int transla int w=0, h=0; // Create this texture - unsigned char * buffer = NULL; + unsigned char * buffer = nullptr; if (!tex->bHasCanvas) { diff --git a/src/gl/textures/gl_material.h b/src/gl/textures/gl_material.h index 04bef6031f..60ec531e58 100644 --- a/src/gl/textures/gl_material.h +++ b/src/gl/textures/gl_material.h @@ -45,7 +45,7 @@ struct FTexCoordInfo //=========================================================================== // -// this is the texture maintenance class for OpenGL. +// device independent wrapper around the hardware texture and its sampler state // //=========================================================================== class FMaterial; @@ -68,10 +68,12 @@ private: public: FGLTexture(FTexture * tx, bool expandpatches); + FGLTexture(FTexture * tx, FHardwareTexture *hwtex); // for the SW framebuffer ~FGLTexture(); void Clean(bool all); void CleanUnused(SpriteHits &usedtranslations); + bool isInitialized() const { return mHwTexture != nullptr; } }; //=========================================================================== @@ -124,6 +126,12 @@ public: void SetSpriteRect(); void Precache(); void PrecacheList(SpriteHits &translations); + void AddTextureLayer(FTexture *tex) + { + FTextureLayer layer = { tex, false }; + ValidateTexture(tex, false); + mTextureLayers.Push(layer); + } bool isMasked() const { return !!mBaseLayer->tex->bMasked; diff --git a/src/polyrenderer/poly_renderer.cpp b/src/polyrenderer/poly_renderer.cpp index 6c6c8e460c..18ec739570 100644 --- a/src/polyrenderer/poly_renderer.cpp +++ b/src/polyrenderer/poly_renderer.cpp @@ -54,26 +54,21 @@ PolyRenderer::PolyRenderer() { } -void PolyRenderer::RenderView(player_t *player) +void PolyRenderer::RenderView(player_t *player, DCanvas *target) { using namespace swrenderer; - if (screen->LockCanvas()) - { - RenderTarget = screen->GetCanvas(); + RenderTarget = target; + int width = SCREENWIDTH; + int height = SCREENHEIGHT; + float trueratio; + ActiveRatio(width, height, &trueratio); + //viewport->SetViewport(&Thread, width, height, trueratio); - int width = SCREENWIDTH; - int height = SCREENHEIGHT; - float trueratio; - ActiveRatio(width, height, &trueratio); - //viewport->SetViewport(&Thread, width, height, trueratio); + RenderActorView(player->mo, false); - RenderActorView(player->mo, false); - - Threads.MainThread()->FlushDrawQueue(); - DrawerThreads::WaitForWorkers(); - screen->UnlockCanvas(); - } + Threads.MainThread()->FlushDrawQueue(); + DrawerThreads::WaitForWorkers(); } void PolyRenderer::RenderViewToCanvas(AActor *actor, DCanvas *canvas, int x, int y, int width, int height, bool dontmaplines) diff --git a/src/polyrenderer/poly_renderer.h b/src/polyrenderer/poly_renderer.h index 2ef60a0ea0..377b10c77d 100644 --- a/src/polyrenderer/poly_renderer.h +++ b/src/polyrenderer/poly_renderer.h @@ -45,7 +45,7 @@ class PolyRenderer public: PolyRenderer(); - void RenderView(player_t *player); + void RenderView(player_t *player, DCanvas *target); void RenderViewToCanvas(AActor *actor, DCanvas *canvas, int x, int y, int width, int height, bool dontmaplines); void RenderRemainingPlayerSprites(); diff --git a/src/r_renderer.h b/src/r_renderer.h index a4b8bad0b8..975fe76bfb 100644 --- a/src/r_renderer.h +++ b/src/r_renderer.h @@ -13,6 +13,7 @@ class player_t; struct sector_t; class FCanvasTexture; class FileWriter; +class DCanvas; struct FRenderer { @@ -22,7 +23,7 @@ struct FRenderer virtual void Precache(uint8_t *texhitlist, TMap &actorhitlist) = 0; // render 3D view - virtual void RenderView(player_t *player) = 0; + virtual void RenderView(player_t *player, DCanvas *target) = 0; // renders view to a savegame picture virtual void WriteSavePic(player_t *player, FileWriter *file, int width, int height) = 0; diff --git a/src/swrenderer/r_swrenderer.cpp b/src/swrenderer/r_swrenderer.cpp index 77c217973c..7bbbe6aae0 100644 --- a/src/swrenderer/r_swrenderer.cpp +++ b/src/swrenderer/r_swrenderer.cpp @@ -175,13 +175,13 @@ void FSoftwareRenderer::Precache(uint8_t *texhitlist, TMap & } } -void FSoftwareRenderer::RenderView(player_t *player) +void FSoftwareRenderer::RenderView(player_t *player, DCanvas *target) { if (r_polyrenderer) { PolyRenderer::Instance()->Viewpoint = r_viewpoint; PolyRenderer::Instance()->Viewwindow = r_viewwindow; - PolyRenderer::Instance()->RenderView(player); + PolyRenderer::Instance()->RenderView(player, target); r_viewpoint = PolyRenderer::Instance()->Viewpoint; r_viewwindow = PolyRenderer::Instance()->Viewwindow; } @@ -189,7 +189,7 @@ void FSoftwareRenderer::RenderView(player_t *player) { mScene.MainThread()->Viewport->viewpoint = r_viewpoint; mScene.MainThread()->Viewport->viewwindow = r_viewwindow; - mScene.RenderView(player); + mScene.RenderView(player, target); r_viewpoint = mScene.MainThread()->Viewport->viewpoint; r_viewwindow = mScene.MainThread()->Viewport->viewwindow; } diff --git a/src/swrenderer/r_swrenderer.h b/src/swrenderer/r_swrenderer.h index a2bcfa625b..3843d58169 100644 --- a/src/swrenderer/r_swrenderer.h +++ b/src/swrenderer/r_swrenderer.h @@ -12,7 +12,7 @@ struct FSoftwareRenderer : public FRenderer void Precache(uint8_t *texhitlist, TMap &actorhitlist) override; // render 3D view - void RenderView(player_t *player) override; + void RenderView(player_t *player, DCanvas *target) override; // renders view to a savegame picture void WriteSavePic (player_t *player, FileWriter *file, int width, int height) override; diff --git a/src/swrenderer/scene/r_scene.cpp b/src/swrenderer/scene/r_scene.cpp index 3847c0d34d..9a4bbb9958 100644 --- a/src/swrenderer/scene/r_scene.cpp +++ b/src/swrenderer/scene/r_scene.cpp @@ -64,6 +64,7 @@ void PeekThreadedErrorPane(); #endif EXTERN_CVAR(Int, r_clearbuffer) +EXTERN_CVAR(Bool, swtruecolor) CVAR(Bool, r_scene_multithreaded, false, 0); CVAR(Bool, r_models, false, 0); @@ -87,44 +88,38 @@ namespace swrenderer clearcolor = color; } - void RenderScene::RenderView(player_t *player) + void RenderScene::RenderView(player_t *player, DCanvas *target) { - if (screen->LockCanvas()) + auto viewport = MainThread()->Viewport.get(); + viewport->RenderTarget = target; + + int width = SCREENWIDTH; + int height = SCREENHEIGHT; + float trueratio; + ActiveRatio(width, height, &trueratio); + viewport->SetViewport(MainThread(), width, height, trueratio); + + if (r_clearbuffer != 0) { - auto viewport = MainThread()->Viewport.get(); - viewport->RenderTarget = screen->GetCanvas(); - - int width = SCREENWIDTH; - int height = SCREENHEIGHT; - float trueratio; - ActiveRatio(width, height, &trueratio); - viewport->SetViewport(MainThread(), width, height, trueratio); - - if (r_clearbuffer != 0) + if (!viewport->RenderTarget->IsBgra()) { - if (!viewport->RenderTarget->IsBgra()) - { - memset(viewport->RenderTarget->GetPixels(), clearcolor, viewport->RenderTarget->GetPitch() * viewport->RenderTarget->GetHeight()); - } - else - { - uint32_t bgracolor = GPalette.BaseColors[clearcolor].d; - int size = viewport->RenderTarget->GetPitch() * viewport->RenderTarget->GetHeight(); - uint32_t *dest = (uint32_t *)viewport->RenderTarget->GetPixels(); - for (int i = 0; i < size; i++) - dest[i] = bgracolor; - } + memset(viewport->RenderTarget->GetPixels(), clearcolor, viewport->RenderTarget->GetPitch() * viewport->RenderTarget->GetHeight()); + } + else + { + uint32_t bgracolor = GPalette.BaseColors[clearcolor].d; + int size = viewport->RenderTarget->GetPitch() * viewport->RenderTarget->GetHeight(); + uint32_t *dest = (uint32_t *)viewport->RenderTarget->GetPixels(); + for (int i = 0; i < size; i++) + dest[i] = bgracolor; } - - RenderActorView(player->mo); - - DrawerWaitCycles.Clock(); - DrawerThreads::WaitForWorkers(); - DrawerWaitCycles.Unclock(); - - screen->UnlockCanvas(); } + RenderActorView(player->mo); + + DrawerWaitCycles.Clock(); + DrawerThreads::WaitForWorkers(); + DrawerWaitCycles.Unclock(); } void RenderScene::RenderActorView(AActor *actor, bool dontmaplines) @@ -367,15 +362,18 @@ namespace swrenderer viewactive = savedviewactive; } + void RenderScene::ScreenResized() { auto viewport = MainThread()->Viewport.get(); - viewport->RenderTarget = screen->GetCanvas(); int width = SCREENWIDTH; int height = SCREENHEIGHT; + viewport->RenderTarget = new DCanvas(width, height, swtruecolor); // Some code deeper down needs something valid here, so give it a dummy canvas. float trueratio; ActiveRatio(width, height, &trueratio); viewport->SetViewport(MainThread(), SCREENWIDTH, SCREENHEIGHT, trueratio); + delete viewport->RenderTarget; + viewport->RenderTarget = nullptr; } void RenderScene::Deinit() diff --git a/src/swrenderer/scene/r_scene.h b/src/swrenderer/scene/r_scene.h index adc9e14497..d3b8613c09 100644 --- a/src/swrenderer/scene/r_scene.h +++ b/src/swrenderer/scene/r_scene.h @@ -49,7 +49,7 @@ namespace swrenderer void SetClearColor(int color); - void RenderView(player_t *player); + void RenderView(player_t *player, DCanvas *target); void RenderViewToCanvas(AActor *actor, DCanvas *canvas, int x, int y, int width, int height, bool dontmaplines = false); bool DontMapLines() const { return dontmaplines; } diff --git a/src/v_2ddrawer.cpp b/src/v_2ddrawer.cpp index 941aae6daf..fd0a9ce7ad 100644 --- a/src/v_2ddrawer.cpp +++ b/src/v_2ddrawer.cpp @@ -307,7 +307,6 @@ void F2DDrawer::AddTexture(FTexture *img, DrawParms &parms) AddCommand(&dg); } - //========================================================================== // // diff --git a/src/v_2ddrawer.h b/src/v_2ddrawer.h index 42d4721372..ad045a9b22 100644 --- a/src/v_2ddrawer.h +++ b/src/v_2ddrawer.h @@ -34,7 +34,6 @@ public: { DTF_Wrap = 1, DTF_Scissor = 2, - //DTF_SpecialColormap = 4, }; diff --git a/src/v_video.cpp b/src/v_video.cpp index 325f95da7c..6507137f30 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -965,6 +965,12 @@ void DFrameBuffer::RenderTextureView(FCanvasTexture *tex, AActor *Viewpoint, dou SWRenderer->RenderTextureView(tex, Viewpoint, FOV); } +void DFrameBuffer::WriteSavePic(player_t *player, FileWriter *file, int width, int height) +{ + SWRenderer->WriteSavePic(player, file, width, height); +} + + CCMD(clean) { Printf ("CleanXfac: %d\nCleanYfac: %d\n", CleanXfac, CleanYfac); diff --git a/src/v_video.h b/src/v_video.h index 0b8dedc26a..39d07eb079 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -226,18 +226,12 @@ public: bool SetBuffer(int width, int height, int pitch, uint8_t *buffer) { - if (PixelBuffer == nullptr) - { - Width = width; - Height = height; - Pitch = pitch; - PixelBuffer = buffer; - return true; - } - else - { - return false; - } + assert(buffer); + Width = width; + Height = height; + Pitch = pitch; + PixelBuffer = buffer; + return true; } @@ -339,10 +333,6 @@ public: virtual bool LegacyHardware() const { return false; } // only for reporting SM1.4 support to the stat collector - // For FrameBuffers with a software canvas that requires special preparation before being used. - virtual bool LockCanvas() { return true; } - virtual void UnlockCanvas() {} - // Begin 2D drawing operations. // Returns true if hardware-accelerated 2D has been entered, false if not. virtual bool Begin2D(bool copy3d); @@ -359,7 +349,7 @@ public: virtual void SetClearColor(int color) {} virtual uint32_t GetCaps(); virtual void RenderTextureView(FCanvasTexture *tex, AActor *Viewpoint, double FOV); - virtual void WriteSavePic(player_t *player, FileWriter *file, int width, int height) {} + virtual void WriteSavePic(player_t *player, FileWriter *file, int width, int height); virtual void RenderView(player_t *player) {} // Screen wiping diff --git a/wadsrc/static/shaders/glsl/swshader.fp b/wadsrc/static/shaders/glsl/swshader.fp new file mode 100644 index 0000000000..79432b2083 --- /dev/null +++ b/wadsrc/static/shaders/glsl/swshader.fp @@ -0,0 +1,31 @@ +in vec4 vTexCoord; +out vec4 FragColor; + +vec4 TextureLookup(vec2 tex_coord) +{ + if (uTextureMode == 1) + { + float index = texture(tex, tex_coord).x; + index = index * 256.0 + 0.5; // We only have 256 color palettes here. + return texture(texture2, vec2(index, 0.5)); + } + else + { + return texture(tex, tex_coord); + } +} + +void main() +{ + if (uFixedColormap == 0) + { + FragColor = TextureLookup(vTexCoord.xy); + } + else + { + vec4 frag = TextureLookup(vTexCoord.xy); + float gray = dot(frag.rgb, vec3(0.4, 0.56, 0.14)); + vec4 cm = uFixedColormapStart + gray * uFixedColormapRange; + FragColor = vec4(clamp(cm.rgb, 0.0, 1.0), 1.0); + } +} diff --git a/wadsrc/static/shaders/swgl/swshadergl2.fp b/wadsrc/static/shaders/swgl/swshadergl2.fp new file mode 100644 index 0000000000..3a0ab3fa72 --- /dev/null +++ b/wadsrc/static/shaders/swgl/swshadergl2.fp @@ -0,0 +1,32 @@ +uniform sampler2D tex; +uniform sampler2D pal; +uniform vec4 uColor1; +uniform vec4 uColor2; + +vec4 TextureLookup(vec2 tex_coord) +{ +#ifdef PAL_TEX + float index = texture2D(tex, tex_coord).x; + index = index * 256.0 + 0.5; // We only have full 256-color palettes here. + return texture2D(pal, vec2(index, 0.5)); +#else + return texture2D(tex, tex_coord); +#endif +} + +float grayscale(vec4 rgb) +{ + return dot(color.rgb, vec3(0.4, 0.56, 0.14)); +} + +void main() +{ +#ifndef SPECIALCM + FragColor = TextureLookup(gl_TexCoord[0].xy); +#else + vec4 frag = TextureLookup(gl_TexCoord[0].xy); + float gray = grayscale(frag); + vec4 cm = uColor1 + gray * uColor2; + gl_FragColor = vec4(clamp(cm.rgb, 0.0, 1.0), 1.0); +#endif +} diff --git a/wadsrc/static/shaders/swgl/swshadergl2.vp b/wadsrc/static/shaders/swgl/swshadergl2.vp new file mode 100644 index 0000000000..97d05c35f8 --- /dev/null +++ b/wadsrc/static/shaders/swgl/swshadergl2.vp @@ -0,0 +1,6 @@ + +void main() +{ + gl_TexCoord[0] = gl_MultiTexCoord0; + gl_Position = ftransform(); +}