volray
changeset 0:b050ce167ff1
foo
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sat, 31 Mar 2012 02:08:42 +0300 |
parents | |
children | 57072295eb83 |
files | Makefile src/sdr.c src/sdr.h src/volray.c volray.p.glsl volray.v.glsl |
diffstat | 6 files changed, 817 insertions(+), 0 deletions(-) [+] |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/Makefile Sat Mar 31 02:08:42 2012 +0300 1.3 @@ -0,0 +1,26 @@ 1.4 +src = $(wildcard src/*.c) 1.5 +obj = $(src:.c=.o) 1.6 +dep = $(obj:.o=.d) 1.7 +bin = volray 1.8 + 1.9 +CC = gcc 1.10 +CFLAGS = -pedantic -Wall -g 1.11 +LDFLAGS = $(libgl) -limago -lvmath -lm 1.12 + 1.13 +ifeq ($(shell uname -s), Darwin) 1.14 + libgl = -framework OpenGL -framework GLUT 1.15 +else 1.16 + libgl = -lGL -lglut -lGLEW 1.17 +endif 1.18 + 1.19 +$(bin): $(obj) 1.20 + $(CC) -o $@ $(obj) $(LDFLAGS) 1.21 + 1.22 +-include $(dep) 1.23 + 1.24 +%.d: %.c 1.25 + @$(CPP) $(CFLAGS) $< -MM -MT $(@:.d=.o) >$@ 1.26 + 1.27 +.PHONY: clean 1.28 +clean: 1.29 + rm -f $(obj) $(bin)
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/src/sdr.c Sat Mar 31 02:08:42 2012 +0300 2.3 @@ -0,0 +1,333 @@ 2.4 +#ifndef NO_SHADERS 2.5 + 2.6 +#include <stdio.h> 2.7 +#include <stdlib.h> 2.8 +#include <string.h> 2.9 +#include <errno.h> 2.10 +#include <assert.h> 2.11 +#include <GL/glew.h> 2.12 + 2.13 +#if defined(unix) || defined(__unix__) 2.14 +#include <unistd.h> 2.15 +#include <sys/stat.h> 2.16 +#endif /* unix */ 2.17 + 2.18 +#include "sdr.h" 2.19 + 2.20 +unsigned int create_vertex_shader(const char *src) 2.21 +{ 2.22 + return create_shader(src, GL_VERTEX_SHADER); 2.23 +} 2.24 + 2.25 +unsigned int create_pixel_shader(const char *src) 2.26 +{ 2.27 + return create_shader(src, GL_FRAGMENT_SHADER); 2.28 +} 2.29 + 2.30 +unsigned int create_shader(const char *src, unsigned int sdr_type) 2.31 +{ 2.32 + unsigned int sdr; 2.33 + int success, info_len; 2.34 + char *info_str = 0; 2.35 + GLenum err; 2.36 + 2.37 + sdr = glCreateShader(sdr_type); 2.38 + assert(glGetError() == GL_NO_ERROR); 2.39 + glShaderSource(sdr, 1, &src, 0); 2.40 + err = glGetError(); 2.41 + assert(err == GL_NO_ERROR); 2.42 + glCompileShader(sdr); 2.43 + assert(glGetError() == GL_NO_ERROR); 2.44 + 2.45 + glGetShaderiv(sdr, GL_COMPILE_STATUS, &success); 2.46 + assert(glGetError() == GL_NO_ERROR); 2.47 + glGetShaderiv(sdr, GL_INFO_LOG_LENGTH, &info_len); 2.48 + assert(glGetError() == GL_NO_ERROR); 2.49 + 2.50 + if(info_len) { 2.51 + if((info_str = malloc(info_len + 1))) { 2.52 + glGetShaderInfoLog(sdr, info_len, 0, info_str); 2.53 + assert(glGetError() == GL_NO_ERROR); 2.54 + } 2.55 + } 2.56 + 2.57 + if(success) { 2.58 + fprintf(stderr, info_str ? "done: %s\n" : "done\n", info_str); 2.59 + } else { 2.60 + fprintf(stderr, info_str ? "failed: %s\n" : "failed\n", info_str); 2.61 + glDeleteShader(sdr); 2.62 + sdr = 0; 2.63 + } 2.64 + 2.65 + free(info_str); 2.66 + return sdr; 2.67 +} 2.68 + 2.69 +void free_shader(unsigned int sdr) 2.70 +{ 2.71 + glDeleteShader(sdr); 2.72 +} 2.73 + 2.74 +unsigned int load_vertex_shader(const char *fname) 2.75 +{ 2.76 + return load_shader(fname, GL_VERTEX_SHADER); 2.77 +} 2.78 + 2.79 +unsigned int load_pixel_shader(const char *fname) 2.80 +{ 2.81 + return load_shader(fname, GL_FRAGMENT_SHADER); 2.82 +} 2.83 + 2.84 +unsigned int load_shader(const char *fname, unsigned int sdr_type) 2.85 +{ 2.86 +#if defined(unix) || defined(__unix__) 2.87 + struct stat st; 2.88 +#endif 2.89 + unsigned int sdr; 2.90 + size_t filesize; 2.91 + FILE *fp; 2.92 + char *src; 2.93 + 2.94 + if(!(fp = fopen(fname, "r"))) { 2.95 + fprintf(stderr, "failed to open shader %s: %s\n", fname, strerror(errno)); 2.96 + return 0; 2.97 + } 2.98 + 2.99 +#if defined(unix) || defined(__unix__) 2.100 + fstat(fileno(fp), &st); 2.101 + filesize = st.st_size; 2.102 +#else 2.103 + fseek(fp, 0, SEEK_END); 2.104 + filesize = ftell(fp); 2.105 + fseek(fp, 0, SEEK_SET); 2.106 +#endif /* unix */ 2.107 + 2.108 + if(!(src = malloc(filesize + 1))) { 2.109 + fclose(fp); 2.110 + return 0; 2.111 + } 2.112 + fread(src, 1, filesize, fp); 2.113 + src[filesize] = 0; 2.114 + fclose(fp); 2.115 + 2.116 + fprintf(stderr, "compiling %s shader: %s... ", (sdr_type == GL_VERTEX_SHADER ? "vertex" : "pixel"), fname); 2.117 + sdr = create_shader(src, sdr_type); 2.118 + 2.119 + free(src); 2.120 + return sdr; 2.121 +} 2.122 + 2.123 + 2.124 +unsigned int get_vertex_shader(const char *fname) 2.125 +{ 2.126 + return get_shader(fname, GL_VERTEX_SHADER); 2.127 +} 2.128 + 2.129 +unsigned int get_pixel_shader(const char *fname) 2.130 +{ 2.131 + return get_shader(fname, GL_FRAGMENT_SHADER); 2.132 +} 2.133 + 2.134 +unsigned int get_shader(const char *fname, unsigned int sdr_type) 2.135 +{ 2.136 + unsigned int sdr; 2.137 + 2.138 + if(!(sdr = load_shader(fname, sdr_type))) { 2.139 + return 0; 2.140 + } 2.141 + return sdr; 2.142 +} 2.143 + 2.144 + 2.145 +/* ---- gpu programs ---- */ 2.146 + 2.147 +unsigned int create_program(void) 2.148 +{ 2.149 + unsigned int prog = glCreateProgram(); 2.150 + assert(glGetError() == GL_NO_ERROR); 2.151 + return prog; 2.152 +} 2.153 + 2.154 +unsigned int create_program_link(unsigned int vs, unsigned int ps) 2.155 +{ 2.156 + unsigned int prog; 2.157 + 2.158 + if(!(prog = create_program())) { 2.159 + return 0; 2.160 + } 2.161 + 2.162 + if(vs) { 2.163 + attach_shader(prog, vs); 2.164 + assert(glGetError() == GL_NO_ERROR); 2.165 + } 2.166 + if(ps) { 2.167 + attach_shader(prog, ps); 2.168 + assert(glGetError() == GL_NO_ERROR); 2.169 + } 2.170 + 2.171 + if(link_program(prog) == -1) { 2.172 + free_program(prog); 2.173 + return 0; 2.174 + } 2.175 + return prog; 2.176 +} 2.177 + 2.178 +unsigned int create_program_load(const char *vfile, const char *pfile) 2.179 +{ 2.180 + unsigned int vs = 0, ps = 0; 2.181 + 2.182 + if(vfile && !(vs = get_vertex_shader(vfile))) { 2.183 + return 0; 2.184 + } 2.185 + if(pfile && !(ps = get_pixel_shader(pfile))) { 2.186 + return 0; 2.187 + } 2.188 + return create_program_link(vs, ps); 2.189 +} 2.190 + 2.191 +void free_program(unsigned int sdr) 2.192 +{ 2.193 + glDeleteProgram(sdr); 2.194 +} 2.195 + 2.196 +void attach_shader(unsigned int prog, unsigned int sdr) 2.197 +{ 2.198 + glAttachShader(prog, sdr); 2.199 + assert(glGetError() == GL_NO_ERROR); 2.200 +} 2.201 + 2.202 +int link_program(unsigned int prog) 2.203 +{ 2.204 + int linked, info_len, retval = 0; 2.205 + char *info_str = 0; 2.206 + 2.207 + glLinkProgram(prog); 2.208 + assert(glGetError() == GL_NO_ERROR); 2.209 + glGetProgramiv(prog, GL_LINK_STATUS, &linked); 2.210 + assert(glGetError() == GL_NO_ERROR); 2.211 + glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &info_len); 2.212 + assert(glGetError() == GL_NO_ERROR); 2.213 + 2.214 + if(info_len) { 2.215 + if((info_str = malloc(info_len + 1))) { 2.216 + glGetProgramInfoLog(prog, info_len, 0, info_str); 2.217 + assert(glGetError() == GL_NO_ERROR); 2.218 + } 2.219 + } 2.220 + 2.221 + if(linked) { 2.222 + fprintf(stderr, info_str ? "linking done: %s\n" : "linking done\n", info_str); 2.223 + } else { 2.224 + fprintf(stderr, info_str ? "linking failed: %s\n" : "linking failed\n", info_str); 2.225 + retval = -1; 2.226 + } 2.227 + 2.228 + free(info_str); 2.229 + return retval; 2.230 +} 2.231 + 2.232 +int bind_program(unsigned int prog) 2.233 +{ 2.234 + GLenum err; 2.235 + 2.236 + glUseProgram(prog); 2.237 + if(prog && (err = glGetError()) != GL_NO_ERROR) { 2.238 + /* maybe the program is not linked, try linking first */ 2.239 + if(err == GL_INVALID_OPERATION) { 2.240 + if(link_program(prog) == -1) { 2.241 + return -1; 2.242 + } 2.243 + glUseProgram(prog); 2.244 + return glGetError() == GL_NO_ERROR ? 0 : -1; 2.245 + } 2.246 + return -1; 2.247 + } 2.248 + return 0; 2.249 +} 2.250 + 2.251 +/* ugly but I'm not going to write the same bloody code over and over */ 2.252 +#define BEGIN_UNIFORM_CODE \ 2.253 + int loc, curr_prog; \ 2.254 + glGetIntegerv(GL_CURRENT_PROGRAM, &curr_prog); \ 2.255 + if(curr_prog != prog && bind_program(prog) == -1) { \ 2.256 + return -1; \ 2.257 + } \ 2.258 + if((loc = glGetUniformLocation(prog, name)) != -1) 2.259 + 2.260 +#define END_UNIFORM_CODE \ 2.261 + if(curr_prog != prog) { \ 2.262 + bind_program(curr_prog); \ 2.263 + } \ 2.264 + return loc == -1 ? -1 : 0 2.265 + 2.266 +int set_uniform_int(unsigned int prog, const char *name, int val) 2.267 +{ 2.268 + BEGIN_UNIFORM_CODE { 2.269 + glUniform1i(loc, val); 2.270 + } 2.271 + END_UNIFORM_CODE; 2.272 +} 2.273 + 2.274 +int set_uniform_float(unsigned int prog, const char *name, float val) 2.275 +{ 2.276 + BEGIN_UNIFORM_CODE { 2.277 + glUniform1f(loc, val); 2.278 + } 2.279 + END_UNIFORM_CODE; 2.280 +} 2.281 + 2.282 +int set_uniform_float3(unsigned int prog, const char *name, float x, float y, float z) 2.283 +{ 2.284 + BEGIN_UNIFORM_CODE { 2.285 + glUniform3f(loc, x, y, z); 2.286 + } 2.287 + END_UNIFORM_CODE; 2.288 +} 2.289 + 2.290 +int set_uniform_float4(unsigned int prog, const char *name, float x, float y, float z, float w) 2.291 +{ 2.292 + BEGIN_UNIFORM_CODE { 2.293 + glUniform4f(loc, x, y, z, w); 2.294 + } 2.295 + END_UNIFORM_CODE; 2.296 +} 2.297 + 2.298 +int set_uniform_matrix4(unsigned int prog, const char *name, float *mat) 2.299 +{ 2.300 + BEGIN_UNIFORM_CODE { 2.301 + glUniformMatrix4fv(loc, 1, GL_FALSE, mat); 2.302 + } 2.303 + END_UNIFORM_CODE; 2.304 +} 2.305 + 2.306 +int set_uniform_matrix4_transposed(unsigned int prog, const char *name, float *mat) 2.307 +{ 2.308 + BEGIN_UNIFORM_CODE { 2.309 + glUniformMatrix4fv(loc, 1, GL_TRUE, mat); 2.310 + } 2.311 + END_UNIFORM_CODE; 2.312 +} 2.313 + 2.314 +int get_attrib_loc(unsigned int prog, const char *name) 2.315 +{ 2.316 + int loc, curr_prog; 2.317 + 2.318 + glGetIntegerv(GL_CURRENT_PROGRAM, &curr_prog); 2.319 + if(curr_prog != prog && bind_program(prog) == -1) { 2.320 + return -1; 2.321 + } 2.322 + 2.323 + loc = glGetAttribLocation(prog, (char*)name); 2.324 + 2.325 + if(curr_prog != prog) { 2.326 + bind_program(curr_prog); 2.327 + } 2.328 + return loc; 2.329 +} 2.330 + 2.331 +void set_attrib_float3(int attr_loc, float x, float y, float z) 2.332 +{ 2.333 + glVertexAttrib3f(attr_loc, x, y, z); 2.334 +} 2.335 + 2.336 +#endif /* !NO_SHADERS */
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/src/sdr.h Sat Mar 31 02:08:42 2012 +0300 3.3 @@ -0,0 +1,49 @@ 3.4 +#ifndef SDR_H_ 3.5 +#define SDR_H_ 3.6 + 3.7 +#ifdef __cplusplus 3.8 +extern "C" { 3.9 +#endif /* __cplusplus */ 3.10 + 3.11 +/* ---- shaders ---- */ 3.12 +unsigned int create_vertex_shader(const char *src); 3.13 +unsigned int create_pixel_shader(const char *src); 3.14 +unsigned int create_shader(const char *src, unsigned int sdr_type); 3.15 +void free_shader(unsigned int sdr); 3.16 + 3.17 +unsigned int load_vertex_shader(const char *fname); 3.18 +unsigned int load_pixel_shader(const char *fname); 3.19 +unsigned int load_shader(const char *src, unsigned int sdr_type); 3.20 + 3.21 +unsigned int get_vertex_shader(const char *fname); 3.22 +unsigned int get_pixel_shader(const char *fname); 3.23 +unsigned int get_shader(const char *fname, unsigned int sdr_type); 3.24 + 3.25 +int add_shader(const char *fname, unsigned int sdr); 3.26 +int remove_shader(const char *fname); 3.27 + 3.28 +/* ---- gpu programs ---- */ 3.29 +unsigned int create_program(void); 3.30 +unsigned int create_program_link(unsigned int vs, unsigned int ps); 3.31 +unsigned int create_program_load(const char *vfile, const char *pfile); 3.32 +void free_program(unsigned int sdr); 3.33 + 3.34 +void attach_shader(unsigned int prog, unsigned int sdr); 3.35 +int link_program(unsigned int prog); 3.36 +int bind_program(unsigned int prog); 3.37 + 3.38 +int set_uniform_int(unsigned int prog, const char *name, int val); 3.39 +int set_uniform_float(unsigned int prog, const char *name, float val); 3.40 +int set_uniform_float3(unsigned int prog, const char *name, float x, float y, float z); 3.41 +int set_uniform_float4(unsigned int prog, const char *name, float x, float y, float z, float w); 3.42 +int set_uniform_matrix4(unsigned int prog, const char *name, float *mat); 3.43 +int set_uniform_matrix4_transposed(unsigned int prog, const char *name, float *mat); 3.44 + 3.45 +int get_attrib_loc(unsigned int prog, const char *name); 3.46 +void set_attrib_float3(int attr_loc, float x, float y, float z); 3.47 + 3.48 +#ifdef __cplusplus 3.49 +} 3.50 +#endif /* __cplusplus */ 3.51 + 3.52 +#endif /* SDR_H_ */
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/src/volray.c Sat Mar 31 02:08:42 2012 +0300 4.3 @@ -0,0 +1,332 @@ 4.4 +#include <stdio.h> 4.5 +#include <stdlib.h> 4.6 +#include <assert.h> 4.7 + 4.8 +#include <GL/glew.h> 4.9 +#ifndef __APPLE__ 4.10 +#include <GL/glut.h> 4.11 +#else 4.12 +#include <GLUT/glut.h> 4.13 +#endif 4.14 + 4.15 +#include <vmath/vmath.h> 4.16 +#include <imago2.h> 4.17 +#include "sdr.h" 4.18 + 4.19 +struct slice_file { 4.20 + char *name; 4.21 + struct slice_file *next; 4.22 +}; 4.23 + 4.24 +int init(void); 4.25 +void disp(void); 4.26 +void reshape(int x, int y); 4.27 +void keyb(unsigned char key, int x, int y); 4.28 +void mouse(int bn, int state, int x, int y); 4.29 +void motion(int x, int y); 4.30 +int parse_args(int argc, char **argv); 4.31 + 4.32 +unsigned int create_ray_texture(int xsz, int ysz, float vfov, vec2_t *tex_scale); 4.33 +static vec3_t get_primary_ray_dir(int x, int y, int w, int h, float vfov_deg); 4.34 +static int round_pow2(int x); 4.35 + 4.36 +float cam_theta = 0, cam_phi = 0, cam_dist = 4.0; 4.37 +float cam_x, cam_y, cam_z; 4.38 + 4.39 +vec2_t tex_scale; 4.40 +struct slice_file *flist; 4.41 +int nslices; 4.42 +unsigned int sdr, vol_tex, ray_tex; 4.43 +int win_xsz, win_ysz; 4.44 + 4.45 +int main(int argc, char **argv) 4.46 +{ 4.47 + glutInit(&argc, argv); 4.48 + glutInitWindowSize(1280, 720); 4.49 + glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); 4.50 + 4.51 + if(parse_args(argc, argv) == -1) { 4.52 + return 1; 4.53 + } 4.54 + 4.55 + glutCreateWindow("Volume Raytracer"); 4.56 + 4.57 + glutDisplayFunc(disp); 4.58 + glutReshapeFunc(reshape); 4.59 + glutKeyboardFunc(keyb); 4.60 + glutMouseFunc(mouse); 4.61 + glutMotionFunc(motion); 4.62 + 4.63 + glewInit(); 4.64 + 4.65 + if(init() == -1) { 4.66 + return 1; 4.67 + } 4.68 + 4.69 + glutMainLoop(); 4.70 + return 0; 4.71 +} 4.72 + 4.73 +int init(void) 4.74 +{ 4.75 + int i, vol_xsz, vol_ysz; 4.76 + 4.77 + if(!(sdr = create_program_load("volray.v.glsl", "volray.p.glsl"))) { 4.78 + return 1; 4.79 + } 4.80 + 4.81 + glGenTextures(1, &vol_tex); 4.82 + glBindTexture(GL_TEXTURE_3D, vol_tex); 4.83 + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 4.84 + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 4.85 + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 4.86 + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 4.87 + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); 4.88 + 4.89 + for(i=0; i<nslices; i++) { 4.90 + int xsz, ysz; 4.91 + void *pix; 4.92 + struct slice_file *sfile = flist; 4.93 + flist = flist->next; 4.94 + 4.95 + if(!(pix = img_load_pixels(sfile->name, &xsz, &ysz, IMG_FMT_RGBA32))) { 4.96 + fprintf(stderr, "failed to load image: %s\n", sfile->name); 4.97 + return -1; 4.98 + } 4.99 + 4.100 + if(i == 0) { 4.101 + /* allocate storage for the texture */ 4.102 + glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, xsz, ysz, nslices, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); 4.103 + 4.104 + vol_xsz = xsz; 4.105 + vol_ysz = ysz; 4.106 + 4.107 + } else { 4.108 + if(xsz != vol_xsz || ysz != vol_ysz) { 4.109 + fprintf(stderr, "%s: inconsistent slice size: %dx%d. expected: %dx%d\n", 4.110 + sfile->name, xsz, ysz, vol_xsz, vol_ysz); 4.111 + img_free_pixels(pix); 4.112 + return -1; 4.113 + } 4.114 + } 4.115 + free(sfile); 4.116 + 4.117 + glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, i, xsz, ysz, 1, GL_RGBA, GL_UNSIGNED_BYTE, pix); 4.118 + img_free_pixels(pix); 4.119 + } 4.120 + 4.121 + return 0; 4.122 +} 4.123 + 4.124 +void disp(void) 4.125 +{ 4.126 + glMatrixMode(GL_MODELVIEW); 4.127 + glLoadIdentity(); 4.128 + glTranslatef(cam_x, cam_y, -cam_z); 4.129 + glRotatef(cam_theta, 0, 1, 0); 4.130 + glRotatef(cam_phi, 1, 0, 0); 4.131 + glTranslatef(0, 0, -cam_dist); 4.132 + 4.133 + glMatrixMode(GL_TEXTURE); 4.134 + glPushMatrix(); 4.135 + glScalef(tex_scale.x, tex_scale.y, 1.0); 4.136 + 4.137 + glActiveTexture(GL_TEXTURE0); 4.138 + glEnable(GL_TEXTURE_3D); 4.139 + glBindTexture(GL_TEXTURE_3D, vol_tex); 4.140 + 4.141 + glActiveTexture(GL_TEXTURE1); 4.142 + glEnable(GL_TEXTURE_2D); 4.143 + glBindTexture(GL_TEXTURE_2D, ray_tex); 4.144 + 4.145 + bind_program(sdr); 4.146 + glBegin(GL_QUADS); 4.147 + glColor3f(1, 1, 1); 4.148 + glTexCoord2f(0, 1); 4.149 + glVertex2f(-1, -1); 4.150 + glTexCoord2f(1, 1); 4.151 + glVertex2f(1, -1); 4.152 + glTexCoord2f(1, 0); 4.153 + glVertex2f(1, 1); 4.154 + glTexCoord2f(0, 0); 4.155 + glVertex2f(-1, 1); 4.156 + glEnd(); 4.157 + bind_program(0); 4.158 + 4.159 + glDisable(GL_TEXTURE_2D); 4.160 + glActiveTexture(GL_TEXTURE0); 4.161 + glDisable(GL_TEXTURE_3D); 4.162 + 4.163 + glMatrixMode(GL_TEXTURE); 4.164 + glPopMatrix(); 4.165 + 4.166 + glutSwapBuffers(); 4.167 + assert(glGetError() == GL_NO_ERROR); 4.168 +} 4.169 + 4.170 +void reshape(int x, int y) 4.171 +{ 4.172 + glViewport(0, 0, x, y); 4.173 + 4.174 + if(x != win_xsz || y != win_ysz) { 4.175 + ray_tex = create_ray_texture(x, y, 50.0, &tex_scale); 4.176 + win_xsz = x; 4.177 + win_ysz = y; 4.178 + } 4.179 +} 4.180 + 4.181 +void keyb(unsigned char key, int x, int y) 4.182 +{ 4.183 + switch(key) { 4.184 + case 27: 4.185 + exit(0); 4.186 + } 4.187 +} 4.188 + 4.189 +static int bnstate[32]; 4.190 +static int prev_x, prev_y; 4.191 + 4.192 +void mouse(int bn, int state, int x, int y) 4.193 +{ 4.194 + bnstate[bn - GLUT_LEFT_BUTTON] = state == GLUT_DOWN; 4.195 + prev_x = x; 4.196 + prev_y = y; 4.197 +} 4.198 + 4.199 +void motion(int x, int y) 4.200 +{ 4.201 + int dx = x - prev_x; 4.202 + int dy = y - prev_y; 4.203 + 4.204 + prev_x = x; 4.205 + prev_y = y; 4.206 + 4.207 + if(bnstate[0]) { 4.208 + cam_theta += dx * 0.5; 4.209 + cam_phi += dy * 0.5; 4.210 + 4.211 + if(cam_phi < -90) cam_phi = -90; 4.212 + if(cam_phi > 90) cam_phi = 90; 4.213 + 4.214 + glutPostRedisplay(); 4.215 + } 4.216 + 4.217 + if(bnstate[1]) { 4.218 + cam_y += dy * 0.1; 4.219 + glutPostRedisplay(); 4.220 + } 4.221 + 4.222 + if(bnstate[2]) { 4.223 + cam_dist += dy * 0.1; 4.224 + if(cam_dist < 0.0) cam_dist = 0.0; 4.225 + glutPostRedisplay(); 4.226 + } 4.227 +} 4.228 + 4.229 + 4.230 +int parse_args(int argc, char **argv) 4.231 +{ 4.232 + int i; 4.233 + struct slice_file *tail; 4.234 + 4.235 + for(i=1; i<argc; i++) { 4.236 + struct slice_file *sfile; 4.237 + 4.238 + if(!(sfile = malloc(sizeof *sfile))) { 4.239 + perror("failed to allocate memory"); 4.240 + return -1; 4.241 + } 4.242 + sfile->name = argv[i]; 4.243 + sfile->next = 0; 4.244 + 4.245 + if(!flist) { 4.246 + flist = tail = sfile; 4.247 + } else { 4.248 + tail->next = sfile; 4.249 + tail = sfile; 4.250 + } 4.251 + nslices++; 4.252 + } 4.253 + 4.254 + if(!nslices) { 4.255 + fprintf(stderr, "pass the slice filenames\n"); 4.256 + return -1; 4.257 + } 4.258 + 4.259 + return 0; 4.260 +} 4.261 + 4.262 + 4.263 +unsigned int create_ray_texture(int xsz, int ysz, float vfov, vec2_t *tex_scale) 4.264 +{ 4.265 + int i, j; 4.266 + unsigned int tex; 4.267 + int tex_xsz = round_pow2(xsz); 4.268 + int tex_ysz = round_pow2(ysz); 4.269 + float *teximg, *dir; 4.270 + 4.271 + if(!(teximg = malloc(3 * tex_xsz * tex_ysz * sizeof *teximg))) { 4.272 + return 0; 4.273 + } 4.274 + dir = teximg; 4.275 + 4.276 + for(i=0; i<tex_ysz; i++) { 4.277 + for(j=0; j<tex_xsz; j++) { 4.278 + if(j < xsz && i < ysz) { 4.279 + vec3_t rdir = get_primary_ray_dir(j, i, xsz, ysz, vfov); 4.280 + dir[0] = rdir.x; 4.281 + dir[1] = rdir.y; 4.282 + dir[2] = rdir.z; 4.283 + } else { 4.284 + dir[0] = dir[1] = 0.0f; 4.285 + dir[2] = 1.0f; 4.286 + } 4.287 + 4.288 + dir += 3; 4.289 + } 4.290 + } 4.291 + 4.292 + glGenTextures(1, &tex); 4.293 + glBindTexture(GL_TEXTURE_2D, tex); 4.294 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 4.295 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 4.296 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); 4.297 + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); 4.298 + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F_ARB, tex_xsz, tex_ysz, 0, GL_RGB, GL_FLOAT, teximg); 4.299 + free(teximg); 4.300 + 4.301 + if(tex_scale) { 4.302 + tex_scale->x = (float)xsz / (float)tex_xsz; 4.303 + tex_scale->y = (float)ysz / (float)tex_ysz; 4.304 + } 4.305 + return tex; 4.306 +} 4.307 + 4.308 +static vec3_t get_primary_ray_dir(int x, int y, int w, int h, float vfov_deg) 4.309 +{ 4.310 + float vfov = M_PI * vfov_deg / 180.0; 4.311 + float aspect = (float)w / (float)h; 4.312 + 4.313 + float ysz = 2.0; 4.314 + float xsz = aspect * ysz; 4.315 + 4.316 + float px = ((float)x / (float)w) * xsz - xsz / 2.0; 4.317 + float py = 1.0 - ((float)y / (float)h) * ysz; 4.318 + float pz = 1.0 / tan(0.5 * vfov); 4.319 + 4.320 + float mag = sqrt(px * px + py * py + pz * pz); 4.321 + 4.322 + return v3_cons(px / mag, py / mag, pz / mag); 4.323 +} 4.324 + 4.325 +static int round_pow2(int x) 4.326 +{ 4.327 + x--; 4.328 + x = (x >> 1) | x; 4.329 + x = (x >> 2) | x; 4.330 + x = (x >> 4) | x; 4.331 + x = (x >> 8) | x; 4.332 + x = (x >> 16) | x; 4.333 + return x + 1; 4.334 +} 4.335 +
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/volray.p.glsl Sat Mar 31 02:08:42 2012 +0300 5.3 @@ -0,0 +1,72 @@ 5.4 +uniform sampler3D volume; 5.5 +uniform sampler2D ray_tex; 5.6 + 5.7 +struct Ray { 5.8 + vec3 origin, dir; 5.9 +}; 5.10 + 5.11 +struct ISect { 5.12 + bool hit; 5.13 + float t; 5.14 + vec3 pos; 5.15 + vec3 normal; 5.16 +}; 5.17 + 5.18 +vec3 ray_march(Ray ray); 5.19 +vec3 shade(Ray ray, ISect isect); 5.20 +Ray get_primary_ray(); 5.21 + 5.22 +void main() 5.23 +{ 5.24 + Ray ray = get_primary_ray(); 5.25 + 5.26 + gl_FragColor = vec4(ray_march(ray), 1.0); 5.27 +} 5.28 + 5.29 +/*vec3 sky(Ray ray) 5.30 +{ 5.31 + vec3 col1 = vec3(0.75, 0.78, 0.8); 5.32 + vec3 col2 = vec3(0.56, 0.7, 1.0); 5.33 + 5.34 + float t = max(ray.dir.y, -0.5); 5.35 + return mix(col1, col2, t); 5.36 +}*/ 5.37 + 5.38 +vec3 ray_march(Ray ray) 5.39 +{ 5.40 + const float ray_step = 0.05; 5.41 + float energy = 1.0; 5.42 + vec3 pos = ray.origin; 5.43 + 5.44 + // assuming view space 5.45 + while(pos.z < 1.0) { 5.46 + energy -= texture3D(volume, pos).x; 5.47 + pos += ray.dir * ray_step; 5.48 + } 5.49 + 5.50 + return vec3(energy, energy, energy); 5.51 +} 5.52 + 5.53 +vec3 shade(Ray ray, ISect isect) 5.54 +{ 5.55 + vec3 ldir = normalize(vec3(10.0, 10.0, -10.0) - isect.pos); 5.56 + vec3 vdir = -ray.dir; 5.57 + vec3 hdir = normalize(ldir + vdir); 5.58 + 5.59 + float ndotl = dot(ldir, isect.normal); 5.60 + float ndoth = dot(hdir, isect.normal); 5.61 + 5.62 + vec3 dcol = vec3(1.0, 1.0, 1.0) * max(ndotl, 0.0); 5.63 + vec3 scol = vec3(0.6, 0.6, 0.6) * pow(max(ndoth, 0.0), 50.0); 5.64 + 5.65 + return vec3(0.01, 0.01, 0.01) + dcol + scol; 5.66 +} 5.67 + 5.68 +Ray get_primary_ray() 5.69 +{ 5.70 + Ray ray; 5.71 + vec2 tc = gl_TexCoord[0].xy; 5.72 + ray.dir = gl_NormalMatrix * normalize(texture2D(ray_tex, tc).xyz); 5.73 + ray.origin = (gl_ModelViewMatrix * vec4(0.0, 0.0, 0.0, 1.0)).xyz; 5.74 + return ray; 5.75 +}