Browse Source

Merge pull request #120 from victorfisac/develop

Standard Lighting (2/3)
Ray 9 years ago
parent
commit
9811a37690

+ 0 - 85
examples/resources/shaders/glsl330/phong.fs

@@ -1,85 +0,0 @@
-#version 330
-
-// Input vertex attributes (from vertex shader)
-in vec2 fragTexCoord;
-in vec3 fragNormal;
-
-// Input uniform values
-uniform sampler2D texture0;
-uniform vec4 fragTintColor;
-
-// Output fragment color
-out vec4 finalColor;
-
-// NOTE: Add here your custom variables
-
-// Light uniform values
-uniform vec3 lightAmbientColor = vec3(0.6, 0.3, 0.0);
-uniform vec3 lightDiffuseColor = vec3(1.0, 0.5, 0.0);
-uniform vec3 lightSpecularColor = vec3(0.0, 1.0, 0.0);
-uniform float lightIntensity = 1.0;
-uniform float lightSpecIntensity = 1.0;
-
-// Material uniform values
-uniform vec3 matAmbientColor = vec3(1.0, 1.0, 1.0);
-uniform vec3 matSpecularColor = vec3(1.0, 1.0, 1.0);
-uniform float matGlossiness = 50.0;
-
-// World uniform values
-uniform vec3 lightPosition;
-uniform vec3 cameraPosition;
-
-// Fragment shader output data
-out vec4 fragColor;
-
-// Calculate ambient lighting component
-vec3 AmbientLighting()
-{
-    return (matAmbientColor*lightAmbientColor);
-}
-
-// Calculate diffuse lighting component
-vec3 DiffuseLighting(in vec3 N, in vec3 L)
-{
-    // Lambertian reflection calculation
-    float diffuse = clamp(dot(N, L), 0, 1);
-
-    return (fragTintColor.xyz*lightDiffuseColor*lightIntensity*diffuse);
-}
-
-// Calculate specular lighting component
-vec3 SpecularLighting(in vec3 N, in vec3 L, in vec3 V)
-{
-    float specular = 0.0;
-
-    // Calculate specular reflection only if the surface is oriented to the light source
-    if (dot(N, L) > 0)
-    {
-        // Calculate half vector
-        vec3 H = normalize(L + V);
-
-        // Calculate specular intensity
-        specular = pow(dot(N, H), 3 + matGlossiness);
-    }
-   
-    return (matSpecularColor*lightSpecularColor*lightSpecIntensity*specular);
-}
-
-void main()
-{
-    // Normalize input vectors
-    vec3 L = normalize(lightPosition);
-    vec3 V = normalize(cameraPosition);
-    vec3 N = normalize(fragNormal);
-    
-    // Calculate lighting components 
-    vec3 ambient = AmbientLighting();
-    vec3 diffuse = DiffuseLighting(N, L);
-    vec3 specular = SpecularLighting(N, L, V);
-    
-    // Texel color fetching from texture sampler
-    vec4 texelColor = texture(texture0, fragTexCoord);
-
-    // Calculate final fragment color
-    finalColor = vec4(texelColor.rgb*(ambient + diffuse + specular), texelColor.a);
-}

+ 0 - 29
examples/resources/shaders/glsl330/phong.vs

@@ -1,29 +0,0 @@
-#version 330
-
-// Input vertex attributes
-in vec3 vertexPosition;
-in vec2 vertexTexCoord;
-in vec3 vertexNormal;
-
-// Input uniform values
-uniform mat4 mvpMatrix;
-
-// Output vertex attributes (to fragment shader)
-out vec2 fragTexCoord;
-out vec3 fragNormal;
-
-// NOTE: Add here your custom variables
-uniform mat4 modelMatrix;
-
-void main()
-{
-    // Send vertex attributes to fragment shader
-    fragTexCoord = vertexTexCoord;
-
-    // Calculate view vector normal from model
-    mat3 normalMatrix = transpose(inverse(mat3(modelMatrix)));
-    fragNormal = normalize(normalMatrix*vertexNormal);
-    
-    // Calculate final vertex position
-    gl_Position = mvpMatrix*vec4(vertexPosition, 1.0);
-}

+ 136 - 0
examples/resources/shaders/standard.fs

@@ -0,0 +1,136 @@
+#version 330
+
+in vec3 fragPosition;
+in vec2 fragTexCoord;
+in vec4 fragColor;
+in vec3 fragNormal;
+
+out vec4 finalColor;
+
+uniform sampler2D texture0;
+
+uniform vec4 colAmbient;
+uniform vec4 colDiffuse;
+uniform vec4 colSpecular;
+uniform float glossiness;
+
+uniform mat4 modelMatrix;
+uniform vec3 viewDir;
+
+struct Light {
+    int enabled;
+    int type;
+    vec3 position;
+    vec3 direction;
+    vec4 diffuse;
+    float intensity;
+    float attenuation;
+    float coneAngle;
+};
+
+const int maxLights = 8;
+uniform int lightsCount;
+uniform Light lights[maxLights];
+
+vec3 CalcPointLight(Light l, vec3 n, vec3 v)
+{
+    vec3 surfacePos = vec3(modelMatrix*vec4(fragPosition, 1));
+    vec3 surfaceToLight = l.position - surfacePos;
+    
+    // Diffuse shading
+    float brightness = clamp(dot(n, surfaceToLight)/(length(surfaceToLight)*length(n)), 0, 1);
+    float diff = 1.0/dot(surfaceToLight/l.attenuation, surfaceToLight/l.attenuation)*brightness*l.intensity;
+    
+    // Specular shading
+    float spec = 0.0;
+    if (diff > 0.0)
+    {
+        vec3 h = normalize(-l.direction + v);
+        spec = pow(dot(n, h), 3 + glossiness);
+    }
+    
+    return (diff*l.diffuse.rgb*colDiffuse.rgb + spec*colSpecular.rgb);
+}
+
+vec3 CalcDirectionalLight(Light l, vec3 n, vec3 v)
+{
+    vec3 lightDir = normalize(-l.direction);
+    
+    // Diffuse shading
+    float diff = clamp(dot(n, lightDir), 0.0, 1.0)*l.intensity;
+    
+    // Specular shading
+    float spec = 0.0;
+    if (diff > 0.0)
+    {
+        vec3 h = normalize(lightDir + v);
+        spec = pow(dot(n, h), 3 + glossiness);
+    }
+    
+    // Combine results
+    return (diff*l.intensity*l.diffuse.rgb*colDiffuse.rgb + spec*colSpecular.rgb);
+}
+
+vec3 CalcSpotLight(Light l, vec3 n, vec3 v)
+{
+    vec3 surfacePos = vec3(modelMatrix*vec4(fragPosition, 1));
+    vec3 lightToSurface = normalize(surfacePos - l.position);
+    vec3 lightDir = normalize(-l.direction);
+    
+    // Diffuse shading
+    float diff = clamp(dot(n, lightDir), 0.0, 1.0)*l.intensity;
+    
+    // Spot attenuation
+    float attenuation = clamp(dot(n, lightToSurface), 0.0, 1.0);
+    attenuation = dot(lightToSurface, -lightDir);
+    float lightToSurfaceAngle = degrees(acos(attenuation));
+    if (lightToSurfaceAngle > l.coneAngle) attenuation = 0.0;
+    float falloff = (l.coneAngle - lightToSurfaceAngle)/l.coneAngle;
+    
+    // Combine diffuse and attenuation
+    float diffAttenuation = diff*attenuation;
+    
+    // Specular shading
+    float spec = 0.0;
+    if (diffAttenuation > 0.0)
+    {
+        vec3 h = normalize(lightDir + v);
+        spec = pow(dot(n, h), 3 + glossiness);
+    }
+    
+    return falloff*(diffAttenuation*l.diffuse.rgb + spec*colSpecular.rgb);
+}
+
+void main()
+{
+    // Calculate fragment normal in screen space
+    mat3 normalMatrix = transpose(inverse(mat3(modelMatrix)));
+    vec3 normal = normalize(normalMatrix*fragNormal);
+   
+    // Normalize normal and view direction vectors
+    vec3 n = normalize(normal);
+    vec3 v = normalize(viewDir);
+
+    // Calculate diffuse texture color fetching
+    vec4 texelColor = texture(texture0, fragTexCoord);
+    vec3 lighting = colAmbient.rgb;
+    
+    for (int i = 0; i < lightsCount; i++)
+    {
+        // Check if light is enabled
+        if (lights[i].enabled == 1)
+        {
+            // Calculate lighting based on light type
+            switch (lights[i].type)
+            {
+                case 0: lighting += CalcPointLight(lights[i], n, v); break;
+                case 1: lighting += CalcDirectionalLight(lights[i], n, v); break;
+                case 2: lighting += CalcSpotLight(lights[i], n, v); break;
+                default: break;
+            }
+        }
+    }
+    
+    // Calculate final fragment color
+    finalColor = vec4(texelColor.rgb*lighting, texelColor.a);
+}

