examples

Toy examples in single C files.
git clone git://henryandlizzy.uk/examples
Log | Files | Refs

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 }