refmod_test
changeset 0:b469e6a72636
initial commit
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Thu, 18 Feb 2016 23:15:43 +0200 |
parents | |
children | 7e911c994ef2 |
files | Makefile refmod_test.c sdr.c sdr.h sdr.ps.glsl sdr.vs.glsl sdr_ref_models.glsl |
diffstat | 7 files changed, 1046 insertions(+), 0 deletions(-) [+] |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/Makefile Thu Feb 18 23:15:43 2016 +0200 1.3 @@ -0,0 +1,18 @@ 1.4 +obj = refmod_test.o sdr.o 1.5 +bin = refmod_test 1.6 +distfile = refmod_test.tar.gz 1.7 + 1.8 +CC = gcc 1.9 +CFLAGS = -pedantic -Wall -g 1.10 +LDFLAGS = -lglut -lGL -lGLU 1.11 + 1.12 +$(bin): $(obj) 1.13 + $(CC) -o $@ $(obj) $(LDFLAGS) 1.14 + 1.15 +.PHONY: clean 1.16 +clean: 1.17 + rm -f $(obj) $(bin) 1.18 + 1.19 +.PHONY: dist 1.20 +dist: clean 1.21 + cd ..; tar czvf $(distfile) refmod_test && mv $(distfile) refmod_test/$(distfile)
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/refmod_test.c Thu Feb 18 23:15:43 2016 +0200 2.3 @@ -0,0 +1,387 @@ 2.4 +#include <stdio.h> 2.5 +#include <stdlib.h> 2.6 +#include <string.h> 2.7 +#include <GL/glut.h> 2.8 +#include "sdr.h" 2.9 + 2.10 +#ifdef FREEGLUT 2.11 +#include <GL/freeglut_ext.h> 2.12 +#define MOUSEWHEEL 2.13 +#endif 2.14 + 2.15 +void redraw(void); 2.16 +void set_material_color(float r, float g, float b, float a); 2.17 +void setup_lights(void); 2.18 +void key_handler(unsigned char key, int x, int y); 2.19 +void key_up_handler(unsigned char key, int x, int y); 2.20 +void skey_handler(int key, int x, int y); 2.21 +void button_handler(int bn, int state, int x, int y); 2.22 +void mouse_handler(int x, int y); 2.23 +void reshape(int x, int y); 2.24 +#ifdef MOUSEWHEEL 2.25 +void wheel_handler(int unk, int dir, int x, int y); 2.26 +#endif 2.27 +void menu_handler(int val); 2.28 +void init_sdr(void); 2.29 + 2.30 +int xres, yres; 2.31 + 2.32 +float cam_x, cam_y = 0.6, cam_z = 4; 2.33 +float cam_rot, cam_pitch = 35.0; 2.34 + 2.35 +float pan_offs = 0.025; 2.36 + 2.37 +unsigned int prog; 2.38 + 2.39 +float roughness = 0.24; 2.40 +float specularity = 0.86; 2.41 +float ior = 3.2; 2.42 +float spec_pow = 60.0; 2.43 + 2.44 +enum {DSDR_LAMBERT, DSDR_OREN_NAYAR}; 2.45 +enum {SSDR_PHONG, SSDR_BLINN, SSDR_COOK_TORR}; 2.46 + 2.47 +int dif_sdr = DSDR_OREN_NAYAR; 2.48 +int spec_sdr = SSDR_COOK_TORR; 2.49 + 2.50 +int main(int argc, char **argv) 2.51 +{ 2.52 + unsigned int vs, ps, pslib; 2.53 + int dif_menu, spec_menu, i; 2.54 + 2.55 + for(i=1; i<argc; i++) { 2.56 + if(argv[i][0] == '-' && argv[i][2] == 0) { 2.57 + switch(argv[i][1]) { 2.58 + case 'd': 2.59 + if(strcmp(argv[++i], "lambert") == 0) { 2.60 + dif_sdr = DSDR_LAMBERT; 2.61 + } else if(strcmp(argv[i], "oren-nayar") == 0) { 2.62 + dif_sdr = DSDR_OREN_NAYAR; 2.63 + } else { 2.64 + printf("-d (diffuse model) choices:\n"); 2.65 + printf(" lambert \"Photometria sive de mensura de gratibus luminis, colorum et umbrae\", 1760\n"); 2.66 + printf(" oren-nayar \"Generalization of Lambert's Reflectance Model\", SIGGRAPH 1994\n"); 2.67 + return EXIT_FAILURE; 2.68 + } 2.69 + break; 2.70 + 2.71 + case 's': 2.72 + if(strcmp(argv[++i], "phong") == 0) { 2.73 + spec_sdr = SSDR_PHONG; 2.74 + } else if(strcmp(argv[i], "cook-torrance") == 0) { 2.75 + spec_sdr = SSDR_COOK_TORR; 2.76 + } else { 2.77 + printf("-s (specular model) choices:\n"); 2.78 + printf(" phong \"Illumination for Computer Generated Pictures\", CACM 1975\n"); 2.79 + printf(" blinn \"Models of Light Reflection for Computer Synthesized Pictures\", SIGGRAPH 1977\n"); 2.80 + printf(" cook-torrance \"A Reflectance Model for Computer Graphics\", SIGGRAPH 1981\n"); 2.81 + return EXIT_FAILURE; 2.82 + } 2.83 + break; 2.84 + 2.85 + default: 2.86 + fprintf(stderr, "unrecognized argument: %s\n", argv[i]); 2.87 + return EXIT_FAILURE; 2.88 + } 2.89 + } 2.90 + } 2.91 + 2.92 + glutInitWindowSize(800, 600); 2.93 + glutInit(&argc, argv); 2.94 + glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE); 2.95 + glutCreateWindow("1.roughness 2.specularity 3.ior 4.phong power"); 2.96 + xres = glutGet(GLUT_WINDOW_WIDTH); 2.97 + yres = glutGet(GLUT_WINDOW_HEIGHT); 2.98 + 2.99 + glutKeyboardFunc(key_handler); 2.100 + glutKeyboardUpFunc(key_up_handler); 2.101 + glutSpecialFunc(skey_handler); 2.102 + glutMotionFunc(mouse_handler); 2.103 + glutMouseFunc(button_handler); 2.104 + glutReshapeFunc(reshape); 2.105 + glutDisplayFunc(redraw); 2.106 +#ifdef MOUSEWHEEL 2.107 + glutMouseWheelFunc(wheel_handler); 2.108 +#endif 2.109 + 2.110 + /* create the menus */ 2.111 + dif_menu = glutCreateMenu(menu_handler); 2.112 + glutAddMenuEntry("lambert", DSDR_LAMBERT); 2.113 + glutAddMenuEntry("oren-nayar", DSDR_OREN_NAYAR); 2.114 + 2.115 + spec_menu = glutCreateMenu(menu_handler); 2.116 + glutAddMenuEntry("phong", SSDR_PHONG + 10); 2.117 + glutAddMenuEntry("blinn", SSDR_BLINN + 10); 2.118 + glutAddMenuEntry("cook-torrance", SSDR_COOK_TORR + 10); 2.119 + 2.120 + glutCreateMenu(menu_handler); 2.121 + glutAddSubMenu("diffuse models", dif_menu); 2.122 + glutAddSubMenu("specular models", spec_menu); 2.123 + 2.124 + glutAttachMenu(GLUT_RIGHT_BUTTON); 2.125 + 2.126 + 2.127 + glEnable(GL_DEPTH_TEST); 2.128 + glEnable(GL_CULL_FACE); 2.129 + 2.130 + glEnable(GL_LIGHTING); 2.131 + glEnable(GL_LIGHT0); 2.132 + 2.133 + glMatrixMode(GL_PROJECTION); 2.134 + gluPerspective(45.0, (float)xres / (float)yres, 1.0, 100.0); 2.135 + glMatrixMode(GL_MODELVIEW); 2.136 + 2.137 + init_sdr(); 2.138 + 2.139 + if(!(vs = load_vertex_shader("sdr.vs.glsl"))) { 2.140 + fprintf(stderr, "failed to load vertex shader\n"); 2.141 + return EXIT_FAILURE; 2.142 + } 2.143 + 2.144 + if(!(pslib = load_pixel_shader("sdr_ref_models.glsl"))) { 2.145 + fprintf(stderr, "failed to load reflection models shader\n"); 2.146 + return EXIT_FAILURE; 2.147 + } 2.148 + 2.149 + if(!(ps = load_pixel_shader("sdr.ps.glsl"))) { 2.150 + fprintf(stderr, "failed to load pixel shader\n"); 2.151 + return EXIT_FAILURE; 2.152 + } 2.153 + 2.154 + if(!(prog = create_program())) { 2.155 + fprintf(stderr, "failed to create GPU program\n"); 2.156 + return EXIT_FAILURE; 2.157 + } 2.158 + attach_shader(prog, vs); 2.159 + attach_shader(prog, pslib); 2.160 + attach_shader(prog, ps); 2.161 + 2.162 + if(link_program(prog) == -1) { 2.163 + fprintf(stderr, "failed to link GPU program\n"); 2.164 + return EXIT_FAILURE; 2.165 + } 2.166 + 2.167 + glutMainLoop(); 2.168 + return 0; 2.169 +} 2.170 + 2.171 +void setup_lights(void) 2.172 +{ 2.173 + float lpos[] = {-6, 8, 10, 1}; 2.174 + glLightfv(GL_LIGHT0, GL_POSITION, lpos); 2.175 +} 2.176 + 2.177 +void redraw(void) 2.178 +{ 2.179 + glClearColor(0, 0, 0, 0); 2.180 + glClearDepth(1.0); 2.181 + 2.182 + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 2.183 + 2.184 + glMatrixMode(GL_MODELVIEW); 2.185 + glLoadIdentity(); 2.186 + glTranslatef(-cam_x, -cam_y, -cam_z); 2.187 + glRotatef(cam_pitch, 1, 0, 0); 2.188 + glRotatef(cam_rot, 0, 1, 0); 2.189 + 2.190 + setup_lights(); 2.191 + 2.192 + glPushMatrix(); 2.193 + glTranslatef(0, 0.8, 0); 2.194 + 2.195 + bind_program(prog); 2.196 + set_uniform_float(prog, "rough", roughness); 2.197 + set_uniform_float(prog, "specularity", specularity); 2.198 + set_uniform_float(prog, "ior", ior); 2.199 + set_uniform_float(prog, "dif_sdr", dif_sdr); 2.200 + set_uniform_float(prog, "spec_sdr", spec_sdr); 2.201 + glFrontFace(GL_CW); 2.202 + set_material_color(0.55, 0.20, 0.10, 1.0); 2.203 + /*set_material_color(0.87, 0.72, 0.62, 1.0);*/ 2.204 + glutSolidTeapot(1.0); 2.205 + glFrontFace(GL_CCW); 2.206 + bind_program(0); 2.207 + 2.208 + glPopMatrix(); 2.209 + 2.210 + 2.211 + glutSwapBuffers(); 2.212 +} 2.213 + 2.214 +void set_material_color(float r, float g, float b, float a) 2.215 +{ 2.216 + float col[4]; 2.217 + col[0] = r; 2.218 + col[1] = g; 2.219 + col[2] = b; 2.220 + col[3] = a; 2.221 + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, col); 2.222 + glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, spec_pow); 2.223 +} 2.224 + 2.225 +int mod_rough, mod_spec, mod_ior, mod_spow; 2.226 + 2.227 +void key_handler(unsigned char key, int x, int y) 2.228 +{ 2.229 + switch(key) { 2.230 + case 27: 2.231 + exit(0); 2.232 + 2.233 + case '1': 2.234 + mod_rough = 1; 2.235 + break; 2.236 + 2.237 + case '2': 2.238 + mod_spec = 1; 2.239 + break; 2.240 + 2.241 + case '3': 2.242 + mod_ior = 1; 2.243 + break; 2.244 + 2.245 + case '4': 2.246 + mod_spow = 1; 2.247 + break; 2.248 + 2.249 + default: 2.250 + break; 2.251 + } 2.252 +} 2.253 + 2.254 +void key_up_handler(unsigned char key, int x, int y) 2.255 +{ 2.256 + switch(key) { 2.257 + case '1': 2.258 + mod_rough = 0; 2.259 + break; 2.260 + 2.261 + case '2': 2.262 + mod_spec = 0; 2.263 + break; 2.264 + 2.265 + case '3': 2.266 + mod_ior = 0; 2.267 + break; 2.268 + 2.269 + case '4': 2.270 + mod_spow = 0; 2.271 + break; 2.272 + 2.273 + default: 2.274 + break; 2.275 + } 2.276 +} 2.277 + 2.278 +void skey_handler(int key, int x, int y) 2.279 +{ 2.280 + switch(key) { 2.281 + default: 2.282 + break; 2.283 + } 2.284 +} 2.285 + 2.286 +static int prev_x = -1; 2.287 +static int prev_y = -1; 2.288 +static int pbn; 2.289 + 2.290 +void button_handler(int button, int state, int x, int y) 2.291 +{ 2.292 + if(state == GLUT_DOWN) { 2.293 + prev_x = x; 2.294 + prev_y = y; 2.295 + pbn = button; 2.296 + } else { 2.297 + prev_x = -1; 2.298 + prev_y = -1; 2.299 + } 2.300 +} 2.301 + 2.302 + 2.303 +#define MIN(a, b) ((a) < (b) ? (a) : (b)) 2.304 +#define MAX(a, b) ((a) > (b) ? (a) : (b)) 2.305 + 2.306 +void mouse_handler(int x, int y) 2.307 +{ 2.308 + if(pbn == GLUT_LEFT_BUTTON) { 2.309 + if(mod_rough || mod_spec || mod_ior || mod_spow) { 2.310 + float dx = (float)(x - prev_x) / (float)xres; 2.311 + 2.312 + if(mod_rough) { 2.313 + roughness = MAX(0.0, MIN(roughness + dx, 1.0)); 2.314 + printf("roughness: %.3f\n", roughness); 2.315 + } 2.316 + if(mod_spec) { 2.317 + specularity = MAX(0.0, MIN(specularity + dx, 1.0)); 2.318 + printf("specularity: %.3f\n", specularity); 2.319 + } 2.320 + if(mod_ior) { 2.321 + ior = MAX(ior + dx, 0.0); 2.322 + printf("ior: %.3f\n", ior); 2.323 + } 2.324 + if(mod_spow) { 2.325 + spec_pow = MAX(spec_pow + dx * 50.0, 0.01); 2.326 + printf("specular power: %.3f\n", spec_pow); 2.327 + } 2.328 + } else { 2.329 + /* 2.330 + cam_x += (float)(prev_x - x) * pan_offs; 2.331 + cam_y += (float)(y - prev_y) * pan_offs; 2.332 + */ 2.333 + } 2.334 + 2.335 + prev_x = x; 2.336 + prev_y = y; 2.337 + glutPostRedisplay(); 2.338 + 2.339 + } else if(pbn == GLUT_MIDDLE_BUTTON) { 2.340 + cam_rot += (float)(x - prev_x) / 2.0f; 2.341 + cam_pitch += (float)(y - prev_y) / 2.0f; 2.342 + if(cam_pitch > 90.0) cam_pitch = 90.0; 2.343 + if(cam_pitch < -90.0) cam_pitch = -90.0; 2.344 + 2.345 + prev_x = x; 2.346 + prev_y = y; 2.347 + glutPostRedisplay(); 2.348 + 2.349 + } else if(pbn == GLUT_RIGHT_BUTTON) { 2.350 + /* 2.351 + cam_z -= (float)(prev_y - y) / 2.0f; 2.352 + prev_y = y; 2.353 + glutPostRedisplay(); 2.354 + */ 2.355 + } 2.356 +} 2.357 + 2.358 +void reshape(int x, int y) 2.359 +{ 2.360 + glViewport(0, 0, x, y); 2.361 + xres = x; 2.362 + yres = y; 2.363 + 2.364 + glMatrixMode(GL_PROJECTION); 2.365 + glLoadIdentity(); 2.366 + gluPerspective(45.0, (float)xres / (float)yres, 1.0, 100.0); 2.367 + glMatrixMode(GL_MODELVIEW); 2.368 +} 2.369 + 2.370 +#ifdef MOUSEWHEEL 2.371 +void wheel_handler(int unk, int dir, int x, int y) 2.372 +{ 2.373 + if(dir > 0) { 2.374 + cam_z -= pan_offs * 5.0; 2.375 + } else { 2.376 + cam_z += pan_offs * 5.0; 2.377 + } 2.378 + glutPostRedisplay(); 2.379 +} 2.380 +#endif 2.381 + 2.382 +void menu_handler(int val) 2.383 +{ 2.384 + if(val < 10) { 2.385 + dif_sdr = val; 2.386 + } else { 2.387 + spec_sdr = val - 10; 2.388 + } 2.389 + glutPostRedisplay(); 2.390 +}
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/sdr.c Thu Feb 18 23:15:43 2016 +0200 3.3 @@ -0,0 +1,417 @@ 3.4 +#include <stdio.h> 3.5 +#include <stdlib.h> 3.6 +#include <string.h> 3.7 +#include <errno.h> 3.8 +#include <assert.h> 3.9 + 3.10 +#if defined(unix) || defined(__unix__) 3.11 +#include <unistd.h> 3.12 +#include <sys/stat.h> 3.13 +#include <GL/glx.h> 3.14 +#endif /* unix */ 3.15 + 3.16 +#if defined(WIN32) || defined(__WIN32__) 3.17 +#include <windows.h> 3.18 + 3.19 +#define glXGetProcAddress wglGetProcAddress 3.20 +#endif /* windows */ 3.21 + 3.22 +#define GL_GLEXT_LEGACY 3.23 +#include <GL/gl.h> 3.24 + 3.25 +#include "sdr.h" 3.26 + 3.27 +#ifndef GL_VERSION_2_0 3.28 + 3.29 +#define GL_FRAGMENT_SHADER 0x8B30 3.30 +#define GL_VERTEX_SHADER 0x8B31 3.31 +#define GL_COMPILE_STATUS 0x8B81 3.32 +#define GL_LINK_STATUS 0x8B82 3.33 +#define GL_INFO_LOG_LENGTH 0x8B84 3.34 +#define GL_CURRENT_PROGRAM 0x8B8D 3.35 + 3.36 +typedef char GLchar; 3.37 + 3.38 +GLuint (*glCreateProgram)(void); 3.39 +GLuint (*glCreateShader)(GLenum); 3.40 +void (*glDeleteProgram)(GLuint); 3.41 +void (*glDeleteShader)(GLuint); 3.42 +void (*glCompileShader)(GLuint); 3.43 +void (*glAttachShader)(GLuint, GLuint); 3.44 +void (*glGetShaderiv)(GLuint, GLenum, GLint *); 3.45 +void (*glGetShaderInfoLog)(GLuint, GLsizei, GLsizei *, GLchar *); 3.46 +void (*glGetProgramiv)(GLuint, GLenum, GLint *); 3.47 +void (*glGetProgramInfoLog)(GLuint, GLsizei, GLsizei *, GLchar *); 3.48 +void (*glLinkProgram)(GLuint); 3.49 +void (*glShaderSource)(GLuint, GLsizei, const GLchar* *, const GLint *); 3.50 +void (*glUseProgram)(GLuint); 3.51 +GLint (*glGetUniformLocation)(GLuint, const GLchar *); 3.52 +void (*glUniform1f)(GLint, GLfloat); 3.53 +void (*glUniform2f)(GLint, GLfloat, GLfloat); 3.54 +void (*glUniform3f)(GLint, GLfloat, GLfloat, GLfloat); 3.55 +void (*glUniform4f)(GLint, GLfloat, GLfloat, GLfloat, GLfloat); 3.56 +void (*glUniform1i)(GLint, GLint); 3.57 +void (*glUniformMatrix4fv)(GLint, GLsizei, GLboolean, const GLfloat *); 3.58 +GLint (*glGetAttribLocation)(GLuint, const GLchar *); 3.59 +void (*glVertexAttrib3f)(GLint, GLfloat, GLfloat, GLfloat); 3.60 + 3.61 +void init_sdr(void) 3.62 +{ 3.63 + glCreateProgram = glXGetProcAddress("glCreateProgramObjectARB"); 3.64 + glCreateShader = glXGetProcAddress("glCreateShaderObjectARB"); 3.65 + glDeleteProgram = glXGetProcAddress("glDeleteObjectARB"); 3.66 + glDeleteShader = glXGetProcAddress("glDeleteObjectARB"); 3.67 + glCompileShader = glXGetProcAddress("glCompileShaderARB"); 3.68 + glAttachShader = glXGetProcAddress("glAttachObjectARB"); 3.69 + glGetShaderiv = glXGetProcAddress("glGetObjectParameterivARB"); 3.70 + glGetShaderInfoLog = glXGetProcAddress("glGetInfoLogARB"); 3.71 + glGetProgramiv = glXGetProcAddress("glGetObjectParameterivARB"); 3.72 + glGetProgramInfoLog = glXGetProcAddress("glGetInfoLogARB"); 3.73 + glLinkProgram = glXGetProcAddress("glLinkProgramARB"); 3.74 + glShaderSource = glXGetProcAddress("glShaderSourceARB"); 3.75 + glUseProgram = glXGetProcAddress("glUseProgramObjectARB"); 3.76 + glGetUniformLocation = glXGetProcAddress("glGetUniformLocationARB"); 3.77 + glUniform1f = glXGetProcAddress("glUniform1fARB"); 3.78 + glUniform2f = glXGetProcAddress("glUniform2fARB"); 3.79 + glUniform3f = glXGetProcAddress("glUniform3fARB"); 3.80 + glUniform4f = glXGetProcAddress("glUniform4fARB"); 3.81 + glUniform1i = glXGetProcAddress("glUniform1iARB"); 3.82 + glUniformMatrix4fv = glXGetProcAddress("glUniformMatrix4fvARB"); 3.83 + glGetAttribLocation = glXGetProcAddress("glGetAttribLocationARB"); 3.84 + glVertexAttrib3f = glXGetProcAddress("glVertexAttrib3fARB"); 3.85 +} 3.86 +#else 3.87 +void init_sdr(void) {} 3.88 +#endif 3.89 + 3.90 +unsigned int create_vertex_shader(const char *src) 3.91 +{ 3.92 + return create_shader(src, GL_VERTEX_SHADER); 3.93 +} 3.94 + 3.95 +unsigned int create_pixel_shader(const char *src) 3.96 +{ 3.97 + return create_shader(src, GL_FRAGMENT_SHADER); 3.98 +} 3.99 + 3.100 +unsigned int create_shader(const char *src, unsigned int sdr_type) 3.101 +{ 3.102 + unsigned int sdr; 3.103 + int success, info_len; 3.104 + char *info_str = 0; 3.105 + GLenum err; 3.106 + 3.107 + sdr = glCreateShader(sdr_type); 3.108 + assert(glGetError() == GL_NO_ERROR); 3.109 + glShaderSource(sdr, 1, &src, 0); 3.110 + err = glGetError(); 3.111 + assert(err == GL_NO_ERROR); 3.112 + glCompileShader(sdr); 3.113 + assert(glGetError() == GL_NO_ERROR); 3.114 + 3.115 + glGetShaderiv(sdr, GL_COMPILE_STATUS, &success); 3.116 + assert(glGetError() == GL_NO_ERROR); 3.117 + glGetShaderiv(sdr, GL_INFO_LOG_LENGTH, &info_len); 3.118 + assert(glGetError() == GL_NO_ERROR); 3.119 + 3.120 + if(info_len) { 3.121 + if((info_str = malloc(info_len + 1))) { 3.122 + glGetShaderInfoLog(sdr, info_len, 0, info_str); 3.123 + assert(glGetError() == GL_NO_ERROR); 3.124 + } 3.125 + } 3.126 + 3.127 + if(success) { 3.128 + fprintf(stderr, info_str ? "done: %s\n" : "done\n", info_str); 3.129 + } else { 3.130 + fprintf(stderr, info_str ? "failed: %s\n" : "failed\n", info_str); 3.131 + glDeleteShader(sdr); 3.132 + sdr = 0; 3.133 + } 3.134 + 3.135 + free(info_str); 3.136 + return sdr; 3.137 +} 3.138 + 3.139 +void free_shader(unsigned int sdr) 3.140 +{ 3.141 + glDeleteShader(sdr); 3.142 +} 3.143 + 3.144 +unsigned int load_vertex_shader(const char *fname) 3.145 +{ 3.146 + return load_shader(fname, GL_VERTEX_SHADER); 3.147 +} 3.148 + 3.149 +unsigned int load_pixel_shader(const char *fname) 3.150 +{ 3.151 + return load_shader(fname, GL_FRAGMENT_SHADER); 3.152 +} 3.153 + 3.154 +unsigned int load_shader(const char *fname, unsigned int sdr_type) 3.155 +{ 3.156 +#if defined(unix) || defined(__unix__) 3.157 + struct stat st; 3.158 +#endif 3.159 + unsigned int sdr; 3.160 + size_t filesize; 3.161 + FILE *fp; 3.162 + char *src; 3.163 + 3.164 + if(!(fp = fopen(fname, "r"))) { 3.165 + fprintf(stderr, "failed to open shader %s: %s\n", fname, strerror(errno)); 3.166 + return 0; 3.167 + } 3.168 + 3.169 +#if defined(unix) || defined(__unix__) 3.170 + fstat(fileno(fp), &st); 3.171 + filesize = st.st_size; 3.172 +#else 3.173 + fseek(fp, 0, SEEK_END); 3.174 + filesize = ftell(fp); 3.175 + fseek(fp, 0, SEEK_SET); 3.176 +#endif /* unix */ 3.177 + 3.178 + if(!(src = malloc(filesize + 1))) { 3.179 + fclose(fp); 3.180 + return 0; 3.181 + } 3.182 + fread(src, 1, filesize, fp); 3.183 + src[filesize] = 0; 3.184 + fclose(fp); 3.185 + 3.186 + fprintf(stderr, "compiling %s shader: %s... ", (sdr_type == GL_VERTEX_SHADER ? "vertex" : "pixel"), fname); 3.187 + sdr = create_shader(src, sdr_type); 3.188 + 3.189 + free(src); 3.190 + return sdr; 3.191 +} 3.192 + 3.193 + 3.194 +unsigned int get_vertex_shader(const char *fname) 3.195 +{ 3.196 + return get_shader(fname, GL_VERTEX_SHADER); 3.197 +} 3.198 + 3.199 +unsigned int get_pixel_shader(const char *fname) 3.200 +{ 3.201 + return get_shader(fname, GL_FRAGMENT_SHADER); 3.202 +} 3.203 + 3.204 +unsigned int get_shader(const char *fname, unsigned int sdr_type) 3.205 +{ 3.206 + unsigned int sdr; 3.207 +#if 0 3.208 + if((res = get_resource(sdrman, fname))) { 3.209 + /* TODO: validate that the shader matches sdr_type? */ 3.210 + return (uintptr_t)res; 3.211 + } 3.212 +#endif 3.213 + 3.214 + if(!(sdr = load_shader(fname, sdr_type))) { 3.215 + return 0; 3.216 + } 3.217 + add_shader(fname, sdr); 3.218 + return sdr; 3.219 +} 3.220 + 3.221 +int add_shader(const char *fname, unsigned int sdr) 3.222 +{ 3.223 + return 0;/*add_resource(sdrman, fname, (void*)(uintptr_t)sdr);*/ 3.224 +} 3.225 + 3.226 +int remove_shader(const char *fname) 3.227 +{ 3.228 + return 0;/*remove_resource(sdrman, fname);*/ 3.229 +} 3.230 + 3.231 + 3.232 +/* ---- gpu programs ---- */ 3.233 + 3.234 +unsigned int create_program(void) 3.235 +{ 3.236 + unsigned int prog = glCreateProgram(); 3.237 + assert(glGetError() == GL_NO_ERROR); 3.238 + return prog; 3.239 +} 3.240 + 3.241 +unsigned int create_program_link(unsigned int vs, unsigned int ps) 3.242 +{ 3.243 + unsigned int prog; 3.244 + 3.245 + if(!(prog = create_program())) { 3.246 + return 0; 3.247 + } 3.248 + 3.249 + attach_shader(prog, vs); 3.250 + assert(glGetError() == GL_NO_ERROR); 3.251 + attach_shader(prog, ps); 3.252 + assert(glGetError() == GL_NO_ERROR); 3.253 + 3.254 + if(link_program(prog) == -1) { 3.255 + free_program(prog); 3.256 + return 0; 3.257 + } 3.258 + return prog; 3.259 +} 3.260 + 3.261 +unsigned int create_program_load(const char *vfile, const char *pfile) 3.262 +{ 3.263 + unsigned int vs, ps; 3.264 + 3.265 + if(!(vs = get_vertex_shader(vfile)) || !(ps = get_pixel_shader(pfile))) { 3.266 + return 0; 3.267 + } 3.268 + return create_program_link(vs, ps); 3.269 +} 3.270 + 3.271 +void free_program(unsigned int sdr) 3.272 +{ 3.273 + glDeleteProgram(sdr); 3.274 +} 3.275 + 3.276 +void attach_shader(unsigned int prog, unsigned int sdr) 3.277 +{ 3.278 + glAttachShader(prog, sdr); 3.279 + assert(glGetError() == GL_NO_ERROR); 3.280 +} 3.281 + 3.282 +int link_program(unsigned int prog) 3.283 +{ 3.284 + int linked, info_len, retval = 0; 3.285 + char *info_str = 0; 3.286 + 3.287 + glLinkProgram(prog); 3.288 + assert(glGetError() == GL_NO_ERROR); 3.289 + glGetProgramiv(prog, GL_LINK_STATUS, &linked); 3.290 + assert(glGetError() == GL_NO_ERROR); 3.291 + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &info_len); 3.292 + assert(glGetError() == GL_NO_ERROR); 3.293 + 3.294 + if(info_len) { 3.295 + if((info_str = malloc(info_len + 1))) { 3.296 + glGetProgramInfoLog(prog, info_len, 0, info_str); 3.297 + assert(glGetError() == GL_NO_ERROR); 3.298 + } 3.299 + } 3.300 + 3.301 + if(linked) { 3.302 + fprintf(stderr, info_str ? "linking done: %s\n" : "linking done\n", info_str); 3.303 + } else { 3.304 + fprintf(stderr, info_str ? "linking failed: %s\n" : "linking failed\n", info_str); 3.305 + retval = -1; 3.306 + } 3.307 + 3.308 + free(info_str); 3.309 + return retval; 3.310 +} 3.311 + 3.312 +int bind_program(unsigned int prog) 3.313 +{ 3.314 + GLenum err; 3.315 + 3.316 + glUseProgram(prog); 3.317 + if(prog && (err = glGetError()) != GL_NO_ERROR) { 3.318 + /* maybe the program is not linked, try to link first */ 3.319 + if(err == GL_INVALID_OPERATION) { 3.320 + if(link_program(prog) == -1) { 3.321 + return -1; 3.322 + } 3.323 + glUseProgram(prog); 3.324 + return glGetError() == GL_NO_ERROR ? 0 : -1; 3.325 + } 3.326 + return -1; 3.327 + } 3.328 + return 0; 3.329 +} 3.330 + 3.331 +/* ugly but I'm not going to write the same bloody code over and over */ 3.332 +#define BEGIN_UNIFORM_CODE \ 3.333 + int loc, curr_prog; \ 3.334 + glGetIntegerv(GL_CURRENT_PROGRAM, &curr_prog); \ 3.335 + if(curr_prog != prog && bind_program(prog) == -1) { \ 3.336 + return -1; \ 3.337 + } \ 3.338 + if((loc = glGetUniformLocation(prog, name)) != -1) 3.339 + 3.340 +#define END_UNIFORM_CODE \ 3.341 + if(curr_prog != prog) { \ 3.342 + bind_program(curr_prog); \ 3.343 + } \ 3.344 + return loc == -1 ? -1 : 0 3.345 + 3.346 +int set_uniform_int(unsigned int prog, const char *name, int val) 3.347 +{ 3.348 + BEGIN_UNIFORM_CODE { 3.349 + glUniform1i(loc, val); 3.350 + } 3.351 + END_UNIFORM_CODE; 3.352 +} 3.353 + 3.354 +int set_uniform_float(unsigned int prog, const char *name, float val) 3.355 +{ 3.356 + BEGIN_UNIFORM_CODE { 3.357 + glUniform1f(loc, val); 3.358 + } 3.359 + END_UNIFORM_CODE; 3.360 +} 3.361 + 3.362 +int set_uniform_vec2(unsigned int prog, const char *name, vec2_t val) 3.363 +{ 3.364 + BEGIN_UNIFORM_CODE { 3.365 + glUniform2f(loc, val.x, val.y); 3.366 + } 3.367 + END_UNIFORM_CODE; 3.368 +} 3.369 + 3.370 +int set_uniform_vec3(unsigned int prog, const char *name, vec3_t val) 3.371 +{ 3.372 + BEGIN_UNIFORM_CODE { 3.373 + glUniform3f(loc, val.x, val.y, val.z); 3.374 + } 3.375 + END_UNIFORM_CODE; 3.376 +} 3.377 + 3.378 +int set_uniform_vec4(unsigned int prog, const char *name, vec4_t val) 3.379 +{ 3.380 + BEGIN_UNIFORM_CODE { 3.381 + glUniform4f(loc, val.x, val.y, val.z, val.w); 3.382 + } 3.383 + END_UNIFORM_CODE; 3.384 +} 3.385 + 3.386 +int set_uniform_mat4(unsigned int prog, const char *name, mat4_t val) 3.387 +{ 3.388 + BEGIN_UNIFORM_CODE { 3.389 + glUniformMatrix4fv(loc, 1, 1, (float*)val); 3.390 + } 3.391 + END_UNIFORM_CODE; 3.392 +} 3.393 + 3.394 + 3.395 +int get_attrib_loc(unsigned int prog, const char *name) 3.396 +{ 3.397 + int loc, curr_prog; 3.398 + 3.399 + glGetIntegerv(GL_CURRENT_PROGRAM, &curr_prog); 3.400 + if(curr_prog != prog && bind_program(prog) == -1) { 3.401 + return -1; 3.402 + } 3.403 + 3.404 + loc = glGetAttribLocation(prog, (char*)name); 3.405 + 3.406 + if(curr_prog != prog) { 3.407 + bind_program(curr_prog); 3.408 + } 3.409 + return loc; 3.410 +} 3.411 + 3.412 +void set_attrib_vec3(int attr_loc, vec3_t val) 3.413 +{ 3.414 + glVertexAttrib3f(attr_loc, val.x, val.y, val.z); 3.415 +} 3.416 + 3.417 +void set_attrib_float3(int attr_loc, float x, float y, float z) 3.418 +{ 3.419 + glVertexAttrib3f(attr_loc, x, y, z); 3.420 +}
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/sdr.h Thu Feb 18 23:15:43 2016 +0200 4.3 @@ -0,0 +1,55 @@ 4.4 +#ifndef _SDR_H_ 4.5 +#define _SDR_H_ 4.6 + 4.7 +typedef struct vec2 {float x, y;} vec2_t; 4.8 +typedef struct vec3 {float x, y, z;} vec3_t; 4.9 +typedef struct vec4 {float x, y, z, w;} vec4_t; 4.10 +typedef float mat4_t[4][4]; 4.11 + 4.12 +#ifdef __cplusplus 4.13 +extern "C" { 4.14 +#endif /* __cplusplus */ 4.15 + 4.16 +/* ---- shaders ---- */ 4.17 +unsigned int create_vertex_shader(const char *src); 4.18 +unsigned int create_pixel_shader(const char *src); 4.19 +unsigned int create_shader(const char *src, unsigned int sdr_type); 4.20 +void free_shader(unsigned int sdr); 4.21 + 4.22 +unsigned int load_vertex_shader(const char *fname); 4.23 +unsigned int load_pixel_shader(const char *fname); 4.24 +unsigned int load_shader(const char *src, unsigned int sdr_type); 4.25 + 4.26 +unsigned int get_vertex_shader(const char *fname); 4.27 +unsigned int get_pixel_shader(const char *fname); 4.28 +unsigned int get_shader(const char *fname, unsigned int sdr_type); 4.29 + 4.30 +int add_shader(const char *fname, unsigned int sdr); 4.31 +int remove_shader(const char *fname); 4.32 + 4.33 +/* ---- gpu programs ---- */ 4.34 +unsigned int create_program(void); 4.35 +unsigned int create_program_link(unsigned int vs, unsigned int ps); 4.36 +unsigned int create_program_load(const char *vfile, const char *pfile); 4.37 +void free_program(unsigned int sdr); 4.38 + 4.39 +void attach_shader(unsigned int prog, unsigned int sdr); 4.40 +int link_program(unsigned int prog); 4.41 +int bind_program(unsigned int prog); 4.42 + 4.43 +int set_uniform_int(unsigned int prog, const char *name, int val); 4.44 +int set_uniform_float(unsigned int prog, const char *name, float val); 4.45 +int set_uniform_vec2(unsigned int prog, const char *name, vec2_t val); 4.46 +int set_uniform_vec3(unsigned int prog, const char *name, vec3_t val); 4.47 +int set_uniform_vec4(unsigned int prog, const char *name, vec4_t val); 4.48 +int set_uniform_mat4(unsigned int prog, const char *name, mat4_t val); 4.49 + 4.50 +int get_attrib_loc(unsigned int prog, const char *name); 4.51 +void set_attrib_vec3(int attr_loc, vec3_t val); 4.52 +void set_attrib_float3(int attr_loc, float x, float y, float z); 4.53 + 4.54 +#ifdef __cplusplus 4.55 +} 4.56 +#endif /* __cplusplus */ 4.57 + 4.58 +#endif /* _SDR_H_ */
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/sdr.ps.glsl Thu Feb 18 23:15:43 2016 +0200 5.3 @@ -0,0 +1,58 @@ 5.4 +#version 110 5.5 + 5.6 +varying vec3 pos, normal; 5.7 + 5.8 +uniform float rough, specularity, ior; 5.9 +uniform float dif_sdr, spec_sdr; 5.10 + 5.11 +#define DSDR_LAMBERT 0.0 5.12 +#define DSDR_OREN_NAYAR 1.0 5.13 + 5.14 +#define SSDR_PHONG 0.0 5.15 +#define SSDR_BLINN 1.0 5.16 +#define SSDR_COOK_TORR 2.0 5.17 + 5.18 +#define EQ(a, b) (abs((a) - (b)) < 0.5) 5.19 + 5.20 +float lambert(vec3 norm, vec3 ldir); 5.21 +float oren_nayar(vec3 view, vec3 norm, vec3 ldir, float rough); 5.22 + 5.23 +float phong(vec3 view, vec3 norm, vec3 ldir, float spow); 5.24 +float blinn(vec3 norm, vec3 hvec, float spow); 5.25 +float cook_torrance(vec3 view, vec3 norm, vec3 ldir, vec3 hvec, float rough, float ior); 5.26 + 5.27 +void main() 5.28 +{ 5.29 + vec4 color = vec4(1.0, 1.0, 1.0, 1.0); 5.30 + float idiff, ispec; 5.31 + 5.32 + vec3 view = -normalize(pos); 5.33 + vec3 norm = normalize(normal); 5.34 + vec3 ldir = normalize(gl_LightSource[0].position.xyz - pos); 5.35 + 5.36 + if(EQ(dif_sdr, DSDR_LAMBERT)) { 5.37 + idiff = lambert(norm, ldir); 5.38 + } else if(EQ(dif_sdr, DSDR_OREN_NAYAR)) { 5.39 + idiff = oren_nayar(view, norm, ldir, rough); 5.40 + } else { 5.41 + idiff = 0.0; 5.42 + } 5.43 + 5.44 + vec4 mcolor = gl_FrontMaterial.diffuse; 5.45 + 5.46 + if(EQ(spec_sdr, SSDR_PHONG)) { 5.47 + ispec = phong(view, norm, ldir, gl_FrontMaterial.shininess); 5.48 + color = mcolor * idiff + vec4(specularity, specularity, specularity, 1.0) * ispec; 5.49 + } else if(EQ(spec_sdr, SSDR_BLINN)) { 5.50 + ispec = blinn(norm, gl_LightSource[0].halfVector.xyz, gl_FrontMaterial.shininess); 5.51 + color = mcolor * idiff + vec4(specularity, specularity, specularity, 1.0) * ispec; 5.52 + } else if(EQ(spec_sdr, SSDR_COOK_TORR)) { 5.53 + ispec = cook_torrance(view, norm, ldir, gl_LightSource[0].halfVector.xyz, rough, ior); 5.54 + color = specularity * ispec * mcolor + (1.0 - specularity) * idiff * mcolor; 5.55 + } else { 5.56 + color = vec4(1.0, 0.0, 0.0, 1.0); 5.57 + } 5.58 + color.a = 1.0; 5.59 + 5.60 + gl_FragColor = color; 5.61 +}
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/sdr.vs.glsl Thu Feb 18 23:15:43 2016 +0200 6.3 @@ -0,0 +1,9 @@ 6.4 +varying vec3 pos, normal; 6.5 + 6.6 +void main() 6.7 +{ 6.8 + gl_Position = ftransform(); 6.9 + 6.10 + pos = (gl_ModelViewMatrix * gl_Vertex).xyz; 6.11 + normal = (gl_NormalMatrix * gl_Normal).xyz; 6.12 +}
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/sdr_ref_models.glsl Thu Feb 18 23:15:43 2016 +0200 7.3 @@ -0,0 +1,102 @@ 7.4 +#version 110 7.5 + 7.6 +#define SQ(x) ((x) * (x)) 7.7 +#define PI 3.141592653 7.8 + 7.9 +/* -- Lambert's cosine law 7.10 + * J. H. Lambert, Photometria sive de mensura de gratibus luminis, colorum et umbrae. 7.11 + * Eberhard Klett, 1760. 7.12 + */ 7.13 +float lambert(vec3 norm, vec3 ldir) 7.14 +{ 7.15 + return max(dot(norm, ldir), 0.0); 7.16 +} 7.17 + 7.18 +/* -- Phong specular model 7.19 + * B. T. Phong, "Illumination for Computer Generated Pictures" 7.20 + * Communications of the ACM, 1975. 7.21 + */ 7.22 +float phong(vec3 view, vec3 norm, vec3 ldir, float spow) 7.23 +{ 7.24 + vec3 lref = reflect(-ldir, norm); 7.25 + return pow(max(dot(lref, view), 0.0), spow); 7.26 +} 7.27 + 7.28 +/* -- Blinn-Phong specular model 7.29 + * J. F. Blinn, "Models of Light Reflection for Computer Synthesized Pictures" 7.30 + * in Proceedings of SIGGRAPH 1977 7.31 + */ 7.32 +float blinn(vec3 norm, vec3 hvec, float spow) 7.33 +{ 7.34 + return pow(max(dot(norm, hvec), 0.0), spow); 7.35 +} 7.36 + 7.37 +/* -- Cook & Torrance model. 7.38 + * R. L. Cook and K. E. Torrance, "A Reflectance Model for Computer Graphics" 7.39 + * in Proceedings of SIGGRAPH 1981. 7.40 + */ 7.41 +float cook_torrance(vec3 view, vec3 norm, vec3 ldir, vec3 hvec, float rough, float ior) 7.42 +{ 7.43 + float m = max(rough, 0.0001); 7.44 + 7.45 + // various useful dot products 7.46 + float ndoth = max(dot(norm, hvec), 0.0); 7.47 + float ndotv = max(dot(norm, view), 0.0); 7.48 + float ndotl = dot(norm, ldir); 7.49 + float vdoth = max(dot(view, hvec), 0.0); 7.50 + float ndoth_sq = SQ(ndoth); 7.51 + 7.52 + // geometric term (shadowing/masking) 7.53 + float geom_a = (2.0 * ndoth * ndotv) / vdoth; 7.54 + float geom_b = (2.0 * ndoth * ndotl) / vdoth; 7.55 + float geom = min(1.0, min(geom_a, geom_b)); 7.56 + 7.57 + // beckmann microfacet distribution term 7.58 + float sin2_ang = 1.0 - ndoth_sq; // sin^2(a) = 1 - cos^2(a) 7.59 + float tan2_ang = sin2_ang / ndoth_sq; // tan^2(a) = sin^2(a) / cos^2(a) 7.60 + float d_mf = exp(-tan2_ang / SQ(m)) / (SQ(m) * SQ(ndoth_sq)); 7.61 + 7.62 + // fresnel term 7.63 + float c = vdoth; 7.64 + float g = sqrt(SQ(ior) + SQ(c) - 1.0); 7.65 + float ftmp = (c * (g + c) - 1.0) / (c * (g - c) + 1.0); 7.66 + float fres = 0.5 * (SQ(g - c) / SQ(g + c)) * (1.0 + SQ(ftmp)); 7.67 + 7.68 + return (fres / PI) * (d_mf / ndotl) * (geom / ndotv); 7.69 +} 7.70 + 7.71 +/* -- Oren & Nayar model 7.72 + * M. Oren and S. K. Nayar, "Generalization of Lambert's Reflectance Model" 7.73 + * in Proceedings of SIGGRAPH 1994. 7.74 + */ 7.75 +float oren_nayar(vec3 view, vec3 norm, vec3 ldir, float rough) 7.76 +{ 7.77 + float vdotn = max(dot(view, norm), 0.0); 7.78 + float ldotn = max(dot(ldir, norm), 0.0); 7.79 + 7.80 + float theta_r = acos(vdotn); 7.81 + float theta_i = acos(ldotn); 7.82 + float cos_pr_minus_pi = dot(normalize(view - norm * vdotn), normalize(ldir - norm * ldotn)); 7.83 + float alpha = max(theta_r, theta_i); 7.84 + float beta = min(theta_r, theta_i); 7.85 + 7.86 + float sigma_sq = SQ(rough); 7.87 + float a = 1.0 - 0.5 * sigma_sq / (sigma_sq + 0.33); 7.88 + float b = 0.45 * sigma_sq / (sigma_sq + 0.09); 7.89 + 7.90 + if(cos_pr_minus_pi >= 0.0) { 7.91 + b *= cos_pr_minus_pi * sin(alpha) * tan(beta); 7.92 + } else { 7.93 + b = 0.0; 7.94 + } 7.95 + 7.96 + return ldotn * (a + b); 7.97 +} 7.98 + 7.99 +/* TODO: need tangent/bitangent 7.100 +float ward(vec3 view, vec3 norm, vec3 ldir, vec3 hvec, vec3 tang, vec3 bitan, float ax, float ay) 7.101 +{ 7.102 + float vdotn = dot(view, norm); 7.103 + float ldotn = dot(light, norm); 7.104 +} 7.105 +*/