Added diffuse, ambient and specular lighting to line and point shaders.

This commit is contained in:
codeanticode
2011-12-07 01:07:43 +00:00
parent baa3ab9111
commit 1201e9072c
6 changed files with 318 additions and 75 deletions

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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();
}

View File

@@ -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;
}

View File

@@ -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;
}