2
0
Эх сурвалжийг харах

Move shaders functions to module rlgl

Shader functionality owns to rlgl, not core module
raysan5 10 жил өмнө
parent
commit
552033da27
4 өөрчлөгдсөн 309 нэмэгдсэн , 251 устгасан
  1. 4 40
      src/core.c
  2. 35 45
      src/raylib.h
  3. 267 160
      src/rlgl.c
  4. 3 6
      src/rlgl.h

+ 4 - 40
src/core.c

@@ -192,9 +192,6 @@ static double targetTime = 0.0;             // Desired time for one frame, if 0
 static char configFlags = 0;
 static bool showLogo = false;
 
-// Shaders variables
-static bool enabledPostpro = false;
-
 //----------------------------------------------------------------------------------
 // Other Modules Functions Declaration (required by core)
 //----------------------------------------------------------------------------------
@@ -468,7 +465,7 @@ int GetScreenHeight(void)
 // Sets Background Color
 void ClearBackground(Color color)
 {
-    // TODO: Review "clearing area", full framebuffer vs render area
+    // Clear full framebuffer (not only render area) to color
     rlClearColor(color.r, color.g, color.b, color.a);
 }
 
@@ -479,7 +476,7 @@ void BeginDrawing(void)
     updateTime = currentTime - previousTime;
     previousTime = currentTime;
 
-    if (enabledPostpro) rlEnableFBO();
+    if (IsPosproShaderEnabled()) rlEnableFBO();
 
     rlClearScreenBuffers();
 
@@ -496,7 +493,7 @@ void EndDrawing(void)
 {
     rlglDraw();                     // Draw Buffers (Only OpenGL 3+ and ES2)
 
-    if (enabledPostpro) rlglDrawPostpro(); // Draw postprocessing effect (shader)
+    if (IsPosproShaderEnabled()) rlglDrawPostpro(); // Draw postprocessing effect (shader)
 
     SwapBuffers();                  // Copy back buffer to front buffer
 
@@ -970,39 +967,6 @@ Vector2 GetTouchPosition(void)
 }
 #endif
 
-// Set postprocessing shader
-void SetPostproShader(Shader shader)
-{
-    if (rlGetVersion() == OPENGL_11) TraceLog(WARNING, "Postprocessing shaders not supported on OpenGL 1.1");
-    else
-    {
-        if (!enabledPostpro)
-        {
-            enabledPostpro = true;
-            rlglInitPostpro();
-            rlglSetPostproShader(shader);
-        }
-        else
-        {
-            rlglSetPostproShader(shader);
-        }
-    }
-}
-
-// Set custom shader to be used in batch draw
-void SetCustomShader(Shader shader)
-{
-    rlglSetCustomShader(shader);
-}
-
-// Set default shader to be used in batch draw
-void SetDefaultShader(void)
-{
-    rlglSetDefaultShader();
-    
-    enabledPostpro = false;
-}
-
 //----------------------------------------------------------------------------------
 // Module specific Functions Definition
 //----------------------------------------------------------------------------------
@@ -1579,7 +1543,7 @@ static void PollInputEvents(void)
     // Poll Events (registered events)
     // TODO: Enable/disable activityMinimized to block activity if minimized
     //while ((ident = ALooper_pollAll(activityMinimized ? 0 : -1, NULL, &events,(void**)&source)) >= 0)
