1
0
Fork 0
mirror of https://github.com/AquariaOSE/Aquaria.git synced 2025-07-03 06:24:32 +00:00

initial support for static vertex buffers. TileRender uses that now.

This commit is contained in:
fgenesis 2023-07-20 22:30:56 +02:00
parent e9e81e5ef9
commit 704981dd00
14 changed files with 448 additions and 61 deletions

View file

@ -116,6 +116,8 @@ set(BBGE_SRCS
TileRender.h
Tileset.cpp
Tileset.h
VertexBuffer.cpp
VertexBuffer.h
Vector.cpp
Vector.h
Window.cpp

View file

@ -145,7 +145,8 @@ void Core::setup_opengl()
glEnable(GL_TEXTURE_2D); // Enable Texture Mapping
glClearDepth(1.0); // Depth Buffer Setup
glDisable(GL_CULL_FACE);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glLoadIdentity();
setClearColor(clearColor);
@ -153,6 +154,8 @@ void Core::setup_opengl()
frameBuffer.init(-1, -1, true);
if(afterEffectManager)
afterEffectManager->updateDevice();
defaultQuadVertexBuf.initQuadVertices(0, 0, 1, 1);
}
void Core::resizeWindow(int w, int h, int full, int bpp, int vsync, int display, int hz)
@ -276,7 +279,7 @@ static bool checkWritable(const std::string& path, bool warn, bool critical)
Core::Core(const std::string &filesystem, const std::string& extraDataDir, int numRenderLayers, const std::string &appName, int particleSize, std::string userDataSubFolder)
: ActionMapper(), StateManager(), appName(appName)
: ActionMapper(), StateManager(), appName(appName), defaultQuadVertexBuf(GPUBUF_STATIC | GPUBUF_VERTEXBUF)
{
window = NULL;
sound = NULL;
@ -1917,6 +1920,8 @@ void Core::shutdown()
frameBuffer.unloadDevice();
debugLog("OK");
defaultQuadVertexBuf.dropBuffer();
debugLog("Shutdown Graphics Library...");
shutdownGraphicsLibrary();
debugLog("OK");

View file

@ -29,7 +29,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "Localization.h"
#include "Window.h"
#include "TextureMgr.h"
#include "VertexBuffer.h"
#include "DarkLayer.h"
#include "GameKeys.h"
@ -413,6 +413,8 @@ public:
TextureMgr texmgr;
inline const DynamicGPUBuffer *getDefaultQuadVertexBuffer() const { return &defaultQuadVertexBuf; }
protected:
CoreWindow *window;
@ -490,6 +492,8 @@ protected:
virtual void updateActionButtons();
void clearActionButtons();
DynamicGPUBuffer defaultQuadVertexBuf;
public:
// inclusive!
inline int getMaxActionStatusIndex() const { return int(actionStatus.size()) - 2; }

View file

@ -68,9 +68,19 @@ PFNGLFRAMEBUFFERTEXTURE3DEXTPROC glFramebufferTexture3DEXT = NULL;
PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbufferEXT = NULL;
PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glGetFramebufferAttachmentParameterivEXT = NULL;
// ARB_vertex_buffer_object
PFNGLGENBUFFERSARBPROC glGenBuffersARB = NULL;
PFNGLDELETEBUFFERSARBPROC glDeleteBuffersARB = NULL;
PFNGLBUFFERDATAARBPROC glBufferDataARB = NULL;
PFNGLBUFFERSUBDATAARBPROC glBufferSubDataARB = NULL;
PFNGLBINDBUFFERARBPROC glBindBufferARB = NULL;
PFNGLMAPBUFFERARBPROC glMapBufferARB = NULL;
PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB = NULL;
// extern
unsigned g_dbg_numRenderCalls = 0;
bool g_has_GL_GENERATE_MIPMAP = false;
bool g_has_GL_BUFFERS = false;
#define GL_FUNC(ret,fn,params,call,rt) \
@ -164,6 +174,15 @@ bool lookup_all_glsyms()
glUniform3ivARB = (PFNGLUNIFORM3IVARBPROC)SDL_GL_GetProcAddress("glUniform3ivARB");
glUniform4ivARB = (PFNGLUNIFORM4IVARBPROC)SDL_GL_GetProcAddress("glUniform4ivARB");
// VBOs
glGenBuffersARB = (PFNGLGENBUFFERSARBPROC)SDL_GL_GetProcAddress("glGenBuffersARB");
glDeleteBuffersARB = (PFNGLDELETEBUFFERSARBPROC)SDL_GL_GetProcAddress("glDeleteBuffersARB");
glBufferDataARB = (PFNGLBUFFERDATAARBPROC)SDL_GL_GetProcAddress("glBufferData");
glBufferSubDataARB = (PFNGLBUFFERSUBDATAARBPROC)SDL_GL_GetProcAddress("glBufferSubData");
glBindBufferARB = (PFNGLBINDBUFFERARBPROC)SDL_GL_GetProcAddress("glBindBufferARB");
glMapBufferARB = (PFNGLMAPBUFFERARBPROC)SDL_GL_GetProcAddress("glMapBufferARB");
glUnmapBufferARB = (PFNGLUNMAPBUFFERARBPROC)SDL_GL_GetProcAddress("glUnmapBufferARB");
return retval;
}
@ -217,6 +236,15 @@ void unload_all_glsyms()
glUniform2ivARB = NULL;
glUniform3ivARB = NULL;
glUniform4ivARB = NULL;
glGenBuffersARB = NULL;
glDeleteBuffersARB = NULL;
glBufferDataARB = NULL;
glBufferSubDataARB = NULL;
glBindBufferARB = NULL;
glMapBufferARB = NULL;
glUnmapBufferARB = NULL;
}
#endif // BBGE_BUILD_OPENGL_STATIC

