From: Diederick Niehorster Date: Sat, 9 Jun 2012 14:56:58 +0000 (+0000) Subject: shapes demo can now test shader based drawing as well, added glmatrix X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=commitdiff_plain;h=8a58cc57b97a1aa188018d987671ed565031874d;p=freeglut shapes demo can now test shader based drawing as well, added glmatrix helpers mostly written by John T. git-svn-id: svn+ssh://svn.code.sf.net/p/freeglut/code/trunk/freeglut/freeglut@1328 7f0cb862-5218-0410-a997-914c9d46530a --- diff --git a/progs/demos/shapes/glmatrix.c b/progs/demos/shapes/glmatrix.c new file mode 100644 index 0000000..3d1b77e --- /dev/null +++ b/progs/demos/shapes/glmatrix.c @@ -0,0 +1,254 @@ +#include +#define _USE_MATH_DEFINES +#include +#include "glmatrix.h" + +#define MMODE_IDX(x) ((x) - GL_MODELVIEW) +#define MAT_STACK_SIZE 32 +#define MAT_IDENT {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1} + +static int mm_idx = 0; +static float mat_stack[3][MAT_STACK_SIZE][16] = {{MAT_IDENT}, {MAT_IDENT}, {MAT_IDENT}}; +static int stack_top[3]; + +void gl_matrix_mode(int mm) +{ + mm_idx = MMODE_IDX(mm); +} + +void gl_push_matrix(void) +{ + int top = stack_top[mm_idx]; + + memcpy(mat_stack[mm_idx][top + 1], mat_stack[mm_idx][top], 16 * sizeof(float)); + stack_top[mm_idx]++; +} + +void gl_pop_matrix(void) +{ + stack_top[mm_idx]--; +} + +void gl_load_identity(void) +{ + static const float idmat[] = MAT_IDENT; + int top = stack_top[mm_idx]; + float *mat = mat_stack[mm_idx][top]; + + memcpy(mat, idmat, sizeof idmat); +} + +void gl_load_matrixf(const float *m) +{ + int top = stack_top[mm_idx]; + float *mat = mat_stack[mm_idx][top]; + + memcpy(mat, m, 16 * sizeof *mat); +} + +#define M4(i, j) ((i << 2) + j) + +void gl_mult_matrixf(const float *m2) +{ + int i, j; + int top = stack_top[mm_idx]; + float *m1 = mat_stack[mm_idx][top]; + float res[16]; + + for(i=0; i<4; i++) { + for(j=0; j<4; j++) { + res[M4(i,j)] = m1[M4(i,0)] * m2[M4(0,j)] + + m1[M4(i,1)] * m2[M4(1,j)] + + m1[M4(i,2)] * m2[M4(2,j)] + + m1[M4(i,3)] * m2[M4(3,j)]; + } + } + + memcpy(m1, res, sizeof res); +} + +void gl_translatef(float x, float y, float z) +{ + float mat[] = MAT_IDENT; + + mat[12] = x; + mat[13] = y; + mat[14] = z; + + gl_mult_matrixf(mat); +} + +void gl_rotatef(float angle, float x, float y, float z) +{ + float mat[] = MAT_IDENT; + + float angle_rad = (float)M_PI * angle / 180.f; + float sina = (float)sin(angle_rad); + float cosa = (float)cos(angle_rad); + float one_minus_cosa = 1.f - cosa; + float nxsq = x * x; + float nysq = y * y; + float nzsq = z * z; + + mat[0] = nxsq + (1.f - nxsq) * cosa; + mat[4] = x * y * one_minus_cosa - z * sina; + mat[8] = x * z * one_minus_cosa + y * sina; + mat[1] = x * y * one_minus_cosa + z * sina; + mat[5] = nysq + (1.f - nysq) * cosa; + mat[9] = y * z * one_minus_cosa - x * sina; + mat[2] = x * z * one_minus_cosa - y * sina; + mat[6] = y * z * one_minus_cosa + x * sina; + mat[10] = nzsq + (1.f - nzsq) * cosa; + + gl_mult_matrixf(mat); +} + +void gl_scalef(float x, float y, float z) +{ + float mat[] = MAT_IDENT; + + mat[0] = x; + mat[5] = y; + mat[10] = z; + + gl_mult_matrixf(mat); +} + +void gl_ortho(float left, float right, float bottom, float top, float near, float far) +{ + float mat[] = MAT_IDENT; + + float dx = right - left; + float dy = top - bottom; + float dz = far - near; + + float tx = -(right + left) / dx; + float ty = -(top + bottom) / dy; + float tz = -(far + near) / dz; + + float sx = 2.f / dx; + float sy = 2.f / dy; + float sz = -2.f / dz; + + mat[0] = sx; + mat[5] = sy; + mat[10] = sz; + mat[12] = tx; + mat[13] = ty; + mat[14] = tz; + + gl_mult_matrixf(mat); +} + +void gl_frustum(float left, float right, float bottom, float top, float near, float far) +{ + float mat[] = MAT_IDENT; + + float dx = right - left; + float dy = top - bottom; + float dz = far - near; + + float a = (right + left) / dx; + float b = (top + bottom) / dy; + float c = -(far + near) / dz; + float d = -2.f * far * near / dz; + + mat[0] = 2.f * near / dx; + mat[5] = 2.f * near / dy; + mat[8] = a; + mat[9] = b; + mat[10] = c; + mat[11] = -1.f; + mat[14] = d; + + gl_mult_matrixf(mat); +} + +void glu_perspective(float vfov, float aspect, float near, float far) +{ + float vfov_rad = (float)M_PI * vfov / 180.f; + float x = near * (float)tan(vfov_rad / 2.f); + gl_frustum(-aspect * x, aspect * x, -x, x, near, far); +} + +float* get_matrix(int mm) +{ + int idx = MMODE_IDX(mm); + int top = stack_top[idx]; + return mat_stack[idx][top]; +} + + +#define M3(i, j) ((i * 3) + j) +static float inv_transpose_result[9]; + +float* get_inv_transpose_3x3(int mm) +{ + int idx = MMODE_IDX(mm); + int top = stack_top[idx]; + float *m1 = mat_stack[idx][top]; + + + float determinant = +m1[M4(0,0)]*(m1[M4(1,1)]*m1[M4(2,2)]-m1[M4(2,1)]*m1[M4(1,2)]) + -m1[M4(0,1)]*(m1[M4(1,0)]*m1[M4(2,2)]-m1[M4(1,2)]*m1[M4(2,0)]) + +m1[M4(0,2)]*(m1[M4(1,0)]*m1[M4(2,1)]-m1[M4(1,1)]*m1[M4(2,0)]); + + float invdet = 1/determinant; + + inv_transpose_result[M3(0,0)] = (m1[M4(1,1)]*m1[M4(2,2)]-m1[M4(2,1)]*m1[M4(1,2)])*invdet; + inv_transpose_result[M3(1,0)] = -(m1[M4(0,1)]*m1[M4(2,2)]-m1[M4(0,2)]*m1[M4(2,1)])*invdet; + inv_transpose_result[M3(2,0)] = (m1[M4(0,1)]*m1[M4(1,2)]-m1[M4(0,2)]*m1[M4(1,1)])*invdet; + inv_transpose_result[M3(0,1)] = -(m1[M4(1,0)]*m1[M4(2,2)]-m1[M4(1,2)]*m1[M4(2,0)])*invdet; + inv_transpose_result[M3(1,1)] = (m1[M4(0,0)]*m1[M4(2,2)]-m1[M4(0,2)]*m1[M4(2,0)])*invdet; + inv_transpose_result[M3(2,1)] = -(m1[M4(0,0)]*m1[M4(1,2)]-m1[M4(1,0)]*m1[M4(0,2)])*invdet; + inv_transpose_result[M3(0,2)] = (m1[M4(1,0)]*m1[M4(2,1)]-m1[M4(2,0)]*m1[M4(1,1)])*invdet; + inv_transpose_result[M3(1,2)] = -(m1[M4(0,0)]*m1[M4(2,1)]-m1[M4(2,0)]*m1[M4(0,1)])*invdet; + inv_transpose_result[M3(2,2)] = (m1[M4(0,0)]*m1[M4(1,1)]-m1[M4(1,0)]*m1[M4(0,1)])*invdet; + + return inv_transpose_result; +} + + +#if 0 +void gl_apply_xform(unsigned int prog) +{ + int loc, mvidx, pidx, tidx, mvtop, ptop, ttop; + + mvidx = MMODE_IDX(GL_MODELVIEW); + pidx = MMODE_IDX(GL_PROJECTION); + tidx = MMODE_IDX(GL_TEXTURE); + + mvtop = stack_top[mvidx]; + ptop = stack_top[pidx]; + ttop = stack_top[tidx]; + + assert(prog); + + if((loc = glGetUniformLocation(prog, "matrix_modelview")) != -1) { + glUniformMatrix4fv(loc, 1, 0, mat_stack[mvidx][mvtop]); + } + + if((loc = glGetUniformLocation(prog, "matrix_projection")) != -1) { + glUniformMatrix4fv(loc, 1, 0, mat_stack[pidx][ptop]); + } + + if((loc = glGetUniformLocation(prog, "matrix_texture")) != -1) { + glUniformMatrix4fv(loc, 1, 0, mat_stack[tidx][ttop]); + } + + if((loc = glGetUniformLocation(prog, "matrix_normal")) != -1) { + float nmat[9]; + + nmat[0] = mat_stack[mvidx][mvtop][0]; + nmat[1] = mat_stack[mvidx][mvtop][1]; + nmat[2] = mat_stack[mvidx][mvtop][2]; + nmat[3] = mat_stack[mvidx][mvtop][4]; + nmat[4] = mat_stack[mvidx][mvtop][5]; + nmat[5] = mat_stack[mvidx][mvtop][6]; + nmat[6] = mat_stack[mvidx][mvtop][8]; + nmat[7] = mat_stack[mvidx][mvtop][9]; + nmat[8] = mat_stack[mvidx][mvtop][10]; + glUniformMatrix3fv(loc, 1, 0, nmat); + } +} +#endif diff --git a/progs/demos/shapes/glmatrix.h b/progs/demos/shapes/glmatrix.h new file mode 100644 index 0000000..ab1c096 --- /dev/null +++ b/progs/demos/shapes/glmatrix.h @@ -0,0 +1,31 @@ +#ifndef GLMATRIX_H_ +#define GLMATRIX_H_ + +#ifndef GL_MODELVIEW +#define GL_MODELVIEW 0x1700 +#endif +#ifndef GL_PROJECTION +#define GL_PROJECTION 0x1701 +#endif +#ifndef GL_TEXTURE +#define GL_TEXTURE 0x1702 +#endif + +void gl_matrix_mode(int mmode); +void gl_push_matrix(void); +void gl_pop_matrix(void); +void gl_load_identity(void); +void gl_load_matrixf(const float *mat); +void gl_mult_matrixf(const float *mat); +void gl_translatef(float x, float y, float z); +void gl_rotatef(float angle, float x, float y, float z); +void gl_scalef(float x, float y, float z); +void gl_ortho(float left, float right, float bottom, float top, float near, float far); +void gl_frustum(float left, float right, float bottom, float top, float near, float far); +void glu_perspective(float vfov, float aspect, float near, float far); + +/* getters */ +float* get_matrix(int mm); +float* get_inv_transpose_3x3(int mm); + +#endif /* GLMATRIX_H_ */ diff --git a/progs/demos/shapes/shapes.c b/progs/demos/shapes/shapes.c index 271ea04..e984d29 100644 --- a/progs/demos/shapes/shapes.c +++ b/progs/demos/shapes/shapes.c @@ -43,12 +43,336 @@ #include #include +#include "glmatrix.h" + #ifdef _MSC_VER /* DUMP MEMORY LEAKS */ #include #endif /* + * OpenGL 2+ shader mode needs some function and macro definitions, + * avoiding a dependency on additional libraries like GLEW or the + * GL/glext.h header + */ +#ifndef GL_FRAGMENT_SHADER +#define GL_FRAGMENT_SHADER 0x8B30 +#endif + +#ifndef GL_VERTEX_SHADER +#define GL_VERTEX_SHADER 0x8B31 +#endif + +#ifndef GL_COMPILE_STATUS +#define GL_COMPILE_STATUS 0x8B81 +#endif + +#ifndef GL_LINK_STATUS +#define GL_LINK_STATUS 0x8B82 +#endif + +#ifndef GL_INFO_LOG_LENGTH +#define GL_INFO_LOG_LENGTH 0x8B84 +#endif + +typedef ptrdiff_t ourGLsizeiptr; +typedef char ourGLchar; + +#ifndef APIENTRY +#define APIENTRY +#endif + +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); +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); +typedef GLuint (APIENTRY *PFNGLCREATEPROGRAMPROC) (void); +typedef void (APIENTRY *PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader); +typedef void (APIENTRY *PFNGLLINKPROGRAMPROC) (GLuint program); +typedef void (APIENTRY *PFNGLUSEPROGRAMPROC) (GLuint program); +typedef void (APIENTRY *PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint *params); +typedef void (APIENTRY *PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, ourGLchar *infoLog); +typedef void (APIENTRY *PFNGLGETPROGRAMIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (APIENTRY *PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei *length, ourGLchar *infoLog); +typedef GLint (APIENTRY *PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const ourGLchar *name); +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); + +PFNGLCREATESHADERPROC gl_CreateShader; +PFNGLSHADERSOURCEPROC gl_ShaderSource; +PFNGLCOMPILESHADERPROC gl_CompileShader; +PFNGLCREATEPROGRAMPROC gl_CreateProgram; +PFNGLATTACHSHADERPROC gl_AttachShader; +PFNGLLINKPROGRAMPROC gl_LinkProgram; +PFNGLUSEPROGRAMPROC gl_UseProgram; +PFNGLGETSHADERIVPROC gl_GetShaderiv; +PFNGLGETSHADERINFOLOGPROC gl_GetShaderInfoLog; +PFNGLGETPROGRAMIVPROC gl_GetProgramiv; +PFNGLGETPROGRAMINFOLOGPROC gl_GetProgramInfoLog; +PFNGLGETATTRIBLOCATIONPROC gl_GetAttribLocation; +PFNGLGETUNIFORMLOCATIONPROC gl_GetUniformLocation; +PFNGLUNIFORMMATRIX4FVPROC gl_UniformMatrix4fv; +PFNGLUNIFORMMATRIX3FVPROC gl_UniformMatrix3fv; + +void initExtensionEntries(void) +{ + gl_CreateShader = (PFNGLCREATESHADERPROC) glutGetProcAddress ("glCreateShader"); + gl_ShaderSource = (PFNGLSHADERSOURCEPROC) glutGetProcAddress ("glShaderSource"); + gl_CompileShader = (PFNGLCOMPILESHADERPROC) glutGetProcAddress ("glCompileShader"); + gl_CreateProgram = (PFNGLCREATEPROGRAMPROC) glutGetProcAddress ("glCreateProgram"); + gl_AttachShader = (PFNGLATTACHSHADERPROC) glutGetProcAddress ("glAttachShader"); + gl_LinkProgram = (PFNGLLINKPROGRAMPROC) glutGetProcAddress ("glLinkProgram"); + gl_UseProgram = (PFNGLUSEPROGRAMPROC) glutGetProcAddress ("glUseProgram"); + gl_GetShaderiv = (PFNGLGETSHADERIVPROC) glutGetProcAddress ("glGetShaderiv"); + gl_GetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC) glutGetProcAddress ("glGetShaderInfoLog"); + gl_GetProgramiv = (PFNGLGETPROGRAMIVPROC) glutGetProcAddress ("glGetProgramiv"); + gl_GetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC) glutGetProcAddress ("glGetProgramInfoLog"); + gl_GetAttribLocation = (PFNGLGETATTRIBLOCATIONPROC) glutGetProcAddress ("glGetAttribLocation"); + gl_GetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC) glutGetProcAddress ("glGetUniformLocation"); + gl_UniformMatrix4fv = (PFNGLUNIFORMMATRIX4FVPROC) glutGetProcAddress ("glUniformMatrix4fv"); + gl_UniformMatrix3fv = (PFNGLUNIFORMMATRIX3FVPROC) glutGetProcAddress ("glUniformMatrix3fv"); +} + +const ourGLchar *vertexShaderSource[] = { + "/**", + " * From the OpenGL Programming wikibook: http://en.wikibooks.org/wiki/GLSL_Programming/GLUT/Smooth_Specular_Highlights", + " * This file is in the public domain.", + " * Contributors: Sylvain Beucler", + " */", + "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", + "uniform mat3 m_3x3_inv_transp;", + " ", + "void main()", + "{", + " vec4 fg_coord4 = vec4(fg_coord, 1.0);", + " position = m * fg_coord4;", + " varyingNormalDirection = normalize(m_3x3_inv_transp * fg_normal);", + " ", + " mat4 mvp = p*m; // normally p*v*m", + " gl_Position = mvp * fg_coord4;", + "}" +}; + +const ourGLchar *fragmentShaderSource[] = { + "/**", + " * From the OpenGL Programming wikibook: http://en.wikibooks.org/wiki/GLSL_Programming/GLUT/Smooth_Specular_Highlights", + " * 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", + " ", + "struct lightSource", + "{", + " vec4 position;", + " vec4 diffuse;", + " vec4 specular;", + " float constantAttenuation, linearAttenuation, quadraticAttenuation;", + " float spotCutoff, spotExponent;", + " vec3 spotDirection;", + "};", + "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,", + " 180.0, 0.0,", + " vec3(0.0, 0.0, 0.0)", + ");", + "vec4 scene_ambient = vec4(1.0, 0.0, 0.0, 1.0);", + " ", + "struct material", + "{", + " vec4 ambient;", + " vec4 diffuse;", + " vec4 specular;", + " 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, 1.0, 1.0, 1.0),", + " 100.0", + ");", + " ", + "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 lightDirection;", + " float attenuation;", + " ", + " if (0.0 == light0.position.w) // directional light?", + " {", + " attenuation = 1.0; // no attenuation", + " lightDirection = normalize(vec3(light0.position));", + " } ", + " else // point light or spotlight (or other kind of light) ", + " {", + " vec3 positionToLightSource = vec3(light0.position - position);", + " float distance = length(positionToLightSource);", + " lightDirection = normalize(positionToLightSource);", + " attenuation = 1.0 / (light0.constantAttenuation", + " + light0.linearAttenuation * distance", + " + light0.quadraticAttenuation * distance * distance);", + " ", + " 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?", + " {", + " attenuation = 0.0;", + " }", + " else", + " {", + " attenuation = attenuation * pow(clampedCosine, light0.spotExponent); ", + " }", + " }", + " }", + " ", + " vec3 ambientLighting = vec3(scene_ambient) * vec3(frontMaterial.ambient);", + " ", + " vec3 diffuseReflection = attenuation ", + " * vec3(light0.diffuse) * vec3(frontMaterial.diffuse)", + " * max(0.0, dot(normalDirection, lightDirection));", + " ", + " vec3 specularReflection;", + " if (dot(normalDirection, lightDirection) < 0.0) // light source on the wrong side?", + " {", + " specularReflection = vec3(0.0, 0.0, 0.0); // no specular reflection", + " }", + " 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);", + " }", + " ", + " gl_FragColor = vec4(ambientLighting + diffuseReflection + specularReflection, 1.0);", + "}" +}; + +GLint getAttribOrUniformLocation(const char* name, GLuint program, GLboolean isAttrib) +{ + if (isAttrib) + { + GLint attrib = gl_GetAttribLocation(program, name); + if (attrib == -1) + { + fprintf(stderr, "Warning: Could not bind attrib %s\n", name); + } + + return attrib; + } + else + { + GLint uniform = gl_GetUniformLocation(program, name); + if (uniform == -1) + { + fprintf(stderr, "Warning: Could not bind uniform %s\n", name); + } + + return uniform; + } +} + +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. + + + +void compileAndCheck(GLuint shader) +{ + GLint status; + gl_CompileShader (shader); + gl_GetShaderiv (shader, GL_COMPILE_STATUS, &status); + if (status == GL_FALSE) { + GLint infoLogLength; + ourGLchar *infoLog; + gl_GetShaderiv (shader, GL_INFO_LOG_LENGTH, &infoLogLength); + infoLog = (ourGLchar*) malloc (infoLogLength); + gl_GetShaderInfoLog (shader, infoLogLength, NULL, infoLog); + fprintf (stderr, "compile log: %s\n", infoLog); + free (infoLog); + } +} + +GLuint compileShaderSource(GLenum type, GLsizei count, const ourGLchar **string) +{ + GLuint shader = gl_CreateShader (type); + gl_ShaderSource (shader, count, string, NULL); + compileAndCheck (shader); + return shader; +} + +void linkAndCheck(GLuint program) +{ + GLint status; + gl_LinkProgram (program); + gl_GetProgramiv (program, GL_LINK_STATUS, &status); + if (status == GL_FALSE) { + GLint infoLogLength; + ourGLchar *infoLog; + gl_GetProgramiv (program, GL_INFO_LOG_LENGTH, &infoLogLength); + infoLog = (ourGLchar*) malloc (infoLogLength); + gl_GetProgramInfoLog (program, infoLogLength, NULL, infoLog); + fprintf (stderr, "link log: %s\n", infoLog); + free (infoLog); + } +} + +void createProgram(GLuint vertexShader, GLuint fragmentShader) +{ + program = gl_CreateProgram (); + if (vertexShader != 0) { + gl_AttachShader (program, vertexShader); + } + if (fragmentShader != 0) { + gl_AttachShader (program, fragmentShader); + } + linkAndCheck (program); +} + +void initShader(void) +{ + const GLsizei vertexShaderLines = sizeof(vertexShaderSource) / sizeof(ourGLchar*); + GLuint vertexShader = + compileShaderSource (GL_VERTEX_SHADER, vertexShaderLines, vertexShaderSource); + + const GLsizei fragmentShaderLines = sizeof(fragmentShaderSource) / sizeof(ourGLchar*); + GLuint fragmentShader = + compileShaderSource (GL_FRAGMENT_SHADER, fragmentShaderLines, fragmentShaderSource); + + createProgram (vertexShader, fragmentShader); + + gl_UseProgram (program); + + attribute_fg_coord = getAttribOrUniformLocation("fg_coord" , program, TRUE); + attribute_fg_normal = getAttribOrUniformLocation("fg_normal" , program, TRUE); + uniform_m = getAttribOrUniformLocation("m" , program, FALSE); + uniform_p = getAttribOrUniformLocation("p" , program, FALSE); + uniform_m_3x3_inv_transp= getAttribOrUniformLocation("m_3x3_inv_transp" , program, FALSE); + + gl_UseProgram (0); + + if (attribute_fg_coord==-1 || attribute_fg_normal==-1 || + uniform_m==-1 || uniform_p==-1 || uniform_m_3x3_inv_transp==-1) + shaderReady = -1; + else + shaderReady = 1; +} + +/* * This macro is only intended to be used on arrays, of course. */ #define NUMBEROF(x) ((sizeof(x))/(sizeof(x[0]))) @@ -69,6 +393,7 @@ static GLboolean show_info = GL_TRUE; static float ar; static GLboolean persProject = GL_TRUE; static GLboolean animateXRot = GL_FALSE; +static GLboolean useShader = GL_FALSE; /* * These one-liners draw particular objects, fetching appropriate @@ -256,37 +581,86 @@ static void display(void) const double a = t*90.0; const double b = (animateXRot?t:1)*60.0; - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - if (persProject) - glFrustum(-ar, ar, -1.0, 1.0, 2.0, 100.0); - else - glOrtho(-ar*3, ar*3, -3.0, 3.0, 2.0, 100.0); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glEnable(GL_LIGHTING); - - glColor3d(1,0,0); - - glPushMatrix(); - glTranslated(0,1.2,-6); - glRotated(b,1,0,0); - glRotated(a,0,0,1); - table [function_index].solid (); - glPopMatrix(); - - glPushMatrix(); - glTranslated(0,-1.2,-6); - glRotated(b,1,0,0); - glRotated(a,0,0,1); - table [function_index].wire (); - glPopMatrix(); + if (useShader && !shaderReady) + initShader(); - glDisable(GL_LIGHTING); - glColor3d(0.1,0.1,0.4); + if (useShader && shaderReady) + { + // setup use of shader (and vertex buffer by FreeGLUT) + gl_UseProgram (program); + glutSetVertexAttribCoord3(attribute_fg_coord); + glutSetVertexAttribNormal(attribute_fg_normal); + + gl_matrix_mode(GL_PROJECTION); + gl_load_identity(); + if (persProject) + gl_frustum(-ar, ar, -1.f, 1.f, 2.f, 100.f); + else + gl_ortho(-ar*3, ar*3, -3.f, 3.f, 2.f, 100.f); + gl_UniformMatrix4fv (uniform_p, 1, GL_FALSE, get_matrix(GL_PROJECTION)); + + + gl_matrix_mode(GL_MODELVIEW); + gl_load_identity(); + + gl_push_matrix(); + /* Not in reverse order like normal OpenGL, matrices are multiplied in in order specified in our util library */ + gl_rotatef((float)a,0,0,1); + gl_rotatef((float)b,1,0,0); + gl_translatef(0,1.2f,-6); + gl_UniformMatrix4fv (uniform_m , 1, GL_FALSE, get_matrix(GL_MODELVIEW)); + gl_UniformMatrix3fv (uniform_m_3x3_inv_transp, 1, GL_FALSE, get_inv_transpose_3x3(GL_MODELVIEW)); + table [function_index].solid (); + gl_pop_matrix(); + + gl_push_matrix(); + gl_rotatef((float)a,0,0,1); + gl_rotatef((float)b,1,0,0); + gl_translatef(0,-1.2f,-6); + gl_UniformMatrix4fv (uniform_m , 1, GL_FALSE, get_matrix(GL_MODELVIEW)); + gl_UniformMatrix3fv (uniform_m_3x3_inv_transp, 1, GL_FALSE, get_inv_transpose_3x3(GL_MODELVIEW)); + table [function_index].wire (); + gl_pop_matrix(); + + gl_UseProgram (0); + glutSetVertexAttribCoord3(-1); + glutSetVertexAttribNormal(-1); + } + else + { + /* fixed function pipeline */ + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + if (persProject) + glFrustum(-ar, ar, -1.0, 1.0, 2.0, 100.0); + else + glOrtho(-ar*3, ar*3, -3.0, 3.0, 2.0, 100.0); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + glEnable(GL_LIGHTING); + + glColor3d(1,0,0); + + glPushMatrix(); + glTranslated(0,1.2,-6); + glRotated(b,1,0,0); + glRotated(a,0,0,1); + table [function_index].solid (); + glPopMatrix(); + + glPushMatrix(); + glTranslated(0,-1.2,-6); + glRotated(b,1,0,0); + glRotated(a,0,0,1); + table [function_index].wire (); + glPopMatrix(); + + glDisable(GL_LIGHTING); + glColor3d(0.1,0.1,0.4); + } if( show_info ) { shapesPrintf (1, 1, "Shape PgUp PgDn: %s", table [function_index].name); @@ -295,6 +669,14 @@ static void display(void) shapesPrintf (4, 1, "Depth (): %d", depth); 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"); + else + shapesPrintf (7, 1, "Orthographic projection"); + if (useShader) + shapesPrintf (8, 1, "Using shader"); + else + shapesPrintf (8, 1, "Using fixed function pipeline"); } else { printf ( "Shape %d slides %d stacks %d\n", function_index, slices, stacks ) ; } @@ -313,7 +695,7 @@ key(unsigned char key, int x, int y) case 'q': glutLeaveMainLoop () ; break; case 'I': - case 'i': show_info = ( show_info == GL_TRUE ) ? GL_FALSE : GL_TRUE; break; + case 'i': show_info=!show_info; break; case '=': case '+': slices++; break; @@ -339,6 +721,9 @@ key(unsigned char key, int x, int y) case 'R': case 'r': animateXRot=!animateXRot; break; + case 'S': + case 's': useShader=!useShader; break; + default: break; } @@ -427,6 +812,8 @@ main(int argc, char *argv[]) glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular); glMaterialfv(GL_FRONT, GL_SHININESS, high_shininess); + initExtensionEntries(); + glutMainLoop(); #ifdef _MSC_VER