-    while ((ident = ALooper_pollAll(0, NULL, &events,(void**)&source)) >= 0)
+    while ((ident = ALooper_pollAll(0, NULL, &events, (void**)&source)) >= 0)
     {
         // Process this event
         if (source != NULL) source->process(app, source);

+ 35 - 45
src/raylib.h

@@ -265,9 +265,6 @@ typedef struct Camera {
     Vector3 up;
 } Camera;
 
-// Camera modes
-typedef enum { CAMERA_CUSTOM = 0, CAMERA_FREE, CAMERA_ORBITAL, CAMERA_FIRST_PERSON, CAMERA_THIRD_PERSON } CameraMode;
-
 // Vertex data definning a mesh
 // NOTE: If using OpenGL 1.1, data loaded in CPU; if OpenGL 3.3+ data loaded in GPU (vaoId)
 typedef struct VertexData {
@@ -284,21 +281,21 @@ typedef struct VertexData {
 typedef struct Shader {
     unsigned int id;                // Shader program id
 
+    // TODO: This should be Texture2D objects
     unsigned int texDiffuseId;      // Diffuse texture id
     unsigned int texNormalId;       // Normal texture id
     unsigned int texSpecularId;     // Specular texture id
     
     // Variable attributes
-    int vertexLoc;     // Vertex attribute location point (vertex shader)
-    int texcoordLoc;   // Texcoord attribute location point (vertex shader)
-    int normalLoc;     // Normal attribute location point (vertex shader)
-    int colorLoc;      // Color attibute location point (vertex shader)
+    int vertexLoc;        // Vertex attribute location point (vertex shader)
+    int texcoordLoc;      // Texcoord attribute location point (vertex shader)
+    int normalLoc;        // Normal attribute location point (vertex shader)
+    int colorLoc;         // Color attibute location point (vertex shader)
 
     // Uniforms
-    int projectionLoc; // Projection matrix uniform location point (vertex shader)
-    int modelviewLoc;  // ModeView matrix uniform location point (vertex shader)
-    
-    int tintColorLoc;  // Color uniform location point (fragment shader)
+    int projectionLoc;    // Projection matrix uniform location point (vertex shader)
+    int modelviewLoc;     // ModeView matrix uniform location point (vertex shader)
+    int tintColorLoc;     // Color uniform location point (fragment shader)
     
     int mapDiffuseLoc;    // Diffuse map texture uniform location point (fragment shader)
     int mapNormalLoc;     // Normal map texture uniform location point (fragment shader)
@@ -421,32 +418,28 @@ Color Fade(Color color, float alpha);                       // Color fade-in or
 void SetConfigFlags(char flags);                            // Enable some window configurations
 void ShowLogo(void);                                        // Activates raylib logo at startup (can be done with flags)
 
-void SetPostproShader(Shader shader);                       // Set fullscreen postproduction shader
-void SetCustomShader(Shader shader);                        // Set custom shader to be used in batch draw
-void SetDefaultShader(void);                                // Set default shader to be used in batch draw
-
-Ray GetMouseRay(Vector2 mousePosition, Camera camera);      // Gives the rayTrace from mouse position
-
-// Camera modes setup and control functions (module: camera)
-void SetCameraMode(int mode);                               // Select camera mode (multiple camera modes available)
-Camera UpdateCamera(Vector3 *position);                     // Update camera with position
-
-void SetCameraControls(int front, int left, int back, int right, int up, int down);
-void SetCameraMouseSensitivity(float sensitivity);
-void SetCameraResetPosition(Vector3 resetPosition);
-void SetCameraResetControl(int resetKey);
-void SetCameraPawnControl(int pawnControlKey);
-void SetCameraFnControl(int fnControlKey);
-void SetCameraSmoothZoomControl(int smoothZoomControlKey);
-void SetCameraOrbitalTarget(Vector3 target);
-
-// Shaders control functions
-int GetShaderLocation(Shader shader, const char *uniformName);
-void SetShaderValue(Shader shader, int uniformLoc, float *value, int size);
+Ray GetMouseRay(Vector2 mousePosition, Camera camera);      // TODO: Gives the ray trace from mouse position
 
-void SetShaderMapDiffuse(Shader *shader, Texture2D texture);
-void SetShaderMapNormal(Shader *shader, const char *uniformName, Texture2D texture);
-void SetShaderMapSpecular(Shader *shader, const char *uniformName, Texture2D texture);
+//------------------------------------------------------------------------------------
+// Shaders System Functions (Module: rlgl)
+// NOTE: This functions are useless when using OpenGL 1.1
+//------------------------------------------------------------------------------------
+Shader LoadShader(char *vsFileName, char *fsFileName);              // Load a custom shader and bind default locations
+unsigned int LoadShaderProgram(char *vShaderStr, char *fShaderStr); // Load a custom shader and return program id
+void UnloadShader(Shader shader);                                   // Unload a custom shader from memory
+void SetPostproShader(Shader shader);                               // Set fullscreen postproduction shader
+void SetCustomShader(Shader shader);                                // Set custom shader to be used in batch draw
+void SetDefaultShader(void);                                        // Set default shader to be used in batch draw
+void SetModelShader(Model *model, Shader shader);                   // Link a shader to a model
+bool IsPosproShaderEnabled(void);                                   // Check if postprocessing shader is enabled
+
+int GetShaderLocation(Shader shader, const char *uniformName);                          // Get shader uniform location
+void SetShaderValue(Shader shader, int uniformLoc, float *value, int size);             // Set shader uniform value (float)
+void SetShaderValuei(Shader shader, int uniformLoc, int *value, int size);              // Set shader uniform value (int)
+void SetShaderMapDiffuse(Shader *shader, Texture2D texture);                            // Default diffuse shader map texture assignment
+void SetShaderMapNormal(Shader *shader, const char *uniformName, Texture2D texture);    // Normal map texture shader assignment
+void SetShaderMapSpecular(Shader *shader, const char *uniformName, Texture2D texture);  // Specular map texture shader assignment
+void SetShaderMap(Shader *shader, int mapLocation, Texture2D texture, int textureUnit); // TODO: Generic shader map assignment
 
 //------------------------------------------------------------------------------------
 // Input Handling Functions (Module: core)
@@ -535,6 +528,7 @@ bool CheckCollisionPointTriangle(Vector2 point, Vector2 p1, Vector2 p2, Vector2
 //------------------------------------------------------------------------------------
 Image LoadImage(const char *fileName);                                                             // Load an image into CPU memory (RAM)
 Image LoadImageEx(Color *pixels, int width, int height);                                           // Load image data from Color array data (RGBA - 32bit)
+Image LoadImageRaw(const char *fileName, int width, int height, int format, int headerSize);       // Load image data from RAW file
 Image LoadImageFromRES(const char *rresName, int resId);                                           // Load an image from rRES file (raylib Resource)
 Texture2D LoadTexture(const char *fileName);                                                       // Load an image as texture into GPU memory
 Texture2D LoadTextureEx(void *data, int width, int height, int textureFormat, int mipmapCount);    // Load a texture from raw data into GPU memory
@@ -542,10 +536,10 @@ Texture2D LoadTextureFromRES(const char *rresName, int resId);
 Texture2D LoadTextureFromImage(Image image);                                                       // Load a texture from image data (and generate mipmaps)
 void UnloadImage(Image image);                                                                     // Unload image from CPU memory (RAM)
 void UnloadTexture(Texture2D texture);                                                             // Unload 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 ImageConvertToPOT(Image *image, Color fillColor);                                             // Convert image to POT (power-of-two)
 void ImageConvertFormat(Image *image, int newFormat);                                              // Convert image data to desired format
-Color *GetPixelData(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 GenTextureMipmaps(Texture2D texture);                                                         // Generate GPU mipmaps for a texture
 
 void DrawTexture(Texture2D texture, int posX, int posY, Color tint);                               // Draw a Texture2D
@@ -600,7 +594,6 @@ Model LoadHeightmap(Image heightmap, float maxHeight);
 Model LoadCubicmap(Image cubicmap);                                                                // Load a map image as a 3d model (cubes based)
 void UnloadModel(Model model);                                                                     // Unload 3d model from memory
 void SetModelTexture(Model *model, Texture2D texture);                                             // Link a texture to a model
-void SetModelShader(Model *model, Shader shader);                                                  // Link a shader to a model (not available on OpenGL 1.1)
 
 void DrawModel(Model model, Vector3 position, float scale, Color tint);                            // Draw a model (with texture if set)
 void DrawModelEx(Model model, Vector3 position, float rotationAngle, Vector3 rotationAxis, Vector3 scale, Color tint);      // Draw a model with extended parameters
@@ -609,12 +602,9 @@ void DrawModelWires(Model model, Vector3 position, float scale, Color color);
 void DrawBillboard(Camera camera, Texture2D texture, Vector3 center, float size, Color tint);                         // Draw a billboard texture
 void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle sourceRec, Vector3 center, float size, Color tint); // Draw a billboard texture defined by sourceRec
 
-Shader LoadShader(char *vsFileName, char *fsFileName);                                             // Load a custom shader (vertex shader + fragment shader)
-void UnloadShader(Shader shader);                                                                  // Unload a custom shader from memory
-
-bool CheckCollisionSpheres(Vector3 centerA, float radiusA, Vector3 centerB, float radiusB);
-bool CheckCollisionBoxes(Vector3 minBBox1, Vector3 maxBBox1, Vector3 minBBox2, Vector3 maxBBox2);
-bool CheckCollisionBoxSphere(Vector3 minBBox, Vector3 maxBBox, Vector3 centerSphere, float radiusSphere);
+bool CheckCollisionSpheres(Vector3 centerA, float radiusA, Vector3 centerB, float radiusB);                     // Detect collision between two spheres
+bool CheckCollisionBoxes(Vector3 minBBox1, Vector3 maxBBox1, Vector3 minBBox2, Vector3 maxBBox2);               // Detect collision between two boxes
+bool CheckCollisionBoxSphere(Vector3 minBBox, Vector3 maxBBox, Vector3 centerSphere, float radiusSphere);       // Detect collision between box and sphere
 Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *playerPosition, float radius);   // Return the normal vector of the impacted surface
 
 //------------------------------------------------------------------------------------

+ 267 - 160
src/rlgl.c

@@ -230,6 +230,9 @@ static bool texCompASTCSupported = false;    // ASTC texture compression support
 // Framebuffer object and texture
 static GLuint fbo, fboColorTexture, fboDepthTexture;
 static Model postproQuad;
+
+// Shaders related variables
+static bool enabledPostpro = false;
 #endif
 
 // Compressed textures support flags
@@ -957,7 +960,7 @@ void rlglInit(void)
     // Init default Shader (GLSL 110) -> Common for GL 3.3+ and ES2
     defaultShader = LoadDefaultShader();
     simpleShader = LoadSimpleShader();
-    //customShader = rlglLoadShader("custom.vs", "custom.fs");     // Works ok
+    //customShader = LoadShader("custom.vs", "custom.fs");     // Works ok
     
     currentShader = defaultShader;
 
@@ -1054,25 +1057,6 @@ void rlglInitPostpro(void)
 #endif
 }
 
-// Set postprocessing shader
-void rlglSetPostproShader(Shader shader)
-{
-#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
-    rlglSetModelShader(&postproQuad, shader);
-    
-    Texture2D texture;
-    texture.id = fboColorTexture;
-    texture.width = GetScreenWidth();
-    texture.height = GetScreenHeight();
-
-    SetShaderMapDiffuse(&postproQuad.shader, texture);
-    
-    //TraceLog(INFO, "Postproquad texture id: %i", postproQuad.texture.id);
-    //TraceLog(INFO, "Postproquad shader diffuse map id: %i", postproQuad.shader.texDiffuseId);
-    //TraceLog(INFO, "Shader diffuse map id: %i", shader.texDiffuseId);
-#endif
-}
-
 // Vertex Buffer Object deinitialization (memory free)
 void rlglClose(void)
 {
@@ -1377,7 +1361,18 @@ void rlglDrawModel(Model model, Vector3 position, float rotationAngle, Vector3 r
     // Set shader textures (diffuse, normal, specular)
     glActiveTexture(GL_TEXTURE0);
     glBindTexture(GL_TEXTURE_2D, model.shader.texDiffuseId);
-    //glUniform1i(model.shader.mapDiffuseLoc, 0);   // Diffuse texture fits in texture unit 0
+
+    if (model.shader.texNormalId != 0)
+    {
+        glActiveTexture(GL_TEXTURE1);
+        glBindTexture(GL_TEXTURE_2D, model.shader.texNormalId);
+    }
+    
+    if (model.shader.texSpecularId != 0)
+    {
+        glActiveTexture(GL_TEXTURE2);
+        glBindTexture(GL_TEXTURE_2D, model.shader.texSpecularId);
+    }
 
     if (vaoSupported)
     {
@@ -1402,9 +1397,21 @@ void rlglDrawModel(Model model, Vector3 position, float rotationAngle, Vector3 r
 
     // Draw call!
     glDrawArrays(GL_TRIANGLES, 0, model.mesh.vertexCount);
+    
+    if (model.shader.texNormalId != 0)
+    {
+        glActiveTexture(GL_TEXTURE1);
+        glBindTexture(GL_TEXTURE_2D, 0);
+    }
+    
+    if (model.shader.texSpecularId != 0)
+    {
+        glActiveTexture(GL_TEXTURE2);
+        glBindTexture(GL_TEXTURE_2D, 0);
+    }
 
-    glBindTexture(GL_TEXTURE_2D, 0);            // Unbind textures
     glActiveTexture(GL_TEXTURE0);               // Set shader active texture to default 0
+    glBindTexture(GL_TEXTURE_2D, 0);            // Unbind textures
 
     if (vaoSupported) glBindVertexArray(0);     // Unbind VAO
     else glBindBuffer(GL_ARRAY_BUFFER, 0);      // Unbind VBOs
@@ -1933,12 +1940,130 @@ Model rlglLoadModel(VertexData mesh)
     return model;
 }
 
+// Read screen pixel data (color buffer)
+unsigned char *rlglReadScreenPixels(int width, int height)
+{
+    unsigned char *screenData = (unsigned char *)malloc(width * height * sizeof(unsigned char) * 4);
+
+    // NOTE: glReadPixels returns image flipped vertically -> (0,0) is the bottom left corner of the framebuffer
+    glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, screenData);
+
+    // Flip image vertically!
+    unsigned char *imgData = (unsigned char *)malloc(width * height * sizeof(unsigned char) * 4);
+
+    for (int y = height-1; y >= 0; y--)
+    {
+        for (int x = 0; x < (width*4); x++)
+        {
+            imgData[x + (height - y - 1)*width*4] = screenData[x + (y*width*4)];
+        }
+    }
+
+    free(screenData);
+
+    return imgData;     // NOTE: image data should be freed
+}
+
+// Read texture pixel data
+void *rlglReadTexturePixels(unsigned int textureId, unsigned int format)
+{
+    int width, height;
+    
+    glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width);
+    glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height);
+    //glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &format);
+    //GL_TEXTURE_RED_SIZE, GL_TEXTURE_GREEN_SIZE, GL_TEXTURE_BLUE_SIZE, GL_TEXTURE_ALPHA_SIZE
+    
+    int glFormat = 0, glType = 0;
+    void *pixels = NULL;
+    unsigned int size = width*height;
+
+    switch (format)
+    {
+        case UNCOMPRESSED_GRAYSCALE: pixels = (unsigned char *)malloc(size); glFormat = GL_LUMINANCE; glType = GL_UNSIGNED_BYTE; break;            // 8 bit per pixel (no alpha)
+        case UNCOMPRESSED_GRAY_ALPHA: pixels = (unsigned char *)malloc(size*2); glFormat = GL_LUMINANCE_ALPHA; glType = GL_UNSIGNED_BYTE; break;   // 16 bpp (2 channels)
+        case UNCOMPRESSED_R5G6B5: pixels = (unsigned short *)malloc(size); glFormat = GL_RGB; glType = GL_UNSIGNED_SHORT_5_6_5; break;             // 16 bpp
+        case UNCOMPRESSED_R8G8B8: pixels = (unsigned char *)malloc(size*3); glFormat = GL_RGB; glType = GL_UNSIGNED_BYTE; break;                   // 24 bpp
+        case UNCOMPRESSED_R5G5B5A1: pixels = (unsigned short *)malloc(size); glFormat = GL_RGBA; glType = GL_UNSIGNED_SHORT_5_5_5_1; break;        // 16 bpp (1 bit alpha)
+        case UNCOMPRESSED_R4G4B4A4: pixels = (unsigned short *)malloc(size); glFormat = GL_RGBA; glType = GL_UNSIGNED_SHORT_4_4_4_4; break;        // 16 bpp (4 bit alpha)
+        case UNCOMPRESSED_R8G8B8A8: pixels = (unsigned char *)malloc(size*4); glFormat = GL_RGBA; glType = GL_UNSIGNED_BYTE; break;                // 32 bpp
+        default: TraceLog(WARNING, "Texture format not suported"); break;
+    }
+
+    glBindTexture(GL_TEXTURE_2D, textureId);
+    
+    // NOTE: Each row written to or read from by OpenGL pixel operations like glGetTexImage are aligned to a 4 byte boundary by default, which may add some padding.
+    // Use glPixelStorei to modify padding with the GL_[UN]PACK_ALIGNMENT setting. 
+    // GL_PACK_ALIGNMENT affects operations that read from OpenGL memory (glReadPixels, glGetTexImage, etc.) 
+    // GL_UNPACK_ALIGNMENT affects operations that write to OpenGL memory (glTexImage, etc.)
+    glPixelStorei(GL_PACK_ALIGNMENT, 1);
+    
+    glGetTexImage(GL_TEXTURE_2D, 0, glFormat, glType, pixels);
+    
+    glBindTexture(GL_TEXTURE_2D, 0);
+    
+    return pixels;
+}
+
+
+//----------------------------------------------------------------------------------
+// Module Functions Definition - Shaders Functions
+// NOTE: Those functions are exposed directly to the user in raylib.h
+//----------------------------------------------------------------------------------
+
+// Load a custom shader and bind default locations
+Shader LoadShader(char *vsFileName, char *fsFileName)
+{
+    Shader shader;
 
 #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
-// Load a shader (vertex shader + fragment shader) from text data
-unsigned int rlglLoadShaderFromText(char *vShaderStr, char *fShaderStr)
+    // Shaders loading from external text file
+    char *vShaderStr = TextFileRead(vsFileName);
+    char *fShaderStr = TextFileRead(fsFileName);
+
+    shader.id = LoadShaderProgram(vShaderStr, fShaderStr);
+
+    if (shader.id != 0) TraceLog(INFO, "[SHDR ID %i] Custom shader loaded successfully", shader.id);
+    else TraceLog(WARNING, "[SHDR ID %i] Custom shader could not be loaded", shader.id);
+
+    // Shader strings must be freed
+    free(vShaderStr);
+    free(fShaderStr);
+    
+    // Set shader textures ids (all 0 by default)
+    shader.texDiffuseId = 0;
+    shader.texNormalId = 0;
+    shader.texSpecularId = 0;
+
+    // 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");
+    // NOTE: custom shader does not use colorLoc
+    shader.colorLoc = -1;
+
+    // Get handles to GLSL uniform locations (vertex shader)
+    shader.modelviewLoc  = glGetUniformLocation(shader.id, "modelviewMatrix");
+    shader.projectionLoc = glGetUniformLocation(shader.id, "projectionMatrix");
+
+    // Get handles to GLSL uniform locations (fragment shader)
+    shader.tintColorLoc = glGetUniformLocation(shader.id, "tintColor");
+    shader.mapDiffuseLoc = glGetUniformLocation(shader.id, "texture0");
+    shader.mapNormalLoc = -1;       // It can be set later
+    shader.mapSpecularLoc = -1;     // It can be set later
+    //--------------------------------------------------------------------
+#endif
+
+    return shader;
+}
+
+// Load a custom shader and return program id
+unsigned int LoadShaderProgram(char *vShaderStr, char *fShaderStr)
 {
-    unsigned int program;
+    unsigned int program = 0;
+	
+#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
     GLuint vertexShader;
     GLuint fragmentShader;
 
@@ -2029,125 +2154,89 @@ unsigned int rlglLoadShaderFromText(char *vShaderStr, char *fShaderStr)
 
     glDeleteShader(vertexShader);
     glDeleteShader(fragmentShader);
-
+#endif
     return program;
 }
-#endif
 
-// Read screen pixel data (color buffer)
-unsigned char *rlglReadScreenPixels(int width, int height)
+// Unload a custom shader from memory
+void UnloadShader(Shader shader)
 {
-    unsigned char *screenData = (unsigned char *)malloc(width * height * sizeof(unsigned char) * 4);
+    rlDeleteShader(shader.id);
+}
 
-    // NOTE: glReadPixels returns image flipped vertically -> (0,0) is the bottom left corner of the framebuffer
-    glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, screenData);
+// Set custom shader to be used on batch draw
+void SetCustomShader(Shader shader)
+{
+#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
+    if (currentShader.id != shader.id)
+    {
+        rlglDraw();
 
-    // Flip image vertically!
-    unsigned char *imgData = (unsigned char *)malloc(width * height * sizeof(unsigned char) * 4);
+        currentShader = shader;
+/*
+        if (vaoSupported) glBindVertexArray(vaoQuads);
+        
+        // Enable vertex attributes: position
+        glBindBuffer(GL_ARRAY_BUFFER, quadsBuffer[0]);
+        glEnableVertexAttribArray(currentShader.vertexLoc);
+        glVertexAttribPointer(currentShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0);
 
-    for (int y = height-1; y >= 0; y--)
-    {
-        for (int x = 0; x < (width*4); x++)
-        {
-            imgData[x + (height - y - 1)*width*4] = screenData[x + (y*width*4)];
-        }
-    }
+        // Enable vertex attributes: texcoords
+        glBindBuffer(GL_ARRAY_BUFFER, quadsBuffer[1]);
+        glEnableVertexAttribArray(currentShader.texcoordLoc);
+        glVertexAttribPointer(currentShader.texcoordLoc, 2, GL_FLOAT, 0, 0, 0);
 
-    free(screenData);
+        // Enable vertex attributes: colors
+        glBindBuffer(GL_ARRAY_BUFFER, quadsBuffer[2]);
+        glEnableVertexAttribArray(currentShader.colorLoc);
+        glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
 
-    return imgData;     // NOTE: image data should be freed
+        if (vaoSupported) glBindVertexArray(0);     // Unbind VAO
+*/
+    }
+#endif
 }
 
-// Read texture pixel data
-void *rlglReadTexturePixels(unsigned int textureId, unsigned int format)
+// Set postprocessing shader
+void SetPostproShader(Shader shader)
 {
-    int width, height;
-    
-    glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width);
-    glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height);
-    //glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &format);
-    //GL_TEXTURE_RED_SIZE, GL_TEXTURE_GREEN_SIZE, GL_TEXTURE_BLUE_SIZE, GL_TEXTURE_ALPHA_SIZE
-    
-    int glFormat, glType;
-    void *pixels = NULL;
-    unsigned int size = width*height;
-
-    switch (format)
+#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
+    if (!enabledPostpro)
     {
-        case UNCOMPRESSED_GRAYSCALE: pixels = (unsigned char *)malloc(size); glFormat = GL_LUMINANCE; glType = GL_UNSIGNED_BYTE;            // 8 bit per pixel (no alpha)
-        case UNCOMPRESSED_GRAY_ALPHA: pixels = (unsigned char *)malloc(size*2); glFormat = GL_LUMINANCE_ALPHA; glType = GL_UNSIGNED_BYTE;   // 16 bpp (2 channels)
-        case UNCOMPRESSED_R5G6B5: pixels = (unsigned short *)malloc(size); glFormat = GL_RGB; glType = GL_UNSIGNED_SHORT_5_6_5;             // 16 bpp
-        case UNCOMPRESSED_R8G8B8: pixels = (unsigned char *)malloc(size*3); glFormat = GL_RGB; glType = GL_UNSIGNED_BYTE;                   // 24 bpp
-        case UNCOMPRESSED_R5G5B5A1: pixels = (unsigned short *)malloc(size); glFormat = GL_RGBA; glType = GL_UNSIGNED_SHORT_5_5_5_1;        // 16 bpp (1 bit alpha)
-        case UNCOMPRESSED_R4G4B4A4: pixels = (unsigned short *)malloc(size); glFormat = GL_RGBA; glType = GL_UNSIGNED_SHORT_4_4_4_4;        // 16 bpp (4 bit alpha)
-        case UNCOMPRESSED_R8G8B8A8: pixels = (unsigned char *)malloc(size*4); glFormat = GL_RGBA; glType = GL_UNSIGNED_BYTE;                // 32 bpp
-        default: TraceLog(WARNING, "Texture format not suported"); break;
+        enabledPostpro = true;
+        rlglInitPostpro();
     }
 
-    glBindTexture(GL_TEXTURE_2D, textureId);
-    
-    // NOTE: Each row written to or read from by OpenGL pixel operations like glGetTexImage are aligned to a 4 byte boundary by default, which may add some padding.
-    // Use glPixelStorei to modify padding with the GL_[UN]PACK_ALIGNMENT setting. 
-    // GL_PACK_ALIGNMENT affects operations that read from OpenGL memory (glReadPixels, glGetTexImage, etc.) 
-    // GL_UNPACK_ALIGNMENT affects operations that write to OpenGL memory (glTexImage, etc.)
-    glPixelStorei(GL_PACK_ALIGNMENT, 1);
+    SetModelShader(&postproQuad, shader);
     
-    glGetTexImage(GL_TEXTURE_2D, 0, glFormat, glType, pixels);
-    
-    glBindTexture(GL_TEXTURE_2D, 0);
+    Texture2D texture;
+    texture.id = fboColorTexture;
+    texture.width = GetScreenWidth();
+    texture.height = GetScreenHeight();
+
+    SetShaderMapDiffuse(&postproQuad.shader, texture);
     
-    return pixels;
+    //TraceLog(DEBUG, "Postproquad texture id: %i", postproQuad.texture.id);
+    //TraceLog(DEBUG, "Postproquad shader diffuse map id: %i", postproQuad.shader.texDiffuseId);
+    //TraceLog(DEBUG, "Shader diffuse map id: %i", shader.texDiffuseId);
+#elif defined(GRAPHICS_API_OPENGL_11)
+    TraceLog(WARNING, "Postprocessing shaders not supported on OpenGL 1.1");
+#endif
 }
 
