nuclear@4: #include nuclear@0: #include "opengl.h" nuclear@0: #include "rend_fast.h" nuclear@4: #include "sdr.h" nuclear@4: nuclear@5: static inline float smoothstep(float a, float b, float x); nuclear@5: nuclear@4: #define XFER_MAP_SZ 1024 nuclear@4: nuclear@4: static unsigned int sdr; nuclear@4: static bool have_tex_float; nuclear@0: nuclear@0: RendererFast::RendererFast() nuclear@0: { nuclear@4: vol_tex = xfer_tex = 0; nuclear@4: vol_tex_valid = xfer_tex_valid = false; nuclear@0: } nuclear@0: nuclear@0: bool RendererFast::init() nuclear@0: { nuclear@4: if(!sdr) { nuclear@4: if(!(sdr = create_program_load("sdr/fast.v.glsl", "sdr/fast.p.glsl"))) { nuclear@4: return false; nuclear@4: } nuclear@4: have_tex_float = GLEW_ARB_texture_float; nuclear@4: } nuclear@4: nuclear@0: glGenTextures(1, &vol_tex); nuclear@0: glBindTexture(GL_TEXTURE_3D, vol_tex); nuclear@0: glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); nuclear@0: glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); nuclear@0: nuclear@4: glGenTextures(1, &xfer_tex); nuclear@4: glBindTexture(GL_TEXTURE_1D, xfer_tex); nuclear@4: glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); nuclear@4: glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); nuclear@4: glTexImage1D(GL_TEXTURE_1D, 0, have_tex_float ? GL_RGB16F : GL_RGB, XFER_MAP_SZ, 0, GL_RGB, GL_FLOAT, 0); nuclear@4: nuclear@0: return true; nuclear@0: } nuclear@0: nuclear@0: void RendererFast::destroy() nuclear@0: { nuclear@0: glDeleteTextures(1, &vol_tex); nuclear@4: glDeleteTextures(1, &xfer_tex); nuclear@4: } nuclear@4: nuclear@4: void RendererFast::set_volume(Volume *vol) nuclear@4: { nuclear@4: vol_tex_valid = false; nuclear@4: Renderer::set_volume(vol); nuclear@4: } nuclear@4: nuclear@4: Curve &RendererFast::transfer_curve(int color) nuclear@4: { nuclear@4: xfer_tex_valid = false; nuclear@4: return Renderer::transfer_curve(color); nuclear@0: } nuclear@0: nuclear@5: void RendererFast::set_simple_transfer(float low, float high) nuclear@5: { nuclear@5: xfer_tex_valid = false; nuclear@5: Renderer::set_simple_transfer(low, high); nuclear@5: } nuclear@5: nuclear@0: void RendererFast::update(unsigned int msec) nuclear@0: { nuclear@0: if(!vol) return; nuclear@0: nuclear@0: // make sure the 3D volume texture is up to date nuclear@0: if(!vol_tex_valid) { nuclear@0: int xsz, ysz, zsz; nuclear@0: nuclear@0: if((xsz = vol->num_samples(0)) > 0) { nuclear@0: ysz = vol->num_samples(1); nuclear@0: zsz = vol->num_samples(2); nuclear@0: } else { nuclear@0: xsz = ysz = zsz = 256; nuclear@0: } nuclear@0: nuclear@4: printf("updating 3D texture data (%dx%dx%d) ... ", xsz, ysz, zsz); nuclear@4: fflush(stdout); nuclear@4: nuclear@0: int int_fmt = GLEW_ARB_texture_float ? GL_RGBA16F_ARB : GL_RGBA; nuclear@0: nuclear@0: glBindTexture(GL_TEXTURE_3D, vol_tex); nuclear@0: glTexImage3D(GL_TEXTURE_3D, 0, int_fmt, xsz, ysz, zsz, 0, GL_RGBA, GL_FLOAT, 0); nuclear@0: nuclear@0: float *slice = new float[xsz * ysz * 4]; nuclear@0: nuclear@0: for(int i=0; ivaluef(x, y, z); nuclear@0: // normal in rgb nuclear@0: vol->normalf(pptr, x, y, z); nuclear@0: // shift normal to the [0,1] range in case we don't have tex_float nuclear@0: pptr[0] = pptr[0] * 0.5 + 0.5; nuclear@0: pptr[1] = pptr[1] * 0.5 + 0.5; nuclear@0: pptr[2] = pptr[2] * 0.5 + 0.5; nuclear@4: nuclear@4: pptr += 4; nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, i, xsz, ysz, 1, GL_RGBA, GL_FLOAT, slice); nuclear@0: } nuclear@0: nuclear@4: printf("done\n"); nuclear@4: nuclear@0: delete [] slice; nuclear@0: nuclear@0: vol_tex_valid = true; nuclear@0: } nuclear@4: nuclear@4: if(!xfer_tex_valid) { nuclear@4: float pixels[XFER_MAP_SZ * 3]; nuclear@4: float *pptr = pixels; nuclear@4: nuclear@4: for(int i=0; i= b) return 1.0; nuclear@5: nuclear@5: x = (x - a) / (b - a); nuclear@5: return x * x * (3.0 - 2.0 * x); nuclear@5: }