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.
This commit is contained in:
parent
1136d4222f
commit
66b096d978
@ -3,8 +3,10 @@
|
||||
in vec3 vertexPosition;
|
||||
in vec2 vertexTexCoord;
|
||||
in vec3 vertexNormal;
|
||||
in vec4 vertexColor;
|
||||
|
||||
out vec2 fragTexCoord;
|
||||
out vec4 fragTintColor;
|
||||
|
||||
uniform mat4 mvpMatrix;
|
||||
|
||||
@ -13,6 +15,7 @@ uniform mat4 mvpMatrix;
|
||||
void main()
|
||||
{
|
||||
fragTexCoord = vertexTexCoord;
|
||||
fragTintColor = vertexColor;
|
||||
|
||||
gl_Position = mvpMatrix*vec4(vertexPosition, 1.0);
|
||||
}
|
@ -1,11 +1,12 @@
|
||||
#version 330
|
||||
|
||||
in vec2 fragTexCoord;
|
||||
in vec4 fragTintColor;
|
||||
|
||||
out vec4 fragColor;
|
||||
|
||||
uniform sampler2D texture0;
|
||||
uniform vec4 fragTintColor;
|
||||
//uniform vec4 fragTintColor;
|
||||
|
||||
// NOTE: Add here your custom variables
|
||||
|
||||
|
@ -41,7 +41,11 @@ int main()
|
||||
Shader shader = LoadShader("resources/shaders/base.vs",
|
||||
"resources/shaders/bloom.fs"); // Load postpro shader
|
||||
|
||||
SetPostproShader(shader); // Set fullscreen postprocessing shader
|
||||
// NOTE: Old postprocessing system is not flexible enough despite being very easy to use
|
||||
//SetPostproShader(shader); // Set fullscreen postprocessing shader
|
||||
|
||||
// New postprocessing system let the user create multiple RenderTexture2D and perform multiple render passes
|
||||
RenderTexture2D target = LoadRenderTexture(screenWidth, screenHeight);
|
||||
|
||||
// Setup orbital camera
|
||||
SetCameraMode(CAMERA_ORBITAL); // Set an orbital camera mode
|
||||
@ -65,6 +69,8 @@ int main()
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
BeginTextureMode(target); // Enable render to texture RenderTexture2D
|
||||
|
||||
Begin3dMode(camera);
|
||||
|
||||
DrawModel(dwarf, position, 2.0f, WHITE); // Draw 3d model with texture
|
||||
@ -73,7 +79,16 @@ int main()
|
||||
|
||||
End3dMode();
|
||||
|
||||
DrawText("(c) Dwarf 3D model by David Moreno", screenWidth - 200, screenHeight - 20, 10, BLACK);
|
||||
DrawText("HELLO TEXTURE!!!", 120, 200, 60, RED);
|
||||
|
||||
EndTextureMode(); // End drawing to texture (now we have a texture available for next passes)
|
||||
|
||||
SetCustomShader(shader);
|
||||
// NOTE: Render texture must be y-flipped due to default OpenGL coordinates (left-bottom)
|
||||
DrawTextureRec(target.texture, (Rectangle){ 0, target.texture.height, target.texture.width, -target.texture.height }, (Vector2){ 0, 0 }, WHITE);
|
||||
SetDefaultShader();
|
||||
|
||||
DrawText("(c) Dwarf 3D model by David Moreno", screenWidth - 200, screenHeight - 20, 10, DARKGRAY);
|
||||
|
||||
DrawFPS(10, 10);
|
||||
|
||||
@ -86,6 +101,7 @@ int main()
|
||||
UnloadShader(shader); // Unload shader
|
||||
UnloadTexture(texture); // Unload texture
|
||||
UnloadModel(dwarf); // Unload model
|
||||
UnloadRenderTexture(target); // Unload render texture
|
||||
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
22
src/core.c
22
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)
|
||||
{
|
||||
|
11
src/raylib.h
11
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)
|
||||
|
118
src/rlgl.c
118
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);
|
||||
|
11
src/rlgl.h
11
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
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user