-// Load a shader (vertex shader + fragment shader) from files
-Shader rlglLoadShader(char *vsFileName, char *fsFileName)
+// Set default shader to be used in batch draw
+void SetDefaultShader(void)
 {
-    Shader shader;
-
 #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
-    // Shaders loading from external text file
-    char *vShaderStr = TextFileRead(vsFileName);
-    char *fShaderStr = TextFileRead(fsFileName);
-
-    shader.id = rlglLoadShaderFromText(vShaderStr, fShaderStr);
-
-    if (shader.id != 0) TraceLog(INFO, "[SHDR ID %i] Custom shader loaded successfully", shader.id);
-    else TraceLog(WARNING, "[SHDR ID %i] Custom shader could not be loaded", shader.id);
-
-    // Shader strings must be freed
-    free(vShaderStr);
-    free(fShaderStr);
+    SetCustomShader(defaultShader);
+    SetPostproShader(defaultShader);
     
-    // Set shader textures ids (all 0 by default)
-    shader.texDiffuseId = 0;
-    shader.texNormalId = 0;
-    shader.texSpecularId = 0;
-
-    // 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");
-    // NOTE: custom shader does not use colorLoc
-    shader.colorLoc = -1;
-
-    // Get handles to GLSL uniform locations (vertex shader)
-    shader.modelviewLoc  = glGetUniformLocation(shader.id, "modelviewMatrix");
-    shader.projectionLoc = glGetUniformLocation(shader.id, "projectionMatrix");
-
-    // Get handles to GLSL uniform locations (fragment shader)
-    shader.tintColorLoc = glGetUniformLocation(shader.id, "tintColor");
-    shader.mapDiffuseLoc = glGetUniformLocation(shader.id, "texture0");
-    shader.mapNormalLoc = -1;       // It can be set later
-    shader.mapSpecularLoc = -1;     // It can be set later
-    //--------------------------------------------------------------------
+    enabledPostpro = false;
 #endif
-
-    return shader;
 }
 
 // Link shader to model
