Преглед на файлове

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.
pull/1381/head
raysan5 преди 4 години
родител
ревизия
cdc8850e68
променени са 4 файла, в които са добавени 197 реда и са изтрити 227 реда
  1. +3
    -3
      src/core.c
  2. +1
    -1
      src/models.c
  3. +150
    -219
      src/rlgl.h
  4. +43
    -4
      src/textures.c

+ 3
- 3
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);

+ 1
- 1
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);

+ 150
- 219
src/rlgl.h Целия файл

@ -1,6 +1,6 @@
/**********************************************************************************************
*
* rlgl - raylib OpenGL abstraction layer
* rlgl n">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(n">byte r, byte g, byte b, byte a); // Define one vertex (color) - 4 byte
RLAPI void rlColor4ub(kt">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(n">byte r, byte g, byte b, byte a) { glColor4ub(r, g, b, a); }
void rlColor4ub(kt">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(n">byte x, byte y, byte z, byte w)
void rlColor4ub(kt">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((n">byte)(r*255), (n">byte)(g*255), (n">byte)(b*255), (n">byte)(a*255));
rlColor4ub((kt">unsigned char)(r*255), (kt">unsigned char)(g*255), (kt">unsigned char)(b*255), (kt">unsigned char)(a*255));
}
// Define one vertex (color)
void rlColor3f(float x, float y, float z)
{
rlColor4ub((n">byte)(x*255), (n">byte)(y*255), (n">byte)(z*255), 255);
rlColor4ub((kt">unsigned char)(x*255), (kt">unsigned char)(y*255), (kt">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(n">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)
t">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)
{
k">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
n">RenderTexture2D rlLoadRenderTexture(int width, int height, int format, int depthBits, bool useDepthTexture)
// Load a framebuffer to be used for rendering
// NOTE: No textures attached
kt">unsigned int rlLoadFramebuffer(int width, int height)
{
n">RenderTexture2D target = { 0 };
kt">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();

+ 43
- 4
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

Зареждане…
Отказ
Запис