View file

@ -26,14 +26,15 @@ GL_FUNC(void,glClear,(GLbitfield a),(a),)
GL_FUNC(void,glClearColor,(GLclampf r,GLclampf g,GLclampf b,GLclampf a),(r,g,b,a),)
GL_FUNC(void,glColor4f,(GLfloat r,GLfloat g,GLfloat b,GLfloat a),(r,g,b,a),)
GL_FUNC(void,glColor4ub,(GLubyte r,GLubyte g,GLubyte b,GLubyte a),(r,g,b,a),)
GL_FUNC(void,glColorPointer,(GLint size,GLenum type,GLsizei stride,const GLvoid* pointer),(size,type,stride,pointer),);
GL_FUNC(void,glCopyPixels,(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type),(x,y,width,height,type),)
GL_FUNC(void,glCopyTexImage2D,(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border),(target, level, internalFormat, x, y, width, height, border),)
GL_FUNC(void,glCopyTexSubImage2D,(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height),(target, level, xoffset, yoffset, x, y, width, height),)
GL_FUNC(void,glDeleteTextures,(GLsizei n, const GLuint *textures),(n,textures),)
GL_FUNC(void,glDisable,(GLenum cap),(cap),)
GL_FUNC(void,glDisableClientState,(GLenum array),(array),)
//GL_FUNC(void,glDrawArrays,(GLenum mode, GLint first, GLsizei count),(mode,first,count),)
//GL_FUNC(void,glDrawElements,(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices),(mode,count,type,indices),)
GL_FUNC(void,glDrawArrays,(GLenum mode, GLint first, GLsizei count),(mode,first,count),)
GL_FUNC(void,glDrawElements,(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices),(mode,count,type,indices),)
GL_FUNC(void,glEnable,(GLenum cap),(cap),)
GL_FUNC(void,glEnableClientState,(GLenum array),(array),)
GL_FUNC(void,glFinish,(void),(),)
@ -70,7 +71,6 @@ GL_FUNC(void,glEnd,(void),(),)
GL_FUNC(void,glClearDepth,(GLclampd x),(x),)
GL_FUNC(void,glColor3f,(GLfloat r,GLfloat g,GLfloat b),(r,g,b),)
//GL_FUNC(void,glDeleteLists,(GLuint list, GLsizei range),(list,range),)
GL_FUNC(void,glDrawArrays,(GLenum mode, GLint first, GLsizei count), (mode,first,count),)
//GL_FUNC(void,glDrawPixels,(GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels),(width,height,format,type,pixels),)
//GL_FUNC(GLuint,glGenLists,(GLsizei range),(range),return)
//GL_FUNC(void,glNewList,(GLuint list, GLenum mode),(list,mode),)

