Add lighting system -IN PROGRESS-

Improved materials
This commit is contained in:
raysan5 2016-05-20 12:28:07 +02:00
parent af890cf210
commit dcf5f45f68
4 changed files with 228 additions and 6 deletions

View File

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

View File

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

View File

@ -72,6 +72,8 @@
#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
#endif
@ -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,10 +1758,18 @@ 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);
@ -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,8 +1791,14 @@ 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)
{
glBindVertexArray(mesh.vaoId);
@ -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)

View File

@ -210,6 +210,28 @@ typedef enum { OPENGL_11 = 1, OPENGL_33, OPENGL_ES_20 } GlVersion;
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;
#endif
@ -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