openclonk/src/graphics/C4DrawGL.h

283 lines
9.1 KiB
Objective-C

/*
* OpenClonk, http://www.openclonk.org
*
* Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/
* Copyright (c) 2010-2016, The OpenClonk Team and contributors
*
* Distributed under the terms of the ISC license; see accompanying file
* "COPYING" for details.
*
* "Clonk" is a registered trademark of Matthes Bender, used with permission.
* See accompanying file "TRADEMARK" for details.
*
* To redistribute this file separately, substitute the full license texts
* for the above references.
*/
/* OpenGL implementation of NewGfx */
#if !defined(INC_StdGL) && !defined(USE_CONSOLE)
#define INC_StdGL
#ifdef _WIN32
#include "platform/C4windowswrapper.h"
#endif
#include <GL/glew.h>
#ifdef USE_COCOA
#import "ObjectiveCAssociated.h"
#endif
#include "graphics/C4Draw.h"
#include "graphics/C4Shader.h"
class C4Window;
class C4DrawGLError: public std::exception
{
public:
C4DrawGLError(const StdStrBuf& buf): Buf(buf) {}
virtual ~C4DrawGLError() throw() {}
virtual const char* what() const throw() { return Buf.getData(); }
private:
StdCopyStrBuf Buf;
};
// Uniform data we give the sprite shader (constants from its viewpoint)
enum C4SS_Uniforms
{
C4SSU_ProjectionMatrix, // 4x4
C4SSU_ModelViewMatrix, // 4x4
C4SSU_NormalMatrix, // 3x3, transpose-inverse of modelview matrix
C4SSU_ClrMod, // always
C4SSU_Gamma, // always
C4SSU_BaseTex, // C4SSC_BASE
C4SSU_OverlayTex, // C4SSC_OVERLAY
C4SSU_OverlayClr, // C4SSC_OVERLAY
C4SSU_LightTex, // C4SSC_LIGHT
C4SSU_LightTransform, // C4SSC_LIGHT
C4SSU_NormalTex, // C4SSC_LIGHT | C4SSC_NORMAL
C4SSU_AmbientTex, // C4SSC_LIGHT
C4SSU_AmbientTransform, // C4SSC_LIGHT
C4SSU_AmbientBrightness, // C4SSC_LIGHT
C4SSU_MaterialAmbient, // for meshes
C4SSU_MaterialDiffuse, // for meshes
C4SSU_MaterialSpecular, // for meshes
C4SSU_MaterialEmission, // for meshes
C4SSU_MaterialShininess, // for meshes
C4SSU_Bones, // for meshes
C4SSU_CullMode, // for meshes
C4SSU_FrameCounter, // for custom shaders
C4SSU_Count
};
// Attribute data for sprites and meshes
enum C4SS_Attributes
{
C4SSA_Position, // 2d for sprites, 3d for meshes
C4SSA_Normal, // meshes only
C4SSA_TexCoord, // 2d
C4SSA_Color, // sprites only, 4d
C4SSA_BoneIndices0,
C4SSA_BoneIndices1,
C4SSA_BoneWeights0,
C4SSA_BoneWeights1,
C4SSA_Count
};
// one OpenGL context
class CStdGLCtx
#ifdef USE_COCOA
: public ObjectiveCAssociated
#endif
{
public:
CStdGLCtx(); // ctor
~CStdGLCtx() { Clear(); } // dtor
void Clear(bool multisample_change = false); // clear objects
#ifdef USE_WGL
std::vector<int> EnumerateMultiSamples() const;
#endif
bool Init(C4Window * pWindow, C4AbstractApp *pApp);
bool Select(bool verbose = false); // select this context
void Deselect(); // select this context
bool PageFlip(); // present scene
protected:
void SelectCommon();
// this handles are declared as pointers to structs
C4Window * pWindow; // window to draw in
#ifdef USE_WGL
HDC hDC; // device context handle
#elif defined(USE_GTK)
/*GLXContext*/void * ctx;
#elif defined(USE_SDL_MAINLOOP)
void * ctx;
#endif
// Global list of all OpenGL contexts in use
static std::list<CStdGLCtx*> contexts;
std::list<CStdGLCtx*>::iterator this_context;
// VAOs available on this context
std::vector<GLuint> hVAOs;
// VAOs to be deleted the next time this context is being made current.
std::vector<unsigned int> VAOsToBeDeleted;
friend class CStdGL;
friend class C4Surface;
};
// OpenGL encapsulation
class CStdGL : public C4Draw
{
public:
CStdGL();
~CStdGL();
protected:
int iPixelFormat; // used pixel format
GLenum sfcFmt; // texture surface format
CStdGLCtx * pMainCtx; // main GL context
CStdGLCtx *pCurrCtx; // current context (owned if fullscreen)
// texture for smooth lines
GLuint lines_tex;
// The orthographic projection matrix
StdProjectionMatrix ProjectionMatrix;
// programs for drawing points, lines, quads
// Sprite shaders -- there is a variety of shaders to avoid
// conditionals in the GLSL code.
C4Shader SpriteShader;
C4Shader SpriteShaderMod2;
C4Shader SpriteShaderBase;
C4Shader SpriteShaderBaseMod2;
C4Shader SpriteShaderBaseOverlay;
C4Shader SpriteShaderBaseOverlayMod2;
C4Shader SpriteShaderLight;
C4Shader SpriteShaderLightMod2;
C4Shader SpriteShaderLightBase;
C4Shader SpriteShaderLightBaseMod2;
C4Shader SpriteShaderLightBaseOverlay;
C4Shader SpriteShaderLightBaseOverlayMod2;
C4Shader SpriteShaderLightBaseNormal;
C4Shader SpriteShaderLightBaseNormalMod2;
C4Shader SpriteShaderLightBaseNormalOverlay;
C4Shader SpriteShaderLightBaseNormalOverlayMod2;
// Generic VBOs for rendering arbitrary points, lines and
// triangles, used by PerformMultiBlt. Use more than one VBO, so that
// two PerformMultiBlt calls in quick succession can use two different
// buffers. Otherwise, the second call would need to wait until the
// rendering pipeline has actually drained the buffer. Each buffer
// starts with a fixed size. If more than this many vertices need to
// be rendered (can happen e.g. for PXS), then the buffer is resized.
static const unsigned int N_GENERIC_VBOS = 16;
static const unsigned int GENERIC_VBO_SIZE = 3 * 64; // vertices
GLuint GenericVBOs[N_GENERIC_VBOS];
unsigned int GenericVBOSizes[N_GENERIC_VBOS];
unsigned int CurrentVBO;
// We need twice as much VAOs, since the sprite rendering routines work
// both with and without textures (in which case we either need texture
// coordinates or not).
unsigned int GenericVAOs[N_GENERIC_VBOS * 2];
// VAO IDs currently in use.
std::set<unsigned int> VAOIDs;
std::set<unsigned int>::iterator NextVAOID;
public:
// Create a new (unique) VAO ID. A VAO ID is a number that identifies
// a certain VAO across all OpenGL contexts. This indirection is needed
// because, unlike most other GL state, VAOs are not shared between
// OpenGL contexts.
unsigned int GenVAOID();
// Free the given VAO ID, i.e. it can be re-used for new VAOs. This causes
// the VAO associated with this ID to be deleted in all OpenGL contexts.
void FreeVAOID(unsigned int vaoid);
// Return a VAO with the given vao ID in the "vao" output variable.
// If the function returns false, the VAO was newly created, otherwise
// an existing VAO is returned.
bool GetVAO(unsigned int vaoid, GLuint& vao);
// General
void Clear();
void Default();
virtual bool OnResolutionChanged(unsigned int iXRes, unsigned int iYRes); // reinit clipper for new resolution
// Clipper
bool UpdateClipper(); // set current clipper to render target
const StdProjectionMatrix& GetProjectionMatrix() const { return ProjectionMatrix; }
virtual bool PrepareMaterial(StdMeshMatManager& mat_manager, StdMeshMaterialLoader& loader, StdMeshMaterial& mat);
// Surface
virtual bool PrepareRendering(C4Surface * sfcToSurface); // check if/make rendering possible to given surface
virtual bool PrepareSpriteShader(C4Shader& shader, const char* name, int ssc, C4GroupSet* pGroups, const char* const* additionalDefines, const char* const* additionalSlices);
virtual CStdGLCtx *CreateContext(C4Window * pWindow, C4AbstractApp *pApp);
// Blit
void SetupMultiBlt(C4ShaderCall& call, const C4BltTransform* pTransform, GLuint baseTex, GLuint overlayTex, GLuint normalTex, DWORD dwOverlayModClr, StdProjectionMatrix* out_modelview);
virtual void PerformMesh(StdMeshInstance &instance, float tx, float ty, float twdt, float thgt, DWORD dwPlayerColor, C4BltTransform* pTransform);
void FillBG(DWORD dwClr=0);
// Drawing
virtual void PerformMultiPix(C4Surface* sfcTarget, const C4BltVertex* vertices, unsigned int n_vertices, C4ShaderCall* shader_call);
virtual void PerformMultiLines(C4Surface* sfcTarget, const C4BltVertex* vertices, unsigned int n_vertices, float width, C4ShaderCall* shader_call);
virtual void PerformMultiTris(C4Surface* sfcTarget, const C4BltVertex* vertices, unsigned int n_vertices, const C4BltTransform* pTransform, C4TexRef* pTex, C4TexRef* pOverlay, C4TexRef* pNormal, DWORD dwOverlayClrMod, C4ShaderCall* shader_call);
void PerformMultiBlt(C4Surface* sfcTarget, DrawOperation op, const C4BltVertex* vertices, unsigned int n_vertices, bool has_tex, C4ShaderCall* shader_call);
// device objects
bool RestoreDeviceObjects(); // restore device dependent objects
bool InvalidateDeviceObjects(); // free device dependent objects
bool DeviceReady() { return !!pMainCtx; }
bool InitShaders(C4GroupSet* pGroups); // load shaders from given group
C4Shader* GetSpriteShader(int ssc);
C4Shader* GetSpriteShader(bool haveBase, bool haveOverlay, bool haveNormal);
struct
{
bool LowMaxVertexUniformCount;
} Workarounds;
void ObjectLabel(uint32_t identifier, uint32_t name, int32_t length, const char * label);
protected:
bool CheckGLError(const char *szAtOp);
const char* GLErrorString(GLenum code);
virtual bool Error(const char *szMsg);
friend class C4Surface;
friend class C4TexRef;
friend class C4Pattern;
friend class CStdGLCtx;
friend class C4StartupOptionsDlg;
friend class C4FullScreen;
friend class C4Window;
friend class C4ShaderCall;
friend class C4FoWRegion;
};
// Global access pointer
extern CStdGL *pGL;
#endif // INC_StdGL