View file

@ -39,7 +39,7 @@ extern PFNGLGETINFOLOGARBPROC glGetInfoLogARB;
extern PFNGLLINKPROGRAMARBPROC glLinkProgramARB;
extern PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocationARB;
extern PFNGLGETACTIVEUNIFORMARBPROC glGetActiveUniformARB;
extern PFNGLUNIFORM1FVARBPROC glUniform1fvARB ;
extern PFNGLUNIFORM1FVARBPROC glUniform1fvARB;
extern PFNGLUNIFORM2FVARBPROC glUniform2fvARB;
extern PFNGLUNIFORM3FVARBPROC glUniform3fvARB;
extern PFNGLUNIFORM4FVARBPROC glUniform4fvARB;
@ -65,6 +65,12 @@ extern PFNGLFRAMEBUFFERTEXTURE3DEXTPROC glFramebufferTexture3DEXT;
extern PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbufferEXT;
extern PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glGetFramebufferAttachmentParameterivEXT;
extern PFNGLGENBUFFERSARBPROC glGenBuffersARB;
extern PFNGLDELETEBUFFERSARBPROC glDeleteBuffersARB;
extern PFNGLBUFFERDATAARBPROC glBufferDataARB;
extern PFNGLBUFFERSUBDATAARBPROC glBufferSubDataARB;
extern PFNGLBINDBUFFERARBPROC glBindBufferARB;
extern PFNGLMAPBUFFERARBPROC glMapBufferARB;
extern PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB;
#endif

View file

