2013-06-23 07:49:34 +00:00
# ifndef __VERTEXBUFFER_H
# define __VERTEXBUFFER_H
# include "tarray.h"
2014-06-14 13:16:33 +00:00
# include "gl/utility/gl_clock.h"
2014-06-14 23:14:41 +00:00
# include "gl/system/gl_interface.h"
2013-06-23 07:49:34 +00:00
struct vertex_t ;
struct secplane_t ;
struct subsector_t ;
struct sector_t ;
class FVertexBuffer
{
protected :
unsigned int vbo_id ;
2014-06-30 22:51:02 +00:00
unsigned int vao_id ;
2013-06-23 07:49:34 +00:00
public :
FVertexBuffer ( ) ;
virtual ~ FVertexBuffer ( ) ;
2014-06-30 22:51:02 +00:00
void BindVBO ( ) ;
2013-06-23 07:49:34 +00:00
} ;
2014-05-10 19:47:07 +00:00
struct FFlatVertex
2013-06-23 07:49:34 +00:00
{
2014-05-10 19:47:07 +00:00
float x , z , y ; // world position
2013-06-23 07:49:34 +00:00
float u , v ; // texture coordinates
void SetFlatVertex ( vertex_t * vt , const secplane_t & plane ) ;
2014-05-12 18:23:54 +00:00
void Set ( float xx , float zz , float yy , float uu , float vv )
{
x = xx ;
z = zz ;
y = yy ;
u = uu ;
v = vv ;
}
2013-06-23 07:49:34 +00:00
} ;
# define VTO ((FFlatVertex*)NULL)
class FFlatVertexBuffer : public FVertexBuffer
{
FFlatVertex * map ;
2014-05-10 19:47:07 +00:00
unsigned int mIndex ;
2014-05-10 23:23:27 +00:00
unsigned int mCurIndex ;
2014-07-27 11:46:35 +00:00
unsigned int mNumReserved ;
2013-06-23 07:49:34 +00:00
void CheckPlanes ( sector_t * sector ) ;
2014-05-20 22:36:04 +00:00
const unsigned int BUFFER_SIZE = 2000000 ;
2014-07-26 08:23:07 +00:00
const unsigned int BUFFER_SIZE_TO_USE = 1999500 ;
2014-05-20 22:36:04 +00:00
2014-06-14 23:14:41 +00:00
void ImmRenderBuffer ( unsigned int primtype , unsigned int offset , unsigned int count ) ;
2013-06-23 07:49:34 +00:00
public :
2014-06-14 23:14:41 +00:00
TArray < FFlatVertex > vbo_shadowdata ; // this is kept around for updating the actual (non-readable) buffer and as stand-in for pre GL 4.x
2013-06-23 07:49:34 +00:00
FFlatVertexBuffer ( ) ;
~ FFlatVertexBuffer ( ) ;
2014-05-10 19:47:07 +00:00
void CreateVBO ( ) ;
void CheckUpdate ( sector_t * sector ) ;
2014-05-10 23:23:27 +00:00
FFlatVertex * GetBuffer ( )
{
return & map [ mCurIndex ] ;
}
unsigned int GetCount ( FFlatVertex * newptr , unsigned int * poffset )
{
2014-06-14 23:14:41 +00:00
2014-05-13 10:00:11 +00:00
unsigned int newofs = ( unsigned int ) ( newptr - map ) ;
2014-05-10 23:23:27 +00:00
unsigned int diff = newofs - mCurIndex ;
* poffset = mCurIndex ;
mCurIndex = newofs ;
2014-07-26 08:23:07 +00:00
if ( mCurIndex > = BUFFER_SIZE_TO_USE ) mCurIndex = mIndex ;
2014-05-10 23:23:27 +00:00
return diff ;
}
2014-05-20 20:37:38 +00:00
# ifdef __GL_PCH_H // we need the system includes for this but we cannot include them ourselves without creating #define clashes. The affected files wouldn't try to draw anyway.
2014-06-14 23:14:41 +00:00
void RenderArray ( unsigned int primtype , unsigned int offset , unsigned int count )
{
2014-07-13 21:14:28 +00:00
drawcalls . Clock ( ) ;
- decided to restrict the 2.0 beta to OpenGL 4.x with GL_ARB_buffer_storage extension and removed all code for supporting older versions.
Sadly, anything else makes no sense.
All the recently made changes live or die, depending on this extension's presence.
Without it, there are major performance issues with the buffer uploads. All of the traditional buffer upload methods are without exception horrendously slow, especially in the context of a Doom engine where frequent small updates are required.
It could be solved with a complete restructuring of the engine, of course, but that's hardly worth the effort, considering it's only for legacy hardware whose market share will inevitably shrink considerably over the next years.
And even then, under the best circumstances I'd still get the same performance as the old immediate mode renderer in GZDoom 1.x and still couldn't implement the additions I'd like to make.
So, since I need to keep GZDoom 1.x around anyway for older GL 2.x hardware, it may as well serve for 3.x hardware, too. It's certainly less work than constantly trying to find workarounds for the older hardware's limitations that cost more time than working on future-proofing the engine.
This new, trimmed down 4.x renderer runs on a core profile configuration and uses persistently mapped buffers for nearly everything that is getting transferred to the GPU. (The global uniforms are still being used as such but they'll be phased out after the first beta release.
2014-08-01 20:42:39 +00:00
glDrawArrays ( primtype , offset , count ) ;
2014-07-13 21:14:28 +00:00
drawcalls . Unclock ( ) ;
2014-06-14 23:14:41 +00:00
}
2014-06-14 13:16:33 +00:00
void RenderCurrent ( FFlatVertex * newptr , unsigned int primtype , unsigned int * poffset = NULL , unsigned int * pcount = NULL )
2014-05-20 20:37:38 +00:00
{
unsigned int offset ;
unsigned int count = GetCount ( newptr , & offset ) ;
2014-06-14 23:14:41 +00:00
RenderArray ( primtype , offset , count ) ;
2014-06-14 13:16:33 +00:00
if ( poffset ) * poffset = offset ;
if ( pcount ) * pcount = count ;
2014-05-20 20:37:38 +00:00
}
2014-06-14 23:14:41 +00:00
2014-05-20 20:37:38 +00:00
# endif
2014-05-10 23:23:27 +00:00
void Reset ( )
{
mCurIndex = mIndex ;
}
2014-05-10 19:47:07 +00:00
private :
2013-06-23 07:49:34 +00:00
int CreateSubsectorVertices ( subsector_t * sub , const secplane_t & plane , int floor ) ;
int CreateSectorVertices ( sector_t * sec , const secplane_t & plane , int floor ) ;
int CreateVertices ( int h , sector_t * sec , const secplane_t & plane , int floor ) ;
void CreateFlatVBO ( ) ;
void UpdatePlaneVertices ( sector_t * sec , int plane ) ;
} ;
2014-06-13 23:24:28 +00:00
struct FSkyVertex
{
float x , y , z , u , v ;
PalEntry color ;
2014-06-14 08:38:30 +00:00
void Set ( float xx , float zz , float yy , float uu = 0 , float vv = 0 , PalEntry col = 0xffffffff )
{
x = xx ;
z = zz ;
y = yy ;
u = uu ;
v = vv ;
color = col ;
}
2014-06-13 23:24:28 +00:00
} ;
class FSkyVertexBuffer : public FVertexBuffer
{
public :
static const int SKYHEMI_UPPER = 1 ;
static const int SKYHEMI_LOWER = 2 ;
enum
{
SKYMODE_MAINLAYER = 0 ,
SKYMODE_SECONDLAYER = 1 ,
SKYMODE_FOGLAYER = 2
} ;
private :
TArray < FSkyVertex > mVertices ;
TArray < unsigned int > mPrimStart ;
int mRows , mColumns ;
void SkyVertex ( int r , int c , bool yflip ) ;
void CreateSkyHemisphere ( int hemi ) ;
void CreateDome ( ) ;
2014-06-14 13:16:33 +00:00
void RenderRow ( int prim , int row ) ;
2014-06-13 23:24:28 +00:00
public :
FSkyVertexBuffer ( ) ;
virtual ~ FSkyVertexBuffer ( ) ;
void RenderDome ( FMaterial * tex , int mode ) ;
} ;
# define VSO ((FSkyVertex*)NULL)
2014-06-15 19:56:37 +00:00
struct FModelVertex
{
float x , y , z ; // world position
float u , v ; // texture coordinates
void Set ( float xx , float yy , float zz , float uu , float vv )
{
x = xx ;
y = yy ;
z = zz ;
u = uu ;
v = vv ;
}
2014-06-19 15:06:26 +00:00
void SetNormal ( float nx , float ny , float nz )
{
// GZDoom currently doesn't use normals. This function is so that the high level code can pretend it does.
}
2014-06-15 19:56:37 +00:00
} ;
class FModelVertexBuffer : public FVertexBuffer
{
int mIndexFrame [ 2 ] ;
2014-06-29 21:24:16 +00:00
unsigned int ibo_id ;
2014-06-15 19:56:37 +00:00
public :
2014-06-19 15:06:26 +00:00
// these are public because it's the models having to fill them in.
2014-06-15 19:56:37 +00:00
TArray < FModelVertex > vbo_shadowdata ; // this is kept around for interpolating on GL 2.0
2014-06-19 15:06:26 +00:00
TArray < unsigned int > ibo_shadowdata ; // this is kept around for interpolating on GL 2.0
2014-06-15 19:56:37 +00:00
FModelVertexBuffer ( ) ;
~ FModelVertexBuffer ( ) ;
2014-06-29 21:24:16 +00:00
unsigned int SetupFrame ( unsigned int frame1 , unsigned int frame2 , float factor ) ;
2014-06-15 19:56:37 +00:00
} ;
# define VMO ((FModelVertex*)NULL)
2014-06-13 23:24:28 +00:00
2013-06-23 07:49:34 +00:00
# endif