glviewvol

view src/rend_fast.cc @ 12:773f89037a35

added copyright headers
author John Tsiombikas <nuclear@member.fsf.org>
date Wed, 31 Dec 2014 07:57:04 +0200
parents 89efc666105c
children
line source
1 /*
2 glviewvol is an OpenGL 3D volume data viewer
3 Copyright (C) 2014 John Tsiombikas <nuclear@member.fsf.org>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18 #include <stdio.h>
19 #include "opengl.h"
20 #include "rend_fast.h"
21 #include "sdr.h"
23 #define DEF_PROXY_COUNT 512
24 #define XFER_MAP_SZ 512
26 static unsigned int sdr;
27 static bool have_tex_float;
29 RendererFast::RendererFast()
30 {
31 vol_tex = xfer_tex = 0;
32 vol_tex_valid = xfer_tex_valid = false;
33 proxy_count = DEF_PROXY_COUNT;
34 vbo_proxy_count = 0;
35 }
37 bool RendererFast::init()
38 {
39 if(!sdr) {
40 if(!(sdr = create_program_load("sdr/fast.v.glsl", "sdr/fast.p.glsl"))) {
41 return false;
42 }
43 have_tex_float = GLEW_ARB_texture_float;
44 }
46 glGenTextures(1, &vol_tex);
47 glBindTexture(GL_TEXTURE_3D, vol_tex);
48 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
49 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
50 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
51 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
52 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
54 glGenTextures(1, &xfer_tex);
55 glBindTexture(GL_TEXTURE_1D, xfer_tex);
56 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
57 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
58 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
59 glTexImage1D(GL_TEXTURE_1D, 0, have_tex_float ? GL_RGBA16F : GL_RGBA, XFER_MAP_SZ, 0, GL_RGB, GL_FLOAT, 0);
61 glGenBuffers(1, &vbo);
62 return true;
63 }
65 void RendererFast::destroy()
66 {
67 glDeleteTextures(1, &vol_tex);
68 glDeleteTextures(1, &xfer_tex);
69 glDeleteBuffers(1, &vbo);
70 }
72 void RendererFast::set_volume(Volume *vol)
73 {
74 vol_tex_valid = false;
75 Renderer::set_volume(vol);
76 }
78 void RendererFast::set_proxy_count(int n)
79 {
80 proxy_count = n;
81 }
83 int RendererFast::get_proxy_count() const
84 {
85 return proxy_count;
86 }
88 void RendererFast::update(unsigned int msec)
89 {
90 if(!vol) return;
92 // make sure the 3D volume texture is up to date
93 if(!vol_tex_valid) {
94 int xsz, ysz, zsz;
96 if((xsz = vol->num_samples(0)) > 0) {
97 ysz = vol->num_samples(1);
98 zsz = vol->num_samples(2);
99 } else {
100 xsz = ysz = zsz = 256;
101 }
103 printf("updating 3D texture data (%dx%dx%d) ... ", xsz, ysz, zsz);
104 fflush(stdout);
106 int int_fmt = GLEW_ARB_texture_float ? GL_RGBA16F_ARB : GL_RGBA;
108 glBindTexture(GL_TEXTURE_3D, vol_tex);
109 glTexImage3D(GL_TEXTURE_3D, 0, int_fmt, xsz, ysz, zsz, 0, GL_RGBA, GL_FLOAT, 0);
111 float *slice = new float[xsz * ysz * 4];
113 for(int i=0; i<zsz; i++) {
114 float z = (float)i;
116 #pragma omp parallel for schedule(dynamic)
117 for(int j=0; j<ysz; j++) {
118 float y = (float)j;
120 float *pptr = slice + (j * xsz) * 4;
121 for(int k=0; k<xsz; k++) {
122 float x = (float)k;
124 // value in alpha channel
125 pptr[3] = vol->valuef(x, y, z);
126 // normal in rgb
127 vol->normalf(pptr, x, y, z);
128 // shift normal to the [0,1] range in case we don't have tex_float
129 pptr[0] = pptr[0] * 0.5 + 0.5;
130 pptr[1] = pptr[1] * 0.5 + 0.5;
131 pptr[2] = pptr[2] * 0.5 + 0.5;
133 pptr += 4;
134 }
135 }
137 glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, i, xsz, ysz, 1, GL_RGBA, GL_FLOAT, slice);
138 }
140 printf("done\n");
142 delete [] slice;
144 vol_tex_valid = true;
145 }
147 if(1) {//if(!xfer_tex_valid) {
148 float pixels[XFER_MAP_SZ * 4];
149 float *pptr = pixels;
151 for(int i=0; i<XFER_MAP_SZ; i++) {
152 float x = (float)i / (float)(XFER_MAP_SZ - 1);
154 if(xfer) {
155 xfer->map(x, pptr);
156 pptr[3] = std::max(pptr[0], std::max(pptr[1], pptr[2]));
157 } else {
158 pptr[0] = pptr[1] = pptr[2] = pptr[3] = x;
159 }
160 pptr += 4;
161 }
163 glBindTexture(GL_TEXTURE_1D, xfer_tex);
164 glTexSubImage1D(GL_TEXTURE_1D, 0, 0, XFER_MAP_SZ, GL_RGBA, GL_FLOAT, pixels);
166 xfer_tex_valid = true;
167 }
169 // make sure the proxy object is up to date
170 if(proxy_count != vbo_proxy_count) {
171 static const float pat[][3] = {{-1, -1}, {1, -1}, {1, 1}, {-1, 1}};
173 int nverts = proxy_count * 4;
174 float *verts = new float[nverts * 3];
175 float *vptr = verts;
177 for(int i=0; i<proxy_count; i++) {
178 float z = 2.0 * (float)i / (float)(proxy_count - 1) - 1.0;
180 for(int j=0; j<4; j++) {
181 *vptr++ = pat[j][0];
182 *vptr++ = pat[j][1];
183 *vptr++ = z;
184 }
185 }
187 glBindBuffer(GL_ARRAY_BUFFER, vbo);
188 glBufferData(GL_ARRAY_BUFFER, nverts * 3 * sizeof(float), verts, GL_STATIC_DRAW);
189 glBindBuffer(GL_ARRAY_BUFFER, 0);
191 delete [] verts;
192 vbo_proxy_count = proxy_count;
193 }
194 }
196 void RendererFast::render() const
197 {
198 if(!vol) return;
200 glClear(GL_COLOR_BUFFER_BIT);
202 glUseProgram(sdr);
204 glActiveTexture(GL_TEXTURE0);
205 glBindTexture(GL_TEXTURE_3D, vol_tex);
206 glActiveTexture(GL_TEXTURE1);
207 glBindTexture(GL_TEXTURE_1D, xfer_tex);
209 set_uniform_int(sdr, "vol_tex", 0);
210 set_uniform_int(sdr, "xfer_tex", 1);
211 set_uniform_float(sdr, "zscale", zscale);
213 glEnable(GL_BLEND);
214 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
216 glBindBuffer(GL_ARRAY_BUFFER, vbo);
217 glVertexPointer(3, GL_FLOAT, 0, 0);
218 glBindBuffer(GL_ARRAY_BUFFER, 0);
220 glEnableClientState(GL_VERTEX_ARRAY);
221 glDrawArrays(GL_QUADS, 0, vbo_proxy_count * 4);
222 glDisableClientState(GL_VERTEX_ARRAY);
224 glDisable(GL_BLEND);
226 glUseProgram(0);
227 }