From 5370fe18e08303afdffcb78b428b92e8205fbc76 Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 11 Jun 2017 23:58:46 +0200 Subject: Additional check for bool header definition --- src/raylib.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src/raylib.h') diff --git a/src/raylib.h b/src/raylib.h index 0b1a6b19..6d597fef 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -296,9 +296,8 @@ //---------------------------------------------------------------------------------- #ifndef __cplusplus // Boolean type - #if !defined(_STDBOOL_H) + #if !defined(_STDBOOL_H) || !defined(__STDBOOL_H) // CLang uses second form typedef enum { false, true } bool; - #define _STDBOOL_H #endif #endif -- cgit v1.2.3 From fcd13fd5d22219d8ed69b88e9cc1138b96b9a16d Mon Sep 17 00:00:00 2001 From: Wilhem Barbier Date: Wed, 28 Jun 2017 12:56:04 +0200 Subject: Add some functions to generate images Namely: - GenImageHorizontalV - GenImageHorizontalH - GenImageChecked - GenImageWhiteNoise - GenImageCellular The gradient implementation may be a bit naive, for example it doesn't do any gamma correction. --- examples/textures/textures_image_generation.c | 57 ++++++++++ src/raylib.h | 7 ++ src/textures.c | 144 +++++++++++++++++++++++++- 3 files changed, 207 insertions(+), 1 deletion(-) create mode 100644 examples/textures/textures_image_generation.c (limited to 'src/raylib.h') diff --git a/examples/textures/textures_image_generation.c b/examples/textures/textures_image_generation.c new file mode 100644 index 00000000..9db64ef7 --- /dev/null +++ b/examples/textures/textures_image_generation.c @@ -0,0 +1,57 @@ +/******************************************************************************************* +* +* raylib [textures] example - Procedural images generation +* +* This example has been created using raylib 1.7 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Copyright (c) 2O17 Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" + +#define TEXTURES_NUM 5 // for now we have 5 generation algorithms + +int main() +{ + int screenWidth = 800; + int screenHeight = 450; + + InitWindow(screenWidth, screenHeight, "raylib [textures] example - procedural images generation"); + + Image verticalGradient = GenImageGradientV(screenWidth, screenHeight, RED, BLUE); + Image horizontalGradient = GenImageGradientH(screenWidth, screenHeight, RED, BLUE); + Image checked = GenImageChecked(screenWidth, screenHeight, 32, 32, RED, BLUE); + Image whiteNoise = GenImageWhiteNoise(screenWidth, screenHeight, 0.5f); + Image cellular = GenImageCellular(screenWidth, screenHeight, 32); + + Texture2D textures[TEXTURES_NUM]; + textures[0] = LoadTextureFromImage(verticalGradient); + textures[1] = LoadTextureFromImage(horizontalGradient); + textures[2] = LoadTextureFromImage(checked); + textures[3] = LoadTextureFromImage(whiteNoise); + textures[4] = LoadTextureFromImage(cellular); + + int currentTexture = 0; + + while (!WindowShouldClose()) + { + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) + { + currentTexture = (currentTexture + 1) % TEXTURES_NUM; // cycle between the 5 textures + } + + BeginDrawing(); + ClearBackground(RAYWHITE); + DrawTexture(textures[currentTexture], 0, 0, WHITE); + EndDrawing(); + } + + for (int i = 0; i < TEXTURES_NUM; i++) // unload the textures + { + UnloadTexture(textures[i]); + } + + CloseWindow(); +} diff --git a/src/raylib.h b/src/raylib.h index 6d597fef..29cc5728 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -873,6 +873,13 @@ RLAPI void ImageColorGrayscale(Image *image); RLAPI void ImageColorContrast(Image *image, float contrast); // Modify image color: contrast (-100 to 100) RLAPI void ImageColorBrightness(Image *image, int brightness); // Modify image color: brightness (-255 to 255) +// Image generation functions +RLAPI Image GenImageGradientV(int width, int height, Color top, Color bottom); // Generate image: vertical gradient +RLAPI Image GenImageGradientH(int width, int height, Color left, Color right); // Generate image: horizontal gradient +RLAPI Image GenImageChecked(int width, int height, int checksX, int checksY, Color col1, Color col2); // Generate image: checked +RLAPI Image GenImageWhiteNoise(int width, int height, float factor); // Generate image: white noise +RLAPI Image GenImageCellular(int width, int height, int tileSize); // Generate image: cellular algorithm. Bigger tileSize means bigger cells + // Texture2D configuration functions RLAPI void GenTextureMipmaps(Texture2D *texture); // Generate GPU mipmaps for a texture RLAPI void SetTextureFilter(Texture2D texture, int filterMode); // Set texture scaling filter mode diff --git a/src/textures.c b/src/textures.c index d249d2be..99392516 100644 --- a/src/textures.c +++ b/src/textures.c @@ -1431,6 +1431,148 @@ void ImageColorBrightness(Image *image, int brightness) } #endif // SUPPORT_IMAGE_MANIPULATION +// Generate image: vertical gradient +Image GenImageGradientV(int width, int height, Color top, Color bottom) +{ + Color *pixels = (Color *)malloc(width*height*sizeof(Color)); + + for (int j = 0; j < height; j++) + { + float factor = (float)j / (float)height; + for (int i = 0; i < width; i++) + { + pixels[j*width + i].r = (int)((float)bottom.r * factor + (float)top.r * (1.f - factor)); + pixels[j*width + i].g = (int)((float)bottom.g * factor + (float)top.g * (1.f - factor)); + pixels[j*width + i].b = (int)((float)bottom.b * factor + (float)top.b * (1.f - factor)); + pixels[j*width + i].a = (int)((float)bottom.a * factor + (float)top.a * (1.f - factor)); + } + } + + Image image = LoadImageEx(pixels, width, height); + free(pixels); + + return image; +} + +// Generate image: horizontal gradient +Image GenImageGradientH(int width, int height, Color left, Color right) +{ + Color *pixels = (Color *)malloc(width*height*sizeof(Color)); + + for (int i = 0; i < width; i++) + { + float factor = (float)i / (float)width; + for (int j = 0; j < height; j++) + { + pixels[j*width + i].r = (int)((float)right.r * factor + (float)left.r * (1.f - factor)); + pixels[j*width + i].g = (int)((float)right.g * factor + (float)left.g * (1.f - factor)); + pixels[j*width + i].b = (int)((float)right.b * factor + (float)left.b * (1.f - factor)); + pixels[j*width + i].a = (int)((float)right.a * factor + (float)left.a * (1.f - factor)); + } + } + + Image image = LoadImageEx(pixels, width, height); + free(pixels); + + return image; +} + +// Generate image: checked +Image GenImageChecked(int width, int height, int checksX, int checksY, Color col1, Color col2) +{ + Color *pixels = (Color *)malloc(width*height*sizeof(Color)); + + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++) + { + if ((x/checksX + y/checksY) % 2 == 0) pixels[y*width + x] = col1; + else pixels[y*width + x] = col2; + } + } + + Image image = LoadImageEx(pixels, width, height); + free(pixels); + + return image; +} + +// Generate image: white noise +Image GenImageWhiteNoise(int width, int height, float factor) +{ + Color *pixels = (Color *)malloc(width*height*sizeof(Color)); + + for (int i = 0; i < width*height; i++) + { + if (GetRandomValue(0, 99) < (int)(factor * 100.f)) pixels[i] = WHITE; + else pixels[i] = BLACK; + } + + Image image = LoadImageEx(pixels, width, height); + free(pixels); + + return image; +} + +// Generate image: cellular algorithm. Bigger tileSize means bigger cells +Image GenImageCellular(int width, int height, int tileSize) +{ + Color *pixels = (Color*)malloc(width*height*sizeof(Color)); + + int seeds_per_row = width / tileSize; + int seeds_per_col = height / tileSize; + int seeds_count = seeds_per_row * seeds_per_col; + + Vector2* seeds = (Vector2*)malloc(seeds_count * sizeof(Vector2)); + + for (int i = 0; i < seeds_count; i++) + { + int y = (i / seeds_per_row) * tileSize + GetRandomValue(0, tileSize-1); + int x = (i % seeds_per_row) * tileSize + GetRandomValue(0, tileSize-1); + seeds[i] = (Vector2){x, y}; + } + + for (int y = 0; y < height; y++) + { + int tile_y = y / tileSize; + for (int x = 0; x < width; x++) + { + int tile_x = x / tileSize; + + float min_distance = strtod("Inf", NULL); + + // Check all adjacent tiles + for (int i = -1; i < 2; i++) + { + if (tile_x + i < 0 || tile_x + i >= seeds_per_row) continue; + + for (int j = -1; j < 2; j++) + { + if (tile_y + j < 0 || tile_y + j >= seeds_per_col) continue; + + Vector2 neighbor_seed = seeds[(tile_y+j) * seeds_per_row + tile_x+i]; + + float dist = hypot(x - (int)neighbor_seed.x, y - (int)neighbor_seed.y); + min_distance = fmin(min_distance, dist); + } + } + + // I made this up but it seems to give good results at all tile sizes + int intensity = (int)(min_distance * 256.f / tileSize); + if (intensity > 255) intensity = 255; + + Color c = {intensity, intensity, intensity, 255}; + pixels[y*width + x] = c; + } + } + free(seeds); + + Image image = LoadImageEx(pixels, width, height); + free(pixels); + + return image; +} + // Generate GPU mipmaps for a texture void GenTextureMipmaps(Texture2D *texture) { @@ -2250,4 +2392,4 @@ static Image LoadASTC(const char *fileName) return image; } -#endif \ No newline at end of file +#endif -- cgit v1.2.3 From 954757532a58113f36314cdf148e72dd1079e54a Mon Sep 17 00:00:00 2001 From: Wilhem Barbier Date: Wed, 28 Jun 2017 14:32:18 +0200 Subject: Add the SaveImageAs function --- src/raylib.h | 3 ++- src/textures.c | 12 ++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) (limited to 'src/raylib.h') diff --git a/src/raylib.h b/src/raylib.h index 29cc5728..ee0d8ccc 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -835,7 +835,7 @@ RLAPI bool CheckCollisionPointTriangle(Vector2 point, Vector2 p1, Vector2 p2, Ve // Texture Loading and Drawing Functions (Module: textures) //------------------------------------------------------------------------------------ -// Image/Texture2D data loading/unloading functions +// Image/Texture2D data loading/unloading/saving functions RLAPI Image LoadImage(const char *fileName); // Load image from file into CPU memory (RAM) RLAPI Image LoadImageEx(Color *pixels, int width, int height); // Load image from Color array data (RGBA - 32bit) RLAPI Image LoadImagePro(void *data, int width, int height, int format); // Load image from raw data with parameters @@ -849,6 +849,7 @@ RLAPI void UnloadRenderTexture(RenderTexture2D target); RLAPI Color *GetImageData(Image image); // Get pixel data from image as a Color struct array RLAPI Image GetTextureData(Texture2D texture); // Get pixel data from GPU texture and return an Image RLAPI void UpdateTexture(Texture2D texture, const void *pixels); // Update GPU texture with new data +RLAPI void SaveImageAs(Image image, const char *fileName); // Save image to a PNG file // Image manipulation functions RLAPI void ImageToPOT(Image *image, Color fillColor); // Convert image to POT (power-of-two) diff --git a/src/textures.c b/src/textures.c index 99392516..f1fcb12c 100644 --- a/src/textures.c +++ b/src/textures.c @@ -553,6 +553,18 @@ void UpdateTexture(Texture2D texture, const void *pixels) rlglUpdateTexture(texture.id, texture.width, texture.height, texture.format, pixels); } +// Save image to a PNG file +void SaveImageAs(Image image, const char *fileName) +{ +#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) + unsigned char* imgData = (unsigned char*)GetImageData(image); // this works since Color is just a container for the RGBA values + SavePNG(fileName, imgData, image.width, image.height, 4); + free(imgData); + + TraceLog(INFO, "Image saved: %s", fileName); +#endif +} + // Convert image data to desired format void ImageFormat(Image *image, int newFormat) { -- cgit v1.2.3 From a0ac8ee2c4ce14a23deedeccf9911977e119749d Mon Sep 17 00:00:00 2001 From: Wilhem Barbier Date: Wed, 28 Jun 2017 15:29:56 +0200 Subject: Add more image generation functions: radial gradient and perlin noise --- examples/textures/gen | Bin 0 -> 13112 bytes examples/textures/textures_image_generation.c | 12 +- src/external/stb_perlin.h | 316 ++++++++++++++++++++++++++ src/raylib.h | 2 + src/textures.c | 55 +++++ 5 files changed, 381 insertions(+), 4 deletions(-) create mode 100755 examples/textures/gen create mode 100644 src/external/stb_perlin.h (limited to 'src/raylib.h') diff --git a/examples/textures/gen b/examples/textures/gen new file mode 100755 index 00000000..a0f5bf61 Binary files /dev/null and b/examples/textures/gen differ diff --git a/examples/textures/textures_image_generation.c b/examples/textures/textures_image_generation.c index 9db64ef7..7525e8a2 100644 --- a/examples/textures/textures_image_generation.c +++ b/examples/textures/textures_image_generation.c @@ -11,7 +11,7 @@ #include "raylib.h" -#define TEXTURES_NUM 5 // for now we have 5 generation algorithms +#define TEXTURES_NUM 7 // for now we have 7 generation algorithms int main() { @@ -22,16 +22,20 @@ int main() Image verticalGradient = GenImageGradientV(screenWidth, screenHeight, RED, BLUE); Image horizontalGradient = GenImageGradientH(screenWidth, screenHeight, RED, BLUE); + Image radialGradient = GenImageRadialGradient(screenWidth, screenHeight, WHITE, BLACK); Image checked = GenImageChecked(screenWidth, screenHeight, 32, 32, RED, BLUE); Image whiteNoise = GenImageWhiteNoise(screenWidth, screenHeight, 0.5f); + Image perlinNoise = GenImagePerlinNoise(screenWidth, screenHeight, 8.f); Image cellular = GenImageCellular(screenWidth, screenHeight, 32); Texture2D textures[TEXTURES_NUM]; textures[0] = LoadTextureFromImage(verticalGradient); textures[1] = LoadTextureFromImage(horizontalGradient); - textures[2] = LoadTextureFromImage(checked); - textures[3] = LoadTextureFromImage(whiteNoise); - textures[4] = LoadTextureFromImage(cellular); + textures[2] = LoadTextureFromImage(radialGradient); + textures[3] = LoadTextureFromImage(checked); + textures[4] = LoadTextureFromImage(whiteNoise); + textures[5] = LoadTextureFromImage(perlinNoise); + textures[6] = LoadTextureFromImage(cellular); int currentTexture = 0; diff --git a/src/external/stb_perlin.h b/src/external/stb_perlin.h new file mode 100644 index 00000000..5d762220 --- /dev/null +++ b/src/external/stb_perlin.h @@ -0,0 +1,316 @@ +// stb_perlin.h - v0.3 - perlin noise +// public domain single-file C implementation by Sean Barrett +// +// LICENSE +// +// See end of file. +// +// +// to create the implementation, +// #define STB_PERLIN_IMPLEMENTATION +// in *one* C/CPP file that includes this file. +// +// +// Documentation: +// +// float stb_perlin_noise3( float x, +// float y, +// float z, +// int x_wrap=0, +// int y_wrap=0, +// int z_wrap=0) +// +// This function computes a random value at the coordinate (x,y,z). +// Adjacent random values are continuous but the noise fluctuates +// its randomness with period 1, i.e. takes on wholly unrelated values +// at integer points. Specifically, this implements Ken Perlin's +// revised noise function from 2002. +// +// The "wrap" parameters can be used to create wraparound noise that +// wraps at powers of two. The numbers MUST be powers of two. Specify +// 0 to mean "don't care". (The noise always wraps every 256 due +// details of the implementation, even if you ask for larger or no +// wrapping.) +// +// Fractal Noise: +// +// Three common fractal noise functions are included, which produce +// a wide variety of nice effects depending on the parameters +// provided. Note that each function will call stb_perlin_noise3 +// 'octaves' times, so this parameter will affect runtime. +// +// float stb_perlin_ridge_noise3(float x, float y, float z, +// float lacunarity, float gain, float offset, int octaves, +// int x_wrap, int y_wrap, int z_wrap); +// +// float stb_perlin_fbm_noise3(float x, float y, float z, +// float lacunarity, float gain, int octaves, +// int x_wrap, int y_wrap, int z_wrap); +// +// float stb_perlin_turbulence_noise3(float x, float y, float z, +// float lacunarity, float gain,int octaves, +// int x_wrap, int y_wrap, int z_wrap); +// +// Typical values to start playing with: +// octaves = 6 -- number of "octaves" of noise3() to sum +// lacunarity = ~ 2.0 -- spacing between successive octaves (use exactly 2.0 for wrapping output) +// gain = 0.5 -- relative weighting applied to each successive octave +// offset = 1.0? -- used to invert the ridges, may need to be larger, not sure +// +// +// Contributors: +// Jack Mott - additional noise functions +// + + +#ifdef __cplusplus +extern "C" { +#endif +extern float stb_perlin_noise3(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap); +extern float stb_perlin_ridge_noise3(float x, float y, float z,float lacunarity, float gain, float offset, int octaves,int x_wrap, int y_wrap, int z_wrap); +extern float stb_perlin_fbm_noise3(float x, float y, float z,float lacunarity, float gain, int octaves,int x_wrap, int y_wrap, int z_wrap); +extern float stb_perlin_turbulence_noise3(float x, float y, float z, float lacunarity, float gain, int octaves,int x_wrap, int y_wrap, int z_wrap); +#ifdef __cplusplus +} +#endif + +#ifdef STB_PERLIN_IMPLEMENTATION + +// not same permutation table as Perlin's reference to avoid copyright issues; +// Perlin's table can be found at http://mrl.nyu.edu/~perlin/noise/ +// @OPTIMIZE: should this be unsigned char instead of int for cache? +static unsigned char stb__perlin_randtab[512] = +{ + 23, 125, 161, 52, 103, 117, 70, 37, 247, 101, 203, 169, 124, 126, 44, 123, + 152, 238, 145, 45, 171, 114, 253, 10, 192, 136, 4, 157, 249, 30, 35, 72, + 175, 63, 77, 90, 181, 16, 96, 111, 133, 104, 75, 162, 93, 56, 66, 240, + 8, 50, 84, 229, 49, 210, 173, 239, 141, 1, 87, 18, 2, 198, 143, 57, + 225, 160, 58, 217, 168, 206, 245, 204, 199, 6, 73, 60, 20, 230, 211, 233, + 94, 200, 88, 9, 74, 155, 33, 15, 219, 130, 226, 202, 83, 236, 42, 172, + 165, 218, 55, 222, 46, 107, 98, 154, 109, 67, 196, 178, 127, 158, 13, 243, + 65, 79, 166, 248, 25, 224, 115, 80, 68, 51, 184, 128, 232, 208, 151, 122, + 26, 212, 105, 43, 179, 213, 235, 148, 146, 89, 14, 195, 28, 78, 112, 76, + 250, 47, 24, 251, 140, 108, 186, 190, 228, 170, 183, 139, 39, 188, 244, 246, + 132, 48, 119, 144, 180, 138, 134, 193, 82, 182, 120, 121, 86, 220, 209, 3, + 91, 241, 149, 85, 205, 150, 113, 216, 31, 100, 41, 164, 177, 214, 153, 231, + 38, 71, 185, 174, 97, 201, 29, 95, 7, 92, 54, 254, 191, 118, 34, 221, + 131, 11, 163, 99, 234, 81, 227, 147, 156, 176, 17, 142, 69, 12, 110, 62, + 27, 255, 0, 194, 59, 116, 242, 252, 19, 21, 187, 53, 207, 129, 64, 135, + 61, 40, 167, 237, 102, 223, 106, 159, 197, 189, 215, 137, 36, 32, 22, 5, + + // and a second copy so we don't need an extra mask or static initializer + 23, 125, 161, 52, 103, 117, 70, 37, 247, 101, 203, 169, 124, 126, 44, 123, + 152, 238, 145, 45, 171, 114, 253, 10, 192, 136, 4, 157, 249, 30, 35, 72, + 175, 63, 77, 90, 181, 16, 96, 111, 133, 104, 75, 162, 93, 56, 66, 240, + 8, 50, 84, 229, 49, 210, 173, 239, 141, 1, 87, 18, 2, 198, 143, 57, + 225, 160, 58, 217, 168, 206, 245, 204, 199, 6, 73, 60, 20, 230, 211, 233, + 94, 200, 88, 9, 74, 155, 33, 15, 219, 130, 226, 202, 83, 236, 42, 172, + 165, 218, 55, 222, 46, 107, 98, 154, 109, 67, 196, 178, 127, 158, 13, 243, + 65, 79, 166, 248, 25, 224, 115, 80, 68, 51, 184, 128, 232, 208, 151, 122, + 26, 212, 105, 43, 179, 213, 235, 148, 146, 89, 14, 195, 28, 78, 112, 76, + 250, 47, 24, 251, 140, 108, 186, 190, 228, 170, 183, 139, 39, 188, 244, 246, + 132, 48, 119, 144, 180, 138, 134, 193, 82, 182, 120, 121, 86, 220, 209, 3, + 91, 241, 149, 85, 205, 150, 113, 216, 31, 100, 41, 164, 177, 214, 153, 231, + 38, 71, 185, 174, 97, 201, 29, 95, 7, 92, 54, 254, 191, 118, 34, 221, + 131, 11, 163, 99, 234, 81, 227, 147, 156, 176, 17, 142, 69, 12, 110, 62, + 27, 255, 0, 194, 59, 116, 242, 252, 19, 21, 187, 53, 207, 129, 64, 135, + 61, 40, 167, 237, 102, 223, 106, 159, 197, 189, 215, 137, 36, 32, 22, 5, +}; + +static float stb__perlin_lerp(float a, float b, float t) +{ + return a + (b-a) * t; +} + +static int stb__perlin_fastfloor(float a) +{ + int ai = (int) a; + return (a < ai) ? ai-1 : ai; +} + +// different grad function from Perlin's, but easy to modify to match reference +static float stb__perlin_grad(int hash, float x, float y, float z) +{ + static float basis[12][4] = + { + { 1, 1, 0 }, + { -1, 1, 0 }, + { 1,-1, 0 }, + { -1,-1, 0 }, + { 1, 0, 1 }, + { -1, 0, 1 }, + { 1, 0,-1 }, + { -1, 0,-1 }, + { 0, 1, 1 }, + { 0,-1, 1 }, + { 0, 1,-1 }, + { 0,-1,-1 }, + }; + + // perlin's gradient has 12 cases so some get used 1/16th of the time + // and some 2/16ths. We reduce bias by changing those fractions + // to 5/64ths and 6/64ths, and the same 4 cases get the extra weight. + static unsigned char indices[64] = + { + 0,1,2,3,4,5,6,7,8,9,10,11, + 0,9,1,11, + 0,1,2,3,4,5,6,7,8,9,10,11, + 0,1,2,3,4,5,6,7,8,9,10,11, + 0,1,2,3,4,5,6,7,8,9,10,11, + 0,1,2,3,4,5,6,7,8,9,10,11, + }; + + // if you use reference permutation table, change 63 below to 15 to match reference + // (this is why the ordering of the table above is funky) + float *grad = basis[indices[hash & 63]]; + return grad[0]*x + grad[1]*y + grad[2]*z; +} + +float stb_perlin_noise3(float x, float y, float z, int x_wrap, int y_wrap, int z_wrap) +{ + float u,v,w; + float n000,n001,n010,n011,n100,n101,n110,n111; + float n00,n01,n10,n11; + float n0,n1; + + unsigned int x_mask = (x_wrap-1) & 255; + unsigned int y_mask = (y_wrap-1) & 255; + unsigned int z_mask = (z_wrap-1) & 255; + int px = stb__perlin_fastfloor(x); + int py = stb__perlin_fastfloor(y); + int pz = stb__perlin_fastfloor(z); + int x0 = px & x_mask, x1 = (px+1) & x_mask; + int y0 = py & y_mask, y1 = (py+1) & y_mask; + int z0 = pz & z_mask, z1 = (pz+1) & z_mask; + int r0,r1, r00,r01,r10,r11; + + #define stb__perlin_ease(a) (((a*6-15)*a + 10) * a * a * a) + + x -= px; u = stb__perlin_ease(x); + y -= py; v = stb__perlin_ease(y); + z -= pz; w = stb__perlin_ease(z); + + r0 = stb__perlin_randtab[x0]; + r1 = stb__perlin_randtab[x1]; + + r00 = stb__perlin_randtab[r0+y0]; + r01 = stb__perlin_randtab[r0+y1]; + r10 = stb__perlin_randtab[r1+y0]; + r11 = stb__perlin_randtab[r1+y1]; + + n000 = stb__perlin_grad(stb__perlin_randtab[r00+z0], x , y , z ); + n001 = stb__perlin_grad(stb__perlin_randtab[r00+z1], x , y , z-1 ); + n010 = stb__perlin_grad(stb__perlin_randtab[r01+z0], x , y-1, z ); + n011 = stb__perlin_grad(stb__perlin_randtab[r01+z1], x , y-1, z-1 ); + n100 = stb__perlin_grad(stb__perlin_randtab[r10+z0], x-1, y , z ); + n101 = stb__perlin_grad(stb__perlin_randtab[r10+z1], x-1, y , z-1 ); + n110 = stb__perlin_grad(stb__perlin_randtab[r11+z0], x-1, y-1, z ); + n111 = stb__perlin_grad(stb__perlin_randtab[r11+z1], x-1, y-1, z-1 ); + + n00 = stb__perlin_lerp(n000,n001,w); + n01 = stb__perlin_lerp(n010,n011,w); + n10 = stb__perlin_lerp(n100,n101,w); + n11 = stb__perlin_lerp(n110,n111,w); + + n0 = stb__perlin_lerp(n00,n01,v); + n1 = stb__perlin_lerp(n10,n11,v); + + return stb__perlin_lerp(n0,n1,u); +} + +float stb_perlin_ridge_noise3(float x, float y, float z,float lacunarity, float gain, float offset, int octaves,int x_wrap, int y_wrap, int z_wrap) +{ + int i; + float frequency = 1.0f; + float prev = 1.0f; + float amplitude = 0.5f; + float sum = 0.0f; + + for (i = 0; i < octaves; i++) { + float r = (float)(stb_perlin_noise3(x*frequency,y*frequency,z*frequency,x_wrap,y_wrap,z_wrap)); + r = r<0 ? -r : r; // fabs() + r = offset - r; + r = r*r; + sum += r*amplitude*prev; + prev = r; + frequency *= lacunarity; + amplitude *= gain; + } + return sum; +} + +float stb_perlin_fbm_noise3(float x, float y, float z,float lacunarity, float gain, int octaves,int x_wrap, int y_wrap, int z_wrap) +{ + int i; + float frequency = 1.0f; + float amplitude = 1.0f; + float sum = 0.0f; + + for (i = 0; i < octaves; i++) { + sum += stb_perlin_noise3(x*frequency,y*frequency,z*frequency,x_wrap,y_wrap,z_wrap)*amplitude; + frequency *= lacunarity; + amplitude *= gain; + } + return sum; +} + +float stb_perlin_turbulence_noise3(float x, float y, float z, float lacunarity, float gain, int octaves,int x_wrap, int y_wrap, int z_wrap) +{ + int i; + float frequency = 1.0f; + float amplitude = 1.0f; + float sum = 0.0f; + + for (i = 0; i < octaves; i++) { + float r = stb_perlin_noise3(x*frequency,y*frequency,z*frequency,x_wrap,y_wrap,z_wrap)*amplitude; + r = r<0 ? -r : r; // fabs() + sum += r; + frequency *= lacunarity; + amplitude *= gain; + } + return sum; +} + +#endif // STB_PERLIN_IMPLEMENTATION + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/src/raylib.h b/src/raylib.h index 29cc5728..828c2fe9 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -876,8 +876,10 @@ RLAPI void ImageColorBrightness(Image *image, int brightness); // Image generation functions RLAPI Image GenImageGradientV(int width, int height, Color top, Color bottom); // Generate image: vertical gradient RLAPI Image GenImageGradientH(int width, int height, Color left, Color right); // Generate image: horizontal gradient +RLAPI Image GenImageRadialGradient(int width, int height, Color inner, Color outer); // Generate image: radial gradient RLAPI Image GenImageChecked(int width, int height, int checksX, int checksY, Color col1, Color col2); // Generate image: checked RLAPI Image GenImageWhiteNoise(int width, int height, float factor); // Generate image: white noise +RLAPI Image GenImagePerlinNoise(int width, int height, float scale); // Generate image: perlin noise RLAPI Image GenImageCellular(int width, int height, int tileSize); // Generate image: cellular algorithm. Bigger tileSize means bigger cells // Texture2D configuration functions diff --git a/src/textures.c b/src/textures.c index 99392516..be089a93 100644 --- a/src/textures.c +++ b/src/textures.c @@ -68,6 +68,9 @@ #include "utils.h" // Required for: fopen() Android mapping +#define STB_PERLIN_IMPLEMENTATION +#include "external/stb_perlin.h"// Required for: stb_perlin_fbm_noise3 + // Support only desired texture formats on stb_image #if !defined(SUPPORT_FILEFORMAT_BMP) #define STBI_NO_BMP @@ -1477,6 +1480,34 @@ Image GenImageGradientH(int width, int height, Color left, Color right) return image; } +// Generate image: radial gradient +Image GenImageRadialGradient(int width, int height, Color inner, Color outer) +{ + Color *pixels = (Color*)malloc(width * height * sizeof(Color)); + float radius = (width < height) ? (float)width / 2.f : (float)height / 2.f; + + float center_x = (float)width / 2.f; + float center_y = (float)height / 2.f; + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++) + { + float dist = hypotf((float)x - center_x, (float)y - center_y); + float factor = dist / radius; + factor = fmin(factor, 1.f); // dist can be bigger than radius so we have to check + pixels[y*width + x].r = (int)((float)outer.r * factor + (float)inner.r * (1.f - factor)); + pixels[y*width + x].g = (int)((float)outer.g * factor + (float)inner.g * (1.f - factor)); + pixels[y*width + x].b = (int)((float)outer.b * factor + (float)inner.b * (1.f - factor)); + pixels[y*width + x].a = (int)((float)outer.a * factor + (float)inner.a * (1.f - factor)); + } + } + + Image image = LoadImageEx(pixels, width, height); + free(pixels); + + return image; +} + // Generate image: checked Image GenImageChecked(int width, int height, int checksX, int checksY, Color col1, Color col2) { @@ -1514,6 +1545,30 @@ Image GenImageWhiteNoise(int width, int height, float factor) return image; } +// Generate image: perlin noise +Image GenImagePerlinNoise(int width, int height, float scale) +{ + Color *pixels = (Color*)malloc(width * height * sizeof(Color)); + + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++) + { + float nx = (float)x * scale / (float)width; + float ny = (float)y * scale / (float)height; + // we need to translate the data from [-1; 1] to [0; 1] + float p = (stb_perlin_fbm_noise3(nx, ny, 1.f, 2.f, 0.5f, 6, 0, 0, 0) + 1.f) / 2.f; + int intensity = (int)(p * 255.f); + pixels[y*width + x] = (Color){intensity, intensity, intensity, 255}; + } + } + + Image image = LoadImageEx(pixels, width, height); + free(pixels); + + return image; +} + // Generate image: cellular algorithm. Bigger tileSize means bigger cells Image GenImageCellular(int width, int height, int tileSize) { -- cgit v1.2.3 From 3fe268d004c9b95f9853b0d399887cae185a11d4 Mon Sep 17 00:00:00 2001 From: Wilhem Barbier Date: Wed, 28 Jun 2017 15:38:34 +0200 Subject: Swap the two parameters --- src/raylib.h | 2 +- src/textures.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/raylib.h') diff --git a/src/raylib.h b/src/raylib.h index ee0d8ccc..aa55b776 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -849,7 +849,7 @@ RLAPI void UnloadRenderTexture(RenderTexture2D target); RLAPI Color *GetImageData(Image image); // Get pixel data from image as a Color struct array RLAPI Image GetTextureData(Texture2D texture); // Get pixel data from GPU texture and return an Image RLAPI void UpdateTexture(Texture2D texture, const void *pixels); // Update GPU texture with new data -RLAPI void SaveImageAs(Image image, const char *fileName); // Save image to a PNG file +RLAPI void SaveImageAs(const char *fileName, Image image); // Save image to a PNG file // Image manipulation functions RLAPI void ImageToPOT(Image *image, Color fillColor); // Convert image to POT (power-of-two) diff --git a/src/textures.c b/src/textures.c index f1fcb12c..34c7453a 100644 --- a/src/textures.c +++ b/src/textures.c @@ -554,7 +554,7 @@ void UpdateTexture(Texture2D texture, const void *pixels) } // Save image to a PNG file -void SaveImageAs(Image image, const char *fileName) +void SaveImageAs(const char* fileName, Image image) { #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) unsigned char* imgData = (unsigned char*)GetImageData(image); // this works since Color is just a container for the RGBA values -- cgit v1.2.3 From 786cd63057d77e7987fe68986da6bca103c96415 Mon Sep 17 00:00:00 2001 From: Wilhem Barbier Date: Wed, 28 Jun 2017 17:27:47 +0200 Subject: Add a density parameter to GenImageRadialGradient --- examples/textures/textures_image_generation.c | 2 +- src/raylib.h | 2 +- src/textures.c | 5 +++-- 3 files changed, 5 insertions(+), 4 deletions(-) (limited to 'src/raylib.h') diff --git a/examples/textures/textures_image_generation.c b/examples/textures/textures_image_generation.c index 7525e8a2..f6343297 100644 --- a/examples/textures/textures_image_generation.c +++ b/examples/textures/textures_image_generation.c @@ -22,7 +22,7 @@ int main() Image verticalGradient = GenImageGradientV(screenWidth, screenHeight, RED, BLUE); Image horizontalGradient = GenImageGradientH(screenWidth, screenHeight, RED, BLUE); - Image radialGradient = GenImageRadialGradient(screenWidth, screenHeight, WHITE, BLACK); + Image radialGradient = GenImageRadialGradient(screenWidth, screenHeight, 0.f, WHITE, BLACK); Image checked = GenImageChecked(screenWidth, screenHeight, 32, 32, RED, BLUE); Image whiteNoise = GenImageWhiteNoise(screenWidth, screenHeight, 0.5f); Image perlinNoise = GenImagePerlinNoise(screenWidth, screenHeight, 8.f); diff --git a/src/raylib.h b/src/raylib.h index a9483f31..0a4ce091 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -877,7 +877,7 @@ RLAPI void ImageColorBrightness(Image *image, int brightness); // Image generation functions RLAPI Image GenImageGradientV(int width, int height, Color top, Color bottom); // Generate image: vertical gradient RLAPI Image GenImageGradientH(int width, int height, Color left, Color right); // Generate image: horizontal gradient -RLAPI Image GenImageRadialGradient(int width, int height, Color inner, Color outer); // Generate image: radial gradient +RLAPI Image GenImageRadialGradient(int width, int height, float density, Color inner, Color outer); // Generate image: radial gradient RLAPI Image GenImageChecked(int width, int height, int checksX, int checksY, Color col1, Color col2); // Generate image: checked RLAPI Image GenImageWhiteNoise(int width, int height, float factor); // Generate image: white noise RLAPI Image GenImagePerlinNoise(int width, int height, float scale); // Generate image: perlin noise diff --git a/src/textures.c b/src/textures.c index 67d03d8d..9b0067cf 100644 --- a/src/textures.c +++ b/src/textures.c @@ -1493,7 +1493,7 @@ Image GenImageGradientH(int width, int height, Color left, Color right) } // Generate image: radial gradient -Image GenImageRadialGradient(int width, int height, Color inner, Color outer) +Image GenImageRadialGradient(int width, int height, float density, Color inner, Color outer) { Color *pixels = (Color*)malloc(width * height * sizeof(Color)); float radius = (width < height) ? (float)width / 2.f : (float)height / 2.f; @@ -1505,7 +1505,8 @@ Image GenImageRadialGradient(int width, int height, Color inner, Color outer) for (int x = 0; x < width; x++) { float dist = hypotf((float)x - center_x, (float)y - center_y); - float factor = dist / radius; + float factor = (dist - radius * density) / (radius * (1.f - density)); + factor = fmax(factor, 0.f); factor = fmin(factor, 1.f); // dist can be bigger than radius so we have to check pixels[y*width + x].r = (int)((float)outer.r * factor + (float)inner.r * (1.f - factor)); pixels[y*width + x].g = (int)((float)outer.g * factor + (float)inner.g * (1.f - factor)); -- cgit v1.2.3 From 9f09f6f55023bf8f14a6889801520d80475d33be Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sun, 2 Jul 2017 12:35:13 +0200 Subject: Rename enum LogType names... ...to avoid possible conflicting symbols --- src/audio.c | 145 +++++++++++++++++------------------- src/core.c | 146 ++++++++++++++++++------------------ src/models.c | 28 +++---- src/raylib.h | 15 ++-- src/rlgl.c | 231 ++++++++++++++++++++++++++++----------------------------- src/rlgl.h | 14 ++-- src/rres.h | 43 +++++------ src/text.c | 36 ++++----- src/textures.c | 126 +++++++++++++++---------------- src/utils.c | 30 ++++---- 10 files changed, 397 insertions(+), 417 deletions(-) (limited to 'src/raylib.h') diff --git a/src/audio.c b/src/audio.c index b81d5572..1b340377 100644 --- a/src/audio.c +++ b/src/audio.c @@ -170,7 +170,7 @@ typedef struct MusicData { } MusicData; #if defined(AUDIO_STANDALONE) -typedef enum { INFO = 0, ERROR, WARNING, DEBUG, OTHER } TraceLogType; +typedef enum { LOG_INFO = 0, LOG_ERROR, LOG_WARNING, LOG_DEBUG, LOG_OTHER } TraceLogType; #endif //---------------------------------------------------------------------------------- @@ -193,7 +193,7 @@ static Wave LoadFLAC(const char *fileName); // Load FLAC file #if defined(AUDIO_STANDALONE) bool IsFileExtension(const char *fileName, const char *ext); // Check file extension -void TraceLog(int msgType, const char *text, ...); // Outputs trace log message (INFO, ERROR, WARNING) +void TraceLog(int msgType, const char *text, ...); // Show trace log messages (LOG_INFO, LOG_WARNING, LOG_ERROR, LOG_DEBUG) #endif //---------------------------------------------------------------------------------- @@ -206,7 +206,7 @@ void InitAudioDevice(void) // Open and initialize a device with default settings ALCdevice *device = alcOpenDevice(NULL); - if (!device) TraceLog(ERROR, "Audio device could not be opened"); + if (!device) TraceLog(LOG_ERROR, "Audio device could not be opened"); else { ALCcontext *context = alcCreateContext(device, NULL); @@ -217,11 +217,11 @@ void InitAudioDevice(void) alcCloseDevice(device); - TraceLog(ERROR, "Could not initialize audio context"); + TraceLog(LOG_ERROR, "Could not initialize audio context"); } else { - TraceLog(INFO, "Audio device and context initialized successfully: %s", alcGetString(device, ALC_DEVICE_SPECIFIER)); + TraceLog(LOG_INFO, "Audio device and context initialized successfully: %s", alcGetString(device, ALC_DEVICE_SPECIFIER)); // Listener definition (just for 2D) alListener3f(AL_POSITION, 0.0f, 0.0f, 0.0f); @@ -239,7 +239,7 @@ void CloseAudioDevice(void) ALCdevice *device; ALCcontext *context = alcGetCurrentContext(); - if (context == NULL) TraceLog(WARNING, "Could not get current audio context for closing"); + if (context == NULL) TraceLog(LOG_WARNING, "Could not get current audio context for closing"); device = alcGetContextsDevice(context); @@ -247,7 +247,7 @@ void CloseAudioDevice(void) alcDestroyContext(context); alcCloseDevice(device); - TraceLog(INFO, "Audio device closed successfully"); + TraceLog(LOG_INFO, "Audio device closed successfully"); } // Check if device has been initialized successfully @@ -298,12 +298,12 @@ Wave LoadWave(const char *fileName) // NOTE: Parameters for RRES_TYPE_WAVE are: sampleCount, sampleRate, sampleSize, channels if (rres[0].type == RRES_TYPE_WAVE) wave = LoadWaveEx(rres[0].data, rres[0].param1, rres[0].param2, rres[0].param3, rres[0].param4); - else TraceLog(WARNING, "[%s] Resource file does not contain wave data", fileName); + else TraceLog(LOG_WARNING, "[%s] Resource file does not contain wave data", fileName); UnloadResource(rres); } #endif - else TraceLog(WARNING, "[%s] Audio fileformat not supported, it can't be loaded", fileName); + else TraceLog(LOG_WARNING, "[%s] Audio fileformat not supported, it can't be loaded", fileName); return wave; } @@ -358,7 +358,7 @@ Sound LoadSoundFromWave(Wave wave) case 8: format = AL_FORMAT_MONO8; break; case 16: format = AL_FORMAT_MONO16; break; case 32: format = AL_FORMAT_MONO_FLOAT32; break; // Requires OpenAL extension: AL_EXT_FLOAT32 - default: TraceLog(WARNING, "Wave sample size not supported: %i", wave.sampleSize); break; + default: TraceLog(LOG_WARNING, "Wave sample size not supported: %i", wave.sampleSize); break; } } else if (wave.channels == 2) @@ -368,10 +368,10 @@ Sound LoadSoundFromWave(Wave wave) case 8: format = AL_FORMAT_STEREO8; break; case 16: format = AL_FORMAT_STEREO16; break; case 32: format = AL_FORMAT_STEREO_FLOAT32; break; // Requires OpenAL extension: AL_EXT_FLOAT32 - default: TraceLog(WARNING, "Wave sample size not supported: %i", wave.sampleSize); break; + default: TraceLog(LOG_WARNING, "Wave sample size not supported: %i", wave.sampleSize); break; } } - else TraceLog(WARNING, "Wave number of channels not supported: %i", wave.channels); + else TraceLog(LOG_WARNING, "Wave number of channels not supported: %i", wave.channels); // Create an audio source ALuint source; @@ -396,7 +396,7 @@ Sound LoadSoundFromWave(Wave wave) // Attach sound buffer to source alSourcei(source, AL_BUFFER, buffer); - TraceLog(INFO, "[SND ID %i][BUFR ID %i] Sound data loaded successfully (%i Hz, %i bit, %s)", source, buffer, wave.sampleRate, wave.sampleSize, (wave.channels == 1) ? "Mono" : "Stereo"); + TraceLog(LOG_INFO, "[SND ID %i][BUFR ID %i] Sound data loaded successfully (%i Hz, %i bit, %s)", source, buffer, wave.sampleRate, wave.sampleSize, (wave.channels == 1) ? "Mono" : "Stereo"); sound.source = source; sound.buffer = buffer; @@ -411,7 +411,7 @@ void UnloadWave(Wave wave) { if (wave.data != NULL) free(wave.data); - TraceLog(INFO, "Unloaded wave data from RAM"); + TraceLog(LOG_INFO, "Unloaded wave data from RAM"); } // Unload sound @@ -422,7 +422,7 @@ void UnloadSound(Sound sound) alDeleteSources(1, &sound.source); alDeleteBuffers(1, &sound.buffer); - TraceLog(INFO, "[SND ID %i][BUFR ID %i] Unloaded sound data from RAM", sound.source, sound.buffer); + TraceLog(LOG_INFO, "[SND ID %i][BUFR ID %i] Unloaded sound data from RAM", sound.source, sound.buffer); } // Update sound buffer with new data @@ -434,9 +434,9 @@ void UpdateSound(Sound sound, const void *data, int samplesCount) alGetBufferi(sound.buffer, AL_BITS, &sampleSize); // It could also be retrieved from sound.format alGetBufferi(sound.buffer, AL_CHANNELS, &channels); // It could also be retrieved from sound.format - TraceLog(DEBUG, "UpdateSound() : AL_FREQUENCY: %i", sampleRate); - TraceLog(DEBUG, "UpdateSound() : AL_BITS: %i", sampleSize); - TraceLog(DEBUG, "UpdateSound() : AL_CHANNELS: %i", channels); + TraceLog(LOG_DEBUG, "UpdateSound() : AL_FREQUENCY: %i", sampleRate); + TraceLog(LOG_DEBUG, "UpdateSound() : AL_BITS: %i", sampleSize); + TraceLog(LOG_DEBUG, "UpdateSound() : AL_CHANNELS: %i", channels); unsigned int dataSize = samplesCount*channels*sampleSize/8; // Size of data in bytes @@ -457,7 +457,7 @@ void PlaySound(Sound sound) { alSourcePlay(sound.source); // Play the sound - //TraceLog(INFO, "Playing sound"); + //TraceLog(LOG_INFO, "Playing sound"); // Find the current position of the sound being played // NOTE: Only work when the entire file is in a single buffer @@ -639,7 +639,7 @@ void WaveCrop(Wave *wave, int initSample, int finalSample) free(wave->data); wave->data = data; } - else TraceLog(WARNING, "Wave crop range out of bounds"); + else TraceLog(LOG_WARNING, "Wave crop range out of bounds"); } // Get samples data from wave as a floats array @@ -675,7 +675,7 @@ Music LoadMusicStream(const char *fileName) // Open ogg audio stream music->ctxOgg = stb_vorbis_open_filename(fileName, NULL, NULL); - if (music->ctxOgg == NULL) TraceLog(WARNING, "[%s] OGG audio file could not be opened", fileName); + if (music->ctxOgg == NULL) TraceLog(LOG_WARNING, "[%s] OGG audio file could not be opened", fileName); else { stb_vorbis_info info = stb_vorbis_get_info(music->ctxOgg); // Get Ogg file info @@ -687,10 +687,10 @@ Music LoadMusicStream(const char *fileName) music->ctxType = MUSIC_AUDIO_OGG; music->loopCount = -1; // Infinite loop by default - TraceLog(DEBUG, "[%s] FLAC total samples: %i", fileName, music->totalSamples); - TraceLog(DEBUG, "[%s] OGG sample rate: %i", fileName, info.sample_rate); - TraceLog(DEBUG, "[%s] OGG channels: %i", fileName, info.channels); - TraceLog(DEBUG, "[%s] OGG memory required: %i", fileName, info.temp_memory_required); + TraceLog(LOG_DEBUG, "[%s] FLAC total samples: %i", fileName, music->totalSamples); + TraceLog(LOG_DEBUG, "[%s] OGG sample rate: %i", fileName, info.sample_rate); + TraceLog(LOG_DEBUG, "[%s] OGG channels: %i", fileName, info.channels); + TraceLog(LOG_DEBUG, "[%s] OGG memory required: %i", fileName, info.temp_memory_required); } } #if defined(SUPPORT_FILEFORMAT_FLAC) @@ -698,7 +698,7 @@ Music LoadMusicStream(const char *fileName) { music->ctxFlac = drflac_open_file(fileName); - if (music->ctxFlac == NULL) TraceLog(WARNING, "[%s] FLAC audio file could not be opened", fileName); + if (music->ctxFlac == NULL) TraceLog(LOG_WARNING, "[%s] FLAC audio file could not be opened", fileName); else { music->stream = InitAudioStream(music->ctxFlac->sampleRate, music->ctxFlac->bitsPerSample, music->ctxFlac->channels); @@ -707,10 +707,10 @@ Music LoadMusicStream(const char *fileName) music->ctxType = MUSIC_AUDIO_FLAC; music->loopCount = -1; // Infinite loop by default - TraceLog(DEBUG, "[%s] FLAC total samples: %i", fileName, music->totalSamples); - TraceLog(DEBUG, "[%s] FLAC sample rate: %i", fileName, music->ctxFlac->sampleRate); - TraceLog(DEBUG, "[%s] FLAC bits per sample: %i", fileName, music->ctxFlac->bitsPerSample); - TraceLog(DEBUG, "[%s] FLAC channels: %i", fileName, music->ctxFlac->channels); + TraceLog(LOG_DEBUG, "[%s] FLAC total samples: %i", fileName, music->totalSamples); + TraceLog(LOG_DEBUG, "[%s] FLAC sample rate: %i", fileName, music->ctxFlac->sampleRate); + TraceLog(LOG_DEBUG, "[%s] FLAC bits per sample: %i", fileName, music->ctxFlac->bitsPerSample); + TraceLog(LOG_DEBUG, "[%s] FLAC channels: %i", fileName, music->ctxFlac->channels); } } #endif @@ -730,10 +730,10 @@ Music LoadMusicStream(const char *fileName) music->ctxType = MUSIC_MODULE_XM; music->loopCount = -1; // Infinite loop by default - TraceLog(DEBUG, "[%s] XM number of samples: %i", fileName, music->totalSamples); - TraceLog(DEBUG, "[%s] XM track length: %11.6f sec", fileName, (float)music->totalSamples/48000.0f); + TraceLog(LOG_DEBUG, "[%s] XM number of samples: %i", fileName, music->totalSamples); + TraceLog(LOG_DEBUG, "[%s] XM track length: %11.6f sec", fileName, (float)music->totalSamples/48000.0f); } - else TraceLog(WARNING, "[%s] XM file could not be opened", fileName); + else TraceLog(LOG_WARNING, "[%s] XM file could not be opened", fileName); } #endif #if defined(SUPPORT_FILEFORMAT_MOD) @@ -749,13 +749,13 @@ Music LoadMusicStream(const char *fileName) music->ctxType = MUSIC_MODULE_MOD; music->loopCount = -1; // Infinite loop by default - TraceLog(DEBUG, "[%s] MOD number of samples: %i", fileName, music->samplesLeft); - TraceLog(DEBUG, "[%s] MOD track length: %11.6f sec", fileName, (float)music->totalSamples/48000.0f); + TraceLog(LOG_DEBUG, "[%s] MOD number of samples: %i", fileName, music->samplesLeft); + TraceLog(LOG_DEBUG, "[%s] MOD track length: %11.6f sec", fileName, (float)music->totalSamples/48000.0f); } - else TraceLog(WARNING, "[%s] MOD file could not be opened", fileName); + else TraceLog(LOG_WARNING, "[%s] MOD file could not be opened", fileName); } #endif - else TraceLog(WARNING, "[%s] Audio fileformat not supported, it can't be loaded", fileName); + else TraceLog(LOG_WARNING, "[%s] Audio fileformat not supported, it can't be loaded", fileName); return music; } @@ -799,7 +799,7 @@ void ResumeMusicStream(Music music) if (state == AL_PAUSED) { - TraceLog(INFO, "[AUD ID %i] Resume music stream playing", music->stream.source); + TraceLog(LOG_INFO, "[AUD ID %i] Resume music stream playing", music->stream.source); alSourcePlay(music->stream.source); } } @@ -992,7 +992,7 @@ AudioStream InitAudioStream(unsigned int sampleRate, unsigned int sampleSize, un if ((channels > 0) && (channels < 3)) stream.channels = channels; else { - TraceLog(WARNING, "Init audio stream: Number of channels not supported: %i", channels); + TraceLog(LOG_WARNING, "Init audio stream: Number of channels not supported: %i", channels); stream.channels = 1; // Fallback to mono channel } @@ -1004,7 +1004,7 @@ AudioStream InitAudioStream(unsigned int sampleRate, unsigned int sampleSize, un case 8: stream.format = AL_FORMAT_MONO8; break; case 16: stream.format = AL_FORMAT_MONO16; break; case 32: stream.format = AL_FORMAT_MONO_FLOAT32; break; // Requires OpenAL extension: AL_EXT_FLOAT32 - default: TraceLog(WARNING, "Init audio stream: Sample size not supported: %i", sampleSize); break; + default: TraceLog(LOG_WARNING, "Init audio stream: Sample size not supported: %i", sampleSize); break; } } else if (stream.channels == 2) @@ -1014,7 +1014,7 @@ AudioStream InitAudioStream(unsigned int sampleRate, unsigned int sampleSize, un case 8: stream.format = AL_FORMAT_STEREO8; break; case 16: stream.format = AL_FORMAT_STEREO16; break; case 32: stream.format = AL_FORMAT_STEREO_FLOAT32; break; // Requires OpenAL extension: AL_EXT_FLOAT32 - default: TraceLog(WARNING, "Init audio stream: Sample size not supported: %i", sampleSize); break; + default: TraceLog(LOG_WARNING, "Init audio stream: Sample size not supported: %i", sampleSize); break; } } @@ -1041,7 +1041,7 @@ AudioStream InitAudioStream(unsigned int sampleRate, unsigned int sampleSize, un alSourceQueueBuffers(stream.source, MAX_STREAM_BUFFERS, stream.buffers); - TraceLog(INFO, "[AUD ID %i] Audio stream loaded successfully (%i Hz, %i bit, %s)", stream.source, stream.sampleRate, stream.sampleSize, (stream.channels == 1) ? "Mono" : "Stereo"); + TraceLog(LOG_INFO, "[AUD ID %i] Audio stream loaded successfully (%i Hz, %i bit, %s)", stream.source, stream.sampleRate, stream.sampleSize, (stream.channels == 1) ? "Mono" : "Stereo"); return stream; } @@ -1068,7 +1068,7 @@ void CloseAudioStream(AudioStream stream) alDeleteSources(1, &stream.source); alDeleteBuffers(MAX_STREAM_BUFFERS, stream.buffers); - TraceLog(INFO, "[AUD ID %i] Unloaded audio stream data", stream.source); + TraceLog(LOG_INFO, "[AUD ID %i] Unloaded audio stream data", stream.source); } // Update audio stream buffers with data @@ -1085,7 +1085,7 @@ void UpdateAudioStream(AudioStream stream, const void *data, int samplesCount) alBufferData(buffer, stream.format, data, samplesCount*stream.sampleSize/8*stream.channels, stream.sampleRate); alSourceQueueBuffers(stream.source, 1, &buffer); } - else TraceLog(WARNING, "[AUD ID %i] Audio buffer not available for unqueuing", stream.source); + else TraceLog(LOG_WARNING, "[AUD ID %i] Audio buffer not available for unqueuing", stream.source); } // Check if any audio stream buffers requires refill @@ -1168,7 +1168,7 @@ static Wave LoadWAV(const char *fileName) if (wavFile == NULL) { - TraceLog(WARNING, "[%s] WAV file could not be opened", fileName); + TraceLog(LOG_WARNING, "[%s] WAV file could not be opened", fileName); wave.data = NULL; } else @@ -1180,7 +1180,7 @@ static Wave LoadWAV(const char *fileName) if (strncmp(wavRiffHeader.chunkID, "RIFF", 4) || strncmp(wavRiffHeader.format, "WAVE", 4)) { - TraceLog(WARNING, "[%s] Invalid RIFF or WAVE Header", fileName); + TraceLog(LOG_WARNING, "[%s] Invalid RIFF or WAVE Header", fileName); } else { @@ -1191,7 +1191,7 @@ static Wave LoadWAV(const char *fileName) if ((wavFormat.subChunkID[0] != 'f') || (wavFormat.subChunkID[1] != 'm') || (wavFormat.subChunkID[2] != 't') || (wavFormat.subChunkID[3] != ' ')) { - TraceLog(WARNING, "[%s] Invalid Wave format", fileName); + TraceLog(LOG_WARNING, "[%s] Invalid Wave format", fileName); } else { @@ -1205,7 +1205,7 @@ static Wave LoadWAV(const char *fileName) if ((wavData.subChunkID[0] != 'd') || (wavData.subChunkID[1] != 'a') || (wavData.subChunkID[2] != 't') || (wavData.subChunkID[3] != 'a')) { - TraceLog(WARNING, "[%s] Invalid data header", fileName); + TraceLog(LOG_WARNING, "[%s] Invalid data header", fileName); } else { @@ -1223,7 +1223,7 @@ static Wave LoadWAV(const char *fileName) // NOTE: Only support 8 bit, 16 bit and 32 bit sample sizes if ((wave.sampleSize != 8) && (wave.sampleSize != 16) && (wave.sampleSize != 32)) { - TraceLog(WARNING, "[%s] WAV sample size (%ibit) not supported, converted to 16bit", fileName, wave.sampleSize); + TraceLog(LOG_WARNING, "[%s] WAV sample size (%ibit) not supported, converted to 16bit", fileName, wave.sampleSize); WaveFormat(&wave, wave.sampleRate, 16, wave.channels); } @@ -1231,13 +1231,13 @@ static Wave LoadWAV(const char *fileName) if (wave.channels > 2) { WaveFormat(&wave, wave.sampleRate, wave.sampleSize, 2); - TraceLog(WARNING, "[%s] WAV channels number (%i) not supported, converted to 2 channels", fileName, wave.channels); + TraceLog(LOG_WARNING, "[%s] WAV channels number (%i) not supported, converted to 2 channels", fileName, wave.channels); } // NOTE: subChunkSize comes in bytes, we need to translate it to number of samples wave.sampleCount = (wavData.subChunkSize/(wave.sampleSize/8))/wave.channels; - TraceLog(INFO, "[%s] WAV file loaded successfully (%i Hz, %i bit, %s)", fileName, wave.sampleRate, wave.sampleSize, (wave.channels == 1) ? "Mono" : "Stereo"); + TraceLog(LOG_INFO, "[%s] WAV file loaded successfully (%i Hz, %i bit, %s)", fileName, wave.sampleRate, wave.sampleSize, (wave.channels == 1) ? "Mono" : "Stereo"); } } } @@ -1258,7 +1258,7 @@ static Wave LoadOGG(const char *fileName) stb_vorbis *oggFile = stb_vorbis_open_filename(fileName, NULL, NULL); - if (oggFile == NULL) TraceLog(WARNING, "[%s] OGG file could not be opened", fileName); + if (oggFile == NULL) TraceLog(LOG_WARNING, "[%s] OGG file could not be opened", fileName); else { stb_vorbis_info info = stb_vorbis_get_info(oggFile); @@ -1269,16 +1269,16 @@ static Wave LoadOGG(const char *fileName) wave.sampleCount = (int)stb_vorbis_stream_length_in_samples(oggFile); // Independent by channel float totalSeconds = stb_vorbis_stream_length_in_seconds(oggFile); - if (totalSeconds > 10) TraceLog(WARNING, "[%s] Ogg audio length is larger than 10 seconds (%f), that's a big file in memory, consider music streaming", fileName, totalSeconds); + if (totalSeconds > 10) TraceLog(LOG_WARNING, "[%s] Ogg audio length is larger than 10 seconds (%f), that's a big file in memory, consider music streaming", fileName, totalSeconds); wave.data = (short *)malloc(wave.sampleCount*wave.channels*sizeof(short)); // NOTE: Returns the number of samples to process (be careful! we ask for number of shorts!) int numSamplesOgg = stb_vorbis_get_samples_short_interleaved(oggFile, info.channels, (short *)wave.data, wave.sampleCount*wave.channels); - TraceLog(DEBUG, "[%s] Samples obtained: %i", fileName, numSamplesOgg); + TraceLog(LOG_DEBUG, "[%s] Samples obtained: %i", fileName, numSamplesOgg); - TraceLog(INFO, "[%s] OGG file loaded successfully (%i Hz, %i bit, %s)", fileName, wave.sampleRate, wave.sampleSize, (wave.channels == 1) ? "Mono" : "Stereo"); + TraceLog(LOG_INFO, "[%s] OGG file loaded successfully (%i Hz, %i bit, %s)", fileName, wave.sampleRate, wave.sampleSize, (wave.channels == 1) ? "Mono" : "Stereo"); stb_vorbis_close(oggFile); } @@ -1302,10 +1302,10 @@ static Wave LoadFLAC(const char *fileName) wave.sampleSize = 16; // NOTE: Only support up to 2 channels (mono, stereo) - if (wave.channels > 2) TraceLog(WARNING, "[%s] FLAC channels number (%i) not supported", fileName, wave.channels); + if (wave.channels > 2) TraceLog(LOG_WARNING, "[%s] FLAC channels number (%i) not supported", fileName, wave.channels); - if (wave.data == NULL) TraceLog(WARNING, "[%s] FLAC data could not be loaded", fileName); - else TraceLog(INFO, "[%s] FLAC file loaded successfully (%i Hz, %i bit, %s)", fileName, wave.sampleRate, wave.sampleSize, (wave.channels == 1) ? "Mono" : "Stereo"); + if (wave.data == NULL) TraceLog(LOG_WARNING, "[%s] FLAC data could not be loaded", fileName); + else TraceLog(LOG_INFO, "[%s] FLAC file loaded successfully (%i Hz, %i bit, %s)", fileName, wave.sampleRate, wave.sampleSize, (wave.channels == 1) ? "Mono" : "Stereo"); return wave; } @@ -1327,35 +1327,26 @@ bool IsFileExtension(const char *fileName, const char *ext) return result; } -// Outputs a trace log message (INFO, ERROR, WARNING) -// NOTE: If a file has been init, output log is written there +// Show trace log messages (LOG_INFO, LOG_WARNING, LOG_ERROR, LOG_DEBUG) void TraceLog(int msgType, const char *text, ...) { va_list args; - int traceDebugMsgs = 0; - -#if defined(DO_NOT_TRACE_DEBUG_MSGS) - traceDebugMsgs = 0; -#endif + va_start(args, text); switch (msgType) { - case INFO: fprintf(stdout, "INFO: "); break; - case ERROR: fprintf(stdout, "ERROR: "); break; - case WARNING: fprintf(stdout, "WARNING: "); break; - case DEBUG: if (traceDebugMsgs) fprintf(stdout, "DEBUG: "); break; + case LOG_INFO: fprintf(stdout, "INFO: "); break; + case LOG_ERROR: fprintf(stdout, "ERROR: "); break; + case LOG_WARNING: fprintf(stdout, "WARNING: "); break; + case LOG_DEBUG: fprintf(stdout, "DEBUG: "); break; default: break; } - if ((msgType != DEBUG) || ((msgType == DEBUG) && (traceDebugMsgs))) - { - va_start(args, text); - vfprintf(stdout, text, args); - va_end(args); + vfprintf(stdout, text, args); + fprintf(stdout, "\n"); - fprintf(stdout, "\n"); - } + va_end(args); - if (msgType == ERROR) exit(1); // If ERROR message, exit program + if (msgType == LOG_ERROR) exit(1); } #endif diff --git a/src/core.c b/src/core.c index f2ecfa04..36180746 100644 --- a/src/core.c +++ b/src/core.c @@ -412,7 +412,7 @@ static void *GamepadThread(void *arg); // Mouse reading thread // Initialize window and OpenGL context void InitWindow(int width, int height, const char *title) { - TraceLog(INFO, "Initializing raylib (v1.7.0)"); + TraceLog(LOG_INFO, "Initializing raylib (v1.7.0)"); // Store window title (could be useful...) windowTitle = title; @@ -475,7 +475,7 @@ void InitWindow(int width, int height, const char *title) // Initialize Android activity void InitWindow(int width, int height, void *state) { - TraceLog(INFO, "Initializing raylib (v1.7.0)"); + TraceLog(LOG_INFO, "Initializing raylib (v1.7.0)"); app_dummy(); @@ -491,19 +491,19 @@ void InitWindow(int width, int height, void *state) int orientation = AConfiguration_getOrientation(app->config); - if (orientation == ACONFIGURATION_ORIENTATION_PORT) TraceLog(INFO, "PORTRAIT window orientation"); - else if (orientation == ACONFIGURATION_ORIENTATION_LAND) TraceLog(INFO, "LANDSCAPE window orientation"); + if (orientation == ACONFIGURATION_ORIENTATION_PORT) TraceLog(LOG_INFO, "PORTRAIT window orientation"); + else if (orientation == ACONFIGURATION_ORIENTATION_LAND) TraceLog(LOG_INFO, "LANDSCAPE window orientation"); // TODO: Automatic orientation doesn't seem to work if (width <= height) { AConfiguration_setOrientation(app->config, ACONFIGURATION_ORIENTATION_PORT); - TraceLog(WARNING, "Window set to portraid mode"); + TraceLog(LOG_WARNING, "Window set to portraid mode"); } else { AConfiguration_setOrientation(app->config, ACONFIGURATION_ORIENTATION_LAND); - TraceLog(WARNING, "Window set to landscape mode"); + TraceLog(LOG_WARNING, "Window set to landscape mode"); } //AConfiguration_getDensity(app->config); @@ -517,7 +517,7 @@ void InitWindow(int width, int height, void *state) InitAssetManager(app->activity->assetManager); - TraceLog(INFO, "Android app initialized successfully"); + TraceLog(LOG_INFO, "Android app initialized successfully"); // Wait for window to be initialized (display and context) while (!windowReady) @@ -596,7 +596,7 @@ void CloseWindow(void) pthread_join(gamepadThreadId, NULL); #endif - TraceLog(INFO, "Window closed successfully"); + TraceLog(LOG_INFO, "Window closed successfully"); } // Check if KEY_ESCAPE pressed or Close icon pressed @@ -636,7 +636,7 @@ void ToggleFullscreen(void) #endif #if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) - TraceLog(WARNING, "Could not toggle to windowed mode"); + TraceLog(LOG_WARNING, "Could not toggle to windowed mode"); #endif } @@ -677,9 +677,9 @@ void SetWindowMonitor(int monitor) if ((monitor >= 0) && (monitor < monitorCount)) { glfwSetWindowMonitor(window, monitors[monitor], 0, 0, screenWidth, screenHeight, GLFW_DONT_CARE); - TraceLog(INFO, "Selected fullscreen monitor: [%i] %s", monitor, glfwGetMonitorName(monitors[monitor])); + TraceLog(LOG_INFO, "Selected fullscreen monitor: [%i] %s", monitor, glfwGetMonitorName(monitors[monitor])); } - else TraceLog(WARNING, "Selected monitor not found"); + else TraceLog(LOG_WARNING, "Selected monitor not found"); #endif } @@ -977,7 +977,7 @@ Ray GetMouseRay(Vector2 mousePosition, Camera camera) // Store values in a vector Vector3 deviceCoords = { x, y, z }; - TraceLog(DEBUG, "Device coordinates: (%f, %f, %f)", deviceCoords.x, deviceCoords.y, deviceCoords.z); + TraceLog(LOG_DEBUG, "Device coordinates: (%f, %f, %f)", deviceCoords.x, deviceCoords.y, deviceCoords.z); // Calculate projection matrix (from perspective instead of frustum) Matrix matProj = MatrixPerspective(camera.fovy, ((double)GetScreenWidth()/(double)GetScreenHeight()), 0.01, 1000.0); @@ -1069,7 +1069,7 @@ void SetTargetFPS(int fps) if (fps < 1) targetTime = 0.0; else targetTime = 1.0/(double)fps; - TraceLog(INFO, "Target time per frame: %02.03f milliseconds", (float)targetTime*1000); + TraceLog(LOG_INFO, "Target time per frame: %02.03f milliseconds", (float)targetTime*1000); } // Returns current FPS @@ -1205,7 +1205,7 @@ void TakeScreenshot(const char *fileName) SavePNG(fileName, imgData, renderWidth, renderHeight, 4); // Save image as PNG free(imgData); - TraceLog(INFO, "Screenshot taken: %s", fileName); + TraceLog(LOG_INFO, "Screenshot taken: %s", fileName); #endif } @@ -1304,7 +1304,7 @@ void StorageSaveValue(int position, int value) // If file doesn't exist, create a new storage data file if (!storageFile) storageFile = fopen(path, "wb"); - if (!storageFile) TraceLog(WARNING, "Storage data file could not be created"); + if (!storageFile) TraceLog(LOG_WARNING, "Storage data file could not be created"); else { // Get file size @@ -1312,7 +1312,7 @@ void StorageSaveValue(int position, int value) int fileSize = ftell(storageFile); // Size in bytes fseek(storageFile, 0, SEEK_SET); - if (fileSize < (position*4)) TraceLog(WARNING, "Storage position could not be found"); + if (fileSize < (position*4)) TraceLog(LOG_WARNING, "Storage position could not be found"); else { fseek(storageFile, (position*4), SEEK_SET); @@ -1341,7 +1341,7 @@ int StorageLoadValue(int position) // Try open existing file to append data FILE *storageFile = fopen(path, "rb"); - if (!storageFile) TraceLog(WARNING, "Storage data file could not be found"); + if (!storageFile) TraceLog(LOG_WARNING, "Storage data file could not be found"); else { // Get file size @@ -1349,7 +1349,7 @@ int StorageLoadValue(int position) int fileSize = ftell(storageFile); // Size in bytes rewind(storageFile); - if (fileSize < (position*4)) TraceLog(WARNING, "Storage position could not be found"); + if (fileSize < (position*4)) TraceLog(LOG_WARNING, "Storage position could not be found"); else { fseek(storageFile, (position*4), SEEK_SET); @@ -1675,7 +1675,7 @@ Vector2 GetTouchPosition(int index) #if defined(PLATFORM_ANDROID) || defined(PLATFORM_WEB) if (index < MAX_TOUCH_POINTS) position = touchPosition[index]; - else TraceLog(WARNING, "Required touch point out of range (Max touch points: %i)", MAX_TOUCH_POINTS); + else TraceLog(LOG_WARNING, "Required touch point out of range (Max touch points: %i)", MAX_TOUCH_POINTS); if ((screenWidth > displayWidth) || (screenHeight > displayHeight)) { @@ -1716,7 +1716,7 @@ static void InitGraphicsDevice(int width, int height) #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) glfwSetErrorCallback(ErrorCallback); - if (!glfwInit()) TraceLog(ERROR, "Failed to initialize GLFW"); + if (!glfwInit()) TraceLog(LOG_ERROR, "Failed to initialize GLFW"); // NOTE: Getting video modes is not implemented in emscripten GLFW3 version #if defined(PLATFORM_DESKTOP) @@ -1752,7 +1752,7 @@ static void InitGraphicsDevice(int width, int height) if (configFlags & FLAG_MSAA_4X_HINT) { glfwWindowHint(GLFW_SAMPLES, 4); // Enables multisampling x4 (MSAA), default is 0 - TraceLog(INFO, "Trying to enable MSAA x4"); + TraceLog(LOG_INFO, "Trying to enable MSAA x4"); } //glfwWindowHint(GLFW_RED_BITS, 8); // Framebuffer red color component bits @@ -1805,7 +1805,7 @@ static void InitGraphicsDevice(int width, int height) } } - TraceLog(WARNING, "Closest fullscreen videomode: %i x %i", displayWidth, displayHeight); + TraceLog(LOG_WARNING, "Closest fullscreen videomode: %i x %i", displayWidth, displayHeight); // NOTE: ISSUE: Closest videomode could not match monitor aspect-ratio, for example, // for a desired screen size of 800x450 (16:9), closest supported videomode is 800x600 (4:3), @@ -1844,17 +1844,17 @@ static void InitGraphicsDevice(int width, int height) if (!window) { glfwTerminate(); - TraceLog(ERROR, "GLFW Failed to initialize Window"); + TraceLog(LOG_ERROR, "GLFW Failed to initialize Window"); } else { - TraceLog(INFO, "Display device initialized successfully"); + TraceLog(LOG_INFO, "Display device initialized successfully"); #if defined(PLATFORM_DESKTOP) - TraceLog(INFO, "Display size: %i x %i", displayWidth, displayHeight); + TraceLog(LOG_INFO, "Display size: %i x %i", displayWidth, displayHeight); #endif - TraceLog(INFO, "Render size: %i x %i", renderWidth, renderHeight); - TraceLog(INFO, "Screen size: %i x %i", screenWidth, screenHeight); - TraceLog(INFO, "Viewport offsets: %i, %i", renderOffsetX, renderOffsetY); + TraceLog(LOG_INFO, "Render size: %i x %i", renderWidth, renderHeight); + TraceLog(LOG_INFO, "Screen size: %i x %i", screenWidth, screenHeight); + TraceLog(LOG_INFO, "Viewport offsets: %i, %i", renderOffsetX, renderOffsetY); } glfwSetWindowSizeCallback(window, WindowSizeCallback); // NOTE: Resizing not allowed by default! @@ -1886,7 +1886,7 @@ static void InitGraphicsDevice(int width, int height) if (configFlags & FLAG_VSYNC_HINT) { glfwSwapInterval(1); - TraceLog(INFO, "Trying to enable VSYNC"); + TraceLog(LOG_INFO, "Trying to enable VSYNC"); } #endif // defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) @@ -1914,7 +1914,7 @@ static void InitGraphicsDevice(int width, int height) { samples = 4; sampleBuffer = 1; - TraceLog(INFO, "Trying to enable MSAA x4"); + TraceLog(LOG_INFO, "Trying to enable MSAA x4"); } const EGLint framebufferAttribs[] = @@ -2022,7 +2022,7 @@ static void InitGraphicsDevice(int width, int height) if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) { - TraceLog(ERROR, "Unable to attach EGL rendering context to EGL surface"); + TraceLog(LOG_ERROR, "Unable to attach EGL rendering context to EGL surface"); } else { @@ -2030,11 +2030,11 @@ static void InitGraphicsDevice(int width, int height) //eglQuerySurface(display, surface, EGL_WIDTH, &renderWidth); //eglQuerySurface(display, surface, EGL_HEIGHT, &renderHeight); - TraceLog(INFO, "Display device initialized successfully"); - TraceLog(INFO, "Display size: %i x %i", displayWidth, displayHeight); - TraceLog(INFO, "Render size: %i x %i", renderWidth, renderHeight); - TraceLog(INFO, "Screen size: %i x %i", screenWidth, screenHeight); - TraceLog(INFO, "Viewport offsets: %i, %i", renderOffsetX, renderOffsetY); + TraceLog(LOG_INFO, "Display device initialized successfully"); + TraceLog(LOG_INFO, "Display size: %i x %i", displayWidth, displayHeight); + TraceLog(LOG_INFO, "Render size: %i x %i", renderWidth, renderHeight); + TraceLog(LOG_INFO, "Screen size: %i x %i", screenWidth, screenHeight); + TraceLog(LOG_INFO, "Viewport offsets: %i, %i", renderOffsetX, renderOffsetY); } #endif // defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) @@ -2085,7 +2085,7 @@ static void SetupFramebufferSize(int displayWidth, int displayHeight) // Calculate renderWidth and renderHeight, we have the display size (input params) and the desired screen size (global var) if ((screenWidth > displayWidth) || (screenHeight > displayHeight)) { - TraceLog(WARNING, "DOWNSCALING: Required screen size (%ix%i) is bigger than display size (%ix%i)", screenWidth, screenHeight, displayWidth, displayHeight); + TraceLog(LOG_WARNING, "DOWNSCALING: Required screen size (%ix%i) is bigger than display size (%ix%i)", screenWidth, screenHeight, displayWidth, displayHeight); // Downscaling to fit display with border-bars float widthRatio = (float)displayWidth/(float)screenWidth; @@ -2116,12 +2116,12 @@ static void SetupFramebufferSize(int displayWidth, int displayHeight) renderWidth = displayWidth; renderHeight = displayHeight; - TraceLog(WARNING, "Downscale matrix generated, content will be rendered at: %i x %i", renderWidth, renderHeight); + TraceLog(LOG_WARNING, "Downscale matrix generated, content will be rendered at: %i x %i", renderWidth, renderHeight); } else if ((screenWidth < displayWidth) || (screenHeight < displayHeight)) { // Required screen size is smaller than display size - TraceLog(INFO, "UPSCALING: Required screen size: %i x %i -> Display size: %i x %i", screenWidth, screenHeight, displayWidth, displayHeight); + TraceLog(LOG_INFO, "UPSCALING: Required screen size: %i x %i -> Display size: %i x %i", screenWidth, screenHeight, displayWidth, displayHeight); // Upscaling to fit display with border-bars float displayRatio = (float)displayWidth/(float)displayHeight; @@ -2167,7 +2167,7 @@ static void InitTimer(void) { baseTime = (uint64_t)now.tv_sec*1000000000LLU + (uint64_t)now.tv_nsec; } - else TraceLog(WARNING, "No hi-resolution timer available"); + else TraceLog(LOG_WARNING, "No hi-resolution timer available"); #endif previousTime = GetTime(); // Get time as double @@ -2397,7 +2397,7 @@ static void PollInputEvents(void) // NOTE: Never close window, native activity is controlled by the system! if (app->destroyRequested != 0) { - //TraceLog(INFO, "Closing Window..."); + //TraceLog(LOG_INFO, "Closing Window..."); //windowShouldClose = true; //ANativeActivity_finish(app->activity); } @@ -2431,7 +2431,7 @@ static void SwapBuffers(void) // GLFW3 Error Callback, runs on GLFW3 error static void ErrorCallback(int error, const char *description) { - TraceLog(WARNING, "[GLFW3 Error] Code: %i Decription: %s", error, description); + TraceLog(LOG_WARNING, "[GLFW3 Error] Code: %i Decription: %s", error, description); } // GLFW3 Srolling Callback, runs on mouse wheel @@ -2460,7 +2460,7 @@ static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, i GifEnd(); gifRecording = false; - TraceLog(INFO, "End animated GIF recording"); + TraceLog(LOG_INFO, "End animated GIF recording"); } else { @@ -2472,7 +2472,7 @@ static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, i GifBegin(FormatText("screenrec%03i.gif", screenshotCounter), screenWidth, screenHeight, (int)(GetFrameTime()*10.0f), 8, false); screenshotCounter++; - TraceLog(INFO, "Begin animated GIF recording: %s", FormatText("screenrec%03i.gif", screenshotCounter)); + TraceLog(LOG_INFO, "Begin animated GIF recording: %s", FormatText("screenrec%03i.gif", screenshotCounter)); } } else @@ -2557,7 +2557,7 @@ static void CharCallback(GLFWwindow *window, unsigned int key) { lastKeyPressed = key; - //TraceLog(INFO, "Char Callback Key pressed: %i\n", key); + //TraceLog(LOG_INFO, "Char Callback Key pressed: %i\n", key); } // GLFW3 CursorEnter Callback, when cursor enters the window @@ -2626,15 +2626,15 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd) case APP_CMD_START: { //rendering = true; - TraceLog(INFO, "APP_CMD_START"); + TraceLog(LOG_INFO, "APP_CMD_START"); } break; case APP_CMD_RESUME: { - TraceLog(INFO, "APP_CMD_RESUME"); + TraceLog(LOG_INFO, "APP_CMD_RESUME"); } break; case APP_CMD_INIT_WINDOW: { - TraceLog(INFO, "APP_CMD_INIT_WINDOW"); + TraceLog(LOG_INFO, "APP_CMD_INIT_WINDOW"); if (app->window != NULL) { @@ -2691,18 +2691,18 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd) } break; case APP_CMD_GAINED_FOCUS: { - TraceLog(INFO, "APP_CMD_GAINED_FOCUS"); + TraceLog(LOG_INFO, "APP_CMD_GAINED_FOCUS"); appEnabled = true; //ResumeMusicStream(); } break; case APP_CMD_PAUSE: { - TraceLog(INFO, "APP_CMD_PAUSE"); + TraceLog(LOG_INFO, "APP_CMD_PAUSE"); } break; case APP_CMD_LOST_FOCUS: { //DrawFrame(); - TraceLog(INFO, "APP_CMD_LOST_FOCUS"); + TraceLog(LOG_INFO, "APP_CMD_LOST_FOCUS"); appEnabled = false; //PauseMusicStream(); } break; @@ -2716,22 +2716,22 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd) contextRebindRequired = true; - TraceLog(INFO, "APP_CMD_TERM_WINDOW"); + TraceLog(LOG_INFO, "APP_CMD_TERM_WINDOW"); } break; case APP_CMD_SAVE_STATE: { - TraceLog(INFO, "APP_CMD_SAVE_STATE"); + TraceLog(LOG_INFO, "APP_CMD_SAVE_STATE"); } break; case APP_CMD_STOP: { - TraceLog(INFO, "APP_CMD_STOP"); + TraceLog(LOG_INFO, "APP_CMD_STOP"); } break; case APP_CMD_DESTROY: { // TODO: Finish activity? //ANativeActivity_finish(app->activity); - TraceLog(INFO, "APP_CMD_DESTROY"); + TraceLog(LOG_INFO, "APP_CMD_DESTROY"); } break; case APP_CMD_CONFIG_CHANGED: { @@ -2740,7 +2740,7 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd) // Check screen orientation here! - TraceLog(INFO, "APP_CMD_CONFIG_CHANGED"); + TraceLog(LOG_INFO, "APP_CMD_CONFIG_CHANGED"); } break; default: break; } @@ -2848,11 +2848,11 @@ static EM_BOOL EmscriptenFullscreenChangeCallback(int eventType, const Emscripte if (e->isFullscreen) { - TraceLog(INFO, "Canvas scaled to fullscreen. ElementSize: (%ix%i), ScreenSize(%ix%i)", e->elementWidth, e->elementHeight, e->screenWidth, e->screenHeight); + TraceLog(LOG_INFO, "Canvas scaled to fullscreen. ElementSize: (%ix%i), ScreenSize(%ix%i)", e->elementWidth, e->elementHeight, e->screenWidth, e->screenHeight); } else { - TraceLog(INFO, "Canvas scaled to windowed. ElementSize: (%ix%i), ScreenSize(%ix%i)", e->elementWidth, e->elementHeight, e->screenWidth, e->screenHeight); + TraceLog(LOG_INFO, "Canvas scaled to windowed. ElementSize: (%ix%i), ScreenSize(%ix%i)", e->elementWidth, e->elementHeight, e->screenWidth, e->screenHeight); } // TODO: Depending on scaling factor (screen vs element), calculate factor to scale mouse/touch input @@ -2885,7 +2885,7 @@ static EM_BOOL EmscriptenMouseCallback(int eventType, const EmscriptenMouseEvent { emscripten_exit_pointerlock(); emscripten_get_pointerlock_status(&plce); - //if (plce.isActive) TraceLog(WARNING, "Pointer lock exit did not work!"); + //if (plce.isActive) TraceLog(LOG_WARNING, "Pointer lock exit did not work!"); } toggleCursorLock = false; @@ -3011,7 +3011,7 @@ static void InitKeyboard(void) if (ioctl(STDIN_FILENO, KDGKBMODE, &defaultKeyboardMode) < 0) { // NOTE: It could mean we are using a remote keyboard through ssh! - TraceLog(WARNING, "Could not change keyboard mode (SSH keyboard?)"); + TraceLog(LOG_WARNING, "Could not change keyboard mode (SSH keyboard?)"); } else { @@ -3046,7 +3046,7 @@ static void ProcessKeyboard(void) // Fill all read bytes (looking for keys) for (int i = 0; i < bufferByteCount; i++) { - TraceLog(DEBUG, "Bytes on keysBuffer: %i", bufferByteCount); + TraceLog(LOG_DEBUG, "Bytes on keysBuffer: %i", bufferByteCount); //printf("Key(s) bytes: "); //for (int i = 0; i < bufferByteCount; i++) printf("0x%02x ", keysBuffer[i]); @@ -3107,7 +3107,7 @@ static void ProcessKeyboard(void) else if (keysBuffer[i] == 0x7f) currentKeyState[259] = 1; // raylib KEY_BACKSPACE else { - TraceLog(DEBUG, "Pressed key (ASCII): 0x%02x", keysBuffer[i]); + TraceLog(LOG_DEBUG, "Pressed key (ASCII): 0x%02x", keysBuffer[i]); // Translate lowercase a-z letters to A-Z if ((keysBuffer[i] >= 97) && (keysBuffer[i] <= 122)) @@ -3145,7 +3145,7 @@ static void InitMouse(void) // NOTE: We can use /dev/input/mice to read from all available mice if ((mouseStream = open(DEFAULT_MOUSE_DEV, O_RDONLY|O_NONBLOCK)) < 0) { - TraceLog(WARNING, "Mouse device could not be opened, no mouse available"); + TraceLog(LOG_WARNING, "Mouse device could not be opened, no mouse available"); } else { @@ -3153,8 +3153,8 @@ static void InitMouse(void) int error = pthread_create(&mouseThreadId, NULL, &MouseThread, NULL); - if (error != 0) TraceLog(WARNING, "Error creating mouse input event thread"); - else TraceLog(INFO, "Mouse device initialized successfully"); + if (error != 0) TraceLog(LOG_WARNING, "Error creating mouse input event thread"); + else TraceLog(LOG_INFO, "Mouse device initialized successfully"); } } @@ -3224,7 +3224,7 @@ static void InitTouch(void) { if ((touchStream = open(DEFAULT_TOUCH_DEV, O_RDONLY|O_NONBLOCK)) < 0) { - TraceLog(WARNING, "Touch device could not be opened, no touchscreen available"); + TraceLog(LOG_WARNING, "Touch device could not be opened, no touchscreen available"); } else { @@ -3232,8 +3232,8 @@ static void InitTouch(void) int error = pthread_create(&touchThreadId, NULL, &TouchThread, NULL); - if (error != 0) TraceLog(WARNING, "Error creating touch input event thread"); - else TraceLog(INFO, "Touch device initialized successfully"); + if (error != 0) TraceLog(LOG_WARNING, "Error creating touch input event thread"); + else TraceLog(LOG_INFO, "Touch device initialized successfully"); } } @@ -3335,7 +3335,7 @@ static void InitGamepad(void) if ((gamepadStream[i] = open(gamepadDev, O_RDONLY|O_NONBLOCK)) < 0) { // NOTE: Only show message for first gamepad - if (i == 0) TraceLog(WARNING, "Gamepad device could not be opened, no gamepad available"); + if (i == 0) TraceLog(LOG_WARNING, "Gamepad device could not be opened, no gamepad available"); } else { @@ -3346,8 +3346,8 @@ static void InitGamepad(void) { int error = pthread_create(&gamepadThreadId, NULL, &GamepadThread, NULL); - if (error != 0) TraceLog(WARNING, "Error creating gamepad input event thread"); - else TraceLog(INFO, "Gamepad device initialized successfully"); + if (error != 0) TraceLog(LOG_WARNING, "Error creating gamepad input event thread"); + else TraceLog(LOG_INFO, "Gamepad device initialized successfully"); } } } @@ -3381,7 +3381,7 @@ static void *GamepadThread(void *arg) // Process gamepad events by type if (gamepadEvent.type == JS_EVENT_BUTTON) { - TraceLog(DEBUG, "Gamepad button: %i, value: %i", gamepadEvent.number, gamepadEvent.value); + TraceLog(LOG_DEBUG, "Gamepad button: %i, value: %i", gamepadEvent.number, gamepadEvent.value); if (gamepadEvent.number < MAX_GAMEPAD_BUTTONS) { @@ -3394,7 +3394,7 @@ static void *GamepadThread(void *arg) } else if (gamepadEvent.type == JS_EVENT_AXIS) { - TraceLog(DEBUG, "Gamepad axis: %i, value: %i", gamepadEvent.number, gamepadEvent.value); + TraceLog(LOG_DEBUG, "Gamepad axis: %i, value: %i", gamepadEvent.number, gamepadEvent.value); if (gamepadEvent.number < MAX_GAMEPAD_AXIS) { diff --git a/src/models.c b/src/models.c index 8a70a811..286581df 100644 --- a/src/models.c +++ b/src/models.c @@ -595,10 +595,10 @@ Mesh LoadMesh(const char *fileName) #if defined(SUPPORT_FILEFORMAT_OBJ) if (IsFileExtension(fileName, ".obj")) mesh = LoadOBJ(fileName); #else - TraceLog(WARNING, "[%s] Mesh fileformat not supported, it can't be loaded", fileName); + TraceLog(LOG_WARNING, "[%s] Mesh fileformat not supported, it can't be loaded", fileName); #endif - if (mesh.vertexCount == 0) TraceLog(WARNING, "Mesh could not be loaded"); + if (mesh.vertexCount == 0) TraceLog(LOG_WARNING, "Mesh could not be loaded"); else rlglLoadMesh(&mesh, false); // Upload vertex data to GPU (static mesh) // TODO: Initialize default mesh data in case loading fails, maybe a cube? @@ -697,7 +697,7 @@ void UnloadModel(Model model) UnloadMesh(&model.mesh); UnloadMaterial(model.material); - TraceLog(INFO, "Unloaded model data (mesh and material) from RAM and VRAM"); + TraceLog(LOG_INFO, "Unloaded model data (mesh and material) from RAM and VRAM"); } // Load material data (from file) @@ -708,7 +708,7 @@ Material LoadMaterial(const char *fileName) #if defined(SUPPORT_FILEFORMAT_MTL) if (IsFileExtension(fileName, ".mtl")) material = LoadMTL(fileName); #else - TraceLog(WARNING, "[%s] Material fileformat not supported, it can't be loaded", fileName); + TraceLog(LOG_WARNING, "[%s] Material fileformat not supported, it can't be loaded", fileName); #endif return material; @@ -1628,7 +1628,7 @@ static Mesh LoadOBJ(const char *fileName) if (objFile == NULL) { - TraceLog(WARNING, "[%s] OBJ file could not be opened", fileName); + TraceLog(LOG_WARNING, "[%s] OBJ file could not be opened", fileName); return mesh; } @@ -1680,10 +1680,10 @@ static Mesh LoadOBJ(const char *fileName) } } - TraceLog(DEBUG, "[%s] Model vertices: %i", fileName, vertexCount); - TraceLog(DEBUG, "[%s] Model texcoords: %i", fileName, texcoordCount); - TraceLog(DEBUG, "[%s] Model normals: %i", fileName, normalCount); - TraceLog(DEBUG, "[%s] Model triangles: %i", fileName, triangleCount); + TraceLog(LOG_DEBUG, "[%s] Model vertices: %i", fileName, vertexCount); + TraceLog(LOG_DEBUG, "[%s] Model texcoords: %i", fileName, texcoordCount); + TraceLog(LOG_DEBUG, "[%s] Model normals: %i", fileName, normalCount); + TraceLog(LOG_DEBUG, "[%s] Model triangles: %i", fileName, triangleCount); // Once we know the number of vertices to store, we create required arrays Vector3 *midVertices = (Vector3 *)malloc(vertexCount*sizeof(Vector3)); @@ -1757,7 +1757,7 @@ static Mesh LoadOBJ(const char *fileName) rewind(objFile); // Return to the beginning of the file, to read again - if (normalCount == 0) TraceLog(INFO, "[%s] No normals data on OBJ, normals will be generated from faces data", fileName); + if (normalCount == 0) TraceLog(LOG_INFO, "[%s] No normals data on OBJ, normals will be generated from faces data", fileName); // Third reading pass: Get faces (triangles) data and fill VertexArray while (!feof(objFile)) @@ -1924,7 +1924,7 @@ static Mesh LoadOBJ(const char *fileName) free(midTexCoords); // NOTE: At this point we have all vertex, texcoord, normal data for the model in mesh struct - TraceLog(INFO, "[%s] Model loaded successfully in RAM (CPU)", fileName); + TraceLog(LOG_INFO, "[%s] Model loaded successfully in RAM (CPU)", fileName); return mesh; } @@ -1950,7 +1950,7 @@ static Material LoadMTL(const char *fileName) if (mtlFile == NULL) { - TraceLog(WARNING, "[%s] MTL file could not be opened", fileName); + TraceLog(LOG_WARNING, "[%s] MTL file could not be opened", fileName); return material; } @@ -1965,7 +1965,7 @@ static Material LoadMTL(const char *fileName) // TODO: Support multiple materials in a single .mtl sscanf(buffer, "newmtl %s", mapFileName); - TraceLog(INFO, "[%s] Loading material...", mapFileName); + TraceLog(LOG_INFO, "[%s] Loading material...", mapFileName); } case 'i': // illum int Illumination model { @@ -2090,7 +2090,7 @@ static Material LoadMTL(const char *fileName) fclose(mtlFile); // NOTE: At this point we have all material data - TraceLog(INFO, "[%s] Material loaded successfully", fileName); + TraceLog(LOG_INFO, "[%s] Material loaded successfully", fileName); return material; } diff --git a/src/raylib.h b/src/raylib.h index 0a4ce091..3d09eff0 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -1,6 +1,6 @@ /********************************************************************************************** * -* raylib v1.7.0 +* raylib v1.8.0 * * A simple and easy-to-use library to learn videogames programming (www.raylib.com) * @@ -533,11 +533,11 @@ typedef struct RRESData *RRES; //---------------------------------------------------------------------------------- // Trace log type typedef enum { - INFO = 0, - WARNING, - ERROR, - DEBUG, - OTHER + LOG_INFO = 0, + LOG_WARNING, + LOG_ERROR, + LOG_DEBUG, + LOG_OTHER } LogType; // Texture formats @@ -711,11 +711,10 @@ RLAPI float *MatrixToFloat(Matrix mat); // Converts Ma // Misc. functions RLAPI void ShowLogo(void); // Activate raylib logo at startup (can be done with flags) RLAPI void SetConfigFlags(char flags); // Setup window configuration flags (view FLAGS) -RLAPI void TraceLog(int logType, const char *text, ...); // Show trace log messages (INFO, WARNING, ERROR, DEBUG) +RLAPI void TraceLog(int logType, const char *text, ...); // Show trace log messages (LOG_INFO, LOG_WARNING, LOG_ERROR, LOG_DEBUG) RLAPI void TakeScreenshot(const char *fileName); // Takes a screenshot of current screen (saved a .png) RLAPI int GetRandomValue(int min, int max); // Returns a random value between min and max (both included) - // Files management functions RLAPI bool IsFileExtension(const char *fileName, const char *ext);// Check file extension RLAPI const char *GetDirectoryPath(const char *fileName); // Get directory for a given fileName (with path) diff --git a/src/rlgl.c b/src/rlgl.c index a40836ca..e3576c30 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -415,7 +415,7 @@ void rlPushMatrix(void) { if (stackCounter == MATRIX_STACK_SIZE - 1) { - TraceLog(ERROR, "Stack Buffer Overflow (MAX %i Matrix)", MATRIX_STACK_SIZE); + TraceLog(LOG_ERROR, "Stack Buffer Overflow (MAX %i Matrix)", MATRIX_STACK_SIZE); } stack[stackCounter] = *currentMatrix; @@ -678,7 +678,7 @@ void rlVertex3f(float x, float y, float z) lines.vCounter++; } - else TraceLog(ERROR, "MAX_LINES_BATCH overflow"); + else TraceLog(LOG_ERROR, "MAX_LINES_BATCH overflow"); } break; case RL_TRIANGLES: @@ -692,7 +692,7 @@ void rlVertex3f(float x, float y, float z) triangles.vCounter++; } - else TraceLog(ERROR, "MAX_TRIANGLES_BATCH overflow"); + else TraceLog(LOG_ERROR, "MAX_TRIANGLES_BATCH overflow"); } break; case RL_QUADS: @@ -708,7 +708,7 @@ void rlVertex3f(float x, float y, float z) draws[drawsCounter - 1].vertexCount++; } - else TraceLog(ERROR, "MAX_QUADS_BATCH overflow"); + else TraceLog(LOG_ERROR, "MAX_QUADS_BATCH overflow"); } break; default: break; @@ -847,7 +847,7 @@ void rlTextureParameters(unsigned int id, int param, int value) case RL_TEXTURE_WRAP_S: case RL_TEXTURE_WRAP_T: { - if ((value == RL_WRAP_CLAMP_MIRROR) && !texClampMirrorSupported) TraceLog(WARNING, "Clamp mirror wrap mode not supported"); + if ((value == RL_WRAP_CLAMP_MIRROR) && !texClampMirrorSupported) TraceLog(LOG_WARNING, "Clamp mirror wrap mode not supported"); else glTexParameteri(GL_TEXTURE_2D, param, value); } break; case RL_TEXTURE_MAG_FILTER: @@ -857,10 +857,10 @@ void rlTextureParameters(unsigned int id, int param, int value) if (value <= maxAnisotropicLevel) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)value); else if (maxAnisotropicLevel > 0.0f) { - TraceLog(WARNING, "[TEX ID %i] Maximum anisotropic filter level supported is %iX", id, maxAnisotropicLevel); + TraceLog(LOG_WARNING, "[TEX ID %i] Maximum anisotropic filter level supported is %iX", id, maxAnisotropicLevel); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)value); } - else TraceLog(WARNING, "Anisotropic filtering not supported"); + else TraceLog(LOG_WARNING, "Anisotropic filtering not supported"); } break; default: break; } @@ -934,7 +934,7 @@ void rlDeleteRenderTextures(RenderTexture2D target) if (target.texture.id != 0) glDeleteTextures(1, &target.texture.id); if (target.depth.id != 0) glDeleteTextures(1, &target.depth.id); - TraceLog(INFO, "[FBO ID %i] Unloaded render texture data from VRAM (GPU)", target.id); + TraceLog(LOG_INFO, "[FBO ID %i] Unloaded render texture data from VRAM (GPU)", target.id); #endif } @@ -953,7 +953,7 @@ void rlDeleteVertexArrays(unsigned int id) if (vaoSupported) { if (id != 0) glDeleteVertexArrays(1, &id); - TraceLog(INFO, "[VAO ID %i] Unloaded model data from VRAM (GPU)", id); + TraceLog(LOG_INFO, "[VAO ID %i] Unloaded model data from VRAM (GPU)", id); } #endif } @@ -965,7 +965,7 @@ void rlDeleteBuffers(unsigned int id) if (id != 0) { glDeleteBuffers(1, &id); - if (!vaoSupported) TraceLog(INFO, "[VBO ID %i] Unloaded model vertex data from VRAM (GPU)", id); + if (!vaoSupported) TraceLog(LOG_INFO, "[VBO ID %i] Unloaded model vertex data from VRAM (GPU)", id); } #endif } @@ -1014,33 +1014,33 @@ void rlglInit(int width, int height) //------------------------------------------------------------------------------ // Print current OpenGL and GLSL version - TraceLog(INFO, "GPU: Vendor: %s", glGetString(GL_VENDOR)); - TraceLog(INFO, "GPU: Renderer: %s", glGetString(GL_RENDERER)); - TraceLog(INFO, "GPU: Version: %s", glGetString(GL_VERSION)); - TraceLog(INFO, "GPU: GLSL: %s", glGetString(GL_SHADING_LANGUAGE_VERSION)); + TraceLog(LOG_INFO, "GPU: Vendor: %s", glGetString(GL_VENDOR)); + TraceLog(LOG_INFO, "GPU: Renderer: %s", glGetString(GL_RENDERER)); + TraceLog(LOG_INFO, "GPU: Version: %s", glGetString(GL_VERSION)); + TraceLog(LOG_INFO, "GPU: GLSL: %s", glGetString(GL_SHADING_LANGUAGE_VERSION)); // NOTE: We can get a bunch of extra information about GPU capabilities (glGet*) //int maxTexSize; //glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTexSize); - //TraceLog(INFO, "GL_MAX_TEXTURE_SIZE: %i", maxTexSize); + //TraceLog(LOG_INFO, "GL_MAX_TEXTURE_SIZE: %i", maxTexSize); //GL_MAX_TEXTURE_IMAGE_UNITS //GL_MAX_VIEWPORT_DIMS //int numAuxBuffers; //glGetIntegerv(GL_AUX_BUFFERS, &numAuxBuffers); - //TraceLog(INFO, "GL_AUX_BUFFERS: %i", numAuxBuffers); + //TraceLog(LOG_INFO, "GL_AUX_BUFFERS: %i", numAuxBuffers); //GLint numComp = 0; //GLint format[32] = { 0 }; //glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numComp); //glGetIntegerv(GL_COMPRESSED_TEXTURE_FORMATS, format); - //for (int i = 0; i < numComp; i++) TraceLog(INFO, "Supported compressed format: 0x%x", format[i]); + //for (int i = 0; i < numComp; i++) TraceLog(LOG_INFO, "Supported compressed format: 0x%x", format[i]); // NOTE: We don't need that much data on screen... right now... #if defined(GRAPHICS_API_OPENGL_11) - //TraceLog(INFO, "OpenGL 1.1 (or driver default) profile initialized"); + //TraceLog(LOG_INFO, "OpenGL 1.1 (or driver default) profile initialized"); #endif #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) @@ -1096,10 +1096,10 @@ void rlglInit(int width, int height) numExt -= 1; #endif - TraceLog(INFO, "Number of supported extensions: %i", numExt); + TraceLog(LOG_INFO, "Number of supported extensions: %i", numExt); // Show supported extensions - //for (int i = 0; i < numExt; i++) TraceLog(INFO, "Supported extension: %s", extList[i]); + //for (int i = 0; i < numExt; i++) TraceLog(LOG_INFO, "Supported extension: %s", extList[i]); // Check required extensions for (int i = 0; i < numExt; i++) @@ -1161,21 +1161,21 @@ void rlglInit(int width, int height) #endif #if defined(GRAPHICS_API_OPENGL_ES2) - if (vaoSupported) TraceLog(INFO, "[EXTENSION] VAO extension detected, VAO functions initialized successfully"); - else TraceLog(WARNING, "[EXTENSION] VAO extension not found, VAO usage not supported"); + if (vaoSupported) TraceLog(LOG_INFO, "[EXTENSION] VAO extension detected, VAO functions initialized successfully"); + else TraceLog(LOG_WARNING, "[EXTENSION] VAO extension not found, VAO usage not supported"); - if (texNPOTSupported) TraceLog(INFO, "[EXTENSION] NPOT textures extension detected, full NPOT textures supported"); - else TraceLog(WARNING, "[EXTENSION] NPOT textures extension not found, limited NPOT support (no-mipmaps, no-repeat)"); + if (texNPOTSupported) TraceLog(LOG_INFO, "[EXTENSION] NPOT textures extension detected, full NPOT textures supported"); + else TraceLog(LOG_WARNING, "[EXTENSION] NPOT textures extension not found, limited NPOT support (no-mipmaps, no-repeat)"); #endif - if (texCompDXTSupported) TraceLog(INFO, "[EXTENSION] DXT compressed textures supported"); - if (texCompETC1Supported) TraceLog(INFO, "[EXTENSION] ETC1 compressed textures supported"); - if (texCompETC2Supported) TraceLog(INFO, "[EXTENSION] ETC2/EAC compressed textures supported"); - if (texCompPVRTSupported) TraceLog(INFO, "[EXTENSION] PVRT compressed textures supported"); - if (texCompASTCSupported) TraceLog(INFO, "[EXTENSION] ASTC compressed textures supported"); + if (texCompDXTSupported) TraceLog(LOG_INFO, "[EXTENSION] DXT compressed textures supported"); + if (texCompETC1Supported) TraceLog(LOG_INFO, "[EXTENSION] ETC1 compressed textures supported"); + if (texCompETC2Supported) TraceLog(LOG_INFO, "[EXTENSION] ETC2/EAC compressed textures supported"); + if (texCompPVRTSupported) TraceLog(LOG_INFO, "[EXTENSION] PVRT compressed textures supported"); + if (texCompASTCSupported) TraceLog(LOG_INFO, "[EXTENSION] ASTC compressed textures supported"); - if (texAnisotropicFilterSupported) TraceLog(INFO, "[EXTENSION] Anisotropic textures filtering supported (max: %.0fX)", maxAnisotropicLevel); - if (texClampMirrorSupported) TraceLog(INFO, "[EXTENSION] Clamp mirror wrap texture mode supported"); + if (texAnisotropicFilterSupported) TraceLog(LOG_INFO, "[EXTENSION] Anisotropic textures filtering supported (max: %.0fX)", maxAnisotropicLevel); + if (texClampMirrorSupported) TraceLog(LOG_INFO, "[EXTENSION] Clamp mirror wrap texture mode supported"); // Initialize buffers, default shaders and default textures //---------------------------------------------------------- @@ -1185,8 +1185,8 @@ void rlglInit(int width, int height) 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"); + if (whiteTexture != 0) TraceLog(LOG_INFO, "[TEX ID %i] Base white texture loaded successfully", whiteTexture); + else TraceLog(LOG_WARNING, "Base white texture could not be loaded"); // Init default Shader (customized for GL 3.3 and ES2) defaultShader = LoadDefaultShader(); @@ -1254,7 +1254,7 @@ void rlglInit(int width, int height) screenWidth = width; screenHeight = height; - TraceLog(INFO, "OpenGL default states initialized successfully"); + TraceLog(LOG_INFO, "OpenGL default states initialized successfully"); } // Vertex Buffer Object deinitialization (memory free) @@ -1266,7 +1266,7 @@ void rlglClose(void) // Delete default white texture glDeleteTextures(1, &whiteTexture); - TraceLog(INFO, "[TEX ID %i] Unloaded texture data (base white texture) from VRAM", whiteTexture); + TraceLog(LOG_INFO, "[TEX ID %i] Unloaded texture data (base white texture) from VRAM", whiteTexture); free(draws); #endif @@ -1292,14 +1292,14 @@ void rlglLoadExtensions(void *loader) #if defined(GRAPHICS_API_OPENGL_21) || defined(GRAPHICS_API_OPENGL_33) // NOTE: glad is generated and contains only required OpenGL 3.3 Core extensions (and lower versions) #if !defined(__APPLE__) - if (!gladLoadGLLoader((GLADloadproc)loader)) TraceLog(WARNING, "GLAD: Cannot load OpenGL extensions"); - else TraceLog(INFO, "GLAD: OpenGL extensions loaded successfully"); + if (!gladLoadGLLoader((GLADloadproc)loader)) TraceLog(LOG_WARNING, "GLAD: Cannot load OpenGL extensions"); + else TraceLog(LOG_INFO, "GLAD: OpenGL extensions loaded successfully"); #if defined(GRAPHICS_API_OPENGL_21) - if (GLAD_GL_VERSION_2_1) TraceLog(INFO, "OpenGL 2.1 profile supported"); + if (GLAD_GL_VERSION_2_1) TraceLog(LOG_INFO, "OpenGL 2.1 profile supported"); #elif defined(GRAPHICS_API_OPENGL_33) - if(GLAD_GL_VERSION_3_3) TraceLog(INFO, "OpenGL 3.3 Core profile supported"); - else TraceLog(ERROR, "OpenGL 3.3 Core profile not supported"); + if(GLAD_GL_VERSION_3_3) TraceLog(LOG_INFO, "OpenGL 3.3 Core profile supported"); + else TraceLog(LOG_ERROR, "OpenGL 3.3 Core profile not supported"); #endif #endif @@ -1342,7 +1342,7 @@ unsigned int rlglLoadTexture(void *data, int width, int height, int format, int #if defined(GRAPHICS_API_OPENGL_11) if (format >= COMPRESSED_DXT1_RGB) { - TraceLog(WARNING, "OpenGL 1.1 does not support GPU compressed texture formats"); + TraceLog(LOG_WARNING, "OpenGL 1.1 does not support GPU compressed texture formats"); return id; } #endif @@ -1350,31 +1350,31 @@ unsigned int rlglLoadTexture(void *data, int width, int height, int format, int if ((!texCompDXTSupported) && ((format == COMPRESSED_DXT1_RGB) || (format == COMPRESSED_DXT1_RGBA) || (format == COMPRESSED_DXT3_RGBA) || (format == COMPRESSED_DXT5_RGBA))) { - TraceLog(WARNING, "DXT compressed texture format not supported"); + TraceLog(LOG_WARNING, "DXT compressed texture format not supported"); return id; } #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) if ((!texCompETC1Supported) && (format == COMPRESSED_ETC1_RGB)) { - TraceLog(WARNING, "ETC1 compressed texture format not supported"); + TraceLog(LOG_WARNING, "ETC1 compressed texture format not supported"); return id; } if ((!texCompETC2Supported) && ((format == COMPRESSED_ETC2_RGB) || (format == COMPRESSED_ETC2_EAC_RGBA))) { - TraceLog(WARNING, "ETC2 compressed texture format not supported"); + TraceLog(LOG_WARNING, "ETC2 compressed texture format not supported"); return id; } if ((!texCompPVRTSupported) && ((format == COMPRESSED_PVRT_RGB) || (format == COMPRESSED_PVRT_RGBA))) { - TraceLog(WARNING, "PVRT compressed texture format not supported"); + TraceLog(LOG_WARNING, "PVRT compressed texture format not supported"); return id; } if ((!texCompASTCSupported) && ((format == COMPRESSED_ASTC_4x4_RGBA) || (format == COMPRESSED_ASTC_8x8_RGBA))) { - TraceLog(WARNING, "ASTC compressed texture format not supported"); + TraceLog(LOG_WARNING, "ASTC compressed texture format not supported"); return id; } #endif @@ -1411,7 +1411,7 @@ unsigned int rlglLoadTexture(void *data, int width, int height, int format, int GLint swizzleMask[] = { GL_RED, GL_RED, GL_RED, GL_ONE }; glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); - TraceLog(INFO, "[TEX ID %i] Grayscale texture loaded and swizzled", id); + TraceLog(LOG_INFO, "[TEX ID %i] Grayscale texture loaded and swizzled", id); } break; case UNCOMPRESSED_GRAY_ALPHA: { @@ -1438,7 +1438,7 @@ unsigned int rlglLoadTexture(void *data, int width, int height, int format, int case COMPRESSED_PVRT_RGBA: if (texCompPVRTSupported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG); break; // NOTE: Requires PowerVR GPU case COMPRESSED_ASTC_4x4_RGBA: if (texCompASTCSupported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA_ASTC_4x4_KHR); break; // NOTE: Requires OpenGL ES 3.1 or OpenGL 4.3 case COMPRESSED_ASTC_8x8_RGBA: if (texCompASTCSupported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA_ASTC_8x8_KHR); break; // NOTE: Requires OpenGL ES 3.1 or OpenGL 4.3 - default: TraceLog(WARNING, "Texture format not recognized"); break; + default: TraceLog(LOG_WARNING, "Texture format not recognized"); break; } #elif defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_ES2) // NOTE: on OpenGL ES 2.0 (WebGL), internalFormat must match format and options allowed are: GL_LUMINANCE, GL_RGB, GL_RGBA @@ -1465,7 +1465,7 @@ unsigned int rlglLoadTexture(void *data, int width, int height, int format, int case COMPRESSED_ASTC_4x4_RGBA: if (texCompASTCSupported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA_ASTC_4x4_KHR); break; // NOTE: Requires OpenGL ES 3.1 or OpenGL 4.3 case COMPRESSED_ASTC_8x8_RGBA: if (texCompASTCSupported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA_ASTC_8x8_KHR); break; // NOTE: Requires OpenGL ES 3.1 or OpenGL 4.3 #endif - default: TraceLog(WARNING, "Texture format not supported"); break; + default: TraceLog(LOG_WARNING, "Texture format not supported"); break; } #endif @@ -1508,8 +1508,8 @@ unsigned int rlglLoadTexture(void *data, int width, int height, int format, int // 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"); + if (id > 0) TraceLog(LOG_INFO, "[TEX ID %i] Texture created successfully (%ix%i)", id, width, height); + else TraceLog(LOG_WARNING, "Texture could not be created"); return id; } @@ -1584,16 +1584,16 @@ RenderTexture2D rlglLoadRenderTexture(int width, int height) if (status != GL_FRAMEBUFFER_COMPLETE) { - TraceLog(WARNING, "Framebuffer object could not be created..."); + TraceLog(LOG_WARNING, "Framebuffer object could not be created..."); switch (status) { - case GL_FRAMEBUFFER_UNSUPPORTED: TraceLog(WARNING, "Framebuffer is unsupported"); break; - case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: TraceLog(WARNING, "Framebuffer incomplete attachment"); break; + case GL_FRAMEBUFFER_UNSUPPORTED: TraceLog(LOG_WARNING, "Framebuffer is unsupported"); break; + case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: TraceLog(LOG_WARNING, "Framebuffer incomplete attachment"); break; #if defined(GRAPHICS_API_OPENGL_ES2) - case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: TraceLog(WARNING, "Framebuffer incomplete dimensions"); break; + case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: TraceLog(LOG_WARNING, "Framebuffer incomplete dimensions"); break; #endif - case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: TraceLog(WARNING, "Framebuffer incomplete missing attachment"); break; + case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: TraceLog(LOG_WARNING, "Framebuffer incomplete missing attachment"); break; default: break; } @@ -1601,7 +1601,7 @@ RenderTexture2D rlglLoadRenderTexture(int width, int height) glDeleteTextures(1, &target.depth.id); glDeleteFramebuffers(1, &target.id); } - else TraceLog(INFO, "[FBO ID %i] Framebuffer object created successfully", target.id); + else TraceLog(LOG_INFO, "[FBO ID %i] Framebuffer object created successfully", target.id); glBindFramebuffer(GL_FRAMEBUFFER, 0); #endif @@ -1624,7 +1624,7 @@ void rlglUpdateTexture(unsigned int id, int width, int height, int format, const case UNCOMPRESSED_R5G5B5A1: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, (unsigned short *)data); break; case UNCOMPRESSED_R4G4B4A4: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, (unsigned short *)data); break; case UNCOMPRESSED_R8G8B8A8: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, (unsigned char *)data); break; - default: TraceLog(WARNING, "Texture format updating not supported"); break; + default: TraceLog(LOG_WARNING, "Texture format updating not supported"); break; } #elif defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_ES2) // NOTE: on OpenGL ES 2.0 (WebGL), internalFormat must match format and options allowed are: GL_LUMINANCE, GL_RGB, GL_RGBA @@ -1637,7 +1637,7 @@ void rlglUpdateTexture(unsigned int id, int width, int height, int format, const case UNCOMPRESSED_R5G5B5A1: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, (unsigned short *)data); break; case UNCOMPRESSED_R4G4B4A4: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, (unsigned short *)data); break; case UNCOMPRESSED_R8G8B8A8: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, (unsigned char *)data); break; - default: TraceLog(WARNING, "Texture format updating not supported"); break; + default: TraceLog(LOG_WARNING, "Texture format updating not supported"); break; } #endif } @@ -1681,7 +1681,7 @@ void rlglGenerateMipmaps(Texture2D *texture) mipHeight /= 2; } - TraceLog(WARNING, "[TEX ID %i] Mipmaps generated manually on CPU side", texture->id); + TraceLog(LOG_WARNING, "[TEX ID %i] Mipmaps generated manually on CPU side", texture->id); // NOTE: Once mipmaps have been generated and data has been uploaded to GPU VRAM, we can discard RAM data free(data); @@ -1692,7 +1692,7 @@ void rlglGenerateMipmaps(Texture2D *texture) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) //glHint(GL_GENERATE_MIPMAP_HINT, GL_DONT_CARE); // Hint for mipmaps generation algorythm: GL_FASTEST, GL_NICEST, GL_DONT_CARE glGenerateMipmap(GL_TEXTURE_2D); // Generate mipmaps automatically - TraceLog(INFO, "[TEX ID %i] Mipmaps generated automatically", texture->id); + TraceLog(LOG_INFO, "[TEX ID %i] Mipmaps generated automatically", texture->id); 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 @@ -1703,7 +1703,7 @@ void rlglGenerateMipmaps(Texture2D *texture) texture->mipmaps = 1 + (int)floor(log(MAX(texture->width, texture->height))/log(2)); #endif } - else TraceLog(WARNING, "[TEX ID %i] Mipmaps can not be generated", texture->id); + else TraceLog(LOG_WARNING, "[TEX ID %i] Mipmaps can not be generated", texture->id); glBindTexture(GL_TEXTURE_2D, 0); } @@ -1834,13 +1834,13 @@ void rlglLoadMesh(Mesh *mesh, bool dynamic) if (vaoId > 0) { mesh->vaoId = vaoId; - TraceLog(INFO, "[VAO ID %i] Mesh uploaded successfully to VRAM (GPU)", mesh->vaoId); + TraceLog(LOG_INFO, "[VAO ID %i] Mesh uploaded successfully to VRAM (GPU)", mesh->vaoId); } - else TraceLog(WARNING, "Mesh could not be uploaded to VRAM (GPU)"); + else TraceLog(LOG_WARNING, "Mesh could not be uploaded to VRAM (GPU)"); } else { - TraceLog(INFO, "[VBOs] Mesh uploaded successfully to VRAM (GPU)"); + TraceLog(LOG_INFO, "[VBOs] Mesh uploaded successfully to VRAM (GPU)"); } #endif } @@ -2219,7 +2219,7 @@ void *rlglReadTexturePixels(Texture2D texture) 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 data retrieval, format not suported"); break; + default: TraceLog(LOG_WARNING, "Texture data retrieval, format not suported"); break; } // 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. @@ -2369,7 +2369,7 @@ char *LoadText(const char *fileName) fclose(textFile); } - else TraceLog(WARNING, "[%s] Text file could not be opened", fileName); + else TraceLog(LOG_WARNING, "[%s] Text file could not be opened", fileName); } return text; @@ -2399,7 +2399,7 @@ Shader LoadShader(char *vsFileName, char *fsFileName) if (shader.id == 0) { - TraceLog(WARNING, "Custom shader could not be loaded"); + TraceLog(LOG_WARNING, "Custom shader could not be loaded"); shader = defaultShader; } #endif @@ -2413,7 +2413,7 @@ void UnloadShader(Shader shader) if (shader.id != 0) { rlDeleteShader(shader.id); - TraceLog(INFO, "[SHDR ID %i] Unloaded shader program data", shader.id); + TraceLog(LOG_INFO, "[SHDR ID %i] Unloaded shader program data", shader.id); } } @@ -2455,7 +2455,7 @@ int GetShaderLocation(Shader shader, const char *uniformName) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) location = glGetUniformLocation(shader.id, uniformName); - if (location == -1) TraceLog(DEBUG, "[SHDR ID %i] Shader location for %s could not be found", shader.id, uniformName); + if (location == -1) TraceLog(LOG_DEBUG, "[SHDR ID %i] Shader location for %s could not be found", shader.id, uniformName); #endif return location; } @@ -2470,7 +2470,7 @@ void SetShaderValue(Shader shader, int uniformLoc, float *value, int size) else if (size == 2) glUniform2fv(uniformLoc, 1, value); // Shader uniform type: vec2 else if (size == 3) glUniform3fv(uniformLoc, 1, value); // Shader uniform type: vec3 else if (size == 4) glUniform4fv(uniformLoc, 1, value); // Shader uniform type: vec4 - else TraceLog(WARNING, "Shader value float array size not supported"); + else TraceLog(LOG_WARNING, "Shader value float array size not supported"); //glUseProgram(0); // Avoid reseting current shader program, in case other uniforms are set #endif @@ -2486,7 +2486,7 @@ void SetShaderValuei(Shader shader, int uniformLoc, int *value, int size) 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"); + else TraceLog(LOG_WARNING, "Shader value int array size not supported"); //glUseProgram(0); #endif @@ -2572,7 +2572,7 @@ void InitVrSimulator(int vrDevice) hmd.chromaAbCorrection[2] = 1.014f; // HMD chromatic aberration correction parameter 2 hmd.chromaAbCorrection[3] = 0.0f; // HMD chromatic aberration correction parameter 3 - TraceLog(INFO, "Initializing VR Simulator (Oculus Rift DK2)"); + TraceLog(LOG_INFO, "Initializing VR Simulator (Oculus Rift DK2)"); } else if ((vrDevice == HMD_DEFAULT_DEVICE) || (vrDevice == HMD_OCULUS_RIFT_CV1)) { @@ -2599,12 +2599,12 @@ void InitVrSimulator(int vrDevice) hmd.chromaAbCorrection[2] = 1.014f; // HMD chromatic aberration correction parameter 2 hmd.chromaAbCorrection[3] = 0.0f; // HMD chromatic aberration correction parameter 3 - TraceLog(INFO, "Initializing VR Simulator (Oculus Rift CV1)"); + TraceLog(LOG_INFO, "Initializing VR Simulator (Oculus Rift CV1)"); } else { - TraceLog(WARNING, "VR Simulator doesn't support selected device parameters,"); - TraceLog(WARNING, "using default VR Simulator parameters"); + TraceLog(LOG_WARNING, "VR Simulator doesn't support selected device parameters,"); + TraceLog(LOG_WARNING, "using default VR Simulator parameters"); } // Initialize framebuffer and textures for stereo rendering @@ -2623,7 +2623,7 @@ void InitVrSimulator(int vrDevice) #endif #if defined(GRAPHICS_API_OPENGL_11) - TraceLog(WARNING, "VR Simulator not supported on OpenGL 1.1"); + TraceLog(LOG_WARNING, "VR Simulator not supported on OpenGL 1.1"); #endif } @@ -2843,7 +2843,7 @@ static unsigned int LoadShaderProgram(const char *vShaderStr, const char *fShade if (success != GL_TRUE) { - TraceLog(WARNING, "[VSHDR ID %i] Failed to compile vertex shader...", vertexShader); + TraceLog(LOG_WARNING, "[VSHDR ID %i] Failed to compile vertex shader...", vertexShader); int maxLength = 0; int length; @@ -2857,13 +2857,13 @@ static unsigned int LoadShaderProgram(const char *vShaderStr, const char *fShade #endif glGetShaderInfoLog(vertexShader, maxLength, &length, log); - TraceLog(INFO, "%s", log); + TraceLog(LOG_INFO, "%s", log); #ifdef _MSC_VER free(log); #endif } - else TraceLog(INFO, "[VSHDR ID %i] Vertex shader compiled successfully", vertexShader); + else TraceLog(LOG_INFO, "[VSHDR ID %i] Vertex shader compiled successfully", vertexShader); glCompileShader(fragmentShader); @@ -2871,7 +2871,7 @@ static unsigned int LoadShaderProgram(const char *vShaderStr, const char *fShade if (success != GL_TRUE) { - TraceLog(WARNING, "[FSHDR ID %i] Failed to compile fragment shader...", fragmentShader); + TraceLog(LOG_WARNING, "[FSHDR ID %i] Failed to compile fragment shader...", fragmentShader); int maxLength = 0; int length; @@ -2885,13 +2885,13 @@ static unsigned int LoadShaderProgram(const char *vShaderStr, const char *fShade #endif glGetShaderInfoLog(fragmentShader, maxLength, &length, log); - TraceLog(INFO, "%s", log); + TraceLog(LOG_INFO, "%s", log); #ifdef _MSC_VER free(log); #endif } - else TraceLog(INFO, "[FSHDR ID %i] Fragment shader compiled successfully", fragmentShader); + else TraceLog(LOG_INFO, "[FSHDR ID %i] Fragment shader compiled successfully", fragmentShader); program = glCreateProgram(); @@ -2916,7 +2916,7 @@ static unsigned int LoadShaderProgram(const char *vShaderStr, const char *fShade if (success == GL_FALSE) { - TraceLog(WARNING, "[SHDR ID %i] Failed to link shader program...", program); + TraceLog(LOG_WARNING, "[SHDR ID %i] Failed to link shader program...", program); int maxLength = 0; int length; @@ -2930,7 +2930,7 @@ static unsigned int LoadShaderProgram(const char *vShaderStr, const char *fShade #endif glGetProgramInfoLog(program, maxLength, &length, log); - TraceLog(INFO, "%s", log); + TraceLog(LOG_INFO, "%s", log); #ifdef _MSC_VER free(log); @@ -2939,7 +2939,7 @@ static unsigned int LoadShaderProgram(const char *vShaderStr, const char *fShade program = 0; } - else TraceLog(INFO, "[SHDR ID %i] Shader program loaded successfully", program); + else TraceLog(LOG_INFO, "[SHDR ID %i] Shader program loaded successfully", program); glDeleteShader(vertexShader); glDeleteShader(fragmentShader); @@ -3015,8 +3015,8 @@ static Shader LoadDefaultShader(void) shader.id = LoadShaderProgram(vDefaultShaderStr, fDefaultShaderStr); - 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); + if (shader.id != 0) TraceLog(LOG_INFO, "[SHDR ID %i] Default shader loaded successfully", shader.id); + else TraceLog(LOG_WARNING, "[SHDR ID %i] Default shader could not be loaded", shader.id); if (shader.id != 0) LoadDefaultShaderLocations(&shader); @@ -3135,7 +3135,7 @@ static void LoadDefaultBuffers(void) quads.tcCounter = 0; quads.cCounter = 0; - TraceLog(INFO, "[CPU] Default buffers initialized successfully (lines, triangles, quads)"); + TraceLog(LOG_INFO, "[CPU] Default buffers initialized successfully (lines, triangles, quads)"); //-------------------------------------------------------------------------------------------- // [GPU] Upload vertex data and initialize VAOs/VBOs (lines, triangles, quads) @@ -3165,8 +3165,8 @@ static void LoadDefaultBuffers(void) glEnableVertexAttribArray(currentShader.colorLoc); glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); - if (vaoSupported) TraceLog(INFO, "[VAO ID %i] Default buffers VAO initialized successfully (lines)", lines.vaoId); - else TraceLog(INFO, "[VBO ID %i][VBO ID %i] Default buffers VBOs initialized successfully (lines)", lines.vboId[0], lines.vboId[1]); + if (vaoSupported) TraceLog(LOG_INFO, "[VAO ID %i] Default buffers VAO initialized successfully (lines)", lines.vaoId); + else TraceLog(LOG_INFO, "[VBO ID %i][VBO ID %i] Default buffers VBOs initialized successfully (lines)", lines.vboId[0], lines.vboId[1]); // Upload and link triangles vertex buffers if (vaoSupported) @@ -3191,8 +3191,8 @@ static void LoadDefaultBuffers(void) glEnableVertexAttribArray(currentShader.colorLoc); glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); - if (vaoSupported) TraceLog(INFO, "[VAO ID %i] Default buffers VAO initialized successfully (triangles)", triangles.vaoId); - else TraceLog(INFO, "[VBO ID %i][VBO ID %i] Default buffers VBOs initialized successfully (triangles)", triangles.vboId[0], triangles.vboId[1]); + if (vaoSupported) TraceLog(LOG_INFO, "[VAO ID %i] Default buffers VAO initialized successfully (triangles)", triangles.vaoId); + else TraceLog(LOG_INFO, "[VBO ID %i][VBO ID %i] Default buffers VBOs initialized successfully (triangles)", triangles.vboId[0], triangles.vboId[1]); // Upload and link quads vertex buffers if (vaoSupported) @@ -3233,8 +3233,8 @@ static void LoadDefaultBuffers(void) glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(short)*6*MAX_QUADS_BATCH, quads.indices, GL_STATIC_DRAW); #endif - if (vaoSupported) TraceLog(INFO, "[VAO ID %i] Default buffers VAO initialized successfully (quads)", quads.vaoId); - else TraceLog(INFO, "[VBO ID %i][VBO ID %i][VBO ID %i][VBO ID %i] Default buffers VBOs initialized successfully (quads)", quads.vboId[0], quads.vboId[1], quads.vboId[2], quads.vboId[3]); + if (vaoSupported) TraceLog(LOG_INFO, "[VAO ID %i] Default buffers VAO initialized successfully (quads)", quads.vaoId); + else TraceLog(LOG_INFO, "[VBO ID %i][VBO ID %i][VBO ID %i][VBO ID %i] Default buffers VBOs initialized successfully (quads)", quads.vboId[0], quads.vboId[1], quads.vboId[2], quads.vboId[3]); // Unbind the current VAO if (vaoSupported) glBindVertexArray(0); @@ -3432,14 +3432,14 @@ static void DrawDefaultBuffers() glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, quads.vboId[3]); } - //TraceLog(DEBUG, "Draws required per frame: %i", drawsCounter); + //TraceLog(LOG_DEBUG, "Draws required per frame: %i", drawsCounter); for (int i = 0; i < drawsCounter; i++) { quadsCount = draws[i].vertexCount/4; numIndicesToProcess = quadsCount*6; // Get number of Quads*6 index by Quad - //TraceLog(DEBUG, "Quads to render: %i - Vertex Count: %i", quadsCount, draws[i].vertexCount); + //TraceLog(LOG_DEBUG, "Quads to render: %i - Vertex Count: %i", quadsCount, draws[i].vertexCount); glBindTexture(GL_TEXTURE_2D, draws[i].textureId); @@ -3450,7 +3450,7 @@ static void DrawDefaultBuffers() glDrawElements(GL_TRIANGLES, numIndicesToProcess, GL_UNSIGNED_SHORT, (GLvoid *)(sizeof(GLushort)*indicesOffset)); #endif //GLenum err; - //if ((err = glGetError()) != GL_NO_ERROR) TraceLog(INFO, "OpenGL error: %i", (int)err); //GL_INVALID_ENUM! + //if ((err = glGetError()) != GL_NO_ERROR) TraceLog(LOG_INFO, "OpenGL error: %i", (int)err); //GL_INVALID_ENUM! indicesOffset += draws[i].vertexCount/4*6; } @@ -3557,17 +3557,17 @@ static void SetStereoConfig(VrDeviceInfo hmd) hmd.distortionK[2]*lensRadiusSq*lensRadiusSq + hmd.distortionK[3]*lensRadiusSq*lensRadiusSq*lensRadiusSq; - TraceLog(DEBUG, "VR: Distortion Scale: %f", distortionScale); + TraceLog(LOG_DEBUG, "VR: Distortion Scale: %f", distortionScale); float normScreenWidth = 0.5f; float normScreenHeight = 1.0f; float scaleIn[2] = { 2.0f/normScreenWidth, 2.0f/normScreenHeight/aspect }; float scale[2] = { normScreenWidth*0.5f/distortionScale, normScreenHeight*0.5f*aspect/distortionScale }; - TraceLog(DEBUG, "VR: Distortion Shader: LeftLensCenter = { %f, %f }", leftLensCenter[0], leftLensCenter[1]); - TraceLog(DEBUG, "VR: Distortion Shader: RightLensCenter = { %f, %f }", rightLensCenter[0], rightLensCenter[1]); - TraceLog(DEBUG, "VR: Distortion Shader: Scale = { %f, %f }", scale[0], scale[1]); - TraceLog(DEBUG, "VR: Distortion Shader: ScaleIn = { %f, %f }", scaleIn[0], scaleIn[1]); + TraceLog(LOG_DEBUG, "VR: Distortion Shader: LeftLensCenter = { %f, %f }", leftLensCenter[0], leftLensCenter[1]); + TraceLog(LOG_DEBUG, "VR: Distortion Shader: RightLensCenter = { %f, %f }", rightLensCenter[0], rightLensCenter[1]); + TraceLog(LOG_DEBUG, "VR: Distortion Shader: Scale = { %f, %f }", scale[0], scale[1]); + TraceLog(LOG_DEBUG, "VR: Distortion Shader: ScaleIn = { %f, %f }", scaleIn[0], scaleIn[1]); #if defined(SUPPORT_DISTORTION_SHADER) // Update distortion shader with lens and distortion-scale parameters @@ -3645,20 +3645,20 @@ static int GenerateMipmaps(unsigned char *data, int baseWidth, int baseHeight) if (width != 1) width /= 2; if (height != 1) height /= 2; - TraceLog(DEBUG, "Next mipmap size: %i x %i", width, height); + TraceLog(LOG_DEBUG, "Next mipmap size: %i x %i", width, height); mipmapCount++; size += (width*height*4); // Add mipmap size (in bytes) } - TraceLog(DEBUG, "Total mipmaps required: %i", mipmapCount); - TraceLog(DEBUG, "Total size of data required: %i", size); + TraceLog(LOG_DEBUG, "Total mipmaps required: %i", mipmapCount); + TraceLog(LOG_DEBUG, "Total size of data required: %i", size); unsigned char *temp = realloc(data, size); if (temp != NULL) data = temp; - else TraceLog(WARNING, "Mipmaps required memory could not be allocated"); + else TraceLog(LOG_WARNING, "Mipmaps required memory could not be allocated"); width = baseWidth; height = baseHeight; @@ -3680,7 +3680,7 @@ static int GenerateMipmaps(unsigned char *data, int baseWidth, int baseHeight) j++; } - TraceLog(DEBUG, "Mipmap base (%ix%i)", width, height); + TraceLog(LOG_DEBUG, "Mipmap base (%ix%i)", width, height); for (int mip = 1; mip < mipmapCount; mip++) { @@ -3751,15 +3751,14 @@ static Color *GenNextMipmap(Color *srcData, int srcWidth, int srcHeight) } } - TraceLog(DEBUG, "Mipmap generated successfully (%ix%i)", width, height); + TraceLog(LOG_DEBUG, "Mipmap generated successfully (%ix%i)", width, height); return mipmap; } #endif #if defined(RLGL_STANDALONE) -// Output a trace log message -// NOTE: Expected msgType: (0)Info, (1)Error, (2)Warning +// Show trace log messages (LOG_INFO, LOG_WARNING, LOG_ERROR, LOG_DEBUG) void TraceLog(int msgType, const char *text, ...) { va_list args; @@ -3767,10 +3766,10 @@ void TraceLog(int msgType, const char *text, ...) switch (msgType) { - case INFO: fprintf(stdout, "INFO: "); break; - case ERROR: fprintf(stdout, "ERROR: "); break; - case WARNING: fprintf(stdout, "WARNING: "); break; - case DEBUG: fprintf(stdout, "DEBUG: "); break; + case LOG_INFO: fprintf(stdout, "INFO: "); break; + case LOG_ERROR: fprintf(stdout, "ERROR: "); break; + case LOG_WARNING: fprintf(stdout, "WARNING: "); break; + case LOG_DEBUG: fprintf(stdout, "DEBUG: "); break; default: break; } @@ -3779,7 +3778,7 @@ void TraceLog(int msgType, const char *text, ...) va_end(args); - if (msgType == ERROR) exit(1); + if (msgType == LOG_ERROR) exit(1); } // Converts Matrix to float array diff --git a/src/rlgl.h b/src/rlgl.h index 6d6ad516..57e77c7d 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -236,11 +236,11 @@ typedef unsigned char byte; // TraceLog message types typedef enum { - INFO = 0, - ERROR, - WARNING, - DEBUG, - OTHER + LOG_INFO = 0, + LOG_ERROR, + LOG_WARNING, + LOG_DEBUG, + LOG_OTHER } TraceLogType; // Texture formats (support depends on OpenGL version) @@ -416,8 +416,8 @@ void EndShaderMode(void); // End custo void BeginBlendMode(int mode); // Begin blending mode (alpha, additive, multiplied) void EndBlendMode(void); // End blending mode (reset to default: alpha blending) -void TraceLog(int msgType, const char *text, ...); -float *MatrixToFloat(Matrix mat); +void TraceLog(int msgType, const char *text, ...); // Show trace log messages (LOG_INFO, LOG_WARNING, LOG_ERROR, LOG_DEBUG) +float *MatrixToFloat(Matrix mat); // Get float array from Matrix data void InitVrSimulator(int vrDevice); // Init VR simulator for selected device void CloseVrSimulator(void); // Close VR simulator for current device diff --git a/src/rres.h b/src/rres.h index 65ebdbba..93d1c395 100644 --- a/src/rres.h +++ b/src/rres.h @@ -252,7 +252,7 @@ RRESDEF RRES LoadResource(const char *fileName, int rresId) FILE *rresFile = fopen(fileName, "rb"); - if (rresFile == NULL) TraceLog(WARNING, "[%s] rRES raylib resource file could not be opened", fileName); + if (rresFile == NULL) TraceLog(LOG_WARNING, "[%s] rRES raylib resource file could not be opened", fileName); else { // Read rres file info header @@ -266,7 +266,7 @@ RRESDEF RRES LoadResource(const char *fileName, int rresId) // Verify "rRES" identifier if ((fileHeader.id[0] != 'r') && (fileHeader.id[1] != 'R') && (fileHeader.id[2] != 'E') && (fileHeader.id[3] != 'S')) { - TraceLog(WARNING, "[%s] This is not a valid raylib resource file", fileName); + TraceLog(LOG_WARNING, "[%s] This is not a valid raylib resource file", fileName); } else { @@ -305,7 +305,7 @@ RRESDEF RRES LoadResource(const char *fileName, int rresId) } else rres[k].data = data; - if (rres[k].data != NULL) TraceLog(INFO, "[%s][ID %i] Resource data loaded successfully", fileName, (int)infoHeader.id); + if (rres[k].data != NULL) TraceLog(LOG_INFO, "[%s][ID %i] Resource data loaded successfully", fileName, (int)infoHeader.id); // Read next part fread(&infoHeader, sizeof(RRESInfoHeader), 1, rresFile); @@ -318,7 +318,7 @@ RRESDEF RRES LoadResource(const char *fileName, int rresId) } } - if (rres[0].data == NULL) TraceLog(WARNING, "[%s][ID %i] Requested resource could not be found", fileName, (int)rresId); + if (rres[0].data == NULL) TraceLog(LOG_WARNING, "[%s][ID %i] Requested resource could not be found", fileName, (int)rresId); } fclose(rresFile); @@ -349,7 +349,7 @@ static void *DecompressData(const unsigned char *data, unsigned long compSize, i // Check correct memory allocation if (uncompData == NULL) { - TraceLog(WARNING, "Out of memory while decompressing data"); + TraceLog(LOG_WARNING, "Out of memory while decompressing data"); } else { @@ -358,18 +358,18 @@ static void *DecompressData(const unsigned char *data, unsigned long compSize, i if (tempUncompSize == -1) { - TraceLog(WARNING, "Data decompression failed"); + TraceLog(LOG_WARNING, "Data decompression failed"); RRES_FREE(uncompData); } if (uncompSize != (int)tempUncompSize) { - TraceLog(WARNING, "Expected uncompressed size do not match, data may be corrupted"); - TraceLog(WARNING, " -- Expected uncompressed size: %i", uncompSize); - TraceLog(WARNING, " -- Returned uncompressed size: %i", tempUncompSize); + TraceLog(LOG_WARNING, "Expected uncompressed size do not match, data may be corrupted"); + TraceLog(LOG_WARNING, " -- Expected uncompressed size: %i", uncompSize); + TraceLog(LOG_WARNING, " -- Returned uncompressed size: %i", tempUncompSize); } - TraceLog(INFO, "Data decompressed successfully from %u bytes to %u bytes", (mz_uint32)compSize, (mz_uint32)tempUncompSize); + TraceLog(LOG_INFO, "Data decompressed successfully from %u bytes to %u bytes", (mz_uint32)compSize, (mz_uint32)tempUncompSize); } return uncompData; @@ -377,36 +377,27 @@ static void *DecompressData(const unsigned char *data, unsigned long compSize, i // Some required functions for rres standalone module version #if defined(RRES_STANDALONE) -// Outputs a trace log message (INFO, ERROR, WARNING) -// NOTE: If a file has been init, output log is written there +// Show trace log messages (LOG_INFO, LOG_WARNING, LOG_ERROR, LOG_DEBUG) void TraceLog(int logType, const char *text, ...) { va_list args; - int traceDebugMsgs = 0; - -#ifdef DO_NOT_TRACE_DEBUG_MSGS - traceDebugMsgs = 0; -#endif + va_start(args, text); switch (msgType) { case LOG_INFO: fprintf(stdout, "INFO: "); break; case LOG_ERROR: fprintf(stdout, "ERROR: "); break; case LOG_WARNING: fprintf(stdout, "WARNING: "); break; - case LOG_DEBUG: if (traceDebugMsgs) fprintf(stdout, "DEBUG: "); break; + case LOG_DEBUG: fprintf(stdout, "DEBUG: "); break; default: break; } - if ((msgType != LOG_DEBUG) || ((msgType == LOG_DEBUG) && (traceDebugMsgs))) - { - va_start(args, text); - vfprintf(stdout, text, args); - va_end(args); + vfprintf(stdout, text, args); + fprintf(stdout, "\n"); - fprintf(stdout, "\n"); - } + va_end(args); - if (msgType == ERROR) exit(1); // If ERROR message, exit program + if (msgType == LOG_ERROR) exit(1); } #endif diff --git a/src/text.c b/src/text.c index 027701de..7ef01c11 100644 --- a/src/text.c +++ b/src/text.c @@ -256,7 +256,7 @@ extern void LoadDefaultFont(void) defaultFont.baseSize = defaultFont.chars[0].rec.height; - TraceLog(INFO, "[TEX ID %i] Default font loaded successfully", defaultFont.texture.id); + TraceLog(LOG_INFO, "[TEX ID %i] Default font loaded successfully", defaultFont.texture.id); } // Unload raylib default font @@ -330,7 +330,7 @@ SpriteFont LoadSpriteFont(const char *fileName) if (spriteFont.texture.id == 0) { - TraceLog(WARNING, "[%s] SpriteFont could not be loaded, using default font", fileName); + TraceLog(LOG_WARNING, "[%s] SpriteFont could not be loaded, using default font", fileName); spriteFont = GetDefaultFont(); } else SetTextureFilter(spriteFont.texture, FILTER_POINT); // By default we set point filter (best performance) @@ -364,7 +364,7 @@ SpriteFont LoadSpriteFontEx(const char *fileName, int fontSize, int charsCount, if (spriteFont.texture.id == 0) { - TraceLog(WARNING, "[%s] SpriteFont could not be generated, using default font", fileName); + TraceLog(LOG_WARNING, "[%s] SpriteFont could not be generated, using default font", fileName); spriteFont = GetDefaultFont(); } @@ -380,7 +380,7 @@ void UnloadSpriteFont(SpriteFont spriteFont) UnloadTexture(spriteFont.texture); free(spriteFont.chars); - TraceLog(DEBUG, "Unloaded sprite font data"); + TraceLog(LOG_DEBUG, "Unloaded sprite font data"); } } @@ -677,7 +677,7 @@ static SpriteFont LoadImageFont(Image image, Color key, int firstChar) xPosToRead = charSpacing; } - TraceLog(DEBUG, "SpriteFont data parsed correctly from image"); + TraceLog(LOG_DEBUG, "SpriteFont data parsed correctly from image"); // NOTE: We need to remove key color borders from image to avoid weird // artifacts on texture scaling when using FILTER_BILINEAR or FILTER_TRILINEAR @@ -713,7 +713,7 @@ static SpriteFont LoadImageFont(Image image, Color key, int firstChar) spriteFont.baseSize = spriteFont.chars[0].rec.height; - TraceLog(INFO, "Image file loaded correctly as SpriteFont"); + TraceLog(LOG_INFO, "Image file loaded correctly as SpriteFont"); return spriteFont; } @@ -743,7 +743,7 @@ static SpriteFont LoadBMFont(const char *fileName) if (fntFile == NULL) { - TraceLog(WARNING, "[%s] FNT file could not be opened", fileName); + TraceLog(LOG_WARNING, "[%s] FNT file could not be opened", fileName); return font; } @@ -756,20 +756,20 @@ static SpriteFont LoadBMFont(const char *fileName) searchPoint = strstr(buffer, "lineHeight"); sscanf(searchPoint, "lineHeight=%i base=%i scaleW=%i scaleH=%i", &fontSize, &base, &texWidth, &texHeight); - TraceLog(DEBUG, "[%s] Font size: %i", fileName, fontSize); - TraceLog(DEBUG, "[%s] Font texture scale: %ix%i", fileName, texWidth, texHeight); + TraceLog(LOG_DEBUG, "[%s] Font size: %i", fileName, fontSize); + TraceLog(LOG_DEBUG, "[%s] Font texture scale: %ix%i", fileName, texWidth, texHeight); fgets(buffer, MAX_BUFFER_SIZE, fntFile); searchPoint = strstr(buffer, "file"); sscanf(searchPoint, "file=\"%128[^\"]\"", texFileName); - TraceLog(DEBUG, "[%s] Font texture filename: %s", fileName, texFileName); + TraceLog(LOG_DEBUG, "[%s] Font texture filename: %s", fileName, texFileName); fgets(buffer, MAX_BUFFER_SIZE, fntFile); searchPoint = strstr(buffer, "count"); sscanf(searchPoint, "count=%i", &charsCount); - TraceLog(DEBUG, "[%s] Font num chars: %i", fileName, charsCount); + TraceLog(LOG_DEBUG, "[%s] Font num chars: %i", fileName, charsCount); // Compose correct path using route of .fnt file (fileName) and texFileName char *texPath = NULL; @@ -785,7 +785,7 @@ static SpriteFont LoadBMFont(const char *fileName) strncat(texPath, fileName, strlen(fileName) - strlen(lastSlash) + 1); strncat(texPath, texFileName, strlen(texFileName)); - TraceLog(DEBUG, "[%s] Font texture loading path: %s", fileName, texPath); + TraceLog(LOG_DEBUG, "[%s] Font texture loading path: %s", fileName, texPath); Image imFont = LoadImage(texPath); @@ -832,7 +832,7 @@ static SpriteFont LoadBMFont(const char *fileName) UnloadSpriteFont(font); font = GetDefaultFont(); } - else TraceLog(INFO, "[%s] SpriteFont loaded successfully", fileName); + else TraceLog(LOG_INFO, "[%s] SpriteFont loaded successfully", fileName); return font; } @@ -853,7 +853,7 @@ static SpriteFont LoadTTF(const char *fileName, int fontSize, int charsCount, in float guessSize = ceilf((float)fontSize*3/4)*ceilf(sqrtf((float)charsCount)); int textureSize = (int)powf(2, ceilf(logf((float)guessSize)/logf(2))); // Calculate next POT - TraceLog(INFO, "TTF spritefont loading: Predicted texture size: %ix%i", textureSize, textureSize); + TraceLog(LOG_INFO, "TTF spritefont loading: Predicted texture size: %ix%i", textureSize, textureSize); unsigned char *ttfBuffer = (unsigned char *)malloc(MAX_TTF_SIZE*1024*1024); unsigned char *dataBitmap = (unsigned char *)malloc(textureSize*textureSize*sizeof(unsigned char)); // One channel bitmap returned! @@ -865,22 +865,22 @@ static SpriteFont LoadTTF(const char *fileName, int fontSize, int charsCount, in if (ttfFile == NULL) { - TraceLog(WARNING, "[%s] TTF file could not be opened", fileName); + TraceLog(LOG_WARNING, "[%s] TTF file could not be opened", fileName); return font; } // NOTE: We try reading up to 16 MB of elements of 1 byte fread(ttfBuffer, 1, MAX_TTF_SIZE*1024*1024, ttfFile); - if (fontChars[0] != 32) TraceLog(WARNING, "TTF spritefont loading: first character is not SPACE(32) character"); + if (fontChars[0] != 32) TraceLog(LOG_WARNING, "TTF spritefont loading: first character is not SPACE(32) character"); // NOTE: Using stb_truetype crappy packing method, no guarante the font fits the image... // TODO: Replace this function by a proper packing method and support random chars order, // we already receive a list (fontChars) with the ordered expected characters int result = stbtt_BakeFontBitmap(ttfBuffer, 0, fontSize, dataBitmap, textureSize, textureSize, fontChars[0], charsCount, charData); - //if (result > 0) TraceLog(INFO, "TTF spritefont loading: first unused row of generated bitmap: %i", result); - if (result < 0) TraceLog(WARNING, "TTF spritefont loading: Not all the characters fit in the font"); + //if (result > 0) TraceLog(LOG_INFO, "TTF spritefont loading: first unused row of generated bitmap: %i", result); + if (result < 0) TraceLog(LOG_WARNING, "TTF spritefont loading: Not all the characters fit in the font"); free(ttfBuffer); diff --git a/src/textures.c b/src/textures.c index 5196b1e1..28bc27f8 100644 --- a/src/textures.c +++ b/src/textures.c @@ -167,7 +167,7 @@ Image LoadImage(const char *fileName) // NOTE: Parameters for RRES_TYPE_IMAGE are: width, height, format, mipmaps if (rres[0].type == RRES_TYPE_IMAGE) image = LoadImagePro(rres[0].data, rres[0].param1, rres[0].param2, rres[0].param3); - else TraceLog(WARNING, "[%s] Resource file does not contain image data", fileName); + else TraceLog(LOG_WARNING, "[%s] Resource file does not contain image data", fileName); UnloadResource(rres); } @@ -234,7 +234,7 @@ Image LoadImage(const char *fileName) else { // TODO: Support different number of channels at 32 bit float - TraceLog(WARNING, "[%s] Image fileformat not supported (only 3 channel 32 bit floats)", fileName); + TraceLog(LOG_WARNING, "[%s] Image fileformat not supported (only 3 channel 32 bit floats)", fileName); UnloadImage(image); } } @@ -254,10 +254,10 @@ Image LoadImage(const char *fileName) #if defined(SUPPORT_FILEFORMAT_ASTC) else if (IsFileExtension(fileName, ".astc")) image = LoadASTC(fileName); #endif - else TraceLog(WARNING, "[%s] Image fileformat not supported", fileName); + else TraceLog(LOG_WARNING, "[%s] Image fileformat not supported", fileName); - if (image.data != NULL) TraceLog(INFO, "[%s] Image loaded successfully (%ix%i)", fileName, image.width, image.height); - else TraceLog(WARNING, "[%s] Image could not be loaded", fileName); + if (image.data != NULL) TraceLog(LOG_INFO, "[%s] Image loaded successfully (%ix%i)", fileName, image.width, image.height); + else TraceLog(LOG_WARNING, "[%s] Image could not be loaded", fileName); return image; } @@ -315,7 +315,7 @@ Image LoadImageRaw(const char *fileName, int width, int height, int format, int if (rawFile == NULL) { - TraceLog(WARNING, "[%s] RAW image file could not be opened", fileName); + TraceLog(LOG_WARNING, "[%s] RAW image file could not be opened", fileName); } else { @@ -333,7 +333,7 @@ Image LoadImageRaw(const char *fileName, int width, int height, int format, int 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 case UNCOMPRESSED_R32G32B32: image.data = (float *)malloc(size*12); size *= 12; break; // 4 byte per channel (12 byte) - default: TraceLog(WARNING, "Image format not suported"); break; + default: TraceLog(LOG_WARNING, "Image format not suported"); break; } // NOTE: fread() returns num read elements instead of bytes, @@ -343,7 +343,7 @@ Image LoadImageRaw(const char *fileName, int width, int height, int format, int // Check if data has been read successfully if (bytes < size) { - TraceLog(WARNING, "[%s] RAW image data can not be read, wrong requested format or size", fileName); + TraceLog(LOG_WARNING, "[%s] RAW image data can not be read, wrong requested format or size", fileName); if (image.data != NULL) free(image.data); } @@ -373,7 +373,7 @@ Texture2D LoadTexture(const char *fileName) texture = LoadTextureFromImage(image); UnloadImage(image); } - else TraceLog(WARNING, "Texture could not be created"); + else TraceLog(LOG_WARNING, "Texture could not be created"); return texture; } @@ -391,7 +391,7 @@ Texture2D LoadTextureFromImage(Image image) texture.mipmaps = image.mipmaps; texture.format = image.format; - TraceLog(DEBUG, "[TEX ID %i] Parameters: %ix%i, %i mips, format %i", texture.id, texture.width, texture.height, texture.mipmaps, texture.format); + TraceLog(LOG_DEBUG, "[TEX ID %i] Parameters: %ix%i, %i mips, format %i", texture.id, texture.width, texture.height, texture.mipmaps, texture.format); return texture; } @@ -410,7 +410,7 @@ void UnloadImage(Image image) free(image.data); // NOTE: It becomes anoying every time a texture is loaded - //TraceLog(INFO, "Unloaded image data"); + //TraceLog(LOG_INFO, "Unloaded image data"); } // Unload texture from GPU memory (VRAM) @@ -420,7 +420,7 @@ void UnloadTexture(Texture2D texture) { rlDeleteTextures(texture.id); - TraceLog(INFO, "[TEX ID %i] Unloaded texture data from VRAM (GPU)", texture.id); + TraceLog(LOG_INFO, "[TEX ID %i] Unloaded texture data from VRAM (GPU)", texture.id); } } @@ -510,7 +510,7 @@ Color *GetImageData(Image image) k += 3; } break; - default: TraceLog(WARNING, "Format not supported for pixel data retrieval"); break; + default: TraceLog(LOG_WARNING, "Format not supported for pixel data retrieval"); break; } } @@ -540,11 +540,11 @@ Image GetTextureData(Texture2D texture) } else image.format = texture.format; - TraceLog(INFO, "Texture pixel data obtained successfully"); + TraceLog(LOG_INFO, "Texture pixel data obtained successfully"); } - else TraceLog(WARNING, "Texture pixel data could not be obtained"); + else TraceLog(LOG_WARNING, "Texture pixel data could not be obtained"); } - else TraceLog(WARNING, "Compressed texture data could not be obtained"); + else TraceLog(LOG_WARNING, "Compressed texture data could not be obtained"); return image; } @@ -564,7 +564,7 @@ void SaveImageAs(const char* fileName, Image image) SavePNG(fileName, imgData, image.width, image.height, 4); free(imgData); - TraceLog(INFO, "Image saved: %s", fileName); + TraceLog(LOG_INFO, "Image saved: %s", fileName); #endif } @@ -697,7 +697,7 @@ void ImageFormat(Image *image, int newFormat) free(pixels); } - else TraceLog(WARNING, "Image data format is compressed, can not be converted"); + else TraceLog(LOG_WARNING, "Image data format is compressed, can not be converted"); } } @@ -708,11 +708,11 @@ void ImageAlphaMask(Image *image, Image alphaMask) { if ((image->width != alphaMask.width) || (image->height != alphaMask.height)) { - TraceLog(WARNING, "Alpha mask must be same size as image"); + TraceLog(LOG_WARNING, "Alpha mask must be same size as image"); } else if (image->format >= COMPRESSED_DXT1_RGB) { - TraceLog(WARNING, "Alpha mask can not be applied to compressed data formats"); + TraceLog(LOG_WARNING, "Alpha mask can not be applied to compressed data formats"); } else { @@ -775,7 +775,7 @@ void ImageToPOT(Image *image, Color fillColor) } } - TraceLog(WARNING, "Image converted to POT: (%ix%i) -> (%ix%i)", image->width, image->height, potWidth, potHeight); + TraceLog(LOG_WARNING, "Image converted to POT: (%ix%i) -> (%ix%i)", image->width, image->height, potWidth, potHeight); free(pixels); // Free pixels data free(image->data); // Free old image data @@ -821,7 +821,7 @@ Image ImageCopy(Image image) case COMPRESSED_PVRT_RGB: case COMPRESSED_PVRT_RGBA: byteSize /= 2; break; // 4 bpp case COMPRESSED_ASTC_8x8_RGBA: byteSize /= 4; break;// 2 bpp - default: TraceLog(WARNING, "Image format not recognized"); break; + default: TraceLog(LOG_WARNING, "Image format not recognized"); break; } newImage.data = malloc(byteSize); @@ -848,13 +848,13 @@ void ImageCrop(Image *image, Rectangle crop) if ((crop.x + crop.width) > image->width) { crop.width = image->width - crop.x; - TraceLog(WARNING, "Crop rectangle width out of bounds, rescaled crop width: %i", crop.width); + TraceLog(LOG_WARNING, "Crop rectangle width out of bounds, rescaled crop width: %i", crop.width); } if ((crop.y + crop.height) > image->height) { crop.height = image->height - crop.y; - TraceLog(WARNING, "Crop rectangle height out of bounds, rescaled crop height: %i", crop.height); + TraceLog(LOG_WARNING, "Crop rectangle height out of bounds, rescaled crop height: %i", crop.height); } if ((crop.x < image->width) && (crop.y < image->height)) @@ -886,7 +886,7 @@ void ImageCrop(Image *image, Rectangle crop) } else { - TraceLog(WARNING, "Image can not be cropped, crop rectangle out of bounds"); + TraceLog(LOG_WARNING, "Image can not be cropped, crop rectangle out of bounds"); } } @@ -961,13 +961,13 @@ void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec) if ((srcRec.x + srcRec.width) > src.width) { srcRec.width = src.width - srcRec.x; - TraceLog(WARNING, "Source rectangle width out of bounds, rescaled width: %i", srcRec.width); + TraceLog(LOG_WARNING, "Source rectangle width out of bounds, rescaled width: %i", srcRec.width); } if ((srcRec.y + srcRec.height) > src.height) { srcRec.height = src.height - srcRec.y; - TraceLog(WARNING, "Source rectangle height out of bounds, rescaled height: %i", srcRec.height); + TraceLog(LOG_WARNING, "Source rectangle height out of bounds, rescaled height: %i", srcRec.height); cropRequired = true; } @@ -988,14 +988,14 @@ void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec) if ((dstRec.x + dstRec.width) > dst->width) { dstRec.width = dst->width - dstRec.x; - TraceLog(WARNING, "Destination rectangle width out of bounds, rescaled width: %i", dstRec.width); + TraceLog(LOG_WARNING, "Destination rectangle width out of bounds, rescaled width: %i", dstRec.width); cropRequired = true; } if ((dstRec.y + dstRec.height) > dst->height) { dstRec.height = dst->height - dstRec.y; - TraceLog(WARNING, "Destination rectangle height out of bounds, rescaled height: %i", dstRec.height); + TraceLog(LOG_WARNING, "Destination rectangle height out of bounds, rescaled height: %i", dstRec.height); cropRequired = true; } @@ -1098,7 +1098,7 @@ Image ImageTextEx(SpriteFont font, const char *text, float fontSize, int spacing if (fontSize > imSize.y) { float scaleFactor = fontSize/imSize.y; - TraceLog(INFO, "Scalefactor: %f", scaleFactor); + TraceLog(LOG_INFO, "Scalefactor: %f", scaleFactor); // Using nearest-neighbor scaling algorithm for default font if (font.texture.id == GetDefaultFont().texture.id) ImageResizeNN(&imText, (int)(imSize.x*scaleFactor), (int)(imSize.y*scaleFactor)); @@ -1186,13 +1186,13 @@ void ImageDither(Image *image, int rBpp, int gBpp, int bBpp, int aBpp) { if (image->format >= COMPRESSED_DXT1_RGB) { - TraceLog(WARNING, "Compressed data formats can not be dithered"); + TraceLog(LOG_WARNING, "Compressed data formats can not be dithered"); return; } if ((rBpp+gBpp+bBpp+aBpp) > 16) { - TraceLog(WARNING, "Unsupported dithering bpps (%ibpp), only 16bpp or lower modes supported", (rBpp+gBpp+bBpp+aBpp)); + TraceLog(LOG_WARNING, "Unsupported dithering bpps (%ibpp), only 16bpp or lower modes supported", (rBpp+gBpp+bBpp+aBpp)); } else { @@ -1202,7 +1202,7 @@ void ImageDither(Image *image, int rBpp, int gBpp, int bBpp, int aBpp) if ((image->format != UNCOMPRESSED_R8G8B8) && (image->format != UNCOMPRESSED_R8G8B8A8)) { - TraceLog(WARNING, "Image format is already 16bpp or lower, dithering could have no effect"); + TraceLog(LOG_WARNING, "Image format is already 16bpp or lower, dithering could have no effect"); } // Define new image format, check if desired bpp match internal known format @@ -1212,7 +1212,7 @@ void ImageDither(Image *image, int rBpp, int gBpp, int bBpp, int aBpp) else { image->format = 0; - TraceLog(WARNING, "Unsupported dithered OpenGL internal format: %ibpp (R%iG%iB%iA%i)", (rBpp+gBpp+bBpp+aBpp), rBpp, gBpp, bBpp, aBpp); + TraceLog(LOG_WARNING, "Unsupported dithered OpenGL internal format: %ibpp (R%iG%iB%iA%i)", (rBpp+gBpp+bBpp+aBpp), rBpp, gBpp, bBpp, aBpp); } // NOTE: We will store the dithered data as unsigned short (16bpp) @@ -1652,7 +1652,7 @@ void GenTextureMipmaps(Texture2D *texture) // Check if texture is POT if ((potWidth != texture->width) || (potHeight != texture->height)) { - TraceLog(WARNING, "Limited NPOT support, no mipmaps available for NPOT textures"); + TraceLog(LOG_WARNING, "Limited NPOT support, no mipmaps available for NPOT textures"); } else rlglGenerateMipmaps(texture); #else @@ -1712,7 +1712,7 @@ void SetTextureFilter(Texture2D texture, int filterMode) } else { - TraceLog(WARNING, "[TEX ID %i] No mipmaps available for TRILINEAR texture filtering", texture.id); + TraceLog(LOG_WARNING, "[TEX ID %i] No mipmaps available for TRILINEAR texture filtering", texture.id); // RL_FILTER_LINEAR - tex filter: BILINEAR, no mipmaps rlTextureParameters(texture.id, RL_TEXTURE_MIN_FILTER, RL_FILTER_LINEAR); @@ -1887,7 +1887,7 @@ static Image LoadDDS(const char *fileName) if (ddsFile == NULL) { - TraceLog(WARNING, "[%s] DDS file could not be opened", fileName); + TraceLog(LOG_WARNING, "[%s] DDS file could not be opened", fileName); } else { @@ -1898,7 +1898,7 @@ static Image LoadDDS(const char *fileName) if (strncmp(filecode, "DDS ", 4) != 0) { - TraceLog(WARNING, "[%s] DDS file does not seem to be a valid image", fileName); + TraceLog(LOG_WARNING, "[%s] DDS file does not seem to be a valid image", fileName); } else { @@ -1907,11 +1907,11 @@ static Image LoadDDS(const char *fileName) // Get the image header fread(&ddsHeader, sizeof(DDSHeader), 1, ddsFile); - TraceLog(DEBUG, "[%s] DDS file header size: %i", fileName, sizeof(DDSHeader)); - TraceLog(DEBUG, "[%s] DDS file pixel format size: %i", fileName, ddsHeader.ddspf.size); - TraceLog(DEBUG, "[%s] DDS file pixel format flags: 0x%x", fileName, ddsHeader.ddspf.flags); - TraceLog(DEBUG, "[%s] DDS file format: 0x%x", fileName, ddsHeader.ddspf.fourCC); - TraceLog(DEBUG, "[%s] DDS file bit count: 0x%x", fileName, ddsHeader.ddspf.rgbBitCount); + TraceLog(LOG_DEBUG, "[%s] DDS file header size: %i", fileName, sizeof(DDSHeader)); + TraceLog(LOG_DEBUG, "[%s] DDS file pixel format size: %i", fileName, ddsHeader.ddspf.size); + TraceLog(LOG_DEBUG, "[%s] DDS file pixel format flags: 0x%x", fileName, ddsHeader.ddspf.flags); + TraceLog(LOG_DEBUG, "[%s] DDS file format: 0x%x", fileName, ddsHeader.ddspf.fourCC); + TraceLog(LOG_DEBUG, "[%s] DDS file bit count: 0x%x", fileName, ddsHeader.ddspf.rgbBitCount); image.width = ddsHeader.width; image.height = ddsHeader.height; @@ -1999,7 +1999,7 @@ static Image LoadDDS(const char *fileName) if (ddsHeader.mipmapCount > 1) size = ddsHeader.pitchOrLinearSize*2; else size = ddsHeader.pitchOrLinearSize; - TraceLog(DEBUG, "Pitch or linear size: %i", ddsHeader.pitchOrLinearSize); + TraceLog(LOG_DEBUG, "Pitch or linear size: %i", ddsHeader.pitchOrLinearSize); image.data = (unsigned char*)malloc(size*sizeof(unsigned char)); @@ -2073,7 +2073,7 @@ static Image LoadPKM(const char *fileName) if (pkmFile == NULL) { - TraceLog(WARNING, "[%s] PKM file could not be opened", fileName); + TraceLog(LOG_WARNING, "[%s] PKM file could not be opened", fileName); } else { @@ -2084,7 +2084,7 @@ static Image LoadPKM(const char *fileName) if (strncmp(pkmHeader.id, "PKM ", 4) != 0) { - TraceLog(WARNING, "[%s] PKM file does not seem to be a valid image", fileName); + TraceLog(LOG_WARNING, "[%s] PKM file does not seem to be a valid image", fileName); } else { @@ -2093,9 +2093,9 @@ static Image LoadPKM(const char *fileName) pkmHeader.width = ((pkmHeader.width & 0x00FF) << 8) | ((pkmHeader.width & 0xFF00) >> 8); pkmHeader.height = ((pkmHeader.height & 0x00FF) << 8) | ((pkmHeader.height & 0xFF00) >> 8); - TraceLog(DEBUG, "PKM (ETC) image width: %i", pkmHeader.width); - TraceLog(DEBUG, "PKM (ETC) image height: %i", pkmHeader.height); - TraceLog(DEBUG, "PKM (ETC) image format: %i", pkmHeader.format); + TraceLog(LOG_DEBUG, "PKM (ETC) image width: %i", pkmHeader.width); + TraceLog(LOG_DEBUG, "PKM (ETC) image height: %i", pkmHeader.height); + TraceLog(LOG_DEBUG, "PKM (ETC) image format: %i", pkmHeader.format); image.width = pkmHeader.width; image.height = pkmHeader.height; @@ -2167,7 +2167,7 @@ static Image LoadKTX(const char *fileName) if (ktxFile == NULL) { - TraceLog(WARNING, "[%s] KTX image file could not be opened", fileName); + TraceLog(LOG_WARNING, "[%s] KTX image file could not be opened", fileName); } else { @@ -2179,7 +2179,7 @@ static Image LoadKTX(const char *fileName) if ((ktxHeader.id[1] != 'K') || (ktxHeader.id[2] != 'T') || (ktxHeader.id[3] != 'X') || (ktxHeader.id[4] != ' ') || (ktxHeader.id[5] != '1') || (ktxHeader.id[6] != '1')) { - TraceLog(WARNING, "[%s] KTX file does not seem to be a valid file", fileName); + TraceLog(LOG_WARNING, "[%s] KTX file does not seem to be a valid file", fileName); } else { @@ -2187,9 +2187,9 @@ static Image LoadKTX(const char *fileName) image.height = ktxHeader.height; image.mipmaps = ktxHeader.mipmapLevels; - TraceLog(DEBUG, "KTX (ETC) image width: %i", ktxHeader.width); - TraceLog(DEBUG, "KTX (ETC) image height: %i", ktxHeader.height); - TraceLog(DEBUG, "KTX (ETC) image format: 0x%x", ktxHeader.glInternalFormat); + TraceLog(LOG_DEBUG, "KTX (ETC) image width: %i", ktxHeader.width); + TraceLog(LOG_DEBUG, "KTX (ETC) image height: %i", ktxHeader.height); + TraceLog(LOG_DEBUG, "KTX (ETC) image format: 0x%x", ktxHeader.glInternalFormat); unsigned char unused; @@ -2288,7 +2288,7 @@ static Image LoadPVR(const char *fileName) if (pvrFile == NULL) { - TraceLog(WARNING, "[%s] PVR file could not be opened", fileName); + TraceLog(LOG_WARNING, "[%s] PVR file could not be opened", fileName); } else { @@ -2307,7 +2307,7 @@ static Image LoadPVR(const char *fileName) if ((pvrHeader.id[0] != 'P') || (pvrHeader.id[1] != 'V') || (pvrHeader.id[2] != 'R') || (pvrHeader.id[3] != 3)) { - TraceLog(WARNING, "[%s] PVR file does not seem to be a valid image", fileName); + TraceLog(LOG_WARNING, "[%s] PVR file does not seem to be a valid image", fileName); } else { @@ -2368,7 +2368,7 @@ static Image LoadPVR(const char *fileName) fread(image.data, dataSize, 1, pvrFile); } } - else if (pvrVersion == 52) TraceLog(INFO, "PVR v2 not supported, update your files to PVR v3"); + else if (pvrVersion == 52) TraceLog(LOG_INFO, "PVR v2 not supported, update your files to PVR v3"); fclose(pvrFile); // Close file pointer } @@ -2412,7 +2412,7 @@ static Image LoadASTC(const char *fileName) if (astcFile == NULL) { - TraceLog(WARNING, "[%s] ASTC file could not be opened", fileName); + TraceLog(LOG_WARNING, "[%s] ASTC file could not be opened", fileName); } else { @@ -2423,7 +2423,7 @@ static Image LoadASTC(const char *fileName) if ((astcHeader.id[3] != 0x5c) || (astcHeader.id[2] != 0xa1) || (astcHeader.id[1] != 0xab) || (astcHeader.id[0] != 0x13)) { - TraceLog(WARNING, "[%s] ASTC file does not seem to be a valid image", fileName); + TraceLog(LOG_WARNING, "[%s] ASTC file does not seem to be a valid image", fileName); } else { @@ -2434,9 +2434,9 @@ static Image LoadASTC(const char *fileName) // NOTE: ASTC format only contains one mipmap level image.mipmaps = 1; - TraceLog(DEBUG, "ASTC image width: %i", image.width); - TraceLog(DEBUG, "ASTC image height: %i", image.height); - TraceLog(DEBUG, "ASTC image blocks: %ix%i", astcHeader.blockX, astcHeader.blockY); + TraceLog(LOG_DEBUG, "ASTC image width: %i", image.width); + TraceLog(LOG_DEBUG, "ASTC image height: %i", image.height); + TraceLog(LOG_DEBUG, "ASTC image blocks: %ix%i", astcHeader.blockX, astcHeader.blockY); // NOTE: Each block is always stored in 128bit so we can calculate the bpp int bpp = 128/(astcHeader.blockX*astcHeader.blockY); @@ -2452,7 +2452,7 @@ static Image LoadASTC(const char *fileName) if (bpp == 8) image.format = COMPRESSED_ASTC_4x4_RGBA; else if (bpp == 2) image.format = COMPRESSED_ASTC_4x4_RGBA; } - else TraceLog(WARNING, "[%s] ASTC block size configuration not supported", fileName); + else TraceLog(LOG_WARNING, "[%s] ASTC block size configuration not supported", fileName); } fclose(astcFile); diff --git a/src/utils.c b/src/utils.c index c86c9c82..cd4638af 100644 --- a/src/utils.c +++ b/src/utils.c @@ -14,10 +14,10 @@ * * #define SUPPORT_TRACELOG * Show TraceLog() output messages -* NOTE: By default DEBUG traces not shown +* NOTE: By default LOG_DEBUG traces not shown * * #define SUPPORT_TRACELOG_DEBUG -* Show TraceLog() DEBUG messages +* Show TraceLog() LOG_DEBUG messages * * DEPENDENCIES: * stb_image_write - BMP/PNG writting functions @@ -45,7 +45,7 @@ **********************************************************************************************/ #define SUPPORT_TRACELOG // Output tracelog messages -//#define SUPPORT_TRACELOG_DEBUG // Avoid DEBUG messages tracing +//#define SUPPORT_TRACELOG_DEBUG // Avoid LOG_DEBUG messages tracing #include "utils.h" @@ -89,7 +89,7 @@ static int android_close(void *cookie); // Module Functions Definition - Utilities //---------------------------------------------------------------------------------- -// Output trace log messages +// Show trace log messages (LOG_INFO, LOG_WARNING, LOG_ERROR, LOG_DEBUG) void TraceLog(int msgType, const char *text, ...) { #if defined(SUPPORT_TRACELOG) @@ -102,10 +102,10 @@ void TraceLog(int msgType, const char *text, ...) switch(msgType) { - case INFO: strcpy(buffer, "INFO: "); break; - case ERROR: strcpy(buffer, "ERROR: "); break; - case WARNING: strcpy(buffer, "WARNING: "); break; - case DEBUG: strcpy(buffer, "DEBUG: "); break; + case LOG_INFO: strcpy(buffer, "INFO: "); break; + case LOG_ERROR: strcpy(buffer, "ERROR: "); break; + case LOG_WARNING: strcpy(buffer, "WARNING: "); break; + case LOG_DEBUG: strcpy(buffer, "DEBUG: "); break; default: break; } @@ -118,19 +118,19 @@ void TraceLog(int msgType, const char *text, ...) #if defined(PLATFORM_ANDROID) switch(msgType) { - case INFO: __android_log_vprint(ANDROID_LOG_INFO, "raylib", buffer, args); break; - case ERROR: __android_log_vprint(ANDROID_LOG_ERROR, "raylib", buffer, args); break; - case WARNING: __android_log_vprint(ANDROID_LOG_WARN, "raylib", buffer, args); break; - case DEBUG: if (traceDebugMsgs) __android_log_vprint(ANDROID_LOG_DEBUG, "raylib", buffer, args); break; + case LOG_INFO: __android_log_vprint(ANDROID_LOG_INFO, "raylib", buffer, args); break; + case LOG_ERROR: __android_log_vprint(ANDROID_LOG_ERROR, "raylib", buffer, args); break; + case LOG_WARNING: __android_log_vprint(ANDROID_LOG_WARN, "raylib", buffer, args); break; + case LOG_DEBUG: if (traceDebugMsgs) __android_log_vprint(ANDROID_LOG_DEBUG, "raylib", buffer, args); break; default: break; } #else - if ((msgType != DEBUG) || ((msgType == DEBUG) && (traceDebugMsgs))) vprintf(buffer, args); + if ((msgType != LOG_DEBUG) || ((msgType == LOG_DEBUG) && (traceDebugMsgs))) vprintf(buffer, args); #endif va_end(args); - if (msgType == ERROR) exit(1); // If ERROR message, exit program + if (msgType == LOG_ERROR) exit(1); // If LOG_ERROR message, exit program #endif // SUPPORT_TRACELOG } @@ -195,7 +195,7 @@ static int android_read(void *cookie, char *buf, int size) static int android_write(void *cookie, const char *buf, int size) { - TraceLog(ERROR, "Can't provide write access to the APK"); + TraceLog(LOG_ERROR, "Can't provide write access to the APK"); return EACCES; } -- cgit v1.2.3 From 6589c808b578732bc710c46fbc74ae73d427f99e Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sun, 2 Jul 2017 19:29:01 +0200 Subject: Review some formatting for consistency --- .gitignore | 2 +- examples/textures/textures_image_generation.c | 44 ++++++++--- examples/textures/textures_image_generation.png | Bin 0 -> 222595 bytes src/raylib.h | 2 +- src/textures.c | 100 +++++++++++++----------- 5 files changed, 87 insertions(+), 61 deletions(-) create mode 100644 examples/textures/textures_image_generation.png (limited to 'src/raylib.h') diff --git a/.gitignore b/.gitignore index 99b04ee4..016b8fa3 100644 --- a/.gitignore +++ b/.gitignore @@ -42,7 +42,7 @@ Thumbs.db *.sbr *.sdf obj/ -# [Rr]elease/ +[Rr]elease/ [Rr]elease.win32/ _ReSharper*/ [Tt]est[Rr]esult* diff --git a/examples/textures/textures_image_generation.c b/examples/textures/textures_image_generation.c index 0dc78f5a..8f87e689 100644 --- a/examples/textures/textures_image_generation.c +++ b/examples/textures/textures_image_generation.c @@ -2,28 +2,29 @@ * * raylib [textures] example - Procedural images generation * -* This example has been created using raylib 1.7 (www.raylib.com) +* This example has been created using raylib 1.8 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * -* Copyright (c) 2O17 Ramon Santamaria (@raysan5) +* Copyright (c) 2O17 Wilhem Barbier (@nounoursheureux) * ********************************************************************************************/ #include "raylib.h" -#define TEXTURES_NUM 7 // for now we have 7 generation algorithms +#define TEXTURES_NUM 7 // for now we have 7 generation algorithms int main() { + // Initialization + //-------------------------------------------------------------------------------------- int screenWidth = 800; int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [textures] example - procedural images generation"); - SetTargetFPS(60); Image verticalGradient = GenImageGradientV(screenWidth, screenHeight, RED, BLUE); Image horizontalGradient = GenImageGradientH(screenWidth, screenHeight, RED, BLUE); - Image radialGradient = GenImageRadialGradient(screenWidth, screenHeight, 0.f, WHITE, BLACK); + Image radialGradient = GenImageGradientRadial(screenWidth, screenHeight, 0.f, WHITE, BLACK); Image checked = GenImageChecked(screenWidth, screenHeight, 32, 32, RED, BLUE); Image whiteNoise = GenImageWhiteNoise(screenWidth, screenHeight, 0.5f); Image perlinNoise = GenImagePerlinNoise(screenWidth, screenHeight, 8.f); @@ -39,20 +40,37 @@ int main() textures[6] = LoadTextureFromImage(cellular); int currentTexture = 0; - + + SetTargetFPS(60); + //--------------------------------------------------------------------------------------- + + // Main game loop while (!WindowShouldClose()) { + // Update + //---------------------------------------------------------------------------------- if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) { currentTexture = (currentTexture + 1) % TEXTURES_NUM; // cycle between the 5 textures } + //---------------------------------------------------------------------------------- + // Draw + //---------------------------------------------------------------------------------- BeginDrawing(); + ClearBackground(RAYWHITE); + DrawTexture(textures[currentTexture], 0, 0, WHITE); + EndDrawing(); + //---------------------------------------------------------------------------------- } + // De-Initialization + //-------------------------------------------------------------------------------------- + + // Unload image data (CPU RAM) UnloadImage(verticalGradient); UnloadImage(horizontalGradient); UnloadImage(radialGradient); @@ -60,10 +78,12 @@ int main() UnloadImage(whiteNoise); UnloadImage(perlinNoise); UnloadImage(cellular); - for (int i = 0; i < TEXTURES_NUM; i++) // unload the textures - { - UnloadTexture(textures[i]); - } - - CloseWindow(); + + // Unload textures data (GPU VRAM) + for (int i = 0; i < TEXTURES_NUM; i++) UnloadTexture(textures[i]); + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; } diff --git a/examples/textures/textures_image_generation.png b/examples/textures/textures_image_generation.png new file mode 100644 index 00000000..a272b405 Binary files /dev/null and b/examples/textures/textures_image_generation.png differ diff --git a/src/raylib.h b/src/raylib.h index 3d09eff0..04aa3b5a 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -876,7 +876,7 @@ RLAPI void ImageColorBrightness(Image *image, int brightness); // Image generation functions RLAPI Image GenImageGradientV(int width, int height, Color top, Color bottom); // Generate image: vertical gradient RLAPI Image GenImageGradientH(int width, int height, Color left, Color right); // Generate image: horizontal gradient -RLAPI Image GenImageRadialGradient(int width, int height, float density, Color inner, Color outer); // Generate image: radial gradient +RLAPI Image GenImageGradientRadial(int width, int height, float density, Color inner, Color outer); // Generate image: radial gradient RLAPI Image GenImageChecked(int width, int height, int checksX, int checksY, Color col1, Color col2); // Generate image: checked RLAPI Image GenImageWhiteNoise(int width, int height, float factor); // Generate image: white noise RLAPI Image GenImagePerlinNoise(int width, int height, float scale); // Generate image: perlin noise diff --git a/src/textures.c b/src/textures.c index 28bc27f8..0a8d7591 100644 --- a/src/textures.c +++ b/src/textures.c @@ -1453,13 +1453,13 @@ Image GenImageGradientV(int width, int height, Color top, Color bottom) for (int j = 0; j < height; j++) { - float factor = (float)j / (float)height; + float factor = (float)j/(float)height; for (int i = 0; i < width; i++) { - pixels[j*width + i].r = (int)((float)bottom.r * factor + (float)top.r * (1.f - factor)); - pixels[j*width + i].g = (int)((float)bottom.g * factor + (float)top.g * (1.f - factor)); - pixels[j*width + i].b = (int)((float)bottom.b * factor + (float)top.b * (1.f - factor)); - pixels[j*width + i].a = (int)((float)bottom.a * factor + (float)top.a * (1.f - factor)); + pixels[j*width + i].r = (int)((float)bottom.r*factor + (float)top.r*(1.f - factor)); + pixels[j*width + i].g = (int)((float)bottom.g*factor + (float)top.g*(1.f - factor)); + pixels[j*width + i].b = (int)((float)bottom.b*factor + (float)top.b*(1.f - factor)); + pixels[j*width + i].a = (int)((float)bottom.a*factor + (float)top.a*(1.f - factor)); } } @@ -1476,13 +1476,13 @@ Image GenImageGradientH(int width, int height, Color left, Color right) for (int i = 0; i < width; i++) { - float factor = (float)i / (float)width; + float factor = (float)i/(float)width; for (int j = 0; j < height; j++) { - pixels[j*width + i].r = (int)((float)right.r * factor + (float)left.r * (1.f - factor)); - pixels[j*width + i].g = (int)((float)right.g * factor + (float)left.g * (1.f - factor)); - pixels[j*width + i].b = (int)((float)right.b * factor + (float)left.b * (1.f - factor)); - pixels[j*width + i].a = (int)((float)right.a * factor + (float)left.a * (1.f - factor)); + pixels[j*width + i].r = (int)((float)right.r*factor + (float)left.r*(1.f - factor)); + pixels[j*width + i].g = (int)((float)right.g*factor + (float)left.g*(1.f - factor)); + pixels[j*width + i].b = (int)((float)right.b*factor + (float)left.b*(1.f - factor)); + pixels[j*width + i].a = (int)((float)right.a*factor + (float)left.a*(1.f - factor)); } } @@ -1493,25 +1493,28 @@ Image GenImageGradientH(int width, int height, Color left, Color right) } // Generate image: radial gradient -Image GenImageRadialGradient(int width, int height, float density, Color inner, Color outer) +Image GenImageGradientRadial(int width, int height, float density, Color inner, Color outer) { - Color *pixels = (Color*)malloc(width * height * sizeof(Color)); - float radius = (width < height) ? (float)width / 2.f : (float)height / 2.f; + Color *pixels = (Color *)malloc(width*height*sizeof(Color)); + float radius = (width < height) ? (float)width/2.0f : (float)height/2.0f; - float center_x = (float)width / 2.f; - float center_y = (float)height / 2.f; + float centerX = (float)width/2.0f; + float centerY = (float)height/2.0f; + for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { - float dist = hypotf((float)x - center_x, (float)y - center_y); - float factor = (dist - radius * density) / (radius * (1.f - density)); + float dist = hypotf((float)x - centerX, (float)y - centerY); + float factor = (dist - radius*density)/(radius*(1.0f - density)); + factor = fmax(factor, 0.f); factor = fmin(factor, 1.f); // dist can be bigger than radius so we have to check - pixels[y*width + x].r = (int)((float)outer.r * factor + (float)inner.r * (1.f - factor)); - pixels[y*width + x].g = (int)((float)outer.g * factor + (float)inner.g * (1.f - factor)); - pixels[y*width + x].b = (int)((float)outer.b * factor + (float)inner.b * (1.f - factor)); - pixels[y*width + x].a = (int)((float)outer.a * factor + (float)inner.a * (1.f - factor)); + + pixels[y*width + x].r = (int)((float)outer.r*factor + (float)inner.r*(1.0f - factor)); + pixels[y*width + x].g = (int)((float)outer.g*factor + (float)inner.g*(1.0f - factor)); + pixels[y*width + x].b = (int)((float)outer.b*factor + (float)inner.b*(1.0f - factor)); + pixels[y*width + x].a = (int)((float)outer.a*factor + (float)inner.a*(1.0f - factor)); } } @@ -1530,7 +1533,7 @@ Image GenImageChecked(int width, int height, int checksX, int checksY, Color col { for (int x = 0; x < width; x++) { - if ((x/checksX + y/checksY) % 2 == 0) pixels[y*width + x] = col1; + if ((x/checksX + y/checksY)%2 == 0) pixels[y*width + x] = col1; else pixels[y*width + x] = col2; } } @@ -1548,7 +1551,7 @@ Image GenImageWhiteNoise(int width, int height, float factor) for (int i = 0; i < width*height; i++) { - if (GetRandomValue(0, 99) < (int)(factor * 100.f)) pixels[i] = WHITE; + if (GetRandomValue(0, 99) < (int)(factor*100.0f)) pixels[i] = WHITE; else pixels[i] = BLACK; } @@ -1561,17 +1564,19 @@ Image GenImageWhiteNoise(int width, int height, float factor) // Generate image: perlin noise Image GenImagePerlinNoise(int width, int height, float scale) { - Color *pixels = (Color*)malloc(width * height * sizeof(Color)); + Color *pixels = (Color *)malloc(width*height*sizeof(Color)); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { - float nx = (float)x * scale / (float)width; - float ny = (float)y * scale / (float)height; + float nx = (float)x*scale/(float)width; + float ny = (float)y*scale/(float)height; + // we need to translate the data from [-1; 1] to [0; 1] - float p = (stb_perlin_fbm_noise3(nx, ny, 1.f, 2.f, 0.5f, 6, 0, 0, 0) + 1.f) / 2.f; - int intensity = (int)(p * 255.f); + float p = (stb_perlin_fbm_noise3(nx, ny, 1.0f, 2.0f, 0.5f, 6, 0, 0, 0) + 1.0f) / 2.0f; + + int intensity = (int)(p * 255.0f); pixels[y*width + x] = (Color){intensity, intensity, intensity, 255}; } } @@ -1585,54 +1590,55 @@ Image GenImagePerlinNoise(int width, int height, float scale) // Generate image: cellular algorithm. Bigger tileSize means bigger cells Image GenImageCellular(int width, int height, int tileSize) { - Color *pixels = (Color*)malloc(width*height*sizeof(Color)); + Color *pixels = (Color *)malloc(width*height*sizeof(Color)); - int seeds_per_row = width / tileSize; - int seeds_per_col = height / tileSize; - int seeds_count = seeds_per_row * seeds_per_col; + int seedsPerRow = width/tileSize; + int seedsPerCol = height/tileSize; + int seedsCount = seedsPerRow * seedsPerCol; - Vector2* seeds = (Vector2*)malloc(seeds_count * sizeof(Vector2)); + Vector2 *seeds = (Vector2 *)malloc(seedsCount*sizeof(Vector2)); - for (int i = 0; i < seeds_count; i++) + for (int i = 0; i < seedsCount; i++) { - int y = (i / seeds_per_row) * tileSize + GetRandomValue(0, tileSize-1); - int x = (i % seeds_per_row) * tileSize + GetRandomValue(0, tileSize-1); + int y = (i/seedsPerRow)*tileSize + GetRandomValue(0, tileSize - 1); + int x = (i%seedsPerRow)*tileSize + GetRandomValue(0, tileSize - 1); seeds[i] = (Vector2){x, y}; } for (int y = 0; y < height; y++) { - int tile_y = y / tileSize; + int tileY = y/tileSize; + for (int x = 0; x < width; x++) { - int tile_x = x / tileSize; + int tileX = x/tileSize; - float min_distance = strtod("Inf", NULL); + float minDistance = strtod("Inf", NULL); // Check all adjacent tiles for (int i = -1; i < 2; i++) { - if (tile_x + i < 0 || tile_x + i >= seeds_per_row) continue; + if ((tileX + i < 0) || (tileX + i >= seedsPerRow)) continue; for (int j = -1; j < 2; j++) { - if (tile_y + j < 0 || tile_y + j >= seeds_per_col) continue; + if ((tileY + j < 0) || (tileY + j >= seedsPerCol)) continue; - Vector2 neighbor_seed = seeds[(tile_y+j) * seeds_per_row + tile_x+i]; + Vector2 neighborSeed = seeds[(tileY + j)*seedsPerRow + tileX + i]; - float dist = hypot(x - (int)neighbor_seed.x, y - (int)neighbor_seed.y); - min_distance = fmin(min_distance, dist); + float dist = hypot(x - (int)neighborSeed.x, y - (int)neighborSeed.y); + minDistance = fmin(minDistance, dist); } } // I made this up but it seems to give good results at all tile sizes - int intensity = (int)(min_distance * 256.f / tileSize); + int intensity = (int)(minDistance*256.0f/tileSize); if (intensity > 255) intensity = 255; - Color c = {intensity, intensity, intensity, 255}; - pixels[y*width + x] = c; + pixels[y*width + x] = (Color){ intensity, intensity, intensity, 255 }; } } + free(seeds); Image image = LoadImageEx(pixels, width, height); -- cgit v1.2.3 From 6546474fa45234ed0a84f62be705d9a9aee43079 Mon Sep 17 00:00:00 2001 From: Ray Date: Mon, 17 Jul 2017 00:33:40 +0200 Subject: Manual integration of material-pbr into develop --- examples/models/models_cubicmap.c | 10 +- examples/models/models_material_pbr.c | 185 +++++++ examples/models/models_material_pbr.png | Bin 0 -> 193874 bytes examples/models/models_skybox.c | 89 +++ examples/models/models_skybox.png | Bin 0 -> 723949 bytes examples/shaders/shaders_model_shader.c | 2 +- src/core.c | 10 +- src/models.c | 535 +++++++++++++----- src/raylib.h | 125 +++-- src/rlgl.c | 952 +++++++++++++++++++++++--------- src/rlgl.h | 205 ++++--- src/shapes.c | 10 +- src/textures.c | 22 +- 13 files changed, 1597 insertions(+), 548 deletions(-) create mode 100644 examples/models/models_material_pbr.c create mode 100644 examples/models/models_material_pbr.png create mode 100644 examples/models/models_skybox.c create mode 100644 examples/models/models_skybox.png (limited to 'src/raylib.h') diff --git a/examples/models/models_cubicmap.c b/examples/models/models_cubicmap.c index 0e613029..ceef6378 100644 --- a/examples/models/models_cubicmap.c +++ b/examples/models/models_cubicmap.c @@ -25,11 +25,13 @@ int main() Image image = LoadImage("resources/cubicmap.png"); // Load cubicmap image (RAM) Texture2D cubicmap = LoadTextureFromImage(image); // Convert image to texture to display (VRAM) - Model map = LoadCubicmap(image); // Load cubicmap model (generate model from image) + + Mesh mesh = GenMeshCubicmap(image, VectorOne()); + Model model = LoadModelFromMesh(mesh, false); // NOTE: By default each cube is mapped to one part of texture atlas Texture2D texture = LoadTexture("resources/cubicmap_atlas.png"); // Load map texture - map.material.texDiffuse = texture; // Set map diffuse texture + model.material.maps[TEXMAP_DIFFUSE].tex = texture; // Set map diffuse texture Vector3 mapPosition = { -16.0f, 0.0f, -8.0f }; // Set model position @@ -56,7 +58,7 @@ int main() Begin3dMode(camera); - DrawModel(map, mapPosition, 1.0f, WHITE); + DrawModel(model, mapPosition, 1.0f, WHITE); End3dMode(); @@ -76,7 +78,7 @@ int main() //-------------------------------------------------------------------------------------- UnloadTexture(cubicmap); // Unload cubicmap texture UnloadTexture(texture); // Unload map texture - UnloadModel(map); // Unload map model + UnloadModel(model); // Unload map model CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- diff --git a/examples/models/models_material_pbr.c b/examples/models/models_material_pbr.c new file mode 100644 index 00000000..9380bd91 --- /dev/null +++ b/examples/models/models_material_pbr.c @@ -0,0 +1,185 @@ +/******************************************************************************************* +* +* raylib [models] example - PBR material +* +* This example has been created using raylib 1.8 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Copyright (c) 2017 Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" +#include "raymath.h" + +#define MAX_LIGHTS 4 // Max lights supported by shader +#define LIGHT_DISTANCE 3.5f // Light distance from world center +#define LIGHT_HEIGHT 1.0f // Light height position + +typedef enum { + LIGHT_DIRECTIONAL, + LIGHT_POINT +} LightType; + +typedef struct { + bool enabled; + LightType type; + Vector3 position; + Vector3 target; + Color color; + int enabledLoc; + int typeLoc; + int posLoc; + int targetLoc; + int colorLoc; +} Light; + +int lightsCount = 0; // Current amount of created lights + +Light CreateLight(int type, Vector3 pos, Vector3 targ, Color color, Shader shader); // Defines a light and get locations from PBR shader +void UpdateLightValues(Shader shader, Light light); // Send to PBR shader light values + +int main() +{ + // Initialization + //-------------------------------------------------------------------------------------- + int screenWidth = 800; + int screenHeight = 450; + + SetConfigFlags(FLAG_MSAA_4X_HINT); // Enable Multi Sampling Anti Aliasing 4x (if available) + InitWindow(screenWidth, screenHeight, "raylib [models] example - pbr material"); + + // Define the camera to look into our 3d world + Camera camera = {{ 4.0f, 4.0f, 4.0f }, { 0.0f, 0.5f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f }; + + // Load model and PBR material + Model model = LoadModel("resources/pbr/trooper.obj"); + + Texture2D texHDR = LoadTexture("resources/pinetree.hdr"); + model.material = LoadMaterialPBR(texHDR, (Color){ 255, 255, 255, 255 }, 1.0f, 1.0f); + + SetMaterialTexture(&model.material, TEXMAP_ALBEDO, LoadTexture("resources/pbr/trooper_albedo.png")); + SetMaterialTexture(&model.material, TEXMAP_NORMAL, LoadTexture("resources/pbr/trooper_normals.png")); + SetMaterialTexture(&model.material, TEXMAP_METALNESS, LoadTexture("resources/pbr/trooper_metalness.png")); + SetMaterialTexture(&model.material, TEXMAP_ROUGHNESS, LoadTexture("resources/pbr/trooper_roughness.png")); + SetMaterialTexture(&model.material, TEXMAP_OCCLUSION, LoadTexture("resources/pbr/trooper_ao.png")); + + // Set textures filtering for better quality + SetTextureFilter(model.material.maps[TEXMAP_ALBEDO].tex, FILTER_BILINEAR); + SetTextureFilter(model.material.maps[TEXMAP_NORMAL].tex, FILTER_BILINEAR); + SetTextureFilter(model.material.maps[TEXMAP_METALNESS].tex, FILTER_BILINEAR); + SetTextureFilter(model.material.maps[TEXMAP_ROUGHNESS].tex, FILTER_BILINEAR); + SetTextureFilter(model.material.maps[TEXMAP_OCCLUSION].tex, FILTER_BILINEAR); + + int renderModeLoc = GetShaderLocation(model.material.shader, "renderMode"); + SetShaderValuei(model.material.shader, renderModeLoc, (int[1]){ 0 }, 1); + + SetCameraMode(camera, CAMERA_ORBITAL); // Set an orbital camera mode + + // Define lights attributes + Light lights[MAX_LIGHTS] = { CreateLight(LIGHT_POINT, (Vector3){ LIGHT_DISTANCE, LIGHT_HEIGHT, 0.0f }, (Vector3){ 0.0f, 0.0f, 0.0f }, (Color){ 255, 0, 0, 255 }, model.material.shader), + CreateLight(LIGHT_POINT, (Vector3){ 0.0f, LIGHT_HEIGHT, LIGHT_DISTANCE }, (Vector3){ 0.0f, 0.0f, 0.0f }, (Color){ 0, 255, 0, 255 }, model.material.shader), + CreateLight(LIGHT_POINT, (Vector3){ -LIGHT_DISTANCE, LIGHT_HEIGHT, 0.0f }, (Vector3){ 0.0f, 0.0f, 0.0f }, (Color){ 0, 0, 255, 255 }, model.material.shader), + CreateLight(LIGHT_DIRECTIONAL, (Vector3){ 0.0f, LIGHT_HEIGHT*2.0f, -LIGHT_DISTANCE }, (Vector3){ 0.0f, 0.0f, 0.0f }, (Color){ 255, 0, 255, 255 }, model.material.shader) }; + + SetTargetFPS(60); // Set our game to run at 60 frames-per-second + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + UpdateCamera(&camera); // Update camera + + // Send to material PBR shader camera view position + float cameraPos[3] = { camera.position.x, camera.position.y, camera.position.z }; + SetShaderValue(model.material.shader, model.material.shader.locs[LOC_VECTOR_VIEW], cameraPos, 3); + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + Begin3dMode(camera); + + DrawModel(model, VectorZero(), 1.0f, WHITE); + + DrawGrid(10, 1.0f); + + End3dMode(); + + DrawFPS(10, 10); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + UnloadModel(model); // Unload skybox model + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} + +// Defines a light and get locations from PBR shader +Light CreateLight(int type, Vector3 pos, Vector3 targ, Color color, Shader shader) +{ + Light light = { 0 }; + + if (lightsCount < MAX_LIGHTS) + { + light.enabled = true; + light.type = type; + light.position = pos; + light.target = targ; + light.color = color; + + char enabledName[32] = "lights[x].enabled\0"; + char typeName[32] = "lights[x].type\0"; + char posName[32] = "lights[x].position\0"; + char targetName[32] = "lights[x].target\0"; + char colorName[32] = "lights[x].color\0"; + enabledName[7] = '0' + lightsCount; + typeName[7] = '0' + lightsCount; + posName[7] = '0' + lightsCount; + targetName[7] = '0' + lightsCount; + colorName[7] = '0' + lightsCount; + + light.enabledLoc = GetShaderLocation(shader, enabledName); + light.typeLoc = GetShaderLocation(shader, typeName); + light.posLoc = GetShaderLocation(shader, posName); + light.targetLoc = GetShaderLocation(shader, targetName); + light.colorLoc = GetShaderLocation(shader, colorName); + + UpdateLightValues(shader, light); + lightsCount++; + } + + return light; +} + +// Send to PBR shader light values +void UpdateLightValues(Shader shader, Light light) +{ + // Send to shader light enabled state and type + SetShaderValuei(shader, light.enabledLoc, (int[1]){ light.enabled }, 1); + SetShaderValuei(shader, light.typeLoc, (int[1]){ light.type }, 1); + + // Send to shader light position values + float position[3] = { light.position.x, light.position.y, light.position.z }; + SetShaderValue(shader, light.posLoc, position, 3); + + // Send to shader light target position values + float target[3] = { light.target.x, light.target.y, light.target.z }; + SetShaderValue(shader, light.targetLoc, target, 3); + + // Send to shader light color values + float diff[4] = { (float)light.color.r/(float)255, (float)light.color.g/(float)255, (float)light.color.b/(float)255, (float)light.color.a/(float)255 }; + SetShaderValue(shader, light.colorLoc, diff, 4); +} diff --git a/examples/models/models_material_pbr.png b/examples/models/models_material_pbr.png new file mode 100644 index 00000000..cde171b9 Binary files /dev/null and b/examples/models/models_material_pbr.png differ diff --git a/examples/models/models_skybox.c b/examples/models/models_skybox.c new file mode 100644 index 00000000..8b302b1c --- /dev/null +++ b/examples/models/models_skybox.c @@ -0,0 +1,89 @@ +/******************************************************************************************* +* +* raylib [models] example - Skybox loading and drawing +* +* This example has been created using raylib 1.8 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Copyright (c) 2017 Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" +#include "raymath.h" + +int main() +{ + // Initialization + //-------------------------------------------------------------------------------------- + int screenWidth = 800; + int screenHeight = 450; + + InitWindow(screenWidth, screenHeight, "raylib [models] example - skybox loading and drawing"); + + // Define the camera to look into our 3d world + Camera camera = {{ 1.0f, 1.0f, 1.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f }; + + // Load skybox model and shader + Mesh cube = GenMeshCube(1.0f, 1.0f, 1.0f); + Model skybox = LoadModelFromMesh(cube, false); + skybox.material.shader = LoadShader("resources/shaders/skybox.vs", "resources/shaders/skybox.fs"); + + Texture2D texHDR = LoadTexture("resources/pinetree.hdr"); + skybox.material.maps[TEXMAP_CUBEMAP].tex = rlGenMapCubemap(texHDR, 512); + SetShaderValuei(skybox.material.shader, GetShaderLocation(skybox.material.shader, "environmentMap"), (int[1]){ TEXMAP_CUBEMAP }, 1); + + // Get skybox shader locations + skybox.material.shader.locs[LOC_MATRIX_PROJECTION] = GetShaderLocation(skybox.material.shader, "projection"); + skybox.material.shader.locs[LOC_MATRIX_VIEW] = GetShaderLocation(skybox.material.shader, "view"); + + // Then before rendering, configure the viewport to the actual screen dimensions + Matrix proj = MatrixPerspective(60.0, (double)GetScreenWidth()/(double)GetScreenHeight(), 0.01, 1000.0); + MatrixTranspose(&proj); + SetShaderValueMatrix(skybox.material.shader, skybox.material.shader.locs[LOC_MATRIX_PROJECTION], proj); + + SetCameraMode(camera, CAMERA_ORBITAL); // Set an orbital camera mode + + SetTargetFPS(60); // Set our game to run at 60 frames-per-second + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + UpdateCamera(&camera); // Update camera + + Matrix view = MatrixLookAt(camera.position, camera.target, camera.up); + SetShaderValueMatrix(skybox.material.shader, skybox.material.shader.locs[LOC_MATRIX_VIEW], view); + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + Begin3dMode(camera); + + DrawModel(skybox, VectorZero(), 1.0f, RED); + + DrawGrid(10, 1.0f); + + End3dMode(); + + DrawFPS(10, 10); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + UnloadModel(skybox); // Unload skybox model + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} diff --git a/examples/models/models_skybox.png b/examples/models/models_skybox.png new file mode 100644 index 00000000..31694fa5 Binary files /dev/null and b/examples/models/models_skybox.png differ diff --git a/examples/shaders/shaders_model_shader.c b/examples/shaders/shaders_model_shader.c index 51e9c1b3..ef5665d2 100644 --- a/examples/shaders/shaders_model_shader.c +++ b/examples/shaders/shaders_model_shader.c @@ -38,7 +38,7 @@ int main() "resources/shaders/glsl330/grayscale.fs"); // Load model shader dwarf.material.shader = shader; // Set shader effect to 3d model - dwarf.material.texDiffuse = texture; // Bind texture to model + dwarf.material.maps[TEXMAP_DIFFUSE].tex = texture; // Bind texture to model Vector3 position = { 0.0f, 0.0f, 0.0f }; // Set model position diff --git a/src/core.c b/src/core.c index a447d750..ad905d4e 100644 --- a/src/core.c +++ b/src/core.c @@ -809,7 +809,7 @@ void EndDrawing(void) { // Get image data for the current frame (from backbuffer) // NOTE: This process is very slow... :( - unsigned char *screenData = rlglReadScreenPixels(screenWidth, screenHeight); + unsigned char *screenData = rlReadScreenPixels(screenWidth, screenHeight); GifWriteFrame(screenData, screenWidth, screenHeight, 10, 8, false); free(screenData); // Free image data @@ -994,10 +994,10 @@ Ray GetMouseRay(Vector2 mousePosition, Camera camera) MatrixTranspose(&matView); //#define USE_RLGL_UNPROJECT -#if defined(USE_RLGL_UNPROJECT) // OPTION 1: Use rlglUnproject() +#if defined(USE_RLGL_UNPROJECT) // OPTION 1: Use rlUnproject() - Vector3 nearPoint = rlglUnproject((Vector3){ deviceCoords.x, deviceCoords.y, 0.0f }, matProj, matView); - Vector3 farPoint = rlglUnproject((Vector3){ deviceCoords.x, deviceCoords.y, 1.0f }, matProj, matView); + Vector3 nearPoint = rlUnproject((Vector3){ deviceCoords.x, deviceCoords.y, 0.0f }, matProj, matView); + Vector3 farPoint = rlUnproject((Vector3){ deviceCoords.x, deviceCoords.y, 1.0f }, matProj, matView); #else // OPTION 2: Compute unprojection directly here @@ -1201,7 +1201,7 @@ void SetConfigFlags(char flags) void TakeScreenshot(const char *fileName) { #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) - unsigned char *imgData = rlglReadScreenPixels(renderWidth, renderHeight); + unsigned char *imgData = rlReadScreenPixels(renderWidth, renderHeight); SavePNG(fileName, imgData, renderWidth, renderHeight, 4); // Save image as PNG free(imgData); diff --git a/src/models.c b/src/models.c index 286581df..d9404c12 100644 --- a/src/models.c +++ b/src/models.c @@ -76,9 +76,6 @@ static Mesh LoadOBJ(const char *fileName); // Load OBJ mesh data static Material LoadMTL(const char *fileName); // Load MTL material data #endif -static Mesh GenMeshHeightmap(Image image, Vector3 size); -static Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize); - //---------------------------------------------------------------------------------- // Module Functions Definition //---------------------------------------------------------------------------------- @@ -587,110 +584,32 @@ void DrawGizmo(Vector3 position) rlPopMatrix(); } -// Load mesh from file -Mesh LoadMesh(const char *fileName) -{ - Mesh mesh = { 0 }; - -#if defined(SUPPORT_FILEFORMAT_OBJ) - if (IsFileExtension(fileName, ".obj")) mesh = LoadOBJ(fileName); -#else - TraceLog(LOG_WARNING, "[%s] Mesh fileformat not supported, it can't be loaded", fileName); -#endif - - if (mesh.vertexCount == 0) TraceLog(LOG_WARNING, "Mesh could not be loaded"); - else rlglLoadMesh(&mesh, false); // Upload vertex data to GPU (static mesh) - - // TODO: Initialize default mesh data in case loading fails, maybe a cube? - - return mesh; -} - -// Load mesh from vertex data -// NOTE: All vertex data arrays must be same size: vertexCount -Mesh LoadMeshEx(int vertexCount, float *vData, float *vtData, float *vnData, Color *cData) -{ - Mesh mesh = { 0 }; - - mesh.vertexCount = vertexCount; - mesh.triangleCount = vertexCount/3; - mesh.vertices = vData; - mesh.texcoords = vtData; - mesh.texcoords2 = NULL; - mesh.normals = vnData; - mesh.tangents = NULL; - mesh.colors = (unsigned char *)cData; - mesh.indices = NULL; - - rlglLoadMesh(&mesh, false); // Upload vertex data to GPU (static mesh) - - return mesh; -} - -// Load model from file +// Load model from files (mesh and material) Model LoadModel(const char *fileName) { Model model = { 0 }; model.mesh = LoadMesh(fileName); model.transform = MatrixIdentity(); - model.material = LoadDefaultMaterial(); - - return model; -} - -// Load model from mesh data -Model LoadModelFromMesh(Mesh data, bool dynamic) -{ - Model model = { 0 }; - - model.mesh = data; - - rlglLoadMesh(&model.mesh, dynamic); // Upload vertex data to GPU - - model.transform = MatrixIdentity(); - model.material = LoadDefaultMaterial(); + model.material = LoadMaterialDefault(); return model; } -// Load heightmap model from image data -// NOTE: model map size is defined in generic units -Model LoadHeightmap(Image heightmap, Vector3 size) +// Load model from generated mesh +Model LoadModelFromMesh(Mesh mesh, bool dynamic) { Model model = { 0 }; - - model.mesh = GenMeshHeightmap(heightmap, size); - - rlglLoadMesh(&model.mesh, false); // Upload vertex data to GPU (static model) - - model.transform = MatrixIdentity(); - model.material = LoadDefaultMaterial(); - - return model; -} - -// Load cubes-based map model from image data -Model LoadCubicmap(Image cubicmap) -{ - Model model = { 0 }; - - model.mesh = GenMeshCubicmap(cubicmap, (Vector3){ 1.0f, 1.5f, 1.0f }); - - rlglLoadMesh(&model.mesh, false); // Upload vertex data to GPU (static model) - + + rlLoadMesh(&mesh, dynamic); + + model.mesh = mesh; model.transform = MatrixIdentity(); - model.material = LoadDefaultMaterial(); + model.material = LoadMaterialDefault(); return model; } -// Unload mesh from memory (RAM and/or VRAM) -void UnloadMesh(Mesh *mesh) -{ - rlglUnloadMesh(mesh); -} - // Unload model from memory (RAM and/or VRAM) void UnloadModel(Model model) { @@ -700,49 +619,190 @@ void UnloadModel(Model model) TraceLog(LOG_INFO, "Unloaded model data (mesh and material) from RAM and VRAM"); } -// Load material data (from file) -Material LoadMaterial(const char *fileName) +// Load mesh from file +Mesh LoadMesh(const char *fileName) { - Material material = { 0 }; + Mesh mesh = { 0 }; -#if defined(SUPPORT_FILEFORMAT_MTL) - if (IsFileExtension(fileName, ".mtl")) material = LoadMTL(fileName); +#if defined(SUPPORT_FILEFORMAT_OBJ) + if (IsFileExtension(fileName, ".obj")) mesh = LoadOBJ(fileName); #else - TraceLog(LOG_WARNING, "[%s] Material fileformat not supported, it can't be loaded", fileName); + TraceLog(WARNING, "[%s] Mesh fileformat not supported, it can't be loaded", fileName); #endif - return material; -} - -// Load default material (uses default models shader) -Material LoadDefaultMaterial(void) -{ - Material material = { 0 }; + if (mesh.vertexCount == 0) TraceLog(WARNING, "Mesh could not be loaded"); + else rlLoadMesh(&mesh, false); // Upload vertex data to GPU (static mesh) - material.shader = GetDefaultShader(); - material.texDiffuse = GetDefaultTexture(); // White texture (1x1 pixel) - //material.texNormal; // NOTE: By default, not set - //material.texSpecular; // NOTE: By default, not set - - material.colDiffuse = WHITE; // Diffuse color - material.colAmbient = WHITE; // Ambient color - material.colSpecular = WHITE; // Specular color + // TODO: Initialize default mesh data in case loading fails, maybe a cube? - material.glossiness = 100.0f; // Glossiness level + return mesh; +} - return material; +// Unload mesh from memory (RAM and/or VRAM) +void UnloadMesh(Mesh *mesh) +{ + rlUnloadMesh(mesh); } -// Unload material from memory -void UnloadMaterial(Material material) +// Generated cuboid mesh +Mesh GenMeshCube(float width, float height, float length) { - rlDeleteTextures(material.texDiffuse.id); - rlDeleteTextures(material.texNormal.id); - rlDeleteTextures(material.texSpecular.id); + Mesh mesh = { 0 }; + /* + float vertices[] = { + -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, + 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, + 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, + 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, + -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, + -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, + -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, + 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, + 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, + -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, + -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, + -1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, + -1.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, + -1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, + -1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, + -1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, + -1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, + 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, + 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, + 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, + 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, + 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, + 1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, + -1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, + 1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f, + 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, + 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, + -1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, + -1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, + -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, + 1.0f, 1.0f , 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, + 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, + -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, + -1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f + }; + */ + float vertices[] = { + -width/2, -height/2, length/2, + width/2, -height/2, length/2, + width/2, height/2, length/2, + -width/2, height/2, length/2, + -width/2, -height/2, -length/2, + -width/2, height/2, -length/2, + width/2, height/2, -length/2, + width/2, -height/2, -length/2, + -width/2, height/2, -length/2, + -width/2, height/2, length/2, + width/2, height/2, length/2, + width/2, height/2, -length/2, + -width/2, -height/2, -length/2, + width/2, -height/2, -length/2, + width/2, -height/2, length/2, + -width/2, -height/2, length/2, + width/2, -height/2, -length/2, + width/2, height/2, -length/2, + width/2, height/2, length/2, + width/2, -height/2, length/2, + -width/2, -height/2, -length/2, + -width/2, -height/2, length/2, + -width/2, height/2, length/2, + -width/2, height/2, -length/2 + }; + + float texcoords[] = { + 0.0f, 0.0f, + 1.0f, 0.0f, + 1.0f, 1.0f, + 0.0f, 1.0f, + 1.0f, 0.0f, + 1.0f, 1.0f, + 0.0f, 1.0f, + 0.0f, 0.0f, + 0.0f, 1.0f, + 0.0f, 0.0f, + 1.0f, 0.0f, + 1.0f, 1.0f, + 1.0f, 1.0f, + 0.0f, 1.0f, + 0.0f, 0.0f, + 1.0f, 0.0f, + 1.0f, 0.0f, + 1.0f, 1.0f, + 0.0f, 1.0f, + 0.0f, 0.0f, + 0.0f, 0.0f, + 1.0f, 0.0f, + 1.0f, 1.0f, + 0.0f, 1.0f + }; + + float normals[] = { + 0.0f, 0.0f, 1.0f, + 0.0f, 0.0f, 1.0f, + 0.0f, 0.0f, 1.0f, + 0.0f, 0.0f, 1.0f, + 0.0f, 0.0f,-1.0f, + 0.0f, 0.0f,-1.0f, + 0.0f, 0.0f,-1.0f, + 0.0f, 0.0f,-1.0f, + 0.0f, 1.0f, 0.0f, + 0.0f, 1.0f, 0.0f, + 0.0f, 1.0f, 0.0f, + 0.0f, 1.0f, 0.0f, + 0.0f,-1.0f, 0.0f, + 0.0f,-1.0f, 0.0f, + 0.0f,-1.0f, 0.0f, + 0.0f,-1.0f, 0.0f, + 1.0f, 0.0f, 0.0f, + 1.0f, 0.0f, 0.0f, + 1.0f, 0.0f, 0.0f, + 1.0f, 0.0f, 0.0f, + -1.0f, 0.0f, 0.0f, + -1.0f, 0.0f, 0.0f, + -1.0f, 0.0f, 0.0f, + -1.0f, 0.0f, 0.0f + }; + + mesh.vertices = (float *)malloc(24*3*sizeof(float)); + memcpy(mesh.vertices, vertices, 24*3*sizeof(float)); + + mesh.texcoords = (float *)malloc(24*2*sizeof(float)); + memcpy(mesh.texcoords, texcoords, 24*2*sizeof(float)); + + mesh.normals = (float *)malloc(24*3*sizeof(float)); + memcpy(mesh.normals, normals, 24*3*sizeof(float)); + + mesh.indices = (unsigned short *)malloc(36*sizeof(unsigned short)); + + int k = 0; + + // Indices can be initialized right now + for (int i = 0; i < 36; i+=6) + { + mesh.indices[i] = 4*k; + mesh.indices[i+1] = 4*k+1; + mesh.indices[i+2] = 4*k+2; + mesh.indices[i+3] = 4*k; + mesh.indices[i+4] = 4*k+2; + mesh.indices[i+5] = 4*k+3; + + k++; + } + + mesh.vertexCount = 24; + mesh.triangleCount = 12; + + return mesh; } // Generate a mesh from heightmap -static Mesh GenMeshHeightmap(Image heightmap, Vector3 size) +Mesh GenMeshHeightmap(Image heightmap, Vector3 size) { #define GRAY_VALUE(c) ((c.r+c.g+c.b)/3) @@ -847,7 +907,7 @@ static Mesh GenMeshHeightmap(Image heightmap, Vector3 size) return mesh; } -static Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize) +Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize) { Mesh mesh = { 0 }; @@ -1201,6 +1261,202 @@ static Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize) return mesh; } +// Load material data (from file) +Material LoadMaterial(const char *fileName) +{ + Material material = { 0 }; + +#if defined(SUPPORT_FILEFORMAT_MTL) + if (IsFileExtension(fileName, ".mtl")) material = LoadMTL(fileName); +#else + TraceLog(WARNING, "[%s] Material fileformat not supported, it can't be loaded", fileName); +#endif + + return material; +} + +// Load default material (Supports: DIFFUSE, SPECULAR, NORMAL maps) +Material LoadMaterialDefault(void) +{ + Material material = { 0 }; + + material.shader = GetShaderDefault(); + material.maps[TEXMAP_DIFFUSE].tex = GetTextureDefault(); // White texture (1x1 pixel) + //material.maps[TEXMAP_NORMAL].tex; // NOTE: By default, not set + //material.maps[TEXMAP_SPECULAR].tex; // NOTE: By default, not set + + material.maps[TEXMAP_DIFFUSE].color = WHITE; // Diffuse color + material.maps[TEXMAP_SPECULAR].color = WHITE; // Specular color + + return material; +} + +// Load PBR material (Supports: ALBEDO, NORMAL, METALNESS, ROUGHNESS, AO, EMMISIVE, HEIGHT maps) +Material LoadMaterialPBR(Texture2D hdr, Color albedo, float metalness, float roughness) +{ + Material mat = { 0 }; + + #define PATH_PBR_VS "resources/shaders/pbr.vs" // Path to physically based rendering vertex shader + #define PATH_PBR_FS "resources/shaders/pbr.fs" // Path to physically based rendering fragment shader + + mat.shader = LoadShader(PATH_PBR_VS, PATH_PBR_FS); + + // Get required locations points for PBR material + // NOTE: Those location names must be available and used in the shader code + mat.shader.locs[LOC_TEXMAP_ALBEDO] = GetShaderLocation(mat.shader, "albedo.sampler"); + mat.shader.locs[LOC_TEXMAP_METALNESS] = GetShaderLocation(mat.shader, "metalness.sampler"); + mat.shader.locs[LOC_TEXMAP_NORMAL] = GetShaderLocation(mat.shader, "normals.sampler"); + mat.shader.locs[LOC_TEXMAP_ROUGHNESS] = GetShaderLocation(mat.shader, "roughness.sampler"); + mat.shader.locs[LOC_TEXMAP_OCCUSION] = GetShaderLocation(mat.shader, "occlusion.sampler"); + mat.shader.locs[LOC_TEXMAP_EMISSION] = GetShaderLocation(mat.shader, "emission.sampler"); + mat.shader.locs[LOC_TEXMAP_HEIGHT] = GetShaderLocation(mat.shader, "height.sampler"); + mat.shader.locs[LOC_TEXMAP_IRRADIANCE] = GetShaderLocation(mat.shader, "irradianceMap"); + mat.shader.locs[LOC_TEXMAP_PREFILTER] = GetShaderLocation(mat.shader, "prefilterMap"); + mat.shader.locs[LOC_TEXMAP_BRDF] = GetShaderLocation(mat.shader, "brdfLUT"); + + // Set view matrix location + mat.shader.locs[LOC_MATRIX_MODEL] = GetShaderLocation(mat.shader, "mMatrix"); + mat.shader.locs[LOC_MATRIX_VIEW] = GetShaderLocation(mat.shader, "view"); + mat.shader.locs[LOC_VECTOR_VIEW] = GetShaderLocation(mat.shader, "viewPos"); + + // Set up material properties color + mat.maps[TEXMAP_ALBEDO].color = albedo; + mat.maps[TEXMAP_NORMAL].color = (Color){ 128, 128, 255, 255 }; + mat.maps[TEXMAP_METALNESS].value = metalness; + mat.maps[TEXMAP_ROUGHNESS].value = roughness; + mat.maps[TEXMAP_OCCLUSION].value = 1.0f; + mat.maps[TEXMAP_EMISSION].value = 0.0f; + mat.maps[TEXMAP_HEIGHT].value = 0.0f; + + #define CUBEMAP_SIZE 1024 // Cubemap texture size + #define IRRADIANCE_SIZE 32 // Irradiance map from cubemap texture size + #define PREFILTERED_SIZE 256 // Prefiltered HDR environment map texture size + #define BRDF_SIZE 512 // BRDF LUT texture map size + + // Set up environment materials cubemap + Texture2D cubemap = rlGenMapCubemap(hdr, CUBEMAP_SIZE); + mat.maps[TEXMAP_IRRADIANCE].tex = rlGenMapIrradiance(cubemap, IRRADIANCE_SIZE); + mat.maps[TEXMAP_PREFILTER].tex = rlGenMapPrefilter(cubemap, PREFILTERED_SIZE); + mat.maps[TEXMAP_BRDF].tex = rlGenMapBRDF(cubemap, BRDF_SIZE); + UnloadTexture(cubemap); + + // NOTE: All maps textures are set to { 0 } + + // Reset viewport dimensions to default + rlViewport(0, 0, GetScreenWidth(), GetScreenHeight()); + + return mat; +} + +// Unload material from memory +void UnloadMaterial(Material material) +{ + // Unload material shader + UnloadShader(material.shader); + + // Unload loaded texture maps + for (int i = 0; i < MAX_MATERIAL_TEXTURE_MAPS; i++) + { + // NOTE: We already check for (tex.id > 0) inside function + rlDeleteTextures(material.maps[i].tex.id); + } +} + +// Set material texture +void SetMaterialTexture(Material *mat, int texmapType, Texture2D texture) +{ + mat->maps[texmapType].tex = texture; + + // Update MaterialProperty use sampler state to use texture fetch instead of color attribute + int location = -1; + switch (texmapType) + { + case TEXMAP_ALBEDO: + { + location = GetShaderLocation(mat->shader, "albedo.useSampler"); + SetShaderValuei(mat->shader, location, (int [1]){ 1 }, 1); + } break; + case TEXMAP_NORMAL: + { + location = GetShaderLocation(mat->shader, "normals.useSampler"); + SetShaderValuei(mat->shader, location, (int [1]){ 1 }, 1); + } break; + case TEXMAP_METALNESS: + { + location = GetShaderLocation(mat->shader, "metalness.useSampler"); + SetShaderValuei(mat->shader, location, (int [1]){ 1 }, 1); + } break; + case TEXMAP_ROUGHNESS: + { + location = GetShaderLocation(mat->shader, "roughness.useSampler"); + SetShaderValuei(mat->shader, location, (int [1]){ 1 }, 1); + } break; + case TEXMAP_OCCLUSION: + { + location = GetShaderLocation(mat->shader, "occlusion.useSampler"); + SetShaderValuei(mat->shader, location, (int [1]){ 1 }, 1); + } break; + case TEXMAP_EMISSION: + { + location = GetShaderLocation(mat->shader, "emission.useSampler"); + SetShaderValuei(mat->shader, location, (int [1]){ 1 }, 1); + } break; + case TEXMAP_HEIGHT: + { + location = GetShaderLocation(mat->shader, "height.useSampler"); + SetShaderValuei(mat->shader, location, (int [1]){ 1 }, 1); + } break; + } +} + +// Unset texture from material and unload it from GPU +void UnsetMaterialTexture(Material *mat, int texmapType) +{ + UnloadTexture(mat->maps[texmapType].tex); + mat->maps[texmapType].tex = (Texture2D){ 0 }; + + // Update MaterialProperty use sampler state to use texture fetch instead of color attribute + int location = -1; + switch (texmapType) + { + case TEXMAP_ALBEDO: + { + location = GetShaderLocation(mat->shader, "albedo.useSampler"); + SetShaderValuei(mat->shader, location, (int [1]){ 0 }, 1); + } break; + case TEXMAP_NORMAL: + { + location = GetShaderLocation(mat->shader, "normals.useSampler"); + SetShaderValuei(mat->shader, location, (int [1]){ 0 }, 1); + } break; + case TEXMAP_METALNESS: + { + location = GetShaderLocation(mat->shader, "metalness.useSampler"); + SetShaderValuei(mat->shader, location, (int [1]){ 0 }, 1); + } break; + case TEXMAP_ROUGHNESS: + { + location = GetShaderLocation(mat->shader, "roughness.useSampler"); + SetShaderValuei(mat->shader, location, (int [1]){ 0 }, 1); + } break; + case TEXMAP_OCCLUSION: + { + location = GetShaderLocation(mat->shader, "occlusion.useSampler"); + SetShaderValuei(mat->shader, location, (int [1]){ 0 }, 1); + } break; + case TEXMAP_EMISSION: + { + location = GetShaderLocation(mat->shader, "emission.useSampler"); + SetShaderValuei(mat->shader, location, (int [1]){ 0 }, 1); + } break; + case TEXMAP_HEIGHT: + { + location = GetShaderLocation(mat->shader, "height.useSampler"); + SetShaderValuei(mat->shader, location, (int [1]){ 0 }, 1); + } break; + } +} + // Draw a model (with texture if set) void DrawModel(Model model, Vector3 position, float scale, Color tint) { @@ -1225,9 +1481,9 @@ void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rota //Matrix matModel = MatrixMultiply(model.transform, matTransform); // Transform to world-space coordinates model.transform = MatrixMultiply(model.transform, matTransform); - model.material.colDiffuse = tint; // TODO: Multiply tint color by diffuse color? + model.material.maps[TEXMAP_DIFFUSE].color = tint; // TODO: Multiply tint color by diffuse color? - rlglDrawMesh(model.mesh, model.material, model.transform); + rlDrawMesh(model.mesh, model.material, model.transform); } // Draw a model wires (with texture if set) @@ -1980,23 +2236,24 @@ static Material LoadMTL(const char *fileName) case 'a': // Ka float float float Ambient color (RGB) { sscanf(buffer, "Ka %f %f %f", &color.x, &color.y, &color.z); - material.colAmbient.r = (unsigned char)(color.x*255); - material.colAmbient.g = (unsigned char)(color.y*255); - material.colAmbient.b = (unsigned char)(color.z*255); + // TODO: Support ambient color + //material.colAmbient.r = (unsigned char)(color.x*255); + //material.colAmbient.g = (unsigned char)(color.y*255); + //material.colAmbient.b = (unsigned char)(color.z*255); } break; case 'd': // Kd float float float Diffuse color (RGB) { sscanf(buffer, "Kd %f %f %f", &color.x, &color.y, &color.z); - material.colDiffuse.r = (unsigned char)(color.x*255); - material.colDiffuse.g = (unsigned char)(color.y*255); - material.colDiffuse.b = (unsigned char)(color.z*255); + material.maps[TEXMAP_DIFFUSE].color.r = (unsigned char)(color.x*255); + material.maps[TEXMAP_DIFFUSE].color.g = (unsigned char)(color.y*255); + material.maps[TEXMAP_DIFFUSE].color.b = (unsigned char)(color.z*255); } break; case 's': // Ks float float float Specular color (RGB) { sscanf(buffer, "Ks %f %f %f", &color.x, &color.y, &color.z); - material.colSpecular.r = (unsigned char)(color.x*255); - material.colSpecular.g = (unsigned char)(color.y*255); - material.colSpecular.b = (unsigned char)(color.z*255); + material.maps[TEXMAP_SPECULAR].color.r = (unsigned char)(color.x*255); + material.maps[TEXMAP_SPECULAR].color.g = (unsigned char)(color.y*255); + material.maps[TEXMAP_SPECULAR].color.b = (unsigned char)(color.z*255); } break; case 'e': // Ke float float float Emmisive color (RGB) { @@ -2012,7 +2269,7 @@ static Material LoadMTL(const char *fileName) int shininess = 0; sscanf(buffer, "Ns %i", &shininess); - material.glossiness = (float)shininess; + //material.params[PARAM_GLOSSINES] = (float)shininess; } else if (buffer[1] == 'i') // Ni int Refraction index. { @@ -2028,12 +2285,12 @@ static Material LoadMTL(const char *fileName) if (buffer[5] == 'd') // map_Kd string Diffuse color texture map. { result = sscanf(buffer, "map_Kd %s", mapFileName); - if (result != EOF) material.texDiffuse = LoadTexture(mapFileName); + if (result != EOF) material.maps[TEXMAP_DIFFUSE].tex = LoadTexture(mapFileName); } else if (buffer[5] == 's') // map_Ks string Specular color texture map. { result = sscanf(buffer, "map_Ks %s", mapFileName); - if (result != EOF) material.texSpecular = LoadTexture(mapFileName); + if (result != EOF) material.maps[TEXMAP_SPECULAR].tex = LoadTexture(mapFileName); } else if (buffer[5] == 'a') // map_Ka string Ambient color texture map. { @@ -2043,12 +2300,12 @@ static Material LoadMTL(const char *fileName) case 'B': // map_Bump string Bump texture map. { result = sscanf(buffer, "map_Bump %s", mapFileName); - if (result != EOF) material.texNormal = LoadTexture(mapFileName); + if (result != EOF) material.maps[TEXMAP_NORMAL].tex = LoadTexture(mapFileName); } break; case 'b': // map_bump string Bump texture map. { result = sscanf(buffer, "map_bump %s", mapFileName); - if (result != EOF) material.texNormal = LoadTexture(mapFileName); + if (result != EOF) material.maps[TEXMAP_NORMAL].tex = LoadTexture(mapFileName); } break; case 'd': // map_d string Opacity texture map. { @@ -2063,7 +2320,7 @@ static Material LoadMTL(const char *fileName) { float alpha = 1.0f; sscanf(buffer, "d %f", &alpha); - material.colDiffuse.a = (unsigned char)(alpha*255); + material.maps[TEXMAP_DIFFUSE].color.a = (unsigned char)(alpha*255); } else if (buffer[1] == 'i') // disp string Displacement map { @@ -2073,13 +2330,13 @@ static Material LoadMTL(const char *fileName) case 'b': // bump string Bump texture map { result = sscanf(buffer, "bump %s", mapFileName); - if (result != EOF) material.texNormal = LoadTexture(mapFileName); + if (result != EOF) material.maps[TEXMAP_NORMAL].tex = LoadTexture(mapFileName); } break; case 'T': // Tr float Transparency Tr (alpha). Tr is inverse of d { float ialpha = 0.0f; sscanf(buffer, "Tr %f", &ialpha); - material.colDiffuse.a = (unsigned char)((1.0f - ialpha)*255); + material.maps[TEXMAP_DIFFUSE].color.a = (unsigned char)((1.0f - ialpha)*255); } break; case 'r': // refl string Reflection texture map diff --git a/src/raylib.h b/src/raylib.h index 04aa3b5a..c84d6ce4 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -291,6 +291,11 @@ #define MAGENTA CLITERAL{ 255, 0, 255, 255 } // Magenta #define RAYWHITE CLITERAL{ 245, 245, 245, 255 } // My own White (raylib logo) +// Shader and material limits +#define MAX_SHADER_LOCATIONS 32 +#define MAX_MATERIAL_TEXTURE_MAPS 12 +#define MAX_MATERIAL_PARAMS 8 + //---------------------------------------------------------------------------------- // Structures Definition //---------------------------------------------------------------------------------- @@ -420,43 +425,24 @@ typedef struct Mesh { unsigned int vboId[7]; // OpenGL Vertex Buffer Objects id (7 types of vertex data) } Mesh; -// Shader type (generic shader) +// Shader type (generic) typedef struct Shader { unsigned int id; // Shader program id - - // Vertex attributes locations (default locations) - int vertexLoc; // Vertex attribute location point (default-location = 0) - int texcoordLoc; // Texcoord attribute location point (default-location = 1) - int texcoord2Loc; // Texcoord2 attribute location point (default-location = 5) - int normalLoc; // Normal attribute location point (default-location = 2) - int tangentLoc; // Tangent attribute location point (default-location = 4) - int colorLoc; // Color attibute location point (default-location = 3) - - // Uniform locations - int mvpLoc; // ModelView-Projection matrix uniform location point (vertex shader) - int colDiffuseLoc; // Diffuse color uniform location point (fragment shader) - int colAmbientLoc; // Ambient color uniform location point (fragment shader) - int colSpecularLoc; // Specular color uniform location point (fragment shader) - - // Texture map locations (generic for any kind of map) - int mapTexture0Loc; // Map texture uniform location point (default-texture-unit = 0) - int mapTexture1Loc; // Map texture uniform location point (default-texture-unit = 1) - int mapTexture2Loc; // Map texture uniform location point (default-texture-unit = 2) + int locs[MAX_SHADER_LOCATIONS]; // Initialized on LoadShader(), set to MAX_SHADER_LOCATIONS } Shader; -// Material type -typedef struct Material { - Shader shader; // Standard shader (supports 3 map textures) - - Texture2D texDiffuse; // Diffuse texture (binded to shader mapTexture0Loc) - Texture2D texNormal; // Normal texture (binded to shader mapTexture1Loc) - Texture2D texSpecular; // Specular texture (binded to shader mapTexture2Loc) +// Material texture map +typedef struct TextureMap { + Texture2D tex; + Color color; + float value; +} TextureMap; - Color colDiffuse; // Diffuse color - Color colAmbient; // Ambient color - Color colSpecular; // Specular color - - float glossiness; // Glossiness level (Ranges from 0 to 1000) +// Material type (generic) +typedef struct Material { + Shader shader; + TextureMap maps[MAX_MATERIAL_TEXTURE_MAPS]; // Initialized on LoadMaterial*(), set to MAX_MATERIAL_TEXTURE_MAPS + float *params; // Initialized on LoadMaterial*(), set to MAX_MATERIAL_PARAMS } Material; // Model type @@ -540,6 +526,54 @@ typedef enum { LOG_OTHER } LogType; +typedef enum { + LOC_VERTEX_POSITION = 0, + LOC_VERTEX_TEXCOORD01, + LOC_VERTEX_TEXCOORD02, + LOC_VERTEX_NORMAL, + LOC_VERTEX_TANGENT, + LOC_VERTEX_COLOR, + LOC_MATRIX_MVP, + LOC_MATRIX_MODEL, + LOC_MATRIX_VIEW, + LOC_MATRIX_PROJECTION, + LOC_VECTOR_VIEW, + LOC_COLOR_DIFFUSE, + LOC_COLOR_SPECULAR, + LOC_COLOR_AMBIENT, + LOC_TEXMAP_ALBEDO, // LOC_TEXMAP_DIFFUSE + LOC_TEXMAP_METALNESS, // LOC_TEXMAP_SPECULAR + LOC_TEXMAP_NORMAL, + LOC_TEXMAP_ROUGHNESS, + LOC_TEXMAP_OCCUSION, + LOC_TEXMAP_EMISSION, + LOC_TEXMAP_HEIGHT, + LOC_TEXMAP_CUBEMAP, + LOC_TEXMAP_IRRADIANCE, + LOC_TEXMAP_PREFILTER, + LOC_TEXMAP_BRDF +} ShaderLocationIndex; + +#define LOC_TEXMAP_DIFFUSE LOC_TEXMAP_ALBEDO +#define LOC_TEXMAP_SPECULAR LOC_TEXMAP_METALNESS + +typedef enum { + TEXMAP_ALBEDO = 0, // TEXMAP_DIFFUSE + TEXMAP_METALNESS = 1, // TEXMAP_SPECULAR + TEXMAP_NORMAL = 2, + TEXMAP_ROUGHNESS = 3, + TEXMAP_OCCLUSION, + TEXMAP_EMISSION, + TEXMAP_HEIGHT, + TEXMAP_CUBEMAP, // NOTE: Uses GL_TEXTURE_CUBE_MAP + TEXMAP_IRRADIANCE, // NOTE: Uses GL_TEXTURE_CUBE_MAP + TEXMAP_PREFILTER, // NOTE: Uses GL_TEXTURE_CUBE_MAP + TEXMAP_BRDF +} TexmapIndex; + +#define TEXMAP_DIFFUSE TEXMAP_ALBEDO +#define TEXMAP_SPECULAR TEXMAP_METALNESS + // Texture formats // NOTE: Support depends on OpenGL version and platform typedef enum { @@ -944,19 +978,26 @@ RLAPI void DrawGizmo(Vector3 position); //------------------------------------------------------------------------------------ // Model loading/unloading functions +RLAPI Model LoadModel(const char *fileName); // Load model from files (mesh and material) +RLAPI Model LoadModelFromMesh(Mesh mesh, bool dynamic); // Load model from generated mesh +RLAPI void UnloadModel(Model model); // Unload model from memory (RAM and/or VRAM) + +// Mesh loading/unloading functions RLAPI Mesh LoadMesh(const char *fileName); // Load mesh from file -RLAPI Mesh LoadMeshEx(int numVertex, float *vData, float *vtData, float *vnData, Color *cData); // Load mesh from vertex data -RLAPI Model LoadModel(const char *fileName); // Load model from file -RLAPI Model LoadModelFromMesh(Mesh data, bool dynamic); // Load model from mesh data -RLAPI Model LoadHeightmap(Image heightmap, Vector3 size); // Load heightmap model from image data -RLAPI Model LoadCubicmap(Image cubicmap); // Load cubes-based map model from image data +//RLAPI void UpdateMesh(Mesh *mesh, int type, void *data); // Update mesh data (CPU and GPU) RLAPI void UnloadMesh(Mesh *mesh); // Unload mesh from memory (RAM and/or VRAM) -RLAPI void UnloadModel(Model model); // Unload model from memory (RAM and/or VRAM) + +RLAPI Mesh GenMeshCube(float width, float height, float length); // Generate cuboid mesh +RLAPI Mesh GenMeshHeightmap(Image heightmap, Vector3 size); // Generate heightmap mesh from image data +RLAPI Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize); // Generate cubes-based map mesh from image data // Material loading/unloading functions RLAPI Material LoadMaterial(const char *fileName); // Load material from file -RLAPI Material LoadDefaultMaterial(void); // Load default material (uses default models shader) +RLAPI Material LoadMaterialDefault(void); // Load default material (Supports: DIFFUSE, SPECULAR, NORMAL maps) +RLAPI Material LoadMaterialPBR(Texture2D cubemap, Color albedo, float metalness, float roughness); // Load PBR material (Supports: ALBEDO, NORMAL, METALNESS, ROUGHNESS...) RLAPI void UnloadMaterial(Material material); // Unload material from GPU memory (VRAM) +RLAPI void SetMaterialTexture(Material *mat, int texmapType, Texture2D texture); // Set material texture +RLAPI void UnsetMaterialTexture(Material *mat, int texmapType); // Unset texture from material and unload it from GPU // Model drawing functions RLAPI void DrawModel(Model model, Vector3 position, float scale, Color tint); // Draw a model (with texture if set) @@ -993,8 +1034,10 @@ RLAPI char *LoadText(const char *fileName); // Loa RLAPI Shader LoadShader(char *vsFileName, char *fsFileName); // Load shader from files and bind default locations RLAPI void UnloadShader(Shader shader); // Unload shader from GPU memory (VRAM) -RLAPI Shader GetDefaultShader(void); // Get default shader -RLAPI Texture2D GetDefaultTexture(void); // Get default texture +RLAPI Shader GetShaderDefault(void); // Get default shader +RLAPI Texture2D GetTextureDefault(void); // Get default texture + +RLAPI Texture2D rlGenMapCubemap(Texture2D skyHDR, int size); // Generate cubemap texture map from HDR texture // Shader configuration functions RLAPI int GetShaderLocation(Shader shader, const char *uniformName); // Get shader uniform location diff --git a/src/rlgl.c b/src/rlgl.c index e3576c30..7f349347 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -333,18 +333,21 @@ static int screenHeight; // Default framebuffer height // Module specific Functions Declaration //---------------------------------------------------------------------------------- #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 void LoadTextureCompressed(unsigned char *data, int width, int height, int compressedFormat, int mipmapCount); static unsigned int LoadShaderProgram(const char *vShaderStr, const char *fShaderStr); // Load custom shader strings and return program id -static Shader LoadDefaultShader(void); // Load default shader (just vertex positioning and texture coloring) -static void LoadDefaultShaderLocations(Shader *shader); // Bind default shader locations (attributes and uniforms) -static void UnloadDefaultShader(void); // Unload default shader +static Shader LoadShaderDefault(void); // Load default shader (just vertex positioning and texture coloring) +static void SetShaderDefaultLocations(Shader *shader); // Bind default shader locations (attributes and uniforms) +static void UnLoadShaderDefault(void); // Unload default shader static void LoadDefaultBuffers(void); // Load default internal buffers (lines, triangles, quads) static void UpdateDefaultBuffers(void); // Update default internal buffers (VAOs/VBOs) with vertex data static void DrawDefaultBuffers(void); // Draw default internal buffers vertex data static void UnloadDefaultBuffers(void); // Unload default internal buffers vertex data from CPU and GPU +static void RenderCube(void); +static void RenderQuad(void); + #if defined(SUPPORT_VR_SIMULATOR) static void SetStereoConfig(VrDeviceInfo info); // Configure stereo rendering (including distortion shader) with HMD device parameters static void SetStereoView(int eye, Matrix matProjection, Matrix matModelView); // Set internal projection and modelview matrix depending on eye @@ -923,16 +926,16 @@ void rlDisableWireMode(void) // Unload texture from GPU memory void rlDeleteTextures(unsigned int id) { - if (id != 0) glDeleteTextures(1, &id); + if (id > 0) glDeleteTextures(1, &id); } // Unload render texture from GPU memory void rlDeleteRenderTextures(RenderTexture2D target) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - if (target.id != 0) glDeleteFramebuffers(1, &target.id); - if (target.texture.id != 0) glDeleteTextures(1, &target.texture.id); - if (target.depth.id != 0) glDeleteTextures(1, &target.depth.id); + if (target.id > 0) glDeleteFramebuffers(1, &target.id); + if (target.texture.id > 0) glDeleteTextures(1, &target.texture.id); + if (target.depth.id > 0) glDeleteTextures(1, &target.depth.id); TraceLog(LOG_INFO, "[FBO ID %i] Unloaded render texture data from VRAM (GPU)", target.id); #endif @@ -1003,6 +1006,29 @@ int rlGetVersion(void) #endif } +// Get world coordinates from screen coordinates +Vector3 rlUnproject(Vector3 source, Matrix proj, Matrix view) +{ + Vector3 result = { 0.0f, 0.0f, 0.0f }; + + // Calculate unproject matrix (multiply projection matrix and view matrix) and invert it + Matrix matProjView = MatrixMultiply(proj, view); + MatrixInvert(&matProjView); + + // Create quaternion from source point + Quaternion quat = { source.x, source.y, source.z, 1.0f }; + + // Multiply quat point by unproject matrix + QuaternionTransform(&quat, matProjView); + + // Normalized world points in vectors + result.x = quat.x/quat.w; + result.y = quat.y/quat.w; + result.z = quat.z/quat.w; + + return result; +} + //---------------------------------------------------------------------------------- // Module Functions Definition - rlgl Functions //---------------------------------------------------------------------------------- @@ -1183,13 +1209,13 @@ void rlglInit(int width, int height) // Init default white texture unsigned char pixels[4] = { 255, 255, 255, 255 }; // 1 pixel RGBA (4 bytes) - whiteTexture = rlglLoadTexture(pixels, 1, 1, UNCOMPRESSED_R8G8B8A8, 1); + whiteTexture = rlLoadTexture(pixels, 1, 1, UNCOMPRESSED_R8G8B8A8, 1); if (whiteTexture != 0) TraceLog(LOG_INFO, "[TEX ID %i] Base white texture loaded successfully", whiteTexture); else TraceLog(LOG_WARNING, "Base white texture could not be loaded"); // Init default Shader (customized for GL 3.3 and ES2) - defaultShader = LoadDefaultShader(); + defaultShader = LoadShaderDefault(); currentShader = defaultShader; // Init default vertex arrays buffers (lines, triangles, quads) @@ -1261,7 +1287,7 @@ void rlglInit(int width, int height) void rlglClose(void) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - UnloadDefaultShader(); + UnloadShaderDefault(); UnloadDefaultBuffers(); // Delete default white texture @@ -1277,7 +1303,7 @@ void rlglDraw(void) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) // NOTE: In a future version, models could be stored in a stack... - //for (int i = 0; i < modelsCount; i++) rlglDrawMesh(models[i]->mesh, models[i]->material, models[i]->transform); + //for (int i = 0; i < modelsCount; i++) rlDrawMesh(models[i]->mesh, models[i]->material, models[i]->transform); // NOTE: Default buffers upload and draw UpdateDefaultBuffers(); @@ -1308,31 +1334,8 @@ void rlglLoadExtensions(void *loader) #endif } -// Get world coordinates from screen coordinates -Vector3 rlglUnproject(Vector3 source, Matrix proj, Matrix view) -{ - Vector3 result = { 0.0f, 0.0f, 0.0f }; - - // Calculate unproject matrix (multiply projection matrix and view matrix) and invert it - Matrix matProjView = MatrixMultiply(proj, view); - MatrixInvert(&matProjView); - - // Create quaternion from source point - Quaternion quat = { source.x, source.y, source.z, 1.0f }; - - // Multiply quat point by unproject matrix - QuaternionTransform(&quat, matProjView); - - // Normalized world points in vectors - result.x = quat.x/quat.w; - result.y = quat.y/quat.w; - result.z = quat.z/quat.w; - - return result; -} - // Convert image data to OpenGL texture (returns OpenGL valid Id) -unsigned int rlglLoadTexture(void *data, int width, int height, int format, int mipmapCount) +unsigned int rlLoadTexture(void *data, int width, int height, int format, int mipmapCount) { glBindTexture(GL_TEXTURE_2D, 0); // Free any old binding @@ -1427,17 +1430,17 @@ unsigned int rlglLoadTexture(void *data, int width, int height, int format, int case UNCOMPRESSED_R4G4B4A4: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA4, width, height, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, (unsigned short *)data); break; case UNCOMPRESSED_R8G8B8A8: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (unsigned char *)data); break; case UNCOMPRESSED_R32G32B32: if (texFloatSupported) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, width, height, 0, GL_RGB, GL_FLOAT, (float *)data); break; - case COMPRESSED_DXT1_RGB: if (texCompDXTSupported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGB_S3TC_DXT1_EXT); break; - case COMPRESSED_DXT1_RGBA: if (texCompDXTSupported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT); break; - case COMPRESSED_DXT3_RGBA: if (texCompDXTSupported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT); break; - case COMPRESSED_DXT5_RGBA: if (texCompDXTSupported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT); break; - case COMPRESSED_ETC1_RGB: if (texCompETC1Supported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_ETC1_RGB8_OES); break; // NOTE: Requires OpenGL ES 2.0 or OpenGL 4.3 - case COMPRESSED_ETC2_RGB: if (texCompETC2Supported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGB8_ETC2); break; // NOTE: Requires OpenGL ES 3.0 or OpenGL 4.3 - case COMPRESSED_ETC2_EAC_RGBA: if (texCompETC2Supported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA8_ETC2_EAC); break; // NOTE: Requires OpenGL ES 3.0 or OpenGL 4.3 - case COMPRESSED_PVRT_RGB: if (texCompPVRTSupported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG); break; // NOTE: Requires PowerVR GPU - case COMPRESSED_PVRT_RGBA: if (texCompPVRTSupported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG); break; // NOTE: Requires PowerVR GPU - case COMPRESSED_ASTC_4x4_RGBA: if (texCompASTCSupported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA_ASTC_4x4_KHR); break; // NOTE: Requires OpenGL ES 3.1 or OpenGL 4.3 - case COMPRESSED_ASTC_8x8_RGBA: if (texCompASTCSupported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA_ASTC_8x8_KHR); break; // NOTE: Requires OpenGL ES 3.1 or OpenGL 4.3 + case COMPRESSED_DXT1_RGB: if (texCompDXTSupported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, mipmapCount); break; + case COMPRESSED_DXT1_RGBA: if (texCompDXTSupported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, mipmapCount); break; + case COMPRESSED_DXT3_RGBA: if (texCompDXTSupported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, mipmapCount); break; + case COMPRESSED_DXT5_RGBA: if (texCompDXTSupported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, mipmapCount); break; + case COMPRESSED_ETC1_RGB: if (texCompETC1Supported) LoadTextureCompressed((unsigned char *)data, width, height, GL_ETC1_RGB8_OES, mipmapCount); break; // NOTE: Requires OpenGL ES 2.0 or OpenGL 4.3 + case COMPRESSED_ETC2_RGB: if (texCompETC2Supported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGB8_ETC2, mipmapCount); break; // NOTE: Requires OpenGL ES 3.0 or OpenGL 4.3 + case COMPRESSED_ETC2_EAC_RGBA: if (texCompETC2Supported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGBA8_ETC2_EAC, mipmapCount); break; // NOTE: Requires OpenGL ES 3.0 or OpenGL 4.3 + case COMPRESSED_PVRT_RGB: if (texCompPVRTSupported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG, mipmapCount); break; // NOTE: Requires PowerVR GPU + case COMPRESSED_PVRT_RGBA: if (texCompPVRTSupported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG, mipmapCount); break; // NOTE: Requires PowerVR GPU + case COMPRESSED_ASTC_4x4_RGBA: if (texCompASTCSupported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGBA_ASTC_4x4_KHR, mipmapCount); break; // NOTE: Requires OpenGL ES 3.1 or OpenGL 4.3 + case COMPRESSED_ASTC_8x8_RGBA: if (texCompASTCSupported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGBA_ASTC_8x8_KHR, mipmapCount); break; // NOTE: Requires OpenGL ES 3.1 or OpenGL 4.3 default: TraceLog(LOG_WARNING, "Texture format not recognized"); break; } #elif defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_ES2) @@ -1452,18 +1455,18 @@ unsigned int rlglLoadTexture(void *data, int width, int height, int format, int case UNCOMPRESSED_R4G4B4A4: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, (unsigned short *)data); break; case UNCOMPRESSED_R8G8B8A8: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (unsigned char *)data); break; #if defined(GRAPHICS_API_OPENGL_ES2) - case UNCOMPRESSED_R32G32B32: if (texFloatSupported) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_FLOAT, (float *)data); break; // Requries extension OES_texture_float - case COMPRESSED_DXT1_RGB: if (texCompDXTSupported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGB_S3TC_DXT1_EXT); break; - case COMPRESSED_DXT1_RGBA: if (texCompDXTSupported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT); break; - case COMPRESSED_DXT3_RGBA: if (texCompDXTSupported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT); break; // NOTE: Not supported by WebGL - case COMPRESSED_DXT5_RGBA: if (texCompDXTSupported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT); break; // NOTE: Not supported by WebGL - case COMPRESSED_ETC1_RGB: if (texCompETC1Supported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_ETC1_RGB8_OES); break; // NOTE: Requires OpenGL ES 2.0 or OpenGL 4.3 - case COMPRESSED_ETC2_RGB: if (texCompETC2Supported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGB8_ETC2); break; // NOTE: Requires OpenGL ES 3.0 or OpenGL 4.3 - case COMPRESSED_ETC2_EAC_RGBA: if (texCompETC2Supported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA8_ETC2_EAC); break; // NOTE: Requires OpenGL ES 3.0 or OpenGL 4.3 - case COMPRESSED_PVRT_RGB: if (texCompPVRTSupported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG); break; // NOTE: Requires PowerVR GPU - case COMPRESSED_PVRT_RGBA: if (texCompPVRTSupported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG); break; // NOTE: Requires PowerVR GPU - case COMPRESSED_ASTC_4x4_RGBA: if (texCompASTCSupported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA_ASTC_4x4_KHR); break; // NOTE: Requires OpenGL ES 3.1 or OpenGL 4.3 - case COMPRESSED_ASTC_8x8_RGBA: if (texCompASTCSupported) LoadCompressedTexture((unsigned char *)data, width, height, mipmapCount, GL_COMPRESSED_RGBA_ASTC_8x8_KHR); break; // NOTE: Requires OpenGL ES 3.1 or OpenGL 4.3 + case UNCOMPRESSED_R32G32B32: if (texFloatSupported) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_FLOAT, (float *)data); break; // NOTE: Requires extension OES_texture_float + case COMPRESSED_DXT1_RGB: if (texCompDXTSupported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, mipmapCount); break; + case COMPRESSED_DXT1_RGBA: if (texCompDXTSupported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, mipmapCount); break; + case COMPRESSED_DXT3_RGBA: if (texCompDXTSupported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, mipmapCount); break; // NOTE: Not supported by WebGL + case COMPRESSED_DXT5_RGBA: if (texCompDXTSupported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, mipmapCount); break; // NOTE: Not supported by WebGL + case COMPRESSED_ETC1_RGB: if (texCompETC1Supported) LoadTextureCompressed((unsigned char *)data, width, height, GL_ETC1_RGB8_OES, mipmapCount); break; // NOTE: Requires OpenGL ES 2.0 or OpenGL 4.3 + case COMPRESSED_ETC2_RGB: if (texCompETC2Supported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGB8_ETC2, mipmapCount); break; // NOTE: Requires OpenGL ES 3.0 or OpenGL 4.3 + case COMPRESSED_ETC2_EAC_RGBA: if (texCompETC2Supported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGBA8_ETC2_EAC, mipmapCount); break; // NOTE: Requires OpenGL ES 3.0 or OpenGL 4.3 + case COMPRESSED_PVRT_RGB: if (texCompPVRTSupported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG, mipmapCount); break; // NOTE: Requires PowerVR GPU + case COMPRESSED_PVRT_RGBA: if (texCompPVRTSupported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG, mipmapCount); break; // NOTE: Requires PowerVR GPU + case COMPRESSED_ASTC_4x4_RGBA: if (texCompASTCSupported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGBA_ASTC_4x4_KHR, mipmapCount); break; // NOTE: Requires OpenGL ES 3.1 or OpenGL 4.3 + case COMPRESSED_ASTC_8x8_RGBA: if (texCompASTCSupported) LoadTextureCompressed((unsigned char *)data, width, height, GL_COMPRESSED_RGBA_ASTC_8x8_KHR, mipmapCount); break; // NOTE: Requires OpenGL ES 3.1 or OpenGL 4.3 #endif default: TraceLog(LOG_WARNING, "Texture format not supported"); break; } @@ -1514,8 +1517,48 @@ unsigned int rlglLoadTexture(void *data, int width, int height, int format, int return id; } +// Update already loaded texture in GPU with new data +void rlUpdateTexture(unsigned int id, int width, int height, int format, const void *data) +{ + glBindTexture(GL_TEXTURE_2D, id); + +#if defined(GRAPHICS_API_OPENGL_33) + switch (format) + { + case UNCOMPRESSED_GRAYSCALE: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RED, GL_UNSIGNED_BYTE, (unsigned char *)data); break; + case UNCOMPRESSED_GRAY_ALPHA: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RG, GL_UNSIGNED_BYTE, (unsigned char *)data); break; + case UNCOMPRESSED_R5G6B5: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, (unsigned short *)data); break; + case UNCOMPRESSED_R8G8B8: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, (unsigned char *)data); break; + case UNCOMPRESSED_R5G5B5A1: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, (unsigned short *)data); break; + case UNCOMPRESSED_R4G4B4A4: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, (unsigned short *)data); break; + case UNCOMPRESSED_R8G8B8A8: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, (unsigned char *)data); break; + default: TraceLog(WARNING, "Texture format updating not supported"); break; + } +#elif defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_ES2) + // NOTE: on OpenGL ES 2.0 (WebGL), internalFormat must match format and options allowed are: GL_LUMINANCE, GL_RGB, GL_RGBA + switch (format) + { + case UNCOMPRESSED_GRAYSCALE: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_LUMINANCE, GL_UNSIGNED_BYTE, (unsigned char *)data); break; + case UNCOMPRESSED_GRAY_ALPHA: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, (unsigned char *)data); break; + case UNCOMPRESSED_R5G6B5: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, (unsigned short *)data); break; + case UNCOMPRESSED_R8G8B8: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, (unsigned char *)data); break; + case UNCOMPRESSED_R5G5B5A1: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, (unsigned short *)data); break; + case UNCOMPRESSED_R4G4B4A4: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, (unsigned short *)data); break; + case UNCOMPRESSED_R8G8B8A8: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, (unsigned char *)data); break; + default: TraceLog(WARNING, "Texture format updating not supported"); break; + } +#endif +} + +// Unload texture from GPU memory +void rlUnloadTexture(unsigned int id) +{ + if (id > 0) glDeleteTextures(1, &id); +} + + // Load a texture to be used for rendering (fbo with color and depth attachments) -RenderTexture2D rlglLoadRenderTexture(int width, int height) +RenderTexture2D rlLoadRenderTexture(int width, int height) { RenderTexture2D target; @@ -1609,41 +1652,8 @@ RenderTexture2D rlglLoadRenderTexture(int width, int height) return target; } -// Update already loaded texture in GPU with new data -void rlglUpdateTexture(unsigned int id, int width, int height, int format, const void *data) -{ - glBindTexture(GL_TEXTURE_2D, id); - -#if defined(GRAPHICS_API_OPENGL_33) - switch (format) - { - case UNCOMPRESSED_GRAYSCALE: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RED, GL_UNSIGNED_BYTE, (unsigned char *)data); break; - case UNCOMPRESSED_GRAY_ALPHA: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RG, GL_UNSIGNED_BYTE, (unsigned char *)data); break; - case UNCOMPRESSED_R5G6B5: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, (unsigned short *)data); break; - case UNCOMPRESSED_R8G8B8: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, (unsigned char *)data); break; - case UNCOMPRESSED_R5G5B5A1: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, (unsigned short *)data); break; - case UNCOMPRESSED_R4G4B4A4: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, (unsigned short *)data); break; - case UNCOMPRESSED_R8G8B8A8: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, (unsigned char *)data); break; - default: TraceLog(LOG_WARNING, "Texture format updating not supported"); break; - } -#elif defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_ES2) - // NOTE: on OpenGL ES 2.0 (WebGL), internalFormat must match format and options allowed are: GL_LUMINANCE, GL_RGB, GL_RGBA - switch (format) - { - case UNCOMPRESSED_GRAYSCALE: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_LUMINANCE, GL_UNSIGNED_BYTE, (unsigned char *)data); break; - case UNCOMPRESSED_GRAY_ALPHA: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, (unsigned char *)data); break; - case UNCOMPRESSED_R5G6B5: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, (unsigned short *)data); break; - case UNCOMPRESSED_R8G8B8: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, (unsigned char *)data); break; - case UNCOMPRESSED_R5G5B5A1: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, (unsigned short *)data); break; - case UNCOMPRESSED_R4G4B4A4: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, (unsigned short *)data); break; - case UNCOMPRESSED_R8G8B8A8: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, (unsigned char *)data); break; - default: TraceLog(LOG_WARNING, "Texture format updating not supported"); break; - } -#endif -} - // Generate mipmap data for selected texture -void rlglGenerateMipmaps(Texture2D *texture) +void rlGenerateMipmaps(Texture2D *texture) { glBindTexture(GL_TEXTURE_2D, texture->id); @@ -1657,7 +1667,7 @@ void rlglGenerateMipmaps(Texture2D *texture) { #if defined(GRAPHICS_API_OPENGL_11) // Compute required mipmaps - void *data = rlglReadTexturePixels(*texture); + void *data = rlReadTexturePixels(*texture); // NOTE: data size is reallocated to fit mipmaps data // NOTE: CPU mipmap generation only supports RGBA 32bit data @@ -1708,8 +1718,425 @@ void rlglGenerateMipmaps(Texture2D *texture) glBindTexture(GL_TEXTURE_2D, 0); } +// Generated cubemap texture +Texture2D rlGenMapCubemap(Texture2D skyHDR, int size) +{ + Texture2D cubemap = { 0 }; + + #define PATH_CUBEMAP_VS "resources/shaders/cubemap.vs" // Path to equirectangular to cubemap vertex shader + #define PATH_CUBEMAP_FS "resources/shaders/cubemap.fs" // Path to equirectangular to cubemap fragment shader + + Shader shader = LoadShader(PATH_CUBEMAP_VS, PATH_CUBEMAP_FS); + + // Get cubemap shader locations + int projectionLoc = GetShaderLocation(shader, "projection"); + int viewLoc = GetShaderLocation(shader, "view"); + int texmapLoc = GetShaderLocation(shader, "equirectangularMap"); + + SetShaderValuei(shader, texmapLoc, (int[1]){ 0 }, 1); // Set default active texture to 0 + + // Set up depth face culling and cubemap seamless + glDisable(GL_CULL_FACE); + glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); + + // Setup framebuffer + unsigned int fbo, rbo; + glGenFramebuffers(1, &fbo); + glGenRenderbuffers(1, &rbo); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glBindRenderbuffer(GL_RENDERBUFFER, rbo); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, size, size); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbo); + + // Set up cubemap to render and attach to framebuffer + // NOTE: faces are stored with 16 bit floating point values + glGenTextures(1, &cubemap.id); + glBindTexture(GL_TEXTURE_CUBE_MAP, cubemap.id); + for (unsigned int i = 0; i < 6; i++) + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB16F, size, size, 0, GL_RGB, GL_FLOAT, NULL); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + // Create projection (transposed) and different views for each face + Matrix fboProjection = MatrixPerspective(90.0, 1.0, 0.01, 1000.0); + MatrixTranspose(&fboProjection); + Matrix fboViews[6] = { + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 1.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ -1.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, 1.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, 1.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, -1.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, 1.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, -1.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }) + }; + + // Convert HDR equirectangular environment map to cubemap equivalent + glUseProgram(shader.id); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, skyHDR.id); + SetShaderValueMatrix(shader, projectionLoc, fboProjection); + + // Note: don't forget to configure the viewport to the capture dimensions + glViewport(0, 0, size, size); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + + for (unsigned int i = 0; i < 6; i++) + { + SetShaderValueMatrix(shader, viewLoc, fboViews[i]); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, cubemap.id, 0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + RenderCube(); + } + + // Unbind framebuffer and textures + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + UnloadShader(shader); + + cubemap.width = size; + cubemap.height = size; + + // Reset viewport dimensions to default + glViewport(0, 0, GetScreenWidth(), GetScreenHeight()); + //glEnable(GL_CULL_FACE); + + return cubemap; +} + +Texture2D rlGenMapIrradiance(Texture2D cubemap, int size) +{ + Texture2D irradiance = { 0 }; + + #define PATH_SKYBOX_VS "resources/shaders/skybox.vs" // Path to skybox vertex shader + #define PATH_IRRADIANCE_FS "resources/shaders/irradiance.fs" // Path to irradiance (GI) calculation fragment shader + + Shader shader = LoadShader(PATH_SKYBOX_VS, PATH_IRRADIANCE_FS); + + // Get irradiance shader locations + int projectionLoc = GetShaderLocation(shader, "projection"); + int viewLoc = GetShaderLocation(shader, "view"); + int texmapLoc = GetShaderLocation(shader, "environmentMap"); + + // Set up shaders constant values + SetShaderValuei(shader, texmapLoc, (int[1]){ 0 }, 1); + + // Setup framebuffer + unsigned int fbo, rbo; + glGenFramebuffers(1, &fbo); + glGenRenderbuffers(1, &rbo); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glBindRenderbuffer(GL_RENDERBUFFER, rbo); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, size, size); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbo); + + // Create an irradiance cubemap, and re-scale capture FBO to irradiance scale + glGenTextures(1, &irradiance.id); + glBindTexture(GL_TEXTURE_CUBE_MAP, irradiance.id); + for (unsigned int i = 0; i < 6; i++) + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB16F, size, size, 0, GL_RGB, GL_FLOAT, NULL); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + // Create projection (transposed) and different views for each face + Matrix fboProjection = MatrixPerspective(90.0, 1.0, 0.01, 1000.0); + MatrixTranspose(&fboProjection); + Matrix fboViews[6] = { + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 1.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ -1.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, 1.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, 1.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, -1.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, 1.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, -1.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }) + }; + + // Solve diffuse integral by convolution to create an irradiance cubemap + glUseProgram(shader.id); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_CUBE_MAP, cubemap.id); + SetShaderValueMatrix(shader, projectionLoc, fboProjection); + + // Note: don't forget to configure the viewport to the capture dimensions + glViewport(0, 0, size, size); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + + for (unsigned int i = 0; i < 6; i++) + { + SetShaderValueMatrix(shader, viewLoc, fboViews[i]); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, irradiance.id, 0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + RenderCube(); + } + + // Unbind framebuffer and textures + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + UnloadShader(shader); + + irradiance.width = size; + irradiance.height = size; + + return irradiance; +} + +Texture2D rlGenMapPrefilter(Texture2D cubemap, int size) +{ + Texture2D prefilter = { 0 }; + + #define PATH_SKYBOX_VS "resources/shaders/skybox.vs" // Path to skybox vertex shader + #define PATH_PREFILTER_FS "resources/shaders/prefilter.fs" // Path to reflection prefilter calculation fragment shader + + Shader shader = LoadShader(PATH_SKYBOX_VS, PATH_PREFILTER_FS); + + // Get prefilter shader locations + int projectionLoc = GetShaderLocation(shader, "projection"); + int viewLoc = GetShaderLocation(shader, "view"); + int roughnessLoc = GetShaderLocation(shader, "roughness"); + int texmapLoc = GetShaderLocation(shader, "environmentMap"); + + SetShaderValuei(shader, texmapLoc, (int[1]){ 0 }, 1); + + // Setup framebuffer + unsigned int fbo, rbo; + glGenFramebuffers(1, &fbo); + glGenRenderbuffers(1, &rbo); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glBindRenderbuffer(GL_RENDERBUFFER, rbo); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, size, size); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbo); + + // Create a prefiltered HDR environment map + glGenTextures(1, &prefilter.id); + glBindTexture(GL_TEXTURE_CUBE_MAP, prefilter.id); + for (unsigned int i = 0; i < 6; i++) + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB16F, size, size, 0, GL_RGB, GL_FLOAT, NULL); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + // Generate mipmaps for the prefiltered HDR texture + glGenerateMipmap(GL_TEXTURE_CUBE_MAP); + + // Create projection (transposed) and different views for each face + Matrix fboProjection = MatrixPerspective(90.0, 1.0, 0.01, 1000.0); + MatrixTranspose(&fboProjection); + Matrix fboViews[6] = { + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 1.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ -1.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, 1.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, 1.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, -1.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, 1.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, -1.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }) + }; + + // Prefilter HDR and store data into mipmap levels + glUseProgram(shader.id); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_CUBE_MAP, cubemap.id); + SetShaderValueMatrix(shader, projectionLoc, fboProjection); + + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + + #define MAX_MIPMAP_LEVELS 5 // Max number of prefilter texture mipmaps + + for (unsigned int mip = 0; mip < MAX_MIPMAP_LEVELS; mip++) + { + // Resize framebuffer according to mip-level size. + unsigned int mipWidth = size*powf(0.5f, mip); + unsigned int mipHeight = size*powf(0.5f, mip); + + glBindRenderbuffer(GL_RENDERBUFFER, rbo); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, mipWidth, mipHeight); + glViewport(0, 0, mipWidth, mipHeight); + + float roughness = (float)mip/(float)(MAX_MIPMAP_LEVELS - 1); + glUniform1f(roughnessLoc, roughness); + + for (unsigned int i = 0; i < 6; ++i) + { + SetShaderValueMatrix(shader, viewLoc, fboViews[i]); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, prefilter.id, mip); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + RenderCube(); + } + } + + // Unbind framebuffer and textures + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + UnloadShader(shader); + + prefilter.width = size; + prefilter.height = size; + + return prefilter; +} + +Texture2D rlGenMapBRDF(Texture2D cubemap, int size) +{ + Texture2D brdf = { 0 }; + + #define PATH_BRDF_VS "resources/shaders/brdf.vs" // Path to bidirectional reflectance distribution function vertex shader + #define PATH_BRDF_FS "resources/shaders/brdf.fs" // Path to bidirectional reflectance distribution function fragment shader + + Shader shader = LoadShader(PATH_BRDF_VS, PATH_BRDF_FS); + + // Generate BRDF convolution texture + glGenTextures(1, &brdf.id); + glBindTexture(GL_TEXTURE_2D, brdf.id); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RG16F, size, size, 0, GL_RG, GL_FLOAT, 0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + // Render BRDF LUT into a quad using FBO + unsigned int fbo, rbo; + glGenFramebuffers(1, &fbo); + glGenRenderbuffers(1, &rbo); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glBindRenderbuffer(GL_RENDERBUFFER, rbo); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, size, size); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, brdf.id, 0); + + rlViewport(0, 0, size, size); + glUseProgram(shader.id); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + RenderQuad(); + + // Unbind framebuffer and textures + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + UnloadShader(shader); + + brdf.width = size; + brdf.height = size; + + return brdf; +} + +// Renders a 1x1 3D cube in NDC +GLuint cubeVAO = 0; +GLuint cubeVBO = 0; +static void RenderCube(void) +{ + // Initialize if it is not yet + if (cubeVAO == 0) + { + GLfloat vertices[] = { + -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, + 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, + 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, + 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, + -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, + -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, + -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, + 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, + 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, + -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, + -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, + -1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, + -1.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, + -1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, + -1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, + -1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, + -1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, + 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, + 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, + 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, + 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, + 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, + 1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, + -1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, + 1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f, + 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, + 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, + -1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, + -1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, + -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, + 1.0f, 1.0f , 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, + 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, + -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, + -1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f + }; + + // Set up cube VAO + glGenVertexArrays(1, &cubeVAO); + glGenBuffers(1, &cubeVBO); + + // Fill buffer + glBindBuffer(GL_ARRAY_BUFFER, cubeVBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); + + // Link vertex attributes + glBindVertexArray(cubeVAO); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), (GLvoid*)0); + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), (GLvoid*)(3*sizeof(GLfloat))); + glEnableVertexAttribArray(2); + glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), (GLvoid*)(6*sizeof(GLfloat))); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); + } + + // Render cube + glBindVertexArray(cubeVAO); + glDrawArrays(GL_TRIANGLES, 0, 36); + glBindVertexArray(0); +} + +// Renders a 1x1 XY quad in NDC +GLuint quadVAO = 0; +GLuint quadVBO; +static void RenderQuad(void) +{ + // Initialize if it is not yet + if (quadVAO == 0) + { + GLfloat quadVertices[] = { + // Positions // Texture Coords + -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, + -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, + 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, + 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, + }; + + // Set up plane VAO + glGenVertexArrays(1, &quadVAO); + glGenBuffers(1, &quadVBO); + glBindVertexArray(quadVAO); + + // Fill buffer + glBindBuffer(GL_ARRAY_BUFFER, quadVBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), &quadVertices, GL_STATIC_DRAW); + + // Link vertex attributes + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (GLvoid*)0); + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (GLvoid*)(3*sizeof(GLfloat))); + } + + // Render quad + glBindVertexArray(quadVAO); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + glBindVertexArray(0); +} + + + // Upload vertex data into a VAO (if supported) and VBO -void rlglLoadMesh(Mesh *mesh, bool dynamic) +// TODO: Check if mesh has already been loaded in GPU +void rlLoadMesh(Mesh *mesh, bool dynamic) { mesh->vaoId = 0; // Vertex Array Object mesh->vboId[0] = 0; // Vertex positions VBO @@ -1846,7 +2273,7 @@ void rlglLoadMesh(Mesh *mesh, bool dynamic) } // Update vertex data on GPU (upload new data to one buffer) -void rlglUpdateMesh(Mesh mesh, int buffer, int numVertex) +void rlUpdateMesh(Mesh mesh, int buffer, int numVertex) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) // Activate mesh VAO @@ -1908,11 +2335,11 @@ void rlglUpdateMesh(Mesh mesh, int buffer, int numVertex) } // Draw a 3d mesh with material and transform -void rlglDrawMesh(Mesh mesh, Material material, Matrix transform) +void rlDrawMesh(Mesh mesh, Material material, Matrix transform) { #if defined(GRAPHICS_API_OPENGL_11) glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, material.texDiffuse.id); + glBindTexture(GL_TEXTURE_2D, material.maps[TEXMAP_DIFFUSE].tex.id); // NOTE: On OpenGL 1.1 we use Vertex Arrays to draw model glEnableClientState(GL_VERTEX_ARRAY); // Enable vertex array @@ -1943,16 +2370,28 @@ void rlglDrawMesh(Mesh mesh, Material material, Matrix transform) #endif #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - glUseProgram(material.shader.id); + // Bind shader program + glUseProgram(material.shader.id); + + // Matrices and other values required by shader + //----------------------------------------------------- + + // Calculate and send to shader model matrix (used by PBR shader) + SetShaderValueMatrix(material.shader, material.shader.locs[LOC_MATRIX_MODEL], transform); + // Upload to shader material.colDiffuse - glUniform4f(material.shader.colDiffuseLoc, (float)material.colDiffuse.r/255, (float)material.colDiffuse.g/255, (float)material.colDiffuse.b/255, (float)material.colDiffuse.a/255); - - // Upload to shader material.colAmbient (if available) - if (material.shader.colAmbientLoc != -1) glUniform4f(material.shader.colAmbientLoc, (float)material.colAmbient.r/255, (float)material.colAmbient.g/255, (float)material.colAmbient.b/255, (float)material.colAmbient.a/255); + glUniform4f(material.shader.locs[LOC_COLOR_DIFFUSE], (float)material.maps[TEXMAP_DIFFUSE].color.r/255, + (float)material.maps[TEXMAP_DIFFUSE].color.g/255, + (float)material.maps[TEXMAP_DIFFUSE].color.b/255, + (float)material.maps[TEXMAP_DIFFUSE].color.a/255); // Upload to shader material.colSpecular (if available) - if (material.shader.colSpecularLoc != -1) glUniform4f(material.shader.colSpecularLoc, (float)material.colSpecular.r/255, (float)material.colSpecular.g/255, (float)material.colSpecular.b/255, (float)material.colSpecular.a/255); + if (material.shader.locs[LOC_COLOR_SPECULAR] != -1) + glUniform4f(material.shader.locs[LOC_COLOR_SPECULAR], (float)material.maps[TEXMAP_SPECULAR].color.r/255, + (float)material.maps[TEXMAP_SPECULAR].color.g/255, + (float)material.maps[TEXMAP_SPECULAR].color.b/255, + (float)material.maps[TEXMAP_SPECULAR].color.a/255); // At this point the modelview matrix just contains the view matrix (camera) // That's because Begin3dMode() sets it an no model-drawing function modifies it, all use rlPushMatrix() and rlPopMatrix() @@ -1961,118 +2400,80 @@ void rlglDrawMesh(Mesh mesh, Material material, Matrix transform) // Calculate model-view matrix combining matModel and matView Matrix matModelView = MatrixMultiply(transform, matView); // Transform to camera-space coordinates + //----------------------------------------------------- - // If not using default shader, we check for some additional location points - // NOTE: This method is quite inefficient... it's a temporal solution while looking for a better one - if (material.shader.id != defaultShader.id) + // Bind active texture maps (if available) + for (int i = 0; i < MAX_MATERIAL_TEXTURE_MAPS; i++) { - // Check if model matrix is located in shader and upload value - int modelMatrixLoc = glGetUniformLocation(material.shader.id, "modelMatrix"); - if (modelMatrixLoc != -1) + if (material.maps[i].tex.id > 0) { - // Transpose and inverse model transformations matrix for fragment normal calculations - Matrix transInvTransform = transform; - MatrixTranspose(&transInvTransform); - MatrixInvert(&transInvTransform); + glActiveTexture(GL_TEXTURE0 + i); + if ((i == TEXMAP_IRRADIANCE) || (i == TEXMAP_PREFILTER) || (i == TEXMAP_CUBEMAP)) glBindTexture(GL_TEXTURE_CUBE_MAP, material.maps[i].tex.id); + else glBindTexture(GL_TEXTURE_2D, material.maps[i].tex.id); - // Send model transformations matrix to shader - glUniformMatrix4fv(modelMatrixLoc, 1, false, MatrixToFloat(transInvTransform)); + glUniform1i(material.shader.locs[LOC_TEXMAP_DIFFUSE + i], i); } - - // Check if view direction is located in shader and upload value - // NOTE: View matrix values m8, m9 and m10 are view direction vector axis (target - position) - int viewDirLoc = glGetUniformLocation(material.shader.id, "viewDir"); - if (viewDirLoc != -1) glUniform3f(viewDirLoc, matView.m8, matView.m9, matView.m10); - - // Check if glossiness is located in shader and upload value - int glossinessLoc = glGetUniformLocation(material.shader.id, "glossiness"); - if (glossinessLoc != -1) glUniform1f(glossinessLoc, material.glossiness); - } - - // Set shader textures (diffuse, normal, specular) - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, material.texDiffuse.id); - glUniform1i(material.shader.mapTexture0Loc, 0); // Diffuse texture fits in active texture unit 0 - - if ((material.texNormal.id != 0) && (material.shader.mapTexture1Loc != -1)) - { - // Upload to shader specular map flag - glUniform1i(glGetUniformLocation(material.shader.id, "useNormal"), 1); - - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, material.texNormal.id); - glUniform1i(material.shader.mapTexture1Loc, 1); // Normal texture fits in active texture unit 1 - } - - if ((material.texSpecular.id != 0) && (material.shader.mapTexture2Loc != -1)) - { - // Upload to shader specular map flag - glUniform1i(glGetUniformLocation(material.shader.id, "useSpecular"), 1); - - glActiveTexture(GL_TEXTURE2); - glBindTexture(GL_TEXTURE_2D, material.texSpecular.id); - glUniform1i(material.shader.mapTexture2Loc, 2); // Specular texture fits in active texture unit 2 } - if (vaoSupported) - { - glBindVertexArray(mesh.vaoId); - } + // Bind vertex array objects (or VBOs) + if (vaoSupported) glBindVertexArray(mesh.vaoId); else { + // TODO: Simplify VBO binding into a for loop + // Bind mesh VBO data: vertex position (shader-location = 0) glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[0]); - glVertexAttribPointer(material.shader.vertexLoc, 3, GL_FLOAT, 0, 0, 0); - glEnableVertexAttribArray(material.shader.vertexLoc); + glVertexAttribPointer(material.shader.locs[LOC_VERTEX_POSITION], 3, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(material.shader.locs[LOC_VERTEX_POSITION]); // Bind mesh VBO data: vertex texcoords (shader-location = 1) glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[1]); - glVertexAttribPointer(material.shader.texcoordLoc, 2, GL_FLOAT, 0, 0, 0); - glEnableVertexAttribArray(material.shader.texcoordLoc); + glVertexAttribPointer(material.shader.locs[LOC_VERTEX_TEXCOORD01], 2, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(material.shader.locs[LOC_VERTEX_TEXCOORD01]); // Bind mesh VBO data: vertex normals (shader-location = 2, if available) - if (material.shader.normalLoc != -1) + if (material.shader.locs[LOC_VERTEX_NORMAL] != -1) { glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[2]); - glVertexAttribPointer(material.shader.normalLoc, 3, GL_FLOAT, 0, 0, 0); - glEnableVertexAttribArray(material.shader.normalLoc); + glVertexAttribPointer(material.shader.locs[LOC_VERTEX_NORMAL], 3, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(material.shader.locs[LOC_VERTEX_NORMAL]); } // Bind mesh VBO data: vertex colors (shader-location = 3, if available) - if (material.shader.colorLoc != -1) + if (material.shader.locs[LOC_VERTEX_COLOR] != -1) { if (mesh.vboId[3] != 0) { glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[3]); - glVertexAttribPointer(material.shader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); - glEnableVertexAttribArray(material.shader.colorLoc); + glVertexAttribPointer(material.shader.locs[LOC_VERTEX_COLOR], 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); + glEnableVertexAttribArray(material.shader.locs[LOC_VERTEX_COLOR]); } else { // Set default value for unused attribute // NOTE: Required when using default shader and no VAO support - glVertexAttrib4f(material.shader.colorLoc, 1.0f, 1.0f, 1.0f, 1.0f); - glDisableVertexAttribArray(material.shader.colorLoc); + glVertexAttrib4f(material.shader.locs[LOC_VERTEX_COLOR], 1.0f, 1.0f, 1.0f, 1.0f); + glDisableVertexAttribArray(material.shader.locs[LOC_VERTEX_COLOR]); } } // Bind mesh VBO data: vertex tangents (shader-location = 4, if available) - if (material.shader.tangentLoc != -1) + if (material.shader.locs[LOC_VERTEX_TANGENT] != -1) { glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[4]); - glVertexAttribPointer(material.shader.tangentLoc, 3, GL_FLOAT, 0, 0, 0); - glEnableVertexAttribArray(material.shader.tangentLoc); + glVertexAttribPointer(material.shader.locs[LOC_VERTEX_TANGENT], 3, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(material.shader.locs[LOC_VERTEX_TANGENT]); } // Bind mesh VBO data: vertex texcoords2 (shader-location = 5, if available) - if (material.shader.texcoord2Loc != -1) + if (material.shader.locs[LOC_VERTEX_TEXCOORD02] != -1) { glBindBuffer(GL_ARRAY_BUFFER, mesh.vboId[5]); - glVertexAttribPointer(material.shader.texcoord2Loc, 2, GL_FLOAT, 0, 0, 0); - glEnableVertexAttribArray(material.shader.texcoord2Loc); + glVertexAttribPointer(material.shader.locs[LOC_VERTEX_TEXCOORD02], 2, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(material.shader.locs[LOC_VERTEX_TEXCOORD02]); } - if (mesh.indices != NULL) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, quads.vboId[3]); + if (mesh.indices != NULL) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.vboId[6]); } int eyesCount = 1; @@ -2091,45 +2492,41 @@ void rlglDrawMesh(Mesh mesh, Material material, Matrix transform) Matrix matMVP = MatrixMultiply(modelview, projection); // Transform to screen-space coordinates // Send combined model-view-projection matrix to shader - glUniformMatrix4fv(material.shader.mvpLoc, 1, false, MatrixToFloat(matMVP)); + glUniformMatrix4fv(material.shader.locs[LOC_MATRIX_MVP], 1, false, MatrixToFloat(matMVP)); // Draw call! if (mesh.indices != NULL) glDrawElements(GL_TRIANGLES, mesh.triangleCount*3, GL_UNSIGNED_SHORT, 0); // Indexed vertices draw else glDrawArrays(GL_TRIANGLES, 0, mesh.vertexCount); } - - if (material.texNormal.id != 0) - { - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, 0); - } - - if (material.texSpecular.id != 0) + + // Unbind all binded texture maps + for (int i = 0; i < MAX_MATERIAL_TEXTURE_MAPS; i++) { - glActiveTexture(GL_TEXTURE2); - glBindTexture(GL_TEXTURE_2D, 0); + glActiveTexture(GL_TEXTURE0 + i); // Set shader active texture + if ((i == TEXMAP_IRRADIANCE) || (i == TEXMAP_PREFILTER) || (i == TEXMAP_CUBEMAP)) glBindTexture(GL_TEXTURE_CUBE_MAP, 0); + else glBindTexture(GL_TEXTURE_2D, 0); // Unbind current active texture } - glActiveTexture(GL_TEXTURE0); // Set shader active texture to default 0 - glBindTexture(GL_TEXTURE_2D, 0); // Unbind textures - - if (vaoSupported) glBindVertexArray(0); // Unbind VAO + // Unind vertex array objects (or VBOs) + if (vaoSupported) glBindVertexArray(0); else { - glBindBuffer(GL_ARRAY_BUFFER, 0); // Unbind VBOs + glBindBuffer(GL_ARRAY_BUFFER, 0); if (mesh.indices != NULL) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); } - glUseProgram(0); // Unbind shader program + // Unbind shader program + glUseProgram(0); // Restore projection/modelview matrices + // NOTE: In stereo rendering matrices are being modified to fit every eye projection = matProjection; modelview = matView; #endif } // Unload mesh data from CPU and GPU -void rlglUnloadMesh(Mesh *mesh) +void rlUnloadMesh(Mesh *mesh) { if (mesh->vertices != NULL) free(mesh->vertices); if (mesh->texcoords != NULL) free(mesh->texcoords); @@ -2151,7 +2548,7 @@ void rlglUnloadMesh(Mesh *mesh) } // Read screen pixel data (color buffer) -unsigned char *rlglReadScreenPixels(int width, int height) +unsigned char *rlReadScreenPixels(int width, int height) { unsigned char *screenData = (unsigned char *)calloc(width*height*4, sizeof(unsigned char)); @@ -2182,7 +2579,7 @@ unsigned char *rlglReadScreenPixels(int width, int height) // Read texture pixel data // NOTE: glGetTexImage() is not available on OpenGL ES 2.0 // Texture2D width and height are required on OpenGL ES 2.0. There is no way to get it from texture id. -void *rlglReadTexturePixels(Texture2D texture) +void *rlReadTexturePixels(Texture2D texture) { void *pixels = NULL; @@ -2235,7 +2632,7 @@ void *rlglReadTexturePixels(Texture2D texture) #if defined(GRAPHICS_API_OPENGL_ES2) - RenderTexture2D fbo = rlglLoadRenderTexture(texture.width, texture.height); + RenderTexture2D fbo = rlLoadRenderTexture(texture.width, texture.height); // NOTE: Two possible Options: // 1 - Bind texture to color fbo attachment and glReadPixels() @@ -2306,7 +2703,7 @@ void *rlglReadTexturePixels(Texture2D texture) /* // TODO: Record draw calls to be processed in batch // NOTE: Global state must be kept -void rlglRecordDraw(void) +void rlRecordDraw(void) { // TODO: Before adding a new draw, check if anything changed from last stored draw #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) @@ -2328,7 +2725,7 @@ void rlglRecordDraw(void) //---------------------------------------------------------------------------------- // Get default internal texture (white texture) -Texture2D GetDefaultTexture(void) +Texture2D GetTextureDefault(void) { Texture2D texture; @@ -2389,8 +2786,8 @@ Shader LoadShader(char *vsFileName, char *fsFileName) { shader.id = LoadShaderProgram(vShaderStr, fShaderStr); - // After shader loading, we try to load default location names - if (shader.id != 0) LoadDefaultShaderLocations(&shader); + // After shader loading, we TRY to set default location names + if (shader.id > 0) SetShaderDefaultLocations(&shader); // Shader strings must be freed free(vShaderStr); @@ -2402,6 +2799,32 @@ Shader LoadShader(char *vsFileName, char *fsFileName) TraceLog(LOG_WARNING, "Custom shader could not be loaded"); shader = defaultShader; } + + + // Get available shader uniforms + // NOTE: This information is useful for debug... + int uniformCount = -1; + + glGetProgramiv(shader.id, GL_ACTIVE_UNIFORMS, &uniformCount); + + for(int i = 0; i < uniformCount; i++) + { + int namelen = -1; + int num = -1; + char name[256]; // Assume no variable names longer than 256 + GLenum type = GL_ZERO; + + // Get the name of the uniforms + glGetActiveUniform(shader.id, i,sizeof(name) - 1, &namelen, &num, &type, name); + + name[namelen] = 0; + + // Get the location of the named uniform + GLuint location = glGetUniformLocation(shader.id, name); + + TraceLog(LOG_INFO, "[SHDR ID %i] Active uniform [%s] set at location: %i", shader.id, name, location); + } + #endif return shader; @@ -2410,7 +2833,7 @@ Shader LoadShader(char *vsFileName, char *fsFileName) // Unload shader from GPU memory (VRAM) void UnloadShader(Shader shader) { - if (shader.id != 0) + if (shader.id > 0) { rlDeleteShader(shader.id); TraceLog(LOG_INFO, "[SHDR ID %i] Unloaded shader program data", shader.id); @@ -2438,7 +2861,7 @@ void EndShaderMode(void) } // Get default shader -Shader GetDefaultShader(void) +Shader GetShaderDefault(void) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) return defaultShader; @@ -2455,7 +2878,8 @@ int GetShaderLocation(Shader shader, const char *uniformName) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) location = glGetUniformLocation(shader.id, uniformName); - if (location == -1) TraceLog(LOG_DEBUG, "[SHDR ID %i] Shader location for %s could not be found", shader.id, uniformName); + if (location == -1) TraceLog(LOG_WARNING, "[SHDR ID %i] Shader uniform [%s] COULD NOT BE FOUND", shader.id, uniformName); + else TraceLog(LOG_INFO, "[SHDR ID %i] Shader uniform [%s] set at location: %i", shader.id, uniformName, location); #endif return location; } @@ -2609,12 +3033,12 @@ void InitVrSimulator(int vrDevice) // Initialize framebuffer and textures for stereo rendering // NOTE: screen size should match HMD aspect ratio - vrConfig.stereoFbo = rlglLoadRenderTexture(screenWidth, screenHeight); + vrConfig.stereoFbo = rlLoadRenderTexture(screenWidth, screenHeight); #if defined(SUPPORT_DISTORTION_SHADER) // Load distortion shader (initialized by default with Oculus Rift CV1 parameters) vrConfig.distortionShader.id = LoadShaderProgram(vDistortionShaderStr, fDistortionShaderStr); - if (vrConfig.distortionShader.id != 0) LoadDefaultShaderLocations(&vrConfig.distortionShader); + if (vrConfig.distortionShader.id > 0) SetShaderDefaultLocations(&vrConfig.distortionShader); #endif SetStereoConfig(hmd); @@ -2727,7 +3151,7 @@ void EndVrDrawing(void) // Draw RenderTexture (stereoFbo) using distortion shader currentShader = vrConfig.distortionShader; #else - currentShader = GetDefaultShader(); + currentShader = GetShaderDefault(); #endif rlEnableTexture(vrConfig.stereoFbo.texture.id); @@ -2783,7 +3207,7 @@ void EndVrDrawing(void) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) // Convert image data to OpenGL texture (returns OpenGL valid Id) // NOTE: Expected compressed image data and POT image -static void LoadCompressedTexture(unsigned char *data, int width, int height, int mipmapCount, int compressedFormat) +static void LoadTextureCompressed(unsigned char *data, int width, int height, int compressedFormat, int mipmapCount) { glPixelStorei(GL_UNPACK_ALIGNMENT, 1); @@ -2950,7 +3374,7 @@ static unsigned int LoadShaderProgram(const char *vShaderStr, const char *fShade // Load default shader (just vertex positioning and texture coloring) // NOTE: This shader program is used for batch buffers (lines, triangles, quads) -static Shader LoadDefaultShader(void) +static Shader LoadShaderDefault(void) { Shader shader; @@ -3015,17 +3439,29 @@ static Shader LoadDefaultShader(void) shader.id = LoadShaderProgram(vDefaultShaderStr, fDefaultShaderStr); - if (shader.id != 0) TraceLog(LOG_INFO, "[SHDR ID %i] Default shader loaded successfully", shader.id); - else TraceLog(LOG_WARNING, "[SHDR ID %i] Default shader could not be loaded", shader.id); - - if (shader.id != 0) LoadDefaultShaderLocations(&shader); + if (shader.id > 0) + { + TraceLog(LOG_INFO, "[SHDR ID %i] Default shader loaded successfully", shader.id); + + // Set default shader locations + // Get handles to GLSL input attibute locations + shader.locs[LOC_VERTEX_POSITION] = glGetAttribLocation(shader.id, "vertexPosition"); + shader.locs[LOC_VERTEX_TEXCOORD01] = glGetAttribLocation(shader.id, "vertexTexCoord"); + shader.locs[LOC_VERTEX_COLOR] = glGetAttribLocation(shader.id, "vertexColor"); + + // Get handles to GLSL uniform locations + shader.locs[LOC_MATRIX_MVP] = glGetUniformLocation(shader.id, "mvpMatrix"); + shader.locs[LOC_COLOR_DIFFUSE] = glGetUniformLocation(shader.id, "colDiffuse"); + shader.locs[LOC_TEXMAP_DIFFUSE] = glGetUniformLocation(shader.id, "texture0"); + } + else TraceLog(WARNING, "[SHDR ID %i] Default shader could not be loaded", shader.id); return shader; } // Get location handlers to for shader attributes and uniforms // NOTE: If any location is not found, loc point becomes -1 -static void LoadDefaultShaderLocations(Shader *shader) +static void SetShaderDefaultLocations(Shader *shader) { // NOTE: Default shader attrib locations have been fixed before linking: // vertex position location = 0 @@ -3036,30 +3472,27 @@ static void LoadDefaultShaderLocations(Shader *shader) // vertex texcoord2 location = 5 // Get handles to GLSL input attibute locations - shader->vertexLoc = glGetAttribLocation(shader->id, DEFAULT_ATTRIB_POSITION_NAME); - shader->texcoordLoc = glGetAttribLocation(shader->id, DEFAULT_ATTRIB_TEXCOORD_NAME); - shader->texcoord2Loc = glGetAttribLocation(shader->id, DEFAULT_ATTRIB_TEXCOORD2_NAME); - shader->normalLoc = glGetAttribLocation(shader->id, DEFAULT_ATTRIB_NORMAL_NAME); - shader->tangentLoc = glGetAttribLocation(shader->id, DEFAULT_ATTRIB_TANGENT_NAME); - shader->colorLoc = glGetAttribLocation(shader->id, DEFAULT_ATTRIB_COLOR_NAME); + shader->locs[LOC_VERTEX_POSITION] = glGetAttribLocation(shader->id, DEFAULT_ATTRIB_POSITION_NAME); + shader->locs[LOC_VERTEX_TEXCOORD01] = glGetAttribLocation(shader->id, DEFAULT_ATTRIB_TEXCOORD_NAME); + shader->locs[LOC_VERTEX_TEXCOORD02] = glGetAttribLocation(shader->id, DEFAULT_ATTRIB_TEXCOORD2_NAME); + shader->locs[LOC_VERTEX_NORMAL] = glGetAttribLocation(shader->id, DEFAULT_ATTRIB_NORMAL_NAME); + shader->locs[LOC_VERTEX_TANGENT] = glGetAttribLocation(shader->id, DEFAULT_ATTRIB_TANGENT_NAME); + shader->locs[LOC_VERTEX_COLOR] = glGetAttribLocation(shader->id, DEFAULT_ATTRIB_COLOR_NAME); // Get handles to GLSL uniform locations (vertex shader) - shader->mvpLoc = glGetUniformLocation(shader->id, "mvpMatrix"); + shader->locs[LOC_MATRIX_MVP] = glGetUniformLocation(shader->id, "mvpMatrix"); // Get handles to GLSL uniform locations (fragment shader) - shader->colDiffuseLoc = glGetUniformLocation(shader->id, "colDiffuse"); - shader->colAmbientLoc = glGetUniformLocation(shader->id, "colAmbient"); - shader->colSpecularLoc = glGetUniformLocation(shader->id, "colSpecular"); - - shader->mapTexture0Loc = glGetUniformLocation(shader->id, "texture0"); - shader->mapTexture1Loc = glGetUniformLocation(shader->id, "texture1"); - shader->mapTexture2Loc = glGetUniformLocation(shader->id, "texture2"); + shader->locs[LOC_COLOR_DIFFUSE] = glGetUniformLocation(shader->id, "colDiffuse"); + shader->locs[LOC_TEXMAP_DIFFUSE] = glGetUniformLocation(shader->id, "texture0"); + shader->locs[LOC_TEXMAP_NORMAL] = glGetUniformLocation(shader->id, "texture1"); + shader->locs[LOC_TEXMAP_SPECULAR] = glGetUniformLocation(shader->id, "texture2"); // TODO: Try to find all expected/recognized shader locations (predefined names, must be documented) } // Unload default shader -static void UnloadDefaultShader(void) +static void UnloadShaderDefault(void) { glUseProgram(0); @@ -3155,15 +3588,15 @@ static void LoadDefaultBuffers(void) glGenBuffers(2, &lines.vboId[0]); glBindBuffer(GL_ARRAY_BUFFER, lines.vboId[0]); glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*2*MAX_LINES_BATCH, lines.vertices, GL_DYNAMIC_DRAW); - glEnableVertexAttribArray(currentShader.vertexLoc); - glVertexAttribPointer(currentShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(currentShader.locs[LOC_VERTEX_POSITION]); + glVertexAttribPointer(currentShader.locs[LOC_VERTEX_POSITION], 3, GL_FLOAT, 0, 0, 0); // Vertex color buffer (shader-location = 3) glGenBuffers(2, &lines.vboId[1]); glBindBuffer(GL_ARRAY_BUFFER, lines.vboId[1]); glBufferData(GL_ARRAY_BUFFER, sizeof(unsigned char)*4*2*MAX_LINES_BATCH, lines.colors, GL_DYNAMIC_DRAW); - glEnableVertexAttribArray(currentShader.colorLoc); - glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); + glEnableVertexAttribArray(currentShader.locs[LOC_VERTEX_COLOR]); + glVertexAttribPointer(currentShader.locs[LOC_VERTEX_COLOR], 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); if (vaoSupported) TraceLog(LOG_INFO, "[VAO ID %i] Default buffers VAO initialized successfully (lines)", lines.vaoId); else TraceLog(LOG_INFO, "[VBO ID %i][VBO ID %i] Default buffers VBOs initialized successfully (lines)", lines.vboId[0], lines.vboId[1]); @@ -3181,15 +3614,15 @@ static void LoadDefaultBuffers(void) glGenBuffers(1, &triangles.vboId[0]); glBindBuffer(GL_ARRAY_BUFFER, triangles.vboId[0]); glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*3*MAX_TRIANGLES_BATCH, triangles.vertices, GL_DYNAMIC_DRAW); - glEnableVertexAttribArray(currentShader.vertexLoc); - glVertexAttribPointer(currentShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(currentShader.locs[LOC_VERTEX_POSITION]); + glVertexAttribPointer(currentShader.locs[LOC_VERTEX_POSITION], 3, GL_FLOAT, 0, 0, 0); // Vertex color buffer (shader-location = 3) glGenBuffers(1, &triangles.vboId[1]); glBindBuffer(GL_ARRAY_BUFFER, triangles.vboId[1]); glBufferData(GL_ARRAY_BUFFER, sizeof(unsigned char)*4*3*MAX_TRIANGLES_BATCH, triangles.colors, GL_DYNAMIC_DRAW); - glEnableVertexAttribArray(currentShader.colorLoc); - glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); + glEnableVertexAttribArray(currentShader.locs[LOC_VERTEX_COLOR]); + glVertexAttribPointer(currentShader.locs[LOC_VERTEX_COLOR], 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); if (vaoSupported) TraceLog(LOG_INFO, "[VAO ID %i] Default buffers VAO initialized successfully (triangles)", triangles.vaoId); else TraceLog(LOG_INFO, "[VBO ID %i][VBO ID %i] Default buffers VBOs initialized successfully (triangles)", triangles.vboId[0], triangles.vboId[1]); @@ -3207,22 +3640,22 @@ static void LoadDefaultBuffers(void) glGenBuffers(1, &quads.vboId[0]); glBindBuffer(GL_ARRAY_BUFFER, quads.vboId[0]); glBufferData(GL_ARRAY_BUFFER, sizeof(float)*3*4*MAX_QUADS_BATCH, quads.vertices, GL_DYNAMIC_DRAW); - glEnableVertexAttribArray(currentShader.vertexLoc); - glVertexAttribPointer(currentShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(currentShader.locs[LOC_VERTEX_POSITION]); + glVertexAttribPointer(currentShader.locs[LOC_VERTEX_POSITION], 3, GL_FLOAT, 0, 0, 0); // Vertex texcoord buffer (shader-location = 1) glGenBuffers(1, &quads.vboId[1]); glBindBuffer(GL_ARRAY_BUFFER, quads.vboId[1]); glBufferData(GL_ARRAY_BUFFER, sizeof(float)*2*4*MAX_QUADS_BATCH, quads.texcoords, GL_DYNAMIC_DRAW); - glEnableVertexAttribArray(currentShader.texcoordLoc); - glVertexAttribPointer(currentShader.texcoordLoc, 2, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(currentShader.locs[LOC_VERTEX_TEXCOORD01]); + glVertexAttribPointer(currentShader.locs[LOC_VERTEX_TEXCOORD01], 2, GL_FLOAT, 0, 0, 0); // Vertex color buffer (shader-location = 3) glGenBuffers(1, &quads.vboId[2]); glBindBuffer(GL_ARRAY_BUFFER, quads.vboId[2]); glBufferData(GL_ARRAY_BUFFER, sizeof(unsigned char)*4*4*MAX_QUADS_BATCH, quads.colors, GL_DYNAMIC_DRAW); - glEnableVertexAttribArray(currentShader.colorLoc); - glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); + glEnableVertexAttribArray(currentShader.locs[LOC_VERTEX_COLOR]); + glVertexAttribPointer(currentShader.locs[LOC_VERTEX_COLOR], 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); // Fill index buffer glGenBuffers(1, &quads.vboId[3]); @@ -3338,9 +3771,9 @@ static void DrawDefaultBuffers() // Create modelview-projection matrix Matrix matMVP = MatrixMultiply(modelview, projection); - glUniformMatrix4fv(currentShader.mvpLoc, 1, false, MatrixToFloat(matMVP)); - glUniform4f(currentShader.colDiffuseLoc, 1.0f, 1.0f, 1.0f, 1.0f); - glUniform1i(currentShader.mapTexture0Loc, 0); + glUniformMatrix4fv(currentShader.locs[LOC_MATRIX_MVP], 1, false, MatrixToFloat(matMVP)); + glUniform4f(currentShader.locs[LOC_COLOR_DIFFUSE], 1.0f, 1.0f, 1.0f, 1.0f); + glUniform1i(currentShader.locs[LOC_TEXMAP_DIFFUSE], 0); // NOTE: Additional map textures not considered for default buffers drawing } @@ -3348,6 +3781,7 @@ static void DrawDefaultBuffers() // Draw lines buffers if (lines.vCounter > 0) { + glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, whiteTexture); if (vaoSupported) @@ -3358,13 +3792,13 @@ static void DrawDefaultBuffers() { // Bind vertex attrib: position (shader-location = 0) glBindBuffer(GL_ARRAY_BUFFER, lines.vboId[0]); - glVertexAttribPointer(currentShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0); - glEnableVertexAttribArray(currentShader.vertexLoc); + glVertexAttribPointer(currentShader.locs[LOC_VERTEX_POSITION], 3, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(currentShader.locs[LOC_VERTEX_POSITION]); // Bind vertex attrib: color (shader-location = 3) glBindBuffer(GL_ARRAY_BUFFER, lines.vboId[1]); - glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); - glEnableVertexAttribArray(currentShader.colorLoc); + glVertexAttribPointer(currentShader.locs[LOC_VERTEX_COLOR], 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); + glEnableVertexAttribArray(currentShader.locs[LOC_VERTEX_COLOR]); } glDrawArrays(GL_LINES, 0, lines.vCounter); @@ -3376,6 +3810,7 @@ static void DrawDefaultBuffers() // Draw triangles buffers if (triangles.vCounter > 0) { + glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, whiteTexture); if (vaoSupported) @@ -3386,13 +3821,13 @@ static void DrawDefaultBuffers() { // Bind vertex attrib: position (shader-location = 0) glBindBuffer(GL_ARRAY_BUFFER, triangles.vboId[0]); - glVertexAttribPointer(currentShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0); - glEnableVertexAttribArray(currentShader.vertexLoc); + glVertexAttribPointer(currentShader.locs[LOC_VERTEX_POSITION], 3, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(currentShader.locs[LOC_VERTEX_POSITION]); // Bind vertex attrib: color (shader-location = 3) glBindBuffer(GL_ARRAY_BUFFER, triangles.vboId[1]); - glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); - glEnableVertexAttribArray(currentShader.colorLoc); + glVertexAttribPointer(currentShader.locs[LOC_VERTEX_COLOR], 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); + glEnableVertexAttribArray(currentShader.locs[LOC_VERTEX_COLOR]); } glDrawArrays(GL_TRIANGLES, 0, triangles.vCounter); @@ -3416,18 +3851,18 @@ static void DrawDefaultBuffers() { // Bind vertex attrib: position (shader-location = 0) glBindBuffer(GL_ARRAY_BUFFER, quads.vboId[0]); - glVertexAttribPointer(currentShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0); - glEnableVertexAttribArray(currentShader.vertexLoc); + glVertexAttribPointer(currentShader.locs[LOC_VERTEX_POSITION], 3, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(currentShader.locs[LOC_VERTEX_POSITION]); // Bind vertex attrib: texcoord (shader-location = 1) glBindBuffer(GL_ARRAY_BUFFER, quads.vboId[1]); - glVertexAttribPointer(currentShader.texcoordLoc, 2, GL_FLOAT, 0, 0, 0); - glEnableVertexAttribArray(currentShader.texcoordLoc); + glVertexAttribPointer(currentShader.locs[LOC_VERTEX_TEXCOORD01], 2, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(currentShader.locs[LOC_VERTEX_TEXCOORD01]); // Bind vertex attrib: color (shader-location = 3) glBindBuffer(GL_ARRAY_BUFFER, quads.vboId[2]); - glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); - glEnableVertexAttribArray(currentShader.colorLoc); + glVertexAttribPointer(currentShader.locs[LOC_VERTEX_COLOR], 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); + glEnableVertexAttribArray(currentShader.locs[LOC_VERTEX_COLOR]); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, quads.vboId[3]); } @@ -3441,6 +3876,7 @@ static void DrawDefaultBuffers() //TraceLog(LOG_DEBUG, "Quads to render: %i - Vertex Count: %i", quadsCount, draws[i].vertexCount); + glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, draws[i].textureId); // NOTE: The final parameter tells the GPU the offset in bytes from the start of the index buffer to the location of the first index to process diff --git a/src/rlgl.h b/src/rlgl.h index 36ff7889..3adf81a5 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -145,6 +145,54 @@ typedef unsigned char byte; // Boolean type typedef enum { false, true } bool; #endif + + typedef enum { + LOC_VERTEX_POSITION = 0, + LOC_VERTEX_TEXCOORD01, + LOC_VERTEX_TEXCOORD02, + LOC_VERTEX_NORMAL, + LOC_VERTEX_TANGENT, + LOC_VERTEX_COLOR, + LOC_MATRIX_MVP, + LOC_MATRIX_MODEL, + LOC_MATRIX_VIEW, + LOC_MATRIX_PROJECTION, + LOC_VECTOR_VIEW, + LOC_COLOR_DIFFUSE, + LOC_COLOR_SPECULAR, + LOC_COLOR_AMBIENT, + LOC_TEXMAP_ALBEDO, // LOC_TEXMAP_DIFFUSE + LOC_TEXMAP_METALNESS, // LOC_TEXMAP_SPECULAR + LOC_TEXMAP_NORMAL, + LOC_TEXMAP_ROUGHNESS, + LOC_TEXMAP_OCCUSION, + LOC_TEXMAP_EMISSION, + LOC_TEXMAP_HEIGHT, + LOC_TEXMAP_CUBEMAP, + LOC_TEXMAP_IRRADIANCE, + LOC_TEXMAP_PREFILTER, + LOC_TEXMAP_BRDF + } ShaderLocationIndex; + + #define LOC_TEXMAP_DIFFUSE LOC_TEXMAP_ALBEDO + #define LOC_TEXMAP_SPECULAR LOC_TEXMAP_METALNESS + + typedef enum { + TEXMAP_ALBEDO = 0, // TEXMAP_DIFFUSE + TEXMAP_METALNESS = 1, // TEXMAP_SPECULAR + TEXMAP_NORMAL = 2, + TEXMAP_ROUGHNESS = 3, + TEXMAP_OCCLUSION, + TEXMAP_EMISSION, + TEXMAP_HEIGHT, + TEXMAP_CUBEMAP, // NOTE: Uses GL_TEXTURE_CUBE_MAP + TEXMAP_IRRADIANCE, // NOTE: Uses GL_TEXTURE_CUBE_MAP + TEXMAP_PREFILTER, // NOTE: Uses GL_TEXTURE_CUBE_MAP + TEXMAP_BRDF + } TexmapIndex; + + #define TEXMAP_DIFFUSE TEXMAP_ALBEDO + #define TEXMAP_SPECULAR TEXMAP_METALNESS // Color type, RGBA (32bit) typedef struct Color { @@ -186,44 +234,30 @@ typedef unsigned char byte; unsigned int vaoId; // OpenGL Vertex Array Object id unsigned int vboId[7]; // OpenGL Vertex Buffer Objects id (7 types of vertex data) } Mesh; - - // Shader type (generic shader) + + // Shader and material limits + #define MAX_SHADER_LOCATIONS 32 + #define MAX_MATERIAL_TEXTURE_MAPS 12 + #define MAX_MATERIAL_PARAMS 8 + + // Shader type (generic) typedef struct Shader { unsigned int id; // Shader program id - - // Vertex attributes locations (default locations) - int vertexLoc; // Vertex attribute location point (default-location = 0) - int texcoordLoc; // Texcoord attribute location point (default-location = 1) - int normalLoc; // Normal attribute location point (default-location = 2) - int colorLoc; // Color attibute location point (default-location = 3) - int tangentLoc; // Tangent attribute location point (default-location = 4) - int texcoord2Loc; // Texcoord2 attribute location point (default-location = 5) - - // Uniform locations - int mvpLoc; // ModelView-Projection matrix uniform location point (vertex shader) - int colDiffuseLoc; // Color uniform location point (fragment shader) - int colAmbientLoc; // Ambient color uniform location point (fragment shader) - int colSpecularLoc; // Specular color uniform location point (fragment shader) - - // Texture map locations (generic for any kind of map) - int mapTexture0Loc; // Map texture uniform location point (default-texture-unit = 0) - int mapTexture1Loc; // Map texture uniform location point (default-texture-unit = 1) - int mapTexture2Loc; // Map texture uniform location point (default-texture-unit = 2) + int locs[MAX_SHADER_LOCATIONS]; // Initialized on LoadShader(), set to MAX_SHADER_LOCATIONS } Shader; - // Material type - typedef struct Material { - Shader shader; // Standard shader (supports 3 map types: diffuse, normal, specular) - - Texture2D texDiffuse; // Diffuse texture - Texture2D texNormal; // Normal texture - Texture2D texSpecular; // Specular texture + // Material texture map + typedef struct TextureMap { + Texture2D tex; + Color color; + float value; + } TextureMap; - Color colDiffuse; // Diffuse color - Color colAmbient; // Ambient color - Color colSpecular; // Specular color - - float glossiness; // Glossiness level (Ranges from 0 to 1000) + // Material type (generic) + typedef struct Material { + Shader shader; + TextureMap maps[MAX_TEXTURE_MAPS]; // Initialized on LoadMaterial*(), set to MAX_TEXTURE_MAPS + float *params; // Initialized on LoadMaterial*(), set to MAX_MATERIAL_PARAMS } Material; // Camera type, defines a camera position/orientation in 3d space @@ -343,23 +377,24 @@ void rlColor4f(float x, float y, float z, float w); // Define one vertex (color) // Functions Declaration - OpenGL equivalent functions (common to 1.1, 3.3+, ES2) // NOTE: This functions are used to completely abstract raylib code from OpenGL layer //------------------------------------------------------------------------------------ -void rlEnableTexture(unsigned int id); // Enable texture usage -void rlDisableTexture(void); // Disable texture usage +void rlEnableTexture(unsigned int id); // Enable texture usage +void rlDisableTexture(void); // Disable texture usage void rlTextureParameters(unsigned int id, int param, int value); // Set texture parameters (filter, wrap) -void rlEnableRenderTexture(unsigned int id); // Enable render texture (fbo) -void rlDisableRenderTexture(void); // Disable render texture (fbo), return to default framebuffer -void rlEnableDepthTest(void); // Enable depth test -void rlDisableDepthTest(void); // Disable depth test -void rlEnableWireMode(void); // Enable wire mode -void rlDisableWireMode(void); // Disable wire mode -void rlDeleteTextures(unsigned int id); // Delete OpenGL texture from GPU +void rlEnableRenderTexture(unsigned int id); // Enable render texture (fbo) +void rlDisableRenderTexture(void); // Disable render texture (fbo), return to default framebuffer +void rlEnableDepthTest(void); // Enable depth test +void rlDisableDepthTest(void); // Disable depth test +void rlEnableWireMode(void); // Enable wire mode +void rlDisableWireMode(void); // Disable wire mode +void rlDeleteTextures(unsigned int id); // Delete OpenGL texture from GPU void rlDeleteRenderTextures(RenderTexture2D target); // Delete render textures (fbo) from GPU -void rlDeleteShader(unsigned int id); // Delete OpenGL shader program from GPU -void rlDeleteVertexArrays(unsigned int id); // Unload vertex data (VAO) from GPU memory -void rlDeleteBuffers(unsigned int id); // Unload vertex data (VBO) from GPU memory -void rlClearColor(byte r, byte g, byte b, byte a); // Clear color buffer with color -void rlClearScreenBuffers(void); // Clear used screen buffers (color and depth) -int rlGetVersion(void); // Returns current OpenGL version +void rlDeleteShader(unsigned int id); // Delete OpenGL shader program from GPU +void rlDeleteVertexArrays(unsigned int id); // Unload vertex data (VAO) from GPU memory +void rlDeleteBuffers(unsigned int id); // Unload vertex data (VBO) from GPU memory +void rlClearColor(byte r, byte g, byte b, byte a); // Clear color buffer with color +void rlClearScreenBuffers(void); // Clear used screen buffers (color and depth) +int rlGetVersion(void); // Returns current OpenGL version +Vector3 rlUnproject(Vector3 source, Matrix proj, Matrix view); // Get world coordinates from screen coordinates //------------------------------------------------------------------------------------ // Functions Declaration - rlgl functionality @@ -369,24 +404,26 @@ void rlglClose(void); // De-init rlgl void rlglDraw(void); // Draw VAO/VBO void rlglLoadExtensions(void *loader); // Load OpenGL extensions -unsigned int rlglLoadTexture(void *data, int width, int height, int format, int mipmapCount); // Load texture in GPU -RenderTexture2D rlglLoadRenderTexture(int width, int height); // Load a texture to be used for rendering (fbo with color and depth attachments) -void rlglUpdateTexture(unsigned int id, int width, int height, int format, const void *data); // Update GPU texture with new data -void rlglGenerateMipmaps(Texture2D *texture); // Generate mipmap data for selected texture - -void rlglLoadMesh(Mesh *mesh, bool dynamic); // Upload vertex data into GPU and provided VAO/VBO ids -void rlglUpdateMesh(Mesh mesh, int buffer, int numVertex); // Update vertex data on GPU (upload new data to one buffer) -void rlglDrawMesh(Mesh mesh, Material material, Matrix transform); // Draw a 3d mesh with material and transform -void rlglUnloadMesh(Mesh *mesh); // Unload mesh data from CPU and GPU - -Vector3 rlglUnproject(Vector3 source, Matrix proj, Matrix view); // Get world coordinates from screen coordinates - -unsigned char *rlglReadScreenPixels(int width, int height); // Read screen pixel data (color buffer) -void *rlglReadTexturePixels(Texture2D texture); // Read texture pixel data - -// VR functions exposed to core module but not to raylib users -void BeginVrDrawing(void); // Begin VR drawing configuration -void EndVrDrawing(void); // End VR drawing process (and desktop mirror) +// Textures data management +unsigned int rlLoadTexture(void *data, int width, int height, int format, int mipmapCount); // Load texture in GPU +void rlUpdateTexture(unsigned int id, int width, int height, int format, const void *data); // Update GPU texture with new data +void rlUnloadTexture(unsigned int id); +void rlGenerateMipmaps(Texture2D *texture); // Generate mipmap data for selected texture +void *rlReadTexturePixels(Texture2D texture); // Read texture pixel data +unsigned char *rlReadScreenPixels(int width, int height); // Read screen pixel data (color buffer) +RenderTexture2D rlLoadRenderTexture(int width, int height); // Load a texture to be used for rendering (fbo with color and depth attachments) + +// Vertex data management +void rlLoadMesh(Mesh *mesh, bool dynamic); // Upload vertex data into GPU and provided VAO/VBO ids +void rlUpdateMesh(Mesh mesh, int buffer, int numVertex); // Update vertex data on GPU (upload new data to one buffer) +void rlDrawMesh(Mesh mesh, Material material, Matrix transform); // Draw a 3d mesh with material and transform +void rlUnloadMesh(Mesh *mesh); // Unload mesh data from CPU and GPU + +// Texture maps generation (PBR) +Texture2D rlGenMapCubemap(Texture2D skyHDR, int size); // Generate cubemap texture map from HDR texture +Texture2D rlGenMapIrradiance(Texture2D cubemap, int size); // Generate irradiance texture map +Texture2D rlGenMapPrefilter(Texture2D cubemap, int size); // Generate prefilter texture map +Texture2D rlGenMapBRDF(Texture2D cubemap, int size); // Generate BRDF texture map // 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 @@ -396,34 +433,34 @@ void EndVrDrawing(void); // End VR drawing process (and deskt // 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 -void UnloadShader(Shader shader); // Unload a custom shader from memory +Shader LoadShader(char *vsFileName, char *fsFileName); // Load a custom shader and bind default locations +void UnloadShader(Shader shader); // Unload a custom shader from memory -Shader GetDefaultShader(void); // Get default shader -Texture2D GetDefaultTexture(void); // Get default texture +Shader GetShaderDefault(void); // Get default shader +Texture2D GetTextureDefault(void); // Get default texture 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 SetShaderValueMatrix(Shader shader, int uniformLoc, Matrix mat); // Set shader uniform value (matrix 4x4) -void SetMatrixProjection(Matrix proj); // Set a custom projection matrix (replaces internal projection matrix) -void SetMatrixModelview(Matrix view); // Set a custom modelview matrix (replaces internal modelview matrix) +void SetMatrixProjection(Matrix proj); // Set a custom projection matrix (replaces internal projection matrix) +void SetMatrixModelview(Matrix view); // Set a custom modelview matrix (replaces internal modelview matrix) -void BeginShaderMode(Shader shader); // Begin custom shader drawing -void EndShaderMode(void); // End custom shader drawing (use default shader) -void BeginBlendMode(int mode); // Begin blending mode (alpha, additive, multiplied) -void EndBlendMode(void); // End blending mode (reset to default: alpha blending) +void BeginShaderMode(Shader shader); // Begin custom shader drawing +void EndShaderMode(void); // End custom shader drawing (use default shader) +void BeginBlendMode(int mode); // Begin blending mode (alpha, additive, multiplied) +void EndBlendMode(void); // End blending mode (reset to default: alpha blending) -void TraceLog(int msgType, const char *text, ...); // Show trace log messages (LOG_INFO, LOG_WARNING, LOG_ERROR, LOG_DEBUG) -float *MatrixToFloat(Matrix mat); // Get float array from Matrix data +void InitVrSimulator(int vrDevice); // Init VR simulator for selected device +void CloseVrSimulator(void); // Close VR simulator for current device +void UpdateVrTracking(Camera *camera); // Update VR tracking (position and orientation) and camera +void ToggleVrMode(void); // Enable/Disable VR experience (device or simulator) +void BeginVrDrawing(void); // Begin VR stereo rendering +void EndVrDrawing(void); // End VR stereo rendering -void InitVrSimulator(int vrDevice); // Init VR simulator for selected device -void CloseVrSimulator(void); // Close VR simulator for current device -void UpdateVrTracking(Camera *camera); // Update VR tracking (position and orientation) and camera -void ToggleVrMode(void); // Enable/Disable VR experience (device or simulator) -void BeginVrDrawing(void); // Begin VR stereo rendering -void EndVrDrawing(void); // End VR stereo rendering +void TraceLog(int msgType, const char *text, ...); // Show trace log messages (LOG_INFO, LOG_WARNING, LOG_ERROR, LOG_DEBUG) +float *MatrixToFloat(Matrix mat); // Converts Matrix to float array #endif #ifdef __cplusplus diff --git a/src/shapes.c b/src/shapes.c index 2a924476..25ed93aa 100644 --- a/src/shapes.c +++ b/src/shapes.c @@ -119,7 +119,7 @@ void DrawLineEx(Vector2 startPos, Vector2 endPos, float thick, Color color) float d = sqrtf(dx*dx + dy*dy); float angle = asinf(dy/d); - rlEnableTexture(GetDefaultTexture().id); + rlEnableTexture(GetTextureDefault().id); rlPushMatrix(); rlTranslatef((float)startPos.x, (float)startPos.y, 0); @@ -203,7 +203,7 @@ void DrawCircleV(Vector2 center, float radius, Color color) } else if ((rlGetVersion() == OPENGL_21) || (rlGetVersion() == OPENGL_33) || (rlGetVersion() == OPENGL_ES_20)) { - rlEnableTexture(GetDefaultTexture().id); // Default white texture + rlEnableTexture(GetTextureDefault().id); // Default white texture rlBegin(RL_QUADS); for (int i = 0; i < 360; i += 20) @@ -253,7 +253,7 @@ void DrawRectangleRec(Rectangle rec, Color color) void DrawRectanglePro(Rectangle rec, Vector2 origin, float rotation, Color color) { - rlEnableTexture(GetDefaultTexture().id); + rlEnableTexture(GetTextureDefault().id); rlPushMatrix(); rlTranslatef((float)rec.x, (float)rec.y, 0); @@ -309,7 +309,7 @@ void DrawRectangleV(Vector2 position, Vector2 size, Color color) } else if ((rlGetVersion() == OPENGL_21) || (rlGetVersion() == OPENGL_33) || (rlGetVersion() == OPENGL_ES_20)) { - rlEnableTexture(GetDefaultTexture().id); // Default white texture + rlEnableTexture(GetTextureDefault().id); // Default white texture rlBegin(RL_QUADS); rlColor4ub(color.r, color.g, color.b, color.a); @@ -376,7 +376,7 @@ void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color) } else if ((rlGetVersion() == OPENGL_21) || (rlGetVersion() == OPENGL_33) || (rlGetVersion() == OPENGL_ES_20)) { - rlEnableTexture(GetDefaultTexture().id); // Default white texture + rlEnableTexture(GetTextureDefault().id); // Default white texture rlBegin(RL_QUADS); rlColor4ub(color.r, color.g, color.b, color.a); diff --git a/src/textures.c b/src/textures.c index 0a8d7591..1436111f 100644 --- a/src/textures.c +++ b/src/textures.c @@ -63,8 +63,8 @@ #include // Required for: strcmp(), strrchr(), strncmp() #include "rlgl.h" // raylib OpenGL abstraction layer to OpenGL 1.1, 3.3 or ES2 - // Required for: rlglLoadTexture() rlDeleteTextures(), - // rlglGenerateMipmaps(), some funcs for DrawTexturePro() + // Required for: rlLoadTexture() rlDeleteTextures(), + // rlGenerateMipmaps(), some funcs for DrawTexturePro() #include "utils.h" // Required for: fopen() Android mapping @@ -384,7 +384,7 @@ Texture2D LoadTextureFromImage(Image image) { Texture2D texture = { 0 }; - texture.id = rlglLoadTexture(image.data, image.width, image.height, image.format, image.mipmaps); + texture.id = rlLoadTexture(image.data, image.width, image.height, image.format, image.mipmaps); texture.width = image.width; texture.height = image.height; @@ -399,7 +399,7 @@ Texture2D LoadTextureFromImage(Image image) // Load texture for rendering (framebuffer) RenderTexture2D LoadRenderTexture(int width, int height) { - RenderTexture2D target = rlglLoadRenderTexture(width, height); + RenderTexture2D target = rlLoadRenderTexture(width, height); return target; } @@ -416,7 +416,7 @@ void UnloadImage(Image image) // Unload texture from GPU memory (VRAM) void UnloadTexture(Texture2D texture) { - if (texture.id != 0) + if (texture.id > 0) { rlDeleteTextures(texture.id); @@ -427,7 +427,7 @@ void UnloadTexture(Texture2D texture) // Unload render texture from GPU memory (VRAM) void UnloadRenderTexture(RenderTexture2D target) { - if (target.id != 0) rlDeleteRenderTextures(target); + if (target.id > 0) rlDeleteRenderTextures(target); } // Get pixel data from image in the form of Color struct array @@ -525,7 +525,7 @@ Image GetTextureData(Texture2D texture) if (texture.format < 8) { - image.data = rlglReadTexturePixels(texture); + image.data = rlReadTexturePixels(texture); if (image.data != NULL) { @@ -553,7 +553,7 @@ Image GetTextureData(Texture2D texture) // NOTE: pixels data must match texture.format void UpdateTexture(Texture2D texture, const void *pixels) { - rlglUpdateTexture(texture.id, texture.width, texture.height, texture.format, pixels); + rlUpdateTexture(texture.id, texture.width, texture.height, texture.format, pixels); } // Save image to a PNG file @@ -1660,9 +1660,9 @@ void GenTextureMipmaps(Texture2D *texture) { TraceLog(LOG_WARNING, "Limited NPOT support, no mipmaps available for NPOT textures"); } - else rlglGenerateMipmaps(texture); + else rlGenerateMipmaps(texture); #else - rlglGenerateMipmaps(texture); + rlGenerateMipmaps(texture); #endif } @@ -1792,7 +1792,7 @@ void DrawTextureRec(Texture2D texture, Rectangle sourceRec, Vector2 position, Co void DrawTexturePro(Texture2D texture, Rectangle sourceRec, Rectangle destRec, Vector2 origin, float rotation, Color tint) { // Check if texture is valid - if (texture.id != 0) + if (texture.id > 0) { if (sourceRec.width < 0) sourceRec.x -= sourceRec.width; if (sourceRec.height < 0) sourceRec.y -= sourceRec.height; -- cgit v1.2.3 From d368403a131522a53c0dedd1ae4f24301898e96e Mon Sep 17 00:00:00 2001 From: raysan5 Date: Wed, 19 Jul 2017 10:09:34 +0200 Subject: Working on PBR materials, renamed some data --- examples/models/models_cubicmap.c | 2 +- examples/models/models_material_pbr.c | 20 +- examples/models/models_skybox.c | 6 +- src/core.c | 2 +- src/models.c | 127 ++--- src/raylib.h | 110 ++-- src/rlgl.c | 1009 +++++++++++++++++---------------- src/rlgl.h | 84 +-- 8 files changed, 689 insertions(+), 671 deletions(-) (limited to 'src/raylib.h') diff --git a/examples/models/models_cubicmap.c b/examples/models/models_cubicmap.c index 8abc7d48..177cf890 100644 --- a/examples/models/models_cubicmap.c +++ b/examples/models/models_cubicmap.c @@ -31,7 +31,7 @@ int main() // NOTE: By default each cube is mapped to one part of texture atlas Texture2D texture = LoadTexture("resources/cubicmap_atlas.png"); // Load map texture - model.material.maps[TEXMAP_DIFFUSE].tex = texture; // Set map diffuse texture + model.material.maps[MAP_DIFFUSE].texture = texture; // Set map diffuse texture Vector3 mapPosition = { -16.0f, 0.0f, -8.0f }; // Set model position diff --git a/examples/models/models_material_pbr.c b/examples/models/models_material_pbr.c index 9380bd91..5761b2af 100644 --- a/examples/models/models_material_pbr.c +++ b/examples/models/models_material_pbr.c @@ -58,18 +58,18 @@ int main() Texture2D texHDR = LoadTexture("resources/pinetree.hdr"); model.material = LoadMaterialPBR(texHDR, (Color){ 255, 255, 255, 255 }, 1.0f, 1.0f); - SetMaterialTexture(&model.material, TEXMAP_ALBEDO, LoadTexture("resources/pbr/trooper_albedo.png")); - SetMaterialTexture(&model.material, TEXMAP_NORMAL, LoadTexture("resources/pbr/trooper_normals.png")); - SetMaterialTexture(&model.material, TEXMAP_METALNESS, LoadTexture("resources/pbr/trooper_metalness.png")); - SetMaterialTexture(&model.material, TEXMAP_ROUGHNESS, LoadTexture("resources/pbr/trooper_roughness.png")); - SetMaterialTexture(&model.material, TEXMAP_OCCLUSION, LoadTexture("resources/pbr/trooper_ao.png")); + SetMaterialTexture(&model.material, MAP_ALBEDO, LoadTexture("resources/pbr/trooper_albedo.png")); + SetMaterialTexture(&model.material, MAP_NORMAL, LoadTexture("resources/pbr/trooper_normals.png")); + SetMaterialTexture(&model.material, MAP_METALNESS, LoadTexture("resources/pbr/trooper_metalness.png")); + SetMaterialTexture(&model.material, MAP_ROUGHNESS, LoadTexture("resources/pbr/trooper_roughness.png")); + SetMaterialTexture(&model.material, MAP_OCCLUSION, LoadTexture("resources/pbr/trooper_ao.png")); // Set textures filtering for better quality - SetTextureFilter(model.material.maps[TEXMAP_ALBEDO].tex, FILTER_BILINEAR); - SetTextureFilter(model.material.maps[TEXMAP_NORMAL].tex, FILTER_BILINEAR); - SetTextureFilter(model.material.maps[TEXMAP_METALNESS].tex, FILTER_BILINEAR); - SetTextureFilter(model.material.maps[TEXMAP_ROUGHNESS].tex, FILTER_BILINEAR); - SetTextureFilter(model.material.maps[TEXMAP_OCCLUSION].tex, FILTER_BILINEAR); + SetTextureFilter(model.material.maps[MAP_ALBEDO].texture, FILTER_BILINEAR); + SetTextureFilter(model.material.maps[MAP_NORMAL].texture, FILTER_BILINEAR); + SetTextureFilter(model.material.maps[MAP_METALNESS].texture, FILTER_BILINEAR); + SetTextureFilter(model.material.maps[MAP_ROUGHNESS].texture, FILTER_BILINEAR); + SetTextureFilter(model.material.maps[MAP_OCCLUSION].texture, FILTER_BILINEAR); int renderModeLoc = GetShaderLocation(model.material.shader, "renderMode"); SetShaderValuei(model.material.shader, renderModeLoc, (int[1]){ 0 }, 1); diff --git a/examples/models/models_skybox.c b/examples/models/models_skybox.c index 8b302b1c..d347854f 100644 --- a/examples/models/models_skybox.c +++ b/examples/models/models_skybox.c @@ -30,8 +30,8 @@ int main() skybox.material.shader = LoadShader("resources/shaders/skybox.vs", "resources/shaders/skybox.fs"); Texture2D texHDR = LoadTexture("resources/pinetree.hdr"); - skybox.material.maps[TEXMAP_CUBEMAP].tex = rlGenMapCubemap(texHDR, 512); - SetShaderValuei(skybox.material.shader, GetShaderLocation(skybox.material.shader, "environmentMap"), (int[1]){ TEXMAP_CUBEMAP }, 1); + skybox.material.maps[MAP_CUBEMAP].texture = GenTextureCubemap(texHDR, 512); + SetShaderValuei(skybox.material.shader, GetShaderLocation(skybox.material.shader, "environmentMap"), (int[1]){ MAP_CUBEMAP }, 1); // Get skybox shader locations skybox.material.shader.locs[LOC_MATRIX_PROJECTION] = GetShaderLocation(skybox.material.shader, "projection"); @@ -66,7 +66,7 @@ int main() Begin3dMode(camera); - DrawModel(skybox, VectorZero(), 1.0f, RED); + DrawModel(skybox, VectorZero(), 1.0f, WHITE); DrawGrid(10, 1.0f); diff --git a/src/core.c b/src/core.c index ad905d4e..5cdd8e6b 100644 --- a/src/core.c +++ b/src/core.c @@ -1878,7 +1878,7 @@ static void InitGraphicsDevice(int width, int height) #if defined(PLATFORM_DESKTOP) // Load OpenGL 3.3 extensions // NOTE: GLFW loader function is passed as parameter - rlglLoadExtensions(glfwGetProcAddress); + rlLoadExtensions(glfwGetProcAddress); #endif // Try to enable GPU V-Sync, so frames are limited to screen refresh rate (60Hz -> 60 FPS) diff --git a/src/models.c b/src/models.c index 0865e8d7..660ecc79 100644 --- a/src/models.c +++ b/src/models.c @@ -1281,12 +1281,12 @@ Material LoadMaterialDefault(void) Material material = { 0 }; material.shader = GetShaderDefault(); - material.maps[TEXMAP_DIFFUSE].tex = GetTextureDefault(); // White texture (1x1 pixel) - //material.maps[TEXMAP_NORMAL].tex; // NOTE: By default, not set - //material.maps[TEXMAP_SPECULAR].tex; // NOTE: By default, not set + material.maps[MAP_DIFFUSE].texture = GetTextureDefault(); // White texture (1x1 pixel) + //material.maps[MAP_NORMAL].tex; // NOTE: By default, not set + //material.maps[MAP_SPECULAR].tex; // NOTE: By default, not set - material.maps[TEXMAP_DIFFUSE].color = WHITE; // Diffuse color - material.maps[TEXMAP_SPECULAR].color = WHITE; // Specular color + material.maps[MAP_DIFFUSE].color = WHITE; // Diffuse color + material.maps[MAP_SPECULAR].color = WHITE; // Specular color return material; } @@ -1294,7 +1294,7 @@ Material LoadMaterialDefault(void) // Load PBR material (Supports: ALBEDO, NORMAL, METALNESS, ROUGHNESS, AO, EMMISIVE, HEIGHT maps) Material LoadMaterialPBR(Texture2D hdr, Color albedo, float metalness, float roughness) { - Material mat = { 0 }; + Material mat = { 0 }; // NOTE: All maps textures are set to { 0 } #define PATH_PBR_VS "resources/shaders/pbr.vs" // Path to physically based rendering vertex shader #define PATH_PBR_FS "resources/shaders/pbr.fs" // Path to physically based rendering fragment shader @@ -1303,16 +1303,16 @@ Material LoadMaterialPBR(Texture2D hdr, Color albedo, float metalness, float rou // Get required locations points for PBR material // NOTE: Those location names must be available and used in the shader code - mat.shader.locs[LOC_TEXMAP_ALBEDO] = GetShaderLocation(mat.shader, "albedo.sampler"); - mat.shader.locs[LOC_TEXMAP_METALNESS] = GetShaderLocation(mat.shader, "metalness.sampler"); - mat.shader.locs[LOC_TEXMAP_NORMAL] = GetShaderLocation(mat.shader, "normals.sampler"); - mat.shader.locs[LOC_TEXMAP_ROUGHNESS] = GetShaderLocation(mat.shader, "roughness.sampler"); - mat.shader.locs[LOC_TEXMAP_OCCUSION] = GetShaderLocation(mat.shader, "occlusion.sampler"); - mat.shader.locs[LOC_TEXMAP_EMISSION] = GetShaderLocation(mat.shader, "emission.sampler"); - mat.shader.locs[LOC_TEXMAP_HEIGHT] = GetShaderLocation(mat.shader, "height.sampler"); - mat.shader.locs[LOC_TEXMAP_IRRADIANCE] = GetShaderLocation(mat.shader, "irradianceMap"); - mat.shader.locs[LOC_TEXMAP_PREFILTER] = GetShaderLocation(mat.shader, "prefilterMap"); - mat.shader.locs[LOC_TEXMAP_BRDF] = GetShaderLocation(mat.shader, "brdfLUT"); + mat.shader.locs[LOC_MAP_ALBEDO] = GetShaderLocation(mat.shader, "albedo.sampler"); + mat.shader.locs[LOC_MAP_METALNESS] = GetShaderLocation(mat.shader, "metalness.sampler"); + mat.shader.locs[LOC_MAP_NORMAL] = GetShaderLocation(mat.shader, "normals.sampler"); + mat.shader.locs[LOC_MAP_ROUGHNESS] = GetShaderLocation(mat.shader, "roughness.sampler"); + mat.shader.locs[LOC_MAP_OCCUSION] = GetShaderLocation(mat.shader, "occlusion.sampler"); + mat.shader.locs[LOC_MAP_EMISSION] = GetShaderLocation(mat.shader, "emission.sampler"); + mat.shader.locs[LOC_MAP_HEIGHT] = GetShaderLocation(mat.shader, "height.sampler"); + mat.shader.locs[LOC_MAP_IRRADIANCE] = GetShaderLocation(mat.shader, "irradianceMap"); + mat.shader.locs[LOC_MAP_PREFILTER] = GetShaderLocation(mat.shader, "prefilterMap"); + mat.shader.locs[LOC_MAP_BRDF] = GetShaderLocation(mat.shader, "brdfLUT"); // Set view matrix location mat.shader.locs[LOC_MATRIX_MODEL] = GetShaderLocation(mat.shader, "mMatrix"); @@ -1320,30 +1320,25 @@ Material LoadMaterialPBR(Texture2D hdr, Color albedo, float metalness, float rou mat.shader.locs[LOC_VECTOR_VIEW] = GetShaderLocation(mat.shader, "viewPos"); // Set up material properties color - mat.maps[TEXMAP_ALBEDO].color = albedo; - mat.maps[TEXMAP_NORMAL].color = (Color){ 128, 128, 255, 255 }; - mat.maps[TEXMAP_METALNESS].value = metalness; - mat.maps[TEXMAP_ROUGHNESS].value = roughness; - mat.maps[TEXMAP_OCCLUSION].value = 1.0f; - mat.maps[TEXMAP_EMISSION].value = 0.0f; - mat.maps[TEXMAP_HEIGHT].value = 0.0f; + mat.maps[MAP_ALBEDO].color = albedo; + mat.maps[MAP_NORMAL].color = (Color){ 128, 128, 255, 255 }; + mat.maps[MAP_METALNESS].value = metalness; + mat.maps[MAP_ROUGHNESS].value = roughness; + mat.maps[MAP_OCCLUSION].value = 1.0f; + mat.maps[MAP_EMISSION].value = 0.0f; + mat.maps[MAP_HEIGHT].value = 0.0f; - #define CUBEMAP_SIZE 1024 // Cubemap texture size + #define CUBEMAP_SIZE 512 // Cubemap texture size #define IRRADIANCE_SIZE 32 // Irradiance map from cubemap texture size #define PREFILTERED_SIZE 256 // Prefiltered HDR environment map texture size #define BRDF_SIZE 512 // BRDF LUT texture map size // Set up environment materials cubemap - Texture2D cubemap = rlGenMapCubemap(hdr, CUBEMAP_SIZE); - mat.maps[TEXMAP_IRRADIANCE].tex = rlGenMapIrradiance(cubemap, IRRADIANCE_SIZE); - mat.maps[TEXMAP_PREFILTER].tex = rlGenMapPrefilter(cubemap, PREFILTERED_SIZE); - mat.maps[TEXMAP_BRDF].tex = rlGenMapBRDF(cubemap, BRDF_SIZE); + Texture2D cubemap = GenTextureCubemap(hdr, CUBEMAP_SIZE); + mat.maps[MAP_IRRADIANCE].texture = GenTextureIrradiance(cubemap, IRRADIANCE_SIZE); + mat.maps[MAP_PREFILTER].texture = GenTexturePrefilter(cubemap, PREFILTERED_SIZE); + mat.maps[MAP_BRDF].texture = GenTextureBRDF(cubemap, BRDF_SIZE); UnloadTexture(cubemap); - - // NOTE: All maps textures are set to { 0 } - - // Reset viewport dimensions to default - rlViewport(0, 0, GetScreenWidth(), GetScreenHeight()); return mat; } @@ -1355,53 +1350,53 @@ void UnloadMaterial(Material material) UnloadShader(material.shader); // Unload loaded texture maps - for (int i = 0; i < MAX_MATERIAL_TEXTURE_MAPS; i++) + for (int i = 0; i < MAX_MATERIAL_MAPS; i++) { // NOTE: We already check for (tex.id > 0) inside function - rlDeleteTextures(material.maps[i].tex.id); + rlDeleteTextures(material.maps[i].texture.id); } } // Set material texture void SetMaterialTexture(Material *mat, int texmapType, Texture2D texture) { - mat->maps[texmapType].tex = texture; + mat->maps[texmapType].texture = texture; // Update MaterialProperty use sampler state to use texture fetch instead of color attribute int location = -1; switch (texmapType) { - case TEXMAP_ALBEDO: + case MAP_ALBEDO: { location = GetShaderLocation(mat->shader, "albedo.useSampler"); SetShaderValuei(mat->shader, location, (int [1]){ 1 }, 1); } break; - case TEXMAP_NORMAL: + case MAP_NORMAL: { location = GetShaderLocation(mat->shader, "normals.useSampler"); SetShaderValuei(mat->shader, location, (int [1]){ 1 }, 1); } break; - case TEXMAP_METALNESS: + case MAP_METALNESS: { location = GetShaderLocation(mat->shader, "metalness.useSampler"); SetShaderValuei(mat->shader, location, (int [1]){ 1 }, 1); } break; - case TEXMAP_ROUGHNESS: + case MAP_ROUGHNESS: { location = GetShaderLocation(mat->shader, "roughness.useSampler"); SetShaderValuei(mat->shader, location, (int [1]){ 1 }, 1); } break; - case TEXMAP_OCCLUSION: + case MAP_OCCLUSION: { location = GetShaderLocation(mat->shader, "occlusion.useSampler"); SetShaderValuei(mat->shader, location, (int [1]){ 1 }, 1); } break; - case TEXMAP_EMISSION: + case MAP_EMISSION: { location = GetShaderLocation(mat->shader, "emission.useSampler"); SetShaderValuei(mat->shader, location, (int [1]){ 1 }, 1); } break; - case TEXMAP_HEIGHT: + case MAP_HEIGHT: { location = GetShaderLocation(mat->shader, "height.useSampler"); SetShaderValuei(mat->shader, location, (int [1]){ 1 }, 1); @@ -1412,44 +1407,44 @@ void SetMaterialTexture(Material *mat, int texmapType, Texture2D texture) // Unset texture from material and unload it from GPU void UnsetMaterialTexture(Material *mat, int texmapType) { - UnloadTexture(mat->maps[texmapType].tex); - mat->maps[texmapType].tex = (Texture2D){ 0 }; + UnloadTexture(mat->maps[texmapType].texture); + mat->maps[texmapType].texture = (Texture2D){ 0 }; // Update MaterialProperty use sampler state to use texture fetch instead of color attribute int location = -1; switch (texmapType) { - case TEXMAP_ALBEDO: + case MAP_ALBEDO: { location = GetShaderLocation(mat->shader, "albedo.useSampler"); SetShaderValuei(mat->shader, location, (int [1]){ 0 }, 1); } break; - case TEXMAP_NORMAL: + case MAP_NORMAL: { location = GetShaderLocation(mat->shader, "normals.useSampler"); SetShaderValuei(mat->shader, location, (int [1]){ 0 }, 1); } break; - case TEXMAP_METALNESS: + case MAP_METALNESS: { location = GetShaderLocation(mat->shader, "metalness.useSampler"); SetShaderValuei(mat->shader, location, (int [1]){ 0 }, 1); } break; - case TEXMAP_ROUGHNESS: + case MAP_ROUGHNESS: { location = GetShaderLocation(mat->shader, "roughness.useSampler"); SetShaderValuei(mat->shader, location, (int [1]){ 0 }, 1); } break; - case TEXMAP_OCCLUSION: + case MAP_OCCLUSION: { location = GetShaderLocation(mat->shader, "occlusion.useSampler"); SetShaderValuei(mat->shader, location, (int [1]){ 0 }, 1); } break; - case TEXMAP_EMISSION: + case MAP_EMISSION: { location = GetShaderLocation(mat->shader, "emission.useSampler"); SetShaderValuei(mat->shader, location, (int [1]){ 0 }, 1); } break; - case TEXMAP_HEIGHT: + case MAP_HEIGHT: { location = GetShaderLocation(mat->shader, "height.useSampler"); SetShaderValuei(mat->shader, location, (int [1]){ 0 }, 1); @@ -1481,7 +1476,7 @@ void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rota //Matrix matModel = MatrixMultiply(model.transform, matTransform); // Transform to world-space coordinates model.transform = MatrixMultiply(model.transform, matTransform); - model.material.maps[TEXMAP_DIFFUSE].color = tint; // TODO: Multiply tint color by diffuse color? + model.material.maps[MAP_DIFFUSE].color = tint; // TODO: Multiply tint color by diffuse color? rlDrawMesh(model.mesh, model.material, model.transform); } @@ -2244,16 +2239,16 @@ static Material LoadMTL(const char *fileName) case 'd': // Kd float float float Diffuse color (RGB) { sscanf(buffer, "Kd %f %f %f", &color.x, &color.y, &color.z); - material.maps[TEXMAP_DIFFUSE].color.r = (unsigned char)(color.x*255); - material.maps[TEXMAP_DIFFUSE].color.g = (unsigned char)(color.y*255); - material.maps[TEXMAP_DIFFUSE].color.b = (unsigned char)(color.z*255); + material.maps[MAP_DIFFUSE].color.r = (unsigned char)(color.x*255); + material.maps[MAP_DIFFUSE].color.g = (unsigned char)(color.y*255); + material.maps[MAP_DIFFUSE].color.b = (unsigned char)(color.z*255); } break; case 's': // Ks float float float Specular color (RGB) { sscanf(buffer, "Ks %f %f %f", &color.x, &color.y, &color.z); - material.maps[TEXMAP_SPECULAR].color.r = (unsigned char)(color.x*255); - material.maps[TEXMAP_SPECULAR].color.g = (unsigned char)(color.y*255); - material.maps[TEXMAP_SPECULAR].color.b = (unsigned char)(color.z*255); + material.maps[MAP_SPECULAR].color.r = (unsigned char)(color.x*255); + material.maps[MAP_SPECULAR].color.g = (unsigned char)(color.y*255); + material.maps[MAP_SPECULAR].color.b = (unsigned char)(color.z*255); } break; case 'e': // Ke float float float Emmisive color (RGB) { @@ -2285,12 +2280,12 @@ static Material LoadMTL(const char *fileName) if (buffer[5] == 'd') // map_Kd string Diffuse color texture map. { result = sscanf(buffer, "map_Kd %s", mapFileName); - if (result != EOF) material.maps[TEXMAP_DIFFUSE].tex = LoadTexture(mapFileName); + if (result != EOF) material.maps[MAP_DIFFUSE].texture = LoadTexture(mapFileName); } else if (buffer[5] == 's') // map_Ks string Specular color texture map. { result = sscanf(buffer, "map_Ks %s", mapFileName); - if (result != EOF) material.maps[TEXMAP_SPECULAR].tex = LoadTexture(mapFileName); + if (result != EOF) material.maps[MAP_SPECULAR].texture = LoadTexture(mapFileName); } else if (buffer[5] == 'a') // map_Ka string Ambient color texture map. { @@ -2300,12 +2295,12 @@ static Material LoadMTL(const char *fileName) case 'B': // map_Bump string Bump texture map. { result = sscanf(buffer, "map_Bump %s", mapFileName); - if (result != EOF) material.maps[TEXMAP_NORMAL].tex = LoadTexture(mapFileName); + if (result != EOF) material.maps[MAP_NORMAL].texture = LoadTexture(mapFileName); } break; case 'b': // map_bump string Bump texture map. { result = sscanf(buffer, "map_bump %s", mapFileName); - if (result != EOF) material.maps[TEXMAP_NORMAL].tex = LoadTexture(mapFileName); + if (result != EOF) material.maps[MAP_NORMAL].texture = LoadTexture(mapFileName); } break; case 'd': // map_d string Opacity texture map. { @@ -2320,7 +2315,7 @@ static Material LoadMTL(const char *fileName) { float alpha = 1.0f; sscanf(buffer, "d %f", &alpha); - material.maps[TEXMAP_DIFFUSE].color.a = (unsigned char)(alpha*255); + material.maps[MAP_DIFFUSE].color.a = (unsigned char)(alpha*255); } else if (buffer[1] == 'i') // disp string Displacement map { @@ -2330,13 +2325,13 @@ static Material LoadMTL(const char *fileName) case 'b': // bump string Bump texture map { result = sscanf(buffer, "bump %s", mapFileName); - if (result != EOF) material.maps[TEXMAP_NORMAL].tex = LoadTexture(mapFileName); + if (result != EOF) material.maps[MAP_NORMAL].texture = LoadTexture(mapFileName); } break; case 'T': // Tr float Transparency Tr (alpha). Tr is inverse of d { float ialpha = 0.0f; sscanf(buffer, "Tr %f", &ialpha); - material.maps[TEXMAP_DIFFUSE].color.a = (unsigned char)((1.0f - ialpha)*255); + material.maps[MAP_DIFFUSE].color.a = (unsigned char)((1.0f - ialpha)*255); } break; case 'r': // refl string Reflection texture map diff --git a/src/raylib.h b/src/raylib.h index c84d6ce4..8d93a214 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -292,9 +292,8 @@ #define RAYWHITE CLITERAL{ 245, 245, 245, 255 } // My own White (raylib logo) // Shader and material limits -#define MAX_SHADER_LOCATIONS 32 -#define MAX_MATERIAL_TEXTURE_MAPS 12 -#define MAX_MATERIAL_PARAMS 8 +#define MAX_SHADER_LOCATIONS 32 // Maximum number of predefined locations stored in shader struct +#define MAX_MATERIAL_MAPS 12 // Maximum number of texture maps stored in shader struct //---------------------------------------------------------------------------------- // Structures Definition @@ -405,21 +404,22 @@ typedef struct Camera2D { // Bounding box type typedef struct BoundingBox { - Vector3 min; // minimum vertex box-corner - Vector3 max; // maximum vertex box-corner + Vector3 min; // Minimum vertex box-corner + Vector3 max; // Maximum vertex box-corner } BoundingBox; // Vertex data definning a mesh typedef struct Mesh { - int vertexCount; // number of vertices stored in arrays - int triangleCount; // number of triangles stored (indexed or not) - float *vertices; // vertex position (XYZ - 3 components per vertex) (shader-location = 0) - float *texcoords; // vertex texture coordinates (UV - 2 components per vertex) (shader-location = 1) - float *texcoords2; // vertex second texture coordinates (useful for lightmaps) (shader-location = 5) - float *normals; // vertex normals (XYZ - 3 components per vertex) (shader-location = 2) - float *tangents; // vertex tangents (XYZ - 3 components per vertex) (shader-location = 4) - unsigned char *colors; // vertex colors (RGBA - 4 components per vertex) (shader-location = 3) - unsigned short *indices;// vertex indices (in case vertex data comes indexed) + int vertexCount; // Number of vertices stored in arrays + int triangleCount; // Number of triangles stored (indexed or not) + + float *vertices; // Vertex position (XYZ - 3 components per vertex) (shader-location = 0) + float *texcoords; // Vertex texture coordinates (UV - 2 components per vertex) (shader-location = 1) + float *texcoords2; // Vertex second texture coordinates (useful for lightmaps) (shader-location = 5) + float *normals; // Vertex normals (XYZ - 3 components per vertex) (shader-location = 2) + float *tangents; // Vertex tangents (XYZ - 3 components per vertex) (shader-location = 4) + unsigned char *colors; // Vertex colors (RGBA - 4 components per vertex) (shader-location = 3) + unsigned short *indices;// Vertex indices (in case vertex data comes indexed) unsigned int vaoId; // OpenGL Vertex Array Object id unsigned int vboId[7]; // OpenGL Vertex Buffer Objects id (7 types of vertex data) @@ -427,22 +427,22 @@ typedef struct Mesh { // Shader type (generic) typedef struct Shader { - unsigned int id; // Shader program id - int locs[MAX_SHADER_LOCATIONS]; // Initialized on LoadShader(), set to MAX_SHADER_LOCATIONS + unsigned int id; // Shader program id + int locs[MAX_SHADER_LOCATIONS]; // Shader locations array } Shader; // Material texture map -typedef struct TextureMap { - Texture2D tex; - Color color; - float value; -} TextureMap; +typedef struct MaterialMap { + Texture2D texture; // Material map texture + Color color; // Material map color + float value; // Material map value +} MaterialMap; // Material type (generic) typedef struct Material { - Shader shader; - TextureMap maps[MAX_MATERIAL_TEXTURE_MAPS]; // Initialized on LoadMaterial*(), set to MAX_MATERIAL_TEXTURE_MAPS - float *params; // Initialized on LoadMaterial*(), set to MAX_MATERIAL_PARAMS + Shader shader; // Material shader + MaterialMap maps[MAX_MATERIAL_MAPS]; // Material maps + float *params; // Material generic parameters (if required) } Material; // Model type @@ -526,6 +526,7 @@ typedef enum { LOG_OTHER } LogType; +// Shader location point type typedef enum { LOC_VERTEX_POSITION = 0, LOC_VERTEX_TEXCOORD01, @@ -541,38 +542,39 @@ typedef enum { LOC_COLOR_DIFFUSE, LOC_COLOR_SPECULAR, LOC_COLOR_AMBIENT, - LOC_TEXMAP_ALBEDO, // LOC_TEXMAP_DIFFUSE - LOC_TEXMAP_METALNESS, // LOC_TEXMAP_SPECULAR - LOC_TEXMAP_NORMAL, - LOC_TEXMAP_ROUGHNESS, - LOC_TEXMAP_OCCUSION, - LOC_TEXMAP_EMISSION, - LOC_TEXMAP_HEIGHT, - LOC_TEXMAP_CUBEMAP, - LOC_TEXMAP_IRRADIANCE, - LOC_TEXMAP_PREFILTER, - LOC_TEXMAP_BRDF + LOC_MAP_ALBEDO, // LOC_MAP_DIFFUSE + LOC_MAP_METALNESS, // LOC_MAP_SPECULAR + LOC_MAP_NORMAL, + LOC_MAP_ROUGHNESS, + LOC_MAP_OCCUSION, + LOC_MAP_EMISSION, + LOC_MAP_HEIGHT, + LOC_MAP_CUBEMAP, + LOC_MAP_IRRADIANCE, + LOC_MAP_PREFILTER, + LOC_MAP_BRDF } ShaderLocationIndex; -#define LOC_TEXMAP_DIFFUSE LOC_TEXMAP_ALBEDO -#define LOC_TEXMAP_SPECULAR LOC_TEXMAP_METALNESS +#define LOC_MAP_DIFFUSE LOC_MAP_ALBEDO +#define LOC_MAP_SPECULAR LOC_MAP_METALNESS +// Material map type typedef enum { - TEXMAP_ALBEDO = 0, // TEXMAP_DIFFUSE - TEXMAP_METALNESS = 1, // TEXMAP_SPECULAR - TEXMAP_NORMAL = 2, - TEXMAP_ROUGHNESS = 3, - TEXMAP_OCCLUSION, - TEXMAP_EMISSION, - TEXMAP_HEIGHT, - TEXMAP_CUBEMAP, // NOTE: Uses GL_TEXTURE_CUBE_MAP - TEXMAP_IRRADIANCE, // NOTE: Uses GL_TEXTURE_CUBE_MAP - TEXMAP_PREFILTER, // NOTE: Uses GL_TEXTURE_CUBE_MAP - TEXMAP_BRDF + MAP_ALBEDO = 0, // MAP_DIFFUSE + MAP_METALNESS = 1, // MAP_SPECULAR + MAP_NORMAL = 2, + MAP_ROUGHNESS = 3, + MAP_OCCLUSION, + MAP_EMISSION, + MAP_HEIGHT, + MAP_CUBEMAP, // NOTE: Uses GL_TEXTURE_CUBE_MAP + MAP_IRRADIANCE, // NOTE: Uses GL_TEXTURE_CUBE_MAP + MAP_PREFILTER, // NOTE: Uses GL_TEXTURE_CUBE_MAP + MAP_BRDF } TexmapIndex; -#define TEXMAP_DIFFUSE TEXMAP_ALBEDO -#define TEXMAP_SPECULAR TEXMAP_METALNESS +#define MAP_DIFFUSE MAP_ALBEDO +#define MAP_SPECULAR MAP_METALNESS // Texture formats // NOTE: Support depends on OpenGL version and platform @@ -1037,8 +1039,6 @@ RLAPI void UnloadShader(Shader shader); // Unl RLAPI Shader GetShaderDefault(void); // Get default shader RLAPI Texture2D GetTextureDefault(void); // Get default texture -RLAPI Texture2D rlGenMapCubemap(Texture2D skyHDR, int size); // Generate cubemap texture map from HDR texture - // Shader configuration functions RLAPI int GetShaderLocation(Shader shader, const char *uniformName); // Get shader uniform location RLAPI void SetShaderValue(Shader shader, int uniformLoc, float *value, int size); // Set shader uniform value (float) @@ -1047,6 +1047,12 @@ RLAPI void SetShaderValueMatrix(Shader shader, int uniformLoc, Matrix mat); RLAPI void SetMatrixProjection(Matrix proj); // Set a custom projection matrix (replaces internal projection matrix) RLAPI void SetMatrixModelview(Matrix view); // Set a custom modelview matrix (replaces internal modelview matrix) +// Texture maps generation (PBR) +RLAPI Texture2D GenTextureCubemap(Texture2D skyHDR, int size); // Generate cubemap texture from HDR texture +RLAPI Texture2D GenTextureIrradiance(Texture2D cubemap, int size); // Generate irradiance texture using cubemap data +RLAPI Texture2D GenTexturePrefilter(Texture2D cubemap, int size); // Generate prefilter texture using cubemap data +RLAPI Texture2D GenTextureBRDF(Texture2D cubemap, int size); // Generate BRDF texture using cubemap data + // Shading begin/end functions RLAPI void BeginShaderMode(Shader shader); // Begin custom shader drawing RLAPI void EndShaderMode(void); // End custom shader drawing (use default shader) diff --git a/src/rlgl.c b/src/rlgl.c index 742b0ed5..b9576b9b 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -340,13 +340,13 @@ static Shader LoadShaderDefault(void); // Load default shader (just vertex static void SetShaderDefaultLocations(Shader *shader); // Bind default shader locations (attributes and uniforms) static void UnloadShaderDefault(void); // Unload default shader -static void LoadDefaultBuffers(void); // Load default internal buffers (lines, triangles, quads) -static void UpdateDefaultBuffers(void); // Update default internal buffers (VAOs/VBOs) with vertex data -static void DrawDefaultBuffers(void); // Draw default internal buffers vertex data -static void UnloadDefaultBuffers(void); // Unload default internal buffers vertex data from CPU and GPU +static void LoadBuffersDefault(void); // Load default internal buffers (lines, triangles, quads) +static void UpdateBuffersDefault(void); // Update default internal buffers (VAOs/VBOs) with vertex data +static void DrawBuffersDefault(void); // Draw default internal buffers vertex data +static void UnloadBuffersDefault(void); // Unload default internal buffers vertex data from CPU and GPU -static void RenderCube(void); -static void RenderQuad(void); +static void GenDrawCube(void); // Generate and draw cube +static void GenDrawQuad(void); // Generate and draw quad #if defined(SUPPORT_VR_SIMULATOR) static void SetStereoConfig(VrDeviceInfo info); // Configure stereo rendering (including distortion shader) with HMD device parameters @@ -1219,7 +1219,7 @@ void rlglInit(int width, int height) currentShader = defaultShader; // Init default vertex arrays buffers (lines, triangles, quads) - LoadDefaultBuffers(); + LoadBuffersDefault(); // Init temp vertex buffer, used when transformation required (translate, rotate, scale) tempBuffer = (Vector3 *)malloc(sizeof(Vector3)*TEMP_VERTEX_BUFFER_SIZE); @@ -1288,7 +1288,7 @@ void rlglClose(void) { #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) UnloadShaderDefault(); - UnloadDefaultBuffers(); + UnloadBuffersDefault(); // Delete default white texture glDeleteTextures(1, &whiteTexture); @@ -1306,14 +1306,14 @@ void rlglDraw(void) //for (int i = 0; i < modelsCount; i++) rlDrawMesh(models[i]->mesh, models[i]->material, models[i]->transform); // NOTE: Default buffers upload and draw - UpdateDefaultBuffers(); - DrawDefaultBuffers(); // NOTE: Stereo rendering is checked inside + UpdateBuffersDefault(); + DrawBuffersDefault(); // NOTE: Stereo rendering is checked inside #endif } // Load OpenGL extensions // NOTE: External loader function could be passed as a pointer -void rlglLoadExtensions(void *loader) +void rlLoadExtensions(void *loader) { #if defined(GRAPHICS_API_OPENGL_21) || defined(GRAPHICS_API_OPENGL_33) // NOTE: glad is generated and contains only required OpenGL 3.3 Core extensions (and lower versions) @@ -1718,422 +1718,6 @@ void rlGenerateMipmaps(Texture2D *texture) glBindTexture(GL_TEXTURE_2D, 0); } -// Generated cubemap texture -Texture2D rlGenMapCubemap(Texture2D skyHDR, int size) -{ - Texture2D cubemap = { 0 }; - - #define PATH_CUBEMAP_VS "resources/shaders/cubemap.vs" // Path to equirectangular to cubemap vertex shader - #define PATH_CUBEMAP_FS "resources/shaders/cubemap.fs" // Path to equirectangular to cubemap fragment shader - - Shader shader = LoadShader(PATH_CUBEMAP_VS, PATH_CUBEMAP_FS); - - // Get cubemap shader locations - int projectionLoc = GetShaderLocation(shader, "projection"); - int viewLoc = GetShaderLocation(shader, "view"); - int texmapLoc = GetShaderLocation(shader, "equirectangularMap"); - - SetShaderValuei(shader, texmapLoc, (int[1]){ 0 }, 1); // Set default active texture to 0 - - // Set up depth face culling and cubemap seamless - glDisable(GL_CULL_FACE); - glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); - - // Setup framebuffer - unsigned int fbo, rbo; - glGenFramebuffers(1, &fbo); - glGenRenderbuffers(1, &rbo); - glBindFramebuffer(GL_FRAMEBUFFER, fbo); - glBindRenderbuffer(GL_RENDERBUFFER, rbo); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, size, size); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbo); - - // Set up cubemap to render and attach to framebuffer - // NOTE: faces are stored with 16 bit floating point values - glGenTextures(1, &cubemap.id); - glBindTexture(GL_TEXTURE_CUBE_MAP, cubemap.id); - for (unsigned int i = 0; i < 6; i++) - glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB16F, size, size, 0, GL_RGB, GL_FLOAT, NULL); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - // Create projection (transposed) and different views for each face - Matrix fboProjection = MatrixPerspective(90.0, 1.0, 0.01, 1000.0); - MatrixTranspose(&fboProjection); - Matrix fboViews[6] = { - MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 1.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), - MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ -1.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), - MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, 1.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, 1.0f }), - MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, -1.0f }), - MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, 1.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), - MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, -1.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }) - }; - - // Convert HDR equirectangular environment map to cubemap equivalent - glUseProgram(shader.id); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, skyHDR.id); - SetShaderValueMatrix(shader, projectionLoc, fboProjection); - - // Note: don't forget to configure the viewport to the capture dimensions - glViewport(0, 0, size, size); - glBindFramebuffer(GL_FRAMEBUFFER, fbo); - - for (unsigned int i = 0; i < 6; i++) - { - SetShaderValueMatrix(shader, viewLoc, fboViews[i]); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, cubemap.id, 0); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - RenderCube(); - } - - // Unbind framebuffer and textures - glBindFramebuffer(GL_FRAMEBUFFER, 0); - - UnloadShader(shader); - - cubemap.width = size; - cubemap.height = size; - - // Reset viewport dimensions to default - glViewport(0, 0, GetScreenWidth(), GetScreenHeight()); - //glEnable(GL_CULL_FACE); - - return cubemap; -} - -Texture2D rlGenMapIrradiance(Texture2D cubemap, int size) -{ - Texture2D irradiance = { 0 }; - - #define PATH_SKYBOX_VS "resources/shaders/skybox.vs" // Path to skybox vertex shader - #define PATH_IRRADIANCE_FS "resources/shaders/irradiance.fs" // Path to irradiance (GI) calculation fragment shader - - Shader shader = LoadShader(PATH_SKYBOX_VS, PATH_IRRADIANCE_FS); - - // Get irradiance shader locations - int projectionLoc = GetShaderLocation(shader, "projection"); - int viewLoc = GetShaderLocation(shader, "view"); - int texmapLoc = GetShaderLocation(shader, "environmentMap"); - - // Set up shaders constant values - SetShaderValuei(shader, texmapLoc, (int[1]){ 0 }, 1); - - // Setup framebuffer - unsigned int fbo, rbo; - glGenFramebuffers(1, &fbo); - glGenRenderbuffers(1, &rbo); - glBindFramebuffer(GL_FRAMEBUFFER, fbo); - glBindRenderbuffer(GL_RENDERBUFFER, rbo); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, size, size); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbo); - - // Create an irradiance cubemap, and re-scale capture FBO to irradiance scale - glGenTextures(1, &irradiance.id); - glBindTexture(GL_TEXTURE_CUBE_MAP, irradiance.id); - for (unsigned int i = 0; i < 6; i++) - glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB16F, size, size, 0, GL_RGB, GL_FLOAT, NULL); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - // Create projection (transposed) and different views for each face - Matrix fboProjection = MatrixPerspective(90.0, 1.0, 0.01, 1000.0); - MatrixTranspose(&fboProjection); - Matrix fboViews[6] = { - MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 1.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), - MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ -1.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), - MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, 1.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, 1.0f }), - MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, -1.0f }), - MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, 1.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), - MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, -1.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }) - }; - - // Solve diffuse integral by convolution to create an irradiance cubemap - glUseProgram(shader.id); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_CUBE_MAP, cubemap.id); - SetShaderValueMatrix(shader, projectionLoc, fboProjection); - - // Note: don't forget to configure the viewport to the capture dimensions - glViewport(0, 0, size, size); - glBindFramebuffer(GL_FRAMEBUFFER, fbo); - - for (unsigned int i = 0; i < 6; i++) - { - SetShaderValueMatrix(shader, viewLoc, fboViews[i]); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, irradiance.id, 0); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - RenderCube(); - } - - // Unbind framebuffer and textures - glBindFramebuffer(GL_FRAMEBUFFER, 0); - - UnloadShader(shader); - - irradiance.width = size; - irradiance.height = size; - - return irradiance; -} - -Texture2D rlGenMapPrefilter(Texture2D cubemap, int size) -{ - Texture2D prefilter = { 0 }; - - #define PATH_SKYBOX_VS "resources/shaders/skybox.vs" // Path to skybox vertex shader - #define PATH_PREFILTER_FS "resources/shaders/prefilter.fs" // Path to reflection prefilter calculation fragment shader - - Shader shader = LoadShader(PATH_SKYBOX_VS, PATH_PREFILTER_FS); - - // Get prefilter shader locations - int projectionLoc = GetShaderLocation(shader, "projection"); - int viewLoc = GetShaderLocation(shader, "view"); - int roughnessLoc = GetShaderLocation(shader, "roughness"); - int texmapLoc = GetShaderLocation(shader, "environmentMap"); - - SetShaderValuei(shader, texmapLoc, (int[1]){ 0 }, 1); - - // Setup framebuffer - unsigned int fbo, rbo; - glGenFramebuffers(1, &fbo); - glGenRenderbuffers(1, &rbo); - glBindFramebuffer(GL_FRAMEBUFFER, fbo); - glBindRenderbuffer(GL_RENDERBUFFER, rbo); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, size, size); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbo); - - // Create a prefiltered HDR environment map - glGenTextures(1, &prefilter.id); - glBindTexture(GL_TEXTURE_CUBE_MAP, prefilter.id); - for (unsigned int i = 0; i < 6; i++) - glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB16F, size, size, 0, GL_RGB, GL_FLOAT, NULL); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - // Generate mipmaps for the prefiltered HDR texture - glGenerateMipmap(GL_TEXTURE_CUBE_MAP); - - // Create projection (transposed) and different views for each face - Matrix fboProjection = MatrixPerspective(90.0, 1.0, 0.01, 1000.0); - MatrixTranspose(&fboProjection); - Matrix fboViews[6] = { - MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 1.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), - MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ -1.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), - MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, 1.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, 1.0f }), - MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, -1.0f }), - MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, 1.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), - MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, -1.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }) - }; - - // Prefilter HDR and store data into mipmap levels - glUseProgram(shader.id); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_CUBE_MAP, cubemap.id); - SetShaderValueMatrix(shader, projectionLoc, fboProjection); - - glBindFramebuffer(GL_FRAMEBUFFER, fbo); - - #define MAX_MIPMAP_LEVELS 5 // Max number of prefilter texture mipmaps - - for (unsigned int mip = 0; mip < MAX_MIPMAP_LEVELS; mip++) - { - // Resize framebuffer according to mip-level size. - unsigned int mipWidth = size*powf(0.5f, mip); - unsigned int mipHeight = size*powf(0.5f, mip); - - glBindRenderbuffer(GL_RENDERBUFFER, rbo); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, mipWidth, mipHeight); - glViewport(0, 0, mipWidth, mipHeight); - - float roughness = (float)mip/(float)(MAX_MIPMAP_LEVELS - 1); - glUniform1f(roughnessLoc, roughness); - - for (unsigned int i = 0; i < 6; ++i) - { - SetShaderValueMatrix(shader, viewLoc, fboViews[i]); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, prefilter.id, mip); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - RenderCube(); - } - } - - // Unbind framebuffer and textures - glBindFramebuffer(GL_FRAMEBUFFER, 0); - - UnloadShader(shader); - - prefilter.width = size; - prefilter.height = size; - - return prefilter; -} - -Texture2D rlGenMapBRDF(Texture2D cubemap, int size) -{ - Texture2D brdf = { 0 }; - - #define PATH_BRDF_VS "resources/shaders/brdf.vs" // Path to bidirectional reflectance distribution function vertex shader - #define PATH_BRDF_FS "resources/shaders/brdf.fs" // Path to bidirectional reflectance distribution function fragment shader - - Shader shader = LoadShader(PATH_BRDF_VS, PATH_BRDF_FS); - - // Generate BRDF convolution texture - glGenTextures(1, &brdf.id); - glBindTexture(GL_TEXTURE_2D, brdf.id); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RG16F, size, size, 0, GL_RG, GL_FLOAT, 0); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - // Render BRDF LUT into a quad using FBO - unsigned int fbo, rbo; - glGenFramebuffers(1, &fbo); - glGenRenderbuffers(1, &rbo); - glBindFramebuffer(GL_FRAMEBUFFER, fbo); - glBindRenderbuffer(GL_RENDERBUFFER, rbo); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, size, size); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, brdf.id, 0); - - rlViewport(0, 0, size, size); - glUseProgram(shader.id); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - RenderQuad(); - - // Unbind framebuffer and textures - glBindFramebuffer(GL_FRAMEBUFFER, 0); - - UnloadShader(shader); - - brdf.width = size; - brdf.height = size; - - return brdf; -} - -// Renders a 1x1 3D cube in NDC -GLuint cubeVAO = 0; -GLuint cubeVBO = 0; -static void RenderCube(void) -{ - // Initialize if it is not yet - if (cubeVAO == 0) - { - GLfloat vertices[] = { - -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, - 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, - 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, - 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, - -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, - -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, - -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, - 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, - 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, - 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, - -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, - -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, - -1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, - -1.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, - -1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, - -1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, - -1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, - -1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, - 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, - 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, - 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, - 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, - 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, - 1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, - -1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, - 1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f, - 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, - 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, - -1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, - -1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, - -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, - 1.0f, 1.0f , 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, - 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, - 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, - -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, - -1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f - }; - - // Set up cube VAO - glGenVertexArrays(1, &cubeVAO); - glGenBuffers(1, &cubeVBO); - - // Fill buffer - glBindBuffer(GL_ARRAY_BUFFER, cubeVBO); - glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); - - // Link vertex attributes - glBindVertexArray(cubeVAO); - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), (GLvoid*)0); - glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), (GLvoid*)(3*sizeof(GLfloat))); - glEnableVertexAttribArray(2); - glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), (GLvoid*)(6*sizeof(GLfloat))); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindVertexArray(0); - } - - // Render cube - glBindVertexArray(cubeVAO); - glDrawArrays(GL_TRIANGLES, 0, 36); - glBindVertexArray(0); -} - -// Renders a 1x1 XY quad in NDC -GLuint quadVAO = 0; -GLuint quadVBO; -static void RenderQuad(void) -{ - // Initialize if it is not yet - if (quadVAO == 0) - { - GLfloat quadVertices[] = { - // Positions // Texture Coords - -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, - -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, - 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, - 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, - }; - - // Set up plane VAO - glGenVertexArrays(1, &quadVAO); - glGenBuffers(1, &quadVBO); - glBindVertexArray(quadVAO); - - // Fill buffer - glBindBuffer(GL_ARRAY_BUFFER, quadVBO); - glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), &quadVertices, GL_STATIC_DRAW); - - // Link vertex attributes - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (GLvoid*)0); - glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (GLvoid*)(3*sizeof(GLfloat))); - } - - // Render quad - glBindVertexArray(quadVAO); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - glBindVertexArray(0); -} - - - // Upload vertex data into a VAO (if supported) and VBO // TODO: Check if mesh has already been loaded in GPU void rlLoadMesh(Mesh *mesh, bool dynamic) @@ -2339,7 +1923,7 @@ void rlDrawMesh(Mesh mesh, Material material, Matrix transform) { #if defined(GRAPHICS_API_OPENGL_11) glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, material.maps[TEXMAP_DIFFUSE].tex.id); + glBindTexture(GL_TEXTURE_2D, material.maps[MAP_DIFFUSE].tex.id); // NOTE: On OpenGL 1.1 we use Vertex Arrays to draw model glEnableClientState(GL_VERTEX_ARRAY); // Enable vertex array @@ -2381,17 +1965,17 @@ void rlDrawMesh(Mesh mesh, Material material, Matrix transform) SetShaderValueMatrix(material.shader, material.shader.locs[LOC_MATRIX_MODEL], transform); // Upload to shader material.colDiffuse - glUniform4f(material.shader.locs[LOC_COLOR_DIFFUSE], (float)material.maps[TEXMAP_DIFFUSE].color.r/255, - (float)material.maps[TEXMAP_DIFFUSE].color.g/255, - (float)material.maps[TEXMAP_DIFFUSE].color.b/255, - (float)material.maps[TEXMAP_DIFFUSE].color.a/255); + glUniform4f(material.shader.locs[LOC_COLOR_DIFFUSE], (float)material.maps[MAP_DIFFUSE].color.r/255, + (float)material.maps[MAP_DIFFUSE].color.g/255, + (float)material.maps[MAP_DIFFUSE].color.b/255, + (float)material.maps[MAP_DIFFUSE].color.a/255); // Upload to shader material.colSpecular (if available) if (material.shader.locs[LOC_COLOR_SPECULAR] != -1) - glUniform4f(material.shader.locs[LOC_COLOR_SPECULAR], (float)material.maps[TEXMAP_SPECULAR].color.r/255, - (float)material.maps[TEXMAP_SPECULAR].color.g/255, - (float)material.maps[TEXMAP_SPECULAR].color.b/255, - (float)material.maps[TEXMAP_SPECULAR].color.a/255); + glUniform4f(material.shader.locs[LOC_COLOR_SPECULAR], (float)material.maps[MAP_SPECULAR].color.r/255, + (float)material.maps[MAP_SPECULAR].color.g/255, + (float)material.maps[MAP_SPECULAR].color.b/255, + (float)material.maps[MAP_SPECULAR].color.a/255); // At this point the modelview matrix just contains the view matrix (camera) // That's because Begin3dMode() sets it an no model-drawing function modifies it, all use rlPushMatrix() and rlPopMatrix() @@ -2403,15 +1987,15 @@ void rlDrawMesh(Mesh mesh, Material material, Matrix transform) //----------------------------------------------------- // Bind active texture maps (if available) - for (int i = 0; i < MAX_MATERIAL_TEXTURE_MAPS; i++) + for (int i = 0; i < MAX_MATERIAL_MAPS; i++) { - if (material.maps[i].tex.id > 0) + if (material.maps[i].texture.id > 0) { glActiveTexture(GL_TEXTURE0 + i); - if ((i == TEXMAP_IRRADIANCE) || (i == TEXMAP_PREFILTER) || (i == TEXMAP_CUBEMAP)) glBindTexture(GL_TEXTURE_CUBE_MAP, material.maps[i].tex.id); - else glBindTexture(GL_TEXTURE_2D, material.maps[i].tex.id); + if ((i == MAP_IRRADIANCE) || (i == MAP_PREFILTER) || (i == MAP_CUBEMAP)) glBindTexture(GL_TEXTURE_CUBE_MAP, material.maps[i].texture.id); + else glBindTexture(GL_TEXTURE_2D, material.maps[i].texture.id); - glUniform1i(material.shader.locs[LOC_TEXMAP_DIFFUSE + i], i); + glUniform1i(material.shader.locs[LOC_MAP_DIFFUSE + i], i); } } @@ -2500,10 +2084,10 @@ void rlDrawMesh(Mesh mesh, Material material, Matrix transform) } // Unbind all binded texture maps - for (int i = 0; i < MAX_MATERIAL_TEXTURE_MAPS; i++) + for (int i = 0; i < MAX_MATERIAL_MAPS; i++) { glActiveTexture(GL_TEXTURE0 + i); // Set shader active texture - if ((i == TEXMAP_IRRADIANCE) || (i == TEXMAP_PREFILTER) || (i == TEXMAP_CUBEMAP)) glBindTexture(GL_TEXTURE_CUBE_MAP, 0); + if ((i == MAP_IRRADIANCE) || (i == MAP_PREFILTER) || (i == MAP_CUBEMAP)) glBindTexture(GL_TEXTURE_CUBE_MAP, 0); else glBindTexture(GL_TEXTURE_2D, 0); // Unbind current active texture } @@ -2738,6 +2322,17 @@ Texture2D GetTextureDefault(void) return texture; } +// Get default shader +Shader GetShaderDefault(void) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + return defaultShader; +#else + Shader shader = { 0 }; + return shader; +#endif +} + // Load text data from file // NOTE: text chars array should be freed manually char *LoadText(const char *fileName) @@ -2860,17 +2455,6 @@ void EndShaderMode(void) #endif } -// Get default shader -Shader GetShaderDefault(void) -{ -#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - return defaultShader; -#else - Shader shader = { 0 }; - return shader; -#endif -} - // Get shader uniform location int GetShaderLocation(Shader shader, const char *uniformName) { @@ -2900,48 +2484,363 @@ void SetShaderValue(Shader shader, int uniformLoc, float *value, int size) #endif } -// Set shader uniform value (int) -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) +{ +#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(LOG_WARNING, "Shader value int array size not supported"); + + //glUseProgram(0); +#endif +} + +// Set shader uniform value (matrix 4x4) +void SetShaderValueMatrix(Shader shader, int uniformLoc, Matrix mat) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + glUseProgram(shader.id); + + glUniformMatrix4fv(uniformLoc, 1, false, MatrixToFloat(mat)); + + //glUseProgram(0); +#endif +} + +// Set a custom projection matrix (replaces internal projection matrix) +void SetMatrixProjection(Matrix proj) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + projection = proj; +#endif +} + +// Set a custom modelview matrix (replaces internal modelview matrix) +void SetMatrixModelview(Matrix view) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + modelview = view; +#endif +} + +// Generate cubemap texture from HDR texture +Texture2D GenTextureCubemap(Texture2D skyHDR, int size) +{ + Texture2D cubemap = { 0 }; + + #define PATH_CUBEMAP_VS "resources/shaders/cubemap.vs" // Path to equirectangular to cubemap vertex shader + #define PATH_CUBEMAP_FS "resources/shaders/cubemap.fs" // Path to equirectangular to cubemap fragment shader + + Shader shader = LoadShader(PATH_CUBEMAP_VS, PATH_CUBEMAP_FS); + + // Get cubemap shader locations + int projectionLoc = GetShaderLocation(shader, "projection"); + int viewLoc = GetShaderLocation(shader, "view"); + int texmapLoc = GetShaderLocation(shader, "equirectangularMap"); + + SetShaderValuei(shader, texmapLoc, (int[1]){ 0 }, 1); // Set default active texture to 0 + + // Set up depth face culling and cubemap seamless + glDisable(GL_CULL_FACE); + glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); + + // Setup framebuffer + unsigned int fbo, rbo; + glGenFramebuffers(1, &fbo); + glGenRenderbuffers(1, &rbo); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glBindRenderbuffer(GL_RENDERBUFFER, rbo); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, size, size); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbo); + + // Set up cubemap to render and attach to framebuffer + // NOTE: faces are stored with 16 bit floating point values + glGenTextures(1, &cubemap.id); + glBindTexture(GL_TEXTURE_CUBE_MAP, cubemap.id); + for (unsigned int i = 0; i < 6; i++) + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB16F, size, size, 0, GL_RGB, GL_FLOAT, NULL); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + // Create projection (transposed) and different views for each face + Matrix fboProjection = MatrixPerspective(90.0, 1.0, 0.01, 1000.0); + MatrixTranspose(&fboProjection); + Matrix fboViews[6] = { + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 1.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ -1.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, 1.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, 1.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, -1.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, 1.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, -1.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }) + }; + + // Convert HDR equirectangular environment map to cubemap equivalent + glUseProgram(shader.id); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, skyHDR.id); + SetShaderValueMatrix(shader, projectionLoc, fboProjection); + + // Note: don't forget to configure the viewport to the capture dimensions + glViewport(0, 0, size, size); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + + for (unsigned int i = 0; i < 6; i++) + { + SetShaderValueMatrix(shader, viewLoc, fboViews[i]); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, cubemap.id, 0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + GenDrawCube(); + } + + // Unbind framebuffer and textures + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + // Reset viewport dimensions to default + glViewport(0, 0, GetScreenWidth(), GetScreenHeight()); + //glEnable(GL_CULL_FACE); + + UnloadShader(shader); + + cubemap.width = size; + cubemap.height = size; + + return cubemap; +} + +// Generate irradiance texture using cubemap data +Texture2D GenTextureIrradiance(Texture2D cubemap, int size) +{ + Texture2D irradiance = { 0 }; + + #define PATH_SKYBOX_VS "resources/shaders/skybox.vs" // Path to skybox vertex shader + #define PATH_IRRADIANCE_FS "resources/shaders/irradiance.fs" // Path to irradiance (GI) calculation fragment shader + + Shader shader = LoadShader(PATH_SKYBOX_VS, PATH_IRRADIANCE_FS); + + // Get irradiance shader locations + int projectionLoc = GetShaderLocation(shader, "projection"); + int viewLoc = GetShaderLocation(shader, "view"); + int texmapLoc = GetShaderLocation(shader, "environmentMap"); + + // Set up shaders constant values + SetShaderValuei(shader, texmapLoc, (int[1]){ 0 }, 1); + + // Setup framebuffer + unsigned int fbo, rbo; + glGenFramebuffers(1, &fbo); + glGenRenderbuffers(1, &rbo); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glBindRenderbuffer(GL_RENDERBUFFER, rbo); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, size, size); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbo); + + // Create an irradiance cubemap, and re-scale capture FBO to irradiance scale + glGenTextures(1, &irradiance.id); + glBindTexture(GL_TEXTURE_CUBE_MAP, irradiance.id); + for (unsigned int i = 0; i < 6; i++) + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB16F, size, size, 0, GL_RGB, GL_FLOAT, NULL); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + // Create projection (transposed) and different views for each face + Matrix fboProjection = MatrixPerspective(90.0, 1.0, 0.01, 1000.0); + MatrixTranspose(&fboProjection); + Matrix fboViews[6] = { + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 1.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ -1.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, 1.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, 1.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, -1.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, 1.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, -1.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }) + }; + + // Solve diffuse integral by convolution to create an irradiance cubemap + glUseProgram(shader.id); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_CUBE_MAP, cubemap.id); + SetShaderValueMatrix(shader, projectionLoc, fboProjection); + + // Note: don't forget to configure the viewport to the capture dimensions + glViewport(0, 0, size, size); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + + for (unsigned int i = 0; i < 6; i++) + { + SetShaderValueMatrix(shader, viewLoc, fboViews[i]); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, irradiance.id, 0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + GenDrawCube(); + } + + // Unbind framebuffer and textures + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + // Reset viewport dimensions to default + glViewport(0, 0, GetScreenWidth(), GetScreenHeight()); + + UnloadShader(shader); + + irradiance.width = size; + irradiance.height = size; + + return irradiance; +} + +// Generate prefilter texture using cubemap data +Texture2D GenTexturePrefilter(Texture2D cubemap, int size) { -#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + Texture2D prefilter = { 0 }; + + #define PATH_SKYBOX_VS "resources/shaders/skybox.vs" // Path to skybox vertex shader + #define PATH_PREFILTER_FS "resources/shaders/prefilter.fs" // Path to reflection prefilter calculation fragment shader + + Shader shader = LoadShader(PATH_SKYBOX_VS, PATH_PREFILTER_FS); + + // Get prefilter shader locations + int projectionLoc = GetShaderLocation(shader, "projection"); + int viewLoc = GetShaderLocation(shader, "view"); + int roughnessLoc = GetShaderLocation(shader, "roughness"); + int texmapLoc = GetShaderLocation(shader, "environmentMap"); + + SetShaderValuei(shader, texmapLoc, (int[1]){ 0 }, 1); + + // Setup framebuffer + unsigned int fbo, rbo; + glGenFramebuffers(1, &fbo); + glGenRenderbuffers(1, &rbo); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glBindRenderbuffer(GL_RENDERBUFFER, rbo); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, size, size); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbo); + + // Create a prefiltered HDR environment map + glGenTextures(1, &prefilter.id); + glBindTexture(GL_TEXTURE_CUBE_MAP, prefilter.id); + for (unsigned int i = 0; i < 6; i++) + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB16F, size, size, 0, GL_RGB, GL_FLOAT, NULL); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + // Generate mipmaps for the prefiltered HDR texture + glGenerateMipmap(GL_TEXTURE_CUBE_MAP); + + // Create projection (transposed) and different views for each face + Matrix fboProjection = MatrixPerspective(90.0, 1.0, 0.01, 1000.0); + MatrixTranspose(&fboProjection); + Matrix fboViews[6] = { + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 1.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ -1.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, 1.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, 1.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, -1.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, 1.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, -1.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }) + }; + + // Prefilter HDR and store data into mipmap levels glUseProgram(shader.id); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_CUBE_MAP, cubemap.id); + SetShaderValueMatrix(shader, projectionLoc, fboProjection); - 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(LOG_WARNING, "Shader value int array size not supported"); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + + #define MAX_MIPMAP_LEVELS 5 // Max number of prefilter texture mipmaps - //glUseProgram(0); -#endif -} + for (unsigned int mip = 0; mip < MAX_MIPMAP_LEVELS; mip++) + { + // Resize framebuffer according to mip-level size. + unsigned int mipWidth = size*powf(0.5f, mip); + unsigned int mipHeight = size*powf(0.5f, mip); + + glBindRenderbuffer(GL_RENDERBUFFER, rbo); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, mipWidth, mipHeight); + glViewport(0, 0, mipWidth, mipHeight); -// Set shader uniform value (matrix 4x4) -void SetShaderValueMatrix(Shader shader, int uniformLoc, Matrix mat) -{ -#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - glUseProgram(shader.id); + float roughness = (float)mip/(float)(MAX_MIPMAP_LEVELS - 1); + glUniform1f(roughnessLoc, roughness); - glUniformMatrix4fv(uniformLoc, 1, false, MatrixToFloat(mat)); + for (unsigned int i = 0; i < 6; ++i) + { + SetShaderValueMatrix(shader, viewLoc, fboViews[i]); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, prefilter.id, mip); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + GenDrawCube(); + } + } - //glUseProgram(0); -#endif + // Unbind framebuffer and textures + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + // Reset viewport dimensions to default + glViewport(0, 0, GetScreenWidth(), GetScreenHeight()); + + UnloadShader(shader); + + prefilter.width = size; + prefilter.height = size; + + return prefilter; } -// Set a custom projection matrix (replaces internal projection matrix) -void SetMatrixProjection(Matrix proj) +// Generate BRDF texture using cubemap data +Texture2D GenTextureBRDF(Texture2D cubemap, int size) { -#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - projection = proj; -#endif -} + Texture2D brdf = { 0 }; + + #define PATH_BRDF_VS "resources/shaders/brdf.vs" // Path to bidirectional reflectance distribution function vertex shader + #define PATH_BRDF_FS "resources/shaders/brdf.fs" // Path to bidirectional reflectance distribution function fragment shader + + Shader shader = LoadShader(PATH_BRDF_VS, PATH_BRDF_FS); + + // Generate BRDF convolution texture + glGenTextures(1, &brdf.id); + glBindTexture(GL_TEXTURE_2D, brdf.id); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RG16F, size, size, 0, GL_RG, GL_FLOAT, 0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); -// Set a custom modelview matrix (replaces internal modelview matrix) -void SetMatrixModelview(Matrix view) -{ -#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - modelview = view; -#endif + // Render BRDF LUT into a quad using FBO + unsigned int fbo, rbo; + glGenFramebuffers(1, &fbo); + glGenRenderbuffers(1, &rbo); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glBindRenderbuffer(GL_RENDERBUFFER, rbo); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, size, size); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, brdf.id, 0); + + glViewport(0, 0, size, size); + glUseProgram(shader.id); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + GenDrawQuad(); + + // Unbind framebuffer and textures + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + // Reset viewport dimensions to default + glViewport(0, 0, GetScreenWidth(), GetScreenHeight()); + + UnloadShader(shader); + + brdf.width = size; + brdf.height = size; + + return brdf; } // Begin blending mode (alpha, additive, multiplied) @@ -3182,8 +3081,8 @@ void EndVrDrawing(void) rlDisableTexture(); // Update and draw render texture fbo with distortion to backbuffer - UpdateDefaultBuffers(); - DrawDefaultBuffers(); + UpdateBuffersDefault(); + DrawBuffersDefault(); // Restore defaultShader currentShader = defaultShader; @@ -3452,7 +3351,7 @@ static Shader LoadShaderDefault(void) // Get handles to GLSL uniform locations shader.locs[LOC_MATRIX_MVP] = glGetUniformLocation(shader.id, "mvpMatrix"); shader.locs[LOC_COLOR_DIFFUSE] = glGetUniformLocation(shader.id, "colDiffuse"); - shader.locs[LOC_TEXMAP_DIFFUSE] = glGetUniformLocation(shader.id, "texture0"); + shader.locs[LOC_MAP_DIFFUSE] = glGetUniformLocation(shader.id, "texture0"); } else TraceLog(LOG_WARNING, "[SHDR ID %i] Default shader could not be loaded", shader.id); @@ -3484,9 +3383,9 @@ static void SetShaderDefaultLocations(Shader *shader) // Get handles to GLSL uniform locations (fragment shader) shader->locs[LOC_COLOR_DIFFUSE] = glGetUniformLocation(shader->id, "colDiffuse"); - shader->locs[LOC_TEXMAP_DIFFUSE] = glGetUniformLocation(shader->id, "texture0"); - shader->locs[LOC_TEXMAP_NORMAL] = glGetUniformLocation(shader->id, "texture1"); - shader->locs[LOC_TEXMAP_SPECULAR] = glGetUniformLocation(shader->id, "texture2"); + shader->locs[LOC_MAP_DIFFUSE] = glGetUniformLocation(shader->id, "texture0"); + shader->locs[LOC_MAP_NORMAL] = glGetUniformLocation(shader->id, "texture1"); + shader->locs[LOC_MAP_SPECULAR] = glGetUniformLocation(shader->id, "texture2"); // TODO: Try to find all expected/recognized shader locations (predefined names, must be documented) } @@ -3504,7 +3403,7 @@ static void UnloadShaderDefault(void) } // Load default internal buffers (lines, triangles, quads) -static void LoadDefaultBuffers(void) +static void LoadBuffersDefault(void) { // [CPU] Allocate and initialize float array buffers to store vertex data (lines, triangles, quads) //-------------------------------------------------------------------------------------------- @@ -3677,7 +3576,7 @@ static void LoadDefaultBuffers(void) // Update default internal buffers (VAOs/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 re-update GPU arrays (change flag required) -static void UpdateDefaultBuffers(void) +static void UpdateBuffersDefault(void) { // Update lines vertex buffers if (lines.vCounter > 0) @@ -3747,7 +3646,7 @@ static void UpdateDefaultBuffers(void) // Draw default internal buffers vertex data // NOTE: We draw in this order: lines, triangles, quads -static void DrawDefaultBuffers() +static void DrawBuffersDefault() { Matrix matProjection = projection; Matrix matModelView = modelview; @@ -3773,7 +3672,7 @@ static void DrawDefaultBuffers() glUniformMatrix4fv(currentShader.locs[LOC_MATRIX_MVP], 1, false, MatrixToFloat(matMVP)); glUniform4f(currentShader.locs[LOC_COLOR_DIFFUSE], 1.0f, 1.0f, 1.0f, 1.0f); - glUniform1i(currentShader.locs[LOC_TEXMAP_DIFFUSE], 0); + glUniform1i(currentShader.locs[LOC_MAP_DIFFUSE], 0); // NOTE: Additional map textures not considered for default buffers drawing } @@ -3897,10 +3796,10 @@ static void DrawDefaultBuffers() glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); } - glBindTexture(GL_TEXTURE_2D, 0); // Unbind textures + glBindTexture(GL_TEXTURE_2D, 0); // Unbind textures } - if (vaoSupported) glBindVertexArray(0); // Unbind VAO + if (vaoSupported) glBindVertexArray(0); // Unbind VAO glUseProgram(0); // Unbind shader program } @@ -3928,7 +3827,7 @@ static void DrawDefaultBuffers() } // Unload default internal buffers vertex data from CPU and GPU -static void UnloadDefaultBuffers(void) +static void UnloadBuffersDefault(void) { // Unbind everything if (vaoSupported) glBindVertexArray(0); @@ -3970,6 +3869,120 @@ static void UnloadDefaultBuffers(void) free(quads.indices); } +// Renders a 1x1 XY quad in NDC +static void GenDrawQuad(void) +{ + unsigned int quadVAO = 0; + unsigned int quadVBO = 0; + + float vertices[] = { + // Positions // Texture Coords + -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, + -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, + 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, + 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, + }; + + // Set up plane VAO + glGenVertexArrays(1, &quadVAO); + glGenBuffers(1, &quadVBO); + glBindVertexArray(quadVAO); + + // Fill buffer + glBindBuffer(GL_ARRAY_BUFFER, quadVBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), &vertices, GL_STATIC_DRAW); + + // Link vertex attributes + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (GLvoid*)0); + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (GLvoid*)(3*sizeof(GLfloat))); + + // Draw quad + glBindVertexArray(quadVAO); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + glBindVertexArray(0); + + glDeleteBuffers(1, &quadVBO); + glDeleteVertexArrays(1, &quadVAO); +} + +// Renders a 1x1 3D cube in NDC +GLuint cubeVAO = 0; +GLuint cubeVBO = 0; +static void GenDrawCube(void) +{ + // Lazy initialization + if (cubeVAO == 0) + { + GLfloat vertices[] = { + -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, + 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, + 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, + 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, + -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, + -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, + -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, + 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, + 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, + -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, + -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, + -1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, + -1.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, + -1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, + -1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, + -1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, + -1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, + 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, + 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, + 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, + 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, + 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, + 1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, + -1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, + 1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f, + 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, + 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, + -1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, + -1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, + -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, + 1.0f, 1.0f , 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, + 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, + -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, + -1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f + }; + + // Set up cube VAO + glGenVertexArrays(1, &cubeVAO); + glGenBuffers(1, &cubeVBO); + + // Fill buffer + glBindBuffer(GL_ARRAY_BUFFER, cubeVBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); + + // Link vertex attributes + glBindVertexArray(cubeVAO); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), (GLvoid*)0); + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), (GLvoid*)(3*sizeof(GLfloat))); + glEnableVertexAttribArray(2); + glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), (GLvoid*)(6*sizeof(GLfloat))); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); + } + + // Draw cube + glBindVertexArray(cubeVAO); + glDrawArrays(GL_TRIANGLES, 0, 36); + glBindVertexArray(0); + + //glDeleteBuffers(1, &cubeVBO); + //glDeleteVertexArrays(1, &cubeVAO); +} + #if defined(SUPPORT_VR_SIMULATOR) // Configure stereo rendering (including distortion shader) with HMD device parameters static void SetStereoConfig(VrDeviceInfo hmd) diff --git a/src/rlgl.h b/src/rlgl.h index 3adf81a5..a509068e 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -146,6 +146,7 @@ typedef unsigned char byte; typedef enum { false, true } bool; #endif + // Shader location point type typedef enum { LOC_VERTEX_POSITION = 0, LOC_VERTEX_TEXCOORD01, @@ -161,38 +162,39 @@ typedef unsigned char byte; LOC_COLOR_DIFFUSE, LOC_COLOR_SPECULAR, LOC_COLOR_AMBIENT, - LOC_TEXMAP_ALBEDO, // LOC_TEXMAP_DIFFUSE - LOC_TEXMAP_METALNESS, // LOC_TEXMAP_SPECULAR - LOC_TEXMAP_NORMAL, - LOC_TEXMAP_ROUGHNESS, - LOC_TEXMAP_OCCUSION, - LOC_TEXMAP_EMISSION, - LOC_TEXMAP_HEIGHT, - LOC_TEXMAP_CUBEMAP, - LOC_TEXMAP_IRRADIANCE, - LOC_TEXMAP_PREFILTER, - LOC_TEXMAP_BRDF + LOC_MAP_ALBEDO, // LOC_MAP_DIFFUSE + LOC_MAP_METALNESS, // LOC_MAP_SPECULAR + LOC_MAP_NORMAL, + LOC_MAP_ROUGHNESS, + LOC_MAP_OCCUSION, + LOC_MAP_EMISSION, + LOC_MAP_HEIGHT, + LOC_MAP_CUBEMAP, + LOC_MAP_IRRADIANCE, + LOC_MAP_PREFILTER, + LOC_MAP_BRDF } ShaderLocationIndex; - #define LOC_TEXMAP_DIFFUSE LOC_TEXMAP_ALBEDO - #define LOC_TEXMAP_SPECULAR LOC_TEXMAP_METALNESS + #define LOC_MAP_DIFFUSE LOC_MAP_ALBEDO + #define LOC_MAP_SPECULAR LOC_MAP_METALNESS + // Material map type typedef enum { - TEXMAP_ALBEDO = 0, // TEXMAP_DIFFUSE - TEXMAP_METALNESS = 1, // TEXMAP_SPECULAR - TEXMAP_NORMAL = 2, - TEXMAP_ROUGHNESS = 3, - TEXMAP_OCCLUSION, - TEXMAP_EMISSION, - TEXMAP_HEIGHT, - TEXMAP_CUBEMAP, // NOTE: Uses GL_TEXTURE_CUBE_MAP - TEXMAP_IRRADIANCE, // NOTE: Uses GL_TEXTURE_CUBE_MAP - TEXMAP_PREFILTER, // NOTE: Uses GL_TEXTURE_CUBE_MAP - TEXMAP_BRDF + MAP_ALBEDO = 0, // MAP_DIFFUSE + MAP_METALNESS = 1, // MAP_SPECULAR + MAP_NORMAL = 2, + MAP_ROUGHNESS = 3, + MAP_OCCLUSION, + MAP_EMISSION, + MAP_HEIGHT, + MAP_CUBEMAP, // NOTE: Uses GL_TEXTURE_CUBE_MAP + MAP_IRRADIANCE, // NOTE: Uses GL_TEXTURE_CUBE_MAP + MAP_PREFILTER, // NOTE: Uses GL_TEXTURE_CUBE_MAP + MAP_BRDF } TexmapIndex; - #define TEXMAP_DIFFUSE TEXMAP_ALBEDO - #define TEXMAP_SPECULAR TEXMAP_METALNESS + #define MAP_DIFFUSE MAP_ALBEDO + #define MAP_SPECULAR MAP_METALNESS // Color type, RGBA (32bit) typedef struct Color { @@ -237,8 +239,7 @@ typedef unsigned char byte; // Shader and material limits #define MAX_SHADER_LOCATIONS 32 - #define MAX_MATERIAL_TEXTURE_MAPS 12 - #define MAX_MATERIAL_PARAMS 8 + #define MAX_MATERIAL_MAPS 12 // Shader type (generic) typedef struct Shader { @@ -247,16 +248,16 @@ typedef unsigned char byte; } Shader; // Material texture map - typedef struct TextureMap { + typedef struct MaterialMap { Texture2D tex; Color color; float value; - } TextureMap; + } MaterialMap; // Material type (generic) typedef struct Material { Shader shader; - TextureMap maps[MAX_TEXTURE_MAPS]; // Initialized on LoadMaterial*(), set to MAX_TEXTURE_MAPS + MaterialMap maps[MAX_TEXTURE_MAPS]; // Initialized on LoadMaterial*(), set to MAX_TEXTURE_MAPS float *params; // Initialized on LoadMaterial*(), set to MAX_MATERIAL_PARAMS } Material; @@ -400,9 +401,10 @@ Vector3 rlUnproject(Vector3 source, Matrix proj, Matrix view); // Get world coo // Functions Declaration - rlgl functionality //------------------------------------------------------------------------------------ void rlglInit(int width, int height); // Initialize rlgl (buffers, shaders, textures, states) -void rlglClose(void); // De-init rlgl -void rlglDraw(void); // Draw VAO/VBO -void rlglLoadExtensions(void *loader); // Load OpenGL extensions +void rlglClose(void); // De-inititialize rlgl (buffers, shaders, textures) +void rlglDraw(void); // Update and Draw default buffers (lines, triangles, quads) + +void rlLoadExtensions(void *loader); // Load OpenGL extensions // Textures data management unsigned int rlLoadTexture(void *data, int width, int height, int format, int mipmapCount); // Load texture in GPU @@ -419,12 +421,6 @@ void rlUpdateMesh(Mesh mesh, int buffer, int numVertex); // Update ve void rlDrawMesh(Mesh mesh, Material material, Matrix transform); // Draw a 3d mesh with material and transform void rlUnloadMesh(Mesh *mesh); // Unload mesh data from CPU and GPU -// Texture maps generation (PBR) -Texture2D rlGenMapCubemap(Texture2D skyHDR, int size); // Generate cubemap texture map from HDR texture -Texture2D rlGenMapIrradiance(Texture2D cubemap, int size); // Generate irradiance texture map -Texture2D rlGenMapPrefilter(Texture2D cubemap, int size); // Generate prefilter texture map -Texture2D rlGenMapBRDF(Texture2D cubemap, int size); // Generate BRDF texture map - // 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 @@ -447,11 +443,19 @@ void SetShaderValueMatrix(Shader shader, int uniformLoc, Matrix mat); // S void SetMatrixProjection(Matrix proj); // Set a custom projection matrix (replaces internal projection matrix) void SetMatrixModelview(Matrix view); // Set a custom modelview matrix (replaces internal modelview matrix) +// Texture maps generation (PBR) +Texture2D GenTextureCubemap(Texture2D skyHDR, int size); // Generate cubemap texture map from HDR texture +Texture2D GenTextureIrradiance(Texture2D cubemap, int size); // Generate irradiance texture map +Texture2D GenTexturePrefilter(Texture2D cubemap, int size); // Generate prefilter texture map +Texture2D GenTextureBRDF(Texture2D cubemap, int size); // Generate BRDF texture map + +// Shading and blending void BeginShaderMode(Shader shader); // Begin custom shader drawing void EndShaderMode(void); // End custom shader drawing (use default shader) void BeginBlendMode(int mode); // Begin blending mode (alpha, additive, multiplied) void EndBlendMode(void); // End blending mode (reset to default: alpha blending) +// VR simulator functionality void InitVrSimulator(int vrDevice); // Init VR simulator for selected device void CloseVrSimulator(void); // Close VR simulator for current device void UpdateVrTracking(Camera *camera); // Update VR tracking (position and orientation) and camera -- cgit v1.2.3 From 76c6f0b1e695b4090fd1e98d7f2d7ff7dea25641 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Wed, 19 Jul 2017 18:55:26 +0200 Subject: Working on PBR system Moved PBR material loading to example, right decision? --- examples/models/models_material_pbr.c | 195 ++++++++++++++--------------- examples/models/resources/shaders/pbr.fs | 3 +- examples/models/rlights.h | 177 ++++++++++++++++++++++++++ src/models.c | 103 ++++----------- src/raylib.h | 14 +-- src/rlgl.c | 207 ++++++++++++++----------------- 6 files changed, 398 insertions(+), 301 deletions(-) create mode 100644 examples/models/rlights.h (limited to 'src/raylib.h') diff --git a/examples/models/models_material_pbr.c b/examples/models/models_material_pbr.c index 5761b2af..49a905a8 100644 --- a/examples/models/models_material_pbr.c +++ b/examples/models/models_material_pbr.c @@ -12,32 +12,16 @@ #include "raylib.h" #include "raymath.h" -#define MAX_LIGHTS 4 // Max lights supported by shader -#define LIGHT_DISTANCE 3.5f // Light distance from world center -#define LIGHT_HEIGHT 1.0f // Light height position - -typedef enum { - LIGHT_DIRECTIONAL, - LIGHT_POINT -} LightType; - -typedef struct { - bool enabled; - LightType type; - Vector3 position; - Vector3 target; - Color color; - int enabledLoc; - int typeLoc; - int posLoc; - int targetLoc; - int colorLoc; -} Light; - -int lightsCount = 0; // Current amount of created lights - -Light CreateLight(int type, Vector3 pos, Vector3 targ, Color color, Shader shader); // Defines a light and get locations from PBR shader -void UpdateLightValues(Shader shader, Light light); // Send to PBR shader light values +#define RLIGHTS_IMPLEMENTATION +#include "rlights.h" + +#define CUBEMAP_SIZE 512 // Cubemap texture size +#define IRRADIANCE_SIZE 32 // Irradiance texture size +#define PREFILTERED_SIZE 256 // Prefiltered HDR environment texture size +#define BRDF_SIZE 512 // BRDF LUT texture size + +// PBR material loading +static Material LoadMaterialPBR(Color albedo, float metalness, float roughness); int main() { @@ -54,33 +38,15 @@ int main() // Load model and PBR material Model model = LoadModel("resources/pbr/trooper.obj"); - - Texture2D texHDR = LoadTexture("resources/pinetree.hdr"); - model.material = LoadMaterialPBR(texHDR, (Color){ 255, 255, 255, 255 }, 1.0f, 1.0f); - - SetMaterialTexture(&model.material, MAP_ALBEDO, LoadTexture("resources/pbr/trooper_albedo.png")); - SetMaterialTexture(&model.material, MAP_NORMAL, LoadTexture("resources/pbr/trooper_normals.png")); - SetMaterialTexture(&model.material, MAP_METALNESS, LoadTexture("resources/pbr/trooper_metalness.png")); - SetMaterialTexture(&model.material, MAP_ROUGHNESS, LoadTexture("resources/pbr/trooper_roughness.png")); - SetMaterialTexture(&model.material, MAP_OCCLUSION, LoadTexture("resources/pbr/trooper_ao.png")); - - // Set textures filtering for better quality - SetTextureFilter(model.material.maps[MAP_ALBEDO].texture, FILTER_BILINEAR); - SetTextureFilter(model.material.maps[MAP_NORMAL].texture, FILTER_BILINEAR); - SetTextureFilter(model.material.maps[MAP_METALNESS].texture, FILTER_BILINEAR); - SetTextureFilter(model.material.maps[MAP_ROUGHNESS].texture, FILTER_BILINEAR); - SetTextureFilter(model.material.maps[MAP_OCCLUSION].texture, FILTER_BILINEAR); - - int renderModeLoc = GetShaderLocation(model.material.shader, "renderMode"); - SetShaderValuei(model.material.shader, renderModeLoc, (int[1]){ 0 }, 1); + model.material = LoadMaterialPBR((Color){ 255, 255, 255, 255 }, 1.0f, 1.0f); - SetCameraMode(camera, CAMERA_ORBITAL); // Set an orbital camera mode - // Define lights attributes Light lights[MAX_LIGHTS] = { CreateLight(LIGHT_POINT, (Vector3){ LIGHT_DISTANCE, LIGHT_HEIGHT, 0.0f }, (Vector3){ 0.0f, 0.0f, 0.0f }, (Color){ 255, 0, 0, 255 }, model.material.shader), CreateLight(LIGHT_POINT, (Vector3){ 0.0f, LIGHT_HEIGHT, LIGHT_DISTANCE }, (Vector3){ 0.0f, 0.0f, 0.0f }, (Color){ 0, 255, 0, 255 }, model.material.shader), CreateLight(LIGHT_POINT, (Vector3){ -LIGHT_DISTANCE, LIGHT_HEIGHT, 0.0f }, (Vector3){ 0.0f, 0.0f, 0.0f }, (Color){ 0, 0, 255, 255 }, model.material.shader), CreateLight(LIGHT_DIRECTIONAL, (Vector3){ 0.0f, LIGHT_HEIGHT*2.0f, -LIGHT_DISTANCE }, (Vector3){ 0.0f, 0.0f, 0.0f }, (Color){ 255, 0, 255, 255 }, model.material.shader) }; + + SetCameraMode(camera, CAMERA_ORBITAL); // Set an orbital camera mode SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- @@ -127,59 +93,88 @@ int main() return 0; } -// Defines a light and get locations from PBR shader -Light CreateLight(int type, Vector3 pos, Vector3 targ, Color color, Shader shader) +// Load PBR material (Supports: ALBEDO, NORMAL, METALNESS, ROUGHNESS, AO, EMMISIVE, HEIGHT maps) +// NOTE: PBR shader is loaded inside this function +static Material LoadMaterialPBR(Color albedo, float metalness, float roughness) { - Light light = { 0 }; - - if (lightsCount < MAX_LIGHTS) - { - light.enabled = true; - light.type = type; - light.position = pos; - light.target = targ; - light.color = color; - - char enabledName[32] = "lights[x].enabled\0"; - char typeName[32] = "lights[x].type\0"; - char posName[32] = "lights[x].position\0"; - char targetName[32] = "lights[x].target\0"; - char colorName[32] = "lights[x].color\0"; - enabledName[7] = '0' + lightsCount; - typeName[7] = '0' + lightsCount; - posName[7] = '0' + lightsCount; - targetName[7] = '0' + lightsCount; - colorName[7] = '0' + lightsCount; - - light.enabledLoc = GetShaderLocation(shader, enabledName); - light.typeLoc = GetShaderLocation(shader, typeName); - light.posLoc = GetShaderLocation(shader, posName); - light.targetLoc = GetShaderLocation(shader, targetName); - light.colorLoc = GetShaderLocation(shader, colorName); - - UpdateLightValues(shader, light); - lightsCount++; - } - - return light; -} - -// Send to PBR shader light values -void UpdateLightValues(Shader shader, Light light) -{ - // Send to shader light enabled state and type - SetShaderValuei(shader, light.enabledLoc, (int[1]){ light.enabled }, 1); - SetShaderValuei(shader, light.typeLoc, (int[1]){ light.type }, 1); - - // Send to shader light position values - float position[3] = { light.position.x, light.position.y, light.position.z }; - SetShaderValue(shader, light.posLoc, position, 3); - - // Send to shader light target position values - float target[3] = { light.target.x, light.target.y, light.target.z }; - SetShaderValue(shader, light.targetLoc, target, 3); + Material mat = { 0 }; // NOTE: All maps textures are set to { 0 } + + #define PATH_PBR_VS "resources/shaders/pbr.vs" // Path to physically based rendering vertex shader + #define PATH_PBR_FS "resources/shaders/pbr.fs" // Path to physically based rendering fragment shader + + mat.shader = LoadShader(PATH_PBR_VS, PATH_PBR_FS); + + // Get required locations points for PBR material + // NOTE: Those location names must be available and used in the shader code + mat.shader.locs[LOC_MAP_ALBEDO] = GetShaderLocation(mat.shader, "albedo.sampler"); + mat.shader.locs[LOC_MAP_METALNESS] = GetShaderLocation(mat.shader, "metalness.sampler"); + mat.shader.locs[LOC_MAP_NORMAL] = GetShaderLocation(mat.shader, "normals.sampler"); + mat.shader.locs[LOC_MAP_ROUGHNESS] = GetShaderLocation(mat.shader, "roughness.sampler"); + mat.shader.locs[LOC_MAP_OCCUSION] = GetShaderLocation(mat.shader, "occlusion.sampler"); + mat.shader.locs[LOC_MAP_EMISSION] = GetShaderLocation(mat.shader, "emission.sampler"); + mat.shader.locs[LOC_MAP_HEIGHT] = GetShaderLocation(mat.shader, "height.sampler"); + mat.shader.locs[LOC_MAP_IRRADIANCE] = GetShaderLocation(mat.shader, "irradianceMap"); + mat.shader.locs[LOC_MAP_PREFILTER] = GetShaderLocation(mat.shader, "prefilterMap"); + mat.shader.locs[LOC_MAP_BRDF] = GetShaderLocation(mat.shader, "brdfLUT"); + + // Set view matrix location + mat.shader.locs[LOC_MATRIX_MODEL] = GetShaderLocation(mat.shader, "mMatrix"); + mat.shader.locs[LOC_MATRIX_VIEW] = GetShaderLocation(mat.shader, "view"); + mat.shader.locs[LOC_VECTOR_VIEW] = GetShaderLocation(mat.shader, "viewPos"); + + // Set PBR standard maps + SetMaterialTexture(&mat, MAP_ALBEDO, LoadTexture("resources/pbr/trooper_albedo.png")); + SetMaterialTexture(&mat, MAP_NORMAL, LoadTexture("resources/pbr/trooper_normals.png")); + SetMaterialTexture(&mat, MAP_METALNESS, LoadTexture("resources/pbr/trooper_metalness.png")); + SetMaterialTexture(&mat, MAP_ROUGHNESS, LoadTexture("resources/pbr/trooper_roughness.png")); + SetMaterialTexture(&mat, MAP_OCCLUSION, LoadTexture("resources/pbr/trooper_ao.png")); + + // Set environment maps + #define PATH_CUBEMAP_VS "resources/shaders/cubemap.vs" // Path to equirectangular to cubemap vertex shader + #define PATH_CUBEMAP_FS "resources/shaders/cubemap.fs" // Path to equirectangular to cubemap fragment shader + #define PATH_SKYBOX_VS "resources/shaders/skybox.vs" // Path to skybox vertex shader + #define PATH_IRRADIANCE_FS "resources/shaders/irradiance.fs" // Path to irradiance (GI) calculation fragment shader + #define PATH_SKYBOX_VS "resources/shaders/skybox.vs" // Path to skybox vertex shader + #define PATH_PREFILTER_FS "resources/shaders/prefilter.fs" // Path to reflection prefilter calculation fragment shader + #define PATH_BRDF_VS "resources/shaders/brdf.vs" // Path to bidirectional reflectance distribution function vertex shader + #define PATH_BRDF_FS "resources/shaders/brdf.fs" // Path to bidirectional reflectance distribution function fragment shader + + Shader shdrCubemap = LoadShader(PATH_CUBEMAP_VS, PATH_CUBEMAP_FS); + Shader shdrIrradiance = LoadShader(PATH_SKYBOX_VS, PATH_IRRADIANCE_FS); + Shader shdrPrefilter = LoadShader(PATH_SKYBOX_VS, PATH_PREFILTER_FS); + Shader shdrBRDF = LoadShader(PATH_BRDF_VS, PATH_BRDF_FS); - // Send to shader light color values - float diff[4] = { (float)light.color.r/(float)255, (float)light.color.g/(float)255, (float)light.color.b/(float)255, (float)light.color.a/(float)255 }; - SetShaderValue(shader, light.colorLoc, diff, 4); + Texture2D texHDR = LoadTexture("resources/pinetree.hdr"); + Texture2D cubemap = GenTextureCubemap(shdrCubemap, texHDR, CUBEMAP_SIZE); + SetMaterialTexture(&mat, MAP_IRRADIANCE, GenTextureIrradiance(shdrIrradiance, cubemap, IRRADIANCE_SIZE)); + SetMaterialTexture(&mat, MAP_PREFILTER, GenTexturePrefilter(shdrPrefilter, cubemap, PREFILTERED_SIZE)); + SetMaterialTexture(&mat, MAP_BRDF, GenTextureBRDF(shdrBRDF, cubemap, BRDF_SIZE)); + UnloadTexture(cubemap); + UnloadTexture(texHDR); + + UnloadShader(shdrCubemap); + UnloadShader(shdrIrradiance); + UnloadShader(shdrPrefilter); + UnloadShader(shdrBRDF); + + // Set textures filtering for better quality + SetTextureFilter(mat.maps[MAP_ALBEDO].texture, FILTER_BILINEAR); + SetTextureFilter(mat.maps[MAP_NORMAL].texture, FILTER_BILINEAR); + SetTextureFilter(mat.maps[MAP_METALNESS].texture, FILTER_BILINEAR); + SetTextureFilter(mat.maps[MAP_ROUGHNESS].texture, FILTER_BILINEAR); + SetTextureFilter(mat.maps[MAP_OCCLUSION].texture, FILTER_BILINEAR); + + int renderModeLoc = GetShaderLocation(mat.shader, "renderMode"); + SetShaderValuei(mat.shader, renderModeLoc, (int[1]){ 0 }, 1); + + // Set up material properties color + mat.maps[MAP_ALBEDO].color = albedo; + mat.maps[MAP_NORMAL].color = (Color){ 128, 128, 255, 255 }; + mat.maps[MAP_METALNESS].value = metalness; + mat.maps[MAP_ROUGHNESS].value = roughness; + mat.maps[MAP_OCCLUSION].value = 1.0f; + mat.maps[MAP_EMISSION].value = 0.5f; + mat.maps[MAP_HEIGHT].value = 0.5f; + + return mat; } diff --git a/examples/models/resources/shaders/pbr.fs b/examples/models/resources/shaders/pbr.fs index 06814823..38d56c5d 100644 --- a/examples/models/resources/shaders/pbr.fs +++ b/examples/models/resources/shaders/pbr.fs @@ -8,10 +8,11 @@ #version 330 -#define MAX_LIGHTS 4 #define MAX_REFLECTION_LOD 4.0 #define MAX_DEPTH_LAYER 20 #define MIN_DEPTH_LAYER 10 + +#define MAX_LIGHTS 4 #define LIGHT_DIRECTIONAL 0 #define LIGHT_POINT 1 diff --git a/examples/models/rlights.h b/examples/models/rlights.h new file mode 100644 index 00000000..0da3e2cb --- /dev/null +++ b/examples/models/rlights.h @@ -0,0 +1,177 @@ +/********************************************************************************************** +* +* raylib.lights - Some useful functions to deal with lights data +* +* CONFIGURATION: +* +* #define RLIGHTS_IMPLEMENTATION +* Generates the implementation of the library into the included file. +* If not defined, the library is in header only mode and can be included in other headers +* or source files without problems. But only ONE file should hold the implementation. +* +* LICENSE: zlib/libpng +* +* Copyright (c) 2017 Victor Fisac 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 RLIGHTS_H +#define RLIGHTS_H + +//---------------------------------------------------------------------------------- +// Defines and Macros +//---------------------------------------------------------------------------------- +#define MAX_LIGHTS 4 // Max lights supported by shader +#define LIGHT_DISTANCE 3.5f // Light distance from world center +#define LIGHT_HEIGHT 1.0f // Light height position + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +//---------------------------------------------------------------------------------- +typedef enum { + LIGHT_DIRECTIONAL, + LIGHT_POINT +} LightType; + +typedef struct { + bool enabled; + LightType type; + Vector3 position; + Vector3 target; + Color color; + int enabledLoc; + int typeLoc; + int posLoc; + int targetLoc; + int colorLoc; +} Light; + +#ifdef __cplusplus +extern "C" { // Prevents name mangling of functions +#endif + +//---------------------------------------------------------------------------------- +// Global Variables Definition +//---------------------------------------------------------------------------------- +int lightsCount = 0; // Current amount of created lights + +//---------------------------------------------------------------------------------- +// Module Functions Declaration +//---------------------------------------------------------------------------------- +Light CreateLight(int type, Vector3 pos, Vector3 targ, Color color, Shader shader); // Defines a light and get locations from PBR shader +void UpdateLightValues(Shader shader, Light light); // Send to PBR shader light values + +#ifdef __cplusplus +} +#endif + +#endif // RLIGHTS_H + + +/*********************************************************************************** +* +* RLIGHTS IMPLEMENTATION +* +************************************************************************************/ + +#if defined(RLIGHTS_IMPLEMENTATION) + +#include "raylib.h" + +//---------------------------------------------------------------------------------- +// Defines and Macros +//---------------------------------------------------------------------------------- +// ... + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +//---------------------------------------------------------------------------------- +// ... + +//---------------------------------------------------------------------------------- +// Global Variables Definition +//---------------------------------------------------------------------------------- +// ... + +//---------------------------------------------------------------------------------- +// Module specific Functions Declaration +//---------------------------------------------------------------------------------- +// ... + +//---------------------------------------------------------------------------------- +// Module Functions Definition +//---------------------------------------------------------------------------------- + +// Defines a light and get locations from PBR shader +Light CreateLight(int type, Vector3 pos, Vector3 targ, Color color, Shader shader) +{ + Light light = { 0 }; + + if (lightsCount < MAX_LIGHTS) + { + light.enabled = true; + light.type = type; + light.position = pos; + light.target = targ; + light.color = color; + + char enabledName[32] = "lights[x].enabled\0"; + char typeName[32] = "lights[x].type\0"; + char posName[32] = "lights[x].position\0"; + char targetName[32] = "lights[x].target\0"; + char colorName[32] = "lights[x].color\0"; + enabledName[7] = '0' + lightsCount; + typeName[7] = '0' + lightsCount; + posName[7] = '0' + lightsCount; + targetName[7] = '0' + lightsCount; + colorName[7] = '0' + lightsCount; + + light.enabledLoc = GetShaderLocation(shader, enabledName); + light.typeLoc = GetShaderLocation(shader, typeName); + light.posLoc = GetShaderLocation(shader, posName); + light.targetLoc = GetShaderLocation(shader, targetName); + light.colorLoc = GetShaderLocation(shader, colorName); + + UpdateLightValues(shader, light); + lightsCount++; + } + + return light; +} + +// Send to PBR shader light values +void UpdateLightValues(Shader shader, Light light) +{ + // Send to shader light enabled state and type + SetShaderValuei(shader, light.enabledLoc, (int[1]){ light.enabled }, 1); + SetShaderValuei(shader, light.typeLoc, (int[1]){ light.type }, 1); + + // Send to shader light position values + float position[3] = { light.position.x, light.position.y, light.position.z }; + SetShaderValue(shader, light.posLoc, position, 3); + + // Send to shader light target position values + float target[3] = { light.target.x, light.target.y, light.target.z }; + SetShaderValue(shader, light.targetLoc, target, 3); + + // Send to shader light color values + float diff[4] = { (float)light.color.r/(float)255, (float)light.color.g/(float)255, (float)light.color.b/(float)255, (float)light.color.a/(float)255 }; + SetShaderValue(shader, light.colorLoc, diff, 4); +} + +#endif // RLIGHTS_IMPLEMENTATION \ No newline at end of file diff --git a/src/models.c b/src/models.c index 660ecc79..34156b61 100644 --- a/src/models.c +++ b/src/models.c @@ -1272,6 +1272,9 @@ Material LoadMaterial(const char *fileName) TraceLog(LOG_WARNING, "[%s] Material fileformat not supported, it can't be loaded", fileName); #endif + // Our material uses the default shader (DIFFUSE, SPECULAR, NORMAL) + material.shader = GetShaderDefault(); + return material; } @@ -1282,8 +1285,8 @@ Material LoadMaterialDefault(void) material.shader = GetShaderDefault(); material.maps[MAP_DIFFUSE].texture = GetTextureDefault(); // White texture (1x1 pixel) - //material.maps[MAP_NORMAL].tex; // NOTE: By default, not set - //material.maps[MAP_SPECULAR].tex; // NOTE: By default, not set + //material.maps[MAP_NORMAL].texture; // NOTE: By default, not set + //material.maps[MAP_SPECULAR].texture; // NOTE: By default, not set material.maps[MAP_DIFFUSE].color = WHITE; // Diffuse color material.maps[MAP_SPECULAR].color = WHITE; // Specular color @@ -1291,58 +1294,6 @@ Material LoadMaterialDefault(void) return material; } -// Load PBR material (Supports: ALBEDO, NORMAL, METALNESS, ROUGHNESS, AO, EMMISIVE, HEIGHT maps) -Material LoadMaterialPBR(Texture2D hdr, Color albedo, float metalness, float roughness) -{ - Material mat = { 0 }; // NOTE: All maps textures are set to { 0 } - - #define PATH_PBR_VS "resources/shaders/pbr.vs" // Path to physically based rendering vertex shader - #define PATH_PBR_FS "resources/shaders/pbr.fs" // Path to physically based rendering fragment shader - - mat.shader = LoadShader(PATH_PBR_VS, PATH_PBR_FS); - - // Get required locations points for PBR material - // NOTE: Those location names must be available and used in the shader code - mat.shader.locs[LOC_MAP_ALBEDO] = GetShaderLocation(mat.shader, "albedo.sampler"); - mat.shader.locs[LOC_MAP_METALNESS] = GetShaderLocation(mat.shader, "metalness.sampler"); - mat.shader.locs[LOC_MAP_NORMAL] = GetShaderLocation(mat.shader, "normals.sampler"); - mat.shader.locs[LOC_MAP_ROUGHNESS] = GetShaderLocation(mat.shader, "roughness.sampler"); - mat.shader.locs[LOC_MAP_OCCUSION] = GetShaderLocation(mat.shader, "occlusion.sampler"); - mat.shader.locs[LOC_MAP_EMISSION] = GetShaderLocation(mat.shader, "emission.sampler"); - mat.shader.locs[LOC_MAP_HEIGHT] = GetShaderLocation(mat.shader, "height.sampler"); - mat.shader.locs[LOC_MAP_IRRADIANCE] = GetShaderLocation(mat.shader, "irradianceMap"); - mat.shader.locs[LOC_MAP_PREFILTER] = GetShaderLocation(mat.shader, "prefilterMap"); - mat.shader.locs[LOC_MAP_BRDF] = GetShaderLocation(mat.shader, "brdfLUT"); - - // Set view matrix location - mat.shader.locs[LOC_MATRIX_MODEL] = GetShaderLocation(mat.shader, "mMatrix"); - mat.shader.locs[LOC_MATRIX_VIEW] = GetShaderLocation(mat.shader, "view"); - mat.shader.locs[LOC_VECTOR_VIEW] = GetShaderLocation(mat.shader, "viewPos"); - - // Set up material properties color - mat.maps[MAP_ALBEDO].color = albedo; - mat.maps[MAP_NORMAL].color = (Color){ 128, 128, 255, 255 }; - mat.maps[MAP_METALNESS].value = metalness; - mat.maps[MAP_ROUGHNESS].value = roughness; - mat.maps[MAP_OCCLUSION].value = 1.0f; - mat.maps[MAP_EMISSION].value = 0.0f; - mat.maps[MAP_HEIGHT].value = 0.0f; - - #define CUBEMAP_SIZE 512 // Cubemap texture size - #define IRRADIANCE_SIZE 32 // Irradiance map from cubemap texture size - #define PREFILTERED_SIZE 256 // Prefiltered HDR environment map texture size - #define BRDF_SIZE 512 // BRDF LUT texture map size - - // Set up environment materials cubemap - Texture2D cubemap = GenTextureCubemap(hdr, CUBEMAP_SIZE); - mat.maps[MAP_IRRADIANCE].texture = GenTextureIrradiance(cubemap, IRRADIANCE_SIZE); - mat.maps[MAP_PREFILTER].texture = GenTexturePrefilter(cubemap, PREFILTERED_SIZE); - mat.maps[MAP_BRDF].texture = GenTextureBRDF(cubemap, BRDF_SIZE); - UnloadTexture(cubemap); - - return mat; -} - // Unload material from memory void UnloadMaterial(Material material) { @@ -1358,96 +1309,96 @@ void UnloadMaterial(Material material) } // Set material texture -void SetMaterialTexture(Material *mat, int texmapType, Texture2D texture) +void SetMaterialTexture(Material *mat, int mapType, Texture2D texture) { - mat->maps[texmapType].texture = texture; + mat->maps[mapType].texture = texture; // Update MaterialProperty use sampler state to use texture fetch instead of color attribute int location = -1; - switch (texmapType) + switch (mapType) { case MAP_ALBEDO: { location = GetShaderLocation(mat->shader, "albedo.useSampler"); - SetShaderValuei(mat->shader, location, (int [1]){ 1 }, 1); + SetShaderValuei(mat->shader, location, (int[1]){ 1 }, 1); } break; case MAP_NORMAL: { location = GetShaderLocation(mat->shader, "normals.useSampler"); - SetShaderValuei(mat->shader, location, (int [1]){ 1 }, 1); + SetShaderValuei(mat->shader, location, (int[1]){ 1 }, 1); } break; case MAP_METALNESS: { location = GetShaderLocation(mat->shader, "metalness.useSampler"); - SetShaderValuei(mat->shader, location, (int [1]){ 1 }, 1); + SetShaderValuei(mat->shader, location, (int[1]){ 1 }, 1); } break; case MAP_ROUGHNESS: { location = GetShaderLocation(mat->shader, "roughness.useSampler"); - SetShaderValuei(mat->shader, location, (int [1]){ 1 }, 1); + SetShaderValuei(mat->shader, location, (int[1]){ 1 }, 1); } break; case MAP_OCCLUSION: { location = GetShaderLocation(mat->shader, "occlusion.useSampler"); - SetShaderValuei(mat->shader, location, (int [1]){ 1 }, 1); + SetShaderValuei(mat->shader, location, (int[1]){ 1 }, 1); } break; case MAP_EMISSION: { location = GetShaderLocation(mat->shader, "emission.useSampler"); - SetShaderValuei(mat->shader, location, (int [1]){ 1 }, 1); + SetShaderValuei(mat->shader, location, (int[1]){ 1 }, 1); } break; case MAP_HEIGHT: { location = GetShaderLocation(mat->shader, "height.useSampler"); - SetShaderValuei(mat->shader, location, (int [1]){ 1 }, 1); + SetShaderValuei(mat->shader, location, (int[1]){ 1 }, 1); } break; } } // Unset texture from material and unload it from GPU -void UnsetMaterialTexture(Material *mat, int texmapType) +void UnsetMaterialTexture(Material *mat, int mapType) { - UnloadTexture(mat->maps[texmapType].texture); - mat->maps[texmapType].texture = (Texture2D){ 0 }; + UnloadTexture(mat->maps[mapType].texture); + mat->maps[mapType].texture = (Texture2D){ 0 }; // Update MaterialProperty use sampler state to use texture fetch instead of color attribute int location = -1; - switch (texmapType) + switch (mapType) { case MAP_ALBEDO: { location = GetShaderLocation(mat->shader, "albedo.useSampler"); - SetShaderValuei(mat->shader, location, (int [1]){ 0 }, 1); + SetShaderValuei(mat->shader, location, (int[1]){ 0 }, 1); } break; case MAP_NORMAL: { location = GetShaderLocation(mat->shader, "normals.useSampler"); - SetShaderValuei(mat->shader, location, (int [1]){ 0 }, 1); + SetShaderValuei(mat->shader, location, (int[1]){ 0 }, 1); } break; case MAP_METALNESS: { location = GetShaderLocation(mat->shader, "metalness.useSampler"); - SetShaderValuei(mat->shader, location, (int [1]){ 0 }, 1); + SetShaderValuei(mat->shader, location, (int[1]){ 0 }, 1); } break; case MAP_ROUGHNESS: { location = GetShaderLocation(mat->shader, "roughness.useSampler"); - SetShaderValuei(mat->shader, location, (int [1]){ 0 }, 1); + SetShaderValuei(mat->shader, location, (int[1]){ 0 }, 1); } break; case MAP_OCCLUSION: { location = GetShaderLocation(mat->shader, "occlusion.useSampler"); - SetShaderValuei(mat->shader, location, (int [1]){ 0 }, 1); + SetShaderValuei(mat->shader, location, (int[1]){ 0 }, 1); } break; case MAP_EMISSION: { location = GetShaderLocation(mat->shader, "emission.useSampler"); - SetShaderValuei(mat->shader, location, (int [1]){ 0 }, 1); + SetShaderValuei(mat->shader, location, (int[1]){ 0 }, 1); } break; case MAP_HEIGHT: { location = GetShaderLocation(mat->shader, "height.useSampler"); - SetShaderValuei(mat->shader, location, (int [1]){ 0 }, 1); + SetShaderValuei(mat->shader, location, (int[1]){ 0 }, 1); } break; } } @@ -2188,7 +2139,7 @@ static Material LoadMTL(const char *fileName) { #define MAX_BUFFER_SIZE 128 - Material material = { 0 }; // LoadDefaultMaterial(); + Material material = { 0 }; char buffer[MAX_BUFFER_SIZE]; Vector3 color = { 1.0f, 1.0f, 1.0f }; diff --git a/src/raylib.h b/src/raylib.h index 8d93a214..22ef06cb 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -996,10 +996,9 @@ RLAPI Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize); // Material loading/unloading functions RLAPI Material LoadMaterial(const char *fileName); // Load material from file RLAPI Material LoadMaterialDefault(void); // Load default material (Supports: DIFFUSE, SPECULAR, NORMAL maps) -RLAPI Material LoadMaterialPBR(Texture2D cubemap, Color albedo, float metalness, float roughness); // Load PBR material (Supports: ALBEDO, NORMAL, METALNESS, ROUGHNESS...) RLAPI void UnloadMaterial(Material material); // Unload material from GPU memory (VRAM) -RLAPI void SetMaterialTexture(Material *mat, int texmapType, Texture2D texture); // Set material texture -RLAPI void UnsetMaterialTexture(Material *mat, int texmapType); // Unset texture from material and unload it from GPU +RLAPI void SetMaterialTexture(Material *mat, int mapType, Texture2D texture); // Set material texture +RLAPI void UnsetMaterialTexture(Material *mat, int mapType); // Unset texture from material and unload it from GPU // Model drawing functions RLAPI void DrawModel(Model model, Vector3 position, float scale, Color tint); // Draw a model (with texture if set) @@ -1048,10 +1047,11 @@ RLAPI void SetMatrixProjection(Matrix proj); // Set RLAPI void SetMatrixModelview(Matrix view); // Set a custom modelview matrix (replaces internal modelview matrix) // Texture maps generation (PBR) -RLAPI Texture2D GenTextureCubemap(Texture2D skyHDR, int size); // Generate cubemap texture from HDR texture -RLAPI Texture2D GenTextureIrradiance(Texture2D cubemap, int size); // Generate irradiance texture using cubemap data -RLAPI Texture2D GenTexturePrefilter(Texture2D cubemap, int size); // Generate prefilter texture using cubemap data -RLAPI Texture2D GenTextureBRDF(Texture2D cubemap, int size); // Generate BRDF texture using cubemap data +// NOTE: Required shaders should be provided +RLAPI Texture2D GenTextureCubemap(Shader shader, Texture2D skyHDR, int size); // Generate cubemap texture from HDR texture +RLAPI Texture2D GenTextureIrradiance(Shader shader, Texture2D cubemap, int size); // Generate irradiance texture using cubemap data +RLAPI Texture2D GenTexturePrefilter(Shader shader, Texture2D cubemap, int size); // Generate prefilter texture using cubemap data +RLAPI Texture2D GenTextureBRDF(Shader shader, Texture2D cubemap, int size); // Generate BRDF texture using cubemap data // Shading begin/end functions RLAPI void BeginShaderMode(Shader shader); // Begin custom shader drawing diff --git a/src/rlgl.c b/src/rlgl.c index b9576b9b..e6d1bbfb 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -1957,15 +1957,14 @@ void rlDrawMesh(Mesh mesh, Material material, Matrix transform) // Bind shader program glUseProgram(material.shader.id); - // Matrices and other values required by shader //----------------------------------------------------- - // Calculate and send to shader model matrix (used by PBR shader) SetShaderValueMatrix(material.shader, material.shader.locs[LOC_MATRIX_MODEL], transform); // Upload to shader material.colDiffuse - glUniform4f(material.shader.locs[LOC_COLOR_DIFFUSE], (float)material.maps[MAP_DIFFUSE].color.r/255, + if (material.shader.locs[LOC_COLOR_DIFFUSE] != -1) + glUniform4f(material.shader.locs[LOC_COLOR_DIFFUSE], (float)material.maps[MAP_DIFFUSE].color.r/255, (float)material.maps[MAP_DIFFUSE].color.g/255, (float)material.maps[MAP_DIFFUSE].color.b/255, (float)material.maps[MAP_DIFFUSE].color.a/255); @@ -1976,6 +1975,9 @@ void rlDrawMesh(Mesh mesh, Material material, Matrix transform) (float)material.maps[MAP_SPECULAR].color.g/255, (float)material.maps[MAP_SPECULAR].color.b/255, (float)material.maps[MAP_SPECULAR].color.a/255); + + if (material.shader.locs[LOC_MATRIX_VIEW] != -1) SetShaderValueMatrix(material.shader, material.shader.locs[LOC_MATRIX_VIEW], modelview); + if (material.shader.locs[LOC_MATRIX_PROJECTION] != -1) SetShaderValueMatrix(material.shader, material.shader.locs[LOC_MATRIX_PROJECTION], projection); // At this point the modelview matrix just contains the view matrix (camera) // That's because Begin3dMode() sets it an no model-drawing function modifies it, all use rlPushMatrix() and rlPopMatrix() @@ -2417,7 +2419,7 @@ Shader LoadShader(char *vsFileName, char *fsFileName) // Get the location of the named uniform GLuint location = glGetUniformLocation(shader.id, name); - TraceLog(LOG_INFO, "[SHDR ID %i] Active uniform [%s] set at location: %i", shader.id, name, location); + TraceLog(LOG_DEBUG, "[SHDR ID %i] Active uniform [%s] set at location: %i", shader.id, name, location); } #endif @@ -2529,18 +2531,13 @@ void SetMatrixModelview(Matrix view) } // Generate cubemap texture from HDR texture -Texture2D GenTextureCubemap(Texture2D skyHDR, int size) +Texture2D GenTextureCubemap(Shader shader, Texture2D skyHDR, int size) { Texture2D cubemap = { 0 }; - #define PATH_CUBEMAP_VS "resources/shaders/cubemap.vs" // Path to equirectangular to cubemap vertex shader - #define PATH_CUBEMAP_FS "resources/shaders/cubemap.fs" // Path to equirectangular to cubemap fragment shader - - Shader shader = LoadShader(PATH_CUBEMAP_VS, PATH_CUBEMAP_FS); - // Get cubemap shader locations - int projectionLoc = GetShaderLocation(shader, "projection"); - int viewLoc = GetShaderLocation(shader, "view"); + //int projectionLoc = GetShaderLocation(shader, "projection"); // Already set at SetShaderDefaultLocations() + //int viewLoc = GetShaderLocation(shader, "view"); // Already set at SetShaderDefaultLocations() int texmapLoc = GetShaderLocation(shader, "equirectangularMap"); SetShaderValuei(shader, texmapLoc, (int[1]){ 0 }, 1); // Set default active texture to 0 @@ -2586,7 +2583,7 @@ Texture2D GenTextureCubemap(Texture2D skyHDR, int size) glUseProgram(shader.id); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, skyHDR.id); - SetShaderValueMatrix(shader, projectionLoc, fboProjection); + SetShaderValueMatrix(shader, shader.locs[LOC_MATRIX_PROJECTION], fboProjection); // Note: don't forget to configure the viewport to the capture dimensions glViewport(0, 0, size, size); @@ -2594,7 +2591,7 @@ Texture2D GenTextureCubemap(Texture2D skyHDR, int size) for (unsigned int i = 0; i < 6; i++) { - SetShaderValueMatrix(shader, viewLoc, fboViews[i]); + SetShaderValueMatrix(shader, shader.locs[LOC_MATRIX_VIEW], fboViews[i]); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, cubemap.id, 0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); GenDrawCube(); @@ -2607,8 +2604,6 @@ Texture2D GenTextureCubemap(Texture2D skyHDR, int size) glViewport(0, 0, GetScreenWidth(), GetScreenHeight()); //glEnable(GL_CULL_FACE); - UnloadShader(shader); - cubemap.width = size; cubemap.height = size; @@ -2616,18 +2611,13 @@ Texture2D GenTextureCubemap(Texture2D skyHDR, int size) } // Generate irradiance texture using cubemap data -Texture2D GenTextureIrradiance(Texture2D cubemap, int size) +Texture2D GenTextureIrradiance(Shader shader, Texture2D cubemap, int size) { Texture2D irradiance = { 0 }; - #define PATH_SKYBOX_VS "resources/shaders/skybox.vs" // Path to skybox vertex shader - #define PATH_IRRADIANCE_FS "resources/shaders/irradiance.fs" // Path to irradiance (GI) calculation fragment shader - - Shader shader = LoadShader(PATH_SKYBOX_VS, PATH_IRRADIANCE_FS); - // Get irradiance shader locations - int projectionLoc = GetShaderLocation(shader, "projection"); - int viewLoc = GetShaderLocation(shader, "view"); + //int projectionLoc = GetShaderLocation(shader, "projection"); // Already set at SetShaderDefaultLocations() + //int viewLoc = GetShaderLocation(shader, "view"); // Already set at SetShaderDefaultLocations() int texmapLoc = GetShaderLocation(shader, "environmentMap"); // Set up shaders constant values @@ -2669,7 +2659,7 @@ Texture2D GenTextureIrradiance(Texture2D cubemap, int size) glUseProgram(shader.id); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_CUBE_MAP, cubemap.id); - SetShaderValueMatrix(shader, projectionLoc, fboProjection); + SetShaderValueMatrix(shader, shader.locs[LOC_MATRIX_PROJECTION], fboProjection); // Note: don't forget to configure the viewport to the capture dimensions glViewport(0, 0, size, size); @@ -2677,7 +2667,7 @@ Texture2D GenTextureIrradiance(Texture2D cubemap, int size) for (unsigned int i = 0; i < 6; i++) { - SetShaderValueMatrix(shader, viewLoc, fboViews[i]); + SetShaderValueMatrix(shader, shader.locs[LOC_MATRIX_VIEW], fboViews[i]); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, irradiance.id, 0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); GenDrawCube(); @@ -2688,9 +2678,7 @@ Texture2D GenTextureIrradiance(Texture2D cubemap, int size) // Reset viewport dimensions to default glViewport(0, 0, GetScreenWidth(), GetScreenHeight()); - - UnloadShader(shader); - + irradiance.width = size; irradiance.height = size; @@ -2698,18 +2686,13 @@ Texture2D GenTextureIrradiance(Texture2D cubemap, int size) } // Generate prefilter texture using cubemap data -Texture2D GenTexturePrefilter(Texture2D cubemap, int size) +Texture2D GenTexturePrefilter(Shader shader, Texture2D cubemap, int size) { Texture2D prefilter = { 0 }; - #define PATH_SKYBOX_VS "resources/shaders/skybox.vs" // Path to skybox vertex shader - #define PATH_PREFILTER_FS "resources/shaders/prefilter.fs" // Path to reflection prefilter calculation fragment shader - - Shader shader = LoadShader(PATH_SKYBOX_VS, PATH_PREFILTER_FS); - // Get prefilter shader locations - int projectionLoc = GetShaderLocation(shader, "projection"); - int viewLoc = GetShaderLocation(shader, "view"); + //int projectionLoc = GetShaderLocation(shader, "projection"); // Already set at SetShaderDefaultLocations() + //int viewLoc = GetShaderLocation(shader, "view"); // Already set at SetShaderDefaultLocations() int roughnessLoc = GetShaderLocation(shader, "roughness"); int texmapLoc = GetShaderLocation(shader, "environmentMap"); @@ -2754,7 +2737,7 @@ Texture2D GenTexturePrefilter(Texture2D cubemap, int size) glUseProgram(shader.id); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_CUBE_MAP, cubemap.id); - SetShaderValueMatrix(shader, projectionLoc, fboProjection); + SetShaderValueMatrix(shader, shader.locs[LOC_MATRIX_PROJECTION], fboProjection); glBindFramebuffer(GL_FRAMEBUFFER, fbo); @@ -2775,7 +2758,7 @@ Texture2D GenTexturePrefilter(Texture2D cubemap, int size) for (unsigned int i = 0; i < 6; ++i) { - SetShaderValueMatrix(shader, viewLoc, fboViews[i]); + SetShaderValueMatrix(shader, shader.locs[LOC_MATRIX_VIEW], fboViews[i]); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, prefilter.id, mip); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); GenDrawCube(); @@ -2787,9 +2770,7 @@ Texture2D GenTexturePrefilter(Texture2D cubemap, int size) // Reset viewport dimensions to default glViewport(0, 0, GetScreenWidth(), GetScreenHeight()); - - UnloadShader(shader); - + prefilter.width = size; prefilter.height = size; @@ -2797,15 +2778,10 @@ Texture2D GenTexturePrefilter(Texture2D cubemap, int size) } // Generate BRDF texture using cubemap data -Texture2D GenTextureBRDF(Texture2D cubemap, int size) +Texture2D GenTextureBRDF(Shader shader, Texture2D cubemap, int size) { Texture2D brdf = { 0 }; - #define PATH_BRDF_VS "resources/shaders/brdf.vs" // Path to bidirectional reflectance distribution function vertex shader - #define PATH_BRDF_FS "resources/shaders/brdf.fs" // Path to bidirectional reflectance distribution function fragment shader - - Shader shader = LoadShader(PATH_BRDF_VS, PATH_BRDF_FS); - // Generate BRDF convolution texture glGenTextures(1, &brdf.id); glBindTexture(GL_TEXTURE_2D, brdf.id); @@ -2835,8 +2811,6 @@ Texture2D GenTextureBRDF(Texture2D cubemap, int size) // Reset viewport dimensions to default glViewport(0, 0, GetScreenWidth(), GetScreenHeight()); - UnloadShader(shader); - brdf.width = size; brdf.height = size; @@ -3380,6 +3354,8 @@ static void SetShaderDefaultLocations(Shader *shader) // Get handles to GLSL uniform locations (vertex shader) shader->locs[LOC_MATRIX_MVP] = glGetUniformLocation(shader->id, "mvpMatrix"); + shader->locs[LOC_MATRIX_PROJECTION] = glGetUniformLocation(shader->id, "projection"); + shader->locs[LOC_MATRIX_VIEW] = glGetUniformLocation(shader->id, "view"); // Get handles to GLSL uniform locations (fragment shader) shader->locs[LOC_COLOR_DIFFUSE] = glGetUniformLocation(shader->id, "colDiffuse"); @@ -3894,9 +3870,9 @@ static void GenDrawQuad(void) // Link vertex attributes glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (GLvoid*)0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5*sizeof(float), (void *)0); glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (GLvoid*)(3*sizeof(GLfloat))); + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5*sizeof(float), (void *)(3*sizeof(float))); // Draw quad glBindVertexArray(quadVAO); @@ -3908,79 +3884,76 @@ static void GenDrawQuad(void) } // Renders a 1x1 3D cube in NDC -GLuint cubeVAO = 0; -GLuint cubeVBO = 0; static void GenDrawCube(void) { - // Lazy initialization - if (cubeVAO == 0) - { - GLfloat vertices[] = { - -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, - 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, - 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, - 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, - -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, - -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, - -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, - 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, - 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, - 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, - -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, - -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, - -1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, - -1.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, - -1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, - -1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, - -1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, - -1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, - 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, - 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, - 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, - 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, - 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, - 1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, - -1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, - 1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f, - 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, - 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, - -1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, - -1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, - -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, - 1.0f, 1.0f , 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, - 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, - 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, - -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, - -1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f - }; - - // Set up cube VAO - glGenVertexArrays(1, &cubeVAO); - glGenBuffers(1, &cubeVBO); - - // Fill buffer - glBindBuffer(GL_ARRAY_BUFFER, cubeVBO); - glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); - - // Link vertex attributes - glBindVertexArray(cubeVAO); - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), (GLvoid*)0); - glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), (GLvoid*)(3*sizeof(GLfloat))); - glEnableVertexAttribArray(2); - glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), (GLvoid*)(6*sizeof(GLfloat))); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindVertexArray(0); - } + unsigned int cubeVAO = 0; + unsigned int cubeVBO = 0; + + float vertices[] = { + -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, + 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, + 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, + 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f, + -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, + -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, + -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, + 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, + 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, + -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, + -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, + -1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, + -1.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, + -1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, + -1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f, + -1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, + -1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f, + 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, + 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, + 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, + 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, + 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, + 1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, + -1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, + 1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f, + 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, + 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, + -1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, + -1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f, + -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, + 1.0f, 1.0f , 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, + 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, + -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, + -1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f + }; + + // Set up cube VAO + glGenVertexArrays(1, &cubeVAO); + glGenBuffers(1, &cubeVBO); + + // Fill buffer + glBindBuffer(GL_ARRAY_BUFFER, cubeVBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); + + // Link vertex attributes + glBindVertexArray(cubeVAO); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8*sizeof(float), (void *)0); + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8*sizeof(float), (void *)(3*sizeof(float))); + glEnableVertexAttribArray(2); + glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8*sizeof(float), (void *)(6*sizeof(float))); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); // Draw cube glBindVertexArray(cubeVAO); glDrawArrays(GL_TRIANGLES, 0, 36); glBindVertexArray(0); - //glDeleteBuffers(1, &cubeVBO); - //glDeleteVertexArrays(1, &cubeVAO); + glDeleteBuffers(1, &cubeVBO); + glDeleteVertexArrays(1, &cubeVAO); } #if defined(SUPPORT_VR_SIMULATOR) -- cgit v1.2.3 From 2679c4ae9b2fefdb0c150a7cd576d5d3297b027b Mon Sep 17 00:00:00 2001 From: raysan5 Date: Fri, 21 Jul 2017 09:34:09 +0200 Subject: Review mesh loading and textures generation --- examples/models/models_cubicmap.c | 2 +- examples/models/models_material_pbr.c | 5 +++++ examples/models/models_skybox.c | 31 ++++++++++++++----------------- src/models.c | 20 +++++++++++++++++--- src/raylib.h | 13 ++++++++----- src/rlgl.c | 12 ++++-------- 6 files changed, 49 insertions(+), 34 deletions(-) (limited to 'src/raylib.h') diff --git a/examples/models/models_cubicmap.c b/examples/models/models_cubicmap.c index 177cf890..268d480a 100644 --- a/examples/models/models_cubicmap.c +++ b/examples/models/models_cubicmap.c @@ -27,7 +27,7 @@ int main() Texture2D cubicmap = LoadTextureFromImage(image); // Convert image to texture to display (VRAM) Mesh mesh = GenMeshCubicmap(image, (Vector3){ 1.0f, 1.0f, 1.0f }); - Model model = LoadModelFromMesh(mesh, false); + Model model = LoadModelFromMesh(mesh); // NOTE: By default each cube is mapped to one part of texture atlas Texture2D texture = LoadTexture("resources/cubicmap_atlas.png"); // Load map texture diff --git a/examples/models/models_material_pbr.c b/examples/models/models_material_pbr.c index f443e245..d55aa773 100644 --- a/examples/models/models_material_pbr.c +++ b/examples/models/models_material_pbr.c @@ -142,6 +142,11 @@ static Material LoadMaterialPBR(Color albedo, float metalness, float roughness) Shader shdrIrradiance = LoadShader(PATH_SKYBOX_VS, PATH_IRRADIANCE_FS); Shader shdrPrefilter = LoadShader(PATH_SKYBOX_VS, PATH_PREFILTER_FS); Shader shdrBRDF = LoadShader(PATH_BRDF_VS, PATH_BRDF_FS); + + // Setup required shader locations + SetShaderValuei(shdrCubemap, GetShaderLocation(shdrCubemap, "equirectangularMap"), (int[1]){ 0 }, 1); + SetShaderValuei(shdrIrradiance, GetShaderLocation(shdrIrradiance, "environmentMap"), (int[1]){ 0 }, 1); + SetShaderValuei(shdrPrefilter, GetShaderLocation(shdrPrefilter, "environmentMap"), (int[1]){ 0 }, 1); Texture2D texHDR = LoadTexture("resources/pinetree.hdr"); Texture2D cubemap = GenTextureCubemap(shdrCubemap, texHDR, CUBEMAP_SIZE); diff --git a/examples/models/models_skybox.c b/examples/models/models_skybox.c index d347854f..500cb19b 100644 --- a/examples/models/models_skybox.c +++ b/examples/models/models_skybox.c @@ -24,24 +24,24 @@ int main() // Define the camera to look into our 3d world Camera camera = {{ 1.0f, 1.0f, 1.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f }; - // Load skybox model and shader + // Load skybox model Mesh cube = GenMeshCube(1.0f, 1.0f, 1.0f); - Model skybox = LoadModelFromMesh(cube, false); + Model skybox = LoadModelFromMesh(cube); + + // Load skybox shader and set required locations + // NOTE: Some locations are automatically set at shader loading skybox.material.shader = LoadShader("resources/shaders/skybox.vs", "resources/shaders/skybox.fs"); - - Texture2D texHDR = LoadTexture("resources/pinetree.hdr"); - skybox.material.maps[MAP_CUBEMAP].texture = GenTextureCubemap(texHDR, 512); SetShaderValuei(skybox.material.shader, GetShaderLocation(skybox.material.shader, "environmentMap"), (int[1]){ MAP_CUBEMAP }, 1); - // Get skybox shader locations - skybox.material.shader.locs[LOC_MATRIX_PROJECTION] = GetShaderLocation(skybox.material.shader, "projection"); - skybox.material.shader.locs[LOC_MATRIX_VIEW] = GetShaderLocation(skybox.material.shader, "view"); - - // Then before rendering, configure the viewport to the actual screen dimensions - Matrix proj = MatrixPerspective(60.0, (double)GetScreenWidth()/(double)GetScreenHeight(), 0.01, 1000.0); - MatrixTranspose(&proj); - SetShaderValueMatrix(skybox.material.shader, skybox.material.shader.locs[LOC_MATRIX_PROJECTION], proj); - + // Load cubemap shader and setup required shader locations + Shader shdrCubemap = LoadShader("resources/shaders/cubemap.vs", "resources/shaders/cubemap.fs"); + SetShaderValuei(shdrCubemap, GetShaderLocation(shdrCubemap, "environmentMap"), (int[1]){ 0 }, 1); + + Texture2D texHDR = LoadTexture("resources/pinetree.hdr"); + skybox.material.maps[MAP_CUBEMAP].texture = GenTextureCubemap(shdrCubemap, texHDR, 512); + + UnloadShader(shdrCubemap); // Cubemap generation shader not required any more + SetCameraMode(camera, CAMERA_ORBITAL); // Set an orbital camera mode SetTargetFPS(60); // Set our game to run at 60 frames-per-second @@ -53,9 +53,6 @@ int main() // Update //---------------------------------------------------------------------------------- UpdateCamera(&camera); // Update camera - - Matrix view = MatrixLookAt(camera.position, camera.target, camera.up); - SetShaderValueMatrix(skybox.material.shader, skybox.material.shader.locs[LOC_MATRIX_VIEW], view); //---------------------------------------------------------------------------------- // Draw diff --git a/src/models.c b/src/models.c index 03e0cb45..7dce9fa6 100644 --- a/src/models.c +++ b/src/models.c @@ -597,12 +597,13 @@ Model LoadModel(const char *fileName) } // Load model from generated mesh -Model LoadModelFromMesh(Mesh mesh, bool dynamic) +// WARNING: A shallow copy of mesh is generated, passed by value, +// as long as struct contains pointers to data and some values, we get a copy +// of mesh pointing to same data as original version... be careful! +Model LoadModelFromMesh(Mesh mesh) { Model model = { 0 }; - rlLoadMesh(&mesh, dynamic); - model.mesh = mesh; model.transform = MatrixIdentity(); model.material = LoadMaterialDefault(); @@ -646,6 +647,7 @@ void UnloadMesh(Mesh *mesh) } // Generated cuboid mesh +// NOTE: Vertex data is uploaded to GPU Mesh GenMeshCube(float width, float height, float length) { Mesh mesh = { 0 }; @@ -759,11 +761,15 @@ Mesh GenMeshCube(float width, float height, float length) mesh.vertexCount = 24; mesh.triangleCount = 12; + + // Upload vertex data to GPU (static mesh) + rlLoadMesh(&mesh, false); return mesh; } // Generate a mesh from heightmap +// NOTE: Vertex data is uploaded to GPU Mesh GenMeshHeightmap(Image heightmap, Vector3 size) { #define GRAY_VALUE(c) ((c.r+c.g+c.b)/3) @@ -865,10 +871,15 @@ Mesh GenMeshHeightmap(Image heightmap, Vector3 size) } free(pixels); + + // Upload vertex data to GPU (static mesh) + rlLoadMesh(&mesh, false); return mesh; } +// Generate a cubes mesh from pixel data +// NOTE: Vertex data is uploaded to GPU Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize) { Mesh mesh = { 0 }; @@ -1219,6 +1230,9 @@ Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize) free(mapTexcoords); free(cubicmapPixels); // Free image pixel data + + // Upload vertex data to GPU (static mesh) + rlLoadMesh(&mesh, false); return mesh; } diff --git a/src/raylib.h b/src/raylib.h index 22ef06cb..cc5b0bb6 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -409,10 +409,11 @@ typedef struct BoundingBox { } BoundingBox; // Vertex data definning a mesh +// NOTE: Data stored in CPU memory (and GPU) typedef struct Mesh { int vertexCount; // Number of vertices stored in arrays int triangleCount; // Number of triangles stored (indexed or not) - + float *vertices; // Vertex position (XYZ - 3 components per vertex) (shader-location = 0) float *texcoords; // Vertex texture coordinates (UV - 2 components per vertex) (shader-location = 1) float *texcoords2; // Vertex second texture coordinates (useful for lightmaps) (shader-location = 5) @@ -981,15 +982,19 @@ RLAPI void DrawGizmo(Vector3 position); // Model loading/unloading functions RLAPI Model LoadModel(const char *fileName); // Load model from files (mesh and material) -RLAPI Model LoadModelFromMesh(Mesh mesh, bool dynamic); // Load model from generated mesh +RLAPI Model LoadModelFromMesh(Mesh mesh); // Load model from generated mesh RLAPI void UnloadModel(Model model); // Unload model from memory (RAM and/or VRAM) // Mesh loading/unloading functions RLAPI Mesh LoadMesh(const char *fileName); // Load mesh from file -//RLAPI void UpdateMesh(Mesh *mesh, int type, void *data); // Update mesh data (CPU and GPU) RLAPI void UnloadMesh(Mesh *mesh); // Unload mesh from memory (RAM and/or VRAM) +//RLAPI Mesh GenMeshPlane(float width, float length, int resX, int resZ); // Generate plane mesh (with desired subdivisions) RLAPI Mesh GenMeshCube(float width, float height, float length); // Generate cuboid mesh +//RLAPI Mesh GenMeshSphere(float radius, int rings, int slices); // Generate sphere mesh (standard sphere) +//RLAPI Mesh GenMeshCylinder(float radiusTop, float radiusBottom, float height, int slices); // Generate cylinder mesh +//RLAPI Mesh GenMeshTorus(float radius1, float radius2, int radSeg, int sides); // Generate torus mesh +//RLAPI Mesh GenMeshTube(float radius1, float radius2, float height, int sides); // Generate tube mesh RLAPI Mesh GenMeshHeightmap(Image heightmap, Vector3 size); // Generate heightmap mesh from image data RLAPI Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize); // Generate cubes-based map mesh from image data @@ -997,8 +1002,6 @@ RLAPI Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize); RLAPI Material LoadMaterial(const char *fileName); // Load material from file RLAPI Material LoadMaterialDefault(void); // Load default material (Supports: DIFFUSE, SPECULAR, NORMAL maps) RLAPI void UnloadMaterial(Material material); // Unload material from GPU memory (VRAM) -RLAPI void SetMaterialTexture(Material *mat, int mapType, Texture2D texture); // Set material texture -RLAPI void UnsetMaterialTexture(Material *mat, int mapType); // Unset texture from material and unload it from GPU // Model drawing functions RLAPI void DrawModel(Model model, Vector3 position, float scale, Color tint); // Draw a model (with texture if set) diff --git a/src/rlgl.c b/src/rlgl.c index 44b20b61..3160c744 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -2520,10 +2520,7 @@ Texture2D GenTextureCubemap(Shader shader, Texture2D skyHDR, int size) Texture2D cubemap = { 0 }; #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) // NOTE: SetShaderDefaultLocations() already setups locations for projection and view Matrix in shader - // TODO: Locations should be taken out of this function... too shader dependant... - SetShaderValuei(shader, GetShaderLocation(shader, "environmentMap"), (int[1]){ 0 }, 1); - - SetShaderValuei(shader, texmapLoc, (int[1]){ 0 }, 1); // Set default active texture to 0 + // Other locations should be setup externally in shader before calling the function // Set up depth face culling and cubemap seamless glDisable(GL_CULL_FACE); @@ -2600,8 +2597,7 @@ Texture2D GenTextureIrradiance(Shader shader, Texture2D cubemap, int size) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) // NOTE: SetShaderDefaultLocations() already setups locations for projection and view Matrix in shader - // TODO: Locations should be taken out of this function... too shader dependant... - SetShaderValuei(shader, GetShaderLocation(shader, "environmentMap"), (int[1]){ 0 }, 1); + // Other locations should be setup externally in shader before calling the function // Setup framebuffer unsigned int fbo, rbo; @@ -2672,9 +2668,9 @@ Texture2D GenTexturePrefilter(Shader shader, Texture2D cubemap, int size) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) // NOTE: SetShaderDefaultLocations() already setups locations for projection and view Matrix in shader + // Other locations should be setup externally in shader before calling the function // TODO: Locations should be taken out of this function... too shader dependant... - int roughnessLoc = GetShaderLocation(shader, "roughness"); - SetShaderValuei(shader, GetShaderLocation(shader, "environmentMap"), (int[1]){ 0 }, 1); + int roughnessLoc = GetShaderLocation(shader, "roughness"); // Setup framebuffer unsigned int fbo, rbo; -- cgit v1.2.3 From 38d9fcb08ef81cd5a3ab93df825eac7714d03e45 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Fri, 21 Jul 2017 15:25:35 +0200 Subject: Moved some functions to raymath Exposed some raymath useful functions to raylib API --- src/core.c | 39 --------------------------------------- src/raylib.h | 9 +++++++-- src/raymath.h | 42 ++++++++++++++++++++++++++++++++++++++++++ src/rlgl.c | 38 +++----------------------------------- src/rlgl.h | 1 - 5 files changed, 52 insertions(+), 77 deletions(-) (limited to 'src/raylib.h') diff --git a/src/core.c b/src/core.c index fc653195..32d4666b 100644 --- a/src/core.c +++ b/src/core.c @@ -1098,45 +1098,6 @@ float *ColorToFloat(Color color) return buffer; } -// Converts Vector3 to float array -float *VectorToFloat(Vector3 vec) -{ - static float buffer[3]; - - buffer[0] = vec.x; - buffer[1] = vec.y; - buffer[2] = vec.z; - - return buffer; -} - -// NOTE: Returned vector is a transposed version of the Matrix struct, -// it should be this way because, despite raymath use OpenGL column-major convention, -// Matrix struct memory alignment and variables naming are not coherent -float *MatrixToFloat(Matrix mat) -{ - static float buffer[16]; - - buffer[0] = mat.m0; - buffer[1] = mat.m4; - buffer[2] = mat.m8; - buffer[3] = mat.m12; - buffer[4] = mat.m1; - buffer[5] = mat.m5; - buffer[6] = mat.m9; - buffer[7] = mat.m13; - buffer[8] = mat.m2; - buffer[9] = mat.m6; - buffer[10] = mat.m10; - buffer[11] = mat.m14; - buffer[12] = mat.m3; - buffer[13] = mat.m7; - buffer[14] = mat.m11; - buffer[15] = mat.m15; - - return buffer; -} - // Returns a Color struct from hexadecimal value Color GetColor(int hexValue) { diff --git a/src/raylib.h b/src/raylib.h index cc5b0bb6..ec5e61fd 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -742,8 +742,13 @@ RLAPI int GetHexValue(Color color); // Returns hex RLAPI Color GetColor(int hexValue); // Returns a Color struct from hexadecimal value RLAPI Color Fade(Color color, float alpha); // Color fade-in or fade-out, alpha goes from 0.0f to 1.0f RLAPI float *ColorToFloat(Color color); // Converts Color to float array and normalizes -RLAPI float *VectorToFloat(Vector3 vec); // Converts Vector3 to float array -RLAPI float *MatrixToFloat(Matrix mat); // Converts Matrix to float array + +// Math useful functions (available from raymath.h) +RLAPI float *VectorToFloat(Vector3 vec); // Returns Vector3 as float array +RLAPI float *MatrixToFloat(Matrix mat); // Returns Matrix as float array +RLAPI Vector3 VectorZero(void); // Vector with components value 0.0f +RLAPI Vector3 VectorOne(void); // Vector with components value 1.0f +RLAPI Matrix MatrixIdentity(void); // Returns identity matrix // Misc. functions RLAPI void ShowLogo(void); // Activate raylib logo at startup (can be done with flags) diff --git a/src/raymath.h b/src/raymath.h index 70d1bedd..ec824408 100644 --- a/src/raymath.h +++ b/src/raymath.h @@ -154,6 +154,7 @@ RMDEF Vector3 VectorReflect(Vector3 vector, Vector3 normal); // Calculate ref RMDEF Vector3 VectorMin(Vector3 vec1, Vector3 vec2); // Return min value for each pair of components RMDEF Vector3 VectorMax(Vector3 vec1, Vector3 vec2); // Return max value for each pair of components RMDEF Vector3 VectorBarycenter(Vector3 p, Vector3 a, Vector3 b, Vector3 c); // Barycenter coords for p in triangle abc +RMDEF float *VectorToFloat(Vector3 vec); // Returns Vector3 as float array //------------------------------------------------------------------------------------ // Functions Declaration to work with Matrix @@ -177,6 +178,7 @@ RMDEF Matrix MatrixFrustum(double left, double right, double bottom, double top, RMDEF Matrix MatrixPerspective(double fovy, double aspect, double near, double far); // Returns perspective projection matrix RMDEF Matrix MatrixOrtho(double left, double right, double bottom, double top, double near, double far); // Returns orthographic projection matrix RMDEF Matrix MatrixLookAt(Vector3 position, Vector3 target, Vector3 up); // Returns camera look-at matrix (view matrix) +RMDEF float *MatrixToFloat(Matrix mat); // Returns float array of Matrix data //------------------------------------------------------------------------------------ // Functions Declaration to work with Quaternions @@ -502,6 +504,18 @@ RMDEF Vector3 VectorBarycenter(Vector3 p, Vector3 a, Vector3 b, Vector3 c) return result; } +// Returns Vector3 as float array +RMDEF float *VectorToFloat(Vector3 vec) +{ + static float buffer[3]; + + buffer[0] = vec.x; + buffer[1] = vec.y; + buffer[2] = vec.z; + + return buffer; +} + //---------------------------------------------------------------------------------- // Module Functions Definition - Matrix math //---------------------------------------------------------------------------------- @@ -943,6 +957,34 @@ RMDEF Matrix MatrixLookAt(Vector3 eye, Vector3 target, Vector3 up) return result; } +// Returns float array of matrix data +// NOTE: Returned vector is a transposed version of the Matrix struct, +// it should be this way because, despite raymath use OpenGL column-major convention, +// Matrix struct memory alignment and variables naming are not coherent +RMDEF float *MatrixToFloat(Matrix mat) +{ + static float buffer[16]; + + buffer[0] = mat.m0; + buffer[1] = mat.m4; + buffer[2] = mat.m8; + buffer[3] = mat.m12; + buffer[4] = mat.m1; + buffer[5] = mat.m5; + buffer[6] = mat.m9; + buffer[7] = mat.m13; + buffer[8] = mat.m2; + buffer[9] = mat.m6; + buffer[10] = mat.m10; + buffer[11] = mat.m14; + buffer[12] = mat.m3; + buffer[13] = mat.m7; + buffer[14] = mat.m11; + buffer[15] = mat.m15; + + return buffer; +} + //---------------------------------------------------------------------------------- // Module Functions Definition - Quaternion math //---------------------------------------------------------------------------------- diff --git a/src/rlgl.c b/src/rlgl.c index a27645dd..54b30b90 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -360,10 +360,6 @@ static int GenerateMipmaps(unsigned char *data, int baseWidth, int baseHeight); static Color *GenNextMipmap(Color *srcData, int srcWidth, int srcHeight); #endif -#if defined(RLGL_STANDALONE) -float *MatrixToFloat(Matrix mat); // Converts Matrix to float array -#endif - //---------------------------------------------------------------------------------- // Module Functions Definition - Matrix operations //---------------------------------------------------------------------------------- @@ -477,15 +473,15 @@ void rlScalef(float x, float y, float z) } // Multiply the current matrix by another matrix -void rlMultMatrixf(float *m) +void rlMultMatrixf(float *mat) { // Matrix creation from array - Matrix mat = { m[0], m[1], m[2], m[3], + Matrix mat2 = { m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8], m[9], m[10], m[11], m[12], m[13], m[14], m[15] }; - *currentMatrix = MatrixMultiply(*currentMatrix, mat); + *currentMatrix = MatrixMultiply(*currentMatrix, mat2); } // Multiply the current matrix by a perspective matrix generated by parameters @@ -4176,32 +4172,4 @@ void TraceLog(int msgType, const char *text, ...) if (msgType == LOG_ERROR) exit(1); } - -// Converts Matrix to float array -// NOTE: Returned vector is a transposed version of the Matrix struct, -// it should be this way because, despite raymath use OpenGL column-major convention, -// Matrix struct memory alignment and variables naming are not coherent -float *MatrixToFloat(Matrix mat) -{ - static float buffer[16]; - - buffer[0] = mat.m0; - buffer[1] = mat.m4; - buffer[2] = mat.m8; - buffer[3] = mat.m12; - buffer[4] = mat.m1; - buffer[5] = mat.m5; - buffer[6] = mat.m9; - buffer[7] = mat.m13; - buffer[8] = mat.m2; - buffer[9] = mat.m6; - buffer[10] = mat.m10; - buffer[11] = mat.m14; - buffer[12] = mat.m3; - buffer[13] = mat.m7; - buffer[14] = mat.m11; - buffer[15] = mat.m15; - - return buffer; -} #endif diff --git a/src/rlgl.h b/src/rlgl.h index a9ee6ec6..84ece706 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -465,7 +465,6 @@ void BeginVrDrawing(void); // Begin VR stereo rende void EndVrDrawing(void); // End VR stereo rendering void TraceLog(int msgType, const char *text, ...); // Show trace log messages (LOG_INFO, LOG_WARNING, LOG_ERROR, LOG_DEBUG) -float *MatrixToFloat(Matrix mat); // Converts Matrix to float array #endif #ifdef __cplusplus -- cgit v1.2.3 From c756227e11ec3a16b6c3ce09826e5c8162cfd031 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sat, 22 Jul 2017 10:44:24 +0200 Subject: Remove BOM from file encoding --- src/raylib.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/raylib.h') diff --git a/src/raylib.h b/src/raylib.h index ec5e61fd..72a8f763 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -1,4 +1,4 @@ -/********************************************************************************************** +/********************************************************************************************** * * raylib v1.8.0 * -- cgit v1.2.3 From a766e2c4808a554f5b6cfd07e6c4dceef711c9f8 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sat, 22 Jul 2017 22:15:50 +0200 Subject: Updated Vector math to new naming --- src/core.c | 4 +-- src/models.c | 80 ++++++++++++++++++++++++++++++------------------------------ src/raylib.h | 4 +-- src/rlgl.c | 6 ++--- 4 files changed, 47 insertions(+), 47 deletions(-) (limited to 'src/raylib.h') diff --git a/src/core.c b/src/core.c index 48c46dfd..4a95c660 100644 --- a/src/core.c +++ b/src/core.c @@ -990,8 +990,8 @@ Ray GetMouseRay(Vector2 mousePosition, Camera camera) Vector3 farPoint = rlUnproject((Vector3){ deviceCoords.x, deviceCoords.y, 1.0f }, matProj, matView); // Calculate normalized direction vector - Vector3 direction = VectorSubtract(farPoint, nearPoint); - VectorNormalize(&direction); + Vector3 direction = Vector3Subtract(farPoint, nearPoint); + Vector3Normalize(&direction); // Apply calculated vectors to ray ray.position = camera.position; diff --git a/src/models.c b/src/models.c index 47175b2c..4ab27926 100644 --- a/src/models.c +++ b/src/models.c @@ -1360,16 +1360,16 @@ void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle sourceRec, Vec | | d-------c */ - VectorScale(&right, sizeRatio.x/2); - VectorScale(&up, sizeRatio.y/2); + Vector3Scale(&right, sizeRatio.x/2); + Vector3Scale(&up, sizeRatio.y/2); - Vector3 p1 = VectorAdd(right, up); - Vector3 p2 = VectorSubtract(right, up); + Vector3 p1 = Vector3Add(right, up); + Vector3 p2 = Vector3Subtract(right, up); - Vector3 a = VectorSubtract(center, p2); - Vector3 b = VectorAdd(center, p1); - Vector3 c = VectorAdd(center, p2); - Vector3 d = VectorSubtract(center, p1); + Vector3 a = Vector3Subtract(center, p2); + Vector3 b = Vector3Add(center, p1); + Vector3 c = Vector3Add(center, p2); + Vector3 d = Vector3Subtract(center, p1); rlEnableTexture(texture.id); @@ -1468,9 +1468,9 @@ bool CheckCollisionRaySphere(Ray ray, Vector3 spherePosition, float sphereRadius { bool collision = false; - Vector3 raySpherePos = VectorSubtract(spherePosition, ray.position); - float distance = VectorLength(raySpherePos); - float vector = VectorDotProduct(raySpherePos, ray.direction); + Vector3 raySpherePos = Vector3Subtract(spherePosition, ray.position); + float distance = Vector3Length(raySpherePos); + float vector = Vector3DotProduct(raySpherePos, ray.direction); float d = sphereRadius*sphereRadius - (distance*distance - vector*vector); if (d >= 0.0f) collision = true; @@ -1483,9 +1483,9 @@ bool CheckCollisionRaySphereEx(Ray ray, Vector3 spherePosition, float sphereRadi { bool collision = false; - Vector3 raySpherePos = VectorSubtract(spherePosition, ray.position); - float distance = VectorLength(raySpherePos); - float vector = VectorDotProduct(raySpherePos, ray.direction); + Vector3 raySpherePos = Vector3Subtract(spherePosition, ray.position); + float distance = Vector3Length(raySpherePos); + float vector = Vector3DotProduct(raySpherePos, ray.direction); float d = sphereRadius*sphereRadius - (distance*distance - vector*vector); if (d >= 0.0f) collision = true; @@ -1498,8 +1498,8 @@ bool CheckCollisionRaySphereEx(Ray ray, Vector3 spherePosition, float sphereRadi if (distance < sphereRadius) collisionDistance = vector + sqrtf(d); else collisionDistance = vector - sqrtf(d); - VectorScale(&offset, collisionDistance); - Vector3 cPoint = VectorAdd(ray.position, offset); + Vector3Scale(&offset, collisionDistance); + Vector3 cPoint = Vector3Add(ray.position, offset); collisionPoint->x = cPoint.x; collisionPoint->y = cPoint.y; @@ -1582,14 +1582,14 @@ RayHitInfo GetCollisionRayTriangle(Ray ray, Vector3 p1, Vector3 p2, Vector3 p3) RayHitInfo result = {0}; // Find vectors for two edges sharing V1 - edge1 = VectorSubtract(p2, p1); - edge2 = VectorSubtract(p3, p1); + edge1 = Vector3Subtract(p2, p1); + edge2 = Vector3Subtract(p3, p1); // Begin calculating determinant - also used to calculate u parameter - p = VectorCrossProduct(ray.direction, edge2); + p = Vector3CrossProduct(ray.direction, edge2); // If determinant is near zero, ray lies in plane of triangle or ray is parallel to plane of triangle - det = VectorDotProduct(edge1, p); + det = Vector3DotProduct(edge1, p); // Avoid culling! if ((det > -EPSILON) && (det < EPSILON)) return result; @@ -1597,24 +1597,24 @@ RayHitInfo GetCollisionRayTriangle(Ray ray, Vector3 p1, Vector3 p2, Vector3 p3) invDet = 1.0f/det; // Calculate distance from V1 to ray origin - tv = VectorSubtract(ray.position, p1); + tv = Vector3Subtract(ray.position, p1); // Calculate u parameter and test bound - u = VectorDotProduct(tv, p)*invDet; + u = Vector3DotProduct(tv, p)*invDet; // The intersection lies outside of the triangle if ((u < 0.0f) || (u > 1.0f)) return result; // Prepare to test v parameter - q = VectorCrossProduct(tv, edge1); + q = Vector3CrossProduct(tv, edge1); // Calculate V parameter and test bound - v = VectorDotProduct(ray.direction, q)*invDet; + v = Vector3DotProduct(ray.direction, q)*invDet; // The intersection lies outside of the triangle if ((v < 0.0f) || ((u + v) > 1.0f)) return result; - t = VectorDotProduct(edge2, q)*invDet; + t = Vector3DotProduct(edge2, q)*invDet; if (t > EPSILON) { @@ -1622,11 +1622,11 @@ RayHitInfo GetCollisionRayTriangle(Ray ray, Vector3 p1, Vector3 p2, Vector3 p3) result.hit = true; result.distance = t; result.hit = true; - result.normal = VectorCrossProduct(edge1, edge2); - VectorNormalize(&result.normal); + result.normal = Vector3CrossProduct(edge1, edge2); + Vector3Normalize(&result.normal); Vector3 rayDir = ray.direction; - VectorScale(&rayDir, t); - result.position = VectorAdd(ray.position, rayDir); + Vector3Scale(&rayDir, t); + result.position = Vector3Add(ray.position, rayDir); } return result; @@ -1646,11 +1646,11 @@ RayHitInfo GetCollisionRayGround(Ray ray, float groundHeight) if (t >= 0.0) { Vector3 rayDir = ray.direction; - VectorScale(&rayDir, t); + Vector3Scale(&rayDir, t); result.hit = true; result.distance = t; result.normal = (Vector3){ 0.0, 1.0, 0.0 }; - result.position = VectorAdd(ray.position, rayDir); + result.position = Vector3Add(ray.position, rayDir); } } @@ -1672,8 +1672,8 @@ BoundingBox CalculateBoundingBox(Mesh mesh) for (int i = 1; i < mesh.vertexCount; i++) { - minVertex = VectorMin(minVertex, (Vector3){ mesh.vertices[i*3], mesh.vertices[i*3 + 1], mesh.vertices[i*3 + 2] }); - maxVertex = VectorMax(maxVertex, (Vector3){ mesh.vertices[i*3], mesh.vertices[i*3 + 1], mesh.vertices[i*3 + 2] }); + minVertex = Vector3Min(minVertex, (Vector3){ mesh.vertices[i*3], mesh.vertices[i*3 + 1], mesh.vertices[i*3 + 2] }); + maxVertex = Vector3Max(maxVertex, (Vector3){ mesh.vertices[i*3], mesh.vertices[i*3 + 1], mesh.vertices[i*3 + 2] }); } } @@ -1888,8 +1888,8 @@ static Mesh LoadOBJ(const char *fileName) else { // If normals not defined, they are calculated from the 3 vertices [N = (V2 - V1) x (V3 - V1)] - Vector3 norm = VectorCrossProduct(VectorSubtract(midVertices[vCount[1]-1], midVertices[vCount[0]-1]), VectorSubtract(midVertices[vCount[2]-1], midVertices[vCount[0]-1])); - VectorNormalize(&norm); + Vector3 norm = Vector3CrossProduct(Vector3Subtract(midVertices[vCount[1]-1], midVertices[vCount[0]-1]), Vector3Subtract(midVertices[vCount[2]-1], midVertices[vCount[0]-1])); + Vector3Normalize(&norm); mesh.normals[nCounter] = norm.x; mesh.normals[nCounter + 1] = norm.y; @@ -1949,8 +1949,8 @@ static Mesh LoadOBJ(const char *fileName) Vector2 uv2 = { mesh.texcoords[uvCount + 4], mesh.texcoords[uvCount + 5] }; // Calculate edges of the triangle (position delta) - Vector3 deltaPos1 = VectorSubtract(v1, v0); - Vector3 deltaPos2 = VectorSubtract(v2, v0); + Vector3 deltaPos1 = Vector3Subtract(v1, v0); + Vector3 deltaPos2 = Vector3Subtract(v2, v0); // UV delta Vector2 deltaUV1 = { uv1.x - uv0.x, uv1.y - uv0.y }; @@ -1963,8 +1963,8 @@ static Mesh LoadOBJ(const char *fileName) // Vector3 b2 = { deltaPos1.x*deltaUV2.x, deltaPos1.y*deltaUV2.x, deltaPos1.z*deltaUV2.x }; // Calculate vertex tangent - Vector3 tangent = VectorSubtract(t1, t2); - VectorScale(&tangent, r); + Vector3 tangent = Vector3Subtract(t1, t2); + Vector3Scale(&tangent, r); // Apply calculated tangents data to mesh struct mesh.tangents[vCount + 0] = tangent.x; @@ -1980,7 +1980,7 @@ static Mesh LoadOBJ(const char *fileName) // TODO: add binormals to mesh struct and assign buffers id and locations properly /* // Calculate vertex binormal Vector3 binormal = VectorSubtract(b1, b2); - VectorScale(&binormal, r); + Vector3Scale(&binormal, r); // Apply calculated binormals data to mesh struct mesh.binormals[vCount + 0] = binormal.x; diff --git a/src/raylib.h b/src/raylib.h index 72a8f763..bad711d9 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -746,8 +746,8 @@ RLAPI float *ColorToFloat(Color color); // Converts Co // Math useful functions (available from raymath.h) RLAPI float *VectorToFloat(Vector3 vec); // Returns Vector3 as float array RLAPI float *MatrixToFloat(Matrix mat); // Returns Matrix as float array -RLAPI Vector3 VectorZero(void); // Vector with components value 0.0f -RLAPI Vector3 VectorOne(void); // Vector with components value 1.0f +RLAPI Vector3 Vector3Zero(void); // Vector with components value 0.0f +RLAPI Vector3 Vector3One(void); // Vector with components value 1.0f RLAPI Matrix MatrixIdentity(void); // Returns identity matrix // Misc. functions diff --git a/src/rlgl.c b/src/rlgl.c index 244badc9..e681ad50 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -455,7 +455,7 @@ void rlRotatef(float angleDeg, float x, float y, float z) Matrix matRotation = MatrixIdentity(); Vector3 axis = (Vector3){ x, y, z }; - VectorNormalize(&axis); + Vector3Normalize(&axis); matRotation = MatrixRotate(axis, angleDeg*DEG2RAD); *currentMatrix = MatrixMultiply(*currentMatrix, matRotation); @@ -553,7 +553,7 @@ void rlEnd(void) // This way, rlTranslatef(), rlRotatef()... behaviour is the same than OpenGL 1.1 // Apply transformation matrix to all temp vertices - for (int i = 0; i < tempBufferCount; i++) VectorTransform(&tempBuffer[i], *currentMatrix); + for (int i = 0; i < tempBufferCount; i++) Vector3Transform(&tempBuffer[i], *currentMatrix); // Deactivate tempBuffer usage to allow rlVertex3f do its job useTempBuffer = false; @@ -1178,7 +1178,7 @@ void rlglInit(int width, int height) // Init temp vertex buffer, used when transformation required (translate, rotate, scale) tempBuffer = (Vector3 *)malloc(sizeof(Vector3)*TEMP_VERTEX_BUFFER_SIZE); - for (int i = 0; i < TEMP_VERTEX_BUFFER_SIZE; i++) tempBuffer[i] = VectorZero(); + for (int i = 0; i < TEMP_VERTEX_BUFFER_SIZE; i++) tempBuffer[i] = Vector3Zero(); // Init draw calls tracking system draws = (DrawCall *)malloc(sizeof(DrawCall)*MAX_DRAWS_BY_TEXTURE); -- cgit v1.2.3 From 88839b093c47a478979eaf9a26a7341ff37d8b63 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sun, 6 Aug 2017 10:44:50 +0200 Subject: Added function DrawRectangleT() Usefult to draw rectangles using default font texture --- src/raylib.h | 1 + src/text.c | 19 ++++++++++++++----- 2 files changed, 15 insertions(+), 5 deletions(-) (limited to 'src/raylib.h') diff --git a/src/raylib.h b/src/raylib.h index bad711d9..85499eb1 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -952,6 +952,7 @@ RLAPI void DrawFPS(int posX, int posY); RLAPI void DrawText(const char *text, int posX, int posY, int fontSize, Color color); // Draw text (using default font) RLAPI void DrawTextEx(SpriteFont spriteFont, const char* text, Vector2 position, // Draw text using SpriteFont and additional parameters float fontSize, int spacing, Color tint); +RLAPI void DrawRectangleT(int posX, int posY, int width, int height, Color color); // Draw rectangle using text character // Text misc. functions RLAPI int MeasureText(const char *text, int fontSize); // Measure string width for default font diff --git a/src/text.c b/src/text.c index 7ef01c11..fe00ce86 100644 --- a/src/text.c +++ b/src/text.c @@ -139,10 +139,10 @@ extern void LoadDefaultFont(void) 0x04000404, 0x4100203c, 0x00000000, 0x00000800, 0xf7df7df0, 0x514bef85, 0xbefbefbe, 0x04513bef, 0x14414500, 0x494a2885, 0xa28a28aa, 0x04510820, 0xf44145f0, 0x474a289d, 0xa28a28aa, 0x04510be0, 0x14414510, 0x494a2884, 0xa28a28aa, 0x02910a00, 0xf7df7df0, 0xd14a2f85, 0xbefbe8aa, 0x011f7be0, 0x00000000, 0x00400804, 0x20080000, 0x00000000, 0x00000000, 0x00600f84, 0x20080000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xac000000, 0x00000f01, 0x00000000, 0x00000000, 0x24000000, 0x00000901, 0x00000000, 0x06000000, 0x24000000, 0x00000901, 0x00000000, 0x09108000, - 0x24fa28a2, 0x00000901, 0x00000000, 0x013e0000, 0x2242252a, 0x00000952, 0x00000000, 0x038a8000, 0x2422222a, 0x00000929, 0x00000000, 0x010a8000, - 0x2412252a, 0x00000901, 0x00000000, 0x010a8000, 0x24fbe8be, 0x00000901, 0x00000000, 0x0ebe8000, 0xac020000, 0x00000f01, 0x00000000, 0x00048000, - 0x0003e000, 0x00000000, 0x00000000, 0x00008000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000038, 0x8443b80e, 0x00203a03, + 0xac000000, 0x00000f01, 0x00000000, 0x00000000, 0x24000000, 0x00000f01, 0x00000000, 0x06000000, 0x24000000, 0x00000f01, 0x00000000, 0x09108000, + 0x24fa28a2, 0x00000f01, 0x00000000, 0x013e0000, 0x2242252a, 0x00000f52, 0x00000000, 0x038a8000, 0x2422222a, 0x00000f29, 0x00000000, 0x010a8000, + 0x2412252a, 0x00000f01, 0x00000000, 0x010a8000, 0x24fbe8be, 0x00000f01, 0x00000000, 0x0ebe8000, 0xac020000, 0x00000f01, 0x00000000, 0x00048000, + 0x0003e000, 0x00000f00, 0x00000000, 0x00008000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000038, 0x8443b80e, 0x00203a03, 0x02bea080, 0xf0000020, 0xc452208a, 0x04202b02, 0xf8029122, 0x07f0003b, 0xe44b388e, 0x02203a02, 0x081e8a1c, 0x0411e92a, 0xf4420be0, 0x01248202, 0xe8140414, 0x05d104ba, 0xe7c3b880, 0x00893a0a, 0x283c0e1c, 0x04500902, 0xc4400080, 0x00448002, 0xe8208422, 0x04500002, 0x80400000, 0x05200002, 0x083e8e00, 0x04100002, 0x804003e0, 0x07000042, 0xf8008400, 0x07f00003, 0x80400000, 0x04000022, 0x00000000, 0x00000000, 0x80400000, 0x04000002, @@ -255,7 +255,7 @@ extern void LoadDefaultFont(void) } defaultFont.baseSize = defaultFont.chars[0].rec.height; - + TraceLog(LOG_INFO, "[TEX ID %i] Default font loaded successfully", defaultFont.texture.id); } @@ -457,6 +457,14 @@ void DrawTextEx(SpriteFont spriteFont, const char *text, Vector2 position, float } } +// Draw rectangle using text character (char: 127) +// NOTE: Useful to avoid changing to default white texture +void DrawRectangleT(int posX, int posY, int width, int height, Color color) +{ + DrawTexturePro(GetDefaultFont().texture, GetDefaultFont().chars[95].rec, + (Rectangle){ posX, posY, width, height }, (Vector2){ 0, 0 }, 0.0f, color); +} + // Formatting of text with variables to 'embed' const char *FormatText(const char *text, ...) { @@ -632,6 +640,7 @@ static SpriteFont LoadImageFont(Image image, Color key, int firstChar) { if (!COLOR_EQUAL(pixels[y*image.width + x], key)) break; } + if (!COLOR_EQUAL(pixels[y*image.width + x], key)) break; } -- cgit v1.2.3