@ -531,6 +531,11 @@ bool TileData::isCoordinateInside(float cx, float cy, float minsize) const
&& cy >= y - hh && cy <= y + hh;
}
TileRepeatData::TileRepeatData()
: vertexbuf(GPUBUF_STATIC | GPUBUF_VERTEXBUF)
{
}
void TileRepeatData::refresh(const ElementTemplate& et, float scalex, float scaley)
{
float tw, th;
@ -555,14 +560,7 @@ void TileRepeatData::refresh(const ElementTemplate& et, float scalex, float scal
this->tu2 = tu2;
this->tv2 = tv2;
texcoords[0] = tu1;
texcoords[1] = 1.0f-tv1;
texcoords[2] = tu2;
texcoords[3] = 1.0f-tv1;
texcoords[4] = tu2;
texcoords[5] = 1.0f-tv2;
texcoords[6] = tu1;
texcoords[7] = 1.0f-tv2;
vertexbuf.initQuadVertices(tu1, tv1, tu2, tv2);
}
TileRepeatData* TileData::setRepeatOn(float texscalex, float texscaley, float offx, float offy)

View file

@ -4,6 +4,7 @@
#include <vector>
#include "Vector.h"
#include "EngineEnums.h"
#include "VertexBuffer.h"
// A Tile is a very stripped down RenderObject that bypasses the default
// rendering pipeline for efficiency reasons.
@ -132,8 +133,10 @@ private:
struct TileRepeatData
{
TileRepeatData();
// written via refresh()
float texcoords[8];
DynamicGPUBuffer vertexbuf;
float tu1, tv1, tu2, tv2;
// set by user

View file

@ -41,24 +41,11 @@ static inline const Vector& getTagColor(int tag)
}
static const float s_quadVerts[] =
{
-0.5f, +0.5f,
+0.5f, +0.5f,
+0.5f, -0.5f,
-0.5f, -0.5f,
};
void TileRender::onRender(const RenderState& rs) const
{
if(storage.tiles.empty())
return;
glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, s_quadVerts);
RenderState rx(rs);
// prepare. get parallax scroll factors
@ -78,7 +65,7 @@ void TileRender::onRender(const RenderState& rs) const
const bool renderExtras = renderBorders || RenderObject::renderCollisionShape;
const TileEffectData *prevEff = ((TileEffectData*)NULL)+1; // initial value is different from anything else
const RenderGrid *grid = NULL;
const float *lastTexcoordBuf = NULL;
const DynamicGPUBuffer *lastVertexBuf = NULL;
for(size_t i = 0; i < storage.tiles.size(); ++i)
{
@ -181,16 +168,16 @@ void TileRender::onRender(const RenderState& rs) const
if(!grid)
{
const float *tcbuf = (tile.flags & TILEFLAG_REPEAT)
? &tile.rep->texcoords[0]
: tile.et->texcoordQuadPtr;
assert(tcbuf);
if(lastTexcoordBuf != tcbuf)
const DynamicGPUBuffer *vb = !(tile.flags & TILEFLAG_REPEAT)
? tile.et->vertexbuf
: &tile.rep->vertexbuf;
assert(vb);
if(vb != lastVertexBuf)
{
lastTexcoordBuf = tcbuf;
glTexCoordPointer(2, GL_FLOAT, 0, tcbuf);
lastVertexBuf = vb;
vb->apply();
}
glDrawArrays(GL_QUADS, 0, 4);
vb->DrawArrays(GL_TRIANGLE_FAN, 4);
}
else
{
@ -248,7 +235,7 @@ void TileRender::onRender(const RenderState& rs) const
glPopMatrix();
}
glPopClientAttrib();
glBindBufferARB(GL_ARRAY_BUFFER, 0);
RenderObject::lastTextureApplied = lastTexId;
RenderObject::lastTextureRepeat = !!lastTexRepeat;

View file

@ -18,8 +18,6 @@ public:
virtual void onUpdate(float dt) OVERRIDE;
bool renderBorders;
private:
};

View file

@ -169,13 +169,12 @@ const ElementTemplate* Tileset::getAdjacent(size_t idx, int direction, bool wrap
return et;
}
static const float s_defaultTexcoordBuf[] =
ElementTemplate::~ElementTemplate()
{
0, 1,
1, 1,
1, 0,
0, 0
};
if(ownsVertexbuf)
delete const_cast<DynamicGPUBuffer*>(vertexbuf);
}
void ElementTemplate::finalize()
{
@ -197,18 +196,19 @@ void ElementTemplate::finalize()
}
if(tu1 == 0 && tv1 == 0 && tu2 == 1 && tv2 == 1)
texcoordQuadPtr = s_defaultTexcoordBuf;
{
// this avoids buffer switches later on
vertexbuf = core->getDefaultQuadVertexBuffer();
ownsVertexbuf = false;
}
else
{
texcoordQuadPtr = &texcoordQuadBuffer[0];
texcoordQuadBuffer[0] = tu1;
texcoordQuadBuffer[1] = 1.0f-tv1;
texcoordQuadBuffer[2] = tu2;
texcoordQuadBuffer[3] = 1.0f-tv1;
texcoordQuadBuffer[4] = tu2;
texcoordQuadBuffer[5] = 1.0f-tv2;
texcoordQuadBuffer[6] = tu1;
texcoordQuadBuffer[7] = 1.0f-tv2;
DynamicGPUBuffer *vb = ownsVertexbuf
? const_cast<DynamicGPUBuffer*>(vertexbuf)
: new DynamicGPUBuffer(GPUBUF_STATIC | GPUBUF_VERTEXBUF);
vb->initQuadVertices(tu1, tv1, tu2, tv2);
vertexbuf = vb;
ownsVertexbuf = true;
}
}

View file

