can now also draw the normal vectors (seems very useful for instructive
[freeglut] / progs / demos / shapes / shapes.c
index c6527fc..b2da232 100644 (file)
 #include <crtdbg.h>
 #endif
 
+/* report GL errors, if any, to stderr */
+void checkError(const char *functionName)
+{
+    GLenum error;
+    while (( error = glGetError() ) != GL_NO_ERROR) {
+        fprintf (stderr, "GL error 0x%X detected in %s\n", error, functionName);
+    }
+}
+
 /*
  * OpenGL 2+ shader mode needs some function and macro definitions, 
  * avoiding a dependency on additional libraries like GLEW or the
@@ -82,9 +91,12 @@ typedef char ourGLchar;
 #define APIENTRY
 #endif
 
+#ifndef GL_VERSION_1_5
 typedef void (APIENTRY *PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers);
 typedef void (APIENTRY *PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer);
 typedef void (APIENTRY *PFNGLBUFFERDATAPROC) (GLenum target, ourGLsizeiptr size, const GLvoid *data, GLenum usage);
+#endif
+#ifndef GL_VERSION_2_0
 typedef GLuint (APIENTRY *PFNGLCREATESHADERPROC) (GLenum type);
 typedef void (APIENTRY *PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const ourGLchar **string, const GLint *length);
 typedef void (APIENTRY *PFNGLCOMPILESHADERPROC) (GLuint shader);
@@ -100,6 +112,7 @@ typedef GLint (APIENTRY *PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const ourG
 typedef GLint (APIENTRY *PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const ourGLchar *name);
 typedef void (APIENTRY *PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
 typedef void (APIENTRY *PFNGLUNIFORMMATRIX3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+#endif
 
 PFNGLCREATESHADERPROC gl_CreateShader;
 PFNGLSHADERSOURCEPROC gl_ShaderSource;
@@ -144,9 +157,9 @@ const ourGLchar *vertexShaderSource[] = {
     " */",
     "attribute vec3 fg_coord;",
     "attribute vec3 fg_normal;",
-    "varying vec4 position;  // position of the vertex (and fragment) in world space",
-    "varying vec3 varyingNormalDirection;  // surface normal vector in world space",
-    "uniform mat4 m, p;      // don't need v, as always identity in our demo",
+    "varying vec4 position;  /* position of the vertex (and fragment) in world space */",
+    "varying vec3 varyingNormalDirection;  /* surface normal vector in world space */",
+    "uniform mat4 m, p;      /* don't need v, as always identity in our demo */",
     "uniform mat3 m_3x3_inv_transp;",
     " ",
     "void main()",
@@ -155,7 +168,7 @@ const ourGLchar *vertexShaderSource[] = {
     "  position = m * fg_coord4;",
     "  varyingNormalDirection = normalize(m_3x3_inv_transp * fg_normal);",
     " ",
-    "  mat4 mvp = p*m;   // normally p*v*m",
+    "  mat4 mvp = p*m;   /* normally p*v*m */",
     "  gl_Position = mvp * fg_coord4;",
     "}"
 };
@@ -166,9 +179,9 @@ const ourGLchar *fragmentShaderSource[] = {
     " * This file is in the public domain.",
     " * Contributors: Martin Kraus, Sylvain Beucler",
     " */",
-    "varying vec4 position;  // position of the vertex (and fragment) in world space",
-    "varying vec3 varyingNormalDirection;  // surface normal vector in world space",
-    "//uniform mat4 v_inv;   // in this demo, the view matrix is always an identity matrix",
+    "varying vec4 position;  /* position of the vertex (and fragment) in world space */",
+    "varying vec3 varyingNormalDirection;  /* surface normal vector in world space */",
+    "/* uniform mat4 v_inv;   // in this demo, the view matrix is always an identity matrix */",
     " ",
     "struct lightSource",
     "{",
@@ -181,13 +194,13 @@ const ourGLchar *fragmentShaderSource[] = {
     "};",
     "lightSource light0 = lightSource(",
     "  vec4(2.0, 5.0, 5.0, 0.0),",
-    "  vec4(1.0,  1.0,  1.0, 1.0),",
-    "  vec4(1.0,  1.0,  1.0, 1.0),",
-    "  0.0, 1.0, 0.0,",
+    "  vec4(1.0, 1.0, 1.0, 1.0),",
+    "  vec4(1.0, 1.0, 1.0, 1.0),",
+    "    0.0, 1.0, 0.0,",
     "  180.0, 0.0,",
     "  vec3(0.0, 0.0, 0.0)",
     ");",
-    "vec4 scene_ambient = vec4(1.0, 0.0, 0.0, 1.0);",
+    "vec4 scene_ambient = vec4(0.2, 0.2, 0.2, 1.0);",
     " ",
     "struct material",
     "{",
@@ -197,8 +210,8 @@ const ourGLchar *fragmentShaderSource[] = {
     "  float shininess;",
     "};",
     "material frontMaterial = material(",
-    "  vec4(0.7, 0.7, 0.7, 1.0),",
-    "  vec4(0.8, 0.8, 0.8, 1.0),",
+    "  vec4(1.0, 0.0, 0.0, 1.0),",
+    "  vec4(1.0, 0.0, 0.0, 1.0),",
     "  vec4(1.0, 1.0, 1.0, 1.0),",
     "  100.0",
     ");",
@@ -206,17 +219,17 @@ const ourGLchar *fragmentShaderSource[] = {
     "void main()",
     "{",
     "  vec3 normalDirection = normalize(varyingNormalDirection);",
-    "  //vec3 viewDirection = normalize(vec3(v_inv * vec4(0.0, 0.0, 0.0, 1.0) - position));",
-    "  vec3 viewDirection = normalize(vec3(vec4(0.0, 0.0, 0.0, 1.0) - position));    // in this demo, the view matrix is always an identity matrix",
+    "  /* vec3 viewDirection = normalize(vec3(v_inv * vec4(0.0, 0.0, 0.0, 1.0) - position)); */",
+    "  vec3 viewDirection = normalize(vec3(vec4(0.0, 0.0, 0.0, 1.0) - position));    /* in this demo, the view matrix is always an identity matrix */",
     "  vec3 lightDirection;",
     "  float attenuation;",
     " ",
-    "  if (0.0 == light0.position.w) // directional light?",
+    "  if (0.0 == light0.position.w) /* directional light? */",
     "    {",
-    "      attenuation = 1.0; // no attenuation",
+    "      attenuation = 1.0; /* no attenuation */",
     "      lightDirection = normalize(vec3(light0.position));",
     "    } ",
-    "  else // point light or spotlight (or other kind of light) ",
+    "  else /* point light or spotlight (or other kind of light) */",
     "    {",
     "      vec3 positionToLightSource = vec3(light0.position - position);",
     "      float distance = length(positionToLightSource);",
@@ -225,10 +238,10 @@ const ourGLchar *fragmentShaderSource[] = {
     "                           + light0.linearAttenuation * distance",
     "                           + light0.quadraticAttenuation * distance * distance);",
     " ",
-    "      if (light0.spotCutoff <= 90.0) // spotlight?",
+    "      if (light0.spotCutoff <= 90.0) /* spotlight? */",
     "        {",
     "          float clampedCosine = max(0.0, dot(-lightDirection, light0.spotDirection));",
-    "          if (clampedCosine < cos(radians(light0.spotCutoff))) // outside of spotlight cone?",
+    "          if (clampedCosine < cos(radians(light0.spotCutoff))) /* outside of spotlight cone? */",
     "            {",
     "              attenuation = 0.0;",
     "            }",
@@ -246,11 +259,11 @@ const ourGLchar *fragmentShaderSource[] = {
     "    * max(0.0, dot(normalDirection, lightDirection));",
     " ",
     "  vec3 specularReflection;",
-    "  if (dot(normalDirection, lightDirection) < 0.0) // light source on the wrong side?",
+    "  if (dot(normalDirection, lightDirection) < 0.0) /* light source on the wrong side? */",
     "    {",
-    "      specularReflection = vec3(0.0, 0.0, 0.0); // no specular reflection",
+    "      specularReflection = vec3(0.0, 0.0, 0.0); /* no specular reflection */",
     "    }",
-    "  else // light source on the right side",
+    "  else /* light source on the right side */",
     "    {",
     "      specularReflection = attenuation * vec3(light0.specular) * vec3(frontMaterial.specular) ",
     "        * pow(max(0.0, dot(reflect(-lightDirection, normalDirection), viewDirection)), frontMaterial.shininess);",
@@ -282,12 +295,13 @@ GLint getAttribOrUniformLocation(const char* name, GLuint program, GLboolean isA
 
         return uniform;
     }
+    checkError ("getAttribOrUniformLocation");
 }
 
 GLuint program;
 GLint attribute_fg_coord = -1, attribute_fg_normal = -1;  
 GLint uniform_m = -1, uniform_p = -1, uniform_m_3x3_inv_transp = -1;
-GLint shaderReady = 0;  // Set to 1 when all initialization went well, to -1 when somehow unusable.
+GLint shaderReady = 0;  /* Set to 1 when all initialization went well, to -1 when shader somehow unusable. */
 
 
 
@@ -305,12 +319,16 @@ void compileAndCheck(GLuint shader)
         fprintf (stderr, "compile log: %s\n", infoLog);
         free (infoLog);
     }
+    checkError ("compileAndCheck");
 }
 
 GLuint compileShaderSource(GLenum type, GLsizei count, const ourGLchar **string)
 {
     GLuint shader = gl_CreateShader (type);
     gl_ShaderSource (shader, count, string, NULL);
+
+    checkError ("compileShaderSource");
+
     compileAndCheck (shader);
     return shader;
 }
@@ -329,6 +347,7 @@ void linkAndCheck(GLuint program)
         fprintf (stderr, "link log: %s\n", infoLog);
         free (infoLog);
     }
+    checkError ("linkAndCheck");
 }
 
 void createProgram(GLuint vertexShader, GLuint fragmentShader)
@@ -340,6 +359,9 @@ void createProgram(GLuint vertexShader, GLuint fragmentShader)
     if (fragmentShader != 0) {
         gl_AttachShader (program, fragmentShader);
     }
+
+    checkError ("createProgram");
+
     linkAndCheck (program);
 }
 
@@ -353,6 +375,8 @@ void initShader(void)
     GLuint fragmentShader =
         compileShaderSource (GL_FRAGMENT_SHADER, fragmentShaderLines, fragmentShaderSource);
 
+    checkError ("initShader - 1");
+
     createProgram (vertexShader, fragmentShader);
 
     gl_UseProgram (program);
@@ -370,6 +394,8 @@ void initShader(void)
         shaderReady = -1;
     else
         shaderReady = 1;
+
+    checkError ("initShader - 2");
 }
 
 /*
@@ -394,6 +420,7 @@ static float ar;
 static GLboolean persProject = GL_TRUE;
 static GLboolean animateXRot = GL_FALSE;
 static GLboolean useShader   = GL_FALSE;
+static GLboolean visNormals  = GL_FALSE;
 
 /*
  * These one-liners draw particular objects, fetching appropriate
@@ -515,7 +542,7 @@ static const entry table [] =
     ENTRY (Sphere),
     ENTRY (Cone),
     ENTRY (Cylinder),
-    ENTRY (Cuboctahedron)
+    ENTRY (Cuboctahedron)   /* This one doesn't work when in shader mode and is then skipped */
 };
 #undef ENTRY
 