-void rlglSetModelShader(Model *model, Shader shader)
+void SetModelShader(Model *model, Shader shader)
 {
 #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
     model->shader = shader;
@@ -2175,48 +2264,17 @@ void rlglSetModelShader(Model *model, Shader shader)
 #endif
 }
 
-// Set custom shader to be used on batch draw
-void rlglSetCustomShader(Shader shader)
+// Check if postprocessing is enabled (used in module: core)
+bool IsPosproShaderEnabled(void)
 {
 #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
-    if (currentShader.id != shader.id)
-    {
-        rlglDraw();
-
-        currentShader = shader;
-/*
-        if (vaoSupported) glBindVertexArray(vaoQuads);
-        
-        // Enable vertex attributes: position
-        glBindBuffer(GL_ARRAY_BUFFER, quadsBuffer[0]);
-        glEnableVertexAttribArray(currentShader.vertexLoc);
-        glVertexAttribPointer(currentShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0);
-
-        // Enable vertex attributes: texcoords
-        glBindBuffer(GL_ARRAY_BUFFER, quadsBuffer[1]);
-        glEnableVertexAttribArray(currentShader.texcoordLoc);
-        glVertexAttribPointer(currentShader.texcoordLoc, 2, GL_FLOAT, 0, 0, 0);
-
-        // Enable vertex attributes: colors
-        glBindBuffer(GL_ARRAY_BUFFER, quadsBuffer[2]);
-        glEnableVertexAttribArray(currentShader.colorLoc);
-        glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
-
-        if (vaoSupported) glBindVertexArray(0);     // Unbind VAO
-*/
-    }
-#endif
-}
-
-// Set default shader to be used on batch draw
-void rlglSetDefaultShader(void)
-{
-#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
-    rlglSetCustomShader(defaultShader);
-    rlglSetPostproShader(defaultShader);
+    return enabledPostpro;
+#elif defined(GRAPHICS_API_OPENGL_11)
+    return false;
 #endif
 }
 
