custom rendertarget support for gl

This commit is contained in:
aap 2020-08-10 13:31:33 +02:00
parent a29bcef4d7
commit b1507e5099
3 changed files with 213 additions and 77 deletions

View File

@ -235,6 +235,8 @@ static GlState curGlState, oldGlState;
static int32 activeTexture;
static uint32 boundTexture[MAXNUMSTAGES];
static uint32 currentFramebuffer;
static uint32 blendMap[] = {
GL_ZERO, // actually invalid
GL_ZERO,
@ -415,6 +417,16 @@ bindTexture(uint32 texid)
return prev;
}
void
bindFramebuffer(uint32 fbo)
{
//glBindFramebuffer(GL_FRAMEBUFFER, fbo);
if(currentFramebuffer != fbo){
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
currentFramebuffer = fbo;
}
}
// TODO: support mipmaps
static GLint filterConvMap_NoMIP[] = {
0, GL_NEAREST, GL_LINEAR,
@ -990,62 +1002,44 @@ flushCache(void)
}
static void
clearCamera(Camera *cam, RGBA *col, uint32 mode)
setFrameBuffer(Camera *cam)
{
RGBAf colf;
GLbitfield mask;
Raster *fbuf = cam->frameBuffer;
Raster *zbuf = cam->zBuffer;
assert(fbuf);
convColor(&colf, col);
glClearColor(colf.red, colf.green, colf.blue, colf.alpha);
mask = 0;
if(mode & Camera::CLEARIMAGE)
mask |= GL_COLOR_BUFFER_BIT;
if(mode & Camera::CLEARZ)
mask |= GL_DEPTH_BUFFER_BIT;
glDepthMask(GL_TRUE);
glClear(mask);
glDepthMask(rwStateCache.zwrite);
}
Gl3Raster *natfb = PLUGINOFFSET(Gl3Raster, fbuf, nativeRasterOffset);
Gl3Raster *natzb = PLUGINOFFSET(Gl3Raster, zbuf, nativeRasterOffset);
assert(fbuf->type == Raster::CAMERA || fbuf->type == Raster::CAMERATEXTURE);
static void
showRaster(Raster *raster, uint32 flags)
{
// TODO: do this properly!
#ifdef LIBRW_SDL2
SDL_GL_SwapWindow(glGlobals.window);
#else
if(flags & Raster::FLIPWAITVSYNCH)
glfwSwapInterval(1);
else
glfwSwapInterval(0);
glfwSwapBuffers(glGlobals.window);
#endif
}
static bool32
rasterRenderFast(Raster *raster, int32 x, int32 y)
{
Raster *src = raster;
Raster *dst = Raster::getCurrentContext();
Gl3Raster *natdst = PLUGINOFFSET(Gl3Raster, dst, nativeRasterOffset);
Gl3Raster *natsrc = PLUGINOFFSET(Gl3Raster, src, nativeRasterOffset);
switch(dst->type){
case Raster::NORMAL:
case Raster::TEXTURE:
case Raster::CAMERATEXTURE:
switch(src->type){
case Raster::CAMERA:
setActiveTexture(0);
glBindTexture(GL_TEXTURE_2D, natdst->texid);
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, x, (dst->height-src->height)-y,
0, 0, src->width, src->height);
glBindTexture(GL_TEXTURE_2D, boundTexture[0]);
return 1;
// Have to make sure depth buffer is attached to FB's fbo
bindFramebuffer(natfb->fbo);
if(zbuf){
if(natfb->fboMate == zbuf){
// all good
assert(natzb->fboMate == fbuf);
}else{
if(natzb->fboMate){
// have to detatch from fbo first!
Gl3Raster *oldfb = PLUGINOFFSET(Gl3Raster, natzb->fboMate, nativeRasterOffset);
if(oldfb->fbo){
bindFramebuffer(oldfb->fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
bindFramebuffer(natfb->fbo);
}
oldfb->fboMate = nil;
}
natfb->fboMate = zbuf;
natzb->fboMate = fbuf;
if(natfb->fbo)
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, natzb->texid, 0);
}
break;
}else{
// remove z-buffer
if(natfb->fboMate && natfb->fbo)
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
natfb->fboMate = nil;
}
return 0;
}
static void
@ -1105,7 +1099,7 @@ beginUpdate(Camera *cam)
proj[10] = -(cam->farPlane+cam->nearPlane)*invz;
proj[11] = 0.0f;
proj[14] = -2.0f*invz;
proj[14] = 2.0f*invz;
proj[15] = 1.0f;
}
memcpy(&cam->devProj, &proj, sizeof(RawMatrix));
@ -1122,12 +1116,20 @@ beginUpdate(Camera *cam)
stateDirty = 1;
}
setFrameBuffer(cam);
int w, h;
if(cam->frameBuffer->type == Raster::CAMERA){
#ifdef LIBRW_SDL2
SDL_GetWindowSize(glGlobals.window, &w, &h);
SDL_GetWindowSize(glGlobals.window, &w, &h);
#else
glfwGetWindowSize(glGlobals.window, &w, &h);
glfwGetWindowSize(glGlobals.window, &w, &h);
#endif
}else{
w = cam->frameBuffer->width;
h = cam->frameBuffer->height;
}
if(w != glGlobals.presentWidth || h != glGlobals.presentHeight){
glViewport(0, 0, w, h);
glGlobals.presentWidth = w;
@ -1135,6 +1137,67 @@ beginUpdate(Camera *cam)
}
}
static void
clearCamera(Camera *cam, RGBA *col, uint32 mode)
{
RGBAf colf;
GLbitfield mask;
setFrameBuffer(cam);
convColor(&colf, col);
glClearColor(colf.red, colf.green, colf.blue, colf.alpha);
mask = 0;
if(mode & Camera::CLEARIMAGE)
mask |= GL_COLOR_BUFFER_BIT;
if(mode & Camera::CLEARZ)
mask |= GL_DEPTH_BUFFER_BIT;
glDepthMask(GL_TRUE);
glClear(mask);
glDepthMask(rwStateCache.zwrite);
}
static void
showRaster(Raster *raster, uint32 flags)
{
// TODO: do this properly!
#ifdef LIBRW_SDL2
SDL_GL_SwapWindow(glGlobals.window);
#else
if(flags & Raster::FLIPWAITVSYNCH)
glfwSwapInterval(1);
else
glfwSwapInterval(0);
glfwSwapBuffers(glGlobals.window);
#endif
}
static bool32
rasterRenderFast(Raster *raster, int32 x, int32 y)
{
Raster *src = raster;
Raster *dst = Raster::getCurrentContext();
Gl3Raster *natdst = PLUGINOFFSET(Gl3Raster, dst, nativeRasterOffset);
Gl3Raster *natsrc = PLUGINOFFSET(Gl3Raster, src, nativeRasterOffset);
switch(dst->type){
case Raster::NORMAL:
case Raster::TEXTURE:
case Raster::CAMERATEXTURE:
switch(src->type){
case Raster::CAMERA:
setActiveTexture(0);
glBindTexture(GL_TEXTURE_2D, natdst->texid);
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, x, (dst->height-src->height)-y,
0, 0, src->width, src->height);
glBindTexture(GL_TEXTURE_2D, boundTexture[0]);
return 1;
}
break;
}
return 0;
}
#ifdef LIBRW_SDL2
static int
openSDL2(EngineOpenParams *openparams)

View File

@ -80,9 +80,6 @@ rasterCreateTexture(Raster *raster)
return raster;
}
// This is totally fake right now, can't render to it. Only used to copy into from FB
// For rendering the idea would probably be to render to the backbuffer and copy it here afterwards.
// alternatively just use FBOs but that probably needs some more infrastructure.
static Raster*
rasterCreateCameraTexture(Raster *raster)
{
@ -138,26 +135,64 @@ rasterCreateCameraTexture(Raster *raster)
natras->addressV = 0;
glBindTexture(GL_TEXTURE_2D, 0);
glGenFramebuffers(1, &natras->fbo);
bindFramebuffer(natras->fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, natras->texid, 0);
bindFramebuffer(0);
natras->fboMate = nil;
return raster;
}
static Raster*
rasterCreateCamera(Raster *raster)
{
Gl3Raster *natras = PLUGINOFFSET(Gl3Raster, raster, nativeRasterOffset);
// TODO: set/check width, height, depth, format?
raster->flags |= Raster::DONTALLOCATE;
raster->originalWidth = raster->width;
raster->originalHeight = raster->height;
raster->stride = 0;
raster->pixels = nil;
natras->texid = 0;
natras->fbo = 0;
natras->fboMate = nil;
return raster;
}
static Raster*
rasterCreateZbuffer(Raster *raster)
{
Gl3Raster *natras = PLUGINOFFSET(Gl3Raster, raster, nativeRasterOffset);
// TODO: set/check width, height, depth, format?
raster->flags |= Raster::DONTALLOCATE;
raster->originalWidth = raster->width;
raster->originalHeight = raster->height;
raster->stride = 0;
raster->pixels = nil;
natras->internalFormat = GL_DEPTH_COMPONENT;
natras->format = GL_DEPTH_COMPONENT;
natras->type = GL_UNSIGNED_BYTE;
glGenTextures(1, &natras->texid);
glBindTexture(GL_TEXTURE_2D, natras->texid);
glTexImage2D(GL_TEXTURE_2D, 0, natras->internalFormat,
raster->width, raster->height,
0, natras->format, natras->type, nil);
natras->filterMode = 0;
natras->addressU = 0;
natras->addressV = 0;
glBindTexture(GL_TEXTURE_2D, 0);
natras->fbo = 0;
natras->fboMate = nil;
return raster;
}
@ -192,27 +227,21 @@ GL_RGB5
Raster*
rasterCreate(Raster *raster)
{
if(raster->width == 0 || raster->height == 0){
raster->flags |= Raster::DONTALLOCATE;
raster->stride = 0;
return raster;
}
if(raster->flags & Raster::DONTALLOCATE)
return raster;
switch(raster->type){
#ifdef RW_OPENGL
case Raster::NORMAL:
case Raster::TEXTURE:
// Dummy to use as subraster
// ^ what did i do there?
if(raster->width == 0 || raster->height == 0){
raster->flags |= Raster::DONTALLOCATE;
raster->stride = 0;
return raster;
}
if(raster->flags & Raster::DONTALLOCATE)
return raster;
return rasterCreateTexture(raster);
case Raster::CAMERATEXTURE:
if(raster->flags & Raster::DONTALLOCATE)
return raster;
return rasterCreateCameraTexture(raster);
case Raster::ZBUFFER:
return rasterCreateZbuffer(raster);
case Raster::CAMERA:
@ -248,13 +277,13 @@ memset(px, 0, raster->stride*raster->height);
GLuint fbo;
GLenum e;
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
bindFramebuffer(fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, natras->texid, 0);
e = glCheckFramebufferStatus(GL_FRAMEBUFFER);
assert(natras->format == GL_RGBA);
glReadPixels(0, 0, raster->width, raster->height, natras->format, natras->type, px);
//e = glGetError(); printf("GL err4 %x (%x)\n", e, natras->format);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
bindFramebuffer(0);
glDeleteFramebuffers(1, &fbo);
#else
uint32 prev = bindTexture(natras->texid);
@ -456,15 +485,53 @@ createNativeRaster(void *object, int32 offset, int32)
{
Gl3Raster *ras = PLUGINOFFSET(Gl3Raster, object, offset);
ras->texid = 0;
ras->fbo = 0;
ras->fboMate = nil;
return object;
}
static void*
destroyNativeRaster(void *object, int32 offset, int32)
{
Gl3Raster *ras = PLUGINOFFSET(Gl3Raster, object, offset);
Raster *raster = (Raster*)object;
Gl3Raster *natras = PLUGINOFFSET(Gl3Raster, object, offset);
#ifdef RW_OPENGL
glDeleteTextures(1, &ras->texid);
switch(raster->type){
case Raster::NORMAL:
case Raster::TEXTURE:
glDeleteTextures(1, &natras->texid);
break;
case Raster::CAMERATEXTURE:
if(natras->fboMate){
// Break apart from currently associated zbuffer
Gl3Raster *zras = PLUGINOFFSET(Gl3Raster, natras->fboMate, offset);
zras->fboMate = nil;
natras->fboMate = nil;
}
glDeleteFramebuffers(1, &natras->fbo);
glDeleteTextures(1, &natras->texid);
break;
case Raster::ZBUFFER:
if(natras->fboMate){
// Detatch from FBO we may be attached to
Gl3Raster *oldfb = PLUGINOFFSET(Gl3Raster, natras->fboMate, nativeRasterOffset);
if(oldfb->fbo){
bindFramebuffer(oldfb->fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
}
oldfb->fboMate = nil;
}
glDeleteTextures(1, &natras->texid);
break;
case Raster::CAMERA:
break;
}
natras->texid = 0;
natras->fbo = 0;
#endif
return object;
}
@ -474,6 +541,8 @@ copyNativeRaster(void *dst, void *, int32 offset, int32)
{
Gl3Raster *d = PLUGINOFFSET(Gl3Raster, dst, offset);
d->texid = 0;
d->fbo = 0;
d->fboMate = nil;
return dst;
}

View File

@ -184,6 +184,7 @@ void setTexture(int32 n, Texture *tex);
void setAlphaBlend(bool32 enable);
bool32 getAlphaBlend(void);
void bindFramebuffer(uint32 fbo);
uint32 bindTexture(uint32 texid);
void flushCache(void);
@ -235,6 +236,9 @@ struct Gl3Raster
uint8 filterMode;
uint8 addressU;
uint8 addressV;
uint32 fbo; // used for camera texture only!
Raster *fboMate; // color or zbuffer raster mate of this one
};
Texture *readNativeTexture(Stream *stream);