aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRay <raysan5@gmail.com>2015-07-28 17:38:37 +0200
committerRay <raysan5@gmail.com>2015-07-28 17:38:37 +0200
commit8b3a82688e82922819d24494c08e24570c03bdc4 (patch)
tree1df1379dfc4948477b664023d2ce0100d83d1783 /src
parenta59433e7a3b22d5ded7505689fb44f1927194077 (diff)
parent067b884f395b7b6d4c179cb3d58b0d17a02950ec (diff)
downloadraylib-8b3a82688e82922819d24494c08e24570c03bdc4.tar.gz
raylib-8b3a82688e82922819d24494c08e24570c03bdc4.zip
Merge pull request #24 from raysan5/develop
Integrate Develop branch
Diffstat (limited to 'src')
-rw-r--r--src/camera.c104
-rw-r--r--src/camera.h69
-rw-r--r--src/core.c46
-rw-r--r--src/gestures.c42
-rw-r--r--src/models.c76
-rw-r--r--src/raylib.h125
-rw-r--r--src/resourcesbin107204 -> 107204 bytes
-rw-r--r--src/rlgl.c544
-rw-r--r--src/rlgl.h18
-rw-r--r--src/stb_image.h16
-rw-r--r--src/text.c18
-rw-r--r--src/textures.c480
12 files changed, 936 insertions, 602 deletions
diff --git a/src/camera.c b/src/camera.c
index cb99ba6b..cde118c9 100644
--- a/src/camera.c
+++ b/src/camera.c
@@ -23,7 +23,8 @@
*
**********************************************************************************************/
-#include "raylib.h"
+#include "camera.h"
+
#include <math.h>
//----------------------------------------------------------------------------------
@@ -93,15 +94,6 @@ static int cameraMode = CAMERA_CUSTOM;
// Module specific Functions Declaration
//----------------------------------------------------------------------------------
static void ProcessCamera(Camera *camera, Vector3 *playerPosition);
-/*
-static void SetCameraControls(int front, int left, int back, right, up, down);
-static void SetMouseSensitivity(int sensitivity);
-static void SetResetPosition(Vector3 resetPosition);
-static void SetResetControl(int resetKey);
-static void SetPawnControl(int pawnControlKey);
-static void SetFnControl(int fnControlKey);
-static void SetSmoothZoomControl(int smoothZoomControlKey);
-*/
//----------------------------------------------------------------------------------
// Module Functions Definition
@@ -153,6 +145,53 @@ Camera UpdateCamera(Vector3 *position)
return internalCamera;
}
+
+void SetCameraControls(int frontKey, int leftKey, int backKey, int rightKey, int upKey, int downKey)
+{
+ cameraMovementController[0] = frontKey;
+ cameraMovementController[1] = leftKey;
+ cameraMovementController[2] = backKey;
+ cameraMovementController[3] = rightKey;
+ cameraMovementController[4] = upKey;
+ cameraMovementController[5] = downKey;
+}
+
+void SetCameraMouseSensitivity(float sensitivity)
+{
+ mouseSensitivity = (sensitivity / 10000.0);
+}
+
+void SetCameraResetPosition(Vector3 resetPosition)
+{
+ resetingPosition = resetPosition;
+}
+
+void SetCameraResetControl(int resetKey)
+{
+ resetingKey = resetKey;
+}
+
+void SetCameraPawnControl(int pawnControlKey)
+{
+ pawnControllingKey = pawnControlKey;
+}
+
+void SetCameraFnControl(int fnControlKey)
+{
+ fnControllingKey = fnControlKey;
+}
+
+void SetCameraSmoothZoomControl(int smoothZoomControlKey)
+{
+ smoothZoomControllingKey = smoothZoomControlKey;
+}
+
+void SetCameraOrbitalTarget(Vector3 target)
+{
+ internalCamera.target = target;
+}
+
+
//----------------------------------------------------------------------------------
// Module specific Functions Definition
//----------------------------------------------------------------------------------
@@ -408,48 +447,3 @@ static void ProcessCamera(Camera *camera, Vector3 *playerPosition)
}
#endif
}
-
-void SetCameraControls(int frontKey, int leftKey, int backKey, int rightKey, int upKey, int downKey)
-{
- cameraMovementController[0] = frontKey;
- cameraMovementController[1] = leftKey;
- cameraMovementController[2] = backKey;
- cameraMovementController[3] = rightKey;
- cameraMovementController[4] = upKey;
- cameraMovementController[5] = downKey;
-}
-
-void SetMouseSensitivity(float sensitivity)
-{
- mouseSensitivity = (sensitivity / 10000.0);
-}
-
-void SetResetPosition(Vector3 resetPosition)
-{
- resetingPosition = resetPosition;
-}
-
-void SetResetControl(int resetKey)
-{
- resetingKey = resetKey;
-}
-
-void SetPawnControl(int pawnControlKey)
-{
- pawnControllingKey = pawnControlKey;
-}
-
-void SetFnControl(int fnControlKey)
-{
- fnControllingKey = fnControlKey;
-}
-
-void SetSmoothZoomControl(int smoothZoomControlKey)
-{
- smoothZoomControllingKey = smoothZoomControlKey;
-}
-
-void SetOrbitalTarget(Vector3 target)
-{
- internalCamera.target = target;
-}
diff --git a/src/camera.h b/src/camera.h
new file mode 100644
index 00000000..cb5f2bde
--- /dev/null
+++ b/src/camera.h
@@ -0,0 +1,69 @@
+/*******************************************************************************************
+*
+* raylib Camera System - Camera Modes Setup and Control Functions
+*
+* Copyright (c) 2015 Marc Palau and Ramon Santamaria
+*
+* This software is provided "as-is", without any express or implied warranty. In no event
+* will the authors be held liable for any damages arising from the use of this software.
+*
+* Permission is granted to anyone to use this software for any purpose, including commercial
+* applications, and to alter it and redistribute it freely, subject to the following restrictions:
+*
+* 1. The origin of this software must not be misrepresented; you must not claim that you
+* wrote the original software. If you use this software in a product, an acknowledgment
+* in the product documentation would be appreciated but is not required.
+*
+* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
+* as being the original software.
+*
+* 3. This notice may not be removed or altered from any source distribution.
+*
+**********************************************************************************************/
+
+#ifndef CAMERA_H
+#define CAMERA_H
+
+#include "raylib.h"
+
+//----------------------------------------------------------------------------------
+// Defines and Macros
+//----------------------------------------------------------------------------------
+//...
+
+//----------------------------------------------------------------------------------
+// Types and Structures Definition
+//----------------------------------------------------------------------------------
+// Camera modes
+typedef enum { CAMERA_CUSTOM = 0, CAMERA_FREE, CAMERA_ORBITAL, CAMERA_FIRST_PERSON, CAMERA_THIRD_PERSON } CameraMode;
+
+
+#ifdef __cplusplus
+extern "C" { // Prevents name mangling of functions
+#endif
+
+//----------------------------------------------------------------------------------
+// Global Variables Definition
+//----------------------------------------------------------------------------------
+//...
+
+//----------------------------------------------------------------------------------
+// Module Functions Declaration
+//----------------------------------------------------------------------------------
+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);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // CAMERA_H
diff --git a/src/core.c b/src/core.c
index 7bbe3892..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
@@ -606,7 +603,7 @@ Color GetColor(int hexValue)
// Returns hexadecimal value for a Color
int GetHexValue(Color color)
{
- return ((color.a << 24) + (color.r << 16) + (color.g << 8) + color.b);
+ return (((int)color.r << 24) | ((int)color.g << 16) | ((int)color.b << 8) | (int)color.a);
}
// Returns a random value between min and max (both included)
@@ -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/gestures.c b/src/gestures.c
index 13209b32..ad8ac9f6 100644
--- a/src/gestures.c
+++ b/src/gestures.c
@@ -24,7 +24,6 @@
**********************************************************************************************/
#include "raylib.h"
-#include "raymath.h"
#include "utils.h"
#include <stdlib.h> // malloc(), free()
@@ -126,16 +125,17 @@ static float pinchDelta = 0;
// Detected gesture
static int currentGesture = GESTURE_NONE;
+unsigned int enabledGestures = 0; // TODO: Currently not in use...
static Vector2 touchPosition;
//----------------------------------------------------------------------------------
// Module specific Functions Declaration
//----------------------------------------------------------------------------------
-extern void ProcessMotionEvent(GestureEvent event);
extern void ResetGestures(void);
extern Vector2 GetRawPosition(void);
+static void ProcessMotionEvent(GestureEvent event);
static float CalculateAngle(Vector2 initialPosition, Vector2 actualPosition, float magnitude);
static float OnPinch();
static void SetDualInput(GestureEvent event);
@@ -185,40 +185,45 @@ int GetGestureType(void)
return currentGesture;
}
+void SetGesturesEnabled(unsigned int gestureFlags)
+{
+ enabledGestures = gestureFlags;
+}
+
// Get drag intensity (pixels per frame)
-float GetDragIntensity(void)
+float GetGestureDragIntensity(void)
{
return intensity;
}
// Get drag angle
// NOTE: Angle in degrees, horizontal-right is 0, counterclock-wise
-float GetDragAngle(void)
+float GetGestureDragAngle(void)
{
return angle;
}
// Get drag vector (between initial and final position)
-Vector2 GetDragVector(void)
+Vector2 GetGestureDragVector(void)
{
return dragVector;
}
// Hold time measured in frames
-int GetHoldDuration(void)
+int GetGestureHoldDuration(void)
{
return 0;
}
// Get magnitude between two pinch points
-float GetPinchDelta(void)
+float GetGesturePinchDelta(void)
{
return pinchDelta;
}
-// Get angle beween two pinch points
+// Get angle beween two pinch points
// NOTE: Angle in degrees, horizontal-right is 0, counterclock-wise
-float GetPinchAngle(void)
+float GetGesturePinchAngle(void)
{
return 0;
}
@@ -260,7 +265,7 @@ extern void InitAndroidGestures(struct android_app *app)
//----------------------------------------------------------------------------------
// Module specific Functions Definition
//----------------------------------------------------------------------------------
-extern void ProcessMotionEvent(GestureEvent event)
+static void ProcessMotionEvent(GestureEvent event)
{
// Resets
dragVector = (Vector2){ 0, 0 };
@@ -354,7 +359,7 @@ extern void ProcessMotionEvent(GestureEvent event)
{
lastDragPosition = endDragPosition;
- endDragPosition = GetRawPosition();
+ endDragPosition = touchPosition;
//endDragPosition.x = AMotionEvent_getX(event, 0);
//endDragPosition.y = AMotionEvent_getY(event, 0);
@@ -417,7 +422,6 @@ extern void ProcessMotionEvent(GestureEvent event)
//--------------------------------------------------------------------
}
-
static float CalculateAngle(Vector2 initialPosition, Vector2 actualPosition, float magnitude)
{
float angle;
@@ -564,6 +568,18 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
{
//int32_t key = AKeyEvent_getKeyCode(event);
//int32_t AKeyEvent_getMetaState(event);
+
+ int32_t code = AKeyEvent_getKeyCode((const AInputEvent *)event);
+
+ // If we are in active mode, we eat the back button and move into pause mode.
+ // If we are already in pause mode, we allow the back button to be handled by the OS, which means we'll be shut down.
+ /*
+ if ((code == AKEYCODE_BACK) && mActiveMode)
+ {
+ setActiveMode(false);
+ return 1;
+ }
+ */
}
int32_t action = AMotionEvent_getAction(event);
@@ -585,7 +601,7 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
ProcessMotionEvent(gestureEvent);
- return 0;
+ return 0; // return 1;
}
#endif
diff --git a/src/models.c b/src/models.c
index 8d772f02..c45e18c8 100644
--- a/src/models.c
+++ b/src/models.c
@@ -600,7 +600,7 @@ Model LoadHeightmap(Image heightmap, float maxHeight)
int mapX = heightmap.width;
int mapZ = heightmap.height;
- Color *heightmapPixels = GetPixelData(heightmap);
+ Color *heightmapPixels = GetImageData(heightmap);
// NOTE: One vertex per pixel
// TODO: Consider resolution when generating model data?
@@ -721,7 +721,7 @@ Model LoadCubicmap(Image cubicmap)
{
VertexData vData;
- Color *cubicmapPixels = GetPixelData(cubicmap);
+ Color *cubicmapPixels = GetImageData(cubicmap);
// Map cube size will be 1.0
float mapCubeSide = 1.0f;
@@ -1105,8 +1105,6 @@ void UnloadModel(Model model)
rlDeleteBuffers(model.mesh.vboId[2]);
rlDeleteVertexArrays(model.mesh.vaoId);
- //rlDeleteTextures(model.texture.id);
- //rlDeleteShader(model.shader.id);
}
// Link a texture to a model
@@ -1114,8 +1112,9 @@ void SetModelTexture(Model *model, Texture2D texture)
{
if (texture.id <= 0)
{
- model->texture.id = whiteTexture; // Default white texture (use mesh color)
- model->shader.texDiffuseId = whiteTexture;
+ // Use default white texture (use mesh color)
+ model->texture.id = whiteTexture; // OpenGL 1.1
+ model->shader.texDiffuseId = whiteTexture; // OpenGL 3.3 / ES 2.0
}
else
{
@@ -1124,26 +1123,6 @@ void SetModelTexture(Model *model, Texture2D texture)
}
}
-// Load a custom shader (vertex shader + fragment shader)
-Shader LoadShader(char *vsFileName, char *fsFileName)
-{
- Shader shader = rlglLoadShader(vsFileName, fsFileName);
-
- return shader;
-}
-
-// Unload a custom shader from memory
-void UnloadShader(Shader shader)
-{
- rlDeleteShader(shader.id);
-}
-
-// Set shader for a model
-void SetModelShader(Model *model, Shader shader)
-{
- rlglSetModelShader(model, shader);
-}
-
// Draw a model (with texture if set)
void DrawModel(Model model, Vector3 position, float scale, Color tint)
{
@@ -1269,7 +1248,7 @@ void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle sourceRec, Vec
rlDisableTexture();
}
-
+// Detect collision between two spheres
bool CheckCollisionSpheres(Vector3 centerA, float radiusA, Vector3 centerB, float radiusB)
{
bool collision = false;
@@ -1285,22 +1264,10 @@ bool CheckCollisionSpheres(Vector3 centerA, float radiusA, Vector3 centerB, floa
return collision;
}
+// Detect collision between two boxes
+// NOTE: Boxes are defined by two points minimum and maximum
bool CheckCollisionBoxes(Vector3 minBBox1, Vector3 maxBBox1, Vector3 minBBox2, Vector3 maxBBox2)
{
- /*
- // Get min and max vertex to construct bounds (AABB)
- Vector3 minVertex = tempVertices[0];
- Vector3 maxVertex = tempVertices[0];
-
- for (int i = 1; i < tempVertices.Count; i++)
- {
- minVertex = Vector3.Min(minVertex, tempVertices[i]);
- maxVertex = Vector3.Max(maxVertex, tempVertices[i]);
- }
-
- bounds = new BoundingBox(minVertex, maxVertex);
- */
-
bool collision = true;
if ((maxBBox1.x >= minBBox2.x) && (minBBox1.x <= maxBBox2.x))
@@ -1313,6 +1280,7 @@ bool CheckCollisionBoxes(Vector3 minBBox1, Vector3 maxBBox1, Vector3 minBBox2, V
return collision;
}
+// Detect collision between box and sphere
bool CheckCollisionBoxSphere(Vector3 minBBox, Vector3 maxBBox, Vector3 centerSphere, float radiusSphere)
{
bool collision = false;
@@ -1326,35 +1294,29 @@ bool CheckCollisionBoxSphere(Vector3 minBBox, Vector3 maxBBox, Vector3 centerSph
{
float dmin = 0;
- if (centerSphere.x - minBBox.x <= radiusSphere)
- dmin += (centerSphere.x - minBBox.x) * (centerSphere.x - minBBox.x);
- else if (maxBBox.x - centerSphere.x <= radiusSphere)
- dmin += (centerSphere.x - maxBBox.x) * (centerSphere.x - maxBBox.x);
+ if (centerSphere.x - minBBox.x <= radiusSphere) dmin += (centerSphere.x - minBBox.x)*(centerSphere.x - minBBox.x);
+ else if (maxBBox.x - centerSphere.x <= radiusSphere) dmin += (centerSphere.x - maxBBox.x)*(centerSphere.x - maxBBox.x);
- if (centerSphere.y - minBBox.y <= radiusSphere)
- dmin += (centerSphere.y - minBBox.y) * (centerSphere.y - minBBox.y);
- else if (maxBBox.y - centerSphere.y <= radiusSphere)
- dmin += (centerSphere.y - maxBBox.y) * (centerSphere.y - maxBBox.y);
+ if (centerSphere.y - minBBox.y <= radiusSphere) dmin += (centerSphere.y - minBBox.y)*(centerSphere.y - minBBox.y);
+ else if (maxBBox.y - centerSphere.y <= radiusSphere) dmin += (centerSphere.y - maxBBox.y)*(centerSphere.y - maxBBox.y);
- if (centerSphere.z - minBBox.z <= radiusSphere)
- dmin += (centerSphere.z - minBBox.z) * (centerSphere.z - minBBox.z);
- else if (maxBBox.z - centerSphere.z <= radiusSphere)
- dmin += (centerSphere.z - maxBBox.z) * (centerSphere.z - maxBBox.z);
+ if (centerSphere.z - minBBox.z <= radiusSphere) dmin += (centerSphere.z - minBBox.z)*(centerSphere.z - minBBox.z);
+ else if (maxBBox.z - centerSphere.z <= radiusSphere) dmin += (centerSphere.z - maxBBox.z)*(centerSphere.z - maxBBox.z);
- if (dmin <= radiusSphere * radiusSphere) collision = true;
+ if (dmin <= radiusSphere*radiusSphere) collision = true;
}
return collision;
}
-// TODO
+// TODO: Useful function to check collision area?
//BoundingBox GetCollisionArea(BoundingBox box1, BoundingBox box2)
// Detect and resolve cubicmap collisions
// NOTE: player position (or camera) is modified inside this function
Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *playerPosition, float radius)
{
- Color *cubicmapPixels = GetPixelData(cubicmap);
+ Color *cubicmapPixels = GetImageData(cubicmap);
// Detect the cell where the player is located
Vector3 impactDirection = { 0, 0, 0 };
@@ -1697,7 +1659,7 @@ static VertexData LoadOBJ(const char *fileName)
// Second reading pass: Get vertex data to fill intermediate arrays
// NOTE: This second pass is required in case of multiple meshes defined in same OBJ
- // TODO: Consider that diferent meshes can have different vertex data available (position, texcoords, normals)
+ // TODO: Consider that different meshes can have different vertex data available (position, texcoords, normals)
while(!feof(objFile))
{
fscanf(objFile, "%c", &dataType);
diff --git a/src/raylib.h b/src/raylib.h
index 6800b260..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)
@@ -358,18 +355,19 @@ typedef enum {
} TextureFormat;
// Gestures type
+// NOTE: It could be used as flags to enable only some gestures
typedef enum {
- GESTURE_NONE = 0,
- GESTURE_TAP,
- GESTURE_DOUBLETAP,
- GESTURE_HOLD,
- GESTURE_DRAG,
- GESTURE_SWIPE_RIGHT,
- GESTURE_SWIPE_LEFT,
- GESTURE_SWIPE_UP,
- GESTURE_SWIPE_DOWN,
- GESTURE_PINCH_IN,
- GESTURE_PINCH_OUT
+ GESTURE_NONE = 1,
+ GESTURE_TAP = 2,
+ GESTURE_DOUBLETAP = 4,
+ GESTURE_HOLD = 8,
+ GESTURE_DRAG = 16,
+ GESTURE_SWIPE_RIGHT = 32,
+ GESTURE_SWIPE_LEFT = 64,
+ GESTURE_SWIPE_UP = 128,
+ GESTURE_SWIPE_DOWN = 256,
+ GESTURE_PINCH_IN = 512,
+ GESTURE_PINCH_OUT = 1024
} Gestures;
#ifdef __cplusplus
@@ -420,31 +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 SetMouseSensitivity(float sensitivity);
-void SetResetPosition(Vector3 resetPosition);
-void SetResetControl(int resetKey);
-void SetPawnControl(int pawnControlKey);
-void SetFnControl(int fnControlKey);
-void SetSmoothZoomControl(int smoothZoomControlKey);
-void SetOrbitalTarget(Vector3 target);
+Ray GetMouseRay(Vector2 mousePosition, Camera camera); // TODO: Gives the ray trace from mouse position
-int GetShaderLocation(Shader shader, const char *uniformName);
-void SetShaderValue(Shader shader, int uniformLoc, float *value, int size);
-
-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)
@@ -488,12 +483,14 @@ Vector2 GetTouchPosition(void); // Returns touch positio
// Gestures System (module: gestures)
bool IsGestureDetected(void);
int GetGestureType(void);
-float GetDragIntensity(void);
-float GetDragAngle(void);
-Vector2 GetDragVector(void);
-int GetHoldDuration(void); // Hold time in frames
-float GetPinchDelta(void);
-float GetPinchAngle(void);
+void SetGesturesEnabled(unsigned int gestureFlags);
+
+float GetGestureDragIntensity(void);
+float GetGestureDragAngle(void);
+Vector2 GetGestureDragVector(void);
+int GetGestureHoldDuration(void); // Hold time in frames
+float GetGesturePinchDelta(void);
+float GetGesturePinchAngle(void);
#endif
//------------------------------------------------------------------------------------
@@ -530,16 +527,20 @@ bool CheckCollisionPointTriangle(Vector2 point, Vector2 p1, Vector2 p2, Vector2
// Texture Loading and Drawing Functions (Module: textures)
//------------------------------------------------------------------------------------
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)
-Image LoadImageFromData(Color *pixels, int width, int height, int format); // Load image from Color array data
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, bool genMipmaps); // Load a texture from raw data into GPU memory
+Texture2D LoadTextureEx(void *data, int width, int height, int textureFormat, int mipmapCount); // 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, bool genMipmaps); // Load a texture from image data (and generate mipmaps)
+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
-void ConvertToPOT(Image *image, Color fillColor); // Convert image to POT (power-of-two)
-Color *GetPixelData(Image image); // Get pixel data from image as a Color struct array
+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
+void GenTextureMipmaps(Texture2D texture); // Generate GPU mipmaps for a texture
void DrawTexture(Texture2D texture, int posX, int posY, Color tint); // Draw a Texture2D
void DrawTextureV(Texture2D texture, Vector2 position, Color tint); // Draw a Texture2D with position defined as Vector2
@@ -593,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
@@ -602,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/resources b/src/resources
index 2038c07a..b41637ff 100644
--- a/src/resources
+++ b/src/resources
Binary files differ
diff --git a/src/rlgl.c b/src/rlgl.c
index 157d8f20..12a25736 100644
--- a/src/rlgl.c
+++ b/src/rlgl.c
@@ -221,7 +221,7 @@ static bool vaoSupported = false; // VAO support (OpenGL ES2 could not support
static bool npotSupported = false; // NPOT textures full support
// Compressed textures support flags
-static bool texCompDXTSupported = false; // DDS texture compression support
+//static bool texCompDXTSupported = false; // DDS texture compression support
static bool texCompETC1Supported = false; // ETC1 texture compression support
static bool texCompETC2Supported = false; // ETC2/EAC texture compression support
static bool texCompPVRTSupported = false; // PVR texture compression support
@@ -230,8 +230,14 @@ 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
+static bool texCompDXTSupported = false; // DDS texture compression support
+
#if defined(GRAPHICS_API_OPENGL_ES2)
// NOTE: VAO functionality is exposed through extensions (OES)
static PFNGLGENVERTEXARRAYSOESPROC glGenVertexArrays;
@@ -263,7 +269,9 @@ static int GenerateMipmaps(unsigned char *data, int baseWidth, int baseHeight);
static pixel *GenNextMipmap(pixel *srcData, int srcWidth, int srcHeight);
#endif
+#if defined(GRAPHICS_API_OPENGL_ES2)
static char** StringSplit(char *baseString, const char delimiter, int *numExt);
+#endif
//----------------------------------------------------------------------------------
// Module Functions Definition - Matrix operations
@@ -952,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;
@@ -967,7 +975,7 @@ void rlglInit(void)
// Create default white texture for plain colors (required by shader)
unsigned char pixels[4] = { 255, 255, 255, 255 }; // 1 pixel RGBA (4 bytes)
- whiteTexture = rlglLoadTexture(pixels, 1, 1, UNCOMPRESSED_R8G8B8A8, 1, false);
+ whiteTexture = rlglLoadTexture(pixels, 1, 1, UNCOMPRESSED_R8G8B8A8, 1);
if (whiteTexture != 0) TraceLog(INFO, "[TEX ID %i] Base white texture loaded successfully", whiteTexture);
else TraceLog(WARNING, "Base white texture could not be loaded");
@@ -1049,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)
{
@@ -1372,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)
{
@@ -1397,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
@@ -1623,7 +1635,7 @@ Vector3 rlglUnproject(Vector3 source, Matrix proj, Matrix view)
}
// Convert image data to OpenGL texture (returns OpenGL valid Id)
-unsigned int rlglLoadTexture(void *data, int width, int height, int textureFormat, int mipmapCount, bool genMipmaps)
+unsigned int rlglLoadTexture(void *data, int width, int height, int textureFormat, int mipmapCount)
{
glBindTexture(GL_TEXTURE_2D, 0); // Free any old binding
@@ -1642,7 +1654,7 @@ unsigned int rlglLoadTexture(void *data, int width, int height, int textureForma
TraceLog(WARNING, "DXT compressed texture format not supported");
return id;
}
-
+#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
if ((!texCompETC1Supported) && (textureFormat == COMPRESSED_ETC1_RGB))
{
TraceLog(WARNING, "ETC1 compressed texture format not supported");
@@ -1666,7 +1678,8 @@ unsigned int rlglLoadTexture(void *data, int width, int height, int textureForma
TraceLog(WARNING, "ASTC compressed texture format not supported");
return id;
}
-
+#endif
+
glGenTextures(1, &id); // Generate Pointer to the texture
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
@@ -1755,23 +1768,67 @@ unsigned int rlglLoadTexture(void *data, int width, int height, int textureForma
}
#endif
- // Check if texture is power-of-two (POT) to enable mipmap generation
- bool texIsPOT = false;
-
- if (((width > 0) && ((width & (width - 1)) == 0)) && ((height > 0) && ((height & (height - 1)) == 0))) texIsPOT = true;
+ // Texture parameters configuration
+ // NOTE: glTexParameteri does NOT affect texture uploading, just the way it's used
+#if defined(GRAPHICS_API_OPENGL_ES2)
+ // NOTE: OpenGL ES 2.0 with no GL_OES_texture_npot support (i.e. WebGL) has limited NPOT support, so CLAMP_TO_EDGE must be used
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); // Set texture to clamp on x-axis
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); // Set texture to clamp on y-axis
+#else
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // Set texture to repeat on x-axis
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // Set texture to repeat on y-axis
+#endif
- if (genMipmaps && !texIsPOT)
+ // Magnification and minification filters
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // Filter for pixel-perfect drawing, alternative: GL_LINEAR
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); // Filter for pixel-perfect drawing, alternative: GL_LINEAR
+
+#if defined(GRAPHICS_API_OPENGL_33)
+ if (mipmapCount > 1)
{
- TraceLog(WARNING, "[TEX ID %i] Texture is not power-of-two, mipmaps can not be generated", id);
- genMipmaps = false;
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); // Activate Trilinear filtering for mipmaps (must be available)
}
+#endif
- // Generate mipmaps if required
- // TODO: Improve mipmaps support
-#if defined(GRAPHICS_API_OPENGL_11)
- if (genMipmaps)
+ // At this point we have the texture loaded in GPU and texture parameters configured
+
+ // NOTE: If mipmaps were not in data, they are not generated automatically
+
+ // Unbind current texture
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ if (id > 0) TraceLog(INFO, "[TEX ID %i] Texture created successfully (%ix%i)", id, width, height);
+ else TraceLog(WARNING, "Texture could not be created");
+
+ return id;
+}
+
+// Generate mipmap data for selected texture
+void rlglGenerateMipmaps(unsigned int textureId)
+{
+ glBindTexture(GL_TEXTURE_2D, textureId);
+
+ // Check if texture is power-of-two (POT)
+ bool texIsPOT = false;
+
+ // NOTE: In OpenGL ES 2.0 we have no way to retrieve texture size from id
+
+#if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33)
+ int width, height;
+
+ glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width);
+ glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height);
+
+ if (((width > 0) && ((width & (width - 1)) == 0)) && ((height > 0) && ((height & (height - 1)) == 0))) texIsPOT = true;
+#endif
+
+ if ((texIsPOT) || (npotSupported))
{
+#if defined(GRAPHICS_API_OPENGL_11)
// Compute required mipmaps
+ void *data = rlglReadTexturePixels(textureId, UNCOMPRESSED_R8G8B8A8); // TODO: Detect internal format
+
// NOTE: data size is reallocated to fit mipmaps data
int mipmapCount = GenerateMipmaps(data, width, height);
@@ -1794,48 +1851,19 @@ unsigned int rlglLoadTexture(void *data, int width, int height, int textureForma
mipHeight /= 2;
}
- TraceLog(WARNING, "[TEX ID %i] Mipmaps generated manually on CPU side", id);
- }
+ TraceLog(WARNING, "[TEX ID %i] Mipmaps generated manually on CPU side", textureId);
+
#elif defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
- if ((mipmapCount == 1) && (genMipmaps))
- {
- glGenerateMipmap(GL_TEXTURE_2D); // Generate mipmaps automatically
- TraceLog(INFO, "[TEX ID %i] Mipmaps generated automatically for new texture", id);
- }
-#endif
+ glGenerateMipmap(GL_TEXTURE_2D); // Generate mipmaps automatically
+ TraceLog(INFO, "[TEX ID %i] Mipmaps generated automatically", textureId);
- // Texture parameters configuration
- // NOTE: glTexParameteri does NOT affect texture uploading, just the way it's used
-#if defined(GRAPHICS_API_OPENGL_ES2)
- // NOTE: OpenGL ES 2.0 with no GL_OES_texture_npot support (i.e. WebGL) has limited NPOT support, so CLAMP_TO_EDGE must be used
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); // Set texture to clamp on x-axis
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); // Set texture to clamp on y-axis
-#else
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // Set texture to repeat on x-axis
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // Set texture to repeat on y-axis
-#endif
-
- // Magnification and minification filters
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // Filter for pixel-perfect drawing, alternative: GL_LINEAR
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); // Filter for pixel-perfect drawing, alternative: GL_LINEAR
-
-#if defined(GRAPHICS_API_OPENGL_33)
- if ((mipmapCount > 1) || (genMipmaps))
- {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); // Activate Trilinear filtering for mipmaps (must be available)
- }
#endif
-
- // At this point we have the texture loaded in GPU, with mipmaps generated (if desired) and texture parameters configured
-
- // Unbind current texture
+ }
+ else TraceLog(WARNING, "[TEX ID %i] Mipmaps can not be generated", textureId);
+
glBindTexture(GL_TEXTURE_2D, 0);
-
- if (id > 0) TraceLog(INFO, "[TEX ID %i] Texture created successfully (%ix%i)", id, width, height);
- else TraceLog(WARNING, "Texture could not be created");
-
- return id;
}
// Load vertex data into a VAO (if supported) and VBO
@@ -1914,12 +1942,135 @@ 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
+// NOTE: Retrieving pixel data from GPU not supported on OpenGL ES 2.0
+void *rlglReadTexturePixels(unsigned int textureId, unsigned int format)
+{
+ void *pixels = NULL;
+
+#if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33)
+ 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;
+
+ 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);
+#endif
+
+ 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;
@@ -2010,84 +2161,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
}
-// Load a shader (vertex shader + fragment shader) from files
-Shader rlglLoadShader(char *vsFileName, char *fsFileName)
+// Set postprocessing shader
+void SetPostproShader(Shader shader)
{
- 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);
+ if (!enabledPostpro)
+ {
+ enabledPostpro = true;
+ rlglInitPostpro();
+ }
- // Shader strings must be freed
- free(vShaderStr);
- free(fShaderStr);
+ SetModelShader(&postproQuad, shader);
- // 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");
+ Texture2D texture;
+ texture.id = fboColorTexture;
+ texture.width = GetScreenWidth();
+ texture.height = GetScreenHeight();
- // 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
- //--------------------------------------------------------------------
+ SetShaderMapDiffuse(&postproQuad.shader, texture);
+
+ //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
+}
- return shader;
+// Set default shader to be used in batch draw
+void SetDefaultShader(void)
+{
+#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
+ SetCustomShader(defaultShader);
+ SetPostproShader(defaultShader);
+
+ enabledPostpro = false;
+#endif
}
// 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;
@@ -2115,72 +2271,64 @@ void rlglSetModelShader(Model *model, Shader shader)
#endif
}
-// Set custom shader to be used on batch draw
-void rlglSetCustomShader(Shader shader)
-{
-#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)
+// Check if postprocessing is enabled (used in module: core)
+bool IsPosproShaderEnabled(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 = glGetUniformLocation(shader.id, uniformName);
+ int location = -1;
+#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
+ location = glGetUniformLocation(shader.id, uniformName);
if (location == -1) TraceLog(WARNING, "[SHDR ID %i] Shader location for %s could not be found", shader.id, uniformName);
-
+#endif
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)
glUseProgram(shader.id);
if (size == 1) glUniform1fv(uniformLoc, 1, value); // Shader uniform type: float
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)
shader->texDiffuseId = texture.id;
glUseProgram(shader->id);
@@ -2193,10 +2341,13 @@ void SetShaderMapDiffuse(Shader *shader, Texture2D texture)
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE0);
glUseProgram(0);
+#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)
shader->mapNormalLoc = glGetUniformLocation(shader->id, uniformName);
if (shader->mapNormalLoc == -1) TraceLog(WARNING, "[SHDR ID %i] Shader location for %s could not be found", shader->id, uniformName);
@@ -2215,10 +2366,13 @@ void SetShaderMapNormal(Shader *shader, const char *uniformName, Texture2D textu
glActiveTexture(GL_TEXTURE0);
glUseProgram(0);
}
+#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)
shader->mapSpecularLoc = glGetUniformLocation(shader->id, uniformName);
if (shader->mapSpecularLoc == -1) TraceLog(WARNING, "[SHDR ID %i] Shader location for %s could not be found", shader->id, uniformName);
@@ -2231,12 +2385,42 @@ 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);
glUseProgram(0);
}
+#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)
@@ -2345,7 +2529,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);
@@ -2421,7 +2605,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);
@@ -2640,7 +2824,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)
@@ -2865,6 +3049,7 @@ void TraceLog(int msgType, const char *text, ...)
}
#endif
+#if defined(GRAPHICS_API_OPENGL_ES2)
static char **StringSplit(char *baseString, const char delimiter, int *numExt)
{
char **result = 0;
@@ -2913,4 +3098,5 @@ static char **StringSplit(char *baseString, const char delimiter, int *numExt)
*numExt = (count - 1);
return result;
-} \ No newline at end of file
+}
+#endif \ No newline at end of file
diff --git a/src/rlgl.h b/src/rlgl.h
index 41c13ef7..eabf07e4 100644
--- a/src/rlgl.h
+++ b/src/rlgl.h
@@ -209,22 +209,22 @@ void rlglClose(void); // De-init rlgl
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, bool genMipmaps); // Load in GPU OpenGL 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
+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
+
+// 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);
-Vector3 rlglUnproject(Vector3 source, Matrix proj, Matrix view); // Get world coordinates from screen coordinates
+Vector3 rlglUnproject(Vector3 source, Matrix proj, Matrix view); // Get world coordinates from screen coordinates
-byte *rlglReadScreenPixels(int width, int height); // Read screen pixel data (color buffer)
+unsigned char *rlglReadScreenPixels(int width, int height); // Read screen pixel data (color buffer)
+void *rlglReadTexturePixels(unsigned int textureId, unsigned int format); // Read texture pixel data
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
void PrintProjectionMatrix(void); // DEBUG: Print projection matrix
diff --git a/src/stb_image.h b/src/stb_image.h
index 1249c303..81d1ecf6 100644
--- a/src/stb_image.h
+++ b/src/stb_image.h
@@ -1,4 +1,4 @@
-/* stb_image - v2.05 - public domain image loader - http://nothings.org/stb_image.h
+/* stb_image - v2.06 - public domain image loader - http://nothings.org/stb_image.h
no warranty implied; use at your own risk
Do this:
@@ -143,6 +143,7 @@
Latest revision history:
+ 2.06 (2015-04-19) fix bug where PSD returns wrong '*comp' value
2.05 (2015-04-19) fix bug in progressive JPEG handling, fix warning
2.04 (2015-04-15) try to re-enable SIMD on MinGW 64-bit
2.03 (2015-04-12) additional corruption checking
@@ -5147,7 +5148,8 @@ static stbi_uc *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int
p = out+channel;
if (channel >= channelCount) {
// Fill this channel with default data.
- for (i = 0; i < pixelCount; i++) *p = (channel == 3 ? 255 : 0), p += 4;
+ for (i = 0; i < pixelCount; i++, p += 4)
+ *p = (channel == 3 ? 255 : 0);
} else {
// Read the RLE data.
count = 0;
@@ -5193,11 +5195,12 @@ static stbi_uc *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int
p = out + channel;
if (channel > channelCount) {
// Fill this channel with default data.
- for (i = 0; i < pixelCount; i++) *p = channel == 3 ? 255 : 0, p += 4;
+ for (i = 0; i < pixelCount; i++, p += 4)
+ *p = channel == 3 ? 255 : 0;
} else {
// Read the data.
- for (i = 0; i < pixelCount; i++)
- *p = stbi__get8(s), p += 4;
+ for (i = 0; i < pixelCount; i++, p += 4)
+ *p = stbi__get8(s);
}
}
}
@@ -5207,7 +5210,7 @@ static stbi_uc *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int
if (out == NULL) return out; // stbi__convert_format frees input on failure
}
- if (comp) *comp = channelCount;
+ if (comp) *comp = 4;
*y = h;
*x = w;
@@ -6300,6 +6303,7 @@ STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int
/*
revision history:
+ 2.06 (2015-04-19) fix bug where PSD returns wrong '*comp' value
2.05 (2015-04-19) fix bug in progressive JPEG handling, fix warning
2.04 (2015-04-15) try to re-enable SIMD on MinGW 64-bit
2.03 (2015-04-12) extra corruption checking (mmozeiko)
diff --git a/src/text.c b/src/text.c
index 1647070c..feed211e 100644
--- a/src/text.c
+++ b/src/text.c
@@ -171,11 +171,12 @@ extern void LoadDefaultFont(void)
//fwrite(image.pixels, 1, 128*128*4, myimage);
//fclose(myimage);
- Image image = LoadImageFromData(imagePixels, imWidth, imHeight, UNCOMPRESSED_GRAY_ALPHA);
+ Image image = LoadImageEx(imagePixels, imWidth, imHeight);
+ ImageConvertFormat(&image, UNCOMPRESSED_GRAY_ALPHA);
free(imagePixels);
- defaultFont.texture = LoadTextureFromImage(image, false); // Convert loaded image to OpenGL texture
+ defaultFont.texture = LoadTextureFromImage(image);
UnloadImage(image);
// Reconstruct charSet using charsWidth[], charsHeight, charsDivisor, numChars
@@ -237,10 +238,10 @@ SpriteFont LoadSpriteFont(const char *fileName)
// At this point we have a data array...
- Color *imagePixels = GetPixelData(image);
+ Color *imagePixels = GetImageData(image);
#if defined(PLATFORM_RPI) || defined(PLATFORM_WEB)
- ConvertToPOT(&image, MAGENTA);
+ ImageConvertToPOT(&image, MAGENTA);
#endif
// Process bitmap Font pixel data to get measures (Character array)
// spriteFont.charSet data is filled inside the function and memory is allocated!
@@ -251,7 +252,7 @@ SpriteFont LoadSpriteFont(const char *fileName)
spriteFont.numChars = numChars;
- spriteFont.texture = LoadTextureFromImage(image, false); // Convert loaded image to OpenGL texture
+ spriteFont.texture = LoadTextureFromImage(image); // Convert loaded image to OpenGL texture
free(imagePixels);
UnloadImage(image);
@@ -556,13 +557,14 @@ static SpriteFont LoadRBMF(const char *fileName)
counter++;
}
- Image image = LoadImageFromData(imagePixels, rbmfHeader.imgWidth, rbmfHeader.imgHeight, UNCOMPRESSED_GRAY_ALPHA);
+ Image image = LoadImageEx(imagePixels, rbmfHeader.imgWidth, rbmfHeader.imgHeight);
+ ImageConvertFormat(&image, UNCOMPRESSED_GRAY_ALPHA);
free(imagePixels);
TraceLog(INFO, "[%s] Image reconstructed correctly, now converting it to texture", fileName);
- spriteFont.texture = LoadTextureFromImage(image, false);
+ spriteFont.texture = LoadTextureFromImage(image);
UnloadImage(image); // Unload image data
//TraceLog(INFO, "[%s] Starting charSet reconstruction", fileName);
@@ -689,7 +691,7 @@ static SpriteFont LoadTTF(const char *fileName, int fontSize)
*/
font.numChars = 95;
font.charSet = (Character *)malloc(font.numChars*sizeof(Character));
- font.texture = LoadTextureFromImage(image, false);
+ font.texture = LoadTextureFromImage(image);
//stbtt_aligned_quad letter;
//int x = 0, y = 0;
diff --git a/src/textures.c b/src/textures.c
index e6c6cccb..b7ab1f7e 100644
--- a/src/textures.c
+++ b/src/textures.c
@@ -123,6 +123,82 @@ Image LoadImage(const char *fileName)
return image;
}
+// Load image data from Color array data (RGBA - 32bit)
+Image LoadImageEx(Color *pixels, int width, int height)
+{
+ Image image;
+ image.data = NULL;
+ image.width = width;
+ image.height = height;
+ image.mipmaps = 1;
+ image.format = UNCOMPRESSED_R8G8B8A8;
+
+ int k = 0;
+
+ image.data = (unsigned char *)malloc(image.width*image.height*4*sizeof(unsigned char));
+
+ for (int i = 0; i < image.width*image.height*4; i += 4)
+ {
+ ((unsigned char *)image.data)[i] = pixels[k].r;
+ ((unsigned char *)image.data)[i + 1] = pixels[k].g;
+ ((unsigned char *)image.data)[i + 2] = pixels[k].b;
+ ((unsigned char *)image.data)[i + 3] = pixels[k].a;
+ k++;
+ }
+
+ return image;
+}
+
+// Load an image from RAW file
+Image LoadImageRaw(const char *fileName, int width, int height, int format, int headerSize)
+{
+ Image image;
+
+ image.data = NULL;
+ image.width = 0;
+ image.height = 0;
+ image.mipmaps = 0;
+ image.format = 0;
+
+ FILE *rawFile = fopen(fileName, "rb");
+
+ if (rawFile == NULL)
+ {
+ TraceLog(WARNING, "[%s] RAW image file could not be opened", fileName);
+ }
+ else
+ {
+ if (headerSize > 0) fseek(rawFile, headerSize, SEEK_SET);
+
+ unsigned int size = width*height;
+
+ switch (format)
+ {
+ case UNCOMPRESSED_GRAYSCALE: image.data = (unsigned char *)malloc(size); break; // 8 bit per pixel (no alpha)
+ case UNCOMPRESSED_GRAY_ALPHA: image.data = (unsigned char *)malloc(size*2); size *= 2; break; // 16 bpp (2 channels)
+ case UNCOMPRESSED_R5G6B5: image.data = (unsigned short *)malloc(size); break; // 16 bpp
+ case UNCOMPRESSED_R8G8B8: image.data = (unsigned char *)malloc(size*3); size *= 3; break; // 24 bpp
+ case UNCOMPRESSED_R5G5B5A1: image.data = (unsigned short *)malloc(size); break; // 16 bpp (1 bit alpha)
+ case UNCOMPRESSED_R4G4B4A4: image.data = (unsigned short *)malloc(size); break; // 16 bpp (4 bit alpha)
+ case UNCOMPRESSED_R8G8B8A8: image.data = (unsigned char *)malloc(size*4); size *= 4; break; // 32 bpp
+ default: TraceLog(WARNING, "Image format not suported"); break;
+ }
+
+ fread(image.data, size, 1, rawFile);
+
+ // TODO: Check if data have been read
+
+ image.width = width;
+ image.height = height;
+ image.mipmaps = 0;
+ image.format = format;
+
+ fclose(rawFile);
+ }
+
+ return image;
+}
+
// Load an image from rRES file (raylib Resource)
// TODO: Review function to support multiple color modes
Image LoadImageFromRES(const char *rresName, int resId)
@@ -243,12 +319,12 @@ Texture2D LoadTexture(const char *fileName)
Image image = LoadImage(fileName);
#if defined(PLATFORM_RPI) || defined(PLATFORM_WEB)
- ConvertToPOT(&image, BLANK);
+ ImageConvertToPOT(&image, BLANK);
#endif
if (image.data != NULL)
{
- texture = LoadTextureFromImage(image, false);
+ texture = LoadTextureFromImage(image);
UnloadImage(image);
}
else
@@ -261,7 +337,7 @@ Texture2D LoadTexture(const char *fileName)
return texture;
}
-Texture2D LoadTextureEx(void *data, int width, int height, int textureFormat, int mipmapCount, bool genMipmaps)
+Texture2D LoadTextureEx(void *data, int width, int height, int textureFormat, int mipmapCount)
{
Texture2D texture;
@@ -270,14 +346,26 @@ Texture2D LoadTextureEx(void *data, int width, int height, int textureFormat, in
texture.mipmaps = mipmapCount;
texture.format = textureFormat;
- texture.id = rlglLoadTexture(data, width, height, textureFormat, mipmapCount, genMipmaps);
+ texture.id = rlglLoadTexture(data, width, height, textureFormat, mipmapCount);
return texture;
}
+// Load an image as texture from rRES file (raylib Resource)
+Texture2D LoadTextureFromRES(const char *rresName, int resId)
+{
+ Texture2D texture;
+
+ Image image = LoadImageFromRES(rresName, resId);
+ texture = LoadTextureFromImage(image);
+ UnloadImage(image);
+
+ return texture;
+}
+
// Load a texture from image data
// NOTE: image is not unloaded, it must be done manually
-Texture2D LoadTextureFromImage(Image image, bool genMipmaps)
+Texture2D LoadTextureFromImage(Image image)
{
Texture2D texture;
@@ -288,7 +376,7 @@ Texture2D LoadTextureFromImage(Image image, bool genMipmaps)
texture.mipmaps = 0;
texture.format = 0;
- texture.id = rlglLoadTexture(image.data, image.width, image.height, image.format, image.mipmaps, false);
+ texture.id = rlglLoadTexture(image.data, image.width, image.height, image.format, image.mipmaps);
texture.width = image.width;
texture.height = image.height;
@@ -298,18 +386,6 @@ Texture2D LoadTextureFromImage(Image image, bool genMipmaps)
return texture;
}
-// Load an image as texture from rRES file (raylib Resource)
-Texture2D LoadTextureFromRES(const char *rresName, int resId)
-{
- Texture2D texture;
-
- Image image = LoadImageFromRES(rresName, resId);
- texture = LoadTextureFromImage(image, false);
- UnloadImage(image);
-
- return texture;
-}
-
// Unload image from CPU memory (RAM)
void UnloadImage(Image image)
{
@@ -322,46 +398,8 @@ void UnloadTexture(Texture2D texture)
rlDeleteTextures(texture.id);
}
-// Convert image to POT (power-of-two)
-// NOTE: Requirement on OpenGL ES 2.0 (RPI, HTML5)
-void ConvertToPOT(Image *image, Color fillColor)
-{
- // TODO: Review for new image struct
- /*
- // Just add the required amount of pixels at the right and bottom sides of image...
- int potWidth = GetNextPOT(image->width);
- int potHeight = GetNextPOT(image->height);
-
- // Check if POT texture generation is required (if texture is not already POT)
- if ((potWidth != image->width) || (potHeight != image->height))
- {
- Color *imgDataPixelPOT = NULL;
-
- // Generate POT array from NPOT data
- imgDataPixelPOT = (Color *)malloc(potWidth * potHeight * sizeof(Color));
-
- for (int j = 0; j < potHeight; j++)
- {
- for (int i = 0; i < potWidth; i++)
- {
- if ((j < image->height) && (i < image->width)) imgDataPixelPOT[j*potWidth + i] = image->data[j*image->width + i];
- else imgDataPixelPOT[j*potWidth + i] = fillColor;
- }
- }
-
- TraceLog(WARNING, "Image converted to POT: (%ix%i) -> (%ix%i)", image->width, image->height, potWidth, potHeight);
-
- free(image->pixels);
-
- image->pixels = imgDataPixelPOT;
- image->width = potWidth;
- image->height = potHeight;
- }
- */
-}
-
// Get pixel data from image in the form of Color struct array
-Color *GetPixelData(Image image)
+Color *GetImageData(Image image)
{
Color *pixels = (Color *)malloc(image.width*image.height*sizeof(Color));
@@ -447,142 +485,242 @@ Color *GetPixelData(Image image)
return pixels;
}
-// Fill image data with pixels Color data (RGBA - 32bit)
-// NOTE: Data is transformed to desired format
-Image LoadImageFromData(Color *pixels, int width, int height, int format)
+// Get pixel data from GPU texture and return an Image
+Image GetTextureData(Texture2D texture)
{
Image image;
- image.data = NULL;
- image.width = width;
- image.height = height;
- image.mipmaps = 1;
- image.format = format;
-
- int k = 0;
- switch (format)
+ image.data = rlglReadTexturePixels(texture.id, texture.format);
+
+ if (image.data != NULL)
{
- case UNCOMPRESSED_GRAYSCALE:
- {
- image.data = (unsigned char *)malloc(image.width*image.height*sizeof(unsigned char));
-
- for (int i = 0; i < image.width*image.height; i++)
- {
- ((unsigned char *)image.data)[i] = (unsigned char)((float)pixels[k].r*0.299f + (float)pixels[k].g*0.587f + (float)pixels[k].b*0.114f);
- k++;
- }
+ image.width = texture.width;
+ image.height = texture.height;
+ image.format = texture.format;
+ image.mipmaps = 1;
+ }
+ else TraceLog(WARNING, "Texture pixel data could not be obtained");
- } break;
- case UNCOMPRESSED_GRAY_ALPHA:
+ return image;
+}
+
+// Convert image data to desired format
+void ImageConvertFormat(Image *image, int newFormat)
+{
+ if ((image->format != newFormat) && (image->format < 8) && (newFormat < 8))
+ {
+ Color *pixels = GetImageData(*image);
+
+ free(image->data);
+
+ image->format = newFormat;
+
+ int k = 0;
+
+ switch (image->format)
{
- image.data = (unsigned char *)malloc(image.width*image.height*2*sizeof(unsigned char));
-
- for (int i = 0; i < image.width*image.height*2; i += 2)
+ case UNCOMPRESSED_GRAYSCALE:
{
- ((unsigned char *)image.data)[i] = (unsigned char)((float)pixels[k].r*0.299f + (float)pixels[k].g*0.587f + (float)pixels[k].b*0.114f);
- ((unsigned char *)image.data)[i + 1] = pixels[k].a;
- k++;
- }
+ image->data = (unsigned char *)malloc(image->width*image->height*sizeof(unsigned char));
+
+ for (int i = 0; i < image->width*image->height; i++)
+ {
+ ((unsigned char *)image->data)[i] = (unsigned char)((float)pixels[k].r*0.299f + (float)pixels[k].g*0.587f + (float)pixels[k].b*0.114f);
+ k++;
+ }
+
+ } break;
+ case UNCOMPRESSED_GRAY_ALPHA:
+ {
+ image->data = (unsigned char *)malloc(image->width*image->height*2*sizeof(unsigned char));
+
+ for (int i = 0; i < image->width*image->height*2; i += 2)
+ {
+ ((unsigned char *)image->data)[i] = (unsigned char)((float)pixels[k].r*0.299f + (float)pixels[k].g*0.587f + (float)pixels[k].b*0.114f);
+ ((unsigned char *)image->data)[i + 1] = pixels[k].a;
+ k++;
+ }
- } break;
- case UNCOMPRESSED_R5G6B5:
- {
- image.data = (unsigned short *)malloc(image.width*image.height*sizeof(unsigned short));
-
- unsigned char r;
- unsigned char g;
- unsigned char b;
-
- for (int i = 0; i < image.width*image.height; i++)
+ } break;
+ case UNCOMPRESSED_R5G6B5:
{
- r = (unsigned char)(round((float)pixels[k].r*31/255));
- g = (unsigned char)(round((float)pixels[k].g*63/255));
- b = (unsigned char)(round((float)pixels[k].b*31/255));
+ image->data = (unsigned short *)malloc(image->width*image->height*sizeof(unsigned short));
+
+ unsigned char r;
+ unsigned char g;
+ unsigned char b;
- ((unsigned short *)image.data)[i] = (unsigned short)r << 11 | (unsigned short)g << 5 | (unsigned short)b;
+ for (int i = 0; i < image->width*image->height; i++)
+ {
+ r = (unsigned char)(round((float)pixels[k].r*31/255));
+ g = (unsigned char)(round((float)pixels[k].g*63/255));
+ b = (unsigned char)(round((float)pixels[k].b*31/255));
+
+ ((unsigned short *)image->data)[i] = (unsigned short)r << 11 | (unsigned short)g << 5 | (unsigned short)b;
- k++;
- }
+ k++;
+ }
- } break;
- case UNCOMPRESSED_R8G8B8:
- {
- image.data = (unsigned char *)malloc(image.width*image.height*3*sizeof(unsigned char));
-
- for (int i = 0; i < image.width*image.height*3; i += 3)
+ } break;
+ case UNCOMPRESSED_R8G8B8:
{
- ((unsigned char *)image.data)[i] = pixels[k].r;
- ((unsigned char *)image.data)[i + 1] = pixels[k].g;
- ((unsigned char *)image.data)[i + 2] = pixels[k].b;
- k++;
- }
- } break;
- case UNCOMPRESSED_R5G5B5A1:
- {
- image.data = (unsigned short *)malloc(image.width*image.height*sizeof(unsigned short));
-
- unsigned char r;
- unsigned char g;
- unsigned char b;
- unsigned char a = 1;
-
- for (int i = 0; i < image.width*image.height; i++)
+ image->data = (unsigned char *)malloc(image->width*image->height*3*sizeof(unsigned char));
+
+ for (int i = 0; i < image->width*image->height*3; i += 3)
+ {
+ ((unsigned char *)image->data)[i] = pixels[k].r;
+ ((unsigned char *)image->data)[i + 1] = pixels[k].g;
+ ((unsigned char *)image->data)[i + 2] = pixels[k].b;
+ k++;
+ }
+ } break;
+ case UNCOMPRESSED_R5G5B5A1:
{
- r = (unsigned char)(round((float)pixels[k].r*31/255));
- g = (unsigned char)(round((float)pixels[k].g*31/255));
- b = (unsigned char)(round((float)pixels[k].b*31/255));
- a = (pixels[k].a > 50) ? 1 : 0;
+ image->data = (unsigned short *)malloc(image->width*image->height*sizeof(unsigned short));
- ((unsigned short *)image.data)[i] = (unsigned short)r << 11 | (unsigned short)g << 6 | (unsigned short)b << 1| (unsigned short)a;
-
- k++;
- }
+ unsigned char r;
+ unsigned char g;
+ unsigned char b;
+ unsigned char a = 1;
+
+ for (int i = 0; i < image->width*image->height; i++)
+ {
+ r = (unsigned char)(round((float)pixels[k].r*31/255));
+ g = (unsigned char)(round((float)pixels[k].g*31/255));
+ b = (unsigned char)(round((float)pixels[k].b*31/255));
+ a = (pixels[k].a > 50) ? 1 : 0;
+
+ ((unsigned short *)image->data)[i] = (unsigned short)r << 11 | (unsigned short)g << 6 | (unsigned short)b << 1| (unsigned short)a;
+
+ k++;
+ }
- } break;
- case UNCOMPRESSED_R4G4B4A4:
- {
- image.data = (unsigned short *)malloc(image.width*image.height*sizeof(unsigned short));
-
- unsigned char r;
- unsigned char g;
- unsigned char b;
- unsigned char a;
-
- for (int i = 0; i < image.width*image.height; i++)
+ } break;
+ case UNCOMPRESSED_R4G4B4A4:
{
- r = (unsigned char)(round((float)pixels[k].r*15/255));
- g = (unsigned char)(round((float)pixels[k].g*15/255));
- b = (unsigned char)(round((float)pixels[k].b*15/255));
- a = (unsigned char)(round((float)pixels[k].a*15/255));
+ image->data = (unsigned short *)malloc(image->width*image->height*sizeof(unsigned short));
+
+ unsigned char r;
+ unsigned char g;
+ unsigned char b;
+ unsigned char a;
+
+ for (int i = 0; i < image->width*image->height; i++)
+ {
+ r = (unsigned char)(round((float)pixels[k].r*15/255));
+ g = (unsigned char)(round((float)pixels[k].g*15/255));
+ b = (unsigned char)(round((float)pixels[k].b*15/255));
+ a = (unsigned char)(round((float)pixels[k].a*15/255));
+
+ ((unsigned short *)image->data)[i] = (unsigned short)r << 12 | (unsigned short)g << 8| (unsigned short)b << 4| (unsigned short)a;
+
+ k++;
+ }
- ((unsigned short *)image.data)[i] = (unsigned short)r << 12 | (unsigned short)g << 8| (unsigned short)b << 4| (unsigned short)a;
+ } break;
+ case UNCOMPRESSED_R8G8B8A8:
+ {
+ image->data = (unsigned char *)malloc(image->width*image->height*4*sizeof(unsigned char));
+
+ for (int i = 0; i < image->width*image->height*4; i += 4)
+ {
+ ((unsigned char *)image->data)[i] = pixels[k].r;
+ ((unsigned char *)image->data)[i + 1] = pixels[k].g;
+ ((unsigned char *)image->data)[i + 2] = pixels[k].b;
+ ((unsigned char *)image->data)[i + 3] = pixels[k].a;
+ k++;
+ }
+ } break;
+ default: break;
+ }
+
+ free(pixels);
+ }
+ else TraceLog(WARNING, "Image data format is compressed, can not be converted");
+}
- k++;
- }
-
- } break;
- case UNCOMPRESSED_R8G8B8A8:
+
+// Convert image to POT (power-of-two)
+// NOTE: Requirement on OpenGL ES 2.0 (RPI, HTML5)
+void ImageConvertToPOT(Image *image, Color fillColor)
+{
+ // TODO: Review for new image struct
+ /*
+ // Just add the required amount of pixels at the right and bottom sides of image...
+ int potWidth = GetNextPOT(image->width);
+ int potHeight = GetNextPOT(image->height);
+
+ // Check if POT texture generation is required (if texture is not already POT)
+ if ((potWidth != image->width) || (potHeight != image->height))
+ {
+ Color *imgDataPixelPOT = NULL;
+
+ // Generate POT array from NPOT data
+ imgDataPixelPOT = (Color *)malloc(potWidth * potHeight * sizeof(Color));
+
+ for (int j = 0; j < potHeight; j++)
{
- image.data = (unsigned char *)malloc(image.width*image.height*4*sizeof(unsigned char));
-
- for (int i = 0; i < image.width*image.height*4; i += 4)
+ for (int i = 0; i < potWidth; i++)
{
- ((unsigned char *)image.data)[i] = pixels[k].r;
- ((unsigned char *)image.data)[i + 1] = pixels[k].g;
- ((unsigned char *)image.data)[i + 2] = pixels[k].b;
- ((unsigned char *)image.data)[i + 3] = pixels[k].a;
- k++;
+ if ((j < image->height) && (i < image->width)) imgDataPixelPOT[j*potWidth + i] = image->data[j*image->width + i];
+ else imgDataPixelPOT[j*potWidth + i] = fillColor;
}
- } break;
- default:
- {
- TraceLog(WARNING, "Format not recognized, image could not be loaded");
-
- return image;
- } break;
+ }
+
+ TraceLog(WARNING, "Image converted to POT: (%ix%i) -> (%ix%i)", image->width, image->height, potWidth, potHeight);
+
+ free(image->pixels);
+
+ image->pixels = imgDataPixelPOT;
+ image->width = potWidth;
+ image->height = potHeight;
}
+ */
+}
- return image;
+// Copy an image to a new image
+Image ImageCopy(Image image)
+{
+ Image newImage;
+
+ int size = image.width*image.height;
+
+ switch (image.format)
+ {
+ case UNCOMPRESSED_GRAYSCALE: newImage.data = (unsigned char *)malloc(size); break; // 8 bit per pixel (no alpha)
+ case UNCOMPRESSED_GRAY_ALPHA: newImage.data = (unsigned char *)malloc(size*2); size *= 2; break; // 16 bpp (2 channels)
+ case UNCOMPRESSED_R5G6B5: newImage.data = (unsigned short *)malloc(size); size *= 2; break; // 16 bpp
+ case UNCOMPRESSED_R8G8B8: newImage.data = (unsigned char *)malloc(size*3); size *= 3; break; // 24 bpp
+ case UNCOMPRESSED_R5G5B5A1: newImage.data = (unsigned short *)malloc(size); size *= 2; break; // 16 bpp (1 bit alpha)
+ case UNCOMPRESSED_R4G4B4A4: newImage.data = (unsigned short *)malloc(size); size *= 2; break; // 16 bpp (4 bit alpha)
+ case UNCOMPRESSED_R8G8B8A8: newImage.data = (unsigned char *)malloc(size*4); size *= 4; break; // 32 bpp
+ default: TraceLog(WARNING, "Image format not suported for copy"); break;
+ }
+
+ if (newImage.data != NULL)
+ {
+ // NOTE: Size must be provided in bytes
+ memcpy(newImage.data, image.data, size);
+
+ newImage.width = image.width;
+ newImage.height = image.height;
+ newImage.mipmaps = image.mipmaps;
+ newImage.format = image.format;
+ }
+
+ return newImage;
+}
+
+// TODO: Some useful functions to deal with images
+//void ImageCrop(Image *image, Rectangle crop) {}
+//void ImageResize(Image *image, int newWidth, int newHeight) {}
+//void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec) {}
+//void ImageDrawText(Image *dst, const char *text, Vector2 position, int size, Color color) {}
+
+// Generate GPU mipmaps for a texture
+void GenTextureMipmaps(Texture2D texture)
+{
+ rlglGenerateMipmaps(texture.id);
}
// Draw a Texture2D
@@ -1224,6 +1362,8 @@ static Image LoadASTC(const char *fileName)
// NOTE: Assuming Little Endian (could it be wrong?)
image.width = 0x00000000 | ((int)header.width[2] << 16) | ((int)header.width[1] << 8) | ((int)header.width[0]);
image.height = 0x00000000 | ((int)header.height[2] << 16) | ((int)header.height[1] << 8) | ((int)header.height[0]);
+
+ // NOTE: ASTC format only contains one mipmap level
image.mipmaps = 1;
TraceLog(DEBUG, "ASTC image width: %i", image.width);
@@ -1251,4 +1391,4 @@ static Image LoadASTC(const char *fileName)
}
return image;
-} \ No newline at end of file
+}