|
@@ -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
|