mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-11 15:21:51 +00:00
- added back sprite splitting for low end, plus some dynamic light code.
This commit is contained in:
parent
89f36fb963
commit
6e1b21d513
7 changed files with 737 additions and 9 deletions
|
@ -141,3 +141,94 @@ bool gl_GetLight(int group, Plane & p, ADynamicLight * light, bool checkside, bo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// Sets up the parameters to render one dynamic light onto one plane
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
bool gl_SetupLight(int group, Plane & p, ADynamicLight * light, Vector & nearPt, Vector & up, Vector & right,
|
||||||
|
float & scale, int desaturation, bool checkside, bool forceadditive)
|
||||||
|
{
|
||||||
|
Vector fn, pos;
|
||||||
|
|
||||||
|
DVector3 lpos = light->PosRelative(group);
|
||||||
|
|
||||||
|
float dist = fabsf(p.DistToPoint(lpos.X, lpos.Z, lpos.Y));
|
||||||
|
float radius = (light->GetRadius() * gl_lights_size);
|
||||||
|
|
||||||
|
if (radius <= 0.f) return false;
|
||||||
|
if (dist > radius) return false;
|
||||||
|
if (checkside && gl_lights_checkside && p.PointOnSide(lpos.X, lpos.Z, lpos.Y))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (light->owned && light->target != NULL && !light->target->IsVisibleToPlayer())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
scale = 1.0f / ((2.f * radius) - dist);
|
||||||
|
|
||||||
|
// project light position onto plane (find closest point on plane)
|
||||||
|
|
||||||
|
|
||||||
|
pos.Set(lpos.X, lpos.Z, lpos.Y);
|
||||||
|
fn = p.Normal();
|
||||||
|
fn.GetRightUp(right, up);
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
nearPt = pos + fn * dist;
|
||||||
|
#else
|
||||||
|
Vector tmpVec = fn * dist;
|
||||||
|
nearPt = pos + tmpVec;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
float cs = 1.0f - (dist / radius);
|
||||||
|
if (gl_lights_additive || light->flags4&MF4_ADDITIVE || forceadditive) cs *= 0.2f; // otherwise the light gets too strong.
|
||||||
|
float r = light->GetRed() / 255.0f * cs * gl_lights_intensity;
|
||||||
|
float g = light->GetGreen() / 255.0f * cs * gl_lights_intensity;
|
||||||
|
float b = light->GetBlue() / 255.0f * cs * gl_lights_intensity;
|
||||||
|
|
||||||
|
if (light->IsSubtractive())
|
||||||
|
{
|
||||||
|
Vector v;
|
||||||
|
|
||||||
|
gl_RenderState.BlendEquation(GL_FUNC_REVERSE_SUBTRACT);
|
||||||
|
v.Set(r, g, b);
|
||||||
|
r = v.Length() - r;
|
||||||
|
g = v.Length() - g;
|
||||||
|
b = v.Length() - b;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gl_RenderState.BlendEquation(GL_FUNC_ADD);
|
||||||
|
}
|
||||||
|
if (desaturation > 0 && gl.glslversion > 0) // no-shader excluded because no desaturated textures.
|
||||||
|
{
|
||||||
|
float gray = (r * 77 + g * 143 + b * 37) / 257;
|
||||||
|
|
||||||
|
r = (r*(32 - desaturation) + gray*desaturation) / 32;
|
||||||
|
g = (g*(32 - desaturation) + gray*desaturation) / 32;
|
||||||
|
b = (b*(32 - desaturation) + gray*desaturation) / 32;
|
||||||
|
}
|
||||||
|
glColor3f(r, g, b);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
bool gl_SetupLightTexture()
|
||||||
|
{
|
||||||
|
|
||||||
|
if (GLRenderer->gllight == NULL) return false;
|
||||||
|
FMaterial * pat = FMaterial::ValidateTexture(GLRenderer->gllight, true);
|
||||||
|
pat->Bind(CLAMP_XY, 0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
|
@ -71,6 +71,7 @@ public:
|
||||||
unsigned int mFBID;
|
unsigned int mFBID;
|
||||||
unsigned int mVAOID;
|
unsigned int mVAOID;
|
||||||
|
|
||||||
|
FTexture *gllight;
|
||||||
FTexture *glpart2;
|
FTexture *glpart2;
|
||||||
FTexture *glpart;
|
FTexture *glpart;
|
||||||
FTexture *mirrortexture;
|
FTexture *mirrortexture;
|
||||||
|
|
|
@ -372,6 +372,54 @@ inline void GLSprite::PutSprite(bool translucent)
|
||||||
gl_drawinfo->drawlists[list].AddSprite(this);
|
gl_drawinfo->drawlists[list].AddSprite(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
void GLSprite::SplitSprite(sector_t * frontsector, bool translucent)
|
||||||
|
{
|
||||||
|
GLSprite copySprite;
|
||||||
|
double lightbottom;
|
||||||
|
unsigned int i;
|
||||||
|
bool put=false;
|
||||||
|
TArray<lightlist_t> & lightlist=frontsector->e->XFloor.lightlist;
|
||||||
|
|
||||||
|
for(i=0;i<lightlist.Size();i++)
|
||||||
|
{
|
||||||
|
// Particles don't go through here so we can safely assume that actor is not NULL
|
||||||
|
if (i<lightlist.Size()-1) lightbottom=lightlist[i+1].plane.ZatPoint(actor);
|
||||||
|
else lightbottom=frontsector->floorplane.ZatPoint(actor);
|
||||||
|
|
||||||
|
if (lightbottom<z2) lightbottom=z2;
|
||||||
|
|
||||||
|
if (lightbottom<z1)
|
||||||
|
{
|
||||||
|
copySprite=*this;
|
||||||
|
copySprite.lightlevel = gl_ClampLight(*lightlist[i].p_lightlevel);
|
||||||
|
copySprite.Colormap.CopyLightColor(lightlist[i].extra_colormap);
|
||||||
|
|
||||||
|
if (glset.nocoloredspritelighting)
|
||||||
|
{
|
||||||
|
copySprite.Colormap.Decolorize();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!gl_isWhite(ThingColor))
|
||||||
|
{
|
||||||
|
copySprite.Colormap.LightColor.r=(copySprite.Colormap.LightColor.r*ThingColor.r)>>8;
|
||||||
|
copySprite.Colormap.LightColor.g=(copySprite.Colormap.LightColor.g*ThingColor.g)>>8;
|
||||||
|
copySprite.Colormap.LightColor.b=(copySprite.Colormap.LightColor.b*ThingColor.b)>>8;
|
||||||
|
}
|
||||||
|
|
||||||
|
z1=copySprite.z2=lightbottom;
|
||||||
|
vt=copySprite.vb=copySprite.vt+
|
||||||
|
(lightbottom-copySprite.z1)*(copySprite.vb-copySprite.vt)/(z2-copySprite.z1);
|
||||||
|
copySprite.PutSprite(translucent);
|
||||||
|
put=true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
|
@ -722,7 +770,7 @@ void GLSprite::Process(AActor* thing, sector_t * sector, bool thruportal)
|
||||||
RenderStyle.CheckFuzz();
|
RenderStyle.CheckFuzz();
|
||||||
if (RenderStyle.BlendOp == STYLEOP_Fuzz)
|
if (RenderStyle.BlendOp == STYLEOP_Fuzz)
|
||||||
{
|
{
|
||||||
if (gl_fuzztype != 0)
|
if (gl_fuzztype != 0 && gl.glslversion > 0)
|
||||||
{
|
{
|
||||||
// Todo: implement shader selection here
|
// Todo: implement shader selection here
|
||||||
RenderStyle = LegacyRenderStyles[STYLE_Translucent];
|
RenderStyle = LegacyRenderStyles[STYLE_Translucent];
|
||||||
|
@ -819,7 +867,18 @@ void GLSprite::Process(AActor* thing, sector_t * sector, bool thruportal)
|
||||||
if (thing->Sector->e->XFloor.lightlist.Size() != 0 && gl_fixedcolormap == CM_DEFAULT && !fullbright &&
|
if (thing->Sector->e->XFloor.lightlist.Size() != 0 && gl_fixedcolormap == CM_DEFAULT && !fullbright &&
|
||||||
RenderStyle.BlendOp != STYLEOP_Shadow && RenderStyle.BlendOp != STYLEOP_RevSub)
|
RenderStyle.BlendOp != STYLEOP_Shadow && RenderStyle.BlendOp != STYLEOP_RevSub)
|
||||||
{
|
{
|
||||||
lightlist = &thing->Sector->e->XFloor.lightlist;
|
if (gl.glslversion < 1.3) // on old hardware we are rather limited...
|
||||||
|
{
|
||||||
|
lightlist = NULL;
|
||||||
|
if (!drawWithXYBillboard && !modelframe)
|
||||||
|
{
|
||||||
|
SplitSprite(thing->Sector, hw_styleflags != STYLEHW_Solid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lightlist = &thing->Sector->e->XFloor.lightlist;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -350,6 +350,7 @@ public:
|
||||||
particle_t * particle;
|
particle_t * particle;
|
||||||
TArray<lightlist_t> *lightlist;
|
TArray<lightlist_t> *lightlist;
|
||||||
|
|
||||||
|
void SplitSprite(sector_t * frontsector, bool translucent);
|
||||||
void SetLowerParam();
|
void SetLowerParam();
|
||||||
void PerformSpriteClipAdjustment(AActor *thing, const DVector2 &thingpos, float spriteheight);
|
void PerformSpriteClipAdjustment(AActor *thing, const DVector2 &thingpos, float spriteheight);
|
||||||
|
|
||||||
|
|
|
@ -31,10 +31,11 @@
|
||||||
**
|
**
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "gl/system/gl_load.h"
|
||||||
|
|
||||||
#include "i_common.h"
|
#include "i_common.h"
|
||||||
|
|
||||||
#import <Carbon/Carbon.h>
|
#import <Carbon/Carbon.h>
|
||||||
#import <OpenGL/gl.h>
|
|
||||||
|
|
||||||
// Avoid collision between DObject class and Objective-C
|
// Avoid collision between DObject class and Objective-C
|
||||||
#define Class ObjectClass
|
#define Class ObjectClass
|
||||||
|
@ -45,6 +46,7 @@
|
||||||
#include "hardware.h"
|
#include "hardware.h"
|
||||||
#include "i_system.h"
|
#include "i_system.h"
|
||||||
#include "m_argv.h"
|
#include "m_argv.h"
|
||||||
|
#include "m_png.h"
|
||||||
#include "r_renderer.h"
|
#include "r_renderer.h"
|
||||||
#include "r_swrenderer.h"
|
#include "r_swrenderer.h"
|
||||||
#include "st_console.h"
|
#include "st_console.h"
|
||||||
|
@ -56,6 +58,11 @@
|
||||||
#include "v_video.h"
|
#include "v_video.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
|
||||||
|
#include "gl/renderer/gl_renderer.h"
|
||||||
|
#include "gl/system/gl_framebuffer.h"
|
||||||
|
#include "gl/system/gl_interface.h"
|
||||||
|
#include "gl/utility/gl_clock.h"
|
||||||
|
|
||||||
#undef Class
|
#undef Class
|
||||||
|
|
||||||
|
|
||||||
|
@ -111,6 +118,41 @@ CUSTOM_CVAR(Bool, vid_autoswitch, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_
|
||||||
Printf("You must restart " GAMENAME " to apply graphics switching mode\n");
|
Printf("You must restart " GAMENAME " to apply graphics switching mode\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int s_currentRenderer;
|
||||||
|
|
||||||
|
CUSTOM_CVAR(Int, vid_renderer, 1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
|
||||||
|
{
|
||||||
|
// 0: Software renderer
|
||||||
|
// 1: OpenGL renderer
|
||||||
|
|
||||||
|
if (self != s_currentRenderer)
|
||||||
|
{
|
||||||
|
switch (self)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
Printf("Switching to software renderer...\n");
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
Printf("Switching to OpenGL renderer...\n");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Printf("Unknown renderer (%d). Falling back to software renderer...\n",
|
||||||
|
static_cast<int>(vid_renderer));
|
||||||
|
self = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Printf("You must restart " GAMENAME " to switch the renderer\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CUSTOM_CVAR(Int, gl_vid_multisample, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
|
||||||
|
{
|
||||||
|
Printf("This won't take effect until " GAMENAME " is restarted.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
EXTERN_CVAR(Bool, gl_smooth_rendered)
|
||||||
|
|
||||||
|
|
||||||
RenderBufferOptions rbOpts;
|
RenderBufferOptions rbOpts;
|
||||||
|
|
||||||
|
@ -187,7 +229,6 @@ namespace
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
@ -235,6 +276,9 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
class CocoaFrameBuffer : public DFrameBuffer
|
class CocoaFrameBuffer : public DFrameBuffer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -286,6 +330,83 @@ private:
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
class NonCopyable
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
NonCopyable() { }
|
||||||
|
~NonCopyable() { }
|
||||||
|
|
||||||
|
private:
|
||||||
|
NonCopyable(const NonCopyable&);
|
||||||
|
const NonCopyable& operator=(const NonCopyable&);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
class RenderTarget : private NonCopyable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RenderTarget(const GLsizei width, const GLsizei height);
|
||||||
|
~RenderTarget();
|
||||||
|
|
||||||
|
void Bind();
|
||||||
|
void Unbind();
|
||||||
|
|
||||||
|
FHardwareTexture& GetColorTexture()
|
||||||
|
{
|
||||||
|
return m_texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
GLuint m_ID;
|
||||||
|
GLuint m_oldID;
|
||||||
|
|
||||||
|
FHardwareTexture m_texture;
|
||||||
|
|
||||||
|
static GLuint GetBoundID();
|
||||||
|
|
||||||
|
}; // class RenderTarget
|
||||||
|
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
struct CapabilityChecker
|
||||||
|
{
|
||||||
|
CapabilityChecker();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
class CocoaOpenGLFrameBuffer : public OpenGLFrameBuffer, private CapabilityChecker, private NonCopyable
|
||||||
|
{
|
||||||
|
typedef OpenGLFrameBuffer Super;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CocoaOpenGLFrameBuffer(void* hMonitor, int width, int height, int bits, int refreshHz, bool fullscreen);
|
||||||
|
|
||||||
|
virtual bool Lock(bool buffered);
|
||||||
|
virtual void Update();
|
||||||
|
|
||||||
|
virtual void GetScreenshotBuffer(const BYTE*& buffer, int& pitch, ESSType& color_type);
|
||||||
|
|
||||||
|
virtual void SetSmoothPicture(bool smooth);
|
||||||
|
|
||||||
|
private:
|
||||||
|
RenderTarget m_renderTarget;
|
||||||
|
|
||||||
|
void DrawRenderTarget();
|
||||||
|
|
||||||
|
}; // class CocoaOpenGLFrameBuffer
|
||||||
|
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
EXTERN_CVAR(Float, Gamma)
|
EXTERN_CVAR(Float, Gamma)
|
||||||
|
|
||||||
CUSTOM_CVAR(Float, rgamma, 1.0f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
CUSTOM_CVAR(Float, rgamma, 1.0f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||||
|
@ -542,7 +663,17 @@ DFrameBuffer* CocoaVideo::CreateFrameBuffer(const int width, const int height, c
|
||||||
delete old;
|
delete old;
|
||||||
}
|
}
|
||||||
|
|
||||||
CocoaFrameBuffer* fb = new CocoaFrameBuffer(width, height, fullscreen);
|
DFrameBuffer* fb = NULL;
|
||||||
|
|
||||||
|
if (1 == s_currentRenderer)
|
||||||
|
{
|
||||||
|
fb = new CocoaOpenGLFrameBuffer(NULL, width, height, 32, 60, fullscreen);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fb = new CocoaFrameBuffer(width, height, fullscreen);
|
||||||
|
}
|
||||||
|
|
||||||
fb->SetFlash(flashColor, flashAmount);
|
fb->SetFlash(flashColor, flashAmount);
|
||||||
|
|
||||||
SetMode(width, height, fullscreen, vid_hidpi);
|
SetMode(width, height, fullscreen, vid_hidpi);
|
||||||
|
@ -762,6 +893,9 @@ CocoaVideo* CocoaVideo::GetInstance()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
CocoaFrameBuffer::CocoaFrameBuffer(int width, int height, bool fullscreen)
|
CocoaFrameBuffer::CocoaFrameBuffer(int width, int height, bool fullscreen)
|
||||||
: DFrameBuffer(width, height)
|
: DFrameBuffer(width, height)
|
||||||
, m_needPaletteUpdate(false)
|
, m_needPaletteUpdate(false)
|
||||||
|
@ -772,6 +906,14 @@ CocoaFrameBuffer::CocoaFrameBuffer(int width, int height, bool fullscreen)
|
||||||
, m_pixelBuffer(new uint8_t[width * height * BYTES_PER_PIXEL])
|
, m_pixelBuffer(new uint8_t[width * height * BYTES_PER_PIXEL])
|
||||||
, m_texture(0)
|
, m_texture(0)
|
||||||
{
|
{
|
||||||
|
static bool isOpenGLInitialized;
|
||||||
|
|
||||||
|
if (!isOpenGLInitialized)
|
||||||
|
{
|
||||||
|
ogl_LoadFunctions();
|
||||||
|
isOpenGLInitialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
glEnable(GL_TEXTURE_RECTANGLE_ARB);
|
glEnable(GL_TEXTURE_RECTANGLE_ARB);
|
||||||
|
|
||||||
glGenTextures(1, &m_texture);
|
glGenTextures(1, &m_texture);
|
||||||
|
@ -1011,6 +1153,423 @@ void CocoaFrameBuffer::Flip()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
static const uint32_t GAMMA_TABLE_ALPHA = 0xFF000000;
|
||||||
|
|
||||||
|
|
||||||
|
SDLGLFB::SDLGLFB(void*, const int width, const int height, int, int, const bool fullscreen)
|
||||||
|
: DFrameBuffer(width, height)
|
||||||
|
, m_lock(-1)
|
||||||
|
, m_isUpdatePending(false)
|
||||||
|
, m_supportsGamma(true)
|
||||||
|
, m_gammaTexture(GAMMA_TABLE_SIZE, 1, false, false, true, true)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SDLGLFB::SDLGLFB()
|
||||||
|
: m_gammaTexture(0, 0, false, false, false, false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SDLGLFB::~SDLGLFB()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SDLGLFB::Lock(bool buffered)
|
||||||
|
{
|
||||||
|
m_lock++;
|
||||||
|
|
||||||
|
Buffer = MemBuffer;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SDLGLFB::Unlock()
|
||||||
|
{
|
||||||
|
if (m_isUpdatePending && 1 == m_lock)
|
||||||
|
{
|
||||||
|
Update();
|
||||||
|
}
|
||||||
|
else if (--m_lock <= 0)
|
||||||
|
{
|
||||||
|
m_lock = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SDLGLFB::IsLocked()
|
||||||
|
{
|
||||||
|
return m_lock > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool SDLGLFB::IsFullscreen()
|
||||||
|
{
|
||||||
|
return CocoaVideo::IsFullscreen();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SDLGLFB::SetVSync(bool vsync)
|
||||||
|
{
|
||||||
|
#if MAC_OS_X_VERSION_MAX_ALLOWED < 1050
|
||||||
|
const long value = vsync ? 1 : 0;
|
||||||
|
#else // 10.5 or newer
|
||||||
|
const GLint value = vsync ? 1 : 0;
|
||||||
|
#endif // prior to 10.5
|
||||||
|
|
||||||
|
[[NSOpenGLContext currentContext] setValues:&value
|
||||||
|
forParameter:NSOpenGLCPSwapInterval];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SDLGLFB::InitializeState()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SDLGLFB::CanUpdate()
|
||||||
|
{
|
||||||
|
if (m_lock != 1)
|
||||||
|
{
|
||||||
|
if (m_lock > 0)
|
||||||
|
{
|
||||||
|
m_isUpdatePending = true;
|
||||||
|
--m_lock;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SDLGLFB::SwapBuffers()
|
||||||
|
{
|
||||||
|
[[NSOpenGLContext currentContext] flushBuffer];
|
||||||
|
}
|
||||||
|
|
||||||
|
void SDLGLFB::SetGammaTable(WORD* table)
|
||||||
|
{
|
||||||
|
const WORD* const red = &table[ 0];
|
||||||
|
const WORD* const green = &table[256];
|
||||||
|
const WORD* const blue = &table[512];
|
||||||
|
|
||||||
|
for (size_t i = 0; i < GAMMA_TABLE_SIZE; ++i)
|
||||||
|
{
|
||||||
|
// Convert 16 bits colors to 8 bits by dividing on 256
|
||||||
|
|
||||||
|
const uint32_t r = red[i] >> 8;
|
||||||
|
const uint32_t g = green[i] >> 8;
|
||||||
|
const uint32_t b = blue[i] >> 8;
|
||||||
|
|
||||||
|
m_gammaTable[i] = GAMMA_TABLE_ALPHA + (b << 16) + (g << 8) + r;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_gammaTexture.CreateTexture(
|
||||||
|
reinterpret_cast<unsigned char*>(m_gammaTable),
|
||||||
|
GAMMA_TABLE_SIZE, 1, false, 1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
void BoundTextureSetFilter(const GLenum target, const GLint filter)
|
||||||
|
{
|
||||||
|
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, filter);
|
||||||
|
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, filter);
|
||||||
|
|
||||||
|
glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BoundTextureDraw2D(const GLsizei width, const GLsizei height)
|
||||||
|
{
|
||||||
|
const bool flipX = width < 0;
|
||||||
|
const bool flipY = height < 0;
|
||||||
|
|
||||||
|
const float u0 = flipX ? 1.0f : 0.0f;
|
||||||
|
const float v0 = flipY ? 1.0f : 0.0f;
|
||||||
|
const float u1 = flipX ? 0.0f : 1.0f;
|
||||||
|
const float v1 = flipY ? 0.0f : 1.0f;
|
||||||
|
|
||||||
|
const float x1 = 0.0f;
|
||||||
|
const float y1 = 0.0f;
|
||||||
|
const float x2 = abs(width );
|
||||||
|
const float y2 = abs(height);
|
||||||
|
|
||||||
|
glDisable(GL_BLEND);
|
||||||
|
glDisable(GL_ALPHA_TEST);
|
||||||
|
|
||||||
|
glBegin(GL_QUADS);
|
||||||
|
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||||
|
glTexCoord2f(u0, v1);
|
||||||
|
glVertex2f(x1, y1);
|
||||||
|
glTexCoord2f(u1, v1);
|
||||||
|
glVertex2f(x2, y1);
|
||||||
|
glTexCoord2f(u1, v0);
|
||||||
|
glVertex2f(x2, y2);
|
||||||
|
glTexCoord2f(u0, v0);
|
||||||
|
glVertex2f(x1, y2);
|
||||||
|
glEnd();
|
||||||
|
|
||||||
|
glEnable(GL_ALPHA_TEST);
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BoundTextureSaveAsPNG(const GLenum target, const char* const path)
|
||||||
|
{
|
||||||
|
if (NULL == path)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLint width = 0;
|
||||||
|
GLint height = 0;
|
||||||
|
|
||||||
|
glGetTexLevelParameteriv(target, 0, GL_TEXTURE_WIDTH, &width );
|
||||||
|
glGetTexLevelParameteriv(target, 0, GL_TEXTURE_HEIGHT, &height);
|
||||||
|
|
||||||
|
if (0 == width || 0 == height)
|
||||||
|
{
|
||||||
|
Printf("BoundTextureSaveAsPNG: invalid texture size %ix%i\n", width, height);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const int BYTES_PER_PIXEL = 4;
|
||||||
|
|
||||||
|
const int imageSize = width * height * BYTES_PER_PIXEL;
|
||||||
|
unsigned char* imageBuffer = static_cast<unsigned char*>(malloc(imageSize));
|
||||||
|
|
||||||
|
if (NULL == imageBuffer)
|
||||||
|
{
|
||||||
|
Printf("BoundTextureSaveAsPNG: cannot allocate %i bytes\n", imageSize);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
glGetTexImage(target, 0, GL_BGRA, GL_UNSIGNED_BYTE, imageBuffer);
|
||||||
|
|
||||||
|
const int lineSize = width * BYTES_PER_PIXEL;
|
||||||
|
unsigned char lineBuffer[lineSize];
|
||||||
|
|
||||||
|
for (GLint line = 0; line < height / 2; ++line)
|
||||||
|
{
|
||||||
|
void* frontLinePtr = &imageBuffer[line * lineSize];
|
||||||
|
void* backLinePtr = &imageBuffer[(height - line - 1) * lineSize];
|
||||||
|
|
||||||
|
memcpy( lineBuffer, frontLinePtr, lineSize);
|
||||||
|
memcpy(frontLinePtr, backLinePtr, lineSize);
|
||||||
|
memcpy( backLinePtr, lineBuffer, lineSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE* file = fopen(path, "w");
|
||||||
|
|
||||||
|
if (NULL == file)
|
||||||
|
{
|
||||||
|
Printf("BoundTextureSaveAsPNG: cannot open file %s\n", path);
|
||||||
|
|
||||||
|
free(imageBuffer);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool result =
|
||||||
|
M_CreatePNG(file, &imageBuffer[0], NULL, SS_BGRA, width, height, width * BYTES_PER_PIXEL)
|
||||||
|
&& M_FinishPNG(file);
|
||||||
|
|
||||||
|
fclose(file);
|
||||||
|
|
||||||
|
free(imageBuffer);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
RenderTarget::RenderTarget(const GLsizei width, const GLsizei height)
|
||||||
|
: m_ID(0)
|
||||||
|
, m_oldID(0)
|
||||||
|
, m_texture(width, height, false, false, true, true)
|
||||||
|
{
|
||||||
|
glGenFramebuffersEXT(1, &m_ID);
|
||||||
|
|
||||||
|
Bind();
|
||||||
|
m_texture.CreateTexture(NULL, width, height, false, 0, 0);
|
||||||
|
m_texture.BindToFrameBuffer();
|
||||||
|
Unbind();
|
||||||
|
}
|
||||||
|
|
||||||
|
RenderTarget::~RenderTarget()
|
||||||
|
{
|
||||||
|
glDeleteFramebuffersEXT(1, &m_ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RenderTarget::Bind()
|
||||||
|
{
|
||||||
|
const GLuint boundID = GetBoundID();
|
||||||
|
|
||||||
|
if (m_ID != boundID)
|
||||||
|
{
|
||||||
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_ID);
|
||||||
|
m_oldID = boundID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderTarget::Unbind()
|
||||||
|
{
|
||||||
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_oldID);
|
||||||
|
m_oldID = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GLuint RenderTarget::GetBoundID()
|
||||||
|
{
|
||||||
|
GLint result;
|
||||||
|
glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &result);
|
||||||
|
|
||||||
|
return static_cast<GLuint>(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
CapabilityChecker::CapabilityChecker()
|
||||||
|
{
|
||||||
|
if (!(gl.flags & RFL_FRAMEBUFFER))
|
||||||
|
{
|
||||||
|
I_FatalError(
|
||||||
|
"The graphics hardware in your system does not support Frame Buffer Object (FBO).\n"
|
||||||
|
"It is required to run this version of " GAMENAME ".\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
CocoaOpenGLFrameBuffer::CocoaOpenGLFrameBuffer(void* hMonitor, int width, int height, int bits, int refreshHz, bool fullscreen)
|
||||||
|
: OpenGLFrameBuffer(hMonitor, width, height, bits, refreshHz, fullscreen)
|
||||||
|
, m_renderTarget(width, height)
|
||||||
|
{
|
||||||
|
SetSmoothPicture(gl_smooth_rendered);
|
||||||
|
|
||||||
|
// Setup uniform samplers for gamma correction shader
|
||||||
|
|
||||||
|
m_gammaProgram.Load("GammaCorrection", "shaders/glsl/main.vp",
|
||||||
|
"shaders/glsl/gamma_correction.fp", NULL, "");
|
||||||
|
|
||||||
|
const GLuint program = m_gammaProgram.GetHandle();
|
||||||
|
|
||||||
|
glUseProgram(program);
|
||||||
|
glUniform1i(glGetUniformLocation(program, "backbuffer"), 0);
|
||||||
|
glUniform1i(glGetUniformLocation(program, "gammaTable"), 1);
|
||||||
|
glUseProgram(0);
|
||||||
|
|
||||||
|
// Fill render target with black color
|
||||||
|
|
||||||
|
m_renderTarget.Bind();
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
m_renderTarget.Unbind();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool CocoaOpenGLFrameBuffer::Lock(bool buffered)
|
||||||
|
{
|
||||||
|
if (0 == m_lock)
|
||||||
|
{
|
||||||
|
m_renderTarget.Bind();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Super::Lock(buffered);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CocoaOpenGLFrameBuffer::Update()
|
||||||
|
{
|
||||||
|
if (!CanUpdate())
|
||||||
|
{
|
||||||
|
GLRenderer->Flush();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Begin2D(false);
|
||||||
|
|
||||||
|
DrawRateStuff();
|
||||||
|
GLRenderer->Flush();
|
||||||
|
|
||||||
|
DrawRenderTarget();
|
||||||
|
|
||||||
|
Swap();
|
||||||
|
Unlock();
|
||||||
|
|
||||||
|
CheckBench();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CocoaOpenGLFrameBuffer::GetScreenshotBuffer(const BYTE*& buffer, int& pitch, ESSType& color_type)
|
||||||
|
{
|
||||||
|
m_renderTarget.Bind();
|
||||||
|
|
||||||
|
Super::GetScreenshotBuffer(buffer, pitch, color_type);
|
||||||
|
|
||||||
|
m_renderTarget.Unbind();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CocoaOpenGLFrameBuffer::DrawRenderTarget()
|
||||||
|
{
|
||||||
|
m_renderTarget.Unbind();
|
||||||
|
|
||||||
|
m_renderTarget.GetColorTexture().Bind(0, 0);
|
||||||
|
m_gammaTexture.Bind(1, 0);
|
||||||
|
|
||||||
|
if (rbOpts.dirty)
|
||||||
|
{
|
||||||
|
// TODO: Figure out why the following glClear() call is needed
|
||||||
|
// to avoid drawing of garbage in fullscreen mode when
|
||||||
|
// in-game's aspect ratio is different from display one
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
|
rbOpts.dirty = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
glViewport(rbOpts.shiftX, rbOpts.shiftY, rbOpts.width, rbOpts.height);
|
||||||
|
|
||||||
|
m_gammaProgram.Bind(0.0f);
|
||||||
|
BoundTextureDraw2D(Width, Height);
|
||||||
|
|
||||||
|
glViewport(0, 0, Width, Height);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CocoaOpenGLFrameBuffer::SetSmoothPicture(const bool smooth)
|
||||||
|
{
|
||||||
|
FHardwareTexture& texture = m_renderTarget.GetColorTexture();
|
||||||
|
texture.Bind(0, 0);
|
||||||
|
BoundTextureSetFilter(GL_TEXTURE_2D, smooth ? GL_LINEAR : GL_NEAREST);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
CUSTOM_CVAR(Bool, gl_smooth_rendered, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
|
||||||
|
{
|
||||||
|
if (NULL != screen)
|
||||||
|
{
|
||||||
|
screen->SetSmoothPicture(self);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
ADD_STAT(blit)
|
ADD_STAT(blit)
|
||||||
{
|
{
|
||||||
FString result;
|
FString result;
|
||||||
|
@ -1022,6 +1581,9 @@ ADD_STAT(blit)
|
||||||
IVideo* Video;
|
IVideo* Video;
|
||||||
|
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
void I_ShutdownGraphics()
|
void I_ShutdownGraphics()
|
||||||
{
|
{
|
||||||
if (NULL != screen)
|
if (NULL != screen)
|
||||||
|
@ -1042,7 +1604,7 @@ void I_InitGraphics()
|
||||||
val.Bool = !!Args->CheckParm("-devparm");
|
val.Bool = !!Args->CheckParm("-devparm");
|
||||||
ticker.SetGenericRepDefault(val, CVAR_Bool);
|
ticker.SetGenericRepDefault(val, CVAR_Bool);
|
||||||
|
|
||||||
Video = new CocoaVideo(0);
|
Video = new CocoaVideo(gl_vid_multisample);
|
||||||
atterm(I_ShutdownGraphics);
|
atterm(I_ShutdownGraphics);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1055,9 +1617,15 @@ static void I_DeleteRenderer()
|
||||||
|
|
||||||
void I_CreateRenderer()
|
void I_CreateRenderer()
|
||||||
{
|
{
|
||||||
|
s_currentRenderer = vid_renderer;
|
||||||
|
|
||||||
if (NULL == Renderer)
|
if (NULL == Renderer)
|
||||||
{
|
{
|
||||||
Renderer = new FSoftwareRenderer;
|
extern FRenderer* gl_CreateInterface();
|
||||||
|
|
||||||
|
Renderer = 1 == s_currentRenderer
|
||||||
|
? gl_CreateInterface()
|
||||||
|
: new FSoftwareRenderer;
|
||||||
atterm(I_DeleteRenderer);
|
atterm(I_DeleteRenderer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1129,6 +1697,9 @@ void I_ClosestResolution(int *width, int *height, int bits)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
EXTERN_CVAR(Int, vid_maxfps);
|
EXTERN_CVAR(Int, vid_maxfps);
|
||||||
EXTERN_CVAR(Bool, cl_capfps);
|
EXTERN_CVAR(Bool, cl_capfps);
|
||||||
|
|
||||||
|
@ -1167,6 +1738,9 @@ CUSTOM_CVAR(Bool, vid_hidpi, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
CCMD(vid_listmodes)
|
CCMD(vid_listmodes)
|
||||||
{
|
{
|
||||||
if (Video == NULL)
|
if (Video == NULL)
|
||||||
|
|
|
@ -416,6 +416,8 @@ public:
|
||||||
virtual bool Is8BitMode() = 0;
|
virtual bool Is8BitMode() = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
virtual void SetSmoothPicture(bool smooth) {}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void DrawRateStuff ();
|
void DrawRateStuff ();
|
||||||
void CopyFromBuff (BYTE *src, int srcPitch, int width, int height, BYTE *dest);
|
void CopyFromBuff (BYTE *src, int srcPitch, int width, int height, BYTE *dest);
|
||||||
|
|
|
@ -811,7 +811,7 @@ bool Win32GLVideo::InitHardware (HWND Window, int multisample)
|
||||||
|
|
||||||
if (m_hRC == NULL && prof == WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB)
|
if (m_hRC == NULL && prof == WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB)
|
||||||
{
|
{
|
||||||
I_Error ("R_OPENGL: Unable to create an OpenGL 3.x render context.\n");
|
I_Error ("R_OPENGL: Unable to create an OpenGL render context.\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -832,7 +832,7 @@ bool Win32GLVideo::InitHardware (HWND Window, int multisample)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// We get here if the driver doesn't support the modern context creation API which always means an old driver.
|
// We get here if the driver doesn't support the modern context creation API which always means an old driver.
|
||||||
I_Error ("R_OPENGL: Unable to create an OpenGL 3.x render context.\n");
|
I_Error ("R_OPENGL: Unable to create an OpenGL render context.\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue