summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorraysan5 <[email protected]>2020-09-18 02:11:49 +0200
committerraysan5 <[email protected]>2020-09-18 02:11:49 +0200
commitcdc8850e6877084657a9c2be1142878e8e1a7f0a (patch)
tree23e75572844f6a8dc689b231e201ec6e440828e0
parentfa2c1146366557e5ce779d8b5c2575579dfa6389 (diff)
downloadraylib-cdc8850e6877084657a9c2be1142878e8e1a7f0a.tar.gz
raylib-cdc8850e6877084657a9c2be1142878e8e1a7f0a.zip
WARNING: REDESIGN of rlgl framebuffers API #721
This redesign allows more flexibility when creating RenderTexture and a simplification (and hopefully removal) of `GenTexture*()` functions, that should not belong to this model but the user code, due to the use of custom shaders. Also, this new API opens the door for a possible GBuffers type and advance rendering possibilities... Some functions of the API have been also simplified or even removed. rlgl module can be used as an standalone library, so, a version for the library has been added: v3.1.0, matching current raylib version.
-rw-r--r--src/core.c6
-rw-r--r--src/models.c2
-rw-r--r--src/rlgl.h369
-rw-r--r--src/textures.c47
4 files changed, 197 insertions, 227 deletions
diff --git a/src/core.c b/src/core.c
index db7b6615..2b69fc82 100644
--- a/src/core.c
+++ b/src/core.c
@@ -1543,7 +1543,7 @@ void BeginTextureMode(RenderTexture2D target)
{
rlglDraw(); // Draw Buffers (Only OpenGL 3+ and ES2)
- rlEnableRenderTexture(target.id); // Enable render target
+ rlEnableFramebuffer(target.id); // Enable render target
// Set viewport to framebuffer size
rlViewport(0, 0, target.texture.width, target.texture.height);
@@ -1569,9 +1569,9 @@ void BeginTextureMode(RenderTexture2D target)
// Ends drawing to render texture
void EndTextureMode(void)
{
- rlglDraw(); // Draw Buffers (Only OpenGL 3+ and ES2)
+ rlglDraw(); // Draw Buffers (Only OpenGL 3+ and ES2)
- rlDisableRenderTexture(); // Disable render target
+ rlDisableFramebuffer(); // Disable render target (fbo)
// Set viewport to default framebuffer size
SetupViewport(CORE.Window.render.width, CORE.Window.render.height);
diff --git a/src/models.c b/src/models.c
index f7d59af7..2a815e7c 100644
--- a/src/models.c
+++ b/src/models.c
@@ -944,7 +944,7 @@ void UnloadMaterial(Material material)
// Unload loaded texture maps (avoid unloading default texture, managed by raylib)
for (int i = 0; i < MAX_MATERIAL_MAPS; i++)
{
- if (material.maps[i].texture.id != GetTextureDefault().id) rlDeleteTextures(material.maps[i].texture.id);
+ if (material.maps[i].texture.id != GetTextureDefault().id) rlUnloadTexture(material.maps[i].texture.id);
}
RL_FREE(material.maps);
diff --git a/src/rlgl.h b/src/rlgl.h
index a90e1f4c..d32d20db 100644
--- a/src/rlgl.h
+++ b/src/rlgl.h
@@ -1,6 +1,6 @@
/**********************************************************************************************
*
-* rlgl - raylib OpenGL abstraction layer
+* rlgl v3.1.0 - raylib OpenGL abstraction layer
*
* rlgl is a wrapper for multiple OpenGL versions (1.1, 2.1, 3.3 Core, ES 2.0) to
* pseudo-OpenGL 1.1 style functions (rlVertex, rlTranslate, rlRotate...).
@@ -205,7 +205,15 @@
//----------------------------------------------------------------------------------
typedef enum { OPENGL_11 = 1, OPENGL_21, OPENGL_33, OPENGL_ES_20 } GlVersion;
-typedef unsigned char byte;
+typedef enum {
+ RL_ATTACHMENT_COLOR_TEXTURE = 0,
+ RL_ATTACHMENT_COLOR_CUBEMAP = 20,
+ RL_ATTACHMENT_COLOR_RENDERBUFFER = 40,
+ RL_ATTACHMENT_DEPTH_TEXTURE = 100,
+ RL_ATTACHMENT_DEPTH_RENDERBUFFER = 101,
+ RL_ATTACHMENT_STENCIL_TEXTURE = 200,
+ RL_ATTACHMENT_STENCIL_RENDERBUFFER = 201,
+} FramebufferAttachType;
#if defined(RLGL_STANDALONE)
#ifndef __cplusplus
@@ -245,16 +253,6 @@ typedef unsigned char byte;
// TextureCubemap type, actually, same as Texture2D
typedef Texture2D TextureCubemap;
- // RenderTexture2D type, for texture rendering
- typedef struct RenderTexture2D {
- unsigned int id; // OpenGL framebuffer (fbo) id
- Texture2D texture; // Color buffer attachment texture
- Texture2D depth; // Depth buffer attachment texture
- } RenderTexture2D;
-
- // RenderTexture type, same as RenderTexture2D
- typedef RenderTexture2D RenderTexture;
-
// Vertex data definning a mesh
typedef struct Mesh {
int vertexCount; // number of vertices stored in arrays
@@ -329,7 +327,6 @@ typedef unsigned char byte;
int eyeViewportLeft[4]; // VR stereo rendering left eye viewport [x, y, w, h]
} VrStereoConfig;
-
// TraceLog message types
typedef enum {
LOG_ALL,
@@ -482,7 +479,7 @@ RLAPI void rlVertex2f(float x, float y); // Define one vertex (posi
RLAPI void rlVertex3f(float x, float y, float z); // Define one vertex (position) - 3 float
RLAPI void rlTexCoord2f(float x, float y); // Define one vertex (texture coordinate) - 2 float
RLAPI void rlNormal3f(float x, float y, float z); // Define one vertex (normal) - 3 float
-RLAPI void rlColor4ub(byte r, byte g, byte b, byte a); // Define one vertex (color) - 4 byte
+RLAPI void rlColor4ub(unsigned char r, unsigned char g, unsigned char b, unsigned char a); // Define one vertex (color) - 4 byte
RLAPI void rlColor3f(float x, float y, float z); // Define one vertex (color) - 3 float
RLAPI void rlColor4f(float x, float y, float z, float w); // Define one vertex (color) - 4 float
@@ -493,8 +490,8 @@ RLAPI void rlColor4f(float x, float y, float z, float w); // Define one vertex (
RLAPI void rlEnableTexture(unsigned int id); // Enable texture usage
RLAPI void rlDisableTexture(void); // Disable texture usage
RLAPI void rlTextureParameters(unsigned int id, int param, int value); // Set texture parameters (filter, wrap)
-RLAPI void rlEnableRenderTexture(unsigned int id); // Enable render texture (fbo)
-RLAPI void rlDisableRenderTexture(void); // Disable render texture (fbo), return to default framebuffer
+RLAPI void rlEnableFramebuffer(unsigned int id); // Enable render texture (fbo)
+RLAPI void rlDisableFramebuffer(void); // Disable render texture (fbo), return to default framebuffer
RLAPI void rlEnableDepthTest(void); // Enable depth test
RLAPI void rlDisableDepthTest(void); // Disable depth test
RLAPI void rlEnableBackfaceCulling(void); // Enable backface culling
@@ -504,12 +501,8 @@ RLAPI void rlDisableScissorTest(void); // Disable scissor
RLAPI void rlScissor(int x, int y, int width, int height); // Scissor test
RLAPI void rlEnableWireMode(void); // Enable wire mode
RLAPI void rlDisableWireMode(void); // Disable wire mode
-RLAPI void rlDeleteTextures(unsigned int id); // Delete OpenGL texture from GPU
-RLAPI void rlDeleteRenderTextures(RenderTexture2D target); // Delete render textures (fbo) from GPU
-RLAPI void rlDeleteShader(unsigned int id); // Delete OpenGL shader program from GPU
-RLAPI void rlDeleteVertexArrays(unsigned int id); // Unload vertex data (VAO) from GPU memory
-RLAPI void rlDeleteBuffers(unsigned int id); // Unload vertex data (VBO) from GPU memory
-RLAPI void rlClearColor(byte r, byte g, byte b, byte a); // Clear color buffer with color
+
+RLAPI void rlClearColor(unsigned char r, unsigned char g, unsigned char b, unsigned char a); // Clear color buffer with color
RLAPI void rlClearScreenBuffers(void); // Clear used screen buffers (color and depth)
RLAPI void rlUpdateBuffer(int bufferId, void *data, int dataSize); // Update GPU buffer with new data
RLAPI unsigned int rlLoadAttribBuffer(unsigned int vaoId, int shaderLoc, void *buffer, int size, bool dynamic); // Load a new attributes buffer
@@ -530,7 +523,7 @@ RLAPI void rlLoadExtensions(void *loader); // Load OpenGL extensions
// Textures data management
RLAPI unsigned int rlLoadTexture(void *data, int width, int height, int format, int mipmapCount); // Load texture in GPU
-RLAPI unsigned int rlLoadTextureDepth(int width, int height, int bits, bool useRenderBuffer); // Load depth texture/renderbuffer (to be attached to fbo)
+RLAPI unsigned int rlLoadTextureDepth(int width, int height, bool useRenderBuffer); // Load depth texture/renderbuffer (to be attached to fbo)
RLAPI unsigned int rlLoadTextureCubemap(void *data, int size, int format); // Load texture cubemap
RLAPI void rlUpdateTexture(unsigned int id, int offsetX, int offsetY, int width, int height, int format, const void *data); // Update GPU texture with new data
RLAPI void rlGetGlTextureFormats(int format, unsigned int *glInternalFormat, unsigned int *glFormat, unsigned int *glType); // Get OpenGL internal formats
@@ -540,10 +533,11 @@ RLAPI void rlGenerateMipmaps(Texture2D *texture); // Gen
RLAPI void *rlReadTexturePixels(Texture2D texture); // Read texture pixel data
RLAPI unsigned char *rlReadScreenPixels(int width, int height); // Read screen pixel data (color buffer)
-// Render texture management (fbo)
-RLAPI RenderTexture2D rlLoadRenderTexture(int width, int height, int format, int depthBits, bool useDepthTexture); // Load a render texture (with color and depth attachments)
-RLAPI void rlRenderTextureAttach(RenderTexture target, unsigned int id, int attachType); // Attach texture/renderbuffer to an fbo
-RLAPI bool rlRenderTextureComplete(RenderTexture target); // Verify render texture is complete
+// Framebuffer management (fbo)
+RLAPI unsigned int rlLoadFramebuffer(int width, int height); // Load an empty framebuffer
+RLAPI void rlFramebufferAttach(unsigned int fboId, unsigned int texId, int attachType); // Attach texture/renderbuffer to a framebuffer
+RLAPI bool rlFramebufferComplete(unsigned int id); // Verify framebuffer is complete
+RLAPI void rlUnloadFramebuffer(unsigned int id); // Delete framebuffer from GPU
// Vertex data management
RLAPI void rlLoadMesh(Mesh *mesh, bool dynamic); // Upload vertex data into GPU and provided VAO/VBO ids
@@ -883,7 +877,8 @@ typedef struct rlglData {
#if defined(SUPPORT_VR_SIMULATOR)
struct {
VrStereoConfig config; // VR stereo configuration for simulator
- RenderTexture2D stereoFbo; // VR stereo rendering framebuffer
+ unsigned int stereoFboId; // VR stereo rendering framebuffer id
+ unsigned int stereoTexId; // VR stereo color texture (attached to framebuffer)
bool simulatorReady; // VR simulator ready flag
bool stereoRender; // VR stereo rendering enabled/disabled flag
} Vr;
@@ -1114,7 +1109,7 @@ void rlVertex2f(float x, float y) { glVertex2f(x, y); }
void rlVertex3f(float x, float y, float z) { glVertex3f(x, y, z); }
void rlTexCoord2f(float x, float y) { glTexCoord2f(x, y); }
void rlNormal3f(float x, float y, float z) { glNormal3f(x, y, z); }
-void rlColor4ub(byte r, byte g, byte b, byte a) { glColor4ub(r, g, b, a); }
+void rlColor4ub(unsigned char r, unsigned char g, unsigned char b, unsigned char a) { glColor4ub(r, g, b, a); }
void rlColor3f(float x, float y, float z) { glColor3f(x, y, z); }
void rlColor4f(float x, float y, float z, float w) { glColor4f(x, y, z, w); }
@@ -1262,7 +1257,7 @@ void rlNormal3f(float x, float y, float z)
}
// Define one vertex (color)
-void rlColor4ub(byte x, byte y, byte z, byte w)
+void rlColor4ub(unsigned char x, unsigned char y, unsigned char z, unsigned char w)
{
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].colors[4*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].cCounter] = x;
RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].colors[4*RLGL.currentBatch->vertexBuffer[RLGL.currentBatch->currentBuffer].cCounter + 1] = y;
@@ -1274,13 +1269,13 @@ void rlColor4ub(byte x, byte y, byte z, byte w)
// Define one vertex (color)
void rlColor4f(float r, float g, float b, float a)
{
- rlColor4ub((byte)(r*255), (byte)(g*255), (byte)(b*255), (byte)(a*255));
+ rlColor4ub((unsigned char)(r*255), (unsigned char)(g*255), (unsigned char)(b*255), (unsigned char)(a*255));
}
// Define one vertex (color)
void rlColor3f(float x, float y, float z)
{
- rlColor4ub((byte)(x*255), (byte)(y*255), (byte)(z*255), 255);
+ rlColor4ub((unsigned char)(x*255), (unsigned char)(y*255), (unsigned char)(z*255), 255);
}
#endif
@@ -1385,7 +1380,7 @@ void rlTextureParameters(unsigned int id, int param, int value)
}
// Enable rendering to texture (fbo)
-void rlEnableRenderTexture(unsigned int id)
+void rlEnableFramebuffer(unsigned int id)
{
#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)) && defined(SUPPORT_RENDER_TEXTURES_HINT)
glBindFramebuffer(GL_FRAMEBUFFER, id);
@@ -1396,7 +1391,7 @@ void rlEnableRenderTexture(unsigned int id)
}
// Disable rendering to texture
-void rlDisableRenderTexture(void)
+void rlDisableFramebuffer(void)
{
#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)) && defined(SUPPORT_RENDER_TEXTURES_HINT)
glBindFramebuffer(GL_FRAMEBUFFER, 0);
@@ -1445,88 +1440,34 @@ void rlDisableWireMode(void)
#endif
}
-// Unload texture from GPU memory
-void rlDeleteTextures(unsigned int id)
-{
- if (id > 0) glDeleteTextures(1, &id);
-}
-
-// Unload render texture from GPU memory
+// Unload framebuffer from GPU memory
// NOTE: All attached textures/cubemaps/renderbuffers are also deleted
-void rlDeleteRenderTextures(RenderTexture2D target)
+void rlUnloadFramebuffer(unsigned int id)
{
#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)) && defined(SUPPORT_RENDER_TEXTURES_HINT)
- int depthType = 0;
- glBindFramebuffer(GL_FRAMEBUFFER, target.id); // Bind framebuffer to query depth texture type
+
+ // Query depth attachment to automatically delete texture/renderbuffer
+ int depthType = 0, depthId = 0;
+ glBindFramebuffer(GL_FRAMEBUFFER, id); // Bind framebuffer to query depth texture type
glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &depthType);
- glBindFramebuffer(GL_FRAMEBUFFER, 0); // Unbind framebuffer to delete textures
+ glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &depthId);
+
+ unsigned int depthIdU = (unsigned int)depthId;
+ if (depthType == GL_RENDERBUFFER) glDeleteRenderbuffers(1, &depthIdU);
+ else if (depthType == GL_RENDERBUFFER) glDeleteTextures(1, &depthIdU);
// NOTE: If a texture object is deleted while its image is attached to the *currently bound* framebuffer,
// the texture image is automatically detached from the currently bound framebuffer.
- if (target.texture.id > 0)
- {
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); // Detach texture from FBO
- glDeleteTextures(1, &target.texture.id);
- }
- if (target.depth.id > 0)
- {
- if (depthType == GL_TEXTURE)
- {
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
- glDeleteTextures(1, &target.depth.id);
- }
- else if (depthType == GL_RENDERBUFFER)
- {
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
- glDeleteRenderbuffers(1, &target.depth.id);
- }
- }
-
- if (target.id > 0) glDeleteFramebuffers(1, &target.id);
-
- TRACELOG(LOG_INFO, "FBO: [ID %i] Unloaded render texture data from VRAM (GPU)", target.id);
-#endif
-}
-
-// Unload shader from GPU memory
-void rlDeleteShader(unsigned int id)
-{
-#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
- if (id != 0) glDeleteProgram(id);
-#endif
-}
-
-// Unload vertex data (VAO) from GPU memory
-void rlDeleteVertexArrays(unsigned int id)
-{
-#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
- if (RLGL.ExtSupported.vao)
- {
- if (id != 0)
- {
- glBindVertexArray(0);
- glDeleteVertexArrays(1, &id);
- TRACELOG(LOG_INFO, "VAO: [ID %i] Unloaded vertex data from VRAM (GPU)", id);
- }
- }
-#endif
-}
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ glDeleteFramebuffers(1, &id);
-// Unload vertex data (VBO) from GPU memory
-void rlDeleteBuffers(unsigned int id)
-{
-#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
- if (id != 0)
- {
- glDeleteBuffers(1, &id);
- if (!RLGL.ExtSupported.vao) TRACELOG(LOG_INFO, "VBO: [ID %i] Unloaded vertex data from VRAM (GPU)", id);
- }
+ TRACELOG(LOG_INFO, "FBO: [ID %i] Unloaded framebuffer from VRAM (GPU)", id);
#endif
}
// Clear color buffer with color
-void rlClearColor(byte r, byte g, byte b, byte a)
+void rlClearColor(unsigned char r, unsigned char g, unsigned char b, unsigned char a)
{
// Color values clamp to 0.0f(0) and 1.0f(255)
float cr = (float)r/255;
@@ -2090,33 +2031,23 @@ unsigned int rlLoadTexture(void *data, int width, int height, int format, int mi
// Load depth texture/renderbuffer (to be attached to fbo)
// WARNING: OpenGL ES 2.0 requires GL_OES_depth_texture/WEBGL_depth_texture extensions
-unsigned int rlLoadTextureDepth(int width, int height, int bits, bool useRenderBuffer)
+unsigned int rlLoadTextureDepth(int width, int height, bool useRenderBuffer)
{
unsigned int id = 0;
-
+
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
- unsigned int glInternalFormat = GL_DEPTH_COMPONENT16;
+ if (!RLGL.ExtSupported.texDepth) useRenderBuffer = false;
- if ((bits != 16) && (bits != 24) && (bits != 32)) bits = 16;
-
- if (bits == 24)
- {
+ // NOTE: We let the implementation to choose the best bit-depth
+ unsigned int glInternalFormat = GL_DEPTH_COMPONENT;
+/*
#if defined(GRAPHICS_API_OPENGL_33)
- glInternalFormat = GL_DEPTH_COMPONENT24;
+ glInternalFormat = GL_DEPTH_COMPONENT24; // GL_DEPTH_COMPONENT32
#elif defined(GRAPHICS_API_OPENGL_ES2)
- if (RLGL.ExtSupported.maxDepthBits >= 24) glInternalFormat = GL_DEPTH_COMPONENT24_OES;
+ if (RLGL.ExtSupported.maxDepthBits == 32) glInternalFormat = GL_DEPTH_COMPONENT32_OES;
+ else if (RLGL.ExtSupported.maxDepthBits == 24) glInternalFormat = GL_DEPTH_COMPONENT24_OES;
#endif
- }
-
- if (bits == 32)
- {
-#if defined(GRAPHICS_API_OPENGL_33)
- glInternalFormat = GL_DEPTH_COMPONENT32;
-#elif defined(GRAPHICS_API_OPENGL_ES2)
- if (RLGL.ExtSupported.maxDepthBits == 32) glInternalFormat = GL_DEPTH_COMPONENT32_OES;
-#endif
- }
-
+*/
if (!useRenderBuffer && RLGL.ExtSupported.texDepth)
{
glGenTextures(1, &id);
@@ -2146,7 +2077,7 @@ unsigned int rlLoadTextureDepth(int width, int height, int bits, bool useRenderB
}
// Load texture cubemap
-// NOTE: Cubemap data is expected to be 6 images in a single column,
+// NOTE: Cubemap data is expected to be 6 images in a single data array (one after the other),
// expected the following convention: +X, -X, +Y, -Y, +Z, -Z
unsigned int rlLoadTextureCubemap(void *data, int size, int format)
{
@@ -2166,8 +2097,30 @@ unsigned int rlLoadTextureCubemap(void *data, int size, int format)
// Load cubemap faces
for (unsigned int i = 0; i < 6; i++)
{
- if (format < COMPRESSED_DXT1_RGB) glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, size, size, 0, glFormat, glType, (unsigned char *)data + i*dataSize);
- else glCompressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, size, size, 0, dataSize, (unsigned char *)data + i*dataSize);
+ if (data == NULL)
+ {
+ if (format < COMPRESSED_DXT1_RGB)
+ {
+ if (format == UNCOMPRESSED_R32G32B32)
+ {
+ #if defined(GRAPHICS_API_OPENGL_33)
+ // Instead of using a sized internal texture format (GL_RGB16F, GL_RGB32F),
+ // we let the driver to choose the better format for us (GL_RGB)
+ glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, size, size, 0, GL_RGB, GL_FLOAT, NULL);
+ #elif defined(GRAPHICS_API_OPENGL_ES2)
+ if (RLGL.ExtSupported.texFloat32) glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, size, size, 0, GL_RGB, GL_FLOAT, NULL);
+ #endif
+ }
+ else if ((format == UNCOMPRESSED_R32) || (format == UNCOMPRESSED_R32G32B32A32)) TRACELOG(LOG_WARNING, "TEXTURES: Cubemap requested format not supported");
+ else glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, size, size, 0, glFormat, glType, NULL);
+ }
+ else TRACELOG(LOG_WARNING, "TEXTURES: Empty cubemap creation does not support compressed format");
+ }
+ else
+ {
+ if (format < COMPRESSED_DXT1_RGB) glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, size, size, 0, glFormat, glType, (unsigned char *)data + i*dataSize);
+ else glCompressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, size, size, 0, dataSize, (unsigned char *)data + i*dataSize);
+ }
#if defined(GRAPHICS_API_OPENGL_33)
if (format == UNCOMPRESSED_GRAYSCALE)
@@ -2274,79 +2227,40 @@ void rlGetGlTextureFormats(int format, unsigned int *glInternalFormat, unsigned
// Unload texture from GPU memory
void rlUnloadTexture(unsigned int id)
{
- if (id > 0) glDeleteTextures(1, &id);
+ glDeleteTextures(1, &id);
}
-// Load a texture to be used for rendering (fbo with default color and depth attachments)
-// NOTE: If colorFormat or depthBits are no supported, no attachment is done
-RenderTexture2D rlLoadRenderTexture(int width, int height, int format, int depthBits, bool useDepthTexture)
+// Load a framebuffer to be used for rendering
+// NOTE: No textures attached
+unsigned int rlLoadFramebuffer(int width, int height)
{
- RenderTexture2D target = { 0 };
+ unsigned int fboId = 0;
#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)) && defined(SUPPORT_RENDER_TEXTURES_HINT)
- if (useDepthTexture && !RLGL.ExtSupported.texDepth) useDepthTexture = false;
-
- // Create the framebuffer object
- glGenFramebuffers(1, &target.id);
- glBindFramebuffer(GL_FRAMEBUFFER, target.id);
-
- // Create fbo color texture attachment
- //-----------------------------------------------------------------------------------------------------
- if ((format != -1) && (format < COMPRESSED_DXT1_RGB))
- {
- // WARNING: Some texture formats are not supported for fbo color attachment
- target.texture.id = rlLoadTexture(NULL, width, height, format, 1);
- target.texture.width = width;
- target.texture.height = height;
- target.texture.format = format;
- target.texture.mipmaps = 1;
- }
- //-----------------------------------------------------------------------------------------------------
-
- // Create fbo depth renderbuffer/texture
- //-----------------------------------------------------------------------------------------------------
- if (depthBits > 0)
- {
- target.depth.id = rlLoadTextureDepth(width, height, depthBits, !useDepthTexture);
- target.depth.width = width;
- target.depth.height = height;
- target.depth.format = 19; //DEPTH_COMPONENT_24BIT?
- target.depth.mipmaps = 1;
- }
- //-----------------------------------------------------------------------------------------------------
-
- // Attach color texture and depth renderbuffer to FBO
- //-----------------------------------------------------------------------------------------------------
- rlRenderTextureAttach(target, target.texture.id, 0); // COLOR attachment
- rlRenderTextureAttach(target, target.depth.id, 1); // DEPTH attachment
- //-----------------------------------------------------------------------------------------------------
-
- // Check if fbo is complete with attachments (valid)
- //-----------------------------------------------------------------------------------------------------
- if (rlRenderTextureComplete(target)) TRACELOG(LOG_INFO, "FBO: [ID %i] Framebuffer object created successfully", target.id);
- //-----------------------------------------------------------------------------------------------------
-
- glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ glGenFramebuffers(1, &fboId); // Create the framebuffer object
+ glBindFramebuffer(GL_FRAMEBUFFER, 0); // Unbind any framebuffer
#endif
- return target;
+ return fboId;
}
// Attach color buffer texture to an fbo (unloads previous attachment)
// NOTE: Attach type: 0-Color, 1-Depth renderbuffer, 2-Depth texture
-void rlRenderTextureAttach(RenderTexture2D target, unsigned int id, int attachType)
+void rlFramebufferAttach(unsigned int fboId, unsigned int texId, int attachType)
{
#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)) && defined(SUPPORT_RENDER_TEXTURES_HINT)
- glBindFramebuffer(GL_FRAMEBUFFER, target.id);
+ glBindFramebuffer(GL_FRAMEBUFFER, fboId);
- if (attachType == 0) glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, id, 0);
- else if (attachType == 1)
+ switch (attachType)
{
- int depthType = 0;
- glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &depthType);
-
- if (depthType == GL_TEXTURE) glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, id, 0);
- else if (depthType == GL_RENDERBUFFER) glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, id);
+ case RL_ATTACHMENT_COLOR_TEXTURE: glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texId, 0); break; // TODO: Support multiple color attachments
+ case RL_ATTACHMENT_COLOR_CUBEMAP: glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X, texId, 0); break; // TODO: Support multiple faces attachments
+ case RL_ATTACHMENT_COLOR_RENDERBUFFER: glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, texId, 0); break;
+ case RL_ATTACHMENT_DEPTH_TEXTURE: glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, texId, 0); break;
+ case RL_ATTACHMENT_DEPTH_RENDERBUFFER: glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, texId); break;
+ case RL_ATTACHMENT_STENCIL_TEXTURE: glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, texId); break;
+ case RL_ATTACHMENT_STENCIL_RENDERBUFFER: glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, texId); break;
+ default: break;
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
@@ -2354,12 +2268,12 @@ void rlRenderTextureAttach(RenderTexture2D target, unsigned int id, int attachTy
}
// Verify render texture is complete
-bool rlRenderTextureComplete(RenderTexture target)
+bool rlFramebufferComplete(unsigned int id)
{
bool result = false;
#if (defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)) && defined(SUPPORT_RENDER_TEXTURES_HINT)
- glBindFramebuffer(GL_FRAMEBUFFER, target.id);
+ glBindFramebuffer(GL_FRAMEBUFFER, id);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
@@ -2367,12 +2281,12 @@ bool rlRenderTextureComplete(RenderTexture target)
{
switch (status)
{
- case GL_FRAMEBUFFER_UNSUPPORTED: TRACELOG(LOG_WARNING, "FBO: [ID %i] Framebuffer is unsupported", target.id); break;
- case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: TRACELOG(LOG_WARNING, "FBO: [ID %i] Framebuffer has incomplete attachment", target.id); break;
+ case GL_FRAMEBUFFER_UNSUPPORTED: TRACELOG(LOG_WARNING, "FBO: [ID %i] Framebuffer is unsupported", id); break;
+ case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: TRACELOG(LOG_WARNING, "FBO: [ID %i] Framebuffer has incomplete attachment", id); break;
#if defined(GRAPHICS_API_OPENGL_ES2)
- case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: TRACELOG(LOG_WARNING, "FBO: [ID %i] Framebuffer has incomplete dimensions", target.id); break;
+ case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: TRACELOG(LOG_WARNING, "FBO: [ID %i] Framebuffer has incomplete dimensions", id); break;
#endif
- case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: TRACELOG(LOG_WARNING, "FBO: [ID %i] Framebuffer has a missing attachment", target.id); break;
+ case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: TRACELOG(LOG_WARNING, "FBO: [ID %i] Framebuffer has a missing attachment", id); break;
default: break;
}
}
@@ -2908,15 +2822,16 @@ void rlUnloadMesh(Mesh mesh)
RL_FREE(mesh.boneWeights);
RL_FREE(mesh.boneIds);
- rlDeleteBuffers(mesh.vboId[0]); // vertex
- rlDeleteBuffers(mesh.vboId[1]); // texcoords
- rlDeleteBuffers(mesh.vboId[2]); // normals
- rlDeleteBuffers(mesh.vboId[3]); // colors
- rlDeleteBuffers(mesh.vboId[4]); // tangents
- rlDeleteBuffers(mesh.vboId[5]); // texcoords2
- rlDeleteBuffers(mesh.vboId[6]); // indices
-
- rlDeleteVertexArrays(mesh.vaoId);
+#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
+ for (int i = 0; i < 7; i++) glDeleteBuffers(1, &mesh.vboId[i]); // DEFAULT_MESH_VERTEX_BUFFERS (model.c)
+ if (RLGL.ExtSupported.vao)
+ {
+ glBindVertexArray(0);
+ glDeleteVertexArrays(1, &mesh.vaoId);
+ TRACELOG(LOG_INFO, "VAO: [ID %i] Unloaded vertex data from VRAM (GPU)", mesh.vaoId);
+ }
+ else TRACELOG(LOG_INFO, "VBO: Unloaded vertex data from VRAM (GPU)");
+#endif
}
// Read screen pixel data (color buffer)
@@ -2991,13 +2906,15 @@ void *rlReadTexturePixels(Texture2D texture)
// 2 - Create an fbo, activate it, render quad with texture, glReadPixels()
// We are using Option 1, just need to care for texture format on retrieval
// NOTE: This behaviour could be conditioned by graphic driver...
- RenderTexture2D fbo = rlLoadRenderTexture(texture.width, texture.height, UNCOMPRESSED_R8G8B8A8, 16, false);
+ unsigned int fboId = rlLoadFramebuffer(texture.width, texture.height);
+
+ // TODO: Create depth texture/renderbuffer for fbo?
+
- glBindFramebuffer(GL_FRAMEBUFFER, fbo.id);
+ glBindFramebuffer(GL_FRAMEBUFFER, fboId);
glBindTexture(GL_TEXTURE_2D, 0);
// Attach our texture to FBO
- // NOTE: Previoust attached texture is automatically detached
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.id, 0);
// We read data as RGBA because FBO texture is configured as RGBA, despite binding another texture format
@@ -3010,7 +2927,7 @@ void *rlReadTexturePixels(Texture2D texture)
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// Clean up temporal fbo
- rlDeleteRenderTextures(fbo);
+ rlUnloadFramebuffer(fbo);
#endif
return pixels;
@@ -3172,13 +3089,15 @@ Shader LoadShaderCode(const char *vsCode, const char *fsCode)
// Unload shader from GPU memory (VRAM)
void UnloadShader(Shader shader)
{
- if ((shader.id != RLGL.State.defaultShader.id) && (shader.id > 0))
+#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
+ if (shader.id != RLGL.State.defaultShader.id)
{
- rlDeleteShader(shader.id);
+ glDeleteProgram(shader.id);
RL_FREE(shader.locs);
TRACELOG(LOG_INFO, "SHADER: [ID %i] Unloaded shader program data from VRAM (GPU)", shader.id);
}
+#endif
}
// Begin custom shader mode
@@ -3674,13 +3593,21 @@ void EndBlendMode(void)
#if defined(SUPPORT_VR_SIMULATOR)
// Init VR simulator for selected device parameters
-// NOTE: It modifies the global variable: RLGL.Vr.stereoFbo
+// NOTE: It modifies the global variable: RLGL.Vr.stereoFboId
void InitVrSimulator(void)
{
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
// Initialize framebuffer and textures for stereo rendering
// NOTE: Screen size should match HMD aspect ratio
- RLGL.Vr.stereoFbo = rlLoadRenderTexture(RLGL.State.framebufferWidth, RLGL.State.framebufferHeight, UNCOMPRESSED_R8G8B8A8, 24, false);
+ RLGL.Vr.stereoFboId = rlLoadFramebuffer(RLGL.State.framebufferWidth, RLGL.State.framebufferHeight);
+
+ // Load color/depth textures to attach to framebuffer
+ RLGL.Vr.stereoTexId = rlLoadTexture(NULL, RLGL.State.framebufferWidth, RLGL.State.framebufferHeight, UNCOMPRESSED_R8G8B8A8, 1);
+ unsigned int depthId = rlLoadTextureDepth(RLGL.State.framebufferWidth, RLGL.State.framebufferHeight, true);
+
+ // Attach color texture and depth renderbuffer/texture to FBO
+ rlFramebufferAttach(RLGL.Vr.stereoFboId, RLGL.Vr.stereoTexId, RL_ATTACHMENT_COLOR_TEXTURE);
+ rlFramebufferAttach(RLGL.Vr.stereoFboId, depthId, RL_ATTACHMENT_DEPTH_RENDERBUFFER);
RLGL.Vr.simulatorReady = true;
#else
@@ -3699,7 +3626,11 @@ void UpdateVrTracking(Camera *camera)
void CloseVrSimulator(void)
{
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
- if (RLGL.Vr.simulatorReady) rlDeleteRenderTextures(RLGL.Vr.stereoFbo); // Unload stereo framebuffer and texture
+ if (RLGL.Vr.simulatorReady)
+ {
+ rlUnloadTexture(RLGL.Vr.stereoTexId); // Unload color texture
+ rlUnloadFramebuffer(RLGL.Vr.stereoFboId); // Unload stereo framebuffer and depth texture/renderbuffer
+ }
#endif
}
@@ -3823,11 +3754,11 @@ void BeginVrDrawing(void)
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
if (RLGL.Vr.simulatorReady)
{
- rlEnableRenderTexture(RLGL.Vr.stereoFbo.id); // Setup framebuffer for stereo rendering
- //glEnable(GL_FRAMEBUFFER_SRGB); // Enable SRGB framebuffer (only if required)
+ rlEnableFramebuffer(RLGL.Vr.stereoFboId); // Setup framebuffer for stereo rendering
+ //glEnable(GL_FRAMEBUFFER_SRGB); // Enable SRGB framebuffer (only if required)
- //glViewport(0, 0, buffer.width, buffer.height); // Useful if rendering to separate framebuffers (every eye)
- rlClearScreenBuffers(); // Clear current framebuffer
+ //rlViewport(0, 0, buffer.width, buffer.height); // Useful if rendering to separate framebuffers (every eye)
+ rlClearScreenBuffers(); // Clear current framebuffer
RLGL.Vr.stereoRender = true;
}
@@ -3840,9 +3771,9 @@ void EndVrDrawing(void)
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
if (RLGL.Vr.simulatorReady)
{
- RLGL.Vr.stereoRender = false; // Disable stereo render
+ RLGL.Vr.stereoRender = false; // Disable stereo render
- rlDisableRenderTexture(); // Unbind current framebuffer
+ rlDisableFramebuffer(); // Unbind current framebuffer
rlClearScreenBuffers(); // Clear current framebuffer
@@ -3856,11 +3787,11 @@ void EndVrDrawing(void)
rlMatrixMode(RL_MODELVIEW); // Enable internal modelview matrix
rlLoadIdentity(); // Reset internal modelview matrix
- // Draw RenderTexture (RLGL.Vr.stereoFbo) using distortion shader if available
+ // Draw stereo framebuffer texture using distortion shader if available
if (RLGL.Vr.config.distortionShader.id > 0) RLGL.State.currentShader = RLGL.Vr.config.distortionShader;
else RLGL.State.currentShader = GetShaderDefault();
- rlEnableTexture(RLGL.Vr.stereoFbo.texture.id);
+ rlEnableTexture(RLGL.Vr.stereoTexId);
rlPushMatrix();
rlBegin(RL_QUADS);
@@ -3873,15 +3804,15 @@ void EndVrDrawing(void)
// Bottom-right corner for texture and quad
rlTexCoord2f(0.0f, 0.0f);
- rlVertex2f(0.0f, (float)RLGL.Vr.stereoFbo.texture.height);
+ rlVertex2f(0.0f, (float)RLGL.State.framebufferHeight);
// Top-right corner for texture and quad
rlTexCoord2f(1.0f, 0.0f);
- rlVertex2f((float)RLGL.Vr.stereoFbo.texture.width, (float)RLGL.Vr.stereoFbo.texture.height);
+ rlVertex2f((float)RLGL.State.framebufferWidth, (float)RLGL.State.framebufferHeight);
// Top-left corner for texture and quad
rlTexCoord2f(1.0f, 1.0f);
- rlVertex2f((float)RLGL.Vr.stereoFbo.texture.width, 0.0f);
+ rlVertex2f((float)RLGL.State.framebufferWidth, 0.0f);
rlEnd();
rlPopMatrix();
diff --git a/src/textures.c b/src/textures.c
index c1c60d08..cc636ac5 100644
--- a/src/textures.c
+++ b/src/textures.c
@@ -72,7 +72,7 @@
#include "utils.h" // Required for: fopen() Android mapping
#include "rlgl.h" // raylib OpenGL abstraction layer to OpenGL 1.1, 3.3 or ES2
- // Required for: rlLoadTexture() rlDeleteTextures(),
+ // Required for: rlLoadTexture() rlUnloadTexture(),
// rlGenerateMipmaps(), some funcs for DrawTexturePro()
// Support only desired texture formats on stb_image
@@ -2796,7 +2796,38 @@ TextureCubemap LoadTextureCubemap(Image image, int layoutType)
// NOTE: Render texture is loaded by default with RGBA color attachment and depth RenderBuffer
RenderTexture2D LoadRenderTexture(int width, int height)
{
- RenderTexture2D target = rlLoadRenderTexture(width, height, UNCOMPRESSED_R8G8B8A8, 24, false);
+ RenderTexture2D target = { 0 };
+
+ target.id = rlLoadFramebuffer(width, height); // Load an empty framebuffer
+
+ if (target.id > 0)
+ {
+ rlEnableFramebuffer(target.id);
+
+ // Create color texture (default to RGBA)
+ target.texture.id = rlLoadTexture(NULL, width, height, UNCOMPRESSED_R8G8B8A8, 1);
+ target.texture.width = width;
+ target.texture.height = height;
+ target.texture.format = UNCOMPRESSED_R8G8B8A8;
+ target.texture.mipmaps = 1;
+
+ // Create depth renderbuffer/texture
+ target.depth.id = rlLoadTextureDepth(width, height, true);
+ target.depth.width = width;
+ target.depth.height = height;
+ target.depth.format = 19; //DEPTH_COMPONENT_24BIT?
+ target.depth.mipmaps = 1;
+
+ // Attach color texture and depth renderbuffer/texture to FBO
+ rlFramebufferAttach(target.id, target.texture.id, RL_ATTACHMENT_COLOR_TEXTURE); // COLOR attachment
+ rlFramebufferAttach(target.id, target.depth.id, RL_ATTACHMENT_DEPTH_RENDERBUFFER); // DEPTH attachment
+
+ // Check if fbo is complete with attachments (valid)
+ if (rlFramebufferComplete(target.id)) TRACELOG(LOG_INFO, "FBO: [ID %i] Framebuffer object created successfully", target.id);
+
+ rlDisableFramebuffer();
+ }
+ else TRACELOG(LOG_WARNING, "FBO: Framebuffer object can not be created");
return target;
}
@@ -2806,7 +2837,7 @@ void UnloadTexture(Texture2D texture)
{
if (texture.id > 0)
{
- rlDeleteTextures(texture.id);
+ rlUnloadTexture(texture.id);
TRACELOG(LOG_INFO, "TEXTURE: [ID %i] Unloaded texture data from VRAM (GPU)", texture.id);
}
@@ -2815,7 +2846,15 @@ void UnloadTexture(Texture2D texture)
// Unload render texture from GPU memory (VRAM)
void UnloadRenderTexture(RenderTexture2D target)
{
- if (target.id > 0) rlDeleteRenderTextures(target);
+ if (target.id > 0)
+ {
+ // Color texture attached to FBO is deleted
+ rlUnloadTexture(target.texture.id);
+
+ // NOTE: Depth texture/renderbuffer is automatically
+ // queried and deleted before deleting framebuffer
+ rlUnloadFramebuffer(target.id);
+ }
}
// Update GPU texture with new data