From 552033da27ddeac2c8e9dd6b8ad33b7058963ef6 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Mon, 13 Jul 2015 18:20:16 +0200 Subject: [PATCH] Move shaders functions to module rlgl Shader functionality owns to rlgl, not core module --- src/core.c | 44 +----- src/raylib.h | 80 +++++----- src/rlgl.c | 427 ++++++++++++++++++++++++++++++++------------------- src/rlgl.h | 9 +- 4 files changed, 309 insertions(+), 251 deletions(-) diff --git a/src/core.c b/src/core.c index 301d9e6e..1cdcd679 100644 --- a/src/core.c +++ b/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); diff --git a/src/raylib.h b/src/raylib.h index e03fc9b2..228d3e58 100644 --- a/src/raylib.h +++ b/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 //------------------------------------------------------------------------------------ diff --git a/src/rlgl.c b/src/rlgl.c index 4ff652b0..b4bd7115 100644 --- a/src/rlgl.c +++ b/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) diff --git a/src/rlgl.h b/src/rlgl.h index e241a9c1..eabf07e4 100644 --- a/src/rlgl.h +++ b/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);