gl-lighting.c (4790B)
1 #include <GLFW/glfw3.h> 2 #include <assert.h> 3 #include <math.h> 4 5 #define DEFAULT_W 800 6 #define DEFAULT_H 450 7 8 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a))) 9 #define FOR_EACH(a, x) for (typeof(&*(a)) x = a; x < (a) + ARRAY_SIZE(a); ++x) 10 11 #define ENABLE_GUARD(x) glEnable(x); for (int i = 1; i--; glDisable(x)) 12 #define MATRIX_GUARD glPushMatrix(); for (int i = 1; i--; glPopMatrix()) 13 #define PROJECTION_GUARD glMatrixMode(GL_PROJECTION); for (int i = 1; i--; glMatrixMode(GL_MODELVIEW)) 14 #define DRAW_GUARD(mode) glBegin(mode); for (int i = 1; i--; glEnd()) 15 16 char const* __asan_default_options() { return "detect_leaks=0"; } 17 18 struct vertex 19 { 20 float colour[3]; 21 float vertex[3]; 22 } const octahedron_vertices[6] = 23 { 24 {{0,0,1}, {0 ,0 , .5}}, 25 {{0,1,0}, {0 , .5, 0}}, 26 {{0,1,1}, {-.5,0 , 0}}, 27 {{1,0,1}, {0 ,-.5, 0}}, 28 {{1,0,0}, { .5, 0, 0}}, 29 {{1,1,0}, {0 ,0 ,-.5}}, 30 }; 31 32 struct triangle 33 { 34 float normal[3]; 35 unsigned char index[3]; 36 } const octahedron_triangles[8] = { 37 {{-1, 1, 1}, {0,1,2}}, 38 {{-1,-1, 1}, {0,2,3}}, 39 {{ 1,-1, 1}, {0,3,4}}, 40 {{ 1, 1, 1}, {0,4,1}}, 41 {{ 1, 1,-1}, {5,1,4}}, 42 {{ 1,-1,-1}, {5,4,3}}, 43 {{-1,-1,-1}, {5,3,2}}, 44 {{-1, 1,-1}, {5,2,1}}, 45 }; 46 47 static void draw_octahedron() 48 { 49 glInterleavedArrays(GL_C3F_V3F, 0, octahedron_vertices); 50 FOR_EACH (octahedron_triangles, t) 51 { 52 glNormal3fv(t->normal); 53 glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_BYTE, t->index); 54 } 55 } 56 57 static void key_cb(GLFWwindow* w, int key, int /*scancode*/, int action, int /*mods*/) 58 { 59 if (action != GLFW_PRESS) 60 return; 61 switch (key) 62 { 63 case GLFW_KEY_ESCAPE: 64 glfwSetWindowShouldClose(w, GLFW_TRUE); 65 return; 66 case GLFW_KEY_F11: 67 GLFWmonitor* monitor = glfwGetWindowMonitor(w); 68 if (!monitor) 69 { 70 monitor = glfwGetPrimaryMonitor(); 71 GLFWvidmode const* mode = glfwGetVideoMode(monitor); 72 glfwSetWindowMonitor(w, monitor, 0, 0, mode->width, mode->height, mode->refreshRate); 73 } else 74 glfwSetWindowMonitor(w, NULL, 0, 0, DEFAULT_W, DEFAULT_H, GLFW_DONT_CARE); 75 return; 76 case GLFW_KEY_F10: 77 return; 78 } 79 } 80 81 static void set_frustum_size(int w, int h) 82 { 83 double fru_horz = w / sqrt(w*w + h*h); 84 double fru_vert = h / sqrt(w*w + h*h); 85 86 PROJECTION_GUARD 87 { 88 glLoadIdentity(); 89 glFrustum(-fru_horz, fru_horz, -fru_vert, fru_vert, 1.5, 8); 90 glTranslated(0, 0, -5); 91 } 92 } 93 94 static void fb_resize_cb(GLFWwindow*, int w, int h) 95 { 96 glViewport(0, 0, w, h); 97 set_frustum_size(w, h); 98 } 99 100 static float const ambient_light[4] = {.1, .1, .1, 1}; 101 static float const light_colour[4] = {1, 1, 1, 1}; 102 static float const material_specular[4] = {.000001, .000001, .000001, 1}; 103 static float light_position0[4] = {0, 0, 1, 1}; 104 static float light_position1[4] = {-.5, -.5, 1.6, 1}; 105 106 int main(int, char* argv[]) 107 { 108 assert(glfwInit()); 109 GLFWwindow* window = glfwCreateWindow(DEFAULT_W, DEFAULT_H, argv[0], NULL, NULL); 110 assert(window); 111 glfwMakeContextCurrent(window); 112 set_frustum_size(DEFAULT_W, DEFAULT_H); 113 glfwSetKeyCallback(window, key_cb); 114 glfwSetFramebufferSizeCallback(window, fb_resize_cb); 115 glfwSwapInterval(1); 116 glClearColor(0, 0, 0, 1); 117 glEnable(GL_CULL_FACE); 118 glEnable(GL_DEPTH_TEST); 119 glEnable(GL_RESCALE_NORMAL); 120 121 for (GLuint light = GL_LIGHT0; light <= GL_LIGHT1; ++light) 122 { 123 glEnable(light); 124 glLightfv(light, GL_DIFFUSE, light_colour); 125 glLightfv(light, GL_SPECULAR, light_colour); 126 } 127 128 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient_light); 129 130 glEnable(GL_COLOR_MATERIAL); 131 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); 132 glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, 24); 133 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, material_specular); 134 glPointSize(10); 135 glEnable(GL_POINT_SMOOTH); 136 137 while (!glfwWindowShouldClose(window)) 138 { 139 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 140 141 double t = glfwGetTime() / 8; 142 double turns = t * 6.283185307; 143 double deg = t * 360; 144 145 glLoadIdentity(); 146 glTranslated(0, -.2, 0); 147 glRotated(-60, 1, 0, 0); 148 glRotated(deg / 7, 0, 0, 1); 149 150 light_position0[0] = -sin(2*turns)*1.5; 151 light_position0[1] = -cos(2*turns)*1.5; 152 153 glLightfv(GL_LIGHT0, GL_POSITION, light_position0); 154 glLightfv(GL_LIGHT1, GL_POSITION, light_position1); 155 156 DRAW_GUARD(GL_POINTS) 157 glColor4fv(light_colour), glVertex4fv(light_position0), glVertex4fv(light_position1); 158 159 ENABLE_GUARD(GL_LIGHTING) 160 { 161 MATRIX_GUARD 162 { 163 glRotated(deg, 0, 0, 1); 164 draw_octahedron(); 165 } 166 167 MATRIX_GUARD 168 { 169 glTranslated(0, 0, 1); 170 glRotated(90, 0, 0, 1); 171 draw_octahedron(); 172 } 173 174 MATRIX_GUARD 175 { 176 glTranslated(0, 0, -1); 177 glRotated(-90, 0, 0, 1); 178 draw_octahedron(); 179 } 180 181 MATRIX_GUARD 182 { 183 glTranslated(sin(2*turns), cos(2*turns), sin(turns)); 184 glRotated(180+deg, 0, 0, 1); 185 draw_octahedron(); 186 } 187 } 188 189 glfwSwapBuffers(window); 190 glfwPollEvents(); 191 } 192 glfwTerminate(); /* Implicit window destroy */ 193 }