[gtkglext] Add gears example using GLSL programs



commit 07d607cd3bb2e85e614709ba4c90cf5ebd487c3e
Author: Mukund Sivaraman <muks banu com>
Date:   Fri Oct 2 11:20:14 2009 +0530

    Add gears example using GLSL programs

 examples/glsl/gears.c    |  614 ++++++++++++++++++++++++++++++++++++++++++++++
 examples/glsl/shiny.fsh  |   33 +++
 examples/glsl/shiny.vsh  |   22 ++
 examples/glsl/velvet.fsh |   53 ++++
 examples/glsl/velvet.vsh |   21 ++
 5 files changed, 743 insertions(+), 0 deletions(-)
---
diff --git a/examples/glsl/gears.c b/examples/glsl/gears.c
new file mode 100644
index 0000000..9bd82a8
--- /dev/null
+++ b/examples/glsl/gears.c
@@ -0,0 +1,614 @@
+/*
+ * 3-D gear wheels.  This program is in the public domain.
+ *
+ * Brian Paul
+ */
+
+/* Conversion to GLUT by Mark J. Kilgard */
+
+/* Conversion to GtkGLExt by Naofumi Yasufuku */
+
+/* Shader code by Mukund Sivaraman, adapted from Michael Brooks's Ruby
+   code also released into public-domain. */
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
+
+#include <gtk/gtkgl.h>
+#include <gdk/gdkglglext.h>
+
+#ifdef G_OS_WIN32
+#define WIN32_LEAN_AND_MEAN 1
+#include <windows.h>
+#endif
+
+#include <GL/gl.h>
+#include <GL/glu.h>
+
+/*
+ * Draw a gear wheel.  You'll probably want to call this function when
+ * building a display list since we do a lot of trig here.
+ *
+ * Input:  inner_radius - radius of hole at center
+ * outer_radius - radius at center of teeth
+ * width - width of gear
+ * teeth - number of teeth
+ * tooth_depth - depth of tooth
+ */
+
+static void
+gear(GLfloat inner_radius,
+     GLfloat outer_radius,
+     GLfloat width,
+     GLint   teeth,
+     GLfloat tooth_depth)
+{
+  GLint i;
+  GLfloat r0, r1, r2;
+  GLfloat angle, da;
+  GLfloat u, v, len;
+
+  r0 = inner_radius;
+  r1 = outer_radius - tooth_depth / 2.0;
+  r2 = outer_radius + tooth_depth / 2.0;
+
+  da = 2.0 * G_PI / teeth / 4.0;
+
+  glShadeModel(GL_FLAT);
+
+  glNormal3f(0.0, 0.0, 1.0);
+
+  /* draw front face */
+  glBegin(GL_QUAD_STRIP);
+  for (i = 0; i <= teeth; i++) {
+    angle = i * 2.0 * G_PI / teeth;
+    glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
+    glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
+    if (i < teeth) {
+      glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
+      glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5);
+    }
+  }
+  glEnd();
+
+  /* draw front sides of teeth */
+  glBegin(GL_QUADS);
+  da = 2.0 * G_PI / teeth / 4.0;
+  for (i = 0; i < teeth; i++) {
+    angle = i * 2.0 * G_PI / teeth;
+
+    glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
+    glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
+    glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), width * 0.5);
+    glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5);
+  }
+  glEnd();
+
+  glNormal3f(0.0, 0.0, -1.0);
+
+  /* draw back face */
+  glBegin(GL_QUAD_STRIP);
+  for (i = 0; i <= teeth; i++) {
+    angle = i * 2.0 * G_PI / teeth;
+    glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
+    glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
+    if (i < teeth) {
+      glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5);
+      glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
+    }
+  }
+  glEnd();
+
+  /* draw back sides of teeth */
+  glBegin(GL_QUADS);
+  da = 2.0 * G_PI / teeth / 4.0;
+  for (i = 0; i < teeth; i++) {
+    angle = i * 2.0 * G_PI / teeth;
+
+    glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5);
+    glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), -width * 0.5);
+    glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
+    glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
+  }
+  glEnd();
+
+  /* draw outward faces of teeth */
+  glBegin(GL_QUAD_STRIP);
+  for (i = 0; i < teeth; i++) {
+    angle = i * 2.0 * G_PI / teeth;
+
+    glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
+    glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
+    u = r2 * cos(angle + da) - r1 * cos(angle);
+    v = r2 * sin(angle + da) - r1 * sin(angle);
+    len = sqrt(u * u + v * v);
+    u /= len;
+    v /= len;
+    glNormal3f(v, -u, 0.0);
+    glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
+    glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
+    glNormal3f(cos(angle), sin(angle), 0.0);
+    glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), width * 0.5);
+    glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), -width * 0.5);
+    u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da);
+    v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da);
+    glNormal3f(v, -u, 0.0);
+    glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5);
+    glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5);
+    glNormal3f(cos(angle), sin(angle), 0.0);
+  }
+
+  glVertex3f(r1 * cos(0), r1 * sin(0), width * 0.5);
+  glVertex3f(r1 * cos(0), r1 * sin(0), -width * 0.5);
+
+  glEnd();
+
+  glShadeModel(GL_SMOOTH);
+
+  /* draw inside radius cylinder */
+  glBegin(GL_QUAD_STRIP);
+  for (i = 0; i <= teeth; i++) {
+    angle = i * 2.0 * G_PI / teeth;
+    glNormal3f(-cos(angle), -sin(angle), 0.0);
+    glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
+    glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
+  }
+  glEnd();
+
+}
+
+static GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0;
+static GLint gear1, gear2, gear3;
+static GLfloat angle = 0.0;
+
+static GTimer *timer = NULL;
+
+static gboolean is_sync = TRUE;
+
+static GLuint program1;
+static GLuint program2;
+
+static gboolean
+draw (GtkWidget      *widget,
+      GdkEventExpose *event,
+      gpointer        data)
+{
+  GdkGLContext *glcontext = gtk_widget_get_gl_context (widget);
+  GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable (widget);
+
+  /*** OpenGL BEGIN ***/
+  if (!gdk_gl_drawable_gl_begin (gldrawable, glcontext))
+    return FALSE;
+
+  glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+  glPushMatrix ();
+    glRotatef (view_rotx, 1.0, 0.0, 0.0);
+    glRotatef (view_roty, 0.0, 1.0, 0.0);
+    glRotatef (view_rotz, 0.0, 0.0, 1.0);
+
+    gdk_gl_glUseProgram (gdk_gl_get_glUseProgram (), program1);
+
+    glPushMatrix ();
+      glTranslatef (-3.0, -2.0, 0.0);
+      glRotatef (angle, 0.0, 0.0, 1.0);
+      glCallList (gear1);
+    glPopMatrix ();
+
+    gdk_gl_glUseProgram (gdk_gl_get_glUseProgram (), program2);
+
+    glPushMatrix ();
+      glTranslatef (3.1, -2.0, 0.0);
+      glRotatef (-2.0 * angle - 9.0, 0.0, 0.0, 1.0);
+      glCallList (gear2);
+    glPopMatrix ();
+
+    glPushMatrix ();
+      glTranslatef (-3.1, 4.2, 0.0);
+      glRotatef (-2.0 * angle - 25.0, 0.0, 0.0, 1.0);
+      glCallList (gear3);
+    glPopMatrix ();
+
+  glPopMatrix ();
+
+  if (gdk_gl_drawable_is_double_buffered (gldrawable))
+    gdk_gl_drawable_swap_buffers (gldrawable);
+  else
+    glFlush ();
+
+  gdk_gl_drawable_gl_end (gldrawable);
+  /*** OpenGL END ***/
+
+  return TRUE;
+}
+
+/* new window size or exposure */
+static gboolean
+reshape (GtkWidget         *widget,
+	 GdkEventConfigure *event,
+	 gpointer           data)
+{
+  GdkGLContext *glcontext = gtk_widget_get_gl_context (widget);
+  GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable (widget);
+
+  GLfloat h = (GLfloat) (widget->allocation.height) / (GLfloat) (widget->allocation.width);
+
+  /*** OpenGL BEGIN ***/
+  if (!gdk_gl_drawable_gl_begin (gldrawable, glcontext))
+    return FALSE;
+
+  glViewport (0, 0, widget->allocation.width, widget->allocation.height);
+  glMatrixMode (GL_PROJECTION);
+  glLoadIdentity ();
+  glFrustum (-1.0, 1.0, -h, h, 5.0, 60.0);
+  glMatrixMode (GL_MODELVIEW);
+  glLoadIdentity ();
+  glTranslatef (0.0, 0.0, -40.0);
+
+  gdk_gl_drawable_gl_end (gldrawable);
+  /*** OpenGL END ***/
+
+  return TRUE;
+}
+
+static GLuint
+create_shader_program (const char *name)
+{
+  GLuint program;
+  GLuint vshader, fshader;
+  char *filename;
+  char *contents;
+  const GLchar *sources[1];
+
+  program = gdk_gl_glCreateProgram (gdk_gl_get_glCreateProgram ());
+
+
+  vshader = gdk_gl_glCreateShader (gdk_gl_get_glCreateShader (),
+                                   GL_VERTEX_SHADER);
+  filename = g_strdup_printf ("%s.vsh", name);
+  g_file_get_contents (filename, &contents, NULL, NULL);
+  sources[0] = contents;
+  gdk_gl_glShaderSource (gdk_gl_get_glShaderSource (),
+                         vshader, 1, sources, NULL);
+  g_free (contents);
+  g_free (filename);
+  gdk_gl_glCompileShader (gdk_gl_get_glCompileShader (), vshader);
+  gdk_gl_glAttachShader (gdk_gl_get_glAttachShader (), program, vshader);
+
+
+  fshader = gdk_gl_glCreateShader (gdk_gl_get_glCreateShader (),
+                                   GL_FRAGMENT_SHADER);
+  filename = g_strdup_printf ("%s.fsh", name);
+  g_file_get_contents (filename, &contents, NULL, NULL);
+  sources[0] = contents;
+  gdk_gl_glShaderSource (gdk_gl_get_glShaderSource (),
+                         fshader, 1, sources, NULL);
+  g_free (contents);
+  g_free (filename);
+  gdk_gl_glCompileShader (gdk_gl_get_glCompileShader (), fshader);
+  gdk_gl_glAttachShader (gdk_gl_get_glAttachShader (), program, fshader);
+
+  gdk_gl_glLinkProgram (gdk_gl_get_glLinkProgram (), program);
+
+  gdk_gl_glDeleteShader (gdk_gl_get_glDeleteShader (), vshader);
+  gdk_gl_glDeleteShader (gdk_gl_get_glDeleteShader (), fshader);
+
+  return program;
+}
+
+static void
+init(GtkWidget *widget,
+     gpointer   data)
+{
+  GdkGLContext *glcontext = gtk_widget_get_gl_context (widget);
+  GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable (widget);
+
+  static GLfloat pos[4] = {100.0, 0.0, 0.0, 1.0};
+  static GLfloat red[4] = {0.8, 0.1, 0.0, 1.0};
+  static GLfloat green[4] = {0.0, 0.8, 0.2, 1.0};
+  static GLfloat blue[4] = {0.2, 0.2, 1.0, 1.0};
+
+  /*** OpenGL BEGIN ***/
+  if (!gdk_gl_drawable_gl_begin (gldrawable, glcontext))
+    return;
+
+  glLightfv (GL_LIGHT0, GL_POSITION, pos);
+  glEnable (GL_CULL_FACE);
+  glEnable (GL_LIGHTING);
+  glEnable (GL_LIGHT0);
+  glShadeModel(GL_SMOOTH);
+  glEnable (GL_DEPTH_TEST);
+
+  /* make the gears */
+  gear1 = glGenLists (1);
+  glNewList (gear1, GL_COMPILE);
+    glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red);
+    gear (1.0, 4.0, 1.0, 20, 0.7);
+  glEndList ();
+
+  gear2 = glGenLists (1);
+  glNewList (gear2, GL_COMPILE);
+    glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green);
+    gear (0.5, 2.0, 2.0, 10, 0.7);
+  glEndList ();
+
+  gear3 = glGenLists (1);
+  glNewList (gear3, GL_COMPILE);
+    glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue);
+    gear (1.3, 2.0, 0.5, 10, 0.7);
+  glEndList ();
+
+  glEnable (GL_NORMALIZE);
+
+  g_print ("\n");
+  g_print ("GL_RENDERER   = %s\n", (char *) glGetString (GL_RENDERER));
+  g_print ("GL_VERSION    = %s\n", (char *) glGetString (GL_VERSION));
+  g_print ("GL_VENDOR     = %s\n", (char *) glGetString (GL_VENDOR));
+  g_print ("GL_EXTENSIONS = %s\n", (char *) glGetString (GL_EXTENSIONS));
+  g_print ("\n");
+
+  program1 = create_shader_program ("shiny");
+  program2 = create_shader_program ("velvet");
+
+  gdk_gl_drawable_gl_end (gldrawable);
+  /*** OpenGL END ***/
+
+  /* create timer */
+  if (timer == NULL)
+    timer = g_timer_new ();
+
+  g_timer_start (timer);
+}
+
+static gboolean
+idle (GtkWidget *widget)
+{
+  angle += 2.0;
+
+  /* Invalidate the whole window. */
+  gdk_window_invalidate_rect (widget->window, &widget->allocation, FALSE);
+
+  /* Update synchronously (fast). */
+  if (is_sync)
+    gdk_window_process_updates (widget->window, FALSE);
+
+  return TRUE;
+}
+
+static guint idle_id = 0;
+
+static void
+idle_add (GtkWidget *widget)
+{
+  if (idle_id == 0)
+    {
+      idle_id = g_timeout_add (50, (GSourceFunc) idle, widget);
+    }
+}
+
+static void
+idle_remove (GtkWidget *widget)
+{
+  if (idle_id != 0)
+    {
+      g_source_remove (idle_id);
+      idle_id = 0;
+    }
+}
+
+static gboolean
+map (GtkWidget   *widget,
+     GdkEventAny *event,
+     gpointer     data)
+{
+  idle_add (widget);
+
+  return TRUE;
+}
+
+static gboolean
+unmap (GtkWidget   *widget,
+       GdkEventAny *event,
+       gpointer     data)
+{
+  idle_remove (widget);
+
+  return TRUE;
+}
+
+static gboolean
+visible (GtkWidget          *widget,
+	 GdkEventVisibility *event,
+	 gpointer            data)
+{
+  if (event->state == GDK_VISIBILITY_FULLY_OBSCURED)
+    idle_remove (widget);
+  else
+    idle_add (widget);
+
+  return TRUE;
+}
+
+/* change view angle, exit upon ESC */
+static gboolean
+key (GtkWidget   *widget,
+     GdkEventKey *event,
+     gpointer     data)
+{
+  switch (event->keyval)
+    {
+    case GDK_z:
+      view_rotz += 5.0;
+      break;
+    case GDK_Z:
+      view_rotz -= 5.0;
+      break;
+    case GDK_Up:
+      view_rotx += 5.0;
+      break;
+    case GDK_Down:
+      view_rotx -= 5.0;
+      break;
+    case GDK_Left:
+      view_roty += 5.0;
+      break;
+    case GDK_Right:
+      view_roty -= 5.0;
+      break;
+    case GDK_Escape:
+      gtk_main_quit ();
+      break;
+    default:
+      return FALSE;
+    }
+
+  gdk_window_invalidate_rect (widget->window, &widget->allocation, FALSE);
+
+  return TRUE;
+}
+
+int
+main (int   argc,
+      char *argv[])
+{
+  GdkGLConfig *glconfig;
+  GtkWidget *window;
+  GtkWidget *vbox;
+  GtkWidget *drawing_area;
+  GtkWidget *button;
+  int i;
+
+  /*
+   * Init GTK.
+   */
+
+  gtk_init (&argc, &argv);
+
+  /*
+   * Init GtkGLExt.
+   */
+
+  gtk_gl_init (&argc, &argv);
+
+  /*
+   * Command line options.
+   */
+
+  for (i = 0; i < argc; i++)
+    {
+      if (strcmp (argv[i], "--async") == 0)
+        is_sync = FALSE;
+    }
+
+  /*
+   * Configure OpenGL-capable visual.
+   */
+
+  /* Try double-buffered visual */
+  glconfig = gdk_gl_config_new_by_mode (GDK_GL_MODE_RGB    |
+					GDK_GL_MODE_DEPTH  |
+					GDK_GL_MODE_DOUBLE);
+  if (glconfig == NULL)
+    {
+      g_print ("*** Cannot find the double-buffered visual.\n");
+      g_print ("*** Trying single-buffered visual.\n");
+
+      /* Try single-buffered visual */
+      glconfig = gdk_gl_config_new_by_mode (GDK_GL_MODE_RGB   |
+					    GDK_GL_MODE_DEPTH);
+      if (glconfig == NULL)
+	{
+	  g_print ("*** No appropriate OpenGL-capable visual found.\n");
+	  exit (1);
+	}
+    }
+
+  /*
+   * Top-level window.
+   */
+
+  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+  gtk_window_set_title (GTK_WINDOW (window), "gears");
+
+  /* Get automatically redrawn if any of their children changed allocation. */
+  gtk_container_set_reallocate_redraws (GTK_CONTAINER (window), TRUE);
+
+  g_signal_connect (G_OBJECT (window), "delete_event",
+		    G_CALLBACK (gtk_main_quit), NULL);
+
+  /*
+   * VBox.
+   */
+
+  vbox = gtk_vbox_new (FALSE, 0);
+  gtk_container_add (GTK_CONTAINER (window), vbox);
+  gtk_widget_show (vbox);
+
+  /*
+   * Drawing area for drawing OpenGL scene.
+   */
+
+  drawing_area = gtk_drawing_area_new ();
+  gtk_widget_set_size_request (drawing_area, 300, 300);
+
+  /* Set OpenGL-capability to the widget. */
+  gtk_widget_set_gl_capability (drawing_area,
+				glconfig,
+				NULL,
+				TRUE,
+				GDK_GL_RGBA_TYPE);
+
+  gtk_widget_add_events (drawing_area,
+			 GDK_VISIBILITY_NOTIFY_MASK);
+
+  g_signal_connect_after (G_OBJECT (drawing_area), "realize",
+                          G_CALLBACK (init), NULL);
+  g_signal_connect (G_OBJECT (drawing_area), "configure_event",
+		    G_CALLBACK (reshape), NULL);
+  g_signal_connect (G_OBJECT (drawing_area), "expose_event",
+		    G_CALLBACK (draw), NULL);
+  g_signal_connect (G_OBJECT (drawing_area), "map_event",
+		    G_CALLBACK (map), NULL);
+  g_signal_connect (G_OBJECT (drawing_area), "unmap_event",
+		    G_CALLBACK (unmap), NULL);
+  g_signal_connect (G_OBJECT (drawing_area), "visibility_notify_event",
+		    G_CALLBACK (visible), NULL);
+
+  g_signal_connect_swapped (G_OBJECT (window), "key_press_event",
+			    G_CALLBACK (key), drawing_area);
+
+  gtk_box_pack_start (GTK_BOX (vbox), drawing_area, TRUE, TRUE, 0);
+
+  gtk_widget_show (drawing_area);
+
+  /*
+   * Simple quit button.
+   */
+
+  button = gtk_button_new_with_label ("Quit");
+
+  g_signal_connect (G_OBJECT (button), "clicked",
+		    G_CALLBACK (gtk_main_quit), NULL);
+
+  gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
+
+  gtk_widget_show (button);
+
+  /*
+   * Show window.
+   */
+
+  gtk_widget_show (window);
+
+  /*
+   * Main loop.
+   */
+
+  gtk_main ();
+
+  return 0;
+}
diff --git a/examples/glsl/shiny.fsh b/examples/glsl/shiny.fsh
new file mode 100644
index 0000000..27023d6
--- /dev/null
+++ b/examples/glsl/shiny.fsh
@@ -0,0 +1,33 @@
+// Based on Point Light shader from oZone3D.Net 
+// http://www.ozone3d.net/tutorials/glsl_lighting_phong_p2.php
+
+varying vec3 normal, light_direction, eye_position;
+varying float attenuation;
+
+void main(void)
+{
+  vec4 final_color = 
+    (gl_FrontLightModelProduct.sceneColor * gl_FrontMaterial.ambient) + 
+	(gl_LightSource[0].ambient * gl_FrontMaterial.ambient)*attenuation;
+							
+  vec3 N = normalize(normal);
+  vec3 L = normalize(light_direction);
+	
+  float lambert_term = dot(N,L);
+	
+  if(lambert_term > 0.0)
+	{
+      final_color += gl_LightSource[0].diffuse * 
+                     gl_FrontMaterial.diffuse * lambert_term * attenuation;	
+		
+      vec3 E = normalize(eye_position);
+      vec3 R = reflect(-L, N);
+		
+      float specular = pow(max(dot(R, E), 0.0), gl_FrontMaterial.shininess);
+		
+      final_color += gl_LightSource[0].specular * gl_FrontMaterial.specular * 
+                     specular * attenuation;	
+	}
+
+	gl_FragColor = final_color;			
+}
diff --git a/examples/glsl/shiny.vsh b/examples/glsl/shiny.vsh
new file mode 100644
index 0000000..520abd2
--- /dev/null
+++ b/examples/glsl/shiny.vsh
@@ -0,0 +1,22 @@
+// Based on Point Light shader from oZone3D.Net 
+// http://www.ozone3d.net/tutorials/glsl_lighting_phong_p2.php
+
+varying vec3 normal, light_direction, eye_position;
+varying float attenuation;
+
+void main(void)
+{	
+  normal = gl_NormalMatrix * gl_Normal;
+
+  vec3 vVertex = vec3(gl_ModelViewMatrix * gl_Vertex);
+  light_direction = vec3(gl_LightSource[0].position.xyz - vVertex);
+  eye_position = -vVertex;
+	
+  float d = length(light_direction);
+	
+  attenuation = 1.0 / ( gl_LightSource[0].constantAttenuation + 
+                (gl_LightSource[0].linearAttenuation*d) + 
+                (gl_LightSource[0].quadraticAttenuation*d*d) );
+
+  gl_Position = ftransform();		
+}
diff --git a/examples/glsl/velvet.fsh b/examples/glsl/velvet.fsh
new file mode 100644
index 0000000..59c8adb
--- /dev/null
+++ b/examples/glsl/velvet.fsh
@@ -0,0 +1,53 @@
+// Based on Velvet shader from ATI RenderMonkey Fabric project
+// http://developer.amd.com/gpu/rendermonkey/
+
+varying vec3 eye_position;
+varying vec3 eye_normal;
+varying vec4 global_ambient;
+varying vec4 light_pos;
+varying vec4 light_color;
+varying vec4 base_color;
+
+const vec4 sheen = vec4(0.8137, 0.8137, 0.8137, 1.0); 
+const vec4 shiny = vec4(0.1267, 0.1267, 0.1267, 1.0);
+const vec4 Ka = vec4(0.23, 0.23, 0.23, 1.0);
+const vec4 Kd = vec4(0.43, 0.43, 0.43, 1.0);
+
+const float roughness = 0.1;
+const float edginess = 20.5;
+const float backscatter = 0.1;
+
+vec4 diffuse(vec3 Neye, vec3 Peye)
+{
+   // Compute normalized vector from vertex to light in eye space  (Leye)
+   vec3 Leye = (vec3(light_pos) - Peye) / length(vec3(light_pos) - Peye);
+
+   float NdotL = dot(Neye, Leye);
+
+   // N.L
+   return vec4(NdotL, NdotL, NdotL, NdotL);
+}
+
+void main(void)
+{
+   vec3 Nf = normalize(eye_normal);           // Normalized normal vector
+   vec3 Veye = -(eye_position / length(eye_position));  // Normalized eye vector
+
+   // For every light do the following:
+
+   // Hemisphere
+   vec3 Leye = ( vec3(light_pos) - eye_position) / length( vec3(light_pos) - eye_position);             // Leye for a given light
+
+   // Retroreflective lobe
+   float cosine = clamp(dot(Leye, Veye), 0.0, 1.0);
+   
+   vec4 local_shiny = shiny + pow (cosine, 1.0 / roughness ) * backscatter * light_color * sheen;
+
+   // Horizon scattering
+   cosine     = clamp (dot(Nf, Veye), 0.0, 1.0);
+   float sine = sqrt (1.0 - (cosine * cosine));
+   local_shiny += pow (sine, edginess) * dot(Leye, Nf) * light_color * sheen;
+
+   // Add in diffuse color and return
+   gl_FragColor = (Ka*global_ambient + Kd*diffuse(eye_normal, eye_position)) * base_color + local_shiny;
+}
\ No newline at end of file
diff --git a/examples/glsl/velvet.vsh b/examples/glsl/velvet.vsh
new file mode 100644
index 0000000..6181a33
--- /dev/null
+++ b/examples/glsl/velvet.vsh
@@ -0,0 +1,21 @@
+// Based on Velvet shader from ATI RenderMonkey Fabric project
+// http://developer.amd.com/gpu/rendermonkey/
+
+varying vec3 eye_position;
+varying vec3 eye_normal;
+varying vec4 global_ambient;
+varying vec4 light_pos;
+varying vec4 light_color;
+varying vec4 base_color;
+
+void main(void)
+{
+  gl_Position = ftransform();
+   
+  eye_position = vec3(gl_ModelViewMatrix * gl_Vertex);
+  eye_normal = gl_NormalMatrix * gl_Normal;
+  global_ambient = gl_LightModel.ambient * gl_FrontMaterial.ambient;
+  light_pos = gl_LightSource[0].position;
+  light_color = gl_LightSource[0].diffuse;
+  base_color = gl_FrontMaterial.diffuse;
+}



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]