mirror of
https://github.com/ZDoom/qzdoom.git
synced 2025-01-18 15:11:46 +00:00
Merge remote-tracking branch 'origin/gl_swframebuffer' into qzdoom
This commit is contained in:
commit
f5c069c759
9 changed files with 4886 additions and 4 deletions
|
@ -1194,6 +1194,8 @@ set( FASTMATH_SOURCES
|
|||
gl/shaders/gl_fxaashader.cpp
|
||||
gl/system/gl_interface.cpp
|
||||
gl/system/gl_framebuffer.cpp
|
||||
gl/system/gl_swframebuffer.cpp
|
||||
gl/system/gl_swwipe.cpp
|
||||
gl/system/gl_debug.cpp
|
||||
gl/system/gl_menu.cpp
|
||||
gl/system/gl_wipe.cpp
|
||||
|
|
3613
src/gl/system/gl_swframebuffer.cpp
Normal file
3613
src/gl/system/gl_swframebuffer.cpp
Normal file
File diff suppressed because it is too large
Load diff
498
src/gl/system/gl_swframebuffer.h
Normal file
498
src/gl/system/gl_swframebuffer.h
Normal file
|
@ -0,0 +1,498 @@
|
|||
#ifndef __GL_SWFRAMEBUFFER
|
||||
#define __GL_SWFRAMEBUFFER
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "win32iface.h"
|
||||
#include "win32gliface.h"
|
||||
#endif
|
||||
|
||||
#include "SkylineBinPack.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
class FGLDebug;
|
||||
|
||||
#ifdef _WIN32
|
||||
class OpenGLSWFrameBuffer : public Win32GLFrameBuffer
|
||||
{
|
||||
typedef Win32GLFrameBuffer Super;
|
||||
DECLARE_CLASS(OpenGLSWFrameBuffer, Win32GLFrameBuffer)
|
||||
#else
|
||||
#include "sdlglvideo.h"
|
||||
class OpenGLFrameBuffer : public SDLGLFB
|
||||
{
|
||||
// typedef SDLGLFB Super; //[C]commented, DECLARE_CLASS defines this in linux
|
||||
DECLARE_CLASS(OpenGLSWFrameBuffer, SDLGLFB)
|
||||
#endif
|
||||
|
||||
|
||||
public:
|
||||
|
||||
explicit OpenGLSWFrameBuffer() {}
|
||||
OpenGLSWFrameBuffer(void *hMonitor, int width, int height, int bits, int refreshHz, bool fullscreen);
|
||||
~OpenGLSWFrameBuffer();
|
||||
|
||||
bool IsValid() override;
|
||||
bool Lock(bool buffered) override;
|
||||
void Unlock() override;
|
||||
void Update() override;
|
||||
PalEntry *GetPalette() override;
|
||||
void GetFlashedPalette(PalEntry palette[256]) override;
|
||||
void UpdatePalette() override;
|
||||
bool SetGamma(float gamma) override;
|
||||
bool SetFlash(PalEntry rgb, int amount) override;
|
||||
void GetFlash(PalEntry &rgb, int &amount) override;
|
||||
int GetPageCount() override;
|
||||
bool IsFullscreen() override;
|
||||
void PaletteChanged() override;
|
||||
int QueryNewPalette() override;
|
||||
void Blank() override;
|
||||
bool PaintToWindow() override;
|
||||
void SetVSync(bool vsync) override;
|
||||
void NewRefreshRate() override;
|
||||
void GetScreenshotBuffer(const uint8_t *&buffer, int &pitch, ESSType &color_type) override;
|
||||
void ReleaseScreenshotBuffer() override;
|
||||
void SetBlendingRect(int x1, int y1, int x2, int y2) override;
|
||||
bool Begin2D(bool copy3d) override;
|
||||
void DrawBlendingRect() override;
|
||||
FNativeTexture *CreateTexture(FTexture *gametex, bool wrapping) override;
|
||||
FNativePalette *CreatePalette(FRemapTable *remap) override;
|
||||
void DrawTextureParms(FTexture *img, DrawParms &parms) override;
|
||||
void Clear(int left, int top, int right, int bottom, int palcolor, uint32 color) override;
|
||||
void Dim(PalEntry color, float amount, int x1, int y1, int w, int h) override;
|
||||
void FlatFill(int left, int top, int right, int bottom, FTexture *src, bool local_origin) override;
|
||||
void DrawLine(int x0, int y0, int x1, int y1, int palColor, uint32 realcolor) override;
|
||||
void DrawPixel(int x, int y, int palcolor, uint32 rgbcolor) override;
|
||||
void FillSimplePoly(FTexture *tex, FVector2 *points, int npoints, double originx, double originy, double scalex, double scaley, DAngle rotation, FDynamicColormap *colormap, int lightlevel) override;
|
||||
bool WipeStartScreen(int type) override;
|
||||
void WipeEndScreen() override;
|
||||
bool WipeDo(int ticks) override;
|
||||
void WipeCleanup() override;
|
||||
bool Is8BitMode() override { return false; }
|
||||
int GetTrueHeight() override { return TrueHeight; }
|
||||
|
||||
private:
|
||||
struct FBVERTEX
|
||||
{
|
||||
float x, y, z, rhw;
|
||||
uint32_t color0, color1;
|
||||
float tu, tv;
|
||||
};
|
||||
|
||||
struct BURNVERTEX
|
||||
{
|
||||
float x, y, z, rhw;
|
||||
float tu0, tv0;
|
||||
float tu1, tv1;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
PSCONST_Desaturation,
|
||||
PSCONST_PaletteMod,
|
||||
PSCONST_Weights,
|
||||
PSCONST_Gamma,
|
||||
PSCONST_ScreenSize,
|
||||
NumPSCONST
|
||||
};
|
||||
|
||||
struct GammaRamp
|
||||
{
|
||||
uint16_t red[256], green[256], blue[256];
|
||||
};
|
||||
|
||||
struct LTRBRect
|
||||
{
|
||||
int left, top, right, bottom;
|
||||
};
|
||||
|
||||
class HWTexture
|
||||
{
|
||||
public:
|
||||
HWTexture() { Buffers[0] = 0; Buffers[1] = 0; }
|
||||
~HWTexture();
|
||||
|
||||
int Texture = 0;
|
||||
int Buffers[2];
|
||||
int CurrentBuffer = 0;
|
||||
int WrapS = 0;
|
||||
int WrapT = 0;
|
||||
int Format = 0;
|
||||
};
|
||||
|
||||
class HWFrameBuffer
|
||||
{
|
||||
public:
|
||||
~HWFrameBuffer();
|
||||
|
||||
int Framebuffer = 0;
|
||||
HWTexture *Texture = nullptr;
|
||||
};
|
||||
|
||||
|
||||
class HWVertexBuffer
|
||||
{
|
||||
public:
|
||||
~HWVertexBuffer();
|
||||
|
||||
FBVERTEX *Lock();
|
||||
void Unlock();
|
||||
|
||||
int VertexArray = 0;
|
||||
int Buffer = 0;
|
||||
int Size = 0;
|
||||
};
|
||||
|
||||
class HWIndexBuffer
|
||||
{
|
||||
public:
|
||||
~HWIndexBuffer();
|
||||
|
||||
uint16_t *Lock();
|
||||
void Unlock();
|
||||
|
||||
int Buffer = 0;
|
||||
int Size = 0;
|
||||
|
||||
private:
|
||||
int LockedOldBinding = 0;
|
||||
};
|
||||
|
||||
class HWPixelShader
|
||||
{
|
||||
public:
|
||||
~HWPixelShader();
|
||||
|
||||
int Program = 0;
|
||||
int VertexShader = 0;
|
||||
int FragmentShader = 0;
|
||||
|
||||
int ConstantLocations[NumPSCONST];
|
||||
int ImageLocation = -1;
|
||||
int PaletteLocation = -1;
|
||||
int NewScreenLocation = -1;
|
||||
int BurnLocation = -1;
|
||||
};
|
||||
|
||||
bool CreateFrameBuffer(const FString &name, int width, int height, HWFrameBuffer **outFramebuffer);
|
||||
bool CreatePixelShader(FString vertexsrc, FString fragmentsrc, const FString &defines, HWPixelShader **outShader);
|
||||
bool CreateVertexBuffer(int size, HWVertexBuffer **outVertexBuffer);
|
||||
bool CreateIndexBuffer(int size, HWIndexBuffer **outIndexBuffer);
|
||||
bool CreateTexture(const FString &name, int width, int height, int levels, int format, HWTexture **outTexture);
|
||||
void SetGammaRamp(const GammaRamp *ramp);
|
||||
void SetPixelShaderConstantF(int uniformIndex, const float *data, int vec4fcount);
|
||||
void SetHWPixelShader(HWPixelShader *shader);
|
||||
void SetStreamSource(HWVertexBuffer *vertexBuffer);
|
||||
void SetIndices(HWIndexBuffer *indexBuffer);
|
||||
void DrawTriangleFans(int count, const FBVERTEX *vertices);
|
||||
void DrawTriangleFans(int count, const BURNVERTEX *vertices);
|
||||
void DrawPoints(int count, const FBVERTEX *vertices);
|
||||
void DrawLineList(int count);
|
||||
void DrawTriangleList(int minIndex, int numVertices, int startIndex, int primitiveCount);
|
||||
void Present();
|
||||
|
||||
static uint32_t ColorARGB(uint32_t a, uint32_t r, uint32_t g, uint32_t b) { return ((a & 0xff) << 24) | ((r & 0xff) << 16) | ((g & 0xff) << 8) | ((b) & 0xff); }
|
||||
static uint32_t ColorRGBA(uint32_t r, uint32_t g, uint32_t b, uint32_t a) { return ColorARGB(a, r, g, b); }
|
||||
static uint32_t ColorXRGB(uint32_t r, uint32_t g, uint32_t b) { return ColorARGB(0xff, r, g, b); }
|
||||
static uint32_t ColorValue(float r, float g, float b, float a) { return ColorRGBA((uint32_t)(r * 255.0f), (uint32_t)(g * 255.0f), (uint32_t)(b * 255.0f), (uint32_t)(a * 255.0f)); }
|
||||
|
||||
// The number of points for the vertex buffer.
|
||||
enum { NUM_VERTS = 10240 };
|
||||
|
||||
// The number of indices for the index buffer.
|
||||
enum { NUM_INDEXES = ((NUM_VERTS * 6) / 4) };
|
||||
|
||||
// The number of quads we can batch together.
|
||||
enum { MAX_QUAD_BATCH = (NUM_INDEXES / 6) };
|
||||
|
||||
// The default size for a texture atlas.
|
||||
enum { DEF_ATLAS_WIDTH = 512 };
|
||||
enum { DEF_ATLAS_HEIGHT = 512 };
|
||||
|
||||
// TYPES -------------------------------------------------------------------
|
||||
|
||||
struct Atlas;
|
||||
|
||||
struct PackedTexture
|
||||
{
|
||||
Atlas *Owner;
|
||||
|
||||
PackedTexture **Prev, *Next;
|
||||
|
||||
// Pixels this image covers
|
||||
LTRBRect Area;
|
||||
|
||||
// Texture coordinates for this image
|
||||
float Left, Top, Right, Bottom;
|
||||
|
||||
// Texture has extra space on the border?
|
||||
bool Padded;
|
||||
};
|
||||
|
||||
struct Atlas
|
||||
{
|
||||
Atlas(OpenGLSWFrameBuffer *fb, int width, int height, int format);
|
||||
~Atlas();
|
||||
|
||||
PackedTexture *AllocateImage(const Rect &rect, bool padded);
|
||||
void FreeBox(PackedTexture *box);
|
||||
|
||||
SkylineBinPack Packer;
|
||||
Atlas *Next;
|
||||
HWTexture *Tex;
|
||||
int Format;
|
||||
PackedTexture *UsedList; // Boxes that contain images
|
||||
int Width, Height;
|
||||
bool OneUse;
|
||||
};
|
||||
|
||||
class OpenGLTex : public FNativeTexture
|
||||
{
|
||||
public:
|
||||
OpenGLTex(FTexture *tex, OpenGLSWFrameBuffer *fb, bool wrapping);
|
||||
~OpenGLTex();
|
||||
|
||||
FTexture *GameTex;
|
||||
PackedTexture *Box;
|
||||
|
||||
OpenGLTex **Prev;
|
||||
OpenGLTex *Next;
|
||||
|
||||
bool IsGray;
|
||||
|
||||
bool Create(OpenGLSWFrameBuffer *fb, bool wrapping);
|
||||
bool Update();
|
||||
bool CheckWrapping(bool wrapping);
|
||||
int GetTexFormat();
|
||||
FTextureFormat ToTexFmt(int fmt);
|
||||
};
|
||||
|
||||
class OpenGLPal : public FNativePalette
|
||||
{
|
||||
public:
|
||||
OpenGLPal(FRemapTable *remap, OpenGLSWFrameBuffer *fb);
|
||||
~OpenGLPal();
|
||||
|
||||
OpenGLPal **Prev;
|
||||
OpenGLPal *Next;
|
||||
|
||||
HWTexture *Tex;
|
||||
uint32_t BorderColor;
|
||||
bool DoColorSkip;
|
||||
|
||||
bool Update();
|
||||
|
||||
FRemapTable *Remap;
|
||||
int RoundedPaletteSize;
|
||||
};
|
||||
|
||||
// Flags for a buffered quad
|
||||
enum
|
||||
{
|
||||
BQF_GamePalette = 1,
|
||||
BQF_CustomPalette = 7,
|
||||
BQF_Paletted = 7,
|
||||
BQF_Bilinear = 8,
|
||||
BQF_WrapUV = 16,
|
||||
BQF_InvertSource = 32,
|
||||
BQF_DisableAlphaTest = 64,
|
||||
BQF_Desaturated = 128,
|
||||
};
|
||||
|
||||
// Shaders for a buffered quad
|
||||
enum
|
||||
{
|
||||
BQS_PalTex,
|
||||
BQS_Plain,
|
||||
BQS_RedToAlpha,
|
||||
BQS_ColorOnly,
|
||||
BQS_SpecialColormap,
|
||||
BQS_InGameColormap,
|
||||
};
|
||||
|
||||
struct PackedTexture;
|
||||
struct Atlas;
|
||||
|
||||
struct BufferedTris
|
||||
{
|
||||
uint8_t Flags;
|
||||
uint8_t ShaderNum;
|
||||
int BlendOp;
|
||||
int SrcBlend;
|
||||
int DestBlend;
|
||||
|
||||
uint8_t Desat;
|
||||
OpenGLPal *Palette;
|
||||
HWTexture *Texture;
|
||||
uint16_t NumVerts; // Number of _unique_ vertices used by this set.
|
||||
uint16_t NumTris; // Number of triangles used by this set.
|
||||
|
||||
void ClearSetup()
|
||||
{
|
||||
Flags = 0;
|
||||
ShaderNum = 0;
|
||||
BlendOp = 0;
|
||||
SrcBlend = 0;
|
||||
DestBlend = 0;
|
||||
}
|
||||
|
||||
bool IsSameSetup(const BufferedTris &other) const
|
||||
{
|
||||
return Flags == other.Flags && ShaderNum == other.ShaderNum && BlendOp == other.BlendOp && SrcBlend == other.SrcBlend && DestBlend == other.DestBlend;
|
||||
}
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
SHADER_NormalColor,
|
||||
SHADER_NormalColorPal,
|
||||
SHADER_NormalColorInv,
|
||||
SHADER_NormalColorPalInv,
|
||||
|
||||
SHADER_RedToAlpha,
|
||||
SHADER_RedToAlphaInv,
|
||||
|
||||
SHADER_VertexColor,
|
||||
|
||||
SHADER_SpecialColormap,
|
||||
SHADER_SpecialColormapPal,
|
||||
|
||||
SHADER_InGameColormap,
|
||||
SHADER_InGameColormapDesat,
|
||||
SHADER_InGameColormapInv,
|
||||
SHADER_InGameColormapInvDesat,
|
||||
SHADER_InGameColormapPal,
|
||||
SHADER_InGameColormapPalDesat,
|
||||
SHADER_InGameColormapPalInv,
|
||||
SHADER_InGameColormapPalInvDesat,
|
||||
|
||||
SHADER_BurnWipe,
|
||||
SHADER_GammaCorrection,
|
||||
|
||||
NUM_SHADERS
|
||||
};
|
||||
static const char *const ShaderDefines[NUM_SHADERS];
|
||||
|
||||
void Flip();
|
||||
void SetInitialState();
|
||||
bool CreateResources();
|
||||
void ReleaseResources();
|
||||
bool LoadShaders();
|
||||
bool CreateFBTexture();
|
||||
bool CreatePaletteTexture();
|
||||
bool CreateVertexes();
|
||||
void UploadPalette();
|
||||
void CalcFullscreenCoords(FBVERTEX verts[4], bool viewarea_only, bool can_double, uint32_t color0, uint32_t color1) const;
|
||||
bool Reset();
|
||||
HWTexture *CopyCurrentScreen();
|
||||
void ReleaseDefaultPoolItems();
|
||||
void KillNativePals();
|
||||
void KillNativeTexs();
|
||||
PackedTexture *AllocPackedTexture(int width, int height, bool wrapping, int format);
|
||||
void DrawPackedTextures(int packnum);
|
||||
void DrawLetterbox();
|
||||
void Draw3DPart(bool copy3d);
|
||||
bool SetStyle(OpenGLTex *tex, DrawParms &parms, uint32_t &color0, uint32_t &color1, BufferedTris &quad);
|
||||
static int GetStyleAlpha(int type);
|
||||
static void SetColorOverlay(uint32_t color, float alpha, uint32_t &color0, uint32_t &color1);
|
||||
void AddColorOnlyQuad(int left, int top, int width, int height, uint32_t color);
|
||||
void AddColorOnlyRect(int left, int top, int width, int height, uint32_t color);
|
||||
void CheckQuadBatch(int numtris = 2, int numverts = 4);
|
||||
void BeginQuadBatch();
|
||||
void EndQuadBatch();
|
||||
void BeginLineBatch();
|
||||
void EndLineBatch();
|
||||
void EndBatch();
|
||||
|
||||
// State
|
||||
void EnableAlphaTest(bool enabled);
|
||||
void SetAlphaBlend(int op, int srcblend = 0, int destblend = 0);
|
||||
void SetConstant(int cnum, float r, float g, float b, float a);
|
||||
void SetPixelShader(HWPixelShader *shader);
|
||||
void SetTexture(int tnum, HWTexture *texture);
|
||||
void SetSamplerWrapS(int tnum, int mode);
|
||||
void SetSamplerWrapT(int tnum, int mode);
|
||||
void SetPaletteTexture(HWTexture *texture, int count, uint32_t border_color);
|
||||
|
||||
template<typename T> static void SafeRelease(T &x) { if (x != nullptr) { delete x; x = nullptr; } }
|
||||
|
||||
std::shared_ptr<FGLDebug> Debug;
|
||||
|
||||
std::unique_ptr<HWVertexBuffer> StreamVertexBuffer, StreamVertexBufferBurn;
|
||||
float ShaderConstants[NumPSCONST * 4];
|
||||
HWPixelShader *CurrentShader = nullptr;
|
||||
|
||||
HWFrameBuffer *OutputFB = nullptr;
|
||||
|
||||
bool AlphaTestEnabled = false;
|
||||
bool AlphaBlendEnabled = false;
|
||||
int AlphaBlendOp = 0;
|
||||
int AlphaSrcBlend = 0;
|
||||
int AlphaDestBlend = 0;
|
||||
float Constant[3][4];
|
||||
uint32_t CurBorderColor;
|
||||
HWPixelShader *CurPixelShader;
|
||||
HWTexture *Texture[5];
|
||||
int SamplerWrapS[5], SamplerWrapT[5];
|
||||
|
||||
PalEntry SourcePalette[256];
|
||||
uint32_t BorderColor;
|
||||
uint32_t FlashColor0, FlashColor1;
|
||||
PalEntry FlashColor;
|
||||
int FlashAmount;
|
||||
int TrueHeight;
|
||||
int PixelDoubling;
|
||||
int LBOffsetI;
|
||||
float LBOffset;
|
||||
float Gamma;
|
||||
bool UpdatePending;
|
||||
bool NeedPalUpdate;
|
||||
bool NeedGammaUpdate;
|
||||
int FBWidth, FBHeight;
|
||||
bool VSync;
|
||||
LTRBRect BlendingRect;
|
||||
int In2D;
|
||||
bool InScene;
|
||||
bool GatheringWipeScreen;
|
||||
bool AALines;
|
||||
uint8_t BlockNum;
|
||||
OpenGLPal *Palettes = nullptr;
|
||||
OpenGLTex *Textures = nullptr;
|
||||
Atlas *Atlases = nullptr;
|
||||
|
||||
HWTexture *FBTexture = nullptr;
|
||||
HWTexture *PaletteTexture = nullptr;
|
||||
HWTexture *ScreenshotTexture = nullptr;
|
||||
|
||||
HWVertexBuffer *VertexBuffer = nullptr;
|
||||
FBVERTEX *VertexData = nullptr;
|
||||
HWIndexBuffer *IndexBuffer = nullptr;
|
||||
uint16_t *IndexData = nullptr;
|
||||
BufferedTris *QuadExtra = nullptr;
|
||||
int VertexPos;
|
||||
int IndexPos;
|
||||
int QuadBatchPos;
|
||||
enum { BATCH_None, BATCH_Quads, BATCH_Lines } BatchType;
|
||||
|
||||
HWPixelShader *Shaders[NUM_SHADERS];
|
||||
|
||||
HWTexture *InitialWipeScreen = nullptr, *FinalWipeScreen = nullptr;
|
||||
|
||||
class Wiper
|
||||
{
|
||||
public:
|
||||
virtual ~Wiper();
|
||||
virtual bool Run(int ticks, OpenGLSWFrameBuffer *fb) = 0;
|
||||
|
||||
void DrawScreen(OpenGLSWFrameBuffer *fb, HWTexture *tex, int blendop = 0, uint32_t color0 = 0, uint32_t color1 = 0xFFFFFFF);
|
||||
};
|
||||
|
||||
class Wiper_Melt; friend class Wiper_Melt;
|
||||
class Wiper_Burn; friend class Wiper_Burn;
|
||||
class Wiper_Crossfade; friend class Wiper_Crossfade;
|
||||
|
||||
Wiper *ScreenWipe;
|
||||
};
|
||||
|
||||
|
||||
#endif //__GL_SWFRAMEBUFFER
|
592
src/gl/system/gl_swwipe.cpp
Normal file
592
src/gl/system/gl_swwipe.cpp
Normal file
|
@ -0,0 +1,592 @@
|
|||
/*
|
||||
** gl_swwipe.cpp
|
||||
** Implements the different screen wipes using OpenGL calls.
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 1998-2008 Randy Heit
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
**
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
*/
|
||||
|
||||
// HEADER FILES ------------------------------------------------------------
|
||||
|
||||
#include "gl/system/gl_system.h"
|
||||
#include "files.h"
|
||||
#include "m_swap.h"
|
||||
#include "v_video.h"
|
||||
#include "doomstat.h"
|
||||
#include "m_png.h"
|
||||
#include "m_crc32.h"
|
||||
#include "vectors.h"
|
||||
#include "v_palette.h"
|
||||
#include "templates.h"
|
||||
|
||||
#include "c_dispatch.h"
|
||||
#include "templates.h"
|
||||
#include "i_system.h"
|
||||
#include "i_video.h"
|
||||
#include "i_input.h"
|
||||
#include "v_pfx.h"
|
||||
#include "stats.h"
|
||||
#include "doomerrors.h"
|
||||
#include "r_main.h"
|
||||
#include "r_data/r_translate.h"
|
||||
#include "f_wipe.h"
|
||||
#include "sbar.h"
|
||||
#include "w_wad.h"
|
||||
#include "r_data/colormaps.h"
|
||||
|
||||
#include "gl/system/gl_interface.h"
|
||||
#include "gl/system/gl_swframebuffer.h"
|
||||
#include "gl/data/gl_data.h"
|
||||
#include "gl/utility/gl_clock.h"
|
||||
#include "gl/utility/gl_templates.h"
|
||||
#include "gl/gl_functions.h"
|
||||
#include "gl_debug.h"
|
||||
#include "m_random.h"
|
||||
|
||||
class OpenGLSWFrameBuffer::Wiper_Crossfade : public OpenGLSWFrameBuffer::Wiper
|
||||
{
|
||||
public:
|
||||
Wiper_Crossfade();
|
||||
bool Run(int ticks, OpenGLSWFrameBuffer *fb);
|
||||
|
||||
private:
|
||||
int Clock;
|
||||
};
|
||||
|
||||
class OpenGLSWFrameBuffer::Wiper_Melt : public OpenGLSWFrameBuffer::Wiper
|
||||
{
|
||||
public:
|
||||
Wiper_Melt();
|
||||
bool Run(int ticks, OpenGLSWFrameBuffer *fb);
|
||||
|
||||
private:
|
||||
// Match the strip sizes that oldschool Doom used.
|
||||
static const int WIDTH = 160, HEIGHT = 200;
|
||||
int y[WIDTH];
|
||||
};
|
||||
|
||||
class OpenGLSWFrameBuffer::Wiper_Burn : public OpenGLSWFrameBuffer::Wiper
|
||||
{
|
||||
public:
|
||||
Wiper_Burn(OpenGLSWFrameBuffer *fb);
|
||||
~Wiper_Burn();
|
||||
bool Run(int ticks, OpenGLSWFrameBuffer *fb);
|
||||
|
||||
private:
|
||||
static const int WIDTH = 64, HEIGHT = 64;
|
||||
uint8_t BurnArray[WIDTH * (HEIGHT + 5)];
|
||||
HWTexture *BurnTexture;
|
||||
int Density;
|
||||
int BurnTime;
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// OpenGLSWFrameBuffer :: WipeStartScreen
|
||||
//
|
||||
// Called before the current screen has started rendering. This needs to
|
||||
// save what was drawn the previous frame so that it can be animated into
|
||||
// what gets drawn this frame.
|
||||
//
|
||||
// In fullscreen mode, we use GetFrontBufferData() to grab the data that
|
||||
// is visible on screen right now.
|
||||
//
|
||||
// In windowed mode, we can't do that because we'll get the whole desktop.
|
||||
// Instead, we can conveniently use the TempRenderTexture, which is normally
|
||||
// used for gamma-correcting copying the image to the back buffer.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
bool OpenGLSWFrameBuffer::WipeStartScreen(int type)
|
||||
{
|
||||
if (!Accel2D)
|
||||
{
|
||||
return Super::WipeStartScreen(type);
|
||||
}
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case wipe_Melt:
|
||||
ScreenWipe = new Wiper_Melt;
|
||||
break;
|
||||
|
||||
case wipe_Burn:
|
||||
ScreenWipe = new Wiper_Burn(this);
|
||||
break;
|
||||
|
||||
case wipe_Fade:
|
||||
ScreenWipe = new Wiper_Crossfade;
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
InitialWipeScreen = CopyCurrentScreen();
|
||||
|
||||
// Make even fullscreen model render to the TempRenderTexture, so
|
||||
// we can have a copy of the new screen readily available.
|
||||
GatheringWipeScreen = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// OpenGLSWFrameBuffer :: WipeEndScreen
|
||||
//
|
||||
// The screen we want to animate to has just been drawn. This function is
|
||||
// called in place of Update(), so it has not been Presented yet.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void OpenGLSWFrameBuffer::WipeEndScreen()
|
||||
{
|
||||
if (!Accel2D)
|
||||
{
|
||||
Super::WipeEndScreen();
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't do anything if there is no starting point.
|
||||
if (InitialWipeScreen == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// If the whole screen was drawn without 2D accel, get it in to
|
||||
// video memory now.
|
||||
if (!In2D)
|
||||
{
|
||||
Begin2D(true);
|
||||
}
|
||||
|
||||
EndBatch(); // Make sure all batched primitives have been drawn.
|
||||
|
||||
FinalWipeScreen = CopyCurrentScreen();
|
||||
|
||||
// At this point, InitialWipeScreen holds the screen we are wiping from.
|
||||
// FinalWipeScreen holds the screen we are wiping to, which may be the
|
||||
// same texture as TempRenderTexture.
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// OpenGLSWFrameBuffer :: WipeDo
|
||||
//
|
||||
// Perform the actual wipe animation. The number of tics since the last
|
||||
// time this function was called is passed in. Returns true when the wipe
|
||||
// is over. The first time this function has been called, the screen is
|
||||
// still locked from before and EndScene() still has not been called.
|
||||
// Successive times need to call BeginScene().
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
bool OpenGLSWFrameBuffer::WipeDo(int ticks)
|
||||
{
|
||||
if (!Accel2D)
|
||||
{
|
||||
return Super::WipeDo(ticks);
|
||||
}
|
||||
|
||||
// Sanity checks.
|
||||
if (InitialWipeScreen == NULL || FinalWipeScreen == NULL)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (GatheringWipeScreen)
|
||||
{ // This is the first time we've been called for this wipe.
|
||||
GatheringWipeScreen = false;
|
||||
}
|
||||
else
|
||||
{ // This is the second or later time we've been called for this wipe.
|
||||
InScene = true;
|
||||
}
|
||||
|
||||
In2D = 3;
|
||||
|
||||
EnableAlphaTest(false);
|
||||
bool done = ScreenWipe->Run(ticks, this);
|
||||
DrawLetterbox();
|
||||
return done;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// OpenGLSWFrameBuffer :: WipeCleanup
|
||||
//
|
||||
// Release any resources that were specifically created for the wipe.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void OpenGLSWFrameBuffer::WipeCleanup()
|
||||
{
|
||||
if (ScreenWipe != NULL)
|
||||
{
|
||||
delete ScreenWipe;
|
||||
ScreenWipe = NULL;
|
||||
}
|
||||
SafeRelease( InitialWipeScreen );
|
||||
SafeRelease( FinalWipeScreen );
|
||||
GatheringWipeScreen = false;
|
||||
if (!Accel2D)
|
||||
{
|
||||
Super::WipeCleanup();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// OpenGLSWFrameBuffer :: Wiper Constructor
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
OpenGLSWFrameBuffer::Wiper::~Wiper()
|
||||
{
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// OpenGLSWFrameBuffer :: Wiper :: DrawScreen
|
||||
//
|
||||
// Draw either the initial or target screen completely to the screen.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void OpenGLSWFrameBuffer::Wiper::DrawScreen(OpenGLSWFrameBuffer *fb, HWTexture *tex,
|
||||
int blendop, uint32_t color0, uint32_t color1)
|
||||
{
|
||||
FBVERTEX verts[4];
|
||||
|
||||
fb->CalcFullscreenCoords(verts, false, false, color0, color1);
|
||||
fb->SetTexture(0, tex);
|
||||
fb->SetAlphaBlend(blendop, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
fb->SetPixelShader(fb->Shaders[SHADER_NormalColor]);
|
||||
fb->DrawTriangleFans(2, verts);
|
||||
}
|
||||
|
||||
// WIPE: CROSSFADE ---------------------------------------------------------
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// OpenGLSWFrameBuffer :: Wiper_Crossfade Constructor
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
OpenGLSWFrameBuffer::Wiper_Crossfade::Wiper_Crossfade()
|
||||
: Clock(0)
|
||||
{
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// OpenGLSWFrameBuffer :: Wiper_Crossfade :: Run
|
||||
//
|
||||
// Fades the old screen into the new one over 32 ticks.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
bool OpenGLSWFrameBuffer::Wiper_Crossfade::Run(int ticks, OpenGLSWFrameBuffer *fb)
|
||||
{
|
||||
Clock += ticks;
|
||||
|
||||
// Put the initial screen back to the buffer.
|
||||
DrawScreen(fb, fb->InitialWipeScreen);
|
||||
|
||||
// Draw the new screen on top of it.
|
||||
DrawScreen(fb, fb->FinalWipeScreen, GL_FUNC_ADD, ColorValue(0,0,0,Clock / 32.f), ColorRGBA(255,255,255,0));
|
||||
|
||||
return Clock >= 32;
|
||||
}
|
||||
|
||||
// WIPE: MELT --------------------------------------------------------------
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// OpenGLSWFrameBuffer :: Wiper_Melt Constructor
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
OpenGLSWFrameBuffer::Wiper_Melt::Wiper_Melt()
|
||||
{
|
||||
int i, r;
|
||||
|
||||
// setup initial column positions
|
||||
// (y<0 => not ready to scroll yet)
|
||||
y[0] = -(M_Random() & 15);
|
||||
for (i = 1; i < WIDTH; ++i)
|
||||
{
|
||||
r = (M_Random()%3) - 1;
|
||||
y[i] = clamp(y[i-1] + r, -15, 0);
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// OpenGLSWFrameBuffer :: Wiper_Melt :: Run
|
||||
//
|
||||
// Fades the old screen into the new one over 32 ticks.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
bool OpenGLSWFrameBuffer::Wiper_Melt::Run(int ticks, OpenGLSWFrameBuffer *fb)
|
||||
{
|
||||
// Draw the new screen on the bottom.
|
||||
DrawScreen(fb, fb->FinalWipeScreen);
|
||||
|
||||
int i, dy;
|
||||
int fbwidth = fb->Width;
|
||||
int fbheight = fb->Height;
|
||||
bool done = true;
|
||||
|
||||
// Copy the old screen in vertical strips on top of the new one.
|
||||
while (ticks--)
|
||||
{
|
||||
done = true;
|
||||
for (i = 0; i < WIDTH; i++)
|
||||
{
|
||||
if (y[i] < 0)
|
||||
{
|
||||
y[i]++;
|
||||
done = false;
|
||||
}
|
||||
else if (y[i] < HEIGHT)
|
||||
{
|
||||
dy = (y[i] < 16) ? y[i]+1 : 8;
|
||||
y[i] = MIN(y[i] + dy, HEIGHT);
|
||||
done = false;
|
||||
}
|
||||
if (ticks == 0)
|
||||
{ // Only draw for the final tick.
|
||||
RECT rect;
|
||||
POINT dpt;
|
||||
|
||||
dpt.x = i * fbwidth / WIDTH;
|
||||
dpt.y = MAX(0, y[i] * fbheight / HEIGHT);
|
||||
rect.left = dpt.x;
|
||||
rect.top = 0;
|
||||
rect.right = (i + 1) * fbwidth / WIDTH;
|
||||
rect.bottom = fbheight - dpt.y;
|
||||
if (rect.bottom > rect.top)
|
||||
{
|
||||
fb->CheckQuadBatch();
|
||||
|
||||
BufferedTris *quad = &fb->QuadExtra[fb->QuadBatchPos];
|
||||
FBVERTEX *vert = &fb->VertexData[fb->VertexPos];
|
||||
WORD *index = &fb->IndexData[fb->IndexPos];
|
||||
|
||||
quad->ClearSetup();
|
||||
quad->Flags = BQF_DisableAlphaTest;
|
||||
quad->ShaderNum = BQS_Plain;
|
||||
quad->Palette = NULL;
|
||||
quad->Texture = fb->InitialWipeScreen;
|
||||
quad->NumVerts = 4;
|
||||
quad->NumTris = 2;
|
||||
|
||||
// Fill the vertex buffer.
|
||||
float u0 = rect.left / float(fb->FBWidth);
|
||||
float v0 = 0;
|
||||
float u1 = rect.right / float(fb->FBWidth);
|
||||
float v1 = (rect.bottom - rect.top) / float(fb->FBHeight);
|
||||
|
||||
float x0 = float(rect.left) - 0.5f;
|
||||
float x1 = float(rect.right) - 0.5f;
|
||||
float y0 = float(dpt.y + fb->LBOffsetI) - 0.5f;
|
||||
float y1 = float(fbheight + fb->LBOffsetI) - 0.5f;
|
||||
|
||||
vert[0].x = x0;
|
||||
vert[0].y = y0;
|
||||
vert[0].z = 0;
|
||||
vert[0].rhw = 1;
|
||||
vert[0].color0 = 0;
|
||||
vert[0].color1 = 0xFFFFFFF;
|
||||
vert[0].tu = u0;
|
||||
vert[0].tv = v0;
|
||||
|
||||
vert[1].x = x1;
|
||||
vert[1].y = y0;
|
||||
vert[1].z = 0;
|
||||
vert[1].rhw = 1;
|
||||
vert[1].color0 = 0;
|
||||
vert[1].color1 = 0xFFFFFFF;
|
||||
vert[1].tu = u1;
|
||||
vert[1].tv = v0;
|
||||
|
||||
vert[2].x = x1;
|
||||
vert[2].y = y1;
|
||||
vert[2].z = 0;
|
||||
vert[2].rhw = 1;
|
||||
vert[2].color0 = 0;
|
||||
vert[2].color1 = 0xFFFFFFF;
|
||||
vert[2].tu = u1;
|
||||
vert[2].tv = v1;
|
||||
|
||||
vert[3].x = x0;
|
||||
vert[3].y = y1;
|
||||
vert[3].z = 0;
|
||||
vert[3].rhw = 1;
|
||||
vert[3].color0 = 0;
|
||||
vert[3].color1 = 0xFFFFFFF;
|
||||
vert[3].tu = u0;
|
||||
vert[3].tv = v1;
|
||||
|
||||
// Fill the vertex index buffer.
|
||||
index[0] = fb->VertexPos;
|
||||
index[1] = fb->VertexPos + 1;
|
||||
index[2] = fb->VertexPos + 2;
|
||||
index[3] = fb->VertexPos;
|
||||
index[4] = fb->VertexPos + 2;
|
||||
index[5] = fb->VertexPos + 3;
|
||||
|
||||
// Batch the quad.
|
||||
fb->QuadBatchPos++;
|
||||
fb->VertexPos += 4;
|
||||
fb->IndexPos += 6;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fb->EndQuadBatch();
|
||||
return done;
|
||||
}
|
||||
|
||||
// WIPE: BURN --------------------------------------------------------------
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// OpenGLSWFrameBuffer :: Wiper_Burn Constructor
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
OpenGLSWFrameBuffer::Wiper_Burn::Wiper_Burn(OpenGLSWFrameBuffer *fb)
|
||||
{
|
||||
Density = 4;
|
||||
BurnTime = 0;
|
||||
memset(BurnArray, 0, sizeof(BurnArray));
|
||||
if (fb->Shaders[SHADER_BurnWipe] == NULL || !fb->CreateTexture("BurnWipe", WIDTH, HEIGHT, 1, GL_R8, &BurnTexture))
|
||||
{
|
||||
BurnTexture = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// OpenGLSWFrameBuffer :: Wiper_Burn Destructor
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
OpenGLSWFrameBuffer::Wiper_Burn::~Wiper_Burn()
|
||||
{
|
||||
SafeRelease( BurnTexture );
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// OpenGLSWFrameBuffer :: Wiper_Burn :: Run
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
bool OpenGLSWFrameBuffer::Wiper_Burn::Run(int ticks, OpenGLSWFrameBuffer *fb)
|
||||
{
|
||||
bool done;
|
||||
|
||||
BurnTime += ticks;
|
||||
ticks *= 2;
|
||||
|
||||
// Make the fire burn
|
||||
done = false;
|
||||
while (!done && ticks--)
|
||||
{
|
||||
Density = wipe_CalcBurn(BurnArray, WIDTH, HEIGHT, Density);
|
||||
done = (Density < 0);
|
||||
}
|
||||
|
||||
// Update the burn texture with the new burn data
|
||||
|
||||
if (BurnTexture->Buffers[0] == 0)
|
||||
{
|
||||
glGenBuffers(2, (GLuint*)BurnTexture->Buffers);
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, BurnTexture->Buffers[0]);
|
||||
glBufferData(GL_PIXEL_UNPACK_BUFFER, WIDTH * HEIGHT, nullptr, GL_STREAM_DRAW);
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, BurnTexture->Buffers[1]);
|
||||
glBufferData(GL_PIXEL_UNPACK_BUFFER, WIDTH * HEIGHT, nullptr, GL_STREAM_DRAW);
|
||||
}
|
||||
else
|
||||
{
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, BurnTexture->Buffers[BurnTexture->CurrentBuffer]);
|
||||
BurnTexture->CurrentBuffer = (BurnTexture->CurrentBuffer + 1) & 1;
|
||||
}
|
||||
|
||||
uint8_t *dest = (uint8_t*)glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, WIDTH * HEIGHT, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
|
||||
if (dest)
|
||||
{
|
||||
memcpy(dest, BurnArray, WIDTH * HEIGHT);
|
||||
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
|
||||
|
||||
GLint oldBinding = 0;
|
||||
glGetIntegerv(GL_TEXTURE_BINDING_2D, &oldBinding);
|
||||
glBindTexture(GL_TEXTURE_2D, BurnTexture->Texture);
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, WIDTH, HEIGHT, GL_RED, GL_UNSIGNED_BYTE, 0);
|
||||
glBindTexture(GL_TEXTURE_2D, oldBinding);
|
||||
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||
}
|
||||
|
||||
// Put the initial screen back to the buffer.
|
||||
DrawScreen(fb, fb->InitialWipeScreen);
|
||||
|
||||
// Burn the new screen on top of it.
|
||||
float top = fb->LBOffset - 0.5f;
|
||||
float right = float(fb->Width) - 0.5f;
|
||||
float bot = float(fb->Height) + top;
|
||||
float texright = float(fb->Width) / float(fb->FBWidth);
|
||||
float texbot = float(fb->Height) / float(fb->FBHeight);
|
||||
|
||||
BURNVERTEX verts[4] =
|
||||
{
|
||||
{ -0.5f, top, 0.5f, 1.f, 0.f, 0.f, 0, 0 },
|
||||
{ right, top, 0.5f, 1.f, texright, 0.f, 1, 0 },
|
||||
{ right, bot, 0.5f, 1.f, texright, texbot, 1, 1 },
|
||||
{ -0.5f, bot, 0.5f, 1.f, 0.f, texbot, 0, 1 }
|
||||
};
|
||||
|
||||
fb->SetTexture(0, fb->FinalWipeScreen);
|
||||
fb->SetTexture(1, BurnTexture);
|
||||
fb->SetAlphaBlend(GL_FUNC_ADD, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
fb->SetPixelShader(fb->Shaders[SHADER_BurnWipe]);
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
fb->DrawTriangleFans(2, verts);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
// The fire may not always stabilize, so the wipe is forced to end
|
||||
// after an arbitrary maximum time.
|
||||
return done || (BurnTime > 40);
|
||||
}
|
|
@ -312,6 +312,7 @@ public:
|
|||
static void FlipNonSquareBlockRemap (BYTE *blockto, const BYTE *blockfrom, int x, int y, int srcpitch, const BYTE *remap);
|
||||
|
||||
friend class D3DTex;
|
||||
friend class OpenGLSWFrameBuffer;
|
||||
|
||||
public:
|
||||
|
||||
|
|
|
@ -137,9 +137,13 @@ void I_InitGraphics ()
|
|||
val.Bool = !!Args->CheckParm ("-devparm");
|
||||
ticker.SetGenericRepDefault (val, CVAR_Bool);
|
||||
|
||||
//currentrenderer = vid_renderer;
|
||||
if (currentrenderer==1) Video = gl_CreateVideo();
|
||||
else Video = new Win32Video (0);
|
||||
//#define USE_D3D9_VIDEO
|
||||
#ifdef USE_D3D9_VIDEO
|
||||
if (currentrenderer == 1) Video = gl_CreateVideo();
|
||||
else Video = new Win32Video(0);
|
||||
#else
|
||||
Video = gl_CreateVideo();
|
||||
#endif
|
||||
|
||||
if (Video == NULL)
|
||||
I_FatalError ("Failed to initialize display");
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
#include "gl/renderer/gl_renderer.h"
|
||||
#include "gl/system/gl_framebuffer.h"
|
||||
#include "gl/system/gl_swframebuffer.h"
|
||||
|
||||
extern "C" {
|
||||
_declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
|
||||
|
@ -387,7 +388,10 @@ DFrameBuffer *Win32GLVideo::CreateFrameBuffer(int width, int height, bool bgra,
|
|||
//old->GetFlash(flashColor, flashAmount);
|
||||
delete old;
|
||||
}
|
||||
fb = new OpenGLFrameBuffer(m_hMonitor, m_DisplayWidth, m_DisplayHeight, m_DisplayBits, m_DisplayHz, fs);
|
||||
if (vid_renderer == 1)
|
||||
fb = new OpenGLFrameBuffer(m_hMonitor, m_DisplayWidth, m_DisplayHeight, m_DisplayBits, m_DisplayHz, fs);
|
||||
else
|
||||
fb = new OpenGLSWFrameBuffer(m_hMonitor, m_DisplayWidth, m_DisplayHeight, m_DisplayBits, m_DisplayHz, fs);
|
||||
return fb;
|
||||
}
|
||||
|
||||
|
|
146
wadsrc/static/shaders/glsl/swshader.fp
Normal file
146
wadsrc/static/shaders/glsl/swshader.fp
Normal file
|
@ -0,0 +1,146 @@
|
|||
|
||||
in vec4 PixelColor0;
|
||||
in vec4 PixelColor1;
|
||||
in vec4 PixelTexCoord0;
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
uniform sampler2D Image;
|
||||
uniform sampler2D Palette;
|
||||
uniform sampler2D NewScreen;
|
||||
uniform sampler2D Burn;
|
||||
|
||||
uniform vec4 Desaturation; // { Desat, 1 - Desat }
|
||||
uniform vec4 PaletteMod;
|
||||
uniform vec4 Weights; // RGB->Gray weighting { 77/256.0, 143/256.0, 37/256.0, 1 }
|
||||
uniform vec4 Gamma;
|
||||
|
||||
vec4 TextureLookup(vec2 tex_coord)
|
||||
{
|
||||
#if PALTEX
|
||||
float index = texture(Image, tex_coord).x;
|
||||
index = index * PaletteMod.x + PaletteMod.y;
|
||||
return texture(Palette, vec2(index, 0.5));
|
||||
#else
|
||||
return texture(Image, tex_coord);
|
||||
#endif
|
||||
}
|
||||
|
||||
vec4 Invert(vec4 rgb)
|
||||
{
|
||||
#if INVERT
|
||||
rgb.rgb = Weights.www - rgb.xyz;
|
||||
#endif
|
||||
return rgb;
|
||||
}
|
||||
|
||||
float Grayscale(vec4 rgb)
|
||||
{
|
||||
return dot(rgb.rgb, Weights.rgb);
|
||||
}
|
||||
|
||||
vec4 SampleTexture(vec2 tex_coord)
|
||||
{
|
||||
return Invert(TextureLookup(tex_coord));
|
||||
}
|
||||
|
||||
// Normal color calculation for most drawing modes.
|
||||
|
||||
vec4 NormalColor(vec2 tex_coord, vec4 Flash, vec4 InvFlash)
|
||||
{
|
||||
return Flash + SampleTexture(tex_coord) * InvFlash;
|
||||
}
|
||||
|
||||
// Copy the red channel to the alpha channel. Pays no attention to palettes.
|
||||
|
||||
vec4 RedToAlpha(vec2 tex_coord, vec4 Flash, vec4 InvFlash)
|
||||
{
|
||||
vec4 color = Invert(texture(Image, tex_coord));
|
||||
color.a = color.r;
|
||||
return Flash + color * InvFlash;
|
||||
}
|
||||
|
||||
// Just return the value of c0.
|
||||
|
||||
vec4 VertexColor(vec4 color)
|
||||
{
|
||||
return color;
|
||||
}
|
||||
|
||||
// Emulate one of the special colormaps. (Invulnerability, gold, etc.)
|
||||
|
||||
vec4 SpecialColormap(vec2 tex_coord, vec4 start, vec4 end)
|
||||
{
|
||||
vec4 color = SampleTexture(tex_coord);
|
||||
vec4 range = end - start;
|
||||
// We can't store values greater than 1.0 in a color register, so we multiply
|
||||
// the final result by 2 and expect the caller to divide the start and end by 2.
|
||||
color.rgb = 2 * (start + Grayscale(color) * range).rgb;
|
||||
// Duplicate alpha semantics of NormalColor.
|
||||
color.a = start.a + color.a * end.a;
|
||||
return color;
|
||||
}
|
||||
|
||||
// In-game colormap effect: fade to a particular color and multiply by another, with
|
||||
// optional desaturation of the original color. Desaturation is stored in c1.
|
||||
// Fade level is packed int fade.a. Fade.rgb has been premultiplied by alpha.
|
||||
// Overall alpha is in color.a.
|
||||
vec4 InGameColormap(vec2 tex_coord, vec4 color, vec4 fade)
|
||||
{
|
||||
vec4 rgb = SampleTexture(tex_coord);
|
||||
|
||||
// Desaturate
|
||||
#if DESAT
|
||||
vec3 intensity;
|
||||
intensity.rgb = vec3(Grayscale(rgb) * Desaturation.x);
|
||||
rgb.rgb = intensity.rgb + rgb.rgb * Desaturation.y;
|
||||
#endif
|
||||
|
||||
// Fade
|
||||
rgb.rgb = rgb.rgb * fade.aaa + fade.rgb;
|
||||
|
||||
// Shade and Alpha
|
||||
rgb = rgb * color;
|
||||
|
||||
return rgb;
|
||||
}
|
||||
|
||||
// Windowed gamma correction.
|
||||
|
||||
vec4 GammaCorrection(vec2 tex_coord)
|
||||
{
|
||||
vec4 color = texture(Image, tex_coord);
|
||||
color.rgb = pow(color.rgb, Gamma.rgb);
|
||||
return color;
|
||||
}
|
||||
|
||||
// The burn wipe effect.
|
||||
|
||||
vec4 BurnWipe(vec4 coord)
|
||||
{
|
||||
vec4 color = texture(NewScreen, coord.xy);
|
||||
vec4 alpha = texture(Burn, coord.zw);
|
||||
color.a = alpha.r * 2;
|
||||
return color;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
#if defined(ENORMALCOLOR)
|
||||
FragColor = NormalColor(PixelTexCoord0.xy, PixelColor0, PixelColor1);
|
||||
#elif defined(EREDTOALPHA)
|
||||
FragColor = RedToAlpha(PixelTexCoord0.xy, PixelColor0, PixelColor1);
|
||||
#elif defined(EVERTEXCOLOR)
|
||||
FragColor = VertexColor(PixelColor0);
|
||||
#elif defined(ESPECIALCOLORMAP)
|
||||
FragColor = SpecialColormap(PixelTexCoord0.xy, PixelColor0, PixelColor1);
|
||||
#elif defined(EINGAMECOLORMAP)
|
||||
FragColor = InGameColormap(PixelTexCoord0.xy, PixelColor0, PixelColor1);
|
||||
#elif defined(EBURNWIPE)
|
||||
FragColor = BurnWipe(PixelTexCoord0);
|
||||
#elif defined(EGAMMACORRECTION)
|
||||
FragColor = GammaCorrection(PixelTexCoord0.xy);
|
||||
#else
|
||||
#error Entry point define is missing
|
||||
#endif
|
||||
}
|
22
wadsrc/static/shaders/glsl/swshader.vp
Normal file
22
wadsrc/static/shaders/glsl/swshader.vp
Normal file
|
@ -0,0 +1,22 @@
|
|||
|
||||
in vec4 AttrPosition;
|
||||
in vec4 AttrColor0;
|
||||
in vec4 AttrColor1;
|
||||
in vec4 AttrTexCoord0;
|
||||
|
||||
out vec4 PixelColor0;
|
||||
out vec4 PixelColor1;
|
||||
out vec4 PixelTexCoord0;
|
||||
|
||||
uniform vec4 ScreenSize;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(AttrPosition.xy / ScreenSize.xy * 2.0 - 1.0, 1.0, 1.0);
|
||||
#if defined(EGAMMACORRECTION)
|
||||
gl_Position.y = -gl_Position.y;
|
||||
#endif
|
||||
PixelColor0 = AttrColor0.bgra;
|
||||
PixelColor1 = AttrColor1.bgra;
|
||||
PixelTexCoord0 = AttrTexCoord0;
|
||||
}
|
Loading…
Reference in a new issue