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 }
|