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@10
|
6 #define DEF_PROXY_COUNT 512
|
nuclear@8
|
7 #define XFER_MAP_SZ 512
|
nuclear@4
|
8
|
nuclear@4
|
9 static unsigned int sdr;
|
nuclear@4
|
10 static bool have_tex_float;
|
nuclear@0
|
11
|
nuclear@0
|
12 RendererFast::RendererFast()
|
nuclear@0
|
13 {
|
nuclear@4
|
14 vol_tex = xfer_tex = 0;
|
nuclear@4
|
15 vol_tex_valid = xfer_tex_valid = false;
|
nuclear@10
|
16 proxy_count = DEF_PROXY_COUNT;
|
nuclear@8
|
17 vbo_proxy_count = 0;
|
nuclear@0
|
18 }
|
nuclear@0
|
19
|
nuclear@0
|
20 bool RendererFast::init()
|
nuclear@0
|
21 {
|
nuclear@4
|
22 if(!sdr) {
|
nuclear@4
|
23 if(!(sdr = create_program_load("sdr/fast.v.glsl", "sdr/fast.p.glsl"))) {
|
nuclear@4
|
24 return false;
|
nuclear@4
|
25 }
|
nuclear@4
|
26 have_tex_float = GLEW_ARB_texture_float;
|
nuclear@4
|
27 }
|
nuclear@4
|
28
|
nuclear@0
|
29 glGenTextures(1, &vol_tex);
|
nuclear@0
|
30 glBindTexture(GL_TEXTURE_3D, vol_tex);
|
nuclear@0
|
31 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
nuclear@0
|
32 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
nuclear@8
|
33 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
nuclear@8
|
34 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
nuclear@8
|
35 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
nuclear@0
|
36
|
nuclear@4
|
37 glGenTextures(1, &xfer_tex);
|
nuclear@4
|
38 glBindTexture(GL_TEXTURE_1D, xfer_tex);
|
nuclear@4
|
39 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
nuclear@4
|
40 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
nuclear@8
|
41 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
nuclear@6
|
42 glTexImage1D(GL_TEXTURE_1D, 0, have_tex_float ? GL_RGBA16F : GL_RGBA, XFER_MAP_SZ, 0, GL_RGB, GL_FLOAT, 0);
|
nuclear@4
|
43
|
nuclear@8
|
44 glGenBuffers(1, &vbo);
|
nuclear@0
|
45 return true;
|
nuclear@0
|
46 }
|
nuclear@0
|
47
|
nuclear@0
|
48 void RendererFast::destroy()
|
nuclear@0
|
49 {
|
nuclear@0
|
50 glDeleteTextures(1, &vol_tex);
|
nuclear@4
|
51 glDeleteTextures(1, &xfer_tex);
|
nuclear@8
|
52 glDeleteBuffers(1, &vbo);
|
nuclear@4
|
53 }
|
nuclear@4
|
54
|
nuclear@4
|
55 void RendererFast::set_volume(Volume *vol)
|
nuclear@4
|
56 {
|
nuclear@4
|
57 vol_tex_valid = false;
|
nuclear@4
|
58 Renderer::set_volume(vol);
|
nuclear@4
|
59 }
|
nuclear@4
|
60
|
nuclear@8
|
61 void RendererFast::set_proxy_count(int n)
|
nuclear@8
|
62 {
|
nuclear@8
|
63 proxy_count = n;
|
nuclear@8
|
64 }
|
nuclear@8
|
65
|
nuclear@8
|
66 int RendererFast::get_proxy_count() const
|
nuclear@8
|
67 {
|
nuclear@8
|
68 return proxy_count;
|
nuclear@8
|
69 }
|
nuclear@8
|
70
|
nuclear@0
|
71 void RendererFast::update(unsigned int msec)
|
nuclear@0
|
72 {
|
nuclear@0
|
73 if(!vol) return;
|
nuclear@0
|
74
|
nuclear@0
|
75 // make sure the 3D volume texture is up to date
|
nuclear@0
|
76 if(!vol_tex_valid) {
|
nuclear@0
|
77 int xsz, ysz, zsz;
|
nuclear@0
|
78
|
nuclear@0
|
79 if((xsz = vol->num_samples(0)) > 0) {
|
nuclear@0
|
80 ysz = vol->num_samples(1);
|
nuclear@0
|
81 zsz = vol->num_samples(2);
|
nuclear@0
|
82 } else {
|
nuclear@0
|
83 xsz = ysz = zsz = 256;
|
nuclear@0
|
84 }
|
nuclear@0
|
85
|
nuclear@4
|
86 printf("updating 3D texture data (%dx%dx%d) ... ", xsz, ysz, zsz);
|
nuclear@4
|
87 fflush(stdout);
|
nuclear@4
|
88
|
nuclear@0
|
89 int int_fmt = GLEW_ARB_texture_float ? GL_RGBA16F_ARB : GL_RGBA;
|
nuclear@0
|
90
|
nuclear@0
|
91 glBindTexture(GL_TEXTURE_3D, vol_tex);
|
nuclear@0
|
92 glTexImage3D(GL_TEXTURE_3D, 0, int_fmt, xsz, ysz, zsz, 0, GL_RGBA, GL_FLOAT, 0);
|
nuclear@0
|
93
|
nuclear@0
|
94 float *slice = new float[xsz * ysz * 4];
|
nuclear@0
|
95
|
nuclear@0
|
96 for(int i=0; i<zsz; i++) {
|
nuclear@4
|
97 float z = (float)i;
|
nuclear@0
|
98
|
nuclear@9
|
99 #pragma omp parallel for schedule(dynamic)
|
nuclear@0
|
100 for(int j=0; j<ysz; j++) {
|
nuclear@4
|
101 float y = (float)j;
|
nuclear@9
|
102
|
nuclear@9
|
103 float *pptr = slice + (j * xsz) * 4;
|
nuclear@0
|
104 for(int k=0; k<xsz; k++) {
|
nuclear@4
|
105 float x = (float)k;
|
nuclear@0
|
106
|
nuclear@0
|
107 // value in alpha channel
|
nuclear@0
|
108 pptr[3] = vol->valuef(x, y, z);
|
nuclear@0
|
109 // normal in rgb
|
nuclear@0
|
110 vol->normalf(pptr, x, y, z);
|
nuclear@0
|
111 // shift normal to the [0,1] range in case we don't have tex_float
|
nuclear@0
|
112 pptr[0] = pptr[0] * 0.5 + 0.5;
|
nuclear@0
|
113 pptr[1] = pptr[1] * 0.5 + 0.5;
|
nuclear@0
|
114 pptr[2] = pptr[2] * 0.5 + 0.5;
|
nuclear@4
|
115
|
nuclear@4
|
116 pptr += 4;
|
nuclear@0
|
117 }
|
nuclear@0
|
118 }
|
nuclear@0
|
119
|
nuclear@0
|
120 glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, i, xsz, ysz, 1, GL_RGBA, GL_FLOAT, slice);
|
nuclear@0
|
121 }
|
nuclear@0
|
122
|
nuclear@4
|
123 printf("done\n");
|
nuclear@4
|
124
|
nuclear@0
|
125 delete [] slice;
|
nuclear@0
|
126
|
nuclear@0
|
127 vol_tex_valid = true;
|
nuclear@0
|
128 }
|
nuclear@4
|
129
|
nuclear@6
|
130 if(1) {//if(!xfer_tex_valid) {
|
nuclear@6
|
131 float pixels[XFER_MAP_SZ * 4];
|
nuclear@4
|
132 float *pptr = pixels;
|
nuclear@4
|
133
|
nuclear@4
|
134 for(int i=0; i<XFER_MAP_SZ; i++) {
|
nuclear@4
|
135 float x = (float)i / (float)(XFER_MAP_SZ - 1);
|
nuclear@5
|
136
|
nuclear@6
|
137 if(xfer) {
|
nuclear@6
|
138 xfer->map(x, pptr);
|
nuclear@7
|
139 pptr[3] = std::max(pptr[0], std::max(pptr[1], pptr[2]));
|
nuclear@6
|
140 } else {
|
nuclear@6
|
141 pptr[0] = pptr[1] = pptr[2] = pptr[3] = x;
|
nuclear@6
|
142 }
|
nuclear@6
|
143 pptr += 4;
|
nuclear@4
|
144 }
|
nuclear@4
|
145
|
nuclear@4
|
146 glBindTexture(GL_TEXTURE_1D, xfer_tex);
|
nuclear@6
|
147 glTexSubImage1D(GL_TEXTURE_1D, 0, 0, XFER_MAP_SZ, GL_RGBA, GL_FLOAT, pixels);
|
nuclear@4
|
148
|
nuclear@4
|
149 xfer_tex_valid = true;
|
nuclear@4
|
150 }
|
nuclear@8
|
151
|
nuclear@8
|
152 // make sure the proxy object is up to date
|
nuclear@8
|
153 if(proxy_count != vbo_proxy_count) {
|
nuclear@8
|
154 static const float pat[][3] = {{-1, -1}, {1, -1}, {1, 1}, {-1, 1}};
|
nuclear@8
|
155
|
nuclear@8
|
156 int nverts = proxy_count * 4;
|
nuclear@8
|
157 float *verts = new float[nverts * 3];
|
nuclear@8
|
158 float *vptr = verts;
|
nuclear@8
|
159
|
nuclear@8
|
160 for(int i=0; i<proxy_count; i++) {
|
nuclear@8
|
161 float z = 2.0 * (float)i / (float)(proxy_count - 1) - 1.0;
|
nuclear@8
|
162
|
nuclear@8
|
163 for(int j=0; j<4; j++) {
|
nuclear@8
|
164 *vptr++ = pat[j][0];
|
nuclear@8
|
165 *vptr++ = pat[j][1];
|
nuclear@8
|
166 *vptr++ = z;
|
nuclear@8
|
167 }
|
nuclear@8
|
168 }
|
nuclear@8
|
169
|
nuclear@8
|
170 glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
nuclear@8
|
171 glBufferData(GL_ARRAY_BUFFER, nverts * 3 * sizeof(float), verts, GL_STATIC_DRAW);
|
nuclear@8
|
172 glBindBuffer(GL_ARRAY_BUFFER, 0);
|
nuclear@8
|
173
|
nuclear@8
|
174 delete [] verts;
|
nuclear@8
|
175 vbo_proxy_count = proxy_count;
|
nuclear@8
|
176 }
|
nuclear@0
|
177 }
|
nuclear@0
|
178
|
nuclear@0
|
179 void RendererFast::render() const
|
nuclear@0
|
180 {
|
nuclear@0
|
181 if(!vol) return;
|
nuclear@0
|
182
|
nuclear@0
|
183 glClear(GL_COLOR_BUFFER_BIT);
|
nuclear@0
|
184
|
nuclear@4
|
185 glUseProgram(sdr);
|
nuclear@4
|
186
|
nuclear@4
|
187 glActiveTexture(GL_TEXTURE0);
|
nuclear@0
|
188 glBindTexture(GL_TEXTURE_3D, vol_tex);
|
nuclear@4
|
189 glActiveTexture(GL_TEXTURE1);
|
nuclear@4
|
190 glBindTexture(GL_TEXTURE_1D, xfer_tex);
|
nuclear@4
|
191
|
nuclear@4
|
192 set_uniform_int(sdr, "vol_tex", 0);
|
nuclear@4
|
193 set_uniform_int(sdr, "xfer_tex", 1);
|
nuclear@10
|
194 set_uniform_float(sdr, "zscale", zscale);
|
nuclear@4
|
195
|
nuclear@8
|
196 glEnable(GL_BLEND);
|
nuclear@8
|
197 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
nuclear@8
|
198
|
nuclear@8
|
199 glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
nuclear@8
|
200 glVertexPointer(3, GL_FLOAT, 0, 0);
|
nuclear@8
|
201 glBindBuffer(GL_ARRAY_BUFFER, 0);
|
nuclear@8
|
202
|
nuclear@8
|
203 glEnableClientState(GL_VERTEX_ARRAY);
|
nuclear@8
|
204 glDrawArrays(GL_QUADS, 0, vbo_proxy_count * 4);
|
nuclear@8
|
205 glDisableClientState(GL_VERTEX_ARRAY);
|
nuclear@8
|
206
|
nuclear@8
|
207 glDisable(GL_BLEND);
|
nuclear@0
|
208
|
nuclear@4
|
209 glUseProgram(0);
|
nuclear@0
|
210 }
|