nuclear@0: uniform sampler3D volume; nuclear@0: uniform sampler2D ray_tex; nuclear@4: uniform sampler1D xfer_tex; nuclear@0: nuclear@0: struct Ray { nuclear@0: vec3 origin, dir; nuclear@0: }; nuclear@0: nuclear@4: struct AABBox { nuclear@4: vec3 min, max; nuclear@4: }; nuclear@4: nuclear@0: struct ISect { nuclear@0: bool hit; nuclear@0: float t; nuclear@0: vec3 pos; nuclear@0: vec3 normal; nuclear@0: }; nuclear@0: nuclear@1: vec3 sky(Ray ray); nuclear@0: vec3 ray_march(Ray ray); nuclear@0: vec3 shade(Ray ray, ISect isect); nuclear@0: Ray get_primary_ray(); nuclear@4: bool intersect_aabb(Ray ray, AABBox aabb, out float t); nuclear@0: nuclear@0: void main() nuclear@0: { nuclear@4: const AABBox aabb = AABBox(vec3(0.0, 0.0, 0.0), vec3(1.0, 1.0, 1.0)); nuclear@0: Ray ray = get_primary_ray(); nuclear@0: nuclear@4: vec3 color = vec3(0.0, 0.0, 0.0); nuclear@4: nuclear@4: float start_t; nuclear@4: if(intersect_aabb(ray, aabb, start_t)) { nuclear@4: ray.origin += ray.dir * start_t; nuclear@4: color = vec3(1.0, 0.0, 0.0);//ray_march(ray); nuclear@4: } nuclear@4: nuclear@4: gl_FragColor = vec4(color, 1.0); nuclear@0: } nuclear@0: nuclear@1: vec3 sky(Ray ray) nuclear@0: { nuclear@0: vec3 col1 = vec3(0.75, 0.78, 0.8); nuclear@0: vec3 col2 = vec3(0.56, 0.7, 1.0); nuclear@0: nuclear@0: float t = max(ray.dir.y, -0.5); nuclear@0: return mix(col1, col2, t); nuclear@1: } nuclear@0: nuclear@4: float eval(vec3 pos) nuclear@4: { nuclear@4: return texture1D(xfer_tex, texture3D(volume, pos).x).x; nuclear@4: } nuclear@4: nuclear@0: vec3 ray_march(Ray ray) nuclear@0: { nuclear@1: const float ray_step = 0.1; nuclear@0: float energy = 1.0; nuclear@0: vec3 pos = ray.origin; nuclear@1: float col = 0.0; nuclear@0: nuclear@1: for(int i=0; i<40; i++) { nuclear@4: float val = eval(pos) * energy; nuclear@1: col += val; nuclear@1: energy -= val; nuclear@1: if(energy < 0.001) { nuclear@1: break; nuclear@1: } nuclear@0: pos += ray.dir * ray_step; nuclear@0: } nuclear@0: nuclear@1: return vec3(col, col, col); nuclear@0: } nuclear@0: nuclear@0: vec3 shade(Ray ray, ISect isect) nuclear@0: { nuclear@0: vec3 ldir = normalize(vec3(10.0, 10.0, -10.0) - isect.pos); nuclear@0: vec3 vdir = -ray.dir; nuclear@0: vec3 hdir = normalize(ldir + vdir); nuclear@0: nuclear@0: float ndotl = dot(ldir, isect.normal); nuclear@0: float ndoth = dot(hdir, isect.normal); nuclear@0: nuclear@0: vec3 dcol = vec3(1.0, 1.0, 1.0) * max(ndotl, 0.0); nuclear@0: vec3 scol = vec3(0.6, 0.6, 0.6) * pow(max(ndoth, 0.0), 50.0); nuclear@0: nuclear@0: return vec3(0.01, 0.01, 0.01) + dcol + scol; nuclear@0: } nuclear@0: nuclear@0: Ray get_primary_ray() nuclear@0: { nuclear@0: Ray ray; nuclear@0: vec2 tc = gl_TexCoord[0].xy; nuclear@0: ray.dir = gl_NormalMatrix * normalize(texture2D(ray_tex, tc).xyz); nuclear@0: ray.origin = (gl_ModelViewMatrix * vec4(0.0, 0.0, 0.0, 1.0)).xyz; nuclear@0: return ray; nuclear@0: } nuclear@4: nuclear@4: bool intersect_aabb(Ray ray, AABBox aabb, out float t) nuclear@4: { nuclear@4: if(ray.origin.x >= aabb.min.x && ray.origin.y >= aabb.min.y && ray.origin.z >= aabb.min.z && nuclear@4: ray.origin.x < aabb.max.x && ray.origin.y < aabb.max.y && ray.origin.z < aabb.max.z) { nuclear@4: return true; nuclear@4: } nuclear@4: nuclear@4: vec4 bbox[2]; nuclear@4: bbox[0] = vec4(aabb.min.x, aabb.min.y, aabb.min.z, 0); nuclear@4: bbox[1] = vec4(aabb.max.x, aabb.max.y, aabb.max.z, 0); nuclear@4: nuclear@4: int xsign = int(ray.dir.x < 0.0); nuclear@4: float invdirx = 1.0 / ray.dir.x; nuclear@4: float tmin = (bbox[xsign].x - ray.origin.x) * invdirx; nuclear@4: float tmax = (bbox[1 - xsign].x - ray.origin.x) * invdirx; nuclear@4: nuclear@4: int ysign = int(ray.dir.y < 0.0); nuclear@4: float invdiry = 1.0 / ray.dir.y; nuclear@4: float tymin = (bbox[ysign].y - ray.origin.y) * invdiry; nuclear@4: float tymax = (bbox[1 - ysign].y - ray.origin.y) * invdiry; nuclear@4: nuclear@4: if(tmin > tymax || tymin > tmax) { nuclear@4: return false; nuclear@4: } nuclear@4: nuclear@4: if(tymin > tmin) tmin = tymin; nuclear@4: if(tymax < tmax) tmax = tymax; nuclear@4: nuclear@4: int zsign = int(ray.dir.z < 0.0); nuclear@4: float invdirz = 1.0 / ray.dir.z; nuclear@4: float tzmin = (bbox[zsign].z - ray.origin.z) * invdirz; nuclear@4: float tzmax = (bbox[1 - zsign].z - ray.origin.z) * invdirz; nuclear@4: nuclear@4: if(tmin > tzmax || tzmin > tmax) { nuclear@4: return false; nuclear@4: } nuclear@4: nuclear@4: t = tmin; nuclear@4: return tmin < 1.0 && tmax > 0.0; nuclear@4: } nuclear@4: