glviewvol

annotate src/rend_fast.cc @ 10:89efc666105c

mostly done
author John Tsiombikas <nuclear@member.fsf.org>
date Wed, 31 Dec 2014 05:21:47 +0200
parents 931a6b35f1cd
children 773f89037a35
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 }