Merge remote-tracking branch 'refs/remotes/raysan5/develop' into develop
This commit is contained in:
commit
e660700924
8 changed files with 209 additions and 224 deletions
|
@ -43,7 +43,7 @@ int main()
|
||||||
UpdateCamera(&camera); // Update internal camera and our camera
|
UpdateCamera(&camera); // Update internal camera and our camera
|
||||||
|
|
||||||
// Calculate cube screen space position (with a little offset to be in top)
|
// Calculate cube screen space position (with a little offset to be in top)
|
||||||
cubeScreenPosition = WorldToScreen((Vector3){cubePosition.x, cubePosition.y + 2.5f, cubePosition.z}, camera);
|
cubeScreenPosition = GetWorldToScreen((Vector3){cubePosition.x, cubePosition.y + 2.5f, cubePosition.z}, camera);
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Draw
|
// Draw
|
||||||
|
|
|
@ -711,7 +711,7 @@ void StopSound(Sound sound)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if a sound is playing
|
// Check if a sound is playing
|
||||||
bool SoundIsPlaying(Sound sound)
|
bool IsSoundPlaying(Sound sound)
|
||||||
{
|
{
|
||||||
bool playing = false;
|
bool playing = false;
|
||||||
ALint state;
|
ALint state;
|
||||||
|
@ -890,7 +890,7 @@ void ResumeMusicStream(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if music is playing
|
// Check if music is playing
|
||||||
bool MusicIsPlaying(void)
|
bool IsMusicPlaying(void)
|
||||||
{
|
{
|
||||||
bool playing = false;
|
bool playing = false;
|
||||||
ALint state;
|
ALint state;
|
||||||
|
|
|
@ -96,7 +96,7 @@ void UnloadSound(Sound sound); // Unload sound
|
||||||
void PlaySound(Sound sound); // Play a sound
|
void PlaySound(Sound sound); // Play a sound
|
||||||
void PauseSound(Sound sound); // Pause a sound
|
void PauseSound(Sound sound); // Pause a sound
|
||||||
void StopSound(Sound sound); // Stop playing a sound
|
void StopSound(Sound sound); // Stop playing a sound
|
||||||
bool SoundIsPlaying(Sound sound); // Check if a sound is currently playing
|
bool IsSoundPlaying(Sound sound); // Check if a sound is currently playing
|
||||||
void SetSoundVolume(Sound sound, float volume); // Set volume for a sound (1.0 is max level)
|
void SetSoundVolume(Sound sound, float volume); // Set volume for a sound (1.0 is max level)
|
||||||
void SetSoundPitch(Sound sound, float pitch); // Set pitch for a sound (1.0 is base level)
|
void SetSoundPitch(Sound sound, float pitch); // Set pitch for a sound (1.0 is base level)
|
||||||
|
|
||||||
|
@ -105,7 +105,7 @@ void UpdateMusicStream(void); // Updates buffe
|
||||||
void StopMusicStream(void); // Stop music playing (close stream)
|
void StopMusicStream(void); // Stop music playing (close stream)
|
||||||
void PauseMusicStream(void); // Pause music playing
|
void PauseMusicStream(void); // Pause music playing
|
||||||
void ResumeMusicStream(void); // Resume playing paused music
|
void ResumeMusicStream(void); // Resume playing paused music
|
||||||
bool MusicIsPlaying(void); // Check if music is playing
|
bool IsMusicPlaying(void); // Check if music is playing
|
||||||
void SetMusicVolume(float volume); // Set volume for music (1.0 is max level)
|
void SetMusicVolume(float volume); // Set volume for music (1.0 is max level)
|
||||||
float GetMusicTimeLength(void); // Get music time length (in seconds)
|
float GetMusicTimeLength(void); // Get music time length (in seconds)
|
||||||
float GetMusicTimePlayed(void); // Get current music time played (in seconds)
|
float GetMusicTimePlayed(void); // Get current music time played (in seconds)
|
||||||
|
|
|
@ -905,7 +905,7 @@ Ray GetMouseRay(Vector2 mousePosition, Camera camera)
|
||||||
Vector3 farPoint = rlglUnproject((Vector3){ deviceCoords.x, deviceCoords.y, 1.0f }, matProj, matView);
|
Vector3 farPoint = rlglUnproject((Vector3){ deviceCoords.x, deviceCoords.y, 1.0f }, matProj, matView);
|
||||||
|
|
||||||
#else // OPTION 2: Compute unprojection directly here
|
#else // OPTION 2: Compute unprojection directly here
|
||||||
|
|
||||||
// Calculate unproject matrix (multiply projection matrix and view matrix) and invert it
|
// Calculate unproject matrix (multiply projection matrix and view matrix) and invert it
|
||||||
Matrix matProjView = MatrixMultiply(matProj, matView);
|
Matrix matProjView = MatrixMultiply(matProj, matView);
|
||||||
MatrixInvert(&matProjView);
|
MatrixInvert(&matProjView);
|
||||||
|
@ -935,7 +935,7 @@ Ray GetMouseRay(Vector2 mousePosition, Camera camera)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the screen space position from a 3d world space position
|
// Returns the screen space position from a 3d world space position
|
||||||
Vector2 WorldToScreen(Vector3 position, Camera camera)
|
Vector2 GetWorldToScreen(Vector3 position, Camera camera)
|
||||||
{
|
{
|
||||||
// Calculate projection matrix (from perspective instead of frustum
|
// Calculate projection matrix (from perspective instead of frustum
|
||||||
Matrix matProj = MatrixPerspective(camera.fovy, (double)GetScreenWidth()/(double)GetScreenHeight(), 0.01, 1000.0);
|
Matrix matProj = MatrixPerspective(camera.fovy, (double)GetScreenWidth()/(double)GetScreenHeight(), 0.01, 1000.0);
|
||||||
|
|
|
@ -586,7 +586,7 @@ void BeginTextureMode(RenderTexture2D target); // Initializes rende
|
||||||
void EndTextureMode(void); // Ends drawing to render texture
|
void EndTextureMode(void); // Ends drawing to render texture
|
||||||
|
|
||||||
Ray GetMouseRay(Vector2 mousePosition, Camera camera); // Returns a ray trace from mouse position
|
Ray GetMouseRay(Vector2 mousePosition, Camera camera); // Returns a ray trace from mouse position
|
||||||
Vector2 WorldToScreen(Vector3 position, Camera camera); // Returns the screen space position from a 3d world space position
|
Vector2 GetWorldToScreen(Vector3 position, Camera camera); // Returns the screen space position from a 3d world space position
|
||||||
Matrix GetCameraMatrix(Camera camera); // Returns camera transform matrix (view matrix)
|
Matrix GetCameraMatrix(Camera camera); // Returns camera transform matrix (view matrix)
|
||||||
|
|
||||||
void SetTargetFPS(int fps); // Set target FPS (maximum)
|
void SetTargetFPS(int fps); // Set target FPS (maximum)
|
||||||
|
@ -882,7 +882,7 @@ void UnloadSound(Sound sound); // Unload sound
|
||||||
void PlaySound(Sound sound); // Play a sound
|
void PlaySound(Sound sound); // Play a sound
|
||||||
void PauseSound(Sound sound); // Pause a sound
|
void PauseSound(Sound sound); // Pause a sound
|
||||||
void StopSound(Sound sound); // Stop playing a sound
|
void StopSound(Sound sound); // Stop playing a sound
|
||||||
bool SoundIsPlaying(Sound sound); // Check if a sound is currently playing
|
bool IsSoundPlaying(Sound sound); // Check if a sound is currently playing
|
||||||
void SetSoundVolume(Sound sound, float volume); // Set volume for a sound (1.0 is max level)
|
void SetSoundVolume(Sound sound, float volume); // Set volume for a sound (1.0 is max level)
|
||||||
void SetSoundPitch(Sound sound, float pitch); // Set pitch for a sound (1.0 is base level)
|
void SetSoundPitch(Sound sound, float pitch); // Set pitch for a sound (1.0 is base level)
|
||||||
|
|
||||||
|
@ -891,7 +891,7 @@ void UpdateMusicStream(void); // Updates buffe
|
||||||
void StopMusicStream(void); // Stop music playing (close stream)
|
void StopMusicStream(void); // Stop music playing (close stream)
|
||||||
void PauseMusicStream(void); // Pause music playing
|
void PauseMusicStream(void); // Pause music playing
|
||||||
void ResumeMusicStream(void); // Resume playing paused music
|
void ResumeMusicStream(void); // Resume playing paused music
|
||||||
bool MusicIsPlaying(void); // Check if music is playing
|
bool IsMusicPlaying(void); // Check if music is playing
|
||||||
void SetMusicVolume(float volume); // Set volume for music (1.0 is max level)
|
void SetMusicVolume(float volume); // Set volume for music (1.0 is max level)
|
||||||
float GetMusicTimeLength(void); // Get current music time length (in seconds)
|
float GetMusicTimeLength(void); // Get current music time length (in seconds)
|
||||||
float GetMusicTimePlayed(void); // Get current music time played (in seconds)
|
float GetMusicTimePlayed(void); // Get current music time played (in seconds)
|
||||||
|
|
299
src/rlgl.c
299
src/rlgl.c
|
@ -196,23 +196,20 @@ static DrawMode currentDrawMode;
|
||||||
|
|
||||||
static float currentDepth = -1.0f;
|
static float currentDepth = -1.0f;
|
||||||
|
|
||||||
// Vertex arrays for lines, triangles and quads
|
// Default vertex buffers for lines, triangles and quads
|
||||||
static VertexPositionColorBuffer lines; // No texture support
|
static VertexPositionColorBuffer lines; // No texture support
|
||||||
static VertexPositionColorBuffer triangles; // No texture support
|
static VertexPositionColorBuffer triangles; // No texture support
|
||||||
static VertexPositionColorTextureIndexBuffer quads;
|
static VertexPositionColorTextureIndexBuffer quads;
|
||||||
|
|
||||||
// Shader Programs
|
// Default vertex buffers VAOs (if supported)
|
||||||
static Shader defaultShader;
|
|
||||||
static Shader currentShader; // By default, defaultShader
|
|
||||||
|
|
||||||
// Vertex Array Objects (VAO)
|
|
||||||
static GLuint vaoLines, vaoTriangles, vaoQuads;
|
static GLuint vaoLines, vaoTriangles, vaoQuads;
|
||||||
|
|
||||||
// Vertex Buffer Objects (VBO)
|
// Default vertex buffers VBOs
|
||||||
static GLuint linesBuffer[2];
|
static GLuint linesBuffer[2]; // Lines buffers (position, color)
|
||||||
static GLuint trianglesBuffer[2];
|
static GLuint trianglesBuffer[2]; // Triangles buffers (position, color)
|
||||||
static GLuint quadsBuffer[4];
|
static GLuint quadsBuffer[4]; // Quads buffers (position, texcoord, color, index)
|
||||||
|
|
||||||
|
// Default buffers draw calls
|
||||||
static DrawCall *draws;
|
static DrawCall *draws;
|
||||||
static int drawsCounter;
|
static int drawsCounter;
|
||||||
|
|
||||||
|
@ -221,11 +218,14 @@ static Vector3 *tempBuffer;
|
||||||
static int tempBufferCount = 0;
|
static int tempBufferCount = 0;
|
||||||
static bool useTempBuffer = false;
|
static bool useTempBuffer = false;
|
||||||
|
|
||||||
|
// Shader Programs
|
||||||
|
static Shader defaultShader;
|
||||||
|
static Shader currentShader; // By default, defaultShader
|
||||||
|
|
||||||
// Flags for supported extensions
|
// Flags for supported extensions
|
||||||
static bool vaoSupported = false; // VAO support (OpenGL ES2 could not support VAO extension)
|
static bool vaoSupported = false; // VAO support (OpenGL ES2 could not support VAO extension)
|
||||||
|
|
||||||
// Compressed textures support flags
|
// Compressed textures support flags
|
||||||
//static bool texCompDXTSupported = false; // DDS texture compression support
|
|
||||||
static bool texCompETC1Supported = false; // ETC1 texture compression support
|
static bool texCompETC1Supported = false; // ETC1 texture compression support
|
||||||
static bool texCompETC2Supported = false; // ETC2/EAC texture compression support
|
static bool texCompETC2Supported = false; // ETC2/EAC texture compression support
|
||||||
static bool texCompPVRTSupported = false; // PVR texture compression support
|
static bool texCompPVRTSupported = false; // PVR texture compression support
|
||||||
|
@ -233,8 +233,8 @@ static bool texCompASTCSupported = false; // ASTC texture compression support
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Compressed textures support flags
|
// Compressed textures support flags
|
||||||
static bool texCompDXTSupported = false; // DDS texture compression support
|
static bool texCompDXTSupported = false; // DDS texture compression support
|
||||||
static bool npotSupported = false; // NPOT textures full support
|
static bool npotSupported = false; // NPOT textures full support
|
||||||
|
|
||||||
#if defined(GRAPHICS_API_OPENGL_ES2)
|
#if defined(GRAPHICS_API_OPENGL_ES2)
|
||||||
// NOTE: VAO functionality is exposed through extensions (OES)
|
// NOTE: VAO functionality is exposed through extensions (OES)
|
||||||
|
@ -254,14 +254,17 @@ unsigned int whiteTexture;
|
||||||
// Module specific Functions Declaration
|
// Module specific Functions Declaration
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||||
|
static void LoadCompressedTexture(unsigned char *data, int width, int height, int mipmapCount, int compressedFormat);
|
||||||
|
|
||||||
static Shader LoadDefaultShader(void);
|
static Shader LoadDefaultShader(void);
|
||||||
static void LoadDefaultShaderLocations(Shader *shader);
|
static void LoadDefaultShaderLocations(Shader *shader);
|
||||||
static void InitializeBuffers(void);
|
static void UnloadDefaultShader(void);
|
||||||
static void InitializeBuffersGPU(void);
|
|
||||||
static void UpdateBuffers(void);
|
|
||||||
static char *TextFileRead(char *fn);
|
|
||||||
|
|
||||||
static void LoadCompressedTexture(unsigned char *data, int width, int height, int mipmapCount, int compressedFormat);
|
static void LoadDefaultBuffers(void);
|
||||||
|
static void UpdateDefaultBuffers(void);
|
||||||
|
static void UnloadDefaultBuffers(void);
|
||||||
|
|
||||||
|
static char *ReadTextFile(const char *fileName);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(GRAPHICS_API_OPENGL_11)
|
#if defined(GRAPHICS_API_OPENGL_11)
|
||||||
|
@ -274,20 +277,6 @@ static void TraceLog(int msgType, const char *text, ...);
|
||||||
float *MatrixToFloat(Matrix mat); // Converts Matrix to float array
|
float *MatrixToFloat(Matrix mat); // Converts Matrix to float array
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(GRAPHICS_API_OPENGL_ES2)
|
|
||||||
// NOTE: strdup() functions replacement (not C99, POSIX function, not available on emscripten)
|
|
||||||
// Duplicates a string, returning an identical malloc'd string
|
|
||||||
char *mystrdup(const char *str)
|
|
||||||
{
|
|
||||||
size_t len = strlen(str) + 1;
|
|
||||||
void *newstr = malloc(len);
|
|
||||||
|
|
||||||
if (newstr == NULL) return NULL;
|
|
||||||
|
|
||||||
return (char *)memcpy(newstr, str, len);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Module Functions Definition - Matrix operations
|
// Module Functions Definition - Matrix operations
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
@ -919,13 +908,18 @@ void rlglInit(void)
|
||||||
|
|
||||||
// NOTE: We have to duplicate string because glGetString() returns a const value
|
// NOTE: We have to duplicate string because glGetString() returns a const value
|
||||||
// If not duplicated, it fails in some systems (Raspberry Pi)
|
// If not duplicated, it fails in some systems (Raspberry Pi)
|
||||||
char *extensionsDup = mystrdup(extensions);
|
// Equivalent to function: char *strdup(const char *str)
|
||||||
|
char *extensionsDup;
|
||||||
|
size_t len = strlen(extensions) + 1;
|
||||||
|
void *newstr = malloc(len);
|
||||||
|
if (newstr == NULL) extensionsDup = NULL;
|
||||||
|
extensionsDup = (char *)memcpy(newstr, extensions, len);
|
||||||
|
|
||||||
// NOTE: String could be splitted using strtok() function (string.h)
|
// NOTE: String could be splitted using strtok() function (string.h)
|
||||||
// NOTE: strtok() modifies the received string, it can not be const
|
// NOTE: strtok() modifies the received string, it can not be const
|
||||||
|
|
||||||
char *extList[512]; // Allocate 512 strings pointers (2 KB)
|
char *extList[512]; // Allocate 512 strings pointers (2 KB)
|
||||||
|
|
||||||
extList[numExt] = strtok(extensionsDup, " ");
|
extList[numExt] = strtok(extensionsDup, " ");
|
||||||
|
|
||||||
while (extList[numExt] != NULL)
|
while (extList[numExt] != NULL)
|
||||||
|
@ -1024,12 +1018,9 @@ void rlglInit(void)
|
||||||
|
|
||||||
// Init default Shader (customized for GL 3.3 and ES2)
|
// Init default Shader (customized for GL 3.3 and ES2)
|
||||||
defaultShader = LoadDefaultShader();
|
defaultShader = LoadDefaultShader();
|
||||||
//customShader = LoadShader("custom.vs", "custom.fs"); // Works ok
|
|
||||||
|
|
||||||
currentShader = defaultShader;
|
currentShader = defaultShader;
|
||||||
|
|
||||||
InitializeBuffers(); // Init vertex arrays
|
LoadDefaultBuffers(); // Initialize default vertex arrays buffers (lines, triangles, quads)
|
||||||
InitializeBuffersGPU(); // Init VBO and VAO
|
|
||||||
|
|
||||||
// Init temp vertex buffer, used when transformation required (translate, rotate, scale)
|
// Init temp vertex buffer, used when transformation required (translate, rotate, scale)
|
||||||
tempBuffer = (Vector3 *)malloc(sizeof(Vector3)*TEMP_VERTEX_BUFFER_SIZE);
|
tempBuffer = (Vector3 *)malloc(sizeof(Vector3)*TEMP_VERTEX_BUFFER_SIZE);
|
||||||
|
@ -1054,54 +1045,10 @@ void rlglInit(void)
|
||||||
void rlglClose(void)
|
void rlglClose(void)
|
||||||
{
|
{
|
||||||
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||||
// Unbind everything
|
UnloadDefaultShader();
|
||||||
if (vaoSupported) glBindVertexArray(0);
|
UnloadDefaultBuffers();
|
||||||
glDisableVertexAttribArray(0);
|
|
||||||
glDisableVertexAttribArray(1);
|
// Delete default white texture
|
||||||
glDisableVertexAttribArray(2);
|
|
||||||
glDisableVertexAttribArray(3);
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
|
||||||
|
|
||||||
glUseProgram(0);
|
|
||||||
|
|
||||||
// Delete VBOs
|
|
||||||
glDeleteBuffers(1, &linesBuffer[0]);
|
|
||||||
glDeleteBuffers(1, &linesBuffer[1]);
|
|
||||||
glDeleteBuffers(1, &trianglesBuffer[0]);
|
|
||||||
glDeleteBuffers(1, &trianglesBuffer[1]);
|
|
||||||
glDeleteBuffers(1, &quadsBuffer[0]);
|
|
||||||
glDeleteBuffers(1, &quadsBuffer[1]);
|
|
||||||
glDeleteBuffers(1, &quadsBuffer[2]);
|
|
||||||
glDeleteBuffers(1, &quadsBuffer[3]);
|
|
||||||
|
|
||||||
if (vaoSupported)
|
|
||||||
{
|
|
||||||
// Delete VAOs
|
|
||||||
glDeleteVertexArrays(1, &vaoLines);
|
|
||||||
glDeleteVertexArrays(1, &vaoTriangles);
|
|
||||||
glDeleteVertexArrays(1, &vaoQuads);
|
|
||||||
}
|
|
||||||
|
|
||||||
//glDetachShader(defaultShaderProgram, vertexShader);
|
|
||||||
//glDetachShader(defaultShaderProgram, fragmentShader);
|
|
||||||
//glDeleteShader(vertexShader); // Already deleted on shader compilation
|
|
||||||
//glDeleteShader(fragmentShader); // Already deleted on sahder compilation
|
|
||||||
glDeleteProgram(defaultShader.id);
|
|
||||||
|
|
||||||
// Free vertex arrays memory
|
|
||||||
free(lines.vertices);
|
|
||||||
free(lines.colors);
|
|
||||||
|
|
||||||
free(triangles.vertices);
|
|
||||||
free(triangles.colors);
|
|
||||||
|
|
||||||
free(quads.vertices);
|
|
||||||
free(quads.texcoords);
|
|
||||||
free(quads.colors);
|
|
||||||
free(quads.indices);
|
|
||||||
|
|
||||||
// Free GPU texture
|
|
||||||
glDeleteTextures(1, &whiteTexture);
|
glDeleteTextures(1, &whiteTexture);
|
||||||
TraceLog(INFO, "[TEX ID %i] Unloaded texture data (base white texture) from VRAM", whiteTexture);
|
TraceLog(INFO, "[TEX ID %i] Unloaded texture data (base white texture) from VRAM", whiteTexture);
|
||||||
|
|
||||||
|
@ -1113,7 +1060,7 @@ void rlglClose(void)
|
||||||
void rlglDraw(void)
|
void rlglDraw(void)
|
||||||
{
|
{
|
||||||
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||||
UpdateBuffers();
|
UpdateDefaultBuffers();
|
||||||
|
|
||||||
if ((lines.vCounter > 0) || (triangles.vCounter > 0) || (quads.vCounter > 0))
|
if ((lines.vCounter > 0) || (triangles.vCounter > 0) || (quads.vCounter > 0))
|
||||||
{
|
{
|
||||||
|
@ -1846,7 +1793,9 @@ void rlglGenerateMipmaps(Texture2D texture)
|
||||||
// NOTE: Once mipmaps have been generated and data has been uploaded to GPU VRAM, we can discard RAM data
|
// NOTE: Once mipmaps have been generated and data has been uploaded to GPU VRAM, we can discard RAM data
|
||||||
free(data);
|
free(data);
|
||||||
|
|
||||||
#elif defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
#endif
|
||||||
|
|
||||||
|
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||||
glGenerateMipmap(GL_TEXTURE_2D); // Generate mipmaps automatically
|
glGenerateMipmap(GL_TEXTURE_2D); // Generate mipmaps automatically
|
||||||
TraceLog(INFO, "[TEX ID %i] Mipmaps generated automatically", texture.id);
|
TraceLog(INFO, "[TEX ID %i] Mipmaps generated automatically", texture.id);
|
||||||
|
|
||||||
|
@ -2116,8 +2065,8 @@ Shader LoadShader(char *vsFileName, char *fsFileName)
|
||||||
|
|
||||||
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||||
// Shaders loading from external text file
|
// Shaders loading from external text file
|
||||||
char *vShaderStr = TextFileRead(vsFileName);
|
char *vShaderStr = ReadTextFile(vsFileName);
|
||||||
char *fShaderStr = TextFileRead(fsFileName);
|
char *fShaderStr = ReadTextFile(fsFileName);
|
||||||
|
|
||||||
if ((vShaderStr != NULL) && (fShaderStr != NULL))
|
if ((vShaderStr != NULL) && (fShaderStr != NULL))
|
||||||
{
|
{
|
||||||
|
@ -2418,7 +2367,7 @@ static void LoadCompressedTexture(unsigned char *data, int width, int height, in
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load Shader (Vertex and Fragment)
|
// Load default shader (Vertex and Fragment)
|
||||||
// NOTE: This shader program is used for batch buffers (lines, triangles, quads)
|
// NOTE: This shader program is used for batch buffers (lines, triangles, quads)
|
||||||
static Shader LoadDefaultShader(void)
|
static Shader LoadDefaultShader(void)
|
||||||
{
|
{
|
||||||
|
@ -2503,43 +2452,24 @@ static void LoadDefaultShaderLocations(Shader *shader)
|
||||||
shader->mapSpecularLoc = glGetUniformLocation(shader->id, "texture2");
|
shader->mapSpecularLoc = glGetUniformLocation(shader->id, "texture2");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read text file
|
// Unload default shader
|
||||||
// NOTE: text chars array should be freed manually
|
static void UnloadDefaultShader(void)
|
||||||
static char *TextFileRead(char *fileName)
|
|
||||||
{
|
{
|
||||||
FILE *textFile;
|
glUseProgram(0);
|
||||||
char *text = NULL;
|
|
||||||
|
|
||||||
int count = 0;
|
//glDetachShader(defaultShaderProgram, vertexShader);
|
||||||
|
//glDetachShader(defaultShaderProgram, fragmentShader);
|
||||||
if (fileName != NULL)
|
//glDeleteShader(vertexShader); // Already deleted on shader compilation
|
||||||
{
|
//glDeleteShader(fragmentShader); // Already deleted on sahder compilation
|
||||||
textFile = fopen(fileName,"rt");
|
glDeleteProgram(defaultShader.id);
|
||||||
|
|
||||||
if (textFile != NULL)
|
|
||||||
{
|
|
||||||
fseek(textFile, 0, SEEK_END);
|
|
||||||
count = ftell(textFile);
|
|
||||||
rewind(textFile);
|
|
||||||
|
|
||||||
if (count > 0)
|
|
||||||
{
|
|
||||||
text = (char *)malloc(sizeof(char)*(count + 1));
|
|
||||||
count = fread(text, sizeof(char), count, textFile);
|
|
||||||
text[count] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(textFile);
|
|
||||||
}
|
|
||||||
else TraceLog(WARNING, "[%s] Text file could not be opened", fileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
return text;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocate and initialize float array buffers to store vertex data (lines, triangles, quads)
|
// Load default internal buffers (lines, triangles, quads)
|
||||||
static void InitializeBuffers(void)
|
static void LoadDefaultBuffers(void)
|
||||||
{
|
{
|
||||||
|
// [CPU] Allocate and initialize float array buffers to store vertex data (lines, triangles, quads)
|
||||||
|
//--------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Initialize lines arrays (vertex position and color data)
|
// Initialize lines arrays (vertex position and color data)
|
||||||
lines.vertices = (float *)malloc(sizeof(float)*3*2*MAX_LINES_BATCH); // 3 float by vertex, 2 vertex by line
|
lines.vertices = (float *)malloc(sizeof(float)*3*2*MAX_LINES_BATCH); // 3 float by vertex, 2 vertex by line
|
||||||
lines.colors = (unsigned char *)malloc(sizeof(unsigned char)*4*2*MAX_LINES_BATCH); // 4 float by color, 2 colors by line
|
lines.colors = (unsigned char *)malloc(sizeof(unsigned char)*4*2*MAX_LINES_BATCH); // 4 float by color, 2 colors by line
|
||||||
|
@ -2593,13 +2523,14 @@ static void InitializeBuffers(void)
|
||||||
quads.tcCounter = 0;
|
quads.tcCounter = 0;
|
||||||
quads.cCounter = 0;
|
quads.cCounter = 0;
|
||||||
|
|
||||||
TraceLog(INFO, "CPU buffers (lines, triangles, quads) initialized successfully");
|
TraceLog(INFO, "Default buffers initialized successfully in CPU (lines, triangles, quads)");
|
||||||
}
|
//--------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Initialize Vertex Array Objects (Contain VBO)
|
// [GPU] Upload vertex data and initialize VAOs/VBOs (lines, triangles, quads)
|
||||||
// NOTE: lines, triangles and quads buffers use currentShader
|
// NOTE: Default buffers are linked to use currentShader (defaultShader)
|
||||||
static void InitializeBuffersGPU(void)
|
//--------------------------------------------------------------------------------------------
|
||||||
{
|
|
||||||
|
// Upload and link lines vertex buffers
|
||||||
if (vaoSupported)
|
if (vaoSupported)
|
||||||
{
|
{
|
||||||
// Initialize Lines VAO
|
// Initialize Lines VAO
|
||||||
|
@ -2622,10 +2553,10 @@ static void InitializeBuffersGPU(void)
|
||||||
glEnableVertexAttribArray(currentShader.colorLoc);
|
glEnableVertexAttribArray(currentShader.colorLoc);
|
||||||
glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
|
glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
|
||||||
|
|
||||||
if (vaoSupported) TraceLog(INFO, "[VAO ID %i] Lines VAO initialized successfully", vaoLines);
|
if (vaoSupported) TraceLog(INFO, "[VAO ID %i] Default buffers (lines) VAO initialized successfully", vaoLines);
|
||||||
else TraceLog(INFO, "[VBO ID %i][VBO ID %i] Lines VBOs initialized successfully", linesBuffer[0], linesBuffer[1]);
|
else TraceLog(INFO, "[VBO ID %i][VBO ID %i] Default buffers (lines) VBOs initialized successfully", linesBuffer[0], linesBuffer[1]);
|
||||||
//--------------------------------------------------------------
|
|
||||||
|
|
||||||
|
// Upload and link triangles vertex buffers
|
||||||
if (vaoSupported)
|
if (vaoSupported)
|
||||||
{
|
{
|
||||||
// Initialize Triangles VAO
|
// Initialize Triangles VAO
|
||||||
|
@ -2647,10 +2578,10 @@ static void InitializeBuffersGPU(void)
|
||||||
glEnableVertexAttribArray(currentShader.colorLoc);
|
glEnableVertexAttribArray(currentShader.colorLoc);
|
||||||
glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
|
glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0);
|
||||||
|
|
||||||
if (vaoSupported) TraceLog(INFO, "[VAO ID %i] Triangles VAO initialized successfully", vaoTriangles);
|
if (vaoSupported) TraceLog(INFO, "[VAO ID %i] Default buffers (triangles) VAO initialized successfully", vaoTriangles);
|
||||||
else TraceLog(INFO, "[VBO ID %i][VBO ID %i] Triangles VBOs initialized successfully", trianglesBuffer[0], trianglesBuffer[1]);
|
else TraceLog(INFO, "[VBO ID %i][VBO ID %i] Default buffers (triangles) VBOs initialized successfully", trianglesBuffer[0], trianglesBuffer[1]);
|
||||||
//--------------------------------------------------------------
|
|
||||||
|
|
||||||
|
// Upload and link quads vertex buffers
|
||||||
if (vaoSupported)
|
if (vaoSupported)
|
||||||
{
|
{
|
||||||
// Initialize Quads VAO
|
// Initialize Quads VAO
|
||||||
|
@ -2685,18 +2616,20 @@ static void InitializeBuffersGPU(void)
|
||||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(short)*6*MAX_QUADS_BATCH, quads.indices, GL_STATIC_DRAW);
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(short)*6*MAX_QUADS_BATCH, quads.indices, GL_STATIC_DRAW);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (vaoSupported) TraceLog(INFO, "[VAO ID %i] Quads VAO initialized successfully", vaoQuads);
|
if (vaoSupported) TraceLog(INFO, "[VAO ID %i] Default buffers (quads) VAO initialized successfully", vaoQuads);
|
||||||
else TraceLog(INFO, "[VBO ID %i][VBO ID %i][VBO ID %i][VBO ID %i] Quads VBOs initialized successfully", quadsBuffer[0], quadsBuffer[1], quadsBuffer[2], quadsBuffer[3]);
|
else TraceLog(INFO, "[VBO ID %i][VBO ID %i][VBO ID %i][VBO ID %i] Default buffers (quads) VBOs initialized successfully", quadsBuffer[0], quadsBuffer[1], quadsBuffer[2], quadsBuffer[3]);
|
||||||
|
|
||||||
// Unbind the current VAO
|
// Unbind the current VAO
|
||||||
if (vaoSupported) glBindVertexArray(0);
|
if (vaoSupported) glBindVertexArray(0);
|
||||||
|
//--------------------------------------------------------------------------------------------
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update VBOs with vertex array data
|
// Update default buffers (VAOs/VBOs) with vertex array data
|
||||||
// NOTE: If there is not vertex data, buffers doesn't need to be updated (vertexCount > 0)
|
// 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 (change flag required)
|
// TODO: If no data changed on the CPU arrays --> No need to re-update GPU arrays (change flag required)
|
||||||
static void UpdateBuffers(void)
|
static void UpdateDefaultBuffers(void)
|
||||||
{
|
{
|
||||||
|
// Update lines vertex buffers
|
||||||
if (lines.vCounter > 0)
|
if (lines.vCounter > 0)
|
||||||
{
|
{
|
||||||
// Activate Lines VAO
|
// Activate Lines VAO
|
||||||
|
@ -2712,8 +2645,8 @@ static void UpdateBuffers(void)
|
||||||
//glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*2*MAX_LINES_BATCH, lines.colors, GL_DYNAMIC_DRAW);
|
//glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*2*MAX_LINES_BATCH, lines.colors, GL_DYNAMIC_DRAW);
|
||||||
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(unsigned char)*4*lines.cCounter, lines.colors);
|
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(unsigned char)*4*lines.cCounter, lines.colors);
|
||||||
}
|
}
|
||||||
//--------------------------------------------------------------
|
|
||||||
|
|
||||||
|
// Update triangles vertex buffers
|
||||||
if (triangles.vCounter > 0)
|
if (triangles.vCounter > 0)
|
||||||
{
|
{
|
||||||
// Activate Triangles VAO
|
// Activate Triangles VAO
|
||||||
|
@ -2729,8 +2662,8 @@ static void UpdateBuffers(void)
|
||||||
//glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*3*MAX_TRIANGLES_BATCH, triangles.colors, GL_DYNAMIC_DRAW);
|
//glBufferData(GL_ARRAY_BUFFER, sizeof(float)*4*3*MAX_TRIANGLES_BATCH, triangles.colors, GL_DYNAMIC_DRAW);
|
||||||
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(unsigned char)*4*triangles.cCounter, triangles.colors);
|
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(unsigned char)*4*triangles.cCounter, triangles.colors);
|
||||||
}
|
}
|
||||||
//--------------------------------------------------------------
|
|
||||||
|
|
||||||
|
// Update quads vertex buffers
|
||||||
if (quads.vCounter > 0)
|
if (quads.vCounter > 0)
|
||||||
{
|
{
|
||||||
// Activate Quads VAO
|
// Activate Quads VAO
|
||||||
|
@ -2752,7 +2685,7 @@ static void UpdateBuffers(void)
|
||||||
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(unsigned char)*4*quads.vCounter, quads.colors);
|
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(unsigned char)*4*quads.vCounter, quads.colors);
|
||||||
|
|
||||||
// Another option would be using buffer mapping...
|
// Another option would be using buffer mapping...
|
||||||
//triangles.vertices = glMapBuffer(GL_ARRAY_BUFFER, GL_READ_WRITE);
|
//quads.vertices = glMapBuffer(GL_ARRAY_BUFFER, GL_READ_WRITE);
|
||||||
// Now we can modify vertices
|
// Now we can modify vertices
|
||||||
//glUnmapBuffer(GL_ARRAY_BUFFER);
|
//glUnmapBuffer(GL_ARRAY_BUFFER);
|
||||||
}
|
}
|
||||||
|
@ -2761,6 +2694,83 @@ static void UpdateBuffers(void)
|
||||||
// Unbind the current VAO
|
// Unbind the current VAO
|
||||||
if (vaoSupported) glBindVertexArray(0);
|
if (vaoSupported) glBindVertexArray(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Unload default buffers vertex data from CPU and GPU
|
||||||
|
static void UnloadDefaultBuffers(void)
|
||||||
|
{
|
||||||
|
// Unbind everything
|
||||||
|
if (vaoSupported) glBindVertexArray(0);
|
||||||
|
glDisableVertexAttribArray(0);
|
||||||
|
glDisableVertexAttribArray(1);
|
||||||
|
glDisableVertexAttribArray(2);
|
||||||
|
glDisableVertexAttribArray(3);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||||
|
|
||||||
|
// Delete VBOs from GPU (VRAM)
|
||||||
|
glDeleteBuffers(1, &linesBuffer[0]);
|
||||||
|
glDeleteBuffers(1, &linesBuffer[1]);
|
||||||
|
glDeleteBuffers(1, &trianglesBuffer[0]);
|
||||||
|
glDeleteBuffers(1, &trianglesBuffer[1]);
|
||||||
|
glDeleteBuffers(1, &quadsBuffer[0]);
|
||||||
|
glDeleteBuffers(1, &quadsBuffer[1]);
|
||||||
|
glDeleteBuffers(1, &quadsBuffer[2]);
|
||||||
|
glDeleteBuffers(1, &quadsBuffer[3]);
|
||||||
|
|
||||||
|
if (vaoSupported)
|
||||||
|
{
|
||||||
|
// Delete VAOs from GPU (VRAM)
|
||||||
|
glDeleteVertexArrays(1, &vaoLines);
|
||||||
|
glDeleteVertexArrays(1, &vaoTriangles);
|
||||||
|
glDeleteVertexArrays(1, &vaoQuads);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Free vertex arrays memory from CPU (RAM)
|
||||||
|
free(lines.vertices);
|
||||||
|
free(lines.colors);
|
||||||
|
|
||||||
|
free(triangles.vertices);
|
||||||
|
free(triangles.colors);
|
||||||
|
|
||||||
|
free(quads.vertices);
|
||||||
|
free(quads.texcoords);
|
||||||
|
free(quads.colors);
|
||||||
|
free(quads.indices);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read text data from file
|
||||||
|
// NOTE: text chars array should be freed manually
|
||||||
|
static char *ReadTextFile(const char *fileName)
|
||||||
|
{
|
||||||
|
FILE *textFile;
|
||||||
|
char *text = NULL;
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
if (fileName != NULL)
|
||||||
|
{
|
||||||
|
textFile = fopen(fileName,"rt");
|
||||||
|
|
||||||
|
if (textFile != NULL)
|
||||||
|
{
|
||||||
|
fseek(textFile, 0, SEEK_END);
|
||||||
|
count = ftell(textFile);
|
||||||
|
rewind(textFile);
|
||||||
|
|
||||||
|
if (count > 0)
|
||||||
|
{
|
||||||
|
text = (char *)malloc(sizeof(char)*(count + 1));
|
||||||
|
count = fread(text, sizeof(char), count, textFile);
|
||||||
|
text[count] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(textFile);
|
||||||
|
}
|
||||||
|
else TraceLog(WARNING, "[%s] Text file could not be opened", fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return text;
|
||||||
|
}
|
||||||
#endif //defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
#endif //defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||||
|
|
||||||
#if defined(GRAPHICS_API_OPENGL_11)
|
#if defined(GRAPHICS_API_OPENGL_11)
|
||||||
|
@ -2891,7 +2901,6 @@ static Color *GenNextMipmap(Color *srcData, int srcWidth, int srcHeight)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(RLGL_STANDALONE)
|
#if defined(RLGL_STANDALONE)
|
||||||
|
|
||||||
// Output a trace log message
|
// Output a trace log message
|
||||||
// NOTE: Expected msgType: (0)Info, (1)Error, (2)Warning
|
// NOTE: Expected msgType: (0)Info, (1)Error, (2)Warning
|
||||||
static void TraceLog(int msgType, const char *text, ...)
|
static void TraceLog(int msgType, const char *text, ...)
|
||||||
|
|
16
src/rlgl.h
16
src/rlgl.h
|
@ -292,11 +292,6 @@ Vector3 rlglUnproject(Vector3 source, Matrix proj, Matrix view); // Get world
|
||||||
unsigned char *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(Texture2D texture); // Read texture pixel data
|
void *rlglReadTexturePixels(Texture2D texture); // Read texture pixel data
|
||||||
|
|
||||||
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
|
||||||
void PrintProjectionMatrix(void); // DEBUG: Print projection matrix
|
|
||||||
void PrintModelviewMatrix(void); // DEBUG: Print modelview matrix
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(RLGL_STANDALONE)
|
#if defined(RLGL_STANDALONE)
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
// Shaders System Functions (Module: rlgl)
|
// Shaders System Functions (Module: rlgl)
|
||||||
|
@ -309,13 +304,10 @@ void SetCustomShader(Shader shader); // Set custo
|
||||||
void SetDefaultShader(void); // Set default 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
|
void SetModelShader(Model *model, Shader shader); // Link a shader to a model
|
||||||
|
|
||||||
int GetShaderLocation(Shader shader, const char *uniformName); // Get shader uniform location
|
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 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 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 SetShaderValueMatrix(Shader shader, int uniformLoc, Matrix mat); // Set shader uniform value (matrix 4x4)
|
||||||
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
|
|
||||||
|
|
||||||
void SetBlendMode(int mode); // Set blending mode (alpha, additive, multiplied)
|
void SetBlendMode(int mode); // Set blending mode (alpha, additive, multiplied)
|
||||||
#endif
|
#endif
|
||||||
|
|
98
src/text.c
98
src/text.c
|
@ -69,8 +69,7 @@ static SpriteFont defaultFont; // Default font provided by raylib
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Module specific Functions Declaration
|
// Module specific Functions Declaration
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
static bool PixelIsMagenta(Color p); // Check if a pixel is magenta
|
static SpriteFont LoadImageFont(Image image, Color key, int firstChar); // Load a Image font file (XNA style)
|
||||||
static int ParseImageData(Image image, int **charValues, Rectangle **charSet); // Parse image pixel data to obtain characters data
|
|
||||||
static SpriteFont LoadRBMF(const char *fileName); // Load a rBMF font file (raylib BitMap Font)
|
static SpriteFont LoadRBMF(const char *fileName); // Load a rBMF font file (raylib BitMap Font)
|
||||||
static SpriteFont LoadBMFont(const char *fileName); // Load a BMFont file (AngelCode font file)
|
static SpriteFont LoadBMFont(const char *fileName); // Load a BMFont file (AngelCode font file)
|
||||||
static SpriteFont LoadTTF(const char *fileName, int fontSize); // Generate a sprite font image from TTF data (font size required)
|
static SpriteFont LoadTTF(const char *fileName, int fontSize); // Generate a sprite font image from TTF data (font size required)
|
||||||
|
@ -210,7 +209,7 @@ extern void LoadDefaultFont(void)
|
||||||
if (testPosX >= defaultFont.texture.width)
|
if (testPosX >= defaultFont.texture.width)
|
||||||
{
|
{
|
||||||
currentLine++;
|
currentLine++;
|
||||||
currentPosX = 2 * charsDivisor + charsWidth[i];
|
currentPosX = 2*charsDivisor + charsWidth[i];
|
||||||
testPosX = currentPosX;
|
testPosX = currentPosX;
|
||||||
|
|
||||||
defaultFont.charRecs[i].x = charsDivisor;
|
defaultFont.charRecs[i].x = charsDivisor;
|
||||||
|
@ -246,7 +245,7 @@ SpriteFont GetDefaultFont()
|
||||||
// Load a SpriteFont image into GPU memory
|
// Load a SpriteFont image into GPU memory
|
||||||
SpriteFont LoadSpriteFont(const char *fileName)
|
SpriteFont LoadSpriteFont(const char *fileName)
|
||||||
{
|
{
|
||||||
SpriteFont spriteFont;
|
SpriteFont spriteFont = { 0 };
|
||||||
|
|
||||||
// Check file extension
|
// Check file extension
|
||||||
if (strcmp(GetExtension(fileName),"rbmf") == 0) spriteFont = LoadRBMF(fileName);
|
if (strcmp(GetExtension(fileName),"rbmf") == 0) spriteFont = LoadRBMF(fileName);
|
||||||
|
@ -255,36 +254,7 @@ SpriteFont LoadSpriteFont(const char *fileName)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Image image = LoadImage(fileName);
|
Image image = LoadImage(fileName);
|
||||||
|
if (image.data != NULL) spriteFont = LoadImageFont(image, MAGENTA, 32);
|
||||||
if (image.data != NULL)
|
|
||||||
{
|
|
||||||
// Process bitmap font pixel data to get characters measures
|
|
||||||
// spriteFont chars data is filled inside the function and memory is allocated!
|
|
||||||
int numChars = ParseImageData(image, &spriteFont.charValues, &spriteFont.charRecs);
|
|
||||||
|
|
||||||
TraceLog(DEBUG, "[%s] SpriteFont data parsed correctly", fileName);
|
|
||||||
TraceLog(DEBUG, "[%s] SpriteFont num chars detected: %i", fileName, numChars);
|
|
||||||
|
|
||||||
spriteFont.numChars = numChars;
|
|
||||||
spriteFont.texture = LoadTextureFromImage(image); // Convert loaded image to OpenGL texture
|
|
||||||
spriteFont.size = spriteFont.charRecs[0].height;
|
|
||||||
|
|
||||||
spriteFont.charOffsets = (Vector2 *)malloc(spriteFont.numChars*sizeof(Vector2));
|
|
||||||
spriteFont.charAdvanceX = (int *)malloc(spriteFont.numChars*sizeof(int));
|
|
||||||
|
|
||||||
for (int i = 0; i < spriteFont.numChars; i++)
|
|
||||||
{
|
|
||||||
// NOTE: On image based fonts (XNA style), character offsets and xAdvance are not required (set to 0)
|
|
||||||
spriteFont.charOffsets[i] = (Vector2){ 0.0f, 0.0f };
|
|
||||||
spriteFont.charAdvanceX[i] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TraceLog(WARNING, "[%s] SpriteFont could not be loaded, using default font", fileName);
|
|
||||||
spriteFont = GetDefaultFont();
|
|
||||||
}
|
|
||||||
|
|
||||||
UnloadImage(image);
|
UnloadImage(image);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -309,7 +279,7 @@ void UnloadSpriteFont(SpriteFont spriteFont)
|
||||||
free(spriteFont.charOffsets);
|
free(spriteFont.charOffsets);
|
||||||
free(spriteFont.charAdvanceX);
|
free(spriteFont.charAdvanceX);
|
||||||
|
|
||||||
TraceLog(INFO, "Unloaded sprite font data");
|
TraceLog(DEBUG, "Unloaded sprite font data");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -517,15 +487,11 @@ void DrawFPS(int posX, int posY)
|
||||||
// Module specific Functions Definition
|
// Module specific Functions Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Check if a pixel is magenta
|
// Load a Image font file (XNA style)
|
||||||
static bool PixelIsMagenta(Color p)
|
static SpriteFont LoadImageFont(Image image, Color key, int firstChar)
|
||||||
{
|
|
||||||
return ((p.r == 255) && (p.g == 0) && (p.b == 255) && (p.a == 255));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse image pixel data to obtain characters data (measures)
|
|
||||||
static int ParseImageData(Image image, int **charValues, Rectangle **charRecs)
|
|
||||||
{
|
{
|
||||||
|
#define COLOR_EQUAL(col1, col2) ((col1.r == col2.r)&&(col1.g == col2.g)&&(col1.b == col2.b)&&(col1.a == col2.a))
|
||||||
|
|
||||||
int charSpacing = 0;
|
int charSpacing = 0;
|
||||||
int lineSpacing = 0;
|
int lineSpacing = 0;
|
||||||
|
|
||||||
|
@ -539,13 +505,14 @@ static int ParseImageData(Image image, int **charValues, Rectangle **charRecs)
|
||||||
|
|
||||||
Color *pixels = GetImageData(image);
|
Color *pixels = GetImageData(image);
|
||||||
|
|
||||||
|
// Parse image data to get charSpacing and lineSpacing
|
||||||
for(y = 0; y < image.height; y++)
|
for(y = 0; y < image.height; y++)
|
||||||
{
|
{
|
||||||
for(x = 0; x < image.width; x++)
|
for(x = 0; x < image.width; x++)
|
||||||
{
|
{
|
||||||
if (!PixelIsMagenta(pixels[y*image.width + x])) break;
|
if (!COLOR_EQUAL(pixels[y*image.width + x], key)) break;
|
||||||
}
|
}
|
||||||
if (!PixelIsMagenta(pixels[y*image.width + x])) break;
|
if (!COLOR_EQUAL(pixels[y*image.width + x], key)) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
charSpacing = x;
|
charSpacing = x;
|
||||||
|
@ -554,7 +521,7 @@ static int ParseImageData(Image image, int **charValues, Rectangle **charRecs)
|
||||||
int charHeight = 0;
|
int charHeight = 0;
|
||||||
int j = 0;
|
int j = 0;
|
||||||
|
|
||||||
while(!PixelIsMagenta(pixels[(lineSpacing + j)*image.width + charSpacing])) j++;
|
while(!COLOR_EQUAL(pixels[(lineSpacing + j)*image.width + charSpacing], key)) j++;
|
||||||
|
|
||||||
charHeight = j;
|
charHeight = j;
|
||||||
|
|
||||||
|
@ -563,12 +530,13 @@ static int ParseImageData(Image image, int **charValues, Rectangle **charRecs)
|
||||||
int lineToRead = 0;
|
int lineToRead = 0;
|
||||||
int xPosToRead = charSpacing;
|
int xPosToRead = charSpacing;
|
||||||
|
|
||||||
|
// Parse image data to get rectangle sizes
|
||||||
while((lineSpacing + lineToRead * (charHeight + lineSpacing)) < image.height)
|
while((lineSpacing + lineToRead * (charHeight + lineSpacing)) < image.height)
|
||||||
{
|
{
|
||||||
while((xPosToRead < image.width) &&
|
while((xPosToRead < image.width) &&
|
||||||
!PixelIsMagenta((pixels[(lineSpacing + (charHeight+lineSpacing)*lineToRead)*image.width + xPosToRead])))
|
!COLOR_EQUAL((pixels[(lineSpacing + (charHeight+lineSpacing)*lineToRead)*image.width + xPosToRead]), key))
|
||||||
{
|
{
|
||||||
tempCharValues[index] = FONT_FIRST_CHAR + index;
|
tempCharValues[index] = firstChar + index;
|
||||||
|
|
||||||
tempCharRecs[index].x = xPosToRead;
|
tempCharRecs[index].x = xPosToRead;
|
||||||
tempCharRecs[index].y = lineSpacing + lineToRead * (charHeight + lineSpacing);
|
tempCharRecs[index].y = lineSpacing + lineToRead * (charHeight + lineSpacing);
|
||||||
|
@ -576,7 +544,7 @@ static int ParseImageData(Image image, int **charValues, Rectangle **charRecs)
|
||||||
|
|
||||||
int charWidth = 0;
|
int charWidth = 0;
|
||||||
|
|
||||||
while(!PixelIsMagenta(pixels[(lineSpacing + (charHeight+lineSpacing)*lineToRead)*image.width + xPosToRead + charWidth])) charWidth++;
|
while(!COLOR_EQUAL(pixels[(lineSpacing + (charHeight+lineSpacing)*lineToRead)*image.width + xPosToRead + charWidth], key)) charWidth++;
|
||||||
|
|
||||||
tempCharRecs[index].width = charWidth;
|
tempCharRecs[index].width = charWidth;
|
||||||
|
|
||||||
|
@ -590,20 +558,35 @@ static int ParseImageData(Image image, int **charValues, Rectangle **charRecs)
|
||||||
}
|
}
|
||||||
|
|
||||||
free(pixels);
|
free(pixels);
|
||||||
|
|
||||||
|
TraceLog(DEBUG, "SpriteFont data parsed correctly from image");
|
||||||
|
|
||||||
|
// Create spritefont with all data parsed from image
|
||||||
|
SpriteFont spriteFont = { 0 };
|
||||||
|
|
||||||
|
spriteFont.texture = LoadTextureFromImage(image); // Convert loaded image to OpenGL texture
|
||||||
|
spriteFont.numChars = index;
|
||||||
|
|
||||||
// We got tempCharValues and tempCharsRecs populated with chars data
|
// We got tempCharValues and tempCharsRecs populated with chars data
|
||||||
// Now we move temp data to sized charValues and charRecs arrays (passed as parameter to the function)
|
// Now we move temp data to sized charValues and charRecs arrays
|
||||||
// NOTE: This memory should be freed!
|
spriteFont.charRecs = (Rectangle *)malloc(spriteFont.numChars*sizeof(Rectangle));
|
||||||
(*charRecs) = (Rectangle *)malloc(index*sizeof(Rectangle));
|
spriteFont.charValues = (int *)malloc(spriteFont.numChars*sizeof(int));
|
||||||
(*charValues) = (int *)malloc(index*sizeof(int));
|
spriteFont.charOffsets = (Vector2 *)malloc(spriteFont.numChars*sizeof(Vector2));
|
||||||
|
spriteFont.charAdvanceX = (int *)malloc(spriteFont.numChars*sizeof(int));
|
||||||
|
|
||||||
for (int i = 0; i < index; i++)
|
for (int i = 0; i < spriteFont.numChars; i++)
|
||||||
{
|
{
|
||||||
(*charValues)[i] = tempCharValues[i];
|
spriteFont.charValues[i] = tempCharValues[i];
|
||||||
(*charRecs)[i] = tempCharRecs[i];
|
spriteFont.charRecs[i] = tempCharRecs[i];
|
||||||
|
|
||||||
|
// NOTE: On image based fonts (XNA style), character offsets and xAdvance are not required (set to 0)
|
||||||
|
spriteFont.charOffsets[i] = (Vector2){ 0.0f, 0.0f };
|
||||||
|
spriteFont.charAdvanceX[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
spriteFont.size = spriteFont.charRecs[0].height;
|
||||||
|
|
||||||
return index;
|
return spriteFont;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load a rBMF font file (raylib BitMap Font)
|
// Load a rBMF font file (raylib BitMap Font)
|
||||||
|
@ -687,6 +670,7 @@ static SpriteFont LoadRBMF(const char *fileName)
|
||||||
|
|
||||||
TraceLog(DEBUG, "[%s] Image reconstructed correctly, now converting it to texture", fileName);
|
TraceLog(DEBUG, "[%s] Image reconstructed correctly, now converting it to texture", fileName);
|
||||||
|
|
||||||
|
// Create spritefont with all data read from rbmf file
|
||||||
spriteFont.texture = LoadTextureFromImage(image);
|
spriteFont.texture = LoadTextureFromImage(image);
|
||||||
UnloadImage(image); // Unload image data
|
UnloadImage(image); // Unload image data
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue