#pragma once #include #include #include #include #include "gl_samplers.h" #include "gl_hwtexture.h" #include "matrix.h" #include "palentry.h" #include "renderstyle.h" #include "hw_material.h" #include "hw_renderstate.h" #include "pm_renderstate.h" #include "templates.h" class FShader; class FGameTexture; class GLInstance; class F2DDrawer; struct palette_t; extern int xdim, ydim; enum { DM_MAINVIEW, DM_OFFSCREEN }; class PaletteManager { IHardwareTexture* palettetextures[256] = {}; IHardwareTexture* lookuptextures[256] = {}; GLInstance* const inst; unsigned FindPalswap(const uint8_t* paldata, palette_t& fadecolor); public: PaletteManager(GLInstance *inst_) : inst(inst_) {} ~PaletteManager(); void DeleteAll(); IHardwareTexture *GetPalette(int index); IHardwareTexture* GetLookup(int index); }; struct glinfo_t { float maxanisotropy; }; enum ECullSide { Cull_Front, Cull_Back }; enum EWinding { Winding_CCW, Winding_CW }; struct ImDrawData; struct palette_t; enum { MAX_TEXTURES = 4, /*15*/ // slot 15 is used internally and not available. - The renderer uses only 5, though. }; struct GLState { int Flags; int DepthFunc; }; class GLInstance { friend IHardwareTexture* setpalettelayer(int layer, int translation); public: TArray rendercommands; PaletteManager palmanager; int lastPalswapIndex = -1; FGameTexture* currentTexture = nullptr; int MatrixChange = 0; PolymostRenderState renderState; public: float mProjectionM5 = 1.0f; // needed by ssao glinfo_t glinfo; void Init(int y); void InitGLState(int fogmode, int multisample); void Deinit(); static int GetTexDimension(int value) { //if (value > gl.max_texturesize) return gl.max_texturesize; return value; } GLInstance(); void Draw(EDrawType type, size_t start, size_t count); void DoDraw(); float GetProjectionM5() { return mProjectionM5; } int SetMatrix(int num, const VSMatrix *mat ); int SetMatrix(int num, const float *mat) { return SetMatrix(num, reinterpret_cast(mat)); } void SetIdentityMatrix(int num); void RestoreMatrix(int num, int index) { renderState.matrixIndex[num] = index; } void SetTextureMode(int m) { renderState.TextureMode = m; } void SetDepthBias(float a, float b) { renderState.mBias.mFactor = a; renderState.mBias.mUnits = b; renderState.mBias.mChanged = true; } void ClearDepthBias() { renderState.mBias.mFactor = 0; renderState.mBias.mUnits = 0; renderState.mBias.mChanged = true; } void SetPalswap(int index); void SetShade(int32_t shade, int numshades) { renderState.Shade = clamp(shade, 0, numshades-1); } void SetVisibility(float visibility) { renderState.VisFactor = visibility; } void EnableBlend(bool on) { if (on) renderState.StateFlags |= STF_BLEND; else renderState.StateFlags &= ~STF_BLEND; } void EnableDepthTest(bool on) { if (on) renderState.StateFlags |= STF_DEPTHTEST; else renderState.StateFlags &= ~STF_DEPTHTEST; } void EnableStencilWrite(int value) { renderState.StateFlags |= STF_STENCILWRITE; renderState.StateFlags &= ~STF_STENCILTEST; } void EnableStencilTest(int value) { renderState.StateFlags &= ~STF_STENCILWRITE; renderState.StateFlags |= STF_STENCILTEST; } void DisableStencil() { renderState.StateFlags &= ~(STF_STENCILWRITE | STF_STENCILTEST); } void SetCull(int type, int winding = Winding_CW) { renderState.StateFlags &= ~(STF_CULLCCW | STF_CULLCW); if (type != Cull_None) { if (winding == Winding_CW) renderState.StateFlags |= STF_CULLCW; else renderState.StateFlags |= STF_CULLCCW; } } void SetColorMask(bool on) { if (on) renderState.StateFlags |= STF_COLORMASK; else renderState.StateFlags &= ~STF_COLORMASK; } void SetDepthMask(bool on) { if (on) renderState.StateFlags |= STF_DEPTHMASK; else renderState.StateFlags &= ~STF_DEPTHMASK; } void ClearScreen(PalEntry pe, bool depth) { renderState.ClearColor = pe; renderState.StateFlags |= STF_CLEARCOLOR; if (depth) renderState.StateFlags |= STF_CLEARDEPTH; } void SetViewport(int x, int y, int w, int h) { renderState.vp_x = (short)x; renderState.vp_y = (short)y; renderState.vp_w = (short)w; renderState.vp_h = (short)h; renderState.StateFlags |= STF_VIEWPORTSET; } void SetScissor(int x1, int y1, int x2, int y2) { renderState.sc_x = (short)x1; renderState.sc_y = (short)y1; renderState.sc_w = (short)x2; renderState.sc_h = (short)y2; renderState.StateFlags |= STF_SCISSORSET; } void DisableScissor() { renderState.sc_x = SHRT_MIN; renderState.StateFlags |= STF_SCISSORSET; } void SetDepthFunc(int func) { renderState.DepthFunc = func; } void ClearScreen(PalEntry pe) { //twod->Clear(); SetViewport(0, 0, xdim, ydim); ClearScreen(pe, true); } void ClearDepth() { renderState.StateFlags |= STF_CLEARDEPTH; } void SetRenderStyle(FRenderStyle style) { renderState.Style = style; } void SetColor(float r, float g, float b, float a = 1.f) { renderState.Color[0] = r; renderState.Color[1] = g; renderState.Color[2] = b; renderState.Color[3] = a; } void SetColorub(uint8_t r, uint8_t g, uint8_t b, uint8_t a = 255) { SetColor(r * (1 / 255.f), g * (1 / 255.f), b * (1 / 255.f), a * (1 / 255.f)); } void SetMaterial(FMaterial* mat, int clampmode, int translation, int overrideshader) { assert(mat); renderState.mMaterial.mMaterial = mat; renderState.mMaterial.mClampMode = clampmode; renderState.mMaterial.mTranslation = translation; renderState.mMaterial.mOverrideShader = overrideshader; renderState.mMaterial.mChanged = true; //mTextureModeFlags = mat->GetLayerFlags(); } void SetMaterial(FGameTexture* tex, EUpscaleFlags upscalemask, int scaleflags, int clampmode, int translation, int overrideshader) { assert(tex); if (shouldUpscale(tex, upscalemask)) scaleflags |= CTF_Upscale; SetMaterial(FMaterial::ValidateTexture(tex, scaleflags), clampmode, translation, overrideshader); } void UseColorOnly(bool yes) { if (yes) renderState.Flags |= RF_ColorOnly; else renderState.Flags &= ~RF_ColorOnly; } void SetNpotEmulation(float factor, float xOffset) { renderState.NPOTEmulation.Y = factor; renderState.NPOTEmulation.X = xOffset; } void SetShadeInterpolate(int32_t yes) { if (yes) renderState.Flags |= RF_ShadeInterpolate; else renderState.Flags &= ~RF_ShadeInterpolate; } void SetFadeDisable(bool yes) { if (yes) renderState.Flags |= RF_FogDisabled; else renderState.Flags &= ~RF_FogDisabled; } // Hack... bool useMapFog = false; void SetMapFog(bool yes) { useMapFog = yes; } void applyMapFog() { if (useMapFog) renderState.Flags |= RF_MapFog; else renderState.Flags &= ~RF_MapFog; } void clearMapFog() { renderState.Flags &= ~RF_MapFog; } void SetTinting(int flags, PalEntry color, PalEntry overlayColor) { renderState.hictint = color; renderState.hictint_overlay = overlayColor; renderState.hictint_flags = flags; } void SetBasepalTint(PalEntry color) { renderState.fullscreenTint = color; } void EnableAlphaTest(bool on) { renderState.AlphaTest = on; } void SetAlphaThreshold(float al) { renderState.AlphaThreshold = al; } bool SetTexture(int globalpicnum, FGameTexture* tex, int palette, int sampleroverride); }; extern GLInstance GLInterface; void renderSetProjectionMatrix(const float* p); void renderSetViewMatrix(const float* p); void renderSetVisibility(float v); void renderBeginScene(); void renderFinishScene(); void DrawRateStuff();