@@ -578,8 +605,8 @@ resize(int width, int height)
 static void display(void)
 {
     const double t = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
-    const double a = t*90.0;
-    const double b = (animateXRot?t:1)*60.0;
+    const double a = t*89.0;
+    const double b = (animateXRot?t:1)*67.0;
 
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
@@ -588,7 +615,7 @@ static void display(void)
 
     if (useShader && shaderReady)
     {
-        // setup use of shader (and vertex buffer by FreeGLUT)
+        /* setup use of shader (and vertex buffer by FreeGLUT) */
         gl_UseProgram (program);
         glutSetVertexAttribCoord3(attribute_fg_coord);
         glutSetVertexAttribNormal(attribute_fg_normal);
@@ -627,10 +654,13 @@ static void display(void)
         gl_UseProgram (0);
         glutSetVertexAttribCoord3(-1);
         glutSetVertexAttribNormal(-1);
+
+        checkError ("display");
     }
     else
     {
         /* fixed function pipeline */
+        glutSetOption(GLUT_OBJECTS_VISUALIZE_NORMALS,visNormals);   /* Normals visualized or not? */
         glMatrixMode(GL_PROJECTION);
         glLoadIdentity();
         if (persProject)
@@ -670,14 +700,21 @@ static void display(void)
         shapesPrintf (5, 1, "Outer radius  Up  Down : %f", orad);
         shapesPrintf (6, 1, "Inner radius Left Right: %f", irad);
         if (persProject)
-            shapesPrintf (7, 1, "Perspective projection");
+            shapesPrintf (7, 1, "Perspective projection (p)");
         else
-            shapesPrintf (7, 1, "Orthographic projection");
+            shapesPrintf (7, 1, "Orthographic projection (p)");
         if (useShader)
-            shapesPrintf (8, 1, "Using shader");
+            shapesPrintf (8, 1, "Using shader (s)");
         else
-            shapesPrintf (8, 1, "Using fixed function pipeline");
+            shapesPrintf (8, 1, "Using fixed function pipeline (s)");
+        if (animateXRot)
+            shapesPrintf (9, 1, "2D rotation (r)");
+        else
+            shapesPrintf (9, 1, "1D rotation (r)");
+        if (!useShader)
+            shapesPrintf (10, 1, "visualizing normals: %i (n)",visNormals);
     } else {
+        /* print to command line instead */
         printf ( "Shape %d slides %d stacks %d\n", function_index, slices, stacks ) ;
     }
 
@@ -724,6 +761,9 @@ key(unsigned char key, int x, int y)
     case 'S':
     case 's': useShader=!useShader;       break;
 
+    case 'N':
+    case 'n': visNormals=!visNormals;     break;
+
     default:
         break;
     }
@@ -776,7 +816,7 @@ const GLfloat high_shininess[] = { 100.0f };
 int
 main(int argc, char *argv[])
 {
-    glutInitWindowSize(640,480);
+    glutInitWindowSize(800,600);
     glutInitWindowPosition(40,40);
     glutInit(&argc, argv);
     glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_MULTISAMPLE);