glviewvol

annotate src/rend_fast.cc @ 15:2a67ea257ac0

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