+// Get shader uniform location
 int GetShaderLocation(Shader shader, const char *uniformName)
 {
     int location = -1;
@@ -2228,6 +2286,7 @@ int GetShaderLocation(Shader shader, const char *uniformName)
     return location;
 }
 
+// Set shader uniform value (float)
 void SetShaderValue(Shader shader, int uniformLoc, float *value, int size)
 {
 #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
@@ -2237,12 +2296,29 @@ void SetShaderValue(Shader shader, int uniformLoc, float *value, int size)
     else if (size == 2) glUniform2fv(uniformLoc, 1, value);     // Shader uniform type: vec2
     else if (size == 3) glUniform3fv(uniformLoc, 1, value);     // Shader uniform type: vec3
     else if (size == 4) glUniform4fv(uniformLoc, 1, value);     // Shader uniform type: vec4
-    else TraceLog(WARNING, "Shader value float array size not recognized");
+    else TraceLog(WARNING, "Shader value float array size not supported");
     
     glUseProgram(0);
 #endif
 }
 
+// Set shader uniform value (int)
+void SetShaderValuei(Shader shader, int uniformLoc, int *value, int size)
+{
+#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
+    glUseProgram(shader.id);
+
+    if (size == 1) glUniform1iv(uniformLoc, 1, value);          // Shader uniform type: int
+    else if (size == 2) glUniform2iv(uniformLoc, 1, value);     // Shader uniform type: ivec2
+    else if (size == 3) glUniform3iv(uniformLoc, 1, value);     // Shader uniform type: ivec3
+    else if (size == 4) glUniform4iv(uniformLoc, 1, value);     // Shader uniform type: ivec4
+    else TraceLog(WARNING, "Shader value int array size not supported");
+    
+    glUseProgram(0);
+#endif
+}
+
+// Default diffuse shader map texture assignment
 void SetShaderMapDiffuse(Shader *shader, Texture2D texture)
 {
 #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
@@ -2261,6 +2337,7 @@ void SetShaderMapDiffuse(Shader *shader, Texture2D texture)
 #endif
 }
 
