Add standard lighting (1/3)

- Ambient and lambert lighting added.
- Ambient and diffuse colors linked to standard shader.
- Single light linked to standard shader.
- LoadStandardMaterial() and depending functions added.
This commit is contained in:
victorfisac 2016-05-20 17:18:07 +02:00
parent c60cc9ee18
commit 30c8058fca
3 changed files with 131 additions and 33 deletions

View File

@ -732,13 +732,13 @@ Material LoadDefaultMaterial(void)
return material;
}
// Load standard material (uses standard models shader)
// Load standard material (uses material attributes and lighting shader)
// NOTE: Standard shader supports multiple maps and lights
Material LoadStandardMaterial(void)
{
Material material = LoadDefaultMaterial();
//material.shader = GetStandardShader();
material.shader = GetStandardShader();
return material;
}
@ -1240,7 +1240,7 @@ void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rota
//Matrix matModel = MatrixMultiply(model.transform, matTransform); // Transform to world-space coordinates
model.transform = MatrixMultiply(MatrixMultiply(matScale, matRotation), matTranslation);
model.material.colDiffuse = tint;
// model.material.colDiffuse = tint;
rlglDrawMesh(model.mesh, model.material, model.transform);
}

View File

@ -398,7 +398,7 @@ typedef struct Shader {
// Uniform locations
int mvpLoc; // ModelView-Projection matrix uniform location point (vertex shader)
int tintColorLoc; // Color uniform location point (fragment shader)
int tintColorLoc; // Diffuse color uniform location point (fragment shader)
// Texture map locations
int mapDiffuseLoc; // Diffuse map texture uniform location point (fragment shader)
@ -444,11 +444,8 @@ typedef struct LightData {
float intensity;
Color specular;
//float specFactor; // Specular intensity ?
//Color ambient; // Required?
float coneAngle; // SpotLight
float coneAngle; // SpotLight
} LightData, *Light;
// Light types
@ -836,6 +833,7 @@ void SetModelTexture(Model *model, Texture2D texture); // Link a textur
Material LoadMaterial(const char *fileName); // Load material data (from file)
Material LoadDefaultMaterial(void); // Load default material (uses default models shader)
Material LoadStandardMaterial(void); // Load standard material (uses material attributes and lighting shader)
void UnloadMaterial(Material material); // Unload material textures from VRAM
void DrawModel(Model model, Vector3 position, float scale, Color tint); // Draw a model (with texture if set)
@ -865,6 +863,7 @@ void UnloadShader(Shader shader); // Unload a
void SetDefaultShader(void); // Set default shader to be used in batch draw
void SetCustomShader(Shader shader); // Set custom shader to be used in batch draw
Shader GetDefaultShader(void); // Get default shader
Shader GetStandardShader(void); // Get default shader
Texture2D GetDefaultTexture(void); // Get default texture
int GetShaderLocation(Shader shader, const char *uniformName); // Get shader uniform location

View File

@ -191,6 +191,7 @@ static bool useTempBuffer = false;
// Shader Programs
static Shader defaultShader;
static Shader standardShader;
static Shader currentShader; // By default, defaultShader
// Flags for supported extensions
@ -236,6 +237,7 @@ static Shader LoadDefaultShader(void); // Load default shader (just vertex
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
static void UnloadStandardShader(void); // Unload standard 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
@ -1018,6 +1020,7 @@ void rlglInit(void)
// Init default Shader (customized for GL 3.3 and ES2)
defaultShader = LoadDefaultShader();
standardShader = LoadStandardShader();
currentShader = defaultShader;
LoadDefaultBuffers(); // Initialize default vertex arrays buffers (lines, triangles, quads)
@ -1046,6 +1049,7 @@ void rlglClose(void)
{
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
UnloadDefaultShader();
UnloadStandardShader();
UnloadDefaultBuffers();
// Delete default white texture
@ -1757,19 +1761,30 @@ void rlglDrawMesh(Mesh mesh, Material material, Matrix transform)
// Send combined model-view-projection matrix to shader
glUniformMatrix4fv(material.shader.mvpLoc, 1, false, MatrixToFloat(matMVP));
// 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);
// Check if using standard shader to get location points
// NOTE: standard shader specific locations are got at render time to keep Shader struct as simple as possible (with just default shader locations)
if(material.shader.id == standardShader.id)
{
// Send model transformations matrix to shader
glUniformMatrix4fv(glGetUniformLocation(material.shader.id, "modelMatrix"), 1, false, MatrixToFloat(transform));
// Setup shader uniforms for lights
SetShaderLights(material.shader);
// Upload to shader material.colAmbient
glUniform4f(glGetUniformLocation(material.shader.id, "colAmbient"), (float)material.colAmbient.r/255, (float)material.colAmbient.g/255, (float)material.colAmbient.b/255, (float)material.colAmbient.a/255);
// Upload to shader material.colSpecular
glUniform4f(glGetUniformLocation(material.shader.id, "colSpecular"), (float)material.colSpecular.r/255, (float)material.colSpecular.g/255, (float)material.colSpecular.b/255, (float)material.colSpecular.a/255);
// 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);
// TODO: Upload to shader glossiness
//glUniform1f(???, material.glossiness);
}
// Set shader textures (diffuse, normal, specular)
glActiveTexture(GL_TEXTURE0);
@ -1791,13 +1806,7 @@ 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)
{
@ -2148,6 +2157,17 @@ Shader GetDefaultShader(void)
#endif
}
// Get default shader
Shader GetStandardShader(void)
{
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
return standardShader;
#else
Shader shader = { 0 };
return shader;
#endif
}
// Get shader uniform location
int GetShaderLocation(Shader shader, const char *uniformName)
{
@ -2499,13 +2519,75 @@ 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)
// Vertex shader directly defined, no external file required
#if defined(GRAPHICS_API_OPENGL_33)
char vShaderStr[] = "#version 330 \n"
"in vec3 vertexPosition; \n"
"in vec3 vertexNormal; \n"
"in vec2 vertexTexCoord; \n"
"in vec4 vertexColor; \n"
"out vec2 fragTexCoord; \n"
"out vec4 fragColor; \n"
"out vec3 fragNormal; \n"
#elif defined(GRAPHICS_API_OPENGL_ES2)
char vShaderStr[] = "#version 100 \n"
"attribute vec3 vertexPosition; \n"
"attribute vec3 vertexNormal; \n"
"attribute vec2 vertexTexCoord; \n"
"attribute vec4 vertexColor; \n"
"varying vec2 fragTexCoord; \n"
"varying vec4 fragColor; \n"
"varying vec3 fragNormal; \n"
#endif
"uniform mat4 mvpMatrix; \n"
"uniform mat4 modelMatrix; \n"
"void main() \n"
"{ \n"
" fragTexCoord = vertexTexCoord; \n"
" fragColor = vertexColor; \n"
" mat3 normalMatrix = transpose(inverse(mat3(modelMatrix))); \n"
" fragNormal = normalize(normalMatrix*vertexNormal); \n"
" gl_Position = mvpMatrix*vec4(vertexPosition, 1.0); \n"
"} \n";
// TODO: add specular calculation, multi-lights structs and light type calculations (directional, point, spot)
// Fragment shader directly defined, no external file required
#if defined(GRAPHICS_API_OPENGL_33)
char fShaderStr[] = "#version 330 \n"
"in vec2 fragTexCoord; \n"
"in vec4 fragColor; \n"
"in vec3 fragNormal; \n"
"out vec4 finalColor; \n"
#elif defined(GRAPHICS_API_OPENGL_ES2)
char fShaderStr[] = "#version 100 \n"
"precision mediump float; \n" // precision required for OpenGL ES2 (WebGL)
"varying vec2 fragTexCoord; \n"
"varying vec4 fragColor; \n"
"varying vec3 fragNormal; \n"
#endif
"uniform sampler2D texture0; \n"
"uniform vec4 fragTintColor; \n"
"uniform vec4 colAmbient; \n"
"uniform vec4 colSpecular; \n"
"uniform vec3 lightDir; \n"
"vec3 LambertLighting(in vec3 n, in vec3 l) \n"
"{ \n"
" return clamp(dot(n, l), 0, 1)*fragTintColor.rgb; \n"
"} \n"
"void main() \n"
"{ \n"
" vec3 n = normalize(fragNormal); \n"
" vec3 l = normalize(lightDir); \n"
#if defined(GRAPHICS_API_OPENGL_33)
" vec4 texelColor = texture(texture0, fragTexCoord); \n"
" finalColor = vec4(texelColor.rgb*(colAmbient.rgb + LambertLighting(n, l)) - colSpecular.rgb + colSpecular.rgb, texelColor.a*fragTintColor.a); \n" // Stupid specular color operation to avoid shader location errors
#elif defined(GRAPHICS_API_OPENGL_ES2)
" vec4 texelColor = texture2D(texture0, fragTexCoord); \n" // NOTE: texture2D() is deprecated on OpenGL 3.3 and ES 3.0
" gl_FragColor = texelColor*fragTintColor*fragColor; \n"
#endif
"} \n";
shader.id = LoadShaderProgram(vShaderStr, fShaderStr);
if (shader.id != 0) TraceLog(INFO, "[SHDR ID %i] Standard shader loaded successfully", shader.id);
@ -2554,10 +2636,23 @@ static void UnloadDefaultShader(void)
//glDetachShader(defaultShader, vertexShader);
//glDetachShader(defaultShader, fragmentShader);
//glDeleteShader(vertexShader); // Already deleted on shader compilation
//glDeleteShader(fragmentShader); // Already deleted on sahder compilation
//glDeleteShader(fragmentShader); // Already deleted on shader compilation
glDeleteProgram(defaultShader.id);
}
// Unload standard shader
static void UnloadStandardShader(void)
{
glUseProgram(0);
//glDetachShader(defaultShader, vertexShader);
//glDetachShader(defaultShader, fragmentShader);
//glDeleteShader(vertexShader); // Already deleted on shader compilation
//glDeleteShader(fragmentShader); // Already deleted on shader compilation
glDeleteProgram(standardShader.id);
}
// Load default internal buffers (lines, triangles, quads)
static void LoadDefaultBuffers(void)
{
@ -3006,6 +3101,9 @@ static void UnloadDefaultBuffers(void)
// TODO: Review memcpy() and parameters pass
static void SetShaderLights(Shader shader)
{
// Note: currently working with one light (index 0)
// TODO: add multi-lights feature (http://www.learnopengl.com/#!Lighting/Multiple-lights)
/*
// NOTE: Standard Shader must include the following data:
@ -3023,7 +3121,7 @@ static void SetShaderLights(Shader shader)
uniform Light lights[maxLights];
*/
int locPoint;
/*int locPoint;
char locName[32] = "lights[x].position\0";
glUseProgram(shader.id);
@ -3052,9 +3150,10 @@ static void SetShaderLights(Shader shader)
glUniform1f(locPoint, lights[i]->intensity);
// TODO: Pass to the shader any other required data from LightData struct
}
}*/
glUseProgram(0);
int locPoint = GetShaderLocation(shader, "lightDir");
glUniform3f(locPoint, lights[0]->position.x, lights[0]->position.y, lights[0]->position.z);
}
// Read text data from file