@ -4,11 +4,13 @@
#include "Vector.h"
#include <vector>
#include "Texture.h"
#include "VertexBuffer.h"
class ElementTemplate
{
public:
ElementTemplate() { w=0; h=0; idx=-1; tu1=tv1=0; tu2=tv2=1; texcoordQuadPtr=NULL; }
ElementTemplate() { w=0; h=0; idx=-1; tu1=tv1=0; tu2=tv2=1; vertexbuf = NULL; ownsVertexbuf = false; }
~ElementTemplate();
inline bool operator<(const ElementTemplate& o) const { return idx < o.idx; }
void finalize(); // call after settings params
@ -16,8 +18,8 @@ public:
// lazily assigned when tex is loaded
CountedPtr<Texture> tex; // NULL if failed to load or not yet loaded
float w,h; // custom size if used, otherwise texture size
const float *texcoordQuadPtr;
float texcoordQuadBuffer[8];
const DynamicGPUBuffer * vertexbuf; // never NULL
bool ownsVertexbuf;
// fixed
float tu1, tu2, tv1, tv2; // texcoords
@ -26,6 +28,7 @@ public:
private:
ElementTemplate(const ElementTemplate&); // no copy
ElementTemplate& operator=(const ElementTemplate&); // no assign
};
class Tileset

262
BBGE/VertexBuffer.cpp Normal file
View file

