glviewvol

annotate src/rend_fast.cc @ 5:5417c25cb238

moving to a simpler transfer function
author John Tsiombikas <nuclear@member.fsf.org>
date Mon, 29 Dec 2014 15:59:55 +0200
parents 04330eb80b36
children f22be47a3572
rev   line source
nuclear@4 1 #include <stdio.h>
nuclear@0 2 #include "opengl.h"
nuclear@0 3 #include "rend_fast.h"
nuclear@4 4 #include "sdr.h"
nuclear@4 5
nuclear@5 6 static inline float smoothstep(float a, float b, float x);
nuclear@5 7
nuclear@4 8 #define XFER_MAP_SZ 1024
nuclear@4 9
nuclear@4 10 static unsigned int sdr;
nuclear@4 11 static bool have_tex_float;
nuclear@0 12
nuclear@0 13 RendererFast::RendererFast()
nuclear@0 14 {
nuclear@4 15 vol_tex = xfer_tex = 0;
nuclear@4 16 vol_tex_valid = xfer_tex_valid = false;
nuclear@0 17 }
nuclear@0 18
nuclear@0 19 bool RendererFast::init()
nuclear@0 20 {
nuclear@4 21 if(!sdr) {
nuclear@4 22 if(!(sdr = create_program_load("sdr/fast.v.glsl", "sdr/fast.p.glsl"))) {
nuclear@4 23 return false;
nuclear@4 24 }
nuclear@4 25 have_tex_float = GLEW_ARB_texture_float;
nuclear@4 26 }
nuclear@4 27
nuclear@0 28 glGenTextures(1, &vol_tex);
nuclear@0 29 glBindTexture(GL_TEXTURE_3D, vol_tex);
nuclear@0 30 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
nuclear@0 31 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
nuclear@0 32
nuclear@4 33 glGenTextures(1, &xfer_tex);
nuclear@4 34 glBindTexture(GL_TEXTURE_1D, xfer_tex);
nuclear@4 35 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
nuclear@4 36 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
nuclear@4 37 glTexImage1D(GL_TEXTURE_1D, 0, have_tex_float ? GL_RGB16F : GL_RGB, XFER_MAP_SZ, 0, GL_RGB, GL_FLOAT, 0);
nuclear@4 38
nuclear@0 39 return true;
nuclear@0 40 }
nuclear@0 41
nuclear@0 42 void RendererFast::destroy()
nuclear@0 43 {
nuclear@0 44 glDeleteTextures(1, &vol_tex);
nuclear@4 45 glDeleteTextures(1, &xfer_tex);
nuclear@4 46 }
nuclear@4 47
nuclear@4 48 void RendererFast::set_volume(Volume *vol)
nuclear@4 49 {
nuclear@4 50 vol_tex_valid = false;
nuclear@4 51 Renderer::set_volume(vol);
nuclear@4 52 }
nuclear@4 53
nuclear@4 54 Curve &RendererFast::transfer_curve(int color)
nuclear@4 55 {
nuclear@4 56 xfer_tex_valid = false;
nuclear@4 57 return Renderer::transfer_curve(color);
nuclear@0 58 }
nuclear@0 59
nuclear@5 60 void RendererFast::set_simple_transfer(float low, float high)
nuclear@5 61 {
nuclear@5 62 xfer_tex_valid = false;
nuclear@5 63 Renderer::set_simple_transfer(low, high);
nuclear@5 64 }
nuclear@5 65
nuclear@0 66 void RendererFast::update(unsigned int msec)
nuclear@0 67 {
nuclear@0 68 if(!vol) return;
nuclear@0 69
nuclear@0 70 // make sure the 3D volume texture is up to date
nuclear@0 71 if(!vol_tex_valid) {
nuclear@0 72 int xsz, ysz, zsz;
nuclear@0 73
nuclear@0 74 if((xsz = vol->num_samples(0)) > 0) {
nuclear@0 75 ysz = vol->num_samples(1);
nuclear@0 76 zsz = vol->num_samples(2);
nuclear@0 77 } else {
nuclear@0 78 xsz = ysz = zsz = 256;
nuclear@0 79 }
nuclear@0 80
nuclear@4 81 printf("updating 3D texture data (%dx%dx%d) ... ", xsz, ysz, zsz);
nuclear@4 82 fflush(stdout);
nuclear@4 83
nuclear@0 84 int int_fmt = GLEW_ARB_texture_float ? GL_RGBA16F_ARB : GL_RGBA;
nuclear@0 85
nuclear@0 86 glBindTexture(GL_TEXTURE_3D, vol_tex);
nuclear@0 87 glTexImage3D(GL_TEXTURE_3D, 0, int_fmt, xsz, ysz, zsz, 0, GL_RGBA, GL_FLOAT, 0);
nuclear@0 88
nuclear@0 89 float *slice = new float[xsz * ysz * 4];
nuclear@0 90
nuclear@0 91 for(int i=0; i<zsz; i++) {
nuclear@4 92 float z = (float)i;
nuclear@0 93 float *pptr = slice;
nuclear@0 94
nuclear@0 95 for(int j=0; j<ysz; j++) {
nuclear@4 96 float y = (float)j;
nuclear@0 97 for(int k=0; k<xsz; k++) {
nuclear@4 98 float x = (float)k;
nuclear@0 99
nuclear@0 100 // value in alpha channel
nuclear@0 101 pptr[3] = vol->valuef(x, y, z);
nuclear@0 102 // normal in rgb
nuclear@0 103 vol->normalf(pptr, x, y, z);
nuclear@0 104 // shift normal to the [0,1] range in case we don't have tex_float
nuclear@0 105 pptr[0] = pptr[0] * 0.5 + 0.5;
nuclear@0 106 pptr[1] = pptr[1] * 0.5 + 0.5;
nuclear@0 107 pptr[2] = pptr[2] * 0.5 + 0.5;
nuclear@4 108
nuclear@4 109 pptr += 4;
nuclear@0 110 }
nuclear@0 111 }
nuclear@0 112
nuclear@0 113 glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, i, xsz, ysz, 1, GL_RGBA, GL_FLOAT, slice);
nuclear@0 114 }
nuclear@0 115
nuclear@4 116 printf("done\n");
nuclear@4 117
nuclear@0 118 delete [] slice;
nuclear@0 119
nuclear@0 120 vol_tex_valid = true;
nuclear@0 121 }
nuclear@4 122
nuclear@4 123 if(!xfer_tex_valid) {
nuclear@4 124 float pixels[XFER_MAP_SZ * 3];
nuclear@4 125 float *pptr = pixels;
nuclear@4 126
nuclear@4 127 for(int i=0; i<XFER_MAP_SZ; i++) {
nuclear@4 128 float x = (float)i / (float)(XFER_MAP_SZ - 1);
nuclear@5 129
nuclear@5 130 // TODO make 0.1 a tweakable parameter
nuclear@5 131 float val = smoothstep(xfer_low - 0.1, xfer_low + 0.1, x);
nuclear@5 132 val *= 1.0 - smoothstep(xfer_high - 0.1, xfer_high + 0.1, x);
nuclear@5 133 *pptr++ = val;
nuclear@5 134 *pptr++ = val;
nuclear@5 135 *pptr++ = val;
nuclear@5 136 /*
nuclear@4 137 *pptr++ = xfer[0].value(x);
nuclear@4 138 *pptr++ = xfer[1].value(x);
nuclear@4 139 *pptr++ = xfer[2].value(x);
nuclear@5 140 */
nuclear@4 141 }
nuclear@4 142
nuclear@4 143 glBindTexture(GL_TEXTURE_1D, xfer_tex);
nuclear@4 144 glTexSubImage1D(GL_TEXTURE_1D, 0, 0, XFER_MAP_SZ, GL_RGB, GL_FLOAT, pixels);
nuclear@4 145
nuclear@4 146 xfer_tex_valid = true;
nuclear@4 147 }
nuclear@0 148 }
nuclear@0 149
nuclear@0 150 void RendererFast::render() const
nuclear@0 151 {
nuclear@0 152 if(!vol) return;
nuclear@0 153
nuclear@0 154 glClear(GL_COLOR_BUFFER_BIT);
nuclear@0 155
nuclear@0 156 glMatrixMode(GL_PROJECTION);
nuclear@0 157 glPushMatrix();
nuclear@0 158 glLoadIdentity();
nuclear@0 159
nuclear@0 160 glMatrixMode(GL_MODELVIEW);
nuclear@0 161 glPushMatrix();
nuclear@0 162 glLoadIdentity();
nuclear@0 163
nuclear@4 164 glUseProgram(sdr);
nuclear@4 165
nuclear@4 166 glActiveTexture(GL_TEXTURE0);
nuclear@0 167 glBindTexture(GL_TEXTURE_3D, vol_tex);
nuclear@4 168 glActiveTexture(GL_TEXTURE1);
nuclear@4 169 glBindTexture(GL_TEXTURE_1D, xfer_tex);
nuclear@4 170
nuclear@4 171 set_uniform_int(sdr, "vol_tex", 0);
nuclear@4 172 set_uniform_int(sdr, "xfer_tex", 1);
nuclear@4 173
nuclear@0 174 glBegin(GL_QUADS);
nuclear@4 175 glTexCoord3f(0, 0, 0.5); glVertex2f(-1, -1);
nuclear@4 176 glTexCoord3f(1, 0, 0.5); glVertex2f(1, -1);
nuclear@4 177 glTexCoord3f(1, 1, 0.5); glVertex2f(1, 1);
nuclear@4 178 glTexCoord3f(0, 1, 0.5); glVertex2f(-1, 1);
nuclear@0 179 glEnd();
nuclear@0 180
nuclear@4 181 glUseProgram(0);
nuclear@4 182
nuclear@0 183 glMatrixMode(GL_PROJECTION);
nuclear@0 184 glPopMatrix();
nuclear@0 185 glMatrixMode(GL_MODELVIEW);
nuclear@0 186 glPopMatrix();
nuclear@0 187 }
nuclear@5 188
nuclear@5 189 static inline float smoothstep(float a, float b, float x)
nuclear@5 190 {
nuclear@5 191 if(x < a) return 0.0;
nuclear@5 192 if(x >= b) return 1.0;
nuclear@5 193
nuclear@5 194 x = (x - a) / (b - a);
nuclear@5 195 return x * x * (3.0 - 2.0 * x);
nuclear@5 196 }