From 8b7ca8b670a0f338fef85125311522833b945bf7 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sun, 27 Mar 2016 18:32:36 +0200 Subject: Review comments --- src/textures.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'src/textures.c') diff --git a/src/textures.c b/src/textures.c index e649df57..9d0d13b6 100644 --- a/src/textures.c +++ b/src/textures.c @@ -29,21 +29,21 @@ #include "raylib.h" -#include // Declares malloc() and free() for memory management -#include // Required for strcmp(), strrchr(), strncmp() +#include // Declares malloc() and free() for memory management +#include // Required for strcmp(), strrchr(), strncmp() -#include "rlgl.h" // raylib OpenGL abstraction layer to OpenGL 1.1, 3.3 or ES2 - // Required: rlglLoadTexture() rlDeleteTextures(), - // rlglGenerateMipmaps(), some funcs for DrawTexturePro() +#include "rlgl.h" // raylib OpenGL abstraction layer to OpenGL 1.1, 3.3 or ES2 + // Required: rlglLoadTexture() rlDeleteTextures(), + // rlglGenerateMipmaps(), some funcs for DrawTexturePro() -#include "utils.h" // rRES data decompression utility function - // NOTE: Includes Android fopen function map +#include "utils.h" // rRES data decompression utility function + // NOTE: Includes Android fopen function map #define STB_IMAGE_IMPLEMENTATION -#include "stb_image.h" // Used to read image data (multiple formats support) +#include "stb_image.h" // Used to read image data (multiple formats support) #define STB_IMAGE_RESIZE_IMPLEMENTATION -#include "stb_image_resize.h" +#include "stb_image_resize.h" // Used on image scaling function: ImageResize() //---------------------------------------------------------------------------------- // Defines and Macros @@ -130,6 +130,7 @@ Image LoadImage(const char *fileName) } // Load image data from Color array data (RGBA - 32bit) +// NOTE: Creates a copy of pixels data array Image LoadImageEx(Color *pixels, int width, int height) { Image image; -- cgit v1.2.3 From 66b096d97848eb096a043781f1f305e7189f2a00 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Wed, 30 Mar 2016 20:09:16 +0200 Subject: 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. --- examples/resources/shaders/base.vs | 3 + examples/resources/shaders/bloom.fs | 3 +- examples/shaders_postprocessing.c | 36 ++++++++--- src/core.c | 22 ++++++- src/raylib.h | 11 ++++ src/rlgl.c | 118 +++++++++++++++++++++++++++++++++++- src/rlgl.h | 11 ++++ src/textures.c | 19 ++++++ 8 files changed, 210 insertions(+), 13 deletions(-) (limited to 'src/textures.c') diff --git a/examples/resources/shaders/base.vs b/examples/resources/shaders/base.vs index b0f930b7..9b8cca69 100644 --- a/examples/resources/shaders/base.vs +++ b/examples/resources/shaders/base.vs @@ -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); } \ No newline at end of file diff --git a/examples/resources/shaders/bloom.fs b/examples/resources/shaders/bloom.fs index 2833ce33..0a73161a 100644 --- a/examples/resources/shaders/bloom.fs +++ b/examples/resources/shaders/bloom.fs @@ -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 diff --git a/examples/shaders_postprocessing.c b/examples/shaders_postprocessing.c index 44829648..fabf5131 100644 --- a/examples/shaders_postprocessing.c +++ b/examples/shaders_postprocessing.c @@ -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,15 +69,26 @@ int main() ClearBackground(RAYWHITE); - Begin3dMode(camera); + BeginTextureMode(target); // Enable render to texture RenderTexture2D + + Begin3dMode(camera); - DrawModel(dwarf, position, 2.0f, WHITE); // Draw 3d model with texture + DrawModel(dwarf, position, 2.0f, WHITE); // Draw 3d model with texture - DrawGrid(10, 1.0f); // Draw a grid + DrawGrid(10, 1.0f); // Draw a grid - End3dMode(); + End3dMode(); + + 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, BLACK); + DrawText("(c) Dwarf 3D model by David Moreno", screenWidth - 200, screenHeight - 20, 10, DARKGRAY); DrawFPS(10, 10); @@ -83,11 +98,12 @@ int main() // De-Initialization //-------------------------------------------------------------------------------------- - UnloadShader(shader); // Unload shader - UnloadTexture(texture); // Unload texture - UnloadModel(dwarf); // Unload model + UnloadShader(shader); // Unload shader + UnloadTexture(texture); // Unload texture + UnloadModel(dwarf); // Unload model + UnloadRenderTexture(target); // Unload render texture - CloseWindow(); // Close window and OpenGL context + CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- return 0; 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) { -- cgit v1.2.3 From aa22d979834eeddb849f45bba7c0f467b575e6db Mon Sep 17 00:00:00 2001 From: raysan5 Date: Thu, 7 Apr 2016 13:31:53 +0200 Subject: Simplified texture flip and added comments --- examples/shaders_custom_uniform.c | 2 +- examples/shaders_postprocessing.c | 2 +- src/rlgl.c | 10 +++++++--- src/textures.c | 4 ++++ 4 files changed, 13 insertions(+), 5 deletions(-) (limited to 'src/textures.c') diff --git a/examples/shaders_custom_uniform.c b/examples/shaders_custom_uniform.c index ceaa86df..32dd7ff1 100644 --- a/examples/shaders_custom_uniform.c +++ b/examples/shaders_custom_uniform.c @@ -94,7 +94,7 @@ int main() 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); + DrawTextureRec(target.texture, (Rectangle){ 0, 0, target.texture.width, -target.texture.height }, (Vector2){ 0, 0 }, WHITE); SetDefaultShader(); DrawText("(c) Dwarf 3D model by David Moreno", screenWidth - 200, screenHeight - 20, 10, GRAY); diff --git a/examples/shaders_postprocessing.c b/examples/shaders_postprocessing.c index 632a6371..e9fafe15 100644 --- a/examples/shaders_postprocessing.c +++ b/examples/shaders_postprocessing.c @@ -82,7 +82,7 @@ int main() 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); + DrawTextureRec(target.texture, (Rectangle){ 0, 0, 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); diff --git a/src/rlgl.c b/src/rlgl.c index b2a36351..f0acf124 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -1897,6 +1897,9 @@ Model rlglLoadModel(Mesh mesh) // Create buffers for our vertex data (positions, texcoords, normals) glGenBuffers(3, vertexBuffer); + + // NOTE: Default shader is assigned to model, so vbo buffers are properly linked to vertex attribs + // If model shader is changed, vbo buffers must be re-assigned to new location points (previously loaded) // Enable vertex attributes: position glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer[0]); @@ -2489,13 +2492,14 @@ static Shader LoadDefaultShader(void) } // Get location handlers to for shader attributes and uniforms +// NOTE: If any location is not found, loc point becomes -1 static void LoadDefaultShaderLocations(Shader *shader) { // Get handles to GLSL input attibute locations shader->vertexLoc = glGetAttribLocation(shader->id, "vertexPosition"); shader->texcoordLoc = glGetAttribLocation(shader->id, "vertexTexCoord"); shader->normalLoc = glGetAttribLocation(shader->id, "vertexNormal"); - shader->colorLoc = glGetAttribLocation(shader->id, "vertexColor"); // -1 if not found + shader->colorLoc = glGetAttribLocation(shader->id, "vertexColor"); // Get handles to GLSL uniform locations (vertex shader) shader->mvpLoc = glGetUniformLocation(shader->id, "mvpMatrix"); @@ -2503,8 +2507,8 @@ static void LoadDefaultShaderLocations(Shader *shader) // Get handles to GLSL uniform locations (fragment shader) shader->tintColorLoc = glGetUniformLocation(shader->id, "fragTintColor"); shader->mapDiffuseLoc = glGetUniformLocation(shader->id, "texture0"); - shader->mapNormalLoc = glGetUniformLocation(shader->id, "texture1"); // -1 if not found - shader->mapSpecularLoc = glGetUniformLocation(shader->id, "texture2"); // -1 if not found + shader->mapNormalLoc = glGetUniformLocation(shader->id, "texture1"); + shader->mapSpecularLoc = glGetUniformLocation(shader->id, "texture2"); } // Read text file diff --git a/src/textures.c b/src/textures.c index 67264afb..79047ab7 100644 --- a/src/textures.c +++ b/src/textures.c @@ -1385,6 +1385,10 @@ void DrawTextureEx(Texture2D texture, Vector2 position, float rotation, float sc void DrawTextureRec(Texture2D texture, Rectangle sourceRec, Vector2 position, Color tint) { Rectangle destRec = { (int)position.x, (int)position.y, abs(sourceRec.width), abs(sourceRec.height) }; + + if (sourceRec.width < 0) sourceRec.x -= sourceRec.width; + if (sourceRec.height < 0) sourceRec.y -= sourceRec.height; + Vector2 origin = { 0, 0 }; DrawTexturePro(texture, sourceRec, destRec, origin, 0.0f, tint); -- cgit v1.2.3