- 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.
This commit is contained in:
Christoph Oelckers 2018-04-05 23:08:09 +02:00
parent d474b849a5
commit b34d7f9e08
32 changed files with 569 additions and 302 deletions

View file

@ -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

View file

@ -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());

View file

@ -196,6 +196,7 @@ enum class ETextureType : uint8_t
SkinGraphic,
Null,
FirstDefined,
SWCanvas,
};
class FTextureID

View file

@ -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();

View file

@ -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
{

View file

@ -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;

View file

@ -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();

View file

@ -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<ADynamicLight> 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<ADynamicLight> 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_t> & 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);

View file

@ -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();

View file

@ -59,6 +59,7 @@ enum EEffect
EFF_SPHEREMAP,
EFF_BURN,
EFF_STENCIL,
EFF_SWQUAD,
MAX_EFFECTS
};

View file

@ -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_t> & 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

127
src/gl/scene/gl_swscene.cpp Normal file
View file

@ -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);
}

View file

@ -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()

View file

@ -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);
}

View file

@ -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);
}

View file

@ -66,6 +66,8 @@ private:
TranslatedTexture glDefTex;
TArray<TranslatedTexture> 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);

View file

@ -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)
{

View file

@ -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;

View file

@ -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)

View file

@ -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();

View file

@ -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<PClassActor*, bool> &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;

View file

@ -175,13 +175,13 @@ void FSoftwareRenderer::Precache(uint8_t *texhitlist, TMap<PClassActor*, bool> &
}
}
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;
}

View file

@ -12,7 +12,7 @@ struct FSoftwareRenderer : public FRenderer
void Precache(uint8_t *texhitlist, TMap<PClassActor*, bool> &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;

View file

@ -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()

View file

@ -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; }

View file

@ -307,7 +307,6 @@ void F2DDrawer::AddTexture(FTexture *img, DrawParms &parms)
AddCommand(&dg);
}
//==========================================================================
//
//

View file

@ -34,7 +34,6 @@ public:
{
DTF_Wrap = 1,
DTF_Scissor = 2,
//DTF_SpecialColormap = 4,
};

View file

@ -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);

View file

@ -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

View file

@ -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);
}
}

View file

@ -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
}

View file

@ -0,0 +1,6 @@
void main()
{
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_Position = ftransform();
}