@ -0,0 +1,262 @@
#include "VertexBuffer.h"
#include "RenderBase.h"
#include "Base.h"
#include <assert.h>
bool DynamicGPUBuffer::_HasARB = false;
static unsigned s_lastVertexBuffer = 0;
static unsigned s_lastIndexBuffer = 0;
static void *s_lastHostPtr = NULL;
static BufDataType s_lastDataType = BufDataType(-1);
static unsigned s_lastState = 0; // StateBits
enum StateBits
{
SB_COLOR_FROM_BUFFER = 0x01
};
static unsigned toGlUsage(unsigned usage)
{
if(usage & GPUBUF_STATIC)
return GL_STATIC_DRAW_ARB;
return GL_DYNAMIC_DRAW;
}
void DynamicGPUBuffer::StaticInit()
{
_HasARB = glGenBuffersARB && glDeleteBuffersARB
&& glBufferDataARB && glBufferSubDataARB
&& glBindBufferARB && glMapBufferARB && glUnmapBufferARB;
}
DynamicGPUBuffer::DynamicGPUBuffer(unsigned usage)
: _bufid(0)
, _binding((usage & GPUBUF_INDEXBUF) ? GL_ELEMENT_ARRAY_BUFFER_ARB : GL_ARRAY_BUFFER_ARB)
, _size(0)
, _cap(0)
, _h_data(NULL)
, _d_map(NULL)
, _usage(toGlUsage(usage))
, _datatype(BufDataType(-1))
{
}
DynamicGPUBuffer::~DynamicGPUBuffer()
{
dropBuffer();
}
void* DynamicGPUBuffer::_allocBytes(size_t bytes)
{
if(s_lastHostPtr == _h_data)
s_lastHostPtr = NULL;
void *p = realloc(_h_data, bytes);
if(p)
{
_cap = bytes;
_h_data = p;
}
return p;
}
void* DynamicGPUBuffer::_ensureBytes(size_t bytes)
{
if(bytes < _cap)
return _h_data;
size_t newsize = 2 * _size;
if(newsize < bytes)
newsize += bytes;
return _allocBytes(newsize);
}
void* DynamicGPUBuffer::beginWrite(BufDataType type, size_t newsize, unsigned access)
{
_size = newsize;
_datatype = type;
if(_HasARB)
{
glBindBufferARB(_binding, _ensureDBuf());
glBufferDataARB(_binding, newsize, NULL, _usage); // orphan buffer
if(!(access & GPUACCESS_HOSTCOPY))
{
void *p = glMapBufferARB(_binding, GL_WRITE_ONLY_ARB);
_d_map = p;
if(p)
return p;
}
}
return _ensureBytes(newsize);
}
bool DynamicGPUBuffer::commitWrite()
{
if(_HasARB)
{
if(_d_map)
{
_d_map = NULL;
return glUnmapBufferARB(_binding); // can fail
}
// otherwise, the prev. call to glMapBufferARB failed (or GPUACCESS_NOMAP was set).
// -> didn't map, but wrote to host memory. upload it.
assert(_h_data);
glBufferSubDataARB(_binding, 0, _size, _h_data);
}
// else nothing to do
return true;
}
void DynamicGPUBuffer::upload(BufDataType type, const void* data, size_t size)
{
_datatype = type;
if(_HasARB)
{
glBindBufferARB(_binding, _ensureDBuf());
glBufferDataARB(_binding, size, data, _usage);
}
else
memcpy(_ensureBytes(size), data, size);
}
static const unsigned s_gltype[] =
{
GL_SHORT,
GL_FLOAT,
};
struct BufPtrConfig
{
uintptr_t bufidOrPtr;
BufDataType datatype;
};
void DynamicGPUBuffer::apply(BufDataType usetype) const
{
if(!usetype)
usetype = _datatype;
void *p;
if(_HasARB)
{
unsigned bufid = this->_bufid;
assert(bufid != s_lastVertexBuffer); // check that it's no redundant state change
if(bufid == s_lastVertexBuffer && usetype == s_lastDataType)
return;
p = NULL;
s_lastVertexBuffer = bufid;
glBindBufferARB(GL_ARRAY_BUFFER_ARB, bufid);
}
else
{
p = (void*)this->_h_data;
assert(p != s_lastHostPtr); // check that it's no redundant state change
if(p == s_lastHostPtr && usetype == s_lastDataType) // don't need to check for datatype since that's const for the buffer with that ptr
return;
}
s_lastDataType = usetype;
assert((ty & 0xf) < Countof(s_gltype));
const unsigned gltype = s_gltype[usetype & 0xf];
const unsigned scalars = (usetype >> 4) & 0xf;
const unsigned stride = (usetype >> 8) & 0xff;
const unsigned tcoffset = (usetype >> 16) & 0xff;
const unsigned coloroffset = usetype >> 24;
// vertex and texcoords are always enabled
glVertexPointer(scalars, gltype, stride, p);
if(tcoffset)
glTexCoordPointer(2, gltype, stride, (void*)((uintptr_t)p + tcoffset));
unsigned wantedstate = 0;
if(coloroffset)
{
wantedstate |= SB_COLOR_FROM_BUFFER;
glColorPointer(4, gltype, stride, (void*)((uintptr_t)p + coloroffset));
}
unsigned wrongbits = wantedstate ^ s_lastState;
if(wrongbits)
{
if(wrongbits & SB_COLOR_FROM_BUFFER)
{
if(wantedstate & SB_COLOR_FROM_BUFFER)
glEnableClientState(GL_COLOR_ARRAY);
else
glDisableClientState(GL_COLOR_ARRAY);
}
s_lastState = wantedstate;
}
}
unsigned DynamicGPUBuffer::_ensureDBuf()
{
assert(_HasARB);
if(!_bufid)
glGenBuffersARB(1, &_bufid);
return _bufid;
}
void DynamicGPUBuffer::dropBuffer()
{
if(s_lastHostPtr == _h_data)
s_lastHostPtr = NULL;
free(_h_data);
_h_data = NULL;
if(_bufid)
{
if(s_lastVertexBuffer == _bufid)
s_lastVertexBuffer = 0;
if(s_lastIndexBuffer == _bufid)
s_lastIndexBuffer = 0;
glDeleteBuffersARB(1, &_bufid);
_bufid = 0;
}
_size = 0;
}
void DynamicGPUBuffer::DrawArrays(unsigned glmode, size_t n, size_t first)
{
glDrawArrays(glmode, first, n);
}
void DynamicGPUBuffer::drawElements(unsigned glmode, size_t n, size_t first)
{
assert(_binding == GL_ELEMENT_ARRAY_BUFFER_ARB);
assert(s_gltype[_datatype & 0xf] == GL_SHORT);
if(s_lastIndexBuffer != _bufid)
{
s_lastIndexBuffer = _bufid;
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, _bufid);
}
glDrawElements(glmode, n, GL_SHORT, NULL);
}
void DynamicGPUBuffer::initQuadVertices(float tu1, float tv1, float tu2, float tv2)
{
do
{
float *p = (float*)beginWrite(GPUBUFTYPE_VEC2_TC, (4*4) * sizeof(float), GPUACCESS_DEFAULT);
*p++ = -0.5f; *p++ = +0.5f; // xy
*p++ = tu1; *p++ = 1.0f-tv1; // uv
*p++ = +0.5f; *p++ = +0.5f; // xy
*p++ = tu2; *p++ = 1.0f-tv1; // uv
*p++ = +0.5f; *p++ = -0.5f; // xy
*p++ = tu2; *p++ = 1.0f-tv2; // uv
*p++ = -0.5f; *p++ = -0.5f; // xy
*p++ = tu1; *p++ = 1.0f-tv2; // uv
}
while(!commitWrite());
}

