aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRay <raysan5@gmail.com>2017-07-17 00:33:40 +0200
committerRay <raysan5@gmail.com>2017-07-17 00:33:40 +0200
commit6546474fa45234ed0a84f62be705d9a9aee43079 (patch)
tree7373f17e2a875a95e1844bca20b28d1a7a052fb9
parent025dab990770a0adc65f07399c6a106d59d24e46 (diff)
downloadraylib-6546474fa45234ed0a84f62be705d9a9aee43079.tar.gz
raylib-6546474fa45234ed0a84f62be705d9a9aee43079.zip
Manual integration of material-pbr into develop
-rw-r--r--examples/models/models_cubicmap.c10
-rw-r--r--examples/models/models_material_pbr.c185
-rw-r--r--examples/models/models_material_pbr.pngbin0 -> 193874 bytes
-rw-r--r--examples/models/models_skybox.c89
-rw-r--r--examples/models/models_skybox.pngbin0 -> 723949 bytes
-rw-r--r--examples/shaders/shaders_model_shader.c2
-rw-r--r--src/core.c10
-rw-r--r--src/models.c535
-rw-r--r--src/raylib.h125
-rw-r--r--src/rlgl.c952
-rw-r--r--src/rlgl.h205
-rw-r--r--src/shapes.c10
-rw-r--r--src/textures.c22
13 files changed, 1597 insertions, 548 deletions
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
--- /dev/null
+++ b/examples/models/models_material_pbr.png
Binary files 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
--- /dev/null
+++ b/examples/models/models_skybox.png
Binary files 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 <string.h> // 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;