├── .gitignore ├── CMakeLists.txt ├── README.md ├── opengl.h ├── data ├── shader.vp └── shader.fp ├── main.c ├── shader.c └── scene.c /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | glsl_lighting 3 | *~ 4 | build 5 | cmake_install* 6 | CMakeC* 7 | CMakeF* 8 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | cmake_minimum_required(VERSION 2.8) 3 | 4 | if(APPLE) 5 | add_definitions(-DAPPLE) 6 | endif(APPLE) 7 | 8 | find_package(OpenGL) 9 | find_package(GLUT) 10 | 11 | set(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR}"/bin") 12 | 13 | include_directories( 14 | ${OPENGL_INCLUDE_DIR} 15 | ${GLUT_INCLUDE_DIR} 16 | ) 17 | 18 | add_executable(glsl_lighting 19 | ./main.c 20 | ./scene.c 21 | ./shader.c 22 | ) 23 | target_link_libraries(glsl_lighting 24 | m 25 | ${OPENGL_gl_LIBRARY} 26 | ${GLUT_glut_LIBRARY} 27 | ) 28 | 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | glsl_lighting 2 | ============= 3 | 4 | This is an OpenGL demo featuring simple per-pixel diffuse/specular lighting using vertex/fragment shaders written in GLSL. It was created for the tutorial [Getting Started with the OpenGL Shading Language](http://joshbeam.com/articles/getting_started_with_glsl/) by [Josh Beam](https://github.com/joshb). 5 | 6 | This program uses the [CMake](https://cmake.org/) build system. Run the following commands from the directory containing the source code to build and run the program: 7 | 8 | mkdir build && cd build 9 | cmake .. && make 10 | ./glsl_lighting 11 | 12 | This program is released under a BSD-style license. You can find the copyright notice and license conditions at the beginning of any of the source code files (such as main.c). 13 | 14 | Contributors 15 | ------------ 16 | * [Julian Straub](https://github.com/jstraub) - added CMake support 17 | -------------------------------------------------------------------------------- /opengl.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 Josh A. Beam 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 18 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 20 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 21 | * WHETHER IN CONTACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 22 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 23 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #ifndef __OPENGL_H__ 27 | #define __OPENGL_H__ 28 | 29 | #ifdef APPLE 30 | #include 31 | #include 32 | #include 33 | #else 34 | #include 35 | #include 36 | #include 37 | #endif /* APPLE */ 38 | 39 | #endif /* __OPENGL_H__ */ 40 | -------------------------------------------------------------------------------- /data/shader.vp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 Josh A. Beam 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 18 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 20 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 21 | * WHETHER IN CONTACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 22 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 23 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | const int NUM_LIGHTS = 3; 27 | 28 | uniform vec3 cameraPosition; 29 | uniform vec3 lightPosition[NUM_LIGHTS]; 30 | 31 | varying vec3 fragmentNormal; 32 | varying vec3 cameraVector; 33 | varying vec3 lightVector[NUM_LIGHTS]; 34 | 35 | void 36 | main() 37 | { 38 | // set the normal for the fragment shader and 39 | // the vector from the vertex to the camera 40 | fragmentNormal = gl_Normal; 41 | cameraVector = cameraPosition - gl_Vertex.xyz; 42 | 43 | // set the vectors from the vertex to each light 44 | for(int i = 0; i < NUM_LIGHTS; ++i) 45 | lightVector[i] = lightPosition[i] - gl_Vertex.xyz; 46 | 47 | // output the transformed vertex 48 | gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; 49 | } 50 | -------------------------------------------------------------------------------- /data/shader.fp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 Josh A. Beam 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 18 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 20 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 21 | * WHETHER IN CONTACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 22 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 23 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | const int NUM_LIGHTS = 3; 27 | const vec3 AMBIENT = vec3(0.1, 0.1, 0.1); 28 | const float MAX_DIST = 2.5; 29 | const float MAX_DIST_SQUARED = MAX_DIST * MAX_DIST; 30 | 31 | uniform vec3 lightColor[NUM_LIGHTS]; 32 | 33 | varying vec3 fragmentNormal; 34 | varying vec3 cameraVector; 35 | varying vec3 lightVector[NUM_LIGHTS]; 36 | 37 | void 38 | main() 39 | { 40 | // initialize diffuse/specular lighting 41 | vec3 diffuse = vec3(0.0, 0.0, 0.0); 42 | vec3 specular = vec3(0.0, 0.0, 0.0); 43 | 44 | // normalize the fragment normal and camera direction 45 | vec3 normal = normalize(fragmentNormal); 46 | vec3 cameraDir = normalize(cameraVector); 47 | 48 | // loop through each light 49 | for(int i = 0; i < NUM_LIGHTS; ++i) { 50 | // calculate distance between 0.0 and 1.0 51 | float dist = min(dot(lightVector[i], lightVector[i]), MAX_DIST_SQUARED) / MAX_DIST_SQUARED; 52 | float distFactor = 1.0 - dist; 53 | 54 | // diffuse 55 | vec3 lightDir = normalize(lightVector[i]); 56 | float diffuseDot = dot(normal, lightDir); 57 | diffuse += lightColor[i] * clamp(diffuseDot, 0.0, 1.0) * distFactor; 58 | 59 | // specular 60 | vec3 halfAngle = normalize(cameraDir + lightDir); 61 | vec3 specularColor = min(lightColor[i] + 0.5, 1.0); 62 | float specularDot = dot(normal, halfAngle); 63 | specular += specularColor * pow(clamp(specularDot, 0.0, 1.0), 16.0) * distFactor; 64 | } 65 | 66 | vec4 sample = vec4(1.0, 1.0, 1.0, 1.0); 67 | gl_FragColor = vec4(clamp(sample.rgb * (diffuse + AMBIENT) + specular, 0.0, 1.0), sample.a); 68 | } 69 | -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 Josh A. Beam 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 18 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 20 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 21 | * WHETHER IN CONTACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 22 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 23 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include "opengl.h" 30 | 31 | static const int WINDOW_WIDTH = 400; 32 | static const int WINDOW_HEIGHT = 300; 33 | 34 | /* scene functions defined in scene.c */ 35 | extern void sceneInit(void); 36 | extern void sceneRender(void); 37 | extern void sceneCycle(void); 38 | 39 | static int g_window; 40 | 41 | static void 42 | handleKeyPress(unsigned char key, int x, int y) 43 | { 44 | switch(key) { 45 | default: 46 | break; 47 | case 27: /* escape */ 48 | glutDestroyWindow(g_window); 49 | exit(0); 50 | break; 51 | } 52 | } 53 | 54 | static void 55 | setPerspective(float fov, float aspect, float near, float far) 56 | { 57 | float f; 58 | float mat[16]; 59 | 60 | f = 1.0f / tanf(fov / 2.0f); 61 | 62 | mat[0] = f / aspect; 63 | mat[1] = 0.0f; 64 | mat[2] = 0.0f; 65 | mat[3] = 0.0f; 66 | 67 | mat[4] = 0.0f; 68 | mat[5] = f; 69 | mat[6] = 0.0f; 70 | mat[7] = 0.0f; 71 | 72 | mat[8] = 0.0f; 73 | mat[9] = 0.0f; 74 | mat[10] = (far + near) / (near - far); 75 | mat[11] = -1.0f; 76 | 77 | mat[12] = 0.0f; 78 | mat[13] = 0.0f; 79 | mat[14] = (2.0f * far * near) / (near - far); 80 | mat[15] = 0.0f; 81 | 82 | glMultMatrixf(mat); 83 | } 84 | 85 | int 86 | main(int argc, char *argv[]) 87 | { 88 | /* initialize GLUT */ 89 | glutInit(&argc, argv); 90 | glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH); 91 | glutInitWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT); 92 | g_window = glutCreateWindow("OpenGL demo - http://joshbeam.com/"); 93 | 94 | /* setup callbacks */ 95 | glutDisplayFunc(sceneRender); 96 | glutIdleFunc(sceneCycle); 97 | glutKeyboardFunc(handleKeyPress); 98 | 99 | /* setup initial GL settings */ 100 | glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 101 | glClearDepth(1.0f); 102 | glDisable(GL_BLEND); 103 | glEnable(GL_DEPTH_TEST); 104 | glDepthFunc(GL_LEQUAL); 105 | glEnable(GL_CULL_FACE); 106 | glFrontFace(GL_CCW); 107 | glCullFace(GL_BACK); 108 | 109 | /* set projection matrix */ 110 | glMatrixMode(GL_PROJECTION); 111 | glLoadIdentity(); 112 | setPerspective(M_PI / 4.0f, (float)WINDOW_WIDTH / (float)WINDOW_HEIGHT, 0.1f, 200.0f); 113 | glMatrixMode(GL_MODELVIEW); 114 | 115 | /* initialize scene and start GLUT main loop */ 116 | sceneInit(); 117 | glutMainLoop(); 118 | return 0; 119 | } 120 | -------------------------------------------------------------------------------- /shader.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 Josh A. Beam 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 18 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 20 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 21 | * WHETHER IN CONTACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 22 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 23 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include "opengl.h" 30 | 31 | /* 32 | * Returns a string containing the text in 33 | * a vertex/fragment shader source file. 34 | */ 35 | static char * 36 | shaderLoadSource(const char *filePath) 37 | { 38 | const size_t blockSize = 512; 39 | FILE *fp; 40 | char buf[blockSize]; 41 | char *source = NULL; 42 | size_t tmp, sourceLength = 0; 43 | 44 | /* open file */ 45 | fp = fopen(filePath, "r"); 46 | if(!fp) { 47 | fprintf(stderr, "shaderLoadSource(): Unable to open %s for reading\n", filePath); 48 | return NULL; 49 | } 50 | 51 | /* read the entire file into a string */ 52 | while((tmp = fread(buf, 1, blockSize, fp)) > 0) { 53 | char *newSource = malloc(sourceLength + tmp + 1); 54 | if(!newSource) { 55 | fprintf(stderr, "shaderLoadSource(): malloc failed\n"); 56 | if(source) 57 | free(source); 58 | return NULL; 59 | } 60 | 61 | if(source) { 62 | memcpy(newSource, source, sourceLength); 63 | free(source); 64 | } 65 | memcpy(newSource + sourceLength, buf, tmp); 66 | 67 | source = newSource; 68 | sourceLength += tmp; 69 | } 70 | 71 | /* close the file and null terminate the string */ 72 | fclose(fp); 73 | if(source) 74 | source[sourceLength] = '\0'; 75 | 76 | return source; 77 | } 78 | 79 | /* 80 | * Returns a shader object containing a shader 81 | * compiled from the given GLSL shader file. 82 | */ 83 | static GLuint 84 | shaderCompileFromFile(GLenum type, const char *filePath) 85 | { 86 | char *source; 87 | GLuint shader; 88 | GLint length, result; 89 | 90 | /* get shader source */ 91 | source = shaderLoadSource(filePath); 92 | if(!source) 93 | return 0; 94 | 95 | /* create shader object, set the source, and compile */ 96 | shader = glCreateShader(type); 97 | length = strlen(source); 98 | glShaderSource(shader, 1, (const char **)&source, &length); 99 | glCompileShader(shader); 100 | free(source); 101 | 102 | /* make sure the compilation was successful */ 103 | glGetShaderiv(shader, GL_COMPILE_STATUS, &result); 104 | if(result == GL_FALSE) { 105 | char *log; 106 | 107 | /* get the shader info log */ 108 | glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length); 109 | log = malloc(length); 110 | glGetShaderInfoLog(shader, length, &result, log); 111 | 112 | /* print an error message and the info log */ 113 | fprintf(stderr, "shaderCompileFromFile(): Unable to compile %s: %s\n", filePath, log); 114 | free(log); 115 | 116 | glDeleteShader(shader); 117 | return 0; 118 | } 119 | 120 | return shader; 121 | } 122 | 123 | /* 124 | * Compiles and attaches a shader of the 125 | * given type to the given program object. 126 | */ 127 | void 128 | shaderAttachFromFile(GLuint program, GLenum type, const char *filePath) 129 | { 130 | /* compile the shader */ 131 | GLuint shader = shaderCompileFromFile(type, filePath); 132 | if(shader != 0) { 133 | /* attach the shader to the program */ 134 | glAttachShader(program, shader); 135 | 136 | /* delete the shader - it won't actually be 137 | * destroyed until the program that it's attached 138 | * to has been destroyed */ 139 | glDeleteShader(shader); 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /scene.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 Josh A. Beam 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 18 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 20 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 21 | * WHETHER IN CONTACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 22 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 23 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #ifdef _WIN32 30 | #include 31 | #include 32 | #define GLUT_DISABLE_ATEXIT_HACK 33 | #else 34 | #include 35 | #endif /* _WIN32 */ 36 | #include "opengl.h" 37 | 38 | /* shader functions defined in shader.c */ 39 | extern void shaderAttachFromFile(GLuint, GLenum, const char *); 40 | 41 | static GLuint g_program; 42 | static GLuint g_programCameraPositionLocation; 43 | static GLuint g_programLightPositionLocation; 44 | static GLuint g_programLightColorLocation; 45 | 46 | static GLuint g_cylinderBufferId; 47 | static unsigned int g_cylinderNumVertices; 48 | 49 | static float g_cameraPosition[3]; 50 | 51 | #define NUM_LIGHTS 3 52 | static float g_lightPosition[NUM_LIGHTS * 3]; 53 | static float g_lightColor[NUM_LIGHTS * 3]; 54 | static float g_lightRotation; 55 | 56 | static void 57 | createCylinder(unsigned int divisions) 58 | { 59 | const int floatsPerVertex = 6; 60 | unsigned int i, size; 61 | float *v; 62 | 63 | g_cylinderNumVertices = (divisions + 1) * 2; 64 | size = floatsPerVertex * g_cylinderNumVertices; 65 | 66 | /* generate vertex data */ 67 | v = malloc(sizeof(float) * size); 68 | for(i = 0; i <= divisions; ++i) { 69 | float r = ((M_PI * 2.0f) / (float)divisions) * (float)i; 70 | unsigned int index1 = i * 2 * floatsPerVertex; 71 | unsigned int index2 = index1 + floatsPerVertex; 72 | 73 | /* vertex positions */ 74 | v[index1 + 0] = cosf(r); 75 | v[index1 + 1] = 1.0f; 76 | v[index1 + 2] = -sinf(r); 77 | v[index2 + 0] = cosf(r); 78 | v[index2 + 1] = -1.0f; 79 | v[index2 + 2] = -sinf(r); 80 | 81 | /* normals */ 82 | v[index1 + 3] = cosf(r); 83 | v[index1 + 4] = 0.0f; 84 | v[index1 + 5] = -sinf(r); 85 | v[index2 + 3] = v[index1 + 3]; 86 | v[index2 + 4] = v[index1 + 4]; 87 | v[index2 + 5] = v[index1 + 5]; 88 | } 89 | 90 | /* create vertex buffer */ 91 | glGenBuffers(1, &g_cylinderBufferId); 92 | glBindBuffer(GL_ARRAY_BUFFER, g_cylinderBufferId); 93 | glBufferData(GL_ARRAY_BUFFER, sizeof(float) * size, v, GL_STATIC_DRAW); 94 | free(v); 95 | 96 | /* enable arrays */ 97 | glEnableClientState(GL_VERTEX_ARRAY); 98 | glEnableClientState(GL_NORMAL_ARRAY); 99 | 100 | /* set pointers */ 101 | glVertexPointer(3, GL_FLOAT, sizeof(float) * floatsPerVertex, 0); 102 | glNormalPointer(GL_FLOAT, sizeof(float) * floatsPerVertex, (const GLvoid *)(sizeof(float) * 3)); 103 | } 104 | 105 | void sceneCycle(void); 106 | 107 | void 108 | sceneInit(void) 109 | { 110 | GLint result; 111 | 112 | /* create program object and attach shaders */ 113 | g_program = glCreateProgram(); 114 | shaderAttachFromFile(g_program, GL_VERTEX_SHADER, "../data/shader.vp"); 115 | shaderAttachFromFile(g_program, GL_FRAGMENT_SHADER, "../data/shader.fp"); 116 | 117 | /* link the program and make sure that there were no errors */ 118 | glLinkProgram(g_program); 119 | glGetProgramiv(g_program, GL_LINK_STATUS, &result); 120 | if(result == GL_FALSE) { 121 | GLint length; 122 | char *log; 123 | 124 | /* get the program info log */ 125 | glGetProgramiv(g_program, GL_INFO_LOG_LENGTH, &length); 126 | log = malloc(length); 127 | glGetProgramInfoLog(g_program, length, &result, log); 128 | 129 | /* print an error message and the info log */ 130 | fprintf(stderr, "sceneInit(): Program linking failed: %s\n", log); 131 | free(log); 132 | 133 | /* delete the program */ 134 | glDeleteProgram(g_program); 135 | g_program = 0; 136 | } 137 | 138 | /* get uniform locations */ 139 | g_programCameraPositionLocation = glGetUniformLocation(g_program, "cameraPosition"); 140 | g_programLightPositionLocation = glGetUniformLocation(g_program, "lightPosition"); 141 | g_programLightColorLocation = glGetUniformLocation(g_program, "lightColor"); 142 | 143 | /* set up red/green/blue lights */ 144 | g_lightColor[0] = 1.0f; g_lightColor[1] = 0.0f; g_lightColor[2] = 0.0f; 145 | g_lightColor[3] = 0.0f; g_lightColor[4] = 1.0f; g_lightColor[5] = 0.0f; 146 | g_lightColor[6] = 0.0f; g_lightColor[7] = 0.0f; g_lightColor[8] = 1.0f; 147 | 148 | /* create cylinder */ 149 | createCylinder(36); 150 | 151 | /* do the first cycle to initialize positions */ 152 | g_lightRotation = 0.0f; 153 | sceneCycle(); 154 | 155 | /* setup camera */ 156 | g_cameraPosition[0] = 0.0f; 157 | g_cameraPosition[1] = 0.0f; 158 | g_cameraPosition[2] = 4.0f; 159 | glLoadIdentity(); 160 | glTranslatef(-g_cameraPosition[0], -g_cameraPosition[1], -g_cameraPosition[2]); 161 | } 162 | 163 | void 164 | sceneRender(void) 165 | { 166 | int i; 167 | 168 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 169 | 170 | /* enable program and set uniform variables */ 171 | glUseProgram(g_program); 172 | glUniform3fv(g_programCameraPositionLocation, 1, g_cameraPosition); 173 | glUniform3fv(g_programLightPositionLocation, NUM_LIGHTS, g_lightPosition); 174 | glUniform3fv(g_programLightColorLocation, NUM_LIGHTS, g_lightColor); 175 | 176 | /* render the cylinder */ 177 | glDrawArrays(GL_TRIANGLE_STRIP, 0, g_cylinderNumVertices); 178 | 179 | /* disable program */ 180 | glUseProgram(0); 181 | 182 | /* render each light */ 183 | for(i = 0; i < NUM_LIGHTS; ++i) { 184 | /* render sphere with the light's color/position */ 185 | glPushMatrix(); 186 | glTranslatef(g_lightPosition[i * 3 + 0], g_lightPosition[i * 3 + 1], g_lightPosition[i * 3 + 2]); 187 | glColor3fv(g_lightColor + (i * 3)); 188 | glutSolidSphere(0.04, 36, 36); 189 | glPopMatrix(); 190 | } 191 | 192 | glutSwapBuffers(); 193 | } 194 | 195 | static unsigned int 196 | getTicks(void) 197 | { 198 | #ifdef _WIN32 199 | return GetTickCount(); 200 | #else 201 | struct timeval t; 202 | 203 | gettimeofday(&t, NULL); 204 | 205 | return (t.tv_sec * 1000) + (t.tv_usec / 1000); 206 | #endif /* _WIN32 */ 207 | } 208 | 209 | void 210 | sceneCycle(void) 211 | { 212 | static unsigned int prevTicks = 0; 213 | unsigned int ticks; 214 | float secondsElapsed; 215 | int i; 216 | 217 | /* calculate the number of seconds that have 218 | * passed since the last call to this function */ 219 | if(prevTicks == 0) 220 | prevTicks = getTicks(); 221 | ticks = getTicks(); 222 | secondsElapsed = (float)(ticks - prevTicks) / 1000.0f; 223 | prevTicks = ticks; 224 | 225 | /* update the light positions */ 226 | g_lightRotation += (M_PI / 4.0f) * secondsElapsed; 227 | for(i = 0; i < NUM_LIGHTS; ++i) { 228 | const float radius = 1.75f; 229 | float r = (((M_PI * 2.0f) / (float)NUM_LIGHTS) * (float)i) + g_lightRotation; 230 | 231 | g_lightPosition[i * 3 + 0] = cosf(r) * radius; 232 | g_lightPosition[i * 3 + 1] = cosf(r) * sinf(r); 233 | g_lightPosition[i * 3 + 2] = sinf(r) * radius; 234 | } 235 | 236 | glutPostRedisplay(); 237 | } 238 | --------------------------------------------------------------------------------