qvolray
changeset 4:3e53a16d4667
foo
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Mon, 02 Apr 2012 17:59:46 +0300 |
parents | 6f275934717b |
children | 0c3874aa717a |
files | src/volray.c volray.p.glsl |
diffstat | 2 files changed, 178 insertions(+), 33 deletions(-) [+] |
line diff
1.1 --- a/src/volray.c Mon Apr 02 14:42:03 2012 +0300 1.2 +++ b/src/volray.c Mon Apr 02 17:59:46 2012 +0300 1.3 @@ -22,8 +22,11 @@ 1.4 1.5 int init(void); 1.6 void disp(void); 1.7 +void render_volume(void); 1.8 +void draw_xfer_func(void); 1.9 void reshape(int x, int y); 1.10 void keyb(unsigned char key, int x, int y); 1.11 +void keyb_up(unsigned char key, int x, int y); 1.12 void mouse(int bn, int state, int x, int y); 1.13 void motion(int x, int y); 1.14 int parse_args(int argc, char **argv); 1.15 @@ -47,6 +50,8 @@ 1.16 float xfer_mean = 0.5, xfer_sdev = 1.0; 1.17 int xfertex_needs_recalc = 1; 1.18 1.19 +static int uimode_xfer; 1.20 + 1.21 int main(int argc, char **argv) 1.22 { 1.23 glutInit(&argc, argv); 1.24 @@ -62,6 +67,7 @@ 1.25 glutDisplayFunc(disp); 1.26 glutReshapeFunc(reshape); 1.27 glutKeyboardFunc(keyb); 1.28 + glutKeyboardUpFunc(keyb_up); 1.29 glutMouseFunc(mouse); 1.30 glutMotionFunc(motion); 1.31 1.32 @@ -90,9 +96,9 @@ 1.33 glBindTexture(GL_TEXTURE_3D, vol_tex); 1.34 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 1.35 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 1.36 - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP); 1.37 - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP); 1.38 - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP); 1.39 + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 1.40 + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 1.41 + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); 1.42 1.43 for(i=0; i<nslices; i++) { 1.44 int xsz, ysz; 1.45 @@ -130,14 +136,27 @@ 1.46 1.47 void disp(void) 1.48 { 1.49 + /* recalculate primary ray texture if needed */ 1.50 if(raytex_needs_recalc) { 1.51 create_ray_texture(win_xsz, win_ysz, 50.0, &tex_scale); 1.52 } 1.53 + /* recalculate transfer function texture if needed */ 1.54 if(xfertex_needs_recalc) { 1.55 create_transfer_map(xfer_mean, xfer_sdev); 1.56 } 1.57 1.58 + render_volume(); 1.59 + draw_xfer_func(); 1.60 + 1.61 + glutSwapBuffers(); 1.62 + assert(glGetError() == GL_NO_ERROR); 1.63 +} 1.64 + 1.65 +void render_volume(void) 1.66 +{ 1.67 + /* set the camera transformation */ 1.68 glMatrixMode(GL_MODELVIEW); 1.69 + glPushMatrix(); 1.70 glLoadIdentity(); 1.71 glRotatef(-90, 1, 0, 0); 1.72 glTranslatef(cam_x, cam_y, -cam_z); 1.73 @@ -145,18 +164,23 @@ 1.74 glRotatef(cam_phi, 1, 0, 0); 1.75 glTranslatef(0, 0, -cam_dist); 1.76 1.77 + /* setup the texture matrix to map the useful part of the ray texture to [0,1] */ 1.78 glMatrixMode(GL_TEXTURE); 1.79 + glPushMatrix(); 1.80 glLoadIdentity(); 1.81 glScalef(tex_scale.x, tex_scale.y, 1.0); 1.82 1.83 + /* tex unit0: volume data 3D texture */ 1.84 glActiveTexture(GL_TEXTURE0); 1.85 glBindTexture(GL_TEXTURE_3D, vol_tex); 1.86 glEnable(GL_TEXTURE_3D); 1.87 1.88 + /* tex unit1: primary rays in view space */ 1.89 glActiveTexture(GL_TEXTURE1); 1.90 glBindTexture(GL_TEXTURE_2D, ray_tex); 1.91 glEnable(GL_TEXTURE_2D); 1.92 1.93 + /* tex unit2: transfer function (1d) */ 1.94 glActiveTexture(GL_TEXTURE2); 1.95 glBindTexture(GL_TEXTURE_1D, xfer_tex); 1.96 glEnable(GL_TEXTURE_1D); 1.97 @@ -179,15 +203,47 @@ 1.98 glDisable(GL_TEXTURE_3D); 1.99 1.100 glMatrixMode(GL_TEXTURE); 1.101 - glLoadIdentity(); 1.102 + glPopMatrix(); 1.103 + glMatrixMode(GL_MODELVIEW); 1.104 + glPopMatrix(); 1.105 +} 1.106 1.107 - glutSwapBuffers(); 1.108 - assert(glGetError() == GL_NO_ERROR); 1.109 +void draw_xfer_func(void) 1.110 +{ 1.111 + glMatrixMode(GL_MODELVIEW); 1.112 + glPushMatrix(); 1.113 + glTranslatef(-0.9, -0.9, 0); 1.114 + glScalef(0.5, 0.1, 1); 1.115 + 1.116 + glBindTexture(GL_TEXTURE_1D, xfer_tex); 1.117 + glEnable(GL_TEXTURE_1D); 1.118 + 1.119 + glBegin(GL_QUADS); 1.120 + glColor3f(1, 1, 1); 1.121 + glTexCoord1f(1); 1.122 + glVertex2f(1, 0); 1.123 + glVertex2f(1, 1); 1.124 + glTexCoord1f(0); 1.125 + glVertex2f(0, 1); 1.126 + glVertex2f(0, 0); 1.127 + glEnd(); 1.128 + 1.129 + glDisable(GL_TEXTURE_1D); 1.130 + 1.131 + glLineWidth(2.0); 1.132 + glBegin(GL_LINE_LOOP); 1.133 + glColor3f(uimode_xfer ? 1 : 0, 0, uimode_xfer ? 0 : 1); 1.134 + glVertex2f(0, 0); 1.135 + glVertex2f(1, 0); 1.136 + glVertex2f(1, 1); 1.137 + glVertex2f(0, 1); 1.138 + glEnd(); 1.139 + 1.140 + glPopMatrix(); 1.141 } 1.142 1.143 void reshape(int x, int y) 1.144 { 1.145 - printf("reshape: %dx%d\n", x, y); 1.146 glViewport(0, 0, x, y); 1.147 1.148 if(x != win_xsz || y != win_ysz) { 1.149 @@ -202,6 +258,21 @@ 1.150 switch(key) { 1.151 case 27: 1.152 exit(0); 1.153 + 1.154 + case 'x': 1.155 + uimode_xfer = 1; 1.156 + glutPostRedisplay(); 1.157 + break; 1.158 + } 1.159 +} 1.160 + 1.161 +void keyb_up(unsigned char key, int x, int y) 1.162 +{ 1.163 + switch(key) { 1.164 + case 'x': 1.165 + uimode_xfer = 0; 1.166 + glutPostRedisplay(); 1.167 + break; 1.168 } 1.169 } 1.170 1.171 @@ -219,30 +290,43 @@ 1.172 { 1.173 int dx = x - prev_x; 1.174 int dy = y - prev_y; 1.175 - 1.176 prev_x = x; 1.177 prev_y = y; 1.178 1.179 - if(bnstate[0]) { 1.180 - cam_theta += dx * 0.5; 1.181 - cam_phi += dy * 0.5; 1.182 + if(uimode_xfer) { 1.183 + if(dx || dy) { 1.184 + xfer_mean += dx / (float)win_xsz; 1.185 + xfer_sdev += 0.5 * dy / (float)win_ysz; 1.186 1.187 - if(cam_phi <= -90) cam_phi = -89; 1.188 - if(cam_phi >= 90) cam_phi = 89; 1.189 + xfer_mean = xfer_mean < 0.0 ? 0.0 : (xfer_mean > 1.0 ? 1.0 : xfer_mean); 1.190 + xfer_sdev = xfer_sdev < 0.0 ? 0.0 : (xfer_sdev > 1.0 ? 1.0 : xfer_sdev); 1.191 1.192 - glutPostRedisplay(); 1.193 - } 1.194 + xfertex_needs_recalc = 1; 1.195 + glutPostRedisplay(); 1.196 + } 1.197 + } else { 1.198 1.199 - if(bnstate[1]) { 1.200 - cam_x += dx * 0.025; 1.201 - cam_y += dy * 0.025; 1.202 - glutPostRedisplay(); 1.203 - } 1.204 + if(bnstate[0]) { 1.205 + cam_theta += dx * 0.5; 1.206 + cam_phi += dy * 0.5; 1.207 1.208 - if(bnstate[2]) { 1.209 - cam_dist += dy * 0.025; 1.210 - if(cam_dist < 0.0) cam_dist = 0.0; 1.211 - glutPostRedisplay(); 1.212 + if(cam_phi <= -90) cam_phi = -89; 1.213 + if(cam_phi >= 90) cam_phi = 89; 1.214 + 1.215 + glutPostRedisplay(); 1.216 + } 1.217 + 1.218 + if(bnstate[1]) { 1.219 + cam_x += dx * 0.025; 1.220 + cam_y += dy * 0.025; 1.221 + glutPostRedisplay(); 1.222 + } 1.223 + 1.224 + if(bnstate[2]) { 1.225 + cam_dist += dy * 0.025; 1.226 + if(cam_dist < 0.0) cam_dist = 0.0; 1.227 + glutPostRedisplay(); 1.228 + } 1.229 } 1.230 } 1.231 1.232 @@ -264,10 +348,10 @@ 1.233 } 1.234 break; 1.235 1.236 - case 'v': 1.237 + case 'd': 1.238 xfer_sdev = strtod(argv[++i], &endp); 1.239 if(endp == argv[i]) { 1.240 - fprintf(stderr, "-v must be followed by the transfer function sdeviance\n"); 1.241 + fprintf(stderr, "-d must be followed by the transfer function std.deviation\n"); 1.242 return -1; 1.243 } 1.244 break; 1.245 @@ -396,10 +480,11 @@ 1.246 } 1.247 1.248 for(i=0; i<XFER_MAP_SZ; i++) { 1.249 - float x = (float)i / (float)XFER_MAP_SZ; 1.250 - map[i] = gaussian(x, mean, sdev); 1.251 + float x = (float)i / (float)(XFER_MAP_SZ - 1); 1.252 + map[i] = gaussian(x, mean, sdev) - 1.0; 1.253 } 1.254 + putchar('\n'); 1.255 1.256 - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, XFER_MAP_SZ, 1, GL_LUMINANCE, GL_FLOAT, map); 1.257 + glTexSubImage1D(GL_TEXTURE_1D, 0, 0, XFER_MAP_SZ, GL_LUMINANCE, GL_FLOAT, map); 1.258 xfertex_needs_recalc = 0; 1.259 }
2.1 --- a/volray.p.glsl Mon Apr 02 14:42:03 2012 +0300 2.2 +++ b/volray.p.glsl Mon Apr 02 17:59:46 2012 +0300 2.3 @@ -1,10 +1,15 @@ 2.4 uniform sampler3D volume; 2.5 uniform sampler2D ray_tex; 2.6 +uniform sampler1D xfer_tex; 2.7 2.8 struct Ray { 2.9 vec3 origin, dir; 2.10 }; 2.11 2.12 +struct AABBox { 2.13 + vec3 min, max; 2.14 +}; 2.15 + 2.16 struct ISect { 2.17 bool hit; 2.18 float t; 2.19 @@ -16,13 +21,22 @@ 2.20 vec3 ray_march(Ray ray); 2.21 vec3 shade(Ray ray, ISect isect); 2.22 Ray get_primary_ray(); 2.23 +bool intersect_aabb(Ray ray, AABBox aabb, out float t); 2.24 2.25 void main() 2.26 { 2.27 + const AABBox aabb = AABBox(vec3(0.0, 0.0, 0.0), vec3(1.0, 1.0, 1.0)); 2.28 Ray ray = get_primary_ray(); 2.29 2.30 - gl_FragColor = vec4(ray_march(ray), 1.0); 2.31 - //gl_FragColor = vec4(sky(ray), 1.0); 2.32 + vec3 color = vec3(0.0, 0.0, 0.0); 2.33 + 2.34 + float start_t; 2.35 + if(intersect_aabb(ray, aabb, start_t)) { 2.36 + ray.origin += ray.dir * start_t; 2.37 + color = vec3(1.0, 0.0, 0.0);//ray_march(ray); 2.38 + } 2.39 + 2.40 + gl_FragColor = vec4(color, 1.0); 2.41 } 2.42 2.43 vec3 sky(Ray ray) 2.44 @@ -34,6 +48,11 @@ 2.45 return mix(col1, col2, t); 2.46 } 2.47 2.48 +float eval(vec3 pos) 2.49 +{ 2.50 + return texture1D(xfer_tex, texture3D(volume, pos).x).x; 2.51 +} 2.52 + 2.53 vec3 ray_march(Ray ray) 2.54 { 2.55 const float ray_step = 0.1; 2.56 @@ -42,8 +61,7 @@ 2.57 float col = 0.0; 2.58 2.59 for(int i=0; i<40; i++) { 2.60 - float val = texture3D(volume, pos).x; 2.61 - val *= energy; 2.62 + float val = eval(pos) * energy; 2.63 col += val; 2.64 energy -= val; 2.65 if(energy < 0.001) { 2.66 @@ -78,3 +96,45 @@ 2.67 ray.origin = (gl_ModelViewMatrix * vec4(0.0, 0.0, 0.0, 1.0)).xyz; 2.68 return ray; 2.69 } 2.70 + 2.71 +bool intersect_aabb(Ray ray, AABBox aabb, out float t) 2.72 +{ 2.73 + if(ray.origin.x >= aabb.min.x && ray.origin.y >= aabb.min.y && ray.origin.z >= aabb.min.z && 2.74 + ray.origin.x < aabb.max.x && ray.origin.y < aabb.max.y && ray.origin.z < aabb.max.z) { 2.75 + return true; 2.76 + } 2.77 + 2.78 + vec4 bbox[2]; 2.79 + bbox[0] = vec4(aabb.min.x, aabb.min.y, aabb.min.z, 0); 2.80 + bbox[1] = vec4(aabb.max.x, aabb.max.y, aabb.max.z, 0); 2.81 + 2.82 + int xsign = int(ray.dir.x < 0.0); 2.83 + float invdirx = 1.0 / ray.dir.x; 2.84 + float tmin = (bbox[xsign].x - ray.origin.x) * invdirx; 2.85 + float tmax = (bbox[1 - xsign].x - ray.origin.x) * invdirx; 2.86 + 2.87 + int ysign = int(ray.dir.y < 0.0); 2.88 + float invdiry = 1.0 / ray.dir.y; 2.89 + float tymin = (bbox[ysign].y - ray.origin.y) * invdiry; 2.90 + float tymax = (bbox[1 - ysign].y - ray.origin.y) * invdiry; 2.91 + 2.92 + if(tmin > tymax || tymin > tmax) { 2.93 + return false; 2.94 + } 2.95 + 2.96 + if(tymin > tmin) tmin = tymin; 2.97 + if(tymax < tmax) tmax = tymax; 2.98 + 2.99 + int zsign = int(ray.dir.z < 0.0); 2.100 + float invdirz = 1.0 / ray.dir.z; 2.101 + float tzmin = (bbox[zsign].z - ray.origin.z) * invdirz; 2.102 + float tzmax = (bbox[1 - zsign].z - ray.origin.z) * invdirz; 2.103 + 2.104 + if(tmin > tzmax || tzmin > tmax) { 2.105 + return false; 2.106 + } 2.107 + 2.108 + t = tmin; 2.109 + return tmin < 1.0 && tmax > 0.0; 2.110 +} 2.111 +