Permalink
Browse files

Multiple lights working for article 08

  • Loading branch information...
1 parent 8ccd767 commit b2e9fccdd4fdd210ef8de544e68b0cd4b97419f4 @tomdalling committed Oct 16, 2013
Showing with 70 additions and 40 deletions.
  1. +28 −20 osx/08_even_more_lighting/resources/fragment-shader.txt
  2. +42 −20 osx/08_even_more_lighting/source/main.mm
@@ -18,52 +18,60 @@ uniform struct Light {
float ambientCoefficient;
float coneAngle;
vec3 coneDirection;
-} lights[MAX_LIGHTS];
+} allLights[MAX_LIGHTS];
in vec2 fragTexCoord;
in vec3 fragNormal;
in vec3 fragVert;
out vec4 finalColor;
-void main() {
- vec3 normal = normalize(transpose(inverse(mat3(model))) * fragNormal);
- vec3 surfacePos = vec3(model * vec4(fragVert, 1));
- vec4 surfaceColor = texture(material.tex, fragTexCoord);
- vec3 surfaceToCamera = normalize(cameraPosition - surfacePos);
+vec3 ApplyLight(Light light, vec3 surfaceColor, vec3 normal, vec3 surfacePos, vec3 surfaceToCamera) {
vec3 surfaceToLight;
- float attenuation = numLights; //TODO: remove "numLights" from here
- if(lights[0].position.w == 0.0) {
+ float attenuation = 1.0;
+ if(light.position.w == 0.0) {
//directional light
- surfaceToLight = normalize(lights[0].position.xyz);
+ surfaceToLight = normalize(light.position.xyz);
attenuation = 1.0; //no attenuation for directional lights
} else {
- //
- surfaceToLight = normalize(lights[0].position.xyz - surfacePos);
- float distanceToLight = length(lights[0].position.xyz - surfacePos);
- attenuation = 1.0 / (1.0 + lights[0].attenuation * pow(distanceToLight, 2));
+ //point light
+ surfaceToLight = normalize(light.position.xyz - surfacePos);
+ float distanceToLight = length(light.position.xyz - surfacePos);
+ attenuation = 1.0 / (1.0 + light.attenuation * pow(distanceToLight, 2));
//cone restrictions (affects attenuation)
- float lightToSurfaceAngle = degrees(acos(dot(-surfaceToLight, normalize(lights[0].coneDirection))));
- attenuation = (1.0-step(lights[0].coneAngle/2.0, lightToSurfaceAngle)) * attenuation;
+ float lightToSurfaceAngle = degrees(acos(dot(-surfaceToLight, normalize(light.coneDirection))));
+ attenuation = (1.0-step(light.coneAngle/2.0, lightToSurfaceAngle)) * attenuation;
}
-
//ambient
- vec3 ambient = lights[0].ambientCoefficient * surfaceColor.rgb * lights[0].intensities;
+ vec3 ambient = light.ambientCoefficient * surfaceColor.rgb * light.intensities;
//diffuse
float diffuseCoefficient = max(0.0, dot(normal, surfaceToLight));
- vec3 diffuse = diffuseCoefficient * surfaceColor.rgb * lights[0].intensities;
+ vec3 diffuse = diffuseCoefficient * surfaceColor.rgb * light.intensities;
//specular
float specularCoefficient = 0.0;
if(diffuseCoefficient > 0.0)
specularCoefficient = pow(max(0.0, dot(surfaceToCamera, reflect(-surfaceToLight, normal))), material.shininess);
- vec3 specular = specularCoefficient * material.specularColor * lights[0].intensities;
+ vec3 specular = specularCoefficient * material.specularColor * light.intensities;
//linear color (color before gamma correction)
- vec3 linearColor = ambient + attenuation*(diffuse + specular);
+ return ambient + attenuation*(diffuse + specular);
+}
+
+void main() {
+ vec3 normal = normalize(transpose(inverse(mat3(model))) * fragNormal);
+ vec3 surfacePos = vec3(model * vec4(fragVert, 1));
+ vec4 surfaceColor = texture(material.tex, fragTexCoord);
+ vec3 surfaceToCamera = normalize(cameraPosition - surfacePos);
+
+ //combine color from all the lights
+ vec3 linearColor = vec3(0);
+ for(int i = 0; i < numLights; ++i){
+ linearColor += ApplyLight(allLights[i], surfaceColor.rgb, normal, surfacePos, surfaceToCamera);
+ }
//final color (after gamma correction)
vec3 gamma = vec3(1.0/2.2);
@@ -29,6 +29,7 @@
#include <stdexcept>
#include <cmath>
#include <list>
+#include <sstream>
// tdogl classes
#include "tdogl/Program.h"
@@ -105,7 +106,7 @@
ModelAsset gWoodenCrate;
std::list<ModelInstance> gInstances;
GLfloat gDegreesRotated = 0.0f;
-Light gLight;
+std::vector<Light> gLights;
// returns the full path to the file `fileName` in the resources directory of the app bundle
@@ -262,6 +263,14 @@ static void CreateInstances() {
gInstances.push_back(hMid);
}
+template <typename T>
+void SetLightUniform(tdogl::Program* shaders, const char* propertyName, size_t lightIndex, const T& value) {
+ std::ostringstream ss;
+ ss << "allLights[" << lightIndex << "]." << propertyName;
+ std::string uniformName = ss.str();
+
+ shaders->setUniform(uniformName.c_str(), value);
+}
//renders a single `ModelInstance`
static void RenderInstance(const ModelInstance& inst) {
@@ -277,14 +286,17 @@ static void RenderInstance(const ModelInstance& inst) {
shaders->setUniform("material.tex", 0); //set to 0 because the texture will be bound to GL_TEXTURE0
shaders->setUniform("material.shininess", asset->shininess);
shaders->setUniform("material.specularColor", asset->specularColor);
- shaders->setUniform("numLights", 1);
- shaders->setUniform("lights[0].position", gLight.position);
- shaders->setUniform("lights[0].intensities", gLight.intensities);
- shaders->setUniform("lights[0].attenuation", gLight.attenuation);
- shaders->setUniform("lights[0].ambientCoefficient", gLight.ambientCoefficient);
- shaders->setUniform("lights[0].coneAngle", gLight.coneAngle);
- shaders->setUniform("lights[0].coneDirection", gLight.coneDirection);
shaders->setUniform("cameraPosition", gCamera.position());
+ shaders->setUniform("numLights", (int)gLights.size());
+
+ for(size_t i = 0; i < gLights.size(); ++i){
+ SetLightUniform(shaders, "position", i, gLights[i].position);
+ SetLightUniform(shaders, "intensities", i, gLights[i].intensities);
+ SetLightUniform(shaders, "attenuation", i, gLights[i].attenuation);
+ SetLightUniform(shaders, "ambientCoefficient", i, gLights[i].ambientCoefficient);
+ SetLightUniform(shaders, "coneAngle", i, gLights[i].coneAngle);
+ SetLightUniform(shaders, "coneDirection", i, gLights[i].coneDirection);
+ }
//bind the texture
glActiveTexture(GL_TEXTURE0);
@@ -346,17 +358,17 @@ static void Update(float secondsElapsed) {
//move light
if(glfwGetKey('1')){
- gLight.position = glm::vec4(gCamera.position(), 1.0);
- gLight.coneDirection = gCamera.forward();
+ gLights[0].position = glm::vec4(gCamera.position(), 1.0);
+ gLights[0].coneDirection = gCamera.forward();
}
// change light color
if(glfwGetKey('2'))
- gLight.intensities = glm::vec3(1,0,0); //red
+ gLights[0].intensities = glm::vec3(2,0,0); //red
else if(glfwGetKey('3'))
- gLight.intensities = glm::vec3(0,1,0); //green
+ gLights[0].intensities = glm::vec3(0,2,0); //green
else if(glfwGetKey('4'))
- gLight.intensities = glm::vec3(1,1,1); //white
+ gLights[0].intensities = glm::vec3(2,2,2); //white
//rotate camera based on mouse movement
@@ -427,13 +439,23 @@ void AppMain() {
gCamera.setViewportAspectRatio(SCREEN_SIZE.x / SCREEN_SIZE.y);
gCamera.setNearAndFarPlanes(0.5f, 100.0f);
- // setup gLight
- gLight.position = glm::vec4(-4,0,17,1);
- gLight.intensities = glm::vec3(1,1,1); //white
- gLight.attenuation = 0.1f;
- gLight.ambientCoefficient = 0.005f;
- gLight.coneAngle = 30.0f;
- gLight.coneDirection = glm::vec3(0,0,-1);
+ // setup lights
+ Light spotlight;
+ spotlight.position = glm::vec4(-4,0,10,1);
+ spotlight.intensities = glm::vec3(2,2,2); //strong white light
+ spotlight.attenuation = 0.1f;
+ spotlight.ambientCoefficient = 0.0f; //no ambient light
+ spotlight.coneAngle = 30.0f;
+ spotlight.coneDirection = glm::vec3(0,0,-1);
+
+ Light directionalLight;
+ directionalLight.position = glm::vec4(1, 0.8, 0.6, 0); //w == 0 indications a directional light
+ directionalLight.intensities = glm::vec3(0.4,0.3,0.1); //weak yellowish light
+ directionalLight.ambientCoefficient = 0.06;
+
+ gLights.push_back(spotlight);
+ gLights.push_back(directionalLight);
+
// run while the window is open
double lastTime = glfwGetTime();

0 comments on commit b2e9fcc

Please sign in to comment.