[gtkglext] Add gears example using GLSL programs
- From: Mukund Sivaraman <muks src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [gtkglext] Add gears example using GLSL programs
- Date: Mon, 19 Oct 2009 19:40:28 +0000 (UTC)
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]