+// Normal map texture shader assignment
 void SetShaderMapNormal(Shader *shader, const char *uniformName, Texture2D texture)
 {
 #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
@@ -2285,6 +2362,7 @@ void SetShaderMapNormal(Shader *shader, const char *uniformName, Texture2D textu
 #endif
 }
 
+// Specular map texture shader assignment
 void SetShaderMapSpecular(Shader *shader, const char *uniformName, Texture2D texture)
 {
 #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
@@ -2300,7 +2378,7 @@ void SetShaderMapSpecular(Shader *shader, const char *uniformName, Texture2D tex
         glActiveTexture(GL_TEXTURE2);
         glBindTexture(GL_TEXTURE_2D, shader->texSpecularId);
         
-        glUniform1i(shader->mapSpecularLoc, 2);    // Texture fits in active texture unit 0
+        glUniform1i(shader->mapSpecularLoc, 2);    // Texture fits in active texture unit 2
         
         glBindTexture(GL_TEXTURE_2D, 0);
         glActiveTexture(GL_TEXTURE0);
@@ -2309,6 +2387,35 @@ void SetShaderMapSpecular(Shader *shader, const char *uniformName, Texture2D tex
 #endif
 }
 
+// Generic shader maps assignment
+// TODO: Trying to find a generic shader to allow any kind of map
+// NOTE: mapLocation should be retrieved by user with GetShaderLocation()
+// ISSUE: mapTextureId: Shader should contain a reference to map texture and corresponding textureUnit,
+//        so it can be automatically checked and used in rlglDrawModel()
+void SetShaderMap(Shader *shader, int mapLocation, Texture2D texture, int textureUnit)
+{
+/*
+#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
+    if (mapLocation == -1) TraceLog(WARNING, "[SHDR ID %i] Map location could not be found", shader->id);
+    else
+    {
+        shader->mapTextureId = texture.id;
+        
+        glUseProgram(shader->id);
+        
+        glActiveTexture(GL_TEXTURE0 + textureUnit);
+        glBindTexture(GL_TEXTURE_2D, shader->mapTextureId);
+        
+        glUniform1i(mapLocation, textureUnit);    // Texture fits in active textureUnit
+        
+        glBindTexture(GL_TEXTURE_2D, 0);
+        glActiveTexture(GL_TEXTURE0);
+        glUseProgram(0);
+    }
+#endif
+*/
+}
+
 #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
 void PrintProjectionMatrix(void)
 {
@@ -2415,7 +2522,7 @@ static Shader LoadDefaultShader(void)
         "    gl_FragColor = texelColor*tintColor; \n"    
         "}                                  \n";
 
-    shader.id = rlglLoadShaderFromText(vShaderStr, fShaderStr);
+    shader.id = LoadShaderProgram(vShaderStr, fShaderStr);
 
     if (shader.id != 0) TraceLog(INFO, "[SHDR ID %i] Default shader loaded successfully", shader.id);
     else TraceLog(WARNING, "[SHDR ID %i] Default shader could not be loaded", shader.id);
@@ -2491,7 +2598,7 @@ static Shader LoadSimpleShader(void)
         "    gl_FragColor = texelColor*tintColor; \n"
         "}                                  \n";
 
-    shader.id = rlglLoadShaderFromText(vShaderStr, fShaderStr);
+    shader.id = LoadShaderProgram(vShaderStr, fShaderStr);
 
     if (shader.id != 0) TraceLog(INFO, "[SHDR ID %i] Simple shader loaded successfully", shader.id);
     else TraceLog(WARNING, "[SHDR ID %i] Simple shader could not be loaded", shader.id);
@@ -2710,7 +2817,7 @@ static void InitializeBuffersGPU(void)
 
 // Update VBOs with vertex array data
 // NOTE: If there is not vertex data, buffers doesn't need to be updated (vertexCount > 0)
-// TODO: If no data changed on the CPU arrays --> No need to update GPU arrays
+// TODO: If no data changed on the CPU arrays --> No need to update GPU arrays (change flag required)
 static void UpdateBuffers(void)
 {
     if (lines.vCounter > 0)

+ 3 - 6
src/rlgl.h

@@ -212,14 +212,11 @@ void rlglInitGraphics(int offsetX, int offsetY, int width, int height);  // Init
 unsigned int rlglLoadTexture(void *data, int width, int height, int textureFormat, int mipmapCount);       // Load in GPU OpenGL texture
 void rlglGenerateMipmaps(unsigned int textureId);                           // Generate mipmap data for selected texture
 
-Shader rlglLoadShader(char *vsFileName, char *fsFileName);                  // Load a shader (vertex shader + fragment shader) from files
-unsigned int rlglLoadShaderFromText(char *vShaderStr, char *fShaderStr);    // Load a shader from text data
+// NOTE: There is a set of shader related functions that are available to end user,
+// to avoid creating function wrappers through core module, they have been directly declared in raylib.h
+
 void rlglInitPostpro(void);                     // Initialize postprocessing system
 void rlglDrawPostpro(void);                     // Draw with postprocessing shader
-void rlglSetPostproShader(Shader shader);       // Set postprocessing shader
-void rlglSetModelShader(Model *model, Shader shader);   // Set shader for a model
-void rlglSetCustomShader(Shader shader);        // Set custom shader to be used on batch draw
-void rlglSetDefaultShader(void);                // Set default shader to be used on batch draw
 
 Model rlglLoadModel(VertexData mesh);           // Upload vertex data into GPU and provided VAO/VBO ids
 void rlglDrawModel(Model model, Vector3 position, float rotationAngle, Vector3 rotationAxis, Vector3 scale, Color color, bool wires);