91
BBGE/VertexBuffer.h Normal file
View file

@ -0,0 +1,91 @@
#ifndef BBGE_VERTEXBUFFER_H
#define BBGE_VERTEXBUFFER_H
#include <stdlib.h> // size_t
enum BufUsage
{
// usage
GPUBUF_DYNAMIC = 0x00,
GPUBUF_STATIC = 0x01,
// binding point
GPUBUF_VERTEXBUF = 0x00,
GPUBUF_INDEXBUF = 0x02
};
enum BufDataType
{
GPUBUFTYPE_NONE = 0,
/* ccoossnt --
^-- type of each scalar
^-- number of coordinate scalars (eg. xyz would be 3)
^^-- stride (distance to next vertex), in bytes
^^-- offset of texcoords, in bytes, if present
^^-- offset of colors, if present */
GPUBUFTYPE_U16 = 0x00000010, // densely packed u16, for indexing
GPUBUFTYPE_VEC2_TC = 0x00081021, // xyuv xyuv xyuv
GPUBUFTYPE_VEC2_TC_RGBA = 0x10082021, // xyuvrgba xyuvrgba xyuvrgba
// ccoossnt
GPUBUFTYPE_VEC2_TC_RGBA_BUT_NO_COLOR = GPUBUFTYPE_VEC2_TC_RGBA & 0xffffff
};
enum AccessFlags
{
// Use whatever works. May directly map in GPU memory so that there is no
// copy on the host; or if there is a previous copy, it may remain untouched.
GPUACCESS_DEFAULT = 0x00,
// Don't use memory mapping. Prepare buffer on the host and upload it in one go.
// The copy remains on the host.
GPUACCESS_HOSTCOPY = 0x01
};
class DynamicGPUBuffer
{
friend class BufMapW;
public:
void StaticInit();
DynamicGPUBuffer(unsigned usage);
~DynamicGPUBuffer();
void dropBuffer();
size_t size() const { return _size; }
// beginWrite(), then write exactly newsize bytes, then commit
void *beginWrite(BufDataType type, size_t newsize, unsigned access); // AccessFlags
bool commitWrite();
void upload(BufDataType type, const void *data, size_t size);
static void DrawArrays(unsigned glmode, size_t n, size_t first = 0); // uses last applied buffer for drawing
// uses own data for indexing and prev. applied buffer for the data to draw
void drawElements(unsigned glmode, size_t n, size_t first = 0);
void apply(BufDataType usetype = GPUBUFTYPE_NONE) const;
// Inteded for use with DrawArrays(4) and GL_TRIANGLE_FAN or GL_QUADS (both work)
void initQuadVertices(float tu1, float tu2, float tv1, float tv2);
private:
void* _allocBytes(size_t bytes);
void* _ensureBytes(size_t bytes);
unsigned _ensureDBuf();
unsigned _bufid;
unsigned _binding;
size_t _size;
size_t _cap;
void *_h_data;
void *_d_map;
const unsigned _usage;
BufDataType _datatype;
static bool _HasARB;
};
#endif // BBGE_VERTEXBUFFER_H