From d368403a131522a53c0dedd1ae4f24301898e96e Mon Sep 17 00:00:00 2001 From: raysan5 Date: Wed, 19 Jul 2017 10:09:34 +0200 Subject: [PATCH] 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 | 947 +++++++++++++------------- src/rlgl.h | 84 +-- 8 files changed, 658 insertions(+), 640 deletions(-) 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) { @@ -2944,6 +2528,321 @@ void SetMatrixModelview(Matrix 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) +{ + 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); + GenDrawCube(); + } + } + + // 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; +} + +// Generate BRDF texture using cubemap data +Texture2D GenTextureBRDF(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); + + 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) // NOTE: Only 3 blending modes supported, default blend mode is alpha void BeginBlendMode(int mode) @@ -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