aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorraysan5 <raysan5@gmail.com>2016-05-20 12:28:07 +0200
committerraysan5 <raysan5@gmail.com>2016-05-20 12:28:07 +0200
commitdcf5f45f687f2a534286aecd5e6471a0440b0c21 (patch)
tree42a5028ebab3277a8d46bdcf3fea2990e1aa590d /src
parentaf890cf21021e4a306bf3f6e4397496b95c1c93a (diff)
downloadraylib-dcf5f45f687f2a534286aecd5e6471a0440b0c21.tar.gz
raylib-dcf5f45f687f2a534286aecd5e6471a0440b0c21.zip
Add lighting system -IN PROGRESS-
Improved materials
Diffstat (limited to 'src')
-rw-r--r--src/models.c12
-rw-r--r--src/raylib.h30
-rw-r--r--src/rlgl.c167
-rw-r--r--src/rlgl.h25
4 files changed, 228 insertions, 6 deletions
diff --git a/src/models.c b/src/models.c
index 6d72d1e3..44e30390 100644
--- a/src/models.c
+++ b/src/models.c
@@ -732,6 +732,18 @@ Material LoadDefaultMaterial(void)
return material;
}
+// Load standard material (uses standard models shader)
+// NOTE: Standard shader supports multiple maps and lights
+Material LoadStandardMaterial(void)
+{
+ Material material = LoadDefaultMaterial();
+
+ //material.shader = GetStandardShader();
+
+ return material;
+}
+
+// Unload material from memory
void UnloadMaterial(Material material)
{
rlDeleteTextures(material.texDiffuse.id);
diff --git a/src/raylib.h b/src/raylib.h
index fc1914bb..d98a0797 100644
--- a/src/raylib.h
+++ b/src/raylib.h
@@ -422,13 +422,38 @@ typedef struct Material {
float normalDepth; // Normal map depth
} Material;
-// 3d Model type
+// Model type
typedef struct Model {
Mesh mesh; // Vertex data buffers (RAM and VRAM)
Matrix transform; // Local transform matrix
Material material; // Shader and textures data
} Model;
+// Light type
+// TODO: Review contained data to support different light types and features
+typedef struct LightData {
+ int id;
+ int type; // LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT
+ bool enabled;
+
+ Vector3 position;
+ Vector3 direction; // Used on LIGHT_DIRECTIONAL and LIGHT_SPOT (cone direction)
+ float attenuation; // Lost of light intensity with distance (use radius?)
+
+ Color diffuse; // Use Vector3 diffuse (including intensities)?
+ float intensity;
+
+ Color specular;
+ //float specFactor; // Specular intensity ?
+
+ //Color ambient; // Required?
+
+ float coneAngle; // SpotLight
+} LightData, *Light;
+
+// Light types
+typedef enum { LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT } LightType;
+
// Ray type (useful for raycast)
typedef struct Ray {
Vector3 position;
@@ -849,6 +874,9 @@ void SetShaderValueMatrix(Shader shader, int uniformLoc, Matrix mat); // S
void SetBlendMode(int mode); // Set blending mode (alpha, additive, multiplied)
+Light CreateLight(int type, Vector3 position, Color diffuse); // Create a new light, initialize it and add to pool
+void DestroyLight(Light light); // Destroy a light and take it out of the list
+
//----------------------------------------------------------------------------------
// Physics System Functions (Module: physac)
//----------------------------------------------------------------------------------
diff --git a/src/rlgl.c b/src/rlgl.c
index cc2b8942..e971d747 100644
--- a/src/rlgl.c
+++ b/src/rlgl.c
@@ -71,6 +71,8 @@
#define MAX_DRAWS_BY_TEXTURE 256 // Draws are organized by texture changes
#define TEMP_VERTEX_BUFFER_SIZE 4096 // Temporal Vertex Buffer (required for vertex-transformations)
// NOTE: Every vertex are 3 floats (12 bytes)
+
+#define MAX_LIGHTS 8 // Max lights supported by standard shader
#ifndef GL_SHADING_LANGUAGE_VERSION
#define GL_SHADING_LANGUAGE_VERSION 0x8B8C
@@ -199,6 +201,10 @@ static bool texCompETC1Supported = false; // ETC1 texture compression support
static bool texCompETC2Supported = false; // ETC2/EAC texture compression support
static bool texCompPVRTSupported = false; // PVR texture compression support
static bool texCompASTCSupported = false; // ASTC texture compression support
+
+// Lighting data
+static Light lights[MAX_LIGHTS]; // Lights pool
+static int lightsCount; // Counts current enabled physic objects
#endif
// Compressed textures support flags
@@ -227,6 +233,7 @@ static void LoadCompressedTexture(unsigned char *data, int width, int height, in
static unsigned int LoadShaderProgram(char *vShaderStr, char *fShaderStr); // Load custom shader strings and return program id
static Shader LoadDefaultShader(void); // Load default shader (just vertex positioning and texture coloring)
+static Shader LoadStandardShader(void); // Load standard shader (support materials and lighting)
static void LoadDefaultShaderLocations(Shader *shader); // Bind default shader locations (attributes and uniforms)
static void UnloadDefaultShader(void); // Unload default shader
@@ -235,6 +242,8 @@ static void UpdateDefaultBuffers(void); // Update default internal buffers (
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 SetShaderLights(Shader shader); // Sets shader uniform values for lights array
+
static char *ReadTextFile(const char *fileName);
#endif
@@ -1749,11 +1758,19 @@ void rlglDrawMesh(Mesh mesh, Material material, Matrix transform)
// Send combined model-view-projection matrix to shader
glUniformMatrix4fv(material.shader.mvpLoc, 1, false, MatrixToFloat(matMVP));
- // Apply color tinting (material.colDiffuse)
- // NOTE: Just update one uniform on fragment shader
- float vColor[4] = { (float)material.colDiffuse.r/255, (float)material.colDiffuse.g/255, (float)material.colDiffuse.b/255, (float)material.colDiffuse.a/255 };
- glUniform4fv(material.shader.tintColorLoc, 1, vColor);
-
+ // Setup shader uniforms for material related data
+ // TODO: Check if using standard shader to get location points
+
+ // Upload to shader material.colDiffuse
+ float vColorDiffuse[4] = { (float)material.colDiffuse.r/255, (float)material.colDiffuse.g/255, (float)material.colDiffuse.b/255, (float)material.colDiffuse.a/255 };
+ glUniform4fv(material.shader.tintColorLoc, 1, vColorDiffuse);
+
+ // TODO: Upload to shader material.colAmbient
+ // glUniform4f(???, (float)material.colAmbient.r/255, (float)material.colAmbient.g/255, (float)material.colAmbient.b/255, (float)material.colAmbient.a/255);
+
+ // TODO: Upload to shader material.colSpecular
+ // glUniform4f(???, (float)material.colSpecular.r/255, (float)material.colSpecular.g/255, (float)material.colSpecular.b/255, (float)material.colSpecular.a/255);
+
// Set shader textures (diffuse, normal, specular)
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, material.texDiffuse.id);
@@ -1764,6 +1781,9 @@ void rlglDrawMesh(Mesh mesh, Material material, Matrix transform)
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, material.texNormal.id);
glUniform1i(material.shader.mapNormalLoc, 1); // Texture fits in active texture unit 1
+
+ // TODO: Upload to shader normalDepth
+ //glUniform1f(???, material.normalDepth);
}
if ((material.texSpecular.id != 0) && (material.shader.mapSpecularLoc != -1))
@@ -1771,7 +1791,13 @@ void rlglDrawMesh(Mesh mesh, Material material, Matrix transform)
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, material.texSpecular.id);
glUniform1i(material.shader.mapSpecularLoc, 2); // Texture fits in active texture unit 2
+
+ // TODO: Upload to shader glossiness
+ //glUniform1f(???, material.glossiness);
}
+
+ // Setup shader uniforms for lights
+ SetShaderLights(material.shader);
if (vaoSupported)
{
@@ -2198,6 +2224,55 @@ void SetBlendMode(int mode)
}
}
+// Create a new light, initialize it and add to pool
+// TODO: Review creation parameters (only generic ones)
+Light CreateLight(int type, Vector3 position, Color diffuse)
+{
+ // Allocate dynamic memory
+ Light light = (Light)malloc(sizeof(LightData));
+
+ // Initialize light values with generic values
+ light->id = lightsCount;
+ light->type = type;
+ light->enabled = true;
+
+ light->position = position;
+ light->direction = (Vector3){ 0.0f, 0.0f, 0.0f };
+ light->intensity = 1.0f;
+ light->diffuse = diffuse;
+ light->specular = WHITE;
+
+ // Add new light to the array
+ lights[lightsCount] = light;
+
+ // Increase enabled lights count
+ lightsCount++;
+
+ return light;
+}
+
+// Destroy a light and take it out of the list
+void DestroyLight(Light light)
+{
+ // Free dynamic memory allocation
+ free(lights[light->id]);
+
+ // Remove *obj from the pointers array
+ for (int i = light->id; i < lightsCount; i++)
+ {
+ // Resort all the following pointers of the array
+ if ((i + 1) < lightsCount)
+ {
+ lights[i] = lights[i + 1];
+ lights[i]->id = lights[i + 1]->id;
+ }
+ else free(lights[i]);
+ }
+
+ // Decrease enabled physic objects count
+ lightsCount--;
+}
+
//----------------------------------------------------------------------------------
// Module specific Functions Definition
//----------------------------------------------------------------------------------
@@ -2415,6 +2490,32 @@ static Shader LoadDefaultShader(void)
return shader;
}
+// Load standard shader
+// NOTE: This shader supports:
+// - Up to 3 different maps: diffuse, normal, specular
+// - Material properties: colDiffuse, colAmbient, colSpecular, glossiness, normalDepth
+// - Up to 8 lights: Point, Directional or Spot
+static Shader LoadStandardShader(void)
+{
+ Shader shader;
+
+ char *vShaderStr;
+ char *fShaderStr;
+
+ // TODO: Implement standard uber-shader, supporting all features (GLSL 100 / GLSL 330)
+
+ // NOTE: Shader could be quite extensive so it could be implemented in external files (standard.vs/standard.fs)
+
+ shader.id = LoadShaderProgram(vShaderStr, fShaderStr);
+
+ if (shader.id != 0) TraceLog(INFO, "[SHDR ID %i] Standard shader loaded successfully", shader.id);
+ else TraceLog(WARNING, "[SHDR ID %i] Standard shader could not be loaded", shader.id);
+
+ if (shader.id != 0) LoadDefaultShaderLocations(&shader); // TODO: Review locations fetching
+
+ 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)
@@ -2900,6 +3001,62 @@ static void UnloadDefaultBuffers(void)
free(quads.indices);
}
+// Sets shader uniform values for lights array
+// NOTE: It would be far easier with shader UBOs but are not supported on OpenGL ES 2.0f
+// TODO: Review memcpy() and parameters pass
+static void SetShaderLights(Shader shader)
+{
+ /*
+ // NOTE: Standard Shader must include the following data:
+
+ // Shader Light struct
+ struct Light {
+ vec3 position;
+ vec3 direction;
+
+ vec3 diffuse;
+ float intensity;
+ }
+
+ const int maxLights = 8;
+ uniform int lightsCount; // Number of lights
+ uniform Light lights[maxLights];
+ */
+
+ int locPoint;
+ char locName[32] = "lights[x].position\0";
+
+ glUseProgram(shader.id);
+
+ locPoint = glGetUniformLocation(shader.id, "lightsCount");
+ glUniform1i(locPoint, lightsCount);
+
+ for (int i = 0; i < lightsCount; i++)
+ {
+ locName[7] = '0' + i;
+
+ memcpy(&locName[10], "position\0", strlen("position\0"));
+ locPoint = glGetUniformLocation(shader.id, locName);
+ glUniform3f(locPoint, lights[i]->position.x, lights[i]->position.y, lights[i]->position.z);
+
+ memcpy(&locName[10], "direction\0", strlen("direction\0"));
+ locPoint = glGetUniformLocation(shader.id, locName);
+ glUniform3f(locPoint, lights[i]->direction.x, lights[i]->direction.y, lights[i]->direction.z);
+
+ memcpy(&locName[10], "diffuse\0", strlen("diffuse\0"));
+ locPoint = glGetUniformLocation(shader.id, locName);
+ glUniform4f(locPoint, (float)lights[i]->diffuse.r/255, (float)lights[i]->diffuse.g/255, (float)lights[i]->diffuse.b/255, (float)lights[i]->diffuse.a/255 );
+
+ memcpy(&locName[10], "intensity\0", strlen("intensity\0"));
+ locPoint = glGetUniformLocation(shader.id, locName);
+ glUniform1f(locPoint, lights[i]->intensity);
+
+ // TODO: Pass to the shader any other required data from LightData struct
+ }
+
+ glUseProgram(0);
+}
+
// Read text data from file
// NOTE: text chars array should be freed manually
static char *ReadTextFile(const char *fileName)
diff --git a/src/rlgl.h b/src/rlgl.h
index a557ffa2..39941b33 100644
--- a/src/rlgl.h
+++ b/src/rlgl.h
@@ -209,6 +209,28 @@ typedef enum { OPENGL_11 = 1, OPENGL_33, OPENGL_ES_20 } GlVersion;
float glossiness;
float normalDepth;
} Material;
+
+ // Light type
+ // TODO: Review contained data to support different light types and features
+ typedef struct LightData {
+ int id;
+ int type; // LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT
+ bool enabled;
+
+ Vector3 position;
+ Vector3 direction; // Used on LIGHT_DIRECTIONAL and LIGHT_SPOT (cone direction)
+ float attenuation; // Lost of light intensity with distance (use radius?)
+
+ Color diffuse; // Use Vector3 diffuse (including intensities)?
+ float intensity;
+
+ Color specular;
+ //float specFactor; // Specular intensity ?
+
+ //Color ambient; // Required?
+
+ float coneAngle; // SpotLight
+ } LightData, *Light;
// Color blending modes (pre-defined)
typedef enum { BLEND_ALPHA = 0, BLEND_ADDITIVE, BLEND_MULTIPLIED } BlendMode;
@@ -311,6 +333,9 @@ void SetShaderValuei(Shader shader, int uniformLoc, int *value, int size); // S
void SetShaderValueMatrix(Shader shader, int uniformLoc, Matrix mat); // Set shader uniform value (matrix 4x4)
void SetBlendMode(int mode); // Set blending mode (alpha, additive, multiplied)
+
+Light CreateLight(int type, Vector3 position, Color diffuse); // Create a new light, initialize it and add to pool
+void DestroyLight(Light light); // Destroy a light and take it out of the list
#endif
#ifdef __cplusplus