+ 23 - 0
examples/resources/shaders/standard.vs

@@ -0,0 +1,23 @@
+#version 330 
+
+in vec3 vertexPosition;
+in vec3 vertexNormal;
+in vec2 vertexTexCoord;
+in vec4 vertexColor;
+
+out vec3 fragPosition;
+out vec2 fragTexCoord;
+out vec4 fragColor;
+out vec3 fragNormal;
+
+uniform mat4 mvpMatrix;
+
+void main()
+{
+    fragPosition = vertexPosition;
+    fragTexCoord = vertexTexCoord;
+    fragColor = vertexColor;
+    fragNormal = vertexNormal;
+
+    gl_Position = mvpMatrix*vec4(vertexPosition, 1.0);
+}

+ 0 - 171
examples/shaders_basic_lighting.c

@@ -1,171 +0,0 @@
-/*******************************************************************************************
-*
-*   raylib [shaders] example - Basic lighting: Blinn-Phong
-*
-*   This example has been created using raylib 1.3 (www.raylib.com)
-*   raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
-*
-*   Copyright (c) 2014 Ramon Santamaria (@raysan5)
-*
-********************************************************************************************/
-
-#include "raylib.h"
-
-#define SHININESS_SPEED 1.0f
-#define LIGHT_SPEED 0.25f
-
-// Light type
-typedef struct Light {
-    Vector3 position;
-    Vector3 direction;
-    float intensity;
-    float specIntensity;
-    Color diffuse;
-    Color ambient;
-    Color specular;
-} Light;
-
-int main()
-{
-    // Initialization
-    //--------------------------------------------------------------------------------------
-    const int screenWidth = 800;
-    const int screenHeight = 450;
-    
-    SetConfigFlags(FLAG_MSAA_4X_HINT);
-    InitWindow(screenWidth, screenHeight, "raylib [shaders] example - basic lighting");
-    
-    // Camera initialization
-    Camera camera = {{ 8.0f, 8.0f, 8.0f }, { 0.0f, 3.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f };
-    
-    // Model initialization
-    Vector3 position = { 0.0f, 0.0f, 0.0f };
-    Model model = LoadModel("resources/model/dwarf.obj");
-    Shader shader = LoadShader("resources/shaders/glsl330/phong.vs", "resources/shaders/glsl330/phong.fs");
-    SetModelShader(&model, shader);
-    
-    // Shader locations initialization
-    int lIntensityLoc = GetShaderLocation(shader, "lightIntensity");
-    int lAmbientLoc = GetShaderLocation(shader, "lightAmbientColor");
-    int lDiffuseLoc = GetShaderLocation(shader, "lightDiffuseColor");
-    int lSpecularLoc = GetShaderLocation(shader, "lightSpecularColor");
-    int lSpecIntensityLoc = GetShaderLocation(shader, "lightSpecIntensity");
-    
-    int mAmbientLoc = GetShaderLocation(shader, "matAmbientColor");
-    int mSpecularLoc = GetShaderLocation(shader, "matSpecularColor");
-    int mGlossLoc = GetShaderLocation(shader, "matGlossiness");
-    
-    // Camera and light vectors shader locations
-    int cameraLoc = GetShaderLocation(shader, "cameraPosition");
-    int lightLoc = GetShaderLocation(shader, "lightPosition");
-    
-    // Model and View matrix locations (required for lighting)
-    int modelLoc = GetShaderLocation(shader, "modelMatrix");
-    //int viewLoc = GetShaderLocation(shader, "viewMatrix");        // Not used
-    
-    // Light and material definitions
-    Light light;
-    Material matBlinn;
-    
-    // Light initialization
-    light.position = (Vector3){ 4.0f, 2.0f, 0.0f };
-    light.direction = (Vector3){ 5.0f, 1.0f, 1.0f };
-    light.intensity = 1.0f;
-    light.diffuse = WHITE;
-    light.ambient = (Color){ 150, 75, 0, 255 };
-    light.specular = WHITE;
-    light.specIntensity = 1.0f;
-    
-    // Material initialization
-    matBlinn.colDiffuse = WHITE;
-    matBlinn.colAmbient = (Color){ 50, 50, 50, 255 };
-    matBlinn.colSpecular = WHITE;
-    matBlinn.glossiness = 50.0f;
-    
-    // Setup camera
-    SetCameraMode(CAMERA_FREE);             // Set camera mode
-    SetCameraPosition(camera.position);     // Set internal camera position to match our camera position
-    SetCameraTarget(camera.target);         // Set internal camera target to match our camera target
-    
-    SetTargetFPS(60);
-    //--------------------------------------------------------------------------------------
-    
-    // Main game loop
-    while (!WindowShouldClose())    // Detect window close button or ESC key
-    {
-        // Update
-        //----------------------------------------------------------------------------------
-        UpdateCamera(&camera);      // Update camera position
-        
-        // NOTE: Model transform can be set in model.transform or directly with params at draw... WATCH OUT!
-        SetShaderValueMatrix(shader, modelLoc, model.transform);            // Send model matrix to shader
-        //SetShaderValueMatrix(shader, viewLoc, GetCameraMatrix(camera));   // Not used
-        
-        // Glossiness input control
-        if(IsKeyDown(KEY_UP)) matBlinn.glossiness += SHININESS_SPEED;
-        else if(IsKeyDown(KEY_DOWN))
-        {
-            matBlinn.glossiness -= SHININESS_SPEED;
-            if( matBlinn.glossiness < 0) matBlinn.glossiness = 0.0f;
-        }
-        
-        // Light X movement
-        if (IsKeyDown(KEY_D)) light.position.x += LIGHT_SPEED;
-        else if(IsKeyDown(KEY_A)) light.position.x -= LIGHT_SPEED;
-        
-        // Light Y movement
-        if (IsKeyDown(KEY_LEFT_SHIFT)) light.position.y += LIGHT_SPEED;
-        else if (IsKeyDown(KEY_LEFT_CONTROL)) light.position.y -= LIGHT_SPEED;
-
-        // Light Z movement
-        if (IsKeyDown(KEY_S)) light.position.z += LIGHT_SPEED;
-        else if (IsKeyDown(KEY_W)) light.position.z -= LIGHT_SPEED;
-        
-        // Send light values to shader
-        SetShaderValue(shader, lIntensityLoc, &light.intensity, 1);
-        SetShaderValue(shader, lAmbientLoc, ColorToFloat(light.ambient), 3);
-        SetShaderValue(shader, lDiffuseLoc, ColorToFloat(light.diffuse), 3);
-        SetShaderValue(shader, lSpecularLoc, ColorToFloat(light.specular), 3);
-        SetShaderValue(shader, lSpecIntensityLoc, &light.specIntensity, 1);
-        
-        // Send material values to shader
-        SetShaderValue(shader, mAmbientLoc, ColorToFloat(matBlinn.colAmbient), 3);
-        SetShaderValue(shader, mSpecularLoc, ColorToFloat(matBlinn.colSpecular), 3);
-        SetShaderValue(shader, mGlossLoc, &matBlinn.glossiness, 1);
-        
-        // Send camera and light transform values to shader
-        SetShaderValue(shader, cameraLoc, VectorToFloat(camera.position), 3);
-        SetShaderValue(shader, lightLoc, VectorToFloat(light.position), 3);
-        //----------------------------------------------------------------------------------
-        
-        // Draw
-        //----------------------------------------------------------------------------------
-        BeginDrawing();
-        
-            ClearBackground(RAYWHITE);
-            
-            Begin3dMode(camera);
-                
-                DrawModel(model, position, 4.0f, matBlinn.colDiffuse);
-                DrawSphere(light.position, 0.5f, GOLD);
-                
-                DrawGrid(20, 1.0f);
-                
-            End3dMode();
-            
-            DrawFPS(10, 10);                // Draw FPS
-            
-        EndDrawing();
-        //----------------------------------------------------------------------------------
-    }
-
-    // De-Initialization
-    //--------------------------------------------------------------------------------------
-    UnloadShader(shader);
-    UnloadModel(model);
-
-    CloseWindow();        // Close window and OpenGL context
-    //--------------------------------------------------------------------------------------
-    
-    return 0;
-}

+ 118 - 0
examples/shaders_standard_lighting.c

@@ -0,0 +1,118 @@
+/*******************************************************************************************
+*
+*   raylib [shaders] example - Standard lighting (materials and lights)
+*
+*   NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders support,
+*         OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3 version.
+*
+*   NOTE: Shaders used in this example are #version 330 (OpenGL 3.3), to test this example
+*         on OpenGL ES 2.0 platforms (Android, Raspberry Pi, HTML5), use #version 100 shaders
+*         raylib comes with shaders ready for both versions, check raylib/shaders install folder
+*
+*   This example has been created using raylib 1.3 (www.raylib.com)
+*   raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
+*
+*   Copyright (c) 2016 Ramon Santamaria (@raysan5)
+*
+********************************************************************************************/
+
+#include "raylib.h"
+#include "raymath.h"
+
+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 [shaders] example - model shader");
+
+    // Define the camera to look into our 3d world
+    Camera camera = {{ 4.0f, 4.0f, 4.0f }, { 0.0f, 1.5f, 0.0f }, { 0.0f, 1.0f, 0.0f }, 45.0f };
+    Vector3 position = { 0.0f, 0.0f, 0.0f };   // Set model position
+    
+    Model dwarf = LoadModel("resources/model/dwarf.obj");                   // Load OBJ model
+    Texture2D texDiffuse = LoadTexture("resources/model/dwarf_diffuse.png");   // Load model diffuse texture
+
+    Material material = LoadStandardMaterial();
+    material.texDiffuse = texDiffuse;
+    material.colDiffuse = (Color){255, 255, 255, 255};
+    material.colAmbient = (Color){0, 0, 10, 255};
+    material.colSpecular = (Color){255, 255, 255, 255};
+    material.glossiness = 50.0f;
+    dwarf.material = material;      // Apply material to model
+    
+    Light spotLight = CreateLight(LIGHT_SPOT, (Vector3){3.0f, 5.0f, 2.0f}, (Color){255, 255, 255, 255});
+    spotLight->target = (Vector3){0.0f, 0.0f, 0.0f};
+    spotLight->intensity = 2.0f;
+    spotLight->diffuse = (Color){255, 100, 100, 255};
+    spotLight->coneAngle = 60.0f;
+    
+    Light dirLight = CreateLight(LIGHT_DIRECTIONAL, (Vector3){0.0f, -3.0f, -3.0f}, (Color){255, 255, 255, 255});
+    dirLight->target = (Vector3){1.0f, -2.0f, -2.0f};
+    dirLight->intensity = 2.0f;
+    dirLight->diffuse = (Color){100, 255, 100, 255};
+    
+    Light pointLight = CreateLight(LIGHT_POINT, (Vector3){0.0f, 4.0f, 5.0f}, (Color){255, 255, 255, 255});
+    pointLight->intensity = 2.0f;
+    pointLight->diffuse = (Color){100, 100, 255, 255};
+    pointLight->attenuation = 3.0f;
+
+    // Setup orbital camera
+    SetCameraMode(CAMERA_ORBITAL);          // Set a orbital camera mode
+    SetCameraPosition(camera.position);     // Set internal camera position to match our camera position
+    SetCameraTarget(camera.target);         // Set internal camera target to match our camera target
+
+    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 internal camera and our camera
+        //----------------------------------------------------------------------------------
+
+        // Draw
+        //----------------------------------------------------------------------------------
+        BeginDrawing();
+
+            ClearBackground(RAYWHITE);
+
+            Begin3dMode(camera);
+
+                DrawModel(dwarf, position, 2.0f, WHITE);   // Draw 3d model with texture
+                
+                DrawLights();   // Draw all created lights in 3D world
+
+                DrawGrid(10, 1.0f);     // Draw a grid
+
+            End3dMode();
+            
+            DrawText("(c) Dwarf 3D model by David Moreno", screenWidth - 200, screenHeight - 20, 10, GRAY);
+
+            DrawFPS(10, 10);
+
+        EndDrawing();
+        //----------------------------------------------------------------------------------
+    }
+
+    // De-Initialization
+    //--------------------------------------------------------------------------------------
+    UnloadMaterial(material);   // Unload material and assigned textures
+    UnloadModel(dwarf);         // Unload model
+    
+    // Destroy all created lights
+    DestroyLight(pointLight);
+    DestroyLight(dirLight);
+    DestroyLight(spotLight);
+
+    CloseWindow();              // Close window and OpenGL context
+    //--------------------------------------------------------------------------------------
+
+    return 0;
+}

+ 3 - 4
src/audio.c

@@ -384,7 +384,7 @@ RawAudioContext InitRawAudioContext(int sampleRate, int channels, bool floatingP
     for(mixIndex = 0; mixIndex < MAX_MIX_CHANNELS; mixIndex++) // find empty mix channel slot
     for(mixIndex = 0; mixIndex < MAX_MIX_CHANNELS; mixIndex++) // find empty mix channel slot
     {
     {
         if(mixChannelsActive_g[mixIndex] == NULL) break;
         if(mixChannelsActive_g[mixIndex] == NULL) break;
-        else if(mixIndex = MAX_MIX_CHANNELS - 1) return -1; // error
+        else if(mixIndex == MAX_MIX_CHANNELS - 1) return -1; // error
     }
     }
     
     
     if(InitMixChannel(sampleRate, mixIndex, channels, floatingPoint))
     if(InitMixChannel(sampleRate, mixIndex, channels, floatingPoint))
@@ -772,7 +772,7 @@ int PlayMusicStream(int musicIndex, char *fileName)
     for(mixIndex = 0; mixIndex < MAX_MIX_CHANNELS; mixIndex++) // find empty mix channel slot
     for(mixIndex = 0; mixIndex < MAX_MIX_CHANNELS; mixIndex++) // find empty mix channel slot
     {
     {
         if(mixChannelsActive_g[mixIndex] == NULL) break;
         if(mixChannelsActive_g[mixIndex] == NULL) break;
-        else if(mixIndex = MAX_MIX_CHANNELS - 1) return 2; // error
+        else if(mixIndex == MAX_MIX_CHANNELS - 1) return 2; // error
     }
     }
     
     
     if (strcmp(GetExtension(fileName),"ogg") == 0)
     if (strcmp(GetExtension(fileName),"ogg") == 0)
@@ -956,7 +956,7 @@ float GetMusicTimeLength(int index)
 // Get current music time played (in seconds)
 // Get current music time played (in seconds)
 float GetMusicTimePlayed(int index)
 float GetMusicTimePlayed(int index)
 {
 {
-    float secondsPlayed;
+    float secondsPlayed = 0.0f;
     if(index < MAX_MUSIC_STREAMS && currentMusic[index].mixc)
     if(index < MAX_MUSIC_STREAMS && currentMusic[index].mixc)
     {
     {
         if (currentMusic[index].chipTune)
         if (currentMusic[index].chipTune)
@@ -972,7 +972,6 @@ float GetMusicTimePlayed(int index)
             secondsPlayed = (float)samplesPlayed / (currentMusic[index].mixc->sampleRate * currentMusic[index].mixc->channels);
             secondsPlayed = (float)samplesPlayed / (currentMusic[index].mixc->sampleRate * currentMusic[index].mixc->channels);
         }
         }
     }
     }
-    
 
 
     return secondsPlayed;
     return secondsPlayed;
 }
 }

+ 37 - 28
src/models.c

@@ -65,6 +65,16 @@ static Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize);
 // Module Functions Definition
 // Module Functions Definition
 //----------------------------------------------------------------------------------
 //----------------------------------------------------------------------------------
 
 
+// Draw a line in 3D world space
+void Draw3DLine(Vector3 startPos, Vector3 endPos, Color color)
+{
+    rlBegin(RL_LINES);
+        rlColor4ub(color.r, color.g, color.b, color.a);
+        rlVertex3f(startPos.x, startPos.y, startPos.z);
+        rlVertex3f(endPos.x, endPos.y, endPos.z);
+    rlEnd();
+}
+
 // Draw cube
 // Draw cube
 // NOTE: Cube position is the center position
 // NOTE: Cube position is the center position
 void DrawCube(Vector3 position, float width, float height, float length, Color color)
 void DrawCube(Vector3 position, float width, float height, float length, Color color)
@@ -292,9 +302,9 @@ void DrawSphereEx(Vector3 centerPos, float radius, int rings, int slices, Color
         rlBegin(RL_TRIANGLES);
         rlBegin(RL_TRIANGLES);
             rlColor4ub(color.r, color.g, color.b, color.a);
             rlColor4ub(color.r, color.g, color.b, color.a);
 
 
-            for(int i = 0; i < (rings + 2); i++)
+            for (int i = 0; i < (rings + 2); i++)
             {
             {
-                for(int j = 0; j < slices; j++)
+                for (int j = 0; j < slices; j++)
                 {
                 {
                     rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*i)) * sin(DEG2RAD*(j*360/slices)),
                     rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*i)) * sin(DEG2RAD*(j*360/slices)),
                                sin(DEG2RAD*(270+(180/(rings + 1))*i)),
                                sin(DEG2RAD*(270+(180/(rings + 1))*i)),
@@ -331,9 +341,9 @@ void DrawSphereWires(Vector3 centerPos, float radius, int rings, int slices, Col
         rlBegin(RL_LINES);
         rlBegin(RL_LINES);
             rlColor4ub(color.r, color.g, color.b, color.a);
             rlColor4ub(color.r, color.g, color.b, color.a);
 
 
-            for(int i = 0; i < (rings + 2); i++)
+            for (int i = 0; i < (rings + 2); i++)
             {
             {
-                for(int j = 0; j < slices; j++)
+                for (int j = 0; j < slices; j++)
                 {
                 {
                     rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*i)) * sin(DEG2RAD*(j*360/slices)),
                     rlVertex3f(cos(DEG2RAD*(270+(180/(rings + 1))*i)) * sin(DEG2RAD*(j*360/slices)),
                                sin(DEG2RAD*(270+(180/(rings + 1))*i)),
                                sin(DEG2RAD*(270+(180/(rings + 1))*i)),
@@ -376,7 +386,7 @@ void DrawCylinder(Vector3 position, float radiusTop, float radiusBottom, float h
             if (radiusTop > 0)
             if (radiusTop > 0)
             {
             {
                 // Draw Body -------------------------------------------------------------------------------------
                 // Draw Body -------------------------------------------------------------------------------------
-                for(int i = 0; i < 360; i += 360/sides)
+                for (int i = 0; i < 360; i += 360/sides)
                 {
                 {
                     rlVertex3f(sin(DEG2RAD*i) * radiusBottom, 0, cos(DEG2RAD*i) * radiusBottom); //Bottom Left
                     rlVertex3f(sin(DEG2RAD*i) * radiusBottom, 0, cos(DEG2RAD*i) * radiusBottom); //Bottom Left
                     rlVertex3f(sin(DEG2RAD*(i+360/sides)) * radiusBottom, 0, cos(DEG2RAD*(i+360/sides)) * radiusBottom); //Bottom Right
                     rlVertex3f(sin(DEG2RAD*(i+360/sides)) * radiusBottom, 0, cos(DEG2RAD*(i+360/sides)) * radiusBottom); //Bottom Right
@@ -388,7 +398,7 @@ void DrawCylinder(Vector3 position, float radiusTop, float radiusBottom, float h
                 }
                 }
 
 
                 // Draw Cap --------------------------------------------------------------------------------------
                 // Draw Cap --------------------------------------------------------------------------------------
-                for(int i = 0; i < 360; i += 360/sides)
+                for (int i = 0; i < 360; i += 360/sides)
                 {
                 {
                     rlVertex3f(0, height, 0);
                     rlVertex3f(0, height, 0);
                     rlVertex3f(sin(DEG2RAD*i) * radiusTop, height, cos(DEG2RAD*i) * radiusTop);
                     rlVertex3f(sin(DEG2RAD*i) * radiusTop, height, cos(DEG2RAD*i) * radiusTop);
@@ -398,7 +408,7 @@ void DrawCylinder(Vector3 position, float radiusTop, float radiusBottom, float h
             else
             else
             {
             {
                 // Draw Cone -------------------------------------------------------------------------------------
                 // Draw Cone -------------------------------------------------------------------------------------
-                for(int i = 0; i < 360; i += 360/sides)
+                for (int i = 0; i < 360; i += 360/sides)
                 {
                 {
                     rlVertex3f(0, height, 0);
                     rlVertex3f(0, height, 0);
                     rlVertex3f(sin(DEG2RAD*i) * radiusBottom, 0, cos(DEG2RAD*i) * radiusBottom);
                     rlVertex3f(sin(DEG2RAD*i) * radiusBottom, 0, cos(DEG2RAD*i) * radiusBottom);
@@ -407,7 +417,7 @@ void DrawCylinder(Vector3 position, float radiusTop, float radiusBottom, float h
             }
             }
 
 
             // Draw Base -----------------------------------------------------------------------------------------
             // Draw Base -----------------------------------------------------------------------------------------
-            for(int i = 0; i < 360; i += 360/sides)
+            for (int i = 0; i < 360; i += 360/sides)
             {
             {
                 rlVertex3f(0, 0, 0);
                 rlVertex3f(0, 0, 0);
                 rlVertex3f(sin(DEG2RAD*(i+360/sides)) * radiusBottom, 0, cos(DEG2RAD*(i+360/sides)) * radiusBottom);
                 rlVertex3f(sin(DEG2RAD*(i+360/sides)) * radiusBottom, 0, cos(DEG2RAD*(i+360/sides)) * radiusBottom);
@@ -421,7 +431,7 @@ void DrawCylinder(Vector3 position, float radiusTop, float radiusBottom, float h
 // NOTE: It could be also used for pyramid and cone
 // NOTE: It could be also used for pyramid and cone
 void DrawCylinderWires(Vector3 position, float radiusTop, float radiusBottom, float height, int sides, Color color)
 void DrawCylinderWires(Vector3 position, float radiusTop, float radiusBottom, float height, int sides, Color color)
 {
 {
-    if(sides < 3) sides = 3;
+    if (sides < 3) sides = 3;
 
 
     rlPushMatrix();
     rlPushMatrix();
         rlTranslatef(position.x, position.y, position.z);
         rlTranslatef(position.x, position.y, position.z);
@@ -429,7 +439,7 @@ void DrawCylinderWires(Vector3 position, float radiusTop, float radiusBottom, fl
         rlBegin(RL_LINES);
         rlBegin(RL_LINES);
             rlColor4ub(color.r, color.g, color.b, color.a);
             rlColor4ub(color.r, color.g, color.b, color.a);
 
 
-            for(int i = 0; i < 360; i += 360/sides)
+            for (int i = 0; i < 360; i += 360/sides)
             {
             {
                 rlVertex3f(sin(DEG2RAD*i) * radiusBottom, 0, cos(DEG2RAD*i) * radiusBottom);
                 rlVertex3f(sin(DEG2RAD*i) * radiusBottom, 0, cos(DEG2RAD*i) * radiusBottom);
                 rlVertex3f(sin(DEG2RAD*(i+360/sides)) * radiusBottom, 0, cos(DEG2RAD*(i+360/sides)) * radiusBottom);
                 rlVertex3f(sin(DEG2RAD*(i+360/sides)) * radiusBottom, 0, cos(DEG2RAD*(i+360/sides)) * radiusBottom);
@@ -490,7 +500,7 @@ void DrawGrid(int slices, float spacing)
     int halfSlices = slices / 2;
     int halfSlices = slices / 2;
 
 
     rlBegin(RL_LINES);
     rlBegin(RL_LINES);
-        for(int i = -halfSlices; i <= halfSlices; i++)
+        for (int i = -halfSlices; i <= halfSlices; i++)
         {
         {
             if (i == 0)
             if (i == 0)
             {
             {
@@ -732,13 +742,13 @@ Material LoadDefaultMaterial(void)
     return material;
     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
 // NOTE: Standard shader supports multiple maps and lights
 Material LoadStandardMaterial(void)
 Material LoadStandardMaterial(void)
 {
 {
     Material material = LoadDefaultMaterial();
     Material material = LoadDefaultMaterial();
     
     
-    //material.shader = GetStandardShader();
+    material.shader = GetStandardShader();
 
 
     return material;
     return material;
 }
 }
@@ -788,9 +798,9 @@ static Mesh GenMeshHeightmap(Image heightmap, Vector3 size)
 
 
     Vector3 scaleFactor = { size.x/mapX, size.y/255.0f, size.z/mapZ };
     Vector3 scaleFactor = { size.x/mapX, size.y/255.0f, size.z/mapZ };
 
 
-    for(int z = 0; z < mapZ-1; z++)
+    for (int z = 0; z < mapZ-1; z++)
     {
     {
-        for(int x = 0; x < mapX-1; x++)
+        for (int x = 0; x < mapX-1; x++)
         {
         {
             // Fill vertices array with data
             // Fill vertices array with data
             //----------------------------------------------------------
             //----------------------------------------------------------
@@ -1240,7 +1250,7 @@ void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rota
     //Matrix matModel = MatrixMultiply(model.transform, matTransform);    // Transform to world-space coordinates
     //Matrix matModel = MatrixMultiply(model.transform, matTransform);    // Transform to world-space coordinates
     
     
     model.transform = MatrixMultiply(MatrixMultiply(matScale, matRotation), matTranslation);
     model.transform = MatrixMultiply(MatrixMultiply(matScale, matRotation), matTranslation);
-    model.material.colDiffuse = tint;
+    // model.material.colDiffuse = tint;
     
     
     rlglDrawMesh(model.mesh, model.material, model.transform);
     rlglDrawMesh(model.mesh, model.material, model.transform);
 }
 }
@@ -1407,7 +1417,7 @@ bool CheckCollisionRaySphere(Ray ray, Vector3 spherePosition, float sphereRadius
     float vector = VectorDotProduct(raySpherePos, ray.direction);
     float vector = VectorDotProduct(raySpherePos, ray.direction);
     float d = sphereRadius*sphereRadius - (distance*distance - vector*vector);
     float d = sphereRadius*sphereRadius - (distance*distance - vector*vector);
     
     
-    if(d >= 0.0f) collision = true;
+    if (d >= 0.0f) collision = true;
     
     
     return collision;
     return collision;
 }
 }
@@ -1422,14 +1432,14 @@ bool CheckCollisionRaySphereEx(Ray ray, Vector3 spherePosition, float sphereRadi
     float vector = VectorDotProduct(raySpherePos, ray.direction);
     float vector = VectorDotProduct(raySpherePos, ray.direction);
     float d = sphereRadius*sphereRadius - (distance*distance - vector*vector);
     float d = sphereRadius*sphereRadius - (distance*distance - vector*vector);
     
     
-    if(d >= 0.0f) collision = true;
+    if (d >= 0.0f) collision = true;
     
     
     // Calculate collision point
     // Calculate collision point
     Vector3 offset = ray.direction;
     Vector3 offset = ray.direction;
     float collisionDistance = 0;
     float collisionDistance = 0;
     
     
     // Check if ray origin is inside the sphere to calculate the correct collision point
     // Check if ray origin is inside the sphere to calculate the correct collision point
-    if(distance < sphereRadius) collisionDistance = vector + sqrt(d);
+    if (distance < sphereRadius) collisionDistance = vector + sqrt(d);
     else collisionDistance = vector - sqrt(d);
     else collisionDistance = vector - sqrt(d);
     
     
     VectorScale(&offset, collisionDistance);
     VectorScale(&offset, collisionDistance);
@@ -1767,11 +1777,11 @@ static Mesh LoadOBJ(const char *fileName)
     // First reading pass: Get numVertex, numNormals, numTexCoords, numTriangles
     // First reading pass: Get numVertex, numNormals, numTexCoords, numTriangles
     // NOTE: vertex, texcoords and normals could be optimized (to be used indexed on faces definition)
     // NOTE: vertex, texcoords and normals could be optimized (to be used indexed on faces definition)
     // NOTE: faces MUST be defined as TRIANGLES (3 vertex per face)
     // NOTE: faces MUST be defined as TRIANGLES (3 vertex per face)
-    while(!feof(objFile))
+    while (!feof(objFile))
     {
     {
         fscanf(objFile, "%c", &dataType);
         fscanf(objFile, "%c", &dataType);
 
 
-        switch(dataType)
+        switch (dataType)
         {
         {
             case '#':   // Comments
             case '#':   // Comments
             case 'o':   // Object name (One OBJ file can contain multible named meshes)
             case 'o':   // Object name (One OBJ file can contain multible named meshes)
@@ -1832,11 +1842,11 @@ static Mesh LoadOBJ(const char *fileName)
     // Second reading pass: Get vertex data to fill intermediate arrays
     // Second reading pass: Get vertex data to fill intermediate arrays
     // NOTE: This second pass is required in case of multiple meshes defined in same OBJ
     // NOTE: This second pass is required in case of multiple meshes defined in same OBJ
     // TODO: Consider that different meshes can have different vertex data available (position, texcoords, normals)
     // TODO: Consider that different meshes can have different vertex data available (position, texcoords, normals)
-    while(!feof(objFile))
+    while (!feof(objFile))
     {
     {
         fscanf(objFile, "%c", &dataType);
         fscanf(objFile, "%c", &dataType);
 
 
-        switch(dataType)
+        switch (dataType)
         {
         {
             case '#': case 'o': case 'g': case 's': case 'm': case 'u': case 'f': fgets(comments, 200, objFile); break;
             case '#': case 'o': case 'g': case 's': case 'm': case 'u': case 'f': fgets(comments, 200, objFile); break;
             case 'v':
             case 'v':
@@ -1893,11 +1903,11 @@ static Mesh LoadOBJ(const char *fileName)
     if (numNormals == 0) TraceLog(INFO, "[%s] No normals data on OBJ, normals will be generated from faces data", fileName);
     if (numNormals == 0) TraceLog(INFO, "[%s] No normals data on OBJ, normals will be generated from faces data", fileName);
 
 
     // Third reading pass: Get faces (triangles) data and fill VertexArray
     // Third reading pass: Get faces (triangles) data and fill VertexArray
-    while(!feof(objFile))
+    while (!feof(objFile))
     {
     {
         fscanf(objFile, "%c", &dataType);
         fscanf(objFile, "%c", &dataType);
 
 
-        switch(dataType)
+        switch (dataType)
         {
         {
             case '#': case 'o': case 'g': case 's': case 'm': case 'u': case 'v': fgets(comments, 200, objFile); break;
             case '#': case 'o': case 'g': case 's': case 'm': case 'u': case 'v': fgets(comments, 200, objFile); break;
             case 'f':
             case 'f':
@@ -2013,7 +2023,7 @@ static Material LoadMTL(const char *fileName)
         return material;
         return material;
     }
     }
 
 
-    while(!feof(mtlFile))
+    while (!feof(mtlFile))
     {
     {
         fgets(buffer, MAX_BUFFER_SIZE, mtlFile);
         fgets(buffer, MAX_BUFFER_SIZE, mtlFile);
         
         
@@ -2071,8 +2081,7 @@ static Material LoadMTL(const char *fileName)
                     int shininess = 0;
                     int shininess = 0;
                     sscanf(buffer, "Ns %i", &shininess);
                     sscanf(buffer, "Ns %i", &shininess);
                     
                     
-                    // Normalize shininess value to material glossiness attribute
-                    material.glossiness = (float)shininess/1000;
+                    material.glossiness = (float)shininess;
                 }
                 }
                 else if (buffer[1] == 'i')  // Ni int   Refraction index.
                 else if (buffer[1] == 'i')  // Ni int   Refraction index.
                 {
                 {

+ 10 - 12
src/raylib.h

@@ -398,7 +398,7 @@ typedef struct Shader {
 
 
     // Uniform locations
     // Uniform locations
     int mvpLoc;           // ModelView-Projection matrix uniform location point (vertex shader)
     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
     // Texture map locations
     int mapDiffuseLoc;    // Diffuse map texture uniform location point (fragment shader)
     int mapDiffuseLoc;    // Diffuse map texture uniform location point (fragment shader)
@@ -418,7 +418,7 @@ typedef struct Material {
     Color colAmbient;           // Ambient color
     Color colAmbient;           // Ambient color
     Color colSpecular;          // Specular color
     Color colSpecular;          // Specular color
     
     
-    float glossiness;           // Glossiness level
+    float glossiness;           // Glossiness level (Ranges from 0 to 1000)
     float normalDepth;          // Normal map depth
     float normalDepth;          // Normal map depth
 } Material;
 } Material;
 
 
@@ -430,25 +430,19 @@ typedef struct Model {
 } Model;
 } Model;
 
 
 // Light type
 // Light type
-// TODO: Review contained data to support different light types and features
 typedef struct LightData {
 typedef struct LightData {
     int id;
     int id;
     int type;           // LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT
     int type;           // LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT
     bool enabled;
     bool enabled;
     
     
     Vector3 position;
     Vector3 position;
-    Vector3 direction;  // Used on LIGHT_DIRECTIONAL and LIGHT_SPOT (cone direction)
-    float attenuation;  // Lost of light intensity with distance (use radius?)
+    Vector3 target;     // Used on LIGHT_DIRECTIONAL and LIGHT_SPOT (cone direction target)
+    float attenuation;  // Lost of light intensity with distance (world distance)
     
     
-    Color diffuse;      // Use Vector3 diffuse (including intensities)?
+    Color diffuse;      // Use Vector3 diffuse
     float intensity;
     float intensity;
     
     
-    Color specular;
-    //float specFactor;   // Specular intensity ?
-
-    //Color ambient;    // Required?
-    
-    float coneAngle;         // SpotLight
+    float coneAngle;    // Spot light max angle
 } LightData, *Light;
 } LightData, *Light;
 
 
 // Light types
 // Light types
@@ -808,6 +802,7 @@ const char *SubText(const char *text, int position, int length);
 //------------------------------------------------------------------------------------
 //------------------------------------------------------------------------------------
 // Basic 3d Shapes Drawing Functions (Module: models)
 // Basic 3d Shapes Drawing Functions (Module: models)
 //------------------------------------------------------------------------------------
 //------------------------------------------------------------------------------------
+void Draw3DLine(Vector3 startPos, Vector3 endPos, Color color);                                    // Draw a line in 3D world space
 void DrawCube(Vector3 position, float width, float height, float lenght, Color color);             // Draw cube
 void DrawCube(Vector3 position, float width, float height, float lenght, Color color);             // Draw cube
 void DrawCubeV(Vector3 position, Vector3 size, Color color);                                       // Draw cube (Vector version)
 void DrawCubeV(Vector3 position, Vector3 size, Color color);                                       // Draw cube (Vector version)
 void DrawCubeWires(Vector3 position, float width, float height, float lenght, Color color);        // Draw cube wires
 void DrawCubeWires(Vector3 position, float width, float height, float lenght, Color color);        // Draw cube wires
@@ -836,6 +831,7 @@ void SetModelTexture(Model *model, Texture2D texture);          // Link a textur
 
 
 Material LoadMaterial(const char *fileName);                    // Load material data (from file)
 Material LoadMaterial(const char *fileName);                    // Load material data (from file)
 Material LoadDefaultMaterial(void);                             // Load default material (uses default models shader)
 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 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)
 void DrawModel(Model model, Vector3 position, float scale, Color tint);                            // Draw a model (with texture if set)
@@ -865,6 +861,7 @@ void UnloadShader(Shader shader);                                   // Unload a
 void SetDefaultShader(void);                                        // Set default shader to be used in batch draw
 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
 void SetCustomShader(Shader shader);                                // Set custom shader to be used in batch draw
 Shader GetDefaultShader(void);                                      // Get default shader
 Shader GetDefaultShader(void);                                      // Get default shader
+Shader GetStandardShader(void);                                     // Get default shader
 Texture2D GetDefaultTexture(void);                                  // Get default texture
 Texture2D GetDefaultTexture(void);                                  // Get default texture
 
 
 int GetShaderLocation(Shader shader, const char *uniformName);              // Get shader uniform location
 int GetShaderLocation(Shader shader, const char *uniformName);              // Get shader uniform location
@@ -875,6 +872,7 @@ void SetShaderValueMatrix(Shader shader, int uniformLoc, Matrix mat);       // S
 void SetBlendMode(int mode);                                        // Set blending mode (alpha, additive, multiplied)
 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
 Light CreateLight(int type, Vector3 position, Color diffuse);       // Create a new light, initialize it and add to pool
+void DrawLights(void);                                              // Draw all created lights in 3D world
 void DestroyLight(Light light);                                     // Destroy a light and take it out of the list
 void DestroyLight(Light light);                                     // Destroy a light and take it out of the list
 
 
 //----------------------------------------------------------------------------------
 //----------------------------------------------------------------------------------

+ 138 - 70
src/rlgl.c

@@ -191,6 +191,7 @@ static bool useTempBuffer = false;
 
 
 // Shader Programs
 // Shader Programs
 static Shader defaultShader;
 static Shader defaultShader;
+static Shader standardShader;
 static Shader currentShader;            // By default, defaultShader
 static Shader currentShader;            // By default, defaultShader
 
 
 // Flags for supported extensions
 // 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 Shader LoadStandardShader(void);     // Load standard shader (support materials and lighting)
 static void LoadDefaultShaderLocations(Shader *shader); // Bind default shader locations (attributes and uniforms)
 static void LoadDefaultShaderLocations(Shader *shader); // Bind default shader locations (attributes and uniforms)
 static void UnloadDefaultShader(void);      // Unload default shader
 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 LoadDefaultBuffers(void);       // Load default internal buffers (lines, triangles, quads)
 static void UpdateDefaultBuffers(void);     // Update default internal buffers (VAOs/VBOs) with vertex data
 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)
     // Init default Shader (customized for GL 3.3 and ES2)
     defaultShader = LoadDefaultShader();
     defaultShader = LoadDefaultShader();
+    standardShader = LoadStandardShader();
     currentShader = defaultShader;
     currentShader = defaultShader;
 
 
     LoadDefaultBuffers();        // Initialize default vertex arrays buffers (lines, triangles, quads)
     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)
 #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
     UnloadDefaultShader();
     UnloadDefaultShader();
+    UnloadStandardShader();
     UnloadDefaultBuffers();
     UnloadDefaultBuffers();
     
     
     // Delete default white texture
     // Delete default white texture
@@ -1393,7 +1397,7 @@ RenderTexture2D rlglLoadRenderTexture(int width, int height)
     {
     {
         TraceLog(WARNING, "Framebuffer object could not be created...");
         TraceLog(WARNING, "Framebuffer object could not be created...");
         
         
-        switch(status)
+        switch (status)
         {
         {
             case GL_FRAMEBUFFER_UNSUPPORTED: TraceLog(WARNING, "Framebuffer is unsupported"); break;
             case GL_FRAMEBUFFER_UNSUPPORTED: TraceLog(WARNING, "Framebuffer is unsupported"); break;
             case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: TraceLog(WARNING, "Framebuffer incomplete attachment"); break;
             case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: TraceLog(WARNING, "Framebuffer incomplete attachment"); break;
@@ -1757,19 +1761,33 @@ void rlglDrawMesh(Mesh mesh, Material material, Matrix transform)
 
 
     // Send combined model-view-projection matrix to shader
     // Send combined model-view-projection matrix to shader
     glUniformMatrix4fv(material.shader.mvpLoc, 1, false, MatrixToFloat(matMVP));
     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
     // 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 };
     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);
     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));
+        
+        // Send view transformation matrix to shader. View matrix 8, 9 and 10 are view direction vector axis values (target - position)
+        glUniform3f(glGetUniformLocation(material.shader.id, "viewDir"), matView.m8, matView.m9, matView.m10);
+        
+        // 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);
+        // Upload to shader glossiness
+        glUniform1f(glGetUniformLocation(material.shader.id, "glossiness"), material.glossiness);
+    }    
     
     
     // Set shader textures (diffuse, normal, specular)
     // Set shader textures (diffuse, normal, specular)
     glActiveTexture(GL_TEXTURE0);
     glActiveTexture(GL_TEXTURE0);
@@ -1791,13 +1809,7 @@ void rlglDrawMesh(Mesh mesh, Material material, Matrix transform)
         glActiveTexture(GL_TEXTURE2);
         glActiveTexture(GL_TEXTURE2);
         glBindTexture(GL_TEXTURE_2D, material.texSpecular.id);
         glBindTexture(GL_TEXTURE_2D, material.texSpecular.id);
         glUniform1i(material.shader.mapSpecularLoc, 2);   // Texture fits in active texture unit 2
         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)
     if (vaoSupported)
     {
     {
@@ -2148,6 +2160,17 @@ Shader GetDefaultShader(void)
 #endif
 #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
 // Get shader uniform location
 int GetShaderLocation(Shader shader, const char *uniformName)
 int GetShaderLocation(Shader shader, const char *uniformName)
 {
 {
@@ -2225,7 +2248,6 @@ void SetBlendMode(int mode)
 }
 }
 
 
 // Create a new light, initialize it and add to pool
 // 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)
 Light CreateLight(int type, Vector3 position, Color diffuse)
 {
 {
     // Allocate dynamic memory
     // Allocate dynamic memory
@@ -2237,10 +2259,9 @@ Light CreateLight(int type, Vector3 position, Color diffuse)
     light->enabled = true;
     light->enabled = true;
     
     
     light->position = position;
     light->position = position;
-    light->direction = (Vector3){ 0.0f, 0.0f, 0.0f };
+    light->target = (Vector3){ 0.0f, 0.0f, 0.0f };
     light->intensity = 1.0f;
     light->intensity = 1.0f;
     light->diffuse = diffuse;
     light->diffuse = diffuse;
-    light->specular = WHITE;
     
     
     // Add new light to the array
     // Add new light to the array
     lights[lightsCount] = light;
     lights[lightsCount] = light;
@@ -2251,6 +2272,31 @@ Light CreateLight(int type, Vector3 position, Color diffuse)
     return light;
     return light;
 }
 }
 
 
+// Draw all created lights in 3D world
+void DrawLights(void)
+{
+    for (int i = 0; i < lightsCount; i++)
+    {
+        switch (lights[i]->type)
+        {
+            case LIGHT_POINT: DrawSphereWires(lights[i]->position, 0.3f*lights[i]->intensity, 4, 8, (lights[i]->enabled ? lights[i]->diffuse : BLACK)); break;
+            case LIGHT_DIRECTIONAL:
+            {                
+                Draw3DLine(lights[i]->position, lights[i]->target, (lights[i]->enabled ? lights[i]->diffuse : BLACK));
+                DrawSphereWires(lights[i]->position, 0.3f*lights[i]->intensity, 4, 8, (lights[i]->enabled ? lights[i]->diffuse : BLACK));
+                DrawCubeWires(lights[i]->target, 0.3f, 0.3f, 0.3f, (lights[i]->enabled ? lights[i]->diffuse : BLACK));
+            } break;
+            case LIGHT_SPOT:
+            {                
+                Draw3DLine(lights[i]->position, lights[i]->target, (lights[i]->enabled ? lights[i]->diffuse : BLACK));
+                DrawCylinderWires(lights[i]->position, 0.0f, 0.3f*lights[i]->coneAngle/50, 0.6f, 5, (lights[i]->enabled ? lights[i]->diffuse : BLACK));
+                DrawCubeWires(lights[i]->target, 0.3f, 0.3f, 0.3f, (lights[i]->enabled ? lights[i]->diffuse : BLACK));
+            } break;
+            default: break;
+        }
+    }
+}
+
 // Destroy a light and take it out of the list
 // Destroy a light and take it out of the list
 void DestroyLight(Light light)
 void DestroyLight(Light light)
 {
 {
@@ -2468,15 +2514,15 @@ static Shader LoadDefaultShader(void)
         "varying vec4 fragColor;            \n"
         "varying vec4 fragColor;            \n"
 #endif
 #endif
         "uniform sampler2D texture0;        \n"
         "uniform sampler2D texture0;        \n"
-        "uniform vec4 fragTintColor;        \n"
+        "uniform vec4 colDiffuse;           \n"
         "void main()                        \n"
         "void main()                        \n"
         "{                                  \n"
         "{                                  \n"
 #if defined(GRAPHICS_API_OPENGL_33)
 #if defined(GRAPHICS_API_OPENGL_33)
         "    vec4 texelColor = texture(texture0, fragTexCoord);   \n"
         "    vec4 texelColor = texture(texture0, fragTexCoord);   \n"
-        "    finalColor = texelColor*fragTintColor*fragColor;     \n"
+        "    finalColor = texelColor*colDiffuse*fragColor;        \n"
 #elif defined(GRAPHICS_API_OPENGL_ES2)
 #elif defined(GRAPHICS_API_OPENGL_ES2)
         "    vec4 texelColor = texture2D(texture0, fragTexCoord); \n" // NOTE: texture2D() is deprecated on OpenGL 3.3 and ES 3.0
         "    vec4 texelColor = texture2D(texture0, fragTexCoord); \n" // NOTE: texture2D() is deprecated on OpenGL 3.3 and ES 3.0
-        "    gl_FragColor = texelColor*fragTintColor*fragColor;   \n"
+        "    gl_FragColor = texelColor*colDiffuse*fragColor;      \n"
 #endif
 #endif
         "}                                  \n";
         "}                                  \n";
 
 
@@ -2493,25 +2539,17 @@ static Shader LoadDefaultShader(void)
 // Load standard shader
 // Load standard shader
 // NOTE: This shader supports: 
 // NOTE: This shader supports: 
 //      - Up to 3 different maps: diffuse, normal, specular
 //      - Up to 3 different maps: diffuse, normal, specular
-//      - Material properties: colDiffuse, colAmbient, colSpecular, glossiness, normalDepth
+//      - Material properties: colAmbient, colDiffuse, colSpecular, glossiness, normalDepth
 //      - Up to 8 lights: Point, Directional or Spot
 //      - Up to 8 lights: Point, Directional or Spot
 static Shader LoadStandardShader(void)
 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);
+    // Load standard shader (TODO: rewrite as char pointers)
+    Shader shader = LoadShader("resources/shaders/standard.vs", "resources/shaders/standard.fs");
 
 
     if (shader.id != 0) TraceLog(INFO, "[SHDR ID %i] Standard shader loaded successfully", shader.id);
     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);
     else TraceLog(WARNING, "[SHDR ID %i] Standard shader could not be loaded", shader.id);
 
 
-    if (shader.id != 0) LoadDefaultShaderLocations(&shader);    // TODO: Review locations fetching
+    if (shader.id != 0) LoadDefaultShaderLocations(&shader);
 
 
     return shader;
     return shader;
 }
 }
@@ -2540,7 +2578,7 @@ static void LoadDefaultShaderLocations(Shader *shader)
     shader->mvpLoc  = glGetUniformLocation(shader->id, "mvpMatrix");
     shader->mvpLoc  = glGetUniformLocation(shader->id, "mvpMatrix");
 
 
     // Get handles to GLSL uniform locations (fragment shader)
     // Get handles to GLSL uniform locations (fragment shader)
-    shader->tintColorLoc = glGetUniformLocation(shader->id, "fragTintColor");
+    shader->tintColorLoc = glGetUniformLocation(shader->id, "colDiffuse");
     shader->mapDiffuseLoc = glGetUniformLocation(shader->id, "texture0");
     shader->mapDiffuseLoc = glGetUniformLocation(shader->id, "texture0");
     shader->mapNormalLoc = glGetUniformLocation(shader->id, "texture1");
     shader->mapNormalLoc = glGetUniformLocation(shader->id, "texture1");
     shader->mapSpecularLoc = glGetUniformLocation(shader->id, "texture2");
     shader->mapSpecularLoc = glGetUniformLocation(shader->id, "texture2");
@@ -2554,10 +2592,23 @@ static void UnloadDefaultShader(void)
     //glDetachShader(defaultShader, vertexShader);
     //glDetachShader(defaultShader, vertexShader);
     //glDetachShader(defaultShader, fragmentShader);
     //glDetachShader(defaultShader, fragmentShader);
     //glDeleteShader(vertexShader);     // Already deleted on shader compilation
     //glDeleteShader(vertexShader);     // Already deleted on shader compilation
-    //glDeleteShader(fragmentShader);   // Already deleted on sahder compilation
+    //glDeleteShader(fragmentShader);   // Already deleted on shader compilation
     glDeleteProgram(defaultShader.id);
     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)
 // Load default internal buffers (lines, triangles, quads)
 static void LoadDefaultBuffers(void)
 static void LoadDefaultBuffers(void)
 {
 {
@@ -3003,58 +3054,75 @@ static void UnloadDefaultBuffers(void)
 
 
 // Sets shader uniform values for lights array
 // 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
 // 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)
 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 = glGetUniformLocation(shader.id, "lightsCount");
+    glUniform1i(locPoint, lightsCount);
     
     
-    int locPoint;
     char locName[32] = "lights[x].position\0";
     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++)
     for (int i = 0; i < lightsCount; i++)
     {
     {
         locName[7] = '0' + 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], "enabled\0", strlen("enabled\0") + 1);
+        locPoint = GetShaderLocation(shader, locName);
+        glUniform1i(locPoint, lights[i]->enabled);
         
         
-        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"));
+        memcpy(&locName[10], "type\0", strlen("type\0") + 1);
+        locPoint = GetShaderLocation(shader, locName);
+        glUniform1i(locPoint, lights[i]->type);
+        
+        memcpy(&locName[10], "diffuse\0", strlen("diffuse\0") + 2);
         locPoint = glGetUniformLocation(shader.id, locName);
         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 );
+        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"));
         memcpy(&locName[10], "intensity\0", strlen("intensity\0"));
         locPoint = glGetUniformLocation(shader.id, locName);
         locPoint = glGetUniformLocation(shader.id, locName);
         glUniform1f(locPoint, lights[i]->intensity);
         glUniform1f(locPoint, lights[i]->intensity);
         
         
+        switch (lights[i]->type)
+        {
+            case LIGHT_POINT:
+            {
+                memcpy(&locName[10], "position\0", strlen("position\0") + 1);
+                locPoint = GetShaderLocation(shader, locName);
+                glUniform3f(locPoint, lights[i]->position.x, lights[i]->position.y, lights[i]->position.z);
+                
+                memcpy(&locName[10], "attenuation\0", strlen("attenuation\0"));
+                locPoint = GetShaderLocation(shader, locName);
+                glUniform1f(locPoint, lights[i]->attenuation);
+            } break;
+            case LIGHT_DIRECTIONAL:
+            {
+                memcpy(&locName[10], "direction\0", strlen("direction\0") + 2);
+                locPoint = GetShaderLocation(shader, locName);
+                Vector3 direction = { lights[i]->target.x - lights[i]->position.x, lights[i]->target.y - lights[i]->position.y, lights[i]->target.z - lights[i]->position.z };
+                VectorNormalize(&direction);
+                glUniform3f(locPoint, direction.x, direction.y, direction.z);
+            } break;
+            case LIGHT_SPOT:
+            {
+                memcpy(&locName[10], "position\0", strlen("position\0") + 1);
+                locPoint = GetShaderLocation(shader, locName);
+                glUniform3f(locPoint, lights[i]->position.x, lights[i]->position.y, lights[i]->position.z);
+                
+                memcpy(&locName[10], "direction\0", strlen("direction\0") + 2);
+                locPoint = GetShaderLocation(shader, locName);
+                
+                Vector3 direction = { lights[i]->target.x - lights[i]->position.x, lights[i]->target.y - lights[i]->position.y, lights[i]->target.z - lights[i]->position.z };
+                VectorNormalize(&direction);
+                glUniform3f(locPoint, direction.x, direction.y, direction.z);
+                
+                memcpy(&locName[10], "coneAngle\0", strlen("coneAngle\0"));
+                locPoint = GetShaderLocation(shader, locName);
+                glUniform1f(locPoint, lights[i]->coneAngle);
+            } break;
+            default: break;
+        }
+        
         // TODO: Pass to the shader any other required data from LightData struct
         // TODO: Pass to the shader any other required data from LightData struct
     }
     }
-    
-    glUseProgram(0);
 }
 }
 
 
 // Read text data from file
 // Read text data from file
@@ -3227,7 +3295,7 @@ static void TraceLog(int msgType, const char *text, ...)
     va_list args;
     va_list args;
     va_start(args, text);
     va_start(args, text);
 
 
-    switch(msgType)
+    switch (msgType)
     {
     {
         case INFO: fprintf(stdout, "INFO: "); break;
         case INFO: fprintf(stdout, "INFO: "); break;
         case ERROR: fprintf(stdout, "ERROR: "); break;
         case ERROR: fprintf(stdout, "ERROR: "); break;

+ 13 - 19
src/rlgl.h

@@ -196,40 +196,34 @@ typedef enum { OPENGL_11 = 1, OPENGL_33, OPENGL_ES_20 } GlVersion;
     
     
     // Material type
     // Material type
     typedef struct Material {
     typedef struct Material {
-        Shader shader;
+        Shader shader;              // Standard shader (supports 3 map types: diffuse, normal, specular)
 
 
-        Texture2D texDiffuse;      // Diffuse texture
-        Texture2D texNormal;       // Normal texture
-        Texture2D texSpecular;     // Specular texture
+        Texture2D texDiffuse;       // Diffuse texture
+        Texture2D texNormal;        // Normal texture
+        Texture2D texSpecular;      // Specular texture
         
         
-        Color colDiffuse;
-        Color colAmbient;
-        Color colSpecular;
+        Color colDiffuse;           // Diffuse color
+        Color colAmbient;           // Ambient color
+        Color colSpecular;          // Specular color
         
         
-        float glossiness;
-        float normalDepth;
+        float glossiness;           // Glossiness level (Ranges from 0 to 1000)
+        float normalDepth;          // Normal map depth
     } Material;
     } Material;
     
     
     // Light type
     // Light type
-    // TODO: Review contained data to support different light types and features
     typedef struct LightData {
     typedef struct LightData {
         int id;
         int id;
         int type;           // LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT
         int type;           // LIGHT_POINT, LIGHT_DIRECTIONAL, LIGHT_SPOT
         bool enabled;
         bool enabled;
         
         
         Vector3 position;
         Vector3 position;
-        Vector3 direction;  // Used on LIGHT_DIRECTIONAL and LIGHT_SPOT (cone direction)
-        float attenuation;  // Lost of light intensity with distance (use radius?)
+        Vector3 target;     // Used on LIGHT_DIRECTIONAL and LIGHT_SPOT (cone direction target)
+        float attenuation;  // Lost of light intensity with distance (world distance)
         
         
-        Color diffuse;      // Use Vector3 diffuse (including intensities)?
+        Color diffuse;      // Use Vector3 diffuse
         float intensity;
         float intensity;
         
         
-        Color specular;
-        //float specFactor;   // Specular intensity ?
-
-        //Color ambient;    // Required?
-        
-        float coneAngle;         // SpotLight
+        float coneAngle;    // Spot light max angle
     } LightData, *Light;
     } LightData, *Light;
 	
 	
     // Color blending modes (pre-defined)
     // Color blending modes (pre-defined)