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 +*/