From 11cf455fe0d2c956043aa70f7d8256c4a339b430 Mon Sep 17 00:00:00 2001 From: victorfisac Date: Mon, 30 May 2016 19:59:21 +0200 Subject: [PATCH] Standard Lighting (3/3) - Added normal and specular maps to standard shader. - Added full tint attribute to standard shader and material data type. - Changed point light attenuation to radius. --- examples/resources/shaders/standard.fs | 44 ++++++++++++++++++-------- examples/shaders_standard_lighting.c | 8 ++--- 2 files changed, 34 insertions(+), 18 deletions(-) diff --git a/examples/resources/shaders/standard.fs b/examples/resources/shaders/standard.fs index 3c3bef4b4..bb9e6865a 100644 --- a/examples/resources/shaders/standard.fs +++ b/examples/resources/shaders/standard.fs @@ -8,12 +8,18 @@ in vec3 fragNormal; out vec4 finalColor; uniform sampler2D texture0; +uniform sampler2D texture1; +uniform sampler2D texture2; +uniform vec4 colTint; uniform vec4 colAmbient; uniform vec4 colDiffuse; uniform vec4 colSpecular; uniform float glossiness; +uniform int useNormal; +uniform int useSpecular; + uniform mat4 modelMatrix; uniform vec3 viewDir; @@ -24,7 +30,7 @@ struct Light { vec3 direction; vec4 diffuse; float intensity; - float attenuation; + float radius; float coneAngle; }; @@ -32,27 +38,27 @@ const int maxLights = 8; uniform int lightsCount; uniform Light lights[maxLights]; -vec3 CalcPointLight(Light l, vec3 n, vec3 v) +vec3 CalcPointLight(Light l, vec3 n, vec3 v, float s) { 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; + float diff = 1.0/dot(surfaceToLight/l.radius, surfaceToLight/l.radius)*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); + spec = pow(dot(n, h), 3 + glossiness)*s; } return (diff*l.diffuse.rgb*colDiffuse.rgb + spec*colSpecular.rgb); } -vec3 CalcDirectionalLight(Light l, vec3 n, vec3 v) +vec3 CalcDirectionalLight(Light l, vec3 n, vec3 v, float s) { vec3 lightDir = normalize(-l.direction); @@ -64,14 +70,14 @@ vec3 CalcDirectionalLight(Light l, vec3 n, vec3 v) if (diff > 0.0) { vec3 h = normalize(lightDir + v); - spec = pow(dot(n, h), 3 + glossiness); + spec = pow(dot(n, h), 3 + glossiness)*s; } // Combine results return (diff*l.intensity*l.diffuse.rgb*colDiffuse.rgb + spec*colSpecular.rgb); } -vec3 CalcSpotLight(Light l, vec3 n, vec3 v) +vec3 CalcSpotLight(Light l, vec3 n, vec3 v, float s) { vec3 surfacePos = vec3(modelMatrix*vec4(fragPosition, 1)); vec3 lightToSurface = normalize(surfacePos - l.position); @@ -95,7 +101,7 @@ vec3 CalcSpotLight(Light l, vec3 n, vec3 v) if (diffAttenuation > 0.0) { vec3 h = normalize(lightDir + v); - spec = pow(dot(n, h), 3 + glossiness); + spec = pow(dot(n, h), 3 + glossiness)*s; } return falloff*(diffAttenuation*l.diffuse.rgb + spec*colSpecular.rgb); @@ -104,9 +110,10 @@ vec3 CalcSpotLight(Light l, vec3 n, vec3 v) void main() { // Calculate fragment normal in screen space + // NOTE: important to multiply model matrix by fragment normal to apply model transformation (rotation and scale) 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); @@ -115,6 +122,17 @@ void main() vec4 texelColor = texture(texture0, fragTexCoord); vec3 lighting = colAmbient.rgb; + // Calculate normal texture color fetching or set to maximum normal value by default + if(useNormal == 1) + { + n *= texture(texture1, fragTexCoord).rgb; + n = normalize(n); + } + + // Calculate specular texture color fetching or set to maximum specular value by default + float spec = 1.0; + if(useSpecular == 1) spec *= normalize(texture(texture2, fragTexCoord).r); + for (int i = 0; i < lightsCount; i++) { // Check if light is enabled @@ -123,14 +141,14 @@ void main() // 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; + case 0: lighting += CalcPointLight(lights[i], n, v, spec); break; + case 1: lighting += CalcDirectionalLight(lights[i], n, v, spec); break; + case 2: lighting += CalcSpotLight(lights[i], n, v, spec); break; default: break; } } } // Calculate final fragment color - finalColor = vec4(texelColor.rgb*lighting, texelColor.a); + finalColor = vec4(texelColor.rgb*lighting*colTint.rgb, texelColor.a*colTint.a); } diff --git a/examples/shaders_standard_lighting.c b/examples/shaders_standard_lighting.c index 6f45ca615..6b5cd9f58 100644 --- a/examples/shaders_standard_lighting.c +++ b/examples/shaders_standard_lighting.c @@ -69,8 +69,6 @@ int main() SetCameraMode(CAMERA_ORBITAL); // Set an 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 - - float framesCounter = 0; // Define frames counter to update model rotation SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- @@ -81,8 +79,6 @@ int main() // Update //---------------------------------------------------------------------------------- UpdateCamera(&camera); // Update internal camera and our camera - - framesCounter += 0.5f; //---------------------------------------------------------------------------------- // Draw @@ -93,7 +89,7 @@ int main() Begin3dMode(camera); - DrawModelEx(dwarf, position, (Vector3){ 0.0f, 1.0f, 0.0f }, framesCounter, (Vector3){ 2.0f, 2.0f, 2.0f}, RED); // Draw 3d model with texture + DrawModel(dwarf, position, 2.0f, WHITE); // Draw 3d model with texture DrawLights(); // Draw all created lights in 3D world @@ -102,6 +98,8 @@ int main() End3dMode(); DrawText("(c) Dwarf 3D model by David Moreno", screenWidth - 200, screenHeight - 20, 10, GRAY); + + DrawFPS(10, 10); EndDrawing(); //----------------------------------------------------------------------------------