From 1201e9072c4a6ca4ed0dc5f2d696b2f986a9be46 Mon Sep 17 00:00:00 2001 From: codeanticode Date: Wed, 7 Dec 2011 01:07:43 +0000 Subject: [PATCH] Added diffuse, ambient and specular lighting to line and point shaders. --- .../src/processing/opengl/LineShaderFrag.glsl | 21 +++ .../src/processing/opengl/LineShaderVert.glsl | 86 +++++++++- .../processing/opengl/PGraphicsOpenGL.java | 158 ++++++++++++------ .../src/processing/opengl/PShape3D.java | 30 +--- .../processing/opengl/PointShaderFrag.glsl | 21 +++ .../processing/opengl/PointShaderVert.glsl | 77 ++++++++- 6 files changed, 318 insertions(+), 75 deletions(-) diff --git a/java/libraries/opengl/src/processing/opengl/LineShaderFrag.glsl b/java/libraries/opengl/src/processing/opengl/LineShaderFrag.glsl index 629b157b9..cd5c944f9 100644 --- a/java/libraries/opengl/src/processing/opengl/LineShaderFrag.glsl +++ b/java/libraries/opengl/src/processing/opengl/LineShaderFrag.glsl @@ -1,3 +1,24 @@ +/* + Part of the Processing project - http://processing.org + + Copyright (c) 2011 Andres Colubri + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA +*/ + void main() { gl_FragColor = gl_Color; } \ No newline at end of file diff --git a/java/libraries/opengl/src/processing/opengl/LineShaderVert.glsl b/java/libraries/opengl/src/processing/opengl/LineShaderVert.glsl index f09c35f7b..20b8ec026 100644 --- a/java/libraries/opengl/src/processing/opengl/LineShaderVert.glsl +++ b/java/libraries/opengl/src/processing/opengl/LineShaderVert.glsl @@ -1,20 +1,92 @@ +/* + Part of the Processing project - http://processing.org + + Copyright (c) 2011 Andres Colubri + Based on glsl code from the dpix library: + http://gfx.cs.princeton.edu/proj/dpix/ + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA +*/ + attribute vec4 attribs; uniform vec4 viewport; +uniform vec4 eye; +uniform int lights; + vec3 clipToWindow(vec4 clip, vec4 viewport) { vec3 post_div = clip.xyz / clip.w; vec2 xypos = (post_div.xy + vec2(1.0, 1.0)) * 0.5 * viewport.zw; return vec3(xypos, post_div.z * 0.5 + 0.5); } +// From the "Directional Lights I & II" tutorials from lighthouse 3D: +// http://www.lighthouse3d.com/tutorials/glsl-tutorial/directional-lights-i/ +vec4 calculateLight(int i) { + // Per-vertex diffuse and ambient lighting. + vec3 normal, lightDir; + vec4 diffuse, ambient, specular; + float NdotL, NdotHV; + + // first transform the normal into eye space and normalize the result. + normal = normalize(gl_NormalMatrix * gl_Normal); + + // now normalize the light's direction. Note that according to the + // OpenGL specification, the light is stored in eye space. Also since + // we're talking about a directional light, the position field is actually + // direction + lightDir = normalize(vec3(gl_LightSource[i].position)); + + // compute the cos of the angle between the normal and lights direction. + // The light is directional so the direction is constant for every vertex. + // Since these two are normalized the cosine is the dot product. We also + // need to clamp the result to the [0,1] range. + NdotL = max(dot(normal, lightDir), 0.0); + + // Compute the diffuse term. Ambient and diffuse material components + // are stored in the vertex color, since processing uses GL_COLOR_MATERIAL + diffuse = gl_Color * gl_LightSource[i].diffuse; + + // Compute the ambient and globalAmbient terms + ambient = gl_Color * gl_LightSource[i].ambient; + + // compute the specular term if NdotL is larger than zero + if (NdotL > 0.0) { + // normalize the half-vector, and then compute the + // cosine (dot product) with the normal + NdotHV = max(dot(normal, gl_LightSource[i].halfVector.xyz), 0.0); + specular = gl_FrontMaterial.specular * gl_LightSource[i].specular * pow(NdotHV, gl_FrontMaterial.shininess); + } + + return NdotL * diffuse + ambient + specular; +} + void main() { vec4 pos_p = gl_Vertex; vec4 pos_q = vec4(attribs.xyz, 1); vec4 v_p = gl_ModelViewMatrix * pos_p; - v_p.xyz = v_p.xyz * 0.99; vec4 clip_p = gl_ProjectionMatrix * v_p; vec4 v_q = gl_ModelViewMatrix * pos_q; + + // Moving vertices slightly toward the camera + // to avoid depth-fighting with the polys. + // Discussed here: + // http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&Number=252848 + v_p.xyz = v_p.xyz * 0.99; v_q.xyz = v_q.xyz * 0.99; vec4 clip_q = gl_ProjectionMatrix * v_q; @@ -29,5 +101,15 @@ void main() { gl_Position.xy = clip_p.xy + window_offset.xy; gl_Position.zw = clip_p.zw; - gl_FrontColor = gl_Color; + + gl_FrontColor = vec4(0, 0, 0, 0); + vec4 globalAmbient = gl_Color * gl_LightModel.ambient; + if (lights == 0) { + gl_FrontColor = gl_Color; + } + for (int i = 0; i < lights; i++) { + vec4 light = calculateLight(i); + gl_FrontColor += light; + } + gl_FrontColor += globalAmbient; } \ No newline at end of file diff --git a/java/libraries/opengl/src/processing/opengl/PGraphicsOpenGL.java b/java/libraries/opengl/src/processing/opengl/PGraphicsOpenGL.java index 02a9311c8..299716485 100644 --- a/java/libraries/opengl/src/processing/opengl/PGraphicsOpenGL.java +++ b/java/libraries/opengl/src/processing/opengl/PGraphicsOpenGL.java @@ -179,7 +179,7 @@ public class PGraphicsOpenGL extends PGraphics { /** Camera field of view. */ public float cameraFOV; - /** Position of the camera. */ + /** Default position of the camera. */ public float cameraX, cameraY, cameraZ; /** Distance of the near and far planes. */ public float cameraNear, cameraFar; @@ -189,8 +189,8 @@ public class PGraphicsOpenGL extends PGraphics { /** Distance between the camera eye and and aim point. */ protected float cameraDepth; - protected float cameraAxisX, cameraAxisY, cameraAxisZ; - protected float cameraCenterX, cameraCenterY, cameraCenterZ; + /** Actual position of the camera. */ + protected float cameraEyeX, cameraEyeY, cameraEyeZ; /** Flag to indicate that we are inside beginCamera/endCamera block. */ protected boolean manipulatingCamera; @@ -385,7 +385,7 @@ public class PGraphicsOpenGL extends PGraphics { protected boolean resized = false; /** Stores previous viewport dimensions. */ - protected int[] viewport = {0, 0, 0, 0}; + protected int[] savedViewport = {0, 0, 0, 0}; // ........................................................ @@ -462,6 +462,8 @@ public class PGraphicsOpenGL extends PGraphics { static protected PShader lineShader; static protected PShader pointShader; + static protected int lineAttribsID; + static protected int pointAttribsID; protected boolean drawing2D; protected PImage textureImage0; @@ -1116,20 +1118,6 @@ public class PGraphicsOpenGL extends PGraphics { defaultSettings(); } - if (lineShader == null) { - lineShader = new PShader(parent); - lineShader.loadVertexShader(PGraphicsOpenGL.class.getResource("LineShaderVert.glsl")); - lineShader.loadFragmentShader(PGraphicsOpenGL.class.getResource("LineShaderFrag.glsl")); - lineShader.setup(); - } - - if (pointShader == null) { - pointShader = new PShader(parent); - pointShader.loadVertexShader(PGraphicsOpenGL.class.getResource("PointShaderVert.glsl")); - pointShader.loadFragmentShader(PGraphicsOpenGL.class.getResource("PointShaderFrag.glsl")); - pointShader.setup(); - } - // We are ready to go! report("top beginDraw()"); @@ -1168,7 +1156,7 @@ public class PGraphicsOpenGL extends PGraphics { } // setup opengl viewport. - gl.glGetIntegerv(GL.GL_VIEWPORT, viewport, 0); + gl.glGetIntegerv(GL.GL_VIEWPORT, savedViewport, 0); gl.glViewport(0, 0, width, height); if (resized) { // To avoid having garbage in the screen after a resize, @@ -1259,7 +1247,7 @@ public class PGraphicsOpenGL extends PGraphics { } // Restoring previous viewport. - gl.glViewport(viewport[0], viewport[1], viewport[2], viewport[3]); + gl.glViewport(savedViewport[0], savedViewport[1], savedViewport[2], savedViewport[3]); if (primarySurface) { // glFlush should be called only once, since it is an expensive @@ -1837,7 +1825,7 @@ public class PGraphicsOpenGL extends PGraphics { protected void renderPoints() { checkVertexBuffers(tess.pointVertexCount); - pointShader.start(); + startPointShader(); vertexBuffer.rewind(); vertexBuffer.put(tess.pointVertices, 0, 3 * tess.pointVertexCount); @@ -1859,26 +1847,21 @@ public class PGraphicsOpenGL extends PGraphics { gl2f.glColorPointer(4, GL.GL_FLOAT, 0, colorBuffer); gl2f.glNormalPointer(GL.GL_FLOAT, 0, normalBuffer); - int attribsID = pointShader.getAttribLocation("vertDisp"); - gl2x.glEnableVertexAttribArray(attribsID); - gl2x.glVertexAttribPointer(attribsID, 2, GL.GL_FLOAT, false, 0, FloatBuffer.wrap(tess.pointAttributes)); - + setupPointShader(tess.pointAttributes); + gl2f.glDrawElements(GL.GL_TRIANGLES, tess.pointIndexCount, GL.GL_UNSIGNED_INT, IntBuffer.wrap(tess.pointIndices)); - gl2x.glDisableVertexAttribArray(attribsID); - gl2f.glDisableClientState(GL2.GL_VERTEX_ARRAY); gl2f.glDisableClientState(GL2.GL_COLOR_ARRAY); gl2f.glDisableClientState(GL2.GL_NORMAL_ARRAY); - pointShader.stop(); + stopPointShader(); } - - + protected void renderLines() { checkVertexBuffers(tess.lineVertexCount); - lineShader.start(); + startLineShader(); vertexBuffer.rewind(); vertexBuffer.put(tess.lineVertices, 0, 3 * tess.lineVertexCount); @@ -1900,23 +1883,15 @@ public class PGraphicsOpenGL extends PGraphics { gl2f.glColorPointer(4, GL.GL_FLOAT, 0, colorBuffer); gl2f.glNormalPointer(GL.GL_FLOAT, 0, normalBuffer); - int[] viewport = {0, 0, 0, 0}; - gl2f.glGetIntegerv(GL.GL_VIEWPORT, viewport, 0); - lineShader.setVecUniform("viewport", viewport[0], viewport[1], viewport[2], viewport[3]); - - int attribsID = lineShader.getAttribLocation("attribs"); - gl2x.glEnableVertexAttribArray(attribsID); - gl2x.glVertexAttribPointer(attribsID, 4, GL.GL_FLOAT, false, 0, FloatBuffer.wrap(tess.lineAttributes)); + setupLineShader(tess.lineAttributes); gl2f.glDrawElements(GL.GL_TRIANGLES, tess.lineIndexCount, GL.GL_UNSIGNED_INT, IntBuffer.wrap(tess.lineIndices)); - gl2x.glDisableVertexAttribArray(attribsID); - gl2f.glDisableClientState(GL2.GL_VERTEX_ARRAY); gl2f.glDisableClientState(GL2.GL_COLOR_ARRAY); gl2f.glDisableClientState(GL2.GL_NORMAL_ARRAY); - lineShader.stop(); + stopLineShader(); } @@ -2080,6 +2055,95 @@ public class PGraphicsOpenGL extends PGraphics { } } + + protected void startLineShader() { + if (lineShader == null) { + lineShader = new PShader(parent); + lineShader.loadVertexShader(PGraphicsOpenGL.class.getResource("LineShaderVert.glsl")); + lineShader.loadFragmentShader(PGraphicsOpenGL.class.getResource("LineShaderFrag.glsl")); + lineShader.setup(); + } + + lineShader.start(); + } + + + protected void setupLineShader(float[] attribs) { + int[] viewport = {0, 0, 0, 0}; + gl2f.glGetIntegerv(GL.GL_VIEWPORT, viewport, 0); + lineShader.setVecUniform("viewport", viewport[0], viewport[1], viewport[2], viewport[3]); + + lineShader.setIntUniform("lights", lightCount); + + lineShader.setVecUniform("eye", cameraEyeX, cameraEyeY, cameraEyeZ, 0); + + lineAttribsID = lineShader.getAttribLocation("attribs"); + gl2x.glEnableVertexAttribArray(lineAttribsID); + gl2x.glVertexAttribPointer(lineAttribsID, 4, GL.GL_FLOAT, false, 0, FloatBuffer.wrap(tess.lineAttributes)); + } + + + protected void setupLineShader(int attrBufID) { + int[] viewport = {0, 0, 0, 0}; + gl2f.glGetIntegerv(GL.GL_VIEWPORT, viewport, 0); + lineShader.setVecUniform("viewport", viewport[0], viewport[1], viewport[2], viewport[3]); + + lineShader.setIntUniform("lights", lightCount); + + lineShader.setVecUniform("eye", cameraEyeX, cameraEyeY, cameraEyeZ, 0); + + lineAttribsID = lineShader.getAttribLocation("attribs"); + gl2x.glEnableVertexAttribArray(lineAttribsID); + gl2f.glBindBuffer(GL.GL_ARRAY_BUFFER, attrBufID); + gl2x.glVertexAttribPointer(lineAttribsID, 4, GL.GL_FLOAT, false, 0, 0); + } + + + protected void stopLineShader() { + gl2x.glDisableVertexAttribArray(lineAttribsID); + lineShader.stop(); + } + + + protected void startPointShader() { + if (pointShader == null) { + pointShader = new PShader(parent); + pointShader.loadVertexShader(PGraphicsOpenGL.class.getResource("PointShaderVert.glsl")); + pointShader.loadFragmentShader(PGraphicsOpenGL.class.getResource("PointShaderFrag.glsl")); + pointShader.setup(); + } + + pointShader.start(); + } + + + protected void setupPointShader(float[] attribs) { + pointShader.setIntUniform("lights", lightCount); + + pointShader.setVecUniform("eye", cameraEyeX, cameraEyeY, cameraEyeZ, 0); + + pointAttribsID = pointShader.getAttribLocation("vertDisp"); + gl2x.glEnableVertexAttribArray(pointAttribsID); + gl2x.glVertexAttribPointer(pointAttribsID, 2, GL.GL_FLOAT, false, 0, FloatBuffer.wrap(attribs)); + } + + + protected void setupPointShader(int attrBufID) { + pointShader.setIntUniform("lights", lightCount); + + pointShader.setVecUniform("eye", cameraEyeX, cameraEyeY, cameraEyeZ, 0); + + pointAttribsID = PGraphicsOpenGL.pointShader.getAttribLocation("vertDisp"); + gl2x.glEnableVertexAttribArray(pointAttribsID); + gl2f.glBindBuffer(GL.GL_ARRAY_BUFFER, attrBufID); + ogl.gl2x.glVertexAttribPointer(pointAttribsID, 2, GL.GL_FLOAT, false, 0, 0); + } + + + protected void stopPointShader() { + gl2x.glDisableVertexAttribArray(pointAttribsID); + pointShader.stop(); + } ////////////////////////////////////////////////////////////// @@ -3437,17 +3501,11 @@ public class PGraphicsOpenGL extends PGraphics { z1 /= mag; z2 /= mag; } + cameraEyeX = eyeX; + cameraEyeY = eyeY; + cameraEyeZ = eyeZ; cameraDepth = mag; - // This information is used to determine if input points - // are contained in the camera plane. - cameraAxisX = z0; - cameraAxisY = z1; - cameraAxisZ = z2; - cameraCenterX = centerX; - cameraCenterY = centerY; - cameraCenterZ = centerZ; - // Calculating Y vector float y0 = upX; float y1 = upY; diff --git a/java/libraries/opengl/src/processing/opengl/PShape3D.java b/java/libraries/opengl/src/processing/opengl/PShape3D.java index 5bcaa28f6..6511832e6 100644 --- a/java/libraries/opengl/src/processing/opengl/PShape3D.java +++ b/java/libraries/opengl/src/processing/opengl/PShape3D.java @@ -1517,7 +1517,7 @@ public class PShape3D extends PShape { protected void renderPoints() { - PGraphicsOpenGL.pointShader.start(); + ogl.startPointShader(); getGl().glEnableClientState(GL2.GL_NORMAL_ARRAY); getGl().glBindBuffer(GL.GL_ARRAY_BUFFER, root.glPointNormalBufferID); @@ -1530,18 +1530,13 @@ public class PShape3D extends PShape { getGl().glEnableClientState(GL2.GL_VERTEX_ARRAY); getGl().glBindBuffer(GL.GL_ARRAY_BUFFER, root.glPointVertexBufferID); getGl().glVertexPointer(3, GL.GL_FLOAT, 0, 0); - - int attribsID = PGraphicsOpenGL.pointShader.getAttribLocation("vertDisp"); - ogl.gl2x.glEnableVertexAttribArray(attribsID); - getGl().glBindBuffer(GL.GL_ARRAY_BUFFER, root.glPointAttribBufferID); - ogl.gl2x.glVertexAttribPointer(attribsID, 2, GL.GL_FLOAT, false, 0, 0); + + ogl.setupPointShader(root.glPointAttribBufferID); getGl().glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, root.glPointIndexBufferID); getGl().glDrawElements(GL.GL_TRIANGLES, tess.lastPointIndex - tess.firstPointIndex + 1, GL.GL_UNSIGNED_INT, tess.firstPointIndex * PGraphicsOpenGL.SIZEOF_INT); - - ogl.gl2x.glDisableVertexAttribArray(attribsID); - + getGl().glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, 0); getGl().glBindBuffer(GL.GL_ARRAY_BUFFER, 0); @@ -1549,12 +1544,12 @@ public class PShape3D extends PShape { getGl().glDisableClientState(GL2.GL_COLOR_ARRAY); getGl().glDisableClientState(GL2.GL_NORMAL_ARRAY); - PGraphicsOpenGL.pointShader.stop(); + ogl.stopPointShader(); } protected void renderLines() { - PGraphicsOpenGL.lineShader.start(); + ogl.startLineShader(); getGl().glEnableClientState(GL2.GL_NORMAL_ARRAY); getGl().glBindBuffer(GL.GL_ARRAY_BUFFER, root.glLineNormalBufferID); @@ -1568,21 +1563,12 @@ public class PShape3D extends PShape { getGl().glBindBuffer(GL.GL_ARRAY_BUFFER, root.glLineVertexBufferID); getGl().glVertexPointer(3, GL.GL_FLOAT, 0, 0); - int[] viewport = {0, 0, 0, 0}; - getGl().glGetIntegerv(GL.GL_VIEWPORT, viewport, 0); - PGraphicsOpenGL.lineShader.setVecUniform("viewport", viewport[0], viewport[1], viewport[2], viewport[3]); - - int attribsID = PGraphicsOpenGL.lineShader.getAttribLocation("attribs"); - ogl.gl2x.glEnableVertexAttribArray(attribsID); - getGl().glBindBuffer(GL.GL_ARRAY_BUFFER, root.glLineAttribBufferID); - ogl.gl2x.glVertexAttribPointer(attribsID, 4, GL.GL_FLOAT, false, 0, 0); + ogl.setupLineShader(root.glLineAttribBufferID); getGl().glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, root.glLineIndexBufferID); getGl().glDrawElements(GL.GL_TRIANGLES, tess.lastLineIndex - tess.firstLineIndex + 1, GL.GL_UNSIGNED_INT, tess.firstLineIndex * PGraphicsOpenGL.SIZEOF_INT); - ogl.gl2x.glDisableVertexAttribArray(attribsID); - getGl().glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, 0); getGl().glBindBuffer(GL.GL_ARRAY_BUFFER, 0); @@ -1590,7 +1576,7 @@ public class PShape3D extends PShape { getGl().glDisableClientState(GL2.GL_COLOR_ARRAY); getGl().glDisableClientState(GL2.GL_NORMAL_ARRAY); - PGraphicsOpenGL.lineShader.stop(); + ogl.stopLineShader(); } diff --git a/java/libraries/opengl/src/processing/opengl/PointShaderFrag.glsl b/java/libraries/opengl/src/processing/opengl/PointShaderFrag.glsl index 1af85c00f..d360bba1a 100644 --- a/java/libraries/opengl/src/processing/opengl/PointShaderFrag.glsl +++ b/java/libraries/opengl/src/processing/opengl/PointShaderFrag.glsl @@ -1,3 +1,24 @@ +/* + Part of the Processing project - http://processing.org + + Copyright (c) 2011 Andres Colubri + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA +*/ + void main() { gl_FragColor = gl_Color; } \ No newline at end of file diff --git a/java/libraries/opengl/src/processing/opengl/PointShaderVert.glsl b/java/libraries/opengl/src/processing/opengl/PointShaderVert.glsl index a98ed5281..5eeebb2a5 100644 --- a/java/libraries/opengl/src/processing/opengl/PointShaderVert.glsl +++ b/java/libraries/opengl/src/processing/opengl/PointShaderVert.glsl @@ -1,8 +1,83 @@ +/* + Part of the Processing project - http://processing.org + + Copyright (c) 2011 Andres Colubri + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA +*/ + attribute vec2 vertDisp; +uniform vec4 eye; +uniform int lights; + +// From the "Directional Lights I & II" tutorials from lighthouse 3D: +// http://www.lighthouse3d.com/tutorials/glsl-tutorial/directional-lights-i/ +vec4 calculateLight(int i) { + // Per-vertex diffuse and ambient lighting. + vec3 normal, lightDir; + vec4 diffuse, ambient, specular; + float NdotL, NdotHV; + + // first transform the normal into eye space and normalize the result. + normal = normalize(gl_NormalMatrix * gl_Normal); + + // now normalize the light's direction. Note that according to the + // OpenGL specification, the light is stored in eye space. Also since + // we're talking about a directional light, the position field is actually + // direction + lightDir = normalize(vec3(gl_LightSource[i].position)); + + // compute the cos of the angle between the normal and lights direction. + // The light is directional so the direction is constant for every vertex. + // Since these two are normalized the cosine is the dot product. We also + // need to clamp the result to the [0,1] range. + NdotL = max(dot(normal, lightDir), 0.0); + + // Compute the diffuse term. Ambient and diffuse material components + // are stored in the vertex color, since processing uses GL_COLOR_MATERIAL + diffuse = gl_Color * gl_LightSource[i].diffuse; + + // Compute the ambient and globalAmbient terms + ambient = gl_Color * gl_LightSource[i].ambient; + + // compute the specular term if NdotL is larger than zero + if (NdotL > 0.0) { + // normalize the half-vector, and then compute the + // cosine (dot product) with the normal + NdotHV = max(dot(normal, gl_LightSource[i].halfVector.xyz), 0.0); + specular = gl_FrontMaterial.specular * gl_LightSource[i].specular * pow(NdotHV, gl_FrontMaterial.shininess); + } + + return NdotL * diffuse + ambient + specular; +} + void main() { vec4 pos = gl_ModelViewMatrix * gl_Vertex; pos.xy += vertDisp.xy; gl_Position = gl_ProjectionMatrix * pos; - gl_FrontColor = gl_Color; + + gl_FrontColor = vec4(0, 0, 0, 0); + vec4 globalAmbient = gl_Color * gl_LightModel.ambient; + if (lights == 0) { + gl_FrontColor = gl_Color; + } + for (int i = 0; i < lights; i++) { + vec4 light = calculateLight(i); + gl_FrontColor += light; + } + gl_FrontColor += globalAmbient; } \ No newline at end of file