aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorraysan5 <raysan5@gmail.com>2016-03-30 20:09:16 +0200
committerraysan5 <raysan5@gmail.com>2016-03-30 20:09:16 +0200
commit66b096d97848eb096a043781f1f305e7189f2a00 (patch)
treecf87fdd3f4bc46dc93dcaa2f189a5d1dd1e3f32b /src
parent1136d4222f81524c10b2319b325fcf1282bc6ec1 (diff)
downloadraylib-66b096d97848eb096a043781f1f305e7189f2a00.tar.gz
raylib-66b096d97848eb096a043781f1f305e7189f2a00.zip
Added support for render to texture (use RenderTexture2D)
Now it's possible to render to texture, old postprocessing system will be removed on next raylib version.
Diffstat (limited to 'src')
-rw-r--r--src/core.c22
-rw-r--r--src/raylib.h11
-rw-r--r--src/rlgl.c118
-rw-r--r--src/rlgl.h11
-rw-r--r--src/textures.c19
5 files changed, 179 insertions, 2 deletions
diff --git a/src/core.c b/src/core.c
index 5150389c..5a794376 100644
--- a/src/core.c
+++ b/src/core.c
@@ -545,7 +545,7 @@ void BeginDrawing(void)
if (IsPosproShaderEnabled()) rlEnablePostproFBO();
- rlClearScreenBuffers();
+ rlClearScreenBuffers(); // Clear current framebuffers
rlLoadIdentity(); // Reset current matrix (MODELVIEW)
@@ -656,6 +656,26 @@ void End3dMode(void)
rlDisableDepthTest(); // Disable DEPTH_TEST for 2D
}
+// Initializes render texture for drawing
+void BeginTextureMode(RenderTexture2D target)
+{
+ rlglDraw(); // Draw Buffers (Only OpenGL 3+ and ES2)
+
+ rlEnableRenderTexture(target.id);
+
+ rlClearScreenBuffers(); // Clear render texture buffers
+
+ rlLoadIdentity(); // Reset current matrix (MODELVIEW)
+}
+
+// Ends drawing to render texture
+void EndTextureMode(void)
+{
+ rlglDraw(); // Draw Buffers (Only OpenGL 3+ and ES2)
+
+ rlDisableRenderTexture();
+}
+
// Set target FPS for the game
void SetTargetFPS(int fps)
{
diff --git a/src/raylib.h b/src/raylib.h
index 2b65df9e..c8f2c2a2 100644
--- a/src/raylib.h
+++ b/src/raylib.h
@@ -324,6 +324,13 @@ typedef struct Texture2D {
int format; // Data format (TextureFormat)
} Texture2D;
+// RenderTexture2D type, for texture rendering
+typedef struct RenderTexture2D {
+ unsigned int id; // Render texture (fbo) id
+ Texture2D texture; // Color buffer attachment texture
+ Texture2D depth; // Depth buffer attachment texture
+} RenderTexture2D;
+
// SpriteFont type, includes texture and charSet array data
typedef struct SpriteFont {
Texture2D texture; // Font texture
@@ -565,6 +572,8 @@ void EndDrawing(void); // End canvas drawin
void Begin3dMode(Camera camera); // Initializes 3D mode for drawing (Camera setup)
void End3dMode(void); // Ends 3D mode and returns to default 2D orthographic mode
+void BeginTextureMode(RenderTexture2D target); // Initializes render texture for drawing
+void EndTextureMode(void); // Ends drawing to render texture
Ray GetMouseRay(Vector2 mousePosition, Camera camera); // Returns a ray trace from mouse position
Vector2 WorldToScreen(Vector3 position, Camera camera); // Returns the screen space position from a 3d world space position
@@ -714,8 +723,10 @@ Texture2D LoadTexture(const char *fileName);
Texture2D LoadTextureEx(void *data, int width, int height, int textureFormat); // Load a texture from raw data into GPU memory
Texture2D LoadTextureFromRES(const char *rresName, int resId); // Load an image as texture from rRES file (raylib Resource)
Texture2D LoadTextureFromImage(Image image); // Load a texture from image data
+RenderTexture2D LoadRenderTexture(int width, int height); // Load a texture to be used for rendering
void UnloadImage(Image image); // Unload image from CPU memory (RAM)
void UnloadTexture(Texture2D texture); // Unload texture from GPU memory
+void UnloadRenderTexture(RenderTexture2D target); // Unload render texture from GPU memory
Color *GetImageData(Image image); // Get pixel data from image as a Color struct array
Image GetTextureData(Texture2D texture); // Get pixel data from GPU texture and return an Image
void ImageToPOT(Image *image, Color fillColor); // Convert image to POT (power-of-two)
diff --git a/src/rlgl.c b/src/rlgl.c
index 39a34095..2153221e 100644
--- a/src/rlgl.c
+++ b/src/rlgl.c
@@ -785,6 +785,20 @@ void rlDisableTexture(void)
#endif
}
+void rlEnableRenderTexture(unsigned int id)
+{
+#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
+ glBindFramebuffer(GL_FRAMEBUFFER, id);
+#endif
+}
+
+void rlDisableRenderTexture(void)
+{
+#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+#endif
+}
+
// Enable depth test
void rlEnableDepthTest(void)
{
@@ -803,6 +817,16 @@ void rlDeleteTextures(unsigned int id)
glDeleteTextures(1, &id);
}
+// Unload render texture from GPU memory
+void rlDeleteRenderTextures(RenderTexture2D target)
+{
+#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
+ glDeleteFramebuffers(1, &target.id);
+ glDeleteTextures(1, &target.texture.id);
+ glDeleteTextures(1, &target.depth.id);
+#endif
+}
+
// Enable rendering to postprocessing FBO
void rlEnablePostproFBO()
{
@@ -1163,7 +1187,7 @@ FBO rlglLoadFBO(int width, int height)
glDeleteTextures(1, &fbo.colorTextureId);
glDeleteTextures(1, &fbo.depthTextureId);
}
- else TraceLog(INFO, "[FBO ID %i] Framebuffer object created successfully", fbo);
+ else TraceLog(INFO, "[FBO ID %i] Framebuffer object created successfully", fbo.id);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
#endif
@@ -1833,6 +1857,98 @@ unsigned int rlglLoadTexture(void *data, int width, int height, int textureForma
return id;
}
+// Load a texture to be used for rendering (fbo with color and depth attachments)
+RenderTexture2D rlglLoadRenderTexture(int width, int height)
+{
+ RenderTexture2D target;
+
+ target.id = 0;
+
+ target.texture.id = 0;
+ target.texture.width = width;
+ target.texture.height = height;
+ target.texture.format = UNCOMPRESSED_R8G8B8;
+ target.texture.mipmaps = 1;
+
+ target.depth.id = 0;
+ target.depth.width = width;
+ target.depth.height = height;
+ target.depth.format = 19; //DEPTH_COMPONENT_16BIT
+ target.depth.mipmaps = 1;
+
+#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
+ // Create the texture that will serve as the color attachment for the framebuffer
+ glGenTextures(1, &target.texture.id);
+ glBindTexture(GL_TEXTURE_2D, target.texture.id);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+#define USE_DEPTH_RENDERBUFFER
+#if defined(USE_DEPTH_RENDERBUFFER)
+ // Create the renderbuffer that will serve as the depth attachment for the framebuffer.
+ glGenRenderbuffers(1, &target.depth.id);
+ glBindRenderbuffer(GL_RENDERBUFFER, target.depth.id);
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height);
+
+#elif defined(USE_DEPTH_TEXTURE)
+ // NOTE: We can also use a texture for depth buffer (GL_ARB_depth_texture/GL_OES_depth_texture extension required)
+ // A renderbuffer is simpler than a texture and could offer better performance on embedded devices
+ glGenTextures(1, &target.depth.id);
+ glBindTexture(GL_TEXTURE_2D, target.depth.id);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, width, height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
+ glBindTexture(GL_TEXTURE_2D, 0);
+#endif
+
+ // Create the framebuffer object
+ glGenFramebuffers(1, &target.id);
+ glBindFramebuffer(GL_FRAMEBUFFER, target.id);
+
+ // Attach color texture and depth renderbuffer to FBO
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, target.texture.id, 0);
+#if defined(USE_DEPTH_RENDERBUFFER)
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, target.depth.id);
+#elif defined(USE_DEPTH_TEXTURE)
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, target.depth.id, 0);
+#endif
+
+ GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+
+ if (status != GL_FRAMEBUFFER_COMPLETE)
+ {
+ TraceLog(WARNING, "Framebuffer object could not be created...");
+
+ switch(status)
+ {
+ case GL_FRAMEBUFFER_UNSUPPORTED: TraceLog(WARNING, "Framebuffer is unsupported"); break;
+ case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: TraceLog(WARNING, "Framebuffer incomplete attachment"); break;
+#if defined(GRAPHICS_API_OPENGL_ES2)
+ case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: TraceLog(WARNING, "Framebuffer incomplete dimensions"); break;
+#endif
+ case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: TraceLog(WARNING, "Framebuffer incomplete missing attachment"); break;
+ default: break;
+ }
+
+ glDeleteTextures(1, &target.texture.id);
+ glDeleteTextures(1, &target.depth.id);
+ glDeleteFramebuffers(1, &target.id);
+ }
+ else TraceLog(INFO, "[FBO ID %i] Framebuffer object created successfully", target.id);
+
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+#endif
+
+ return target;
+}
+
+// Update already loaded texture in GPU with new data
void rlglUpdateTexture(unsigned int id, int width, int height, int format, void *data)
{
glBindTexture(GL_TEXTURE_2D, id);
diff --git a/src/rlgl.h b/src/rlgl.h
index 1a5260eb..679cb590 100644
--- a/src/rlgl.h
+++ b/src/rlgl.h
@@ -183,6 +183,13 @@ typedef enum { OPENGL_11 = 1, OPENGL_33, OPENGL_ES_20 } GlVersion;
int format; // Data format (TextureFormat)
} Texture2D;
+ // RenderTexture2D type, for texture rendering
+ typedef struct RenderTexture2D {
+ unsigned int id; // Render texture (fbo) id
+ Texture2D texture; // Color buffer attachment texture
+ Texture2D depth; // Depth buffer attachment texture
+ } RenderTexture2D;
+
// Material type
typedef struct Material {
Shader shader;
@@ -248,9 +255,12 @@ void rlColor4f(float x, float y, float z, float w); // Define one vertex (color)
//------------------------------------------------------------------------------------
void rlEnableTexture(unsigned int id); // Enable texture usage
void rlDisableTexture(void); // Disable texture usage
+void rlEnableRenderTexture(unsigned int id); // Enable render texture (fbo)
+void rlDisableRenderTexture(void); // Disable render texture (fbo), return to default framebuffer
void rlEnableDepthTest(void); // Enable depth test
void rlDisableDepthTest(void); // Disable depth test
void rlDeleteTextures(unsigned int id); // Delete OpenGL texture from GPU
+void rlDeleteRenderTextures(RenderTexture2D target); // Delete render textures (fbo) from GPU
void rlDeleteShader(unsigned int id); // Delete OpenGL shader program from GPU
void rlDeleteVertexArrays(unsigned int id); // Unload vertex data (VAO) from GPU memory
void rlDeleteBuffers(unsigned int id); // Unload vertex data (VBO) from GPU memory
@@ -268,6 +278,7 @@ void rlglDraw(void); // Draw VAO/VBO
void rlglInitGraphics(int offsetX, int offsetY, int width, int height); // Initialize Graphics (OpenGL stuff)
unsigned int rlglLoadTexture(void *data, int width, int height, int textureFormat, int mipmapCount); // Load texture in GPU
+RenderTexture2D rlglLoadRenderTexture(int width, int height); // Load a texture to be used for rendering (fbo with color and depth attachments)
void rlglUpdateTexture(unsigned int id, int width, int height, int format, void *data); // Update GPU texture with new data
void rlglGenerateMipmaps(Texture2D texture); // Generate mipmap data for selected texture
diff --git a/src/textures.c b/src/textures.c
index 9d0d13b6..67264afb 100644
--- a/src/textures.c
+++ b/src/textures.c
@@ -389,6 +389,14 @@ Texture2D LoadTextureFromImage(Image image)
return texture;
}
+// Load a texture to be used for rendering
+RenderTexture2D LoadRenderTexture(int width, int height)
+{
+ RenderTexture2D target = rlglLoadRenderTexture(width, height);
+
+ return target;
+}
+
// Unload image from CPU memory (RAM)
void UnloadImage(Image image)
{
@@ -409,6 +417,17 @@ void UnloadTexture(Texture2D texture)
}
}
+// Unload render texture from GPU memory
+void UnloadRenderTexture(RenderTexture2D target)
+{
+ if (target.id != 0)
+ {
+ rlDeleteRenderTextures(target);
+
+ TraceLog(INFO, "[FBO ID %i] Unloaded render texture data from VRAM (GPU)", target.id);
+ }
+}
+
// Get pixel data from image in the form of Color struct array
Color *GetImageData(Image image)
{