00001 #include "GL3DView.h"
00002
00003 #include <QtGui>
00004 #include <QtOpenGL>
00005
00006 #include "TimeCounter.h"
00007
00008 GLMultiProgramm::GLMultiProgramm()
00009 {
00010 }
00011
00012 void GLMultiProgramm::load(QString &vertexShaderName, QString &loopFragmentShaderName, QString &lastFragmentShaderName)
00013 {
00014 loopProgramm.load(vertexShaderName, loopFragmentShaderName);
00015 lastProgramm.load(vertexShaderName, lastFragmentShaderName);
00016 }
00017
00018 void GLMultiProgramm::link()
00019 {
00020 loopProgramm.link();
00021 lastProgramm.fragmentShader.maxLoopIterations = loopProgramm.fragmentShader.maxLoopIterations;
00022 lastProgramm.fragmentShader.loopIterations = loopProgramm.fragmentShader.loopIterations;
00023 lastProgramm.link();
00024 }
00025
00026 void GLMultiProgramm::free()
00027 {
00028 loopProgramm.free();
00029 lastProgramm.free();
00030 }
00031
00032 GL3DView::GL3DView() : GLView()
00033 {
00034 zRot = 0.0f;
00035 xRot = -90.0f;
00036 dist = -3.5f;
00037
00038 rtSize = 1024;
00039 rcBigSize = 1024;
00040 rcSmallSize = rcBigSize;
00041 minFps = 12;
00042
00043 aspectRatio = 1;
00044
00045 rcProgramms[0].load(QString("rc_vertex"), QString("rc_fragment_mip_loop"), QString("rc_fragment_mip_last"));
00046 rcProgramms[1].load(QString("rc_vertex"), QString("rc_fragment_dvr"), QString("rc_fragment_dvr"));
00047 rtProgramm.load(QString("rt_vertex"), QString("rt_fragment"));
00048
00049 transferTexture.setTypes(GL_RGBA8, GL_NEAREST);
00050
00051 rtBoxFrontBuffer.createTexture()->setTypes(GL_RGB10_A2, GL_LINEAR);
00052 rtBoxBackBuffer.createTexture()->setTypes(GL_RGB10_A2, GL_LINEAR);
00053 rcSmallBuffer.createTexture()->setTypes(GL_RGBA8, GL_NEAREST);
00054 rcBigBuffer.createTexture()->setTypes(GL_RGBA8, GL_NEAREST);
00055
00056 viewChanged = true;
00057 }
00058
00059 GL3DView::~GL3DView()
00060 {
00061 }
00062
00063 void GL3DView::initializeGL()
00064 {
00065 GLenum glError;
00066
00067 glError = glGetError();
00068 if(glError != GL_NO_ERROR)
00069 {
00070 qDebug() << "initializeGL3D: an error was still registered: " << (char*)gluErrorString(glError);
00071 }
00072
00073
00074 glShadeModel(GL_SMOOTH);
00075 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
00076 glDisable(GL_DEPTH_TEST);
00077 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
00078 glEnable(GL_CULL_FACE);
00079
00080 glMatrixMode(GL_PROJECTION);
00081 glLoadIdentity();
00082
00083 glMatrixMode(GL_MODELVIEW);
00084 glLoadIdentity();
00085
00086
00087 rtProgramm.link();
00088 for(int i = 0;i < shaderCount;++i)
00089 {
00090 rcProgramms[i].link();
00091 }
00092
00093
00094 transferTexture.create(4096);
00095 loadTransferFunction();
00096
00097
00098 rtBoxFrontBuffer.create(rtSize, rtSize);
00099 rtBoxBackBuffer.create(rtSize, rtSize);
00100 rcSmallBuffer.create(rcSmallSize, rcSmallSize);
00101 rcBigBuffer.create(rcBigSize, rcBigSize);
00102
00103 glError = glGetError();
00104 if(glError != GL_NO_ERROR)
00105 {
00106 qDebug() << "initializeGL3D error: " << (char*)gluErrorString(glError);
00107 }
00108
00109
00110 }
00111
00112 void GL3DView::uninitializeGL()
00113 {
00114 GLenum glError;
00115
00116 glError = glGetError();
00117 if(glError != GL_NO_ERROR)
00118 {
00119 qDebug() << "uninitializeGL3D: an error was still registered: " << (char*)gluErrorString(glError);
00120 }
00121
00122 for(int i = 0;i < shaderCount;++i)
00123 rcProgramms[i].free();
00124 rtProgramm.free();
00125
00126 transferTexture.free();
00127
00128 rtBoxFrontBuffer.free();
00129 rtBoxBackBuffer.free();
00130 rcSmallBuffer.free();
00131 rcBigBuffer.free();
00132
00133 glDisable(GL_CULL_FACE);
00134 glEnable(GL_DEPTH_TEST);
00135
00136 glError = glGetError();
00137 if(glError != GL_NO_ERROR)
00138 {
00139 qDebug() << "uninitializeGL3D error: " << (char*)gluErrorString(glError);
00140 }
00141 }
00142
00143 void GL3DView::paintGL()
00144 {
00145 LONGLONG startCount;
00146 GLenum glError;
00147
00148 if(volumeDesc->volumeTexture != 0)
00149 {
00150
00151
00152 if(transferFunctionDesc->hasChanged)
00153 {
00154 transferFunctionDesc->hasChanged = false;
00155 loadTransferFunction();
00156 }
00157
00158 if(viewChanged || volumeDesc->hasChanged)
00159 {
00160 viewChanged = false;
00161 drawColorCubes();
00162 }
00163
00164 if(volumeDesc->hasChanged || stateDesc->shaderChanged)
00165 {
00166 stateDesc->shaderChanged = false;
00167 volumeDesc->hasChanged = false;
00168
00169 GLuint maxNeededSteps;
00170 GLuint maxLoopStepsPerIteration, maxLastStepsPerIteration;
00171 GLuint loopStepsPerIteration, lastStepsPerIteration;
00172
00173 maxNeededSteps = volumeDesc->maxSideLength;
00174 maxLoopStepsPerIteration = rcProgramms[stateDesc->shaderIndex].loopProgramm.fragmentShader.maxLoopIterations;
00175 maxLastStepsPerIteration = rcProgramms[stateDesc->shaderIndex].lastProgramm.fragmentShader.maxLoopIterations;
00176
00177 qDebug() << "max needed steps: " << maxNeededSteps << " | max loop iterations: " << maxLoopStepsPerIteration << " | max last iterations: " << maxLastStepsPerIteration;
00178
00179 loopIterations = ((maxNeededSteps - maxLastStepsPerIteration) + maxLoopStepsPerIteration - 1) / maxLoopStepsPerIteration;
00180 loopStepsPerIteration = maxLoopStepsPerIteration;
00181 lastStepsPerIteration = maxNeededSteps - loopStepsPerIteration * loopIterations;
00182
00183 qDebug() << "loop iterations: " << loopIterations << " | loop steps: " << loopStepsPerIteration << " | last steps: " << lastStepsPerIteration;
00184
00185 rcProgramms[stateDesc->shaderIndex].lastProgramm.fragmentShader.loopIterations = lastStepsPerIteration;
00186 rcProgramms[stateDesc->shaderIndex].lastProgramm.link();
00187
00188 glFinish();
00189 }
00190
00191 startCount = TimeCounter_read();
00192
00193 drawVolume(&rcSmallBuffer);
00194
00195 float fps = 1000000.0f / TimeCounter_getDiffInUs(TimeCounter_read(), startCount);
00196 if(fps < minFps && rcSmallSize > 128)
00197 {
00198 rcSmallSize /= 2;
00199 rcSmallBuffer.create(rcSmallSize, rcSmallSize);
00200 qDebug() << "speed 3d draw to slow: " << fps << "fps | reduced size to: " << rcSmallSize;
00201 }
00202 else if(fps > minFps * 5 && rcSmallSize < rcBigSize)
00203 {
00204 rcSmallSize *= 2;
00205 rcSmallBuffer.create(rcSmallSize, rcSmallSize);
00206 qDebug() << "speed 3d draw to \"fast\": " << fps << "fps | increased size to: " << rcSmallSize;
00207 }
00208
00209 glBindTexture(GL_TEXTURE_2D, rcSmallBuffer.getTexture()->getTexture());
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225 glClear(GL_COLOR_BUFFER_BIT);
00226 glUseProgram(rtProgramm.programm);
00227
00228 glUniform1i(glGetUniformLocation(rtProgramm.programm, "rcTexture"), 0);
00229 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00230 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00231
00232 glBegin(GL_QUADS);
00233 glTexCoord2i(0, 0);
00234 glVertex3f(-1, -1, 0);
00235 glTexCoord2i(1, 0);
00236 glVertex3f(1, -1, 0);
00237 glTexCoord2i(1, 1);
00238 glVertex3f(1, 1, 0);
00239 glTexCoord2i(0, 1);
00240 glVertex3f(-1, 1, 0);
00241 glEnd();
00242
00243 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
00244 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
00245 glUseProgram(0);
00246 }
00247 else
00248 {
00249 glClear(GL_COLOR_BUFFER_BIT);
00250 }
00251
00252 glError = glGetError();
00253 if(glError != GL_NO_ERROR)
00254 {
00255 qDebug() << "paintGL3D error end: " << (char*)gluErrorString(glError);
00256 }
00257 }
00258
00259 void GL3DView::resizeGL(int width, int height)
00260 {
00261 GLenum glError;
00262
00263 glError = glGetError();
00264 if(glError != GL_NO_ERROR)
00265 {
00266 qDebug() << "resizeGL3D: an error was still registered: " << (char*)gluErrorString(glError);
00267 }
00268 glViewport(0, 0, width, height);
00269
00270 this->width = width;
00271 this->height = height;
00272 aspectRatio = (GLfloat)width / (GLfloat)height;
00273
00274 viewChanged = true;
00275 }
00276
00277 void GL3DView::mousePressEvent(QMouseEvent *event)
00278 {
00279 lastPos = event->pos();
00280 }
00281
00282 void GL3DView::mouseMoveEvent(QMouseEvent *event)
00283 {
00284 int dx = event->x() - lastPos.x();
00285 int dy = event->y() - lastPos.y();
00286
00287 if(event->buttons() & Qt::LeftButton) {
00288 zRot += dx;
00289 xRot += dy;
00290 viewChanged = true;
00291 parent->updateGL();
00292 }
00293 lastPos = event->pos();
00294 }
00295
00296 void GL3DView::wheelEvent(QWheelEvent *event)
00297 {
00298 float newDist;
00299
00300 newDist = dist + event->delta() / 200.0;
00301 if(newDist > -1.6f)
00302 {
00303 newDist = -1.6f;
00304 }
00305 if(newDist != dist)
00306 {
00307 dist = newDist;
00308 viewChanged = true;
00309 parent->updateGL();
00310 }
00311 }
00312
00313 void GL3DView::setColorVertex(GLfloat x, GLfloat y, GLfloat z)
00314 {
00315 x = x * volumeDesc->xNormLength + volumeDesc->xNormOffset;
00316 y = y * volumeDesc->yNormLength + volumeDesc->yNormOffset;
00317 z = z * volumeDesc->zNormLength + volumeDesc->zNormOffset;
00318 glColor3f(x, y, z);
00319
00320 x = x * 2 - 1;
00321 y = y * 2 - 1;
00322 z = z * 2 - 1;
00323 glVertex3f(x, y, z);
00324 }
00325
00326 void GL3DView::drawCube()
00327 {
00328 GLfloat xStartClip = 0.0f;
00329
00330 glBegin(GL_QUADS);
00331 setColorVertex(1, 1, 0);
00332 setColorVertex(xStartClip, 1, 0);
00333 setColorVertex(xStartClip, 1, 1);
00334 setColorVertex(1, 1, 1);
00335
00336 setColorVertex(1, 0, 1);
00337 setColorVertex(xStartClip, 0, 1);
00338 setColorVertex(xStartClip, 0, 0);
00339 setColorVertex(1, 0, 0);
00340
00341 setColorVertex(1, 1, 1);
00342 setColorVertex(xStartClip, 1, 1);
00343 setColorVertex(xStartClip, 0, 1);
00344 setColorVertex(1, 0, 1);
00345
00346 setColorVertex(1, 0, 0);
00347 setColorVertex(xStartClip, 0, 0);
00348 setColorVertex(xStartClip, 1, 0);
00349 setColorVertex(1, 1, 0);
00350
00351 setColorVertex(xStartClip, 1, 1);
00352 setColorVertex(xStartClip, 1, 0);
00353 setColorVertex(xStartClip, 0, 0);
00354 setColorVertex(xStartClip, 0, 1);
00355
00356 setColorVertex(1, 1, 0);
00357 setColorVertex(1, 1, 1);
00358 setColorVertex(1, 0, 1);
00359 setColorVertex(1, 0, 0);
00360 glEnd();
00361
00362 glColor3f(1.0f, 1.0f, 1.0f);
00363 }
00364
00365 void GL3DView::loadTransferFunction()
00366 {
00367 GLint width = transferTexture.getWidth();
00368 if(width != 4096) {
00369 GLint scale = 4096 / width;
00370 unsigned int *scaledTransferTexture = new unsigned int[width];
00371 for(GLint i = 0;i < width;++i)
00372 {
00373 scaledTransferTexture[i] = transferFunctionDesc->transferFunction[i * scale];
00374 }
00375 transferTexture.updateSubImage(0, width, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, (void*)scaledTransferTexture);
00376 delete [] scaledTransferTexture;
00377 }
00378 else
00379 {
00380 transferTexture.updateSubImage(0, 4096, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, (void*)transferFunctionDesc->transferFunction);
00381 }
00382 transferFunctionDesc->hasChanged = false;
00383
00384 }
00385
00386 void GL3DView::drawColorCubes()
00387 {
00388 GLenum glError;
00389
00390 glError = glGetError();
00391 if(glError != GL_NO_ERROR)
00392 {
00393 qDebug() << "drawColorCubes: an error was still registered: " << (char*)gluErrorString(glError);
00394 }
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407 glViewport(0, 0, rtSize, rtSize);
00408
00409 glMatrixMode(GL_PROJECTION);
00410 glLoadIdentity();
00411
00412 gluPerspective(45.0f, aspectRatio, 0.1f, 100.0f);
00413
00414 glMatrixMode(GL_MODELVIEW);
00415 glLoadIdentity();
00416 glTranslatef(0.0f, 0.0f, dist);
00417 glRotatef(xRot, 1.0f, 0.0f, 0.0f);
00418 glRotatef(zRot, 0.0f, 0.0f, 1.0f);
00419
00420 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, rtBoxFrontBuffer.getBuffer());
00421 glClear(GL_COLOR_BUFFER_BIT);
00422 glCullFace(GL_BACK);
00423
00424 drawCube();
00425
00426 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, rtBoxBackBuffer.getBuffer());
00427 glClear(GL_COLOR_BUFFER_BIT);
00428 glCullFace(GL_FRONT);
00429
00430 drawCube();
00431
00432 glCullFace(GL_BACK);
00433 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
00434
00435 glMatrixMode(GL_PROJECTION);
00436 glLoadIdentity();
00437
00438 glMatrixMode(GL_MODELVIEW);
00439 glLoadIdentity();
00440
00441 glViewport(0, 0, width, height);
00442 }
00443
00444 void GL3DView::drawVolume(GLFramebuffer *framebuffer)
00445 {
00446 GLenum glError;
00447
00448 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffer->getBuffer());
00449 glError = glGetError();
00450 if(glError != GL_NO_ERROR)
00451 {
00452 qDebug() << "paintGL3D error glBindFramebufferEXT: " << (char*)gluErrorString(glError);
00453 }
00454
00455 glViewport(0, 0, framebuffer->getWidth(), framebuffer->getHeight());
00456
00457 glClear(GL_COLOR_BUFFER_BIT);
00458
00459
00460
00461 GLuint rcProgramm, loopStepsPerIteration;
00462
00463 loopStepsPerIteration = 0;
00464
00465 if(loopIterations > 0)
00466 {
00467 rcProgramm = rcProgramms[stateDesc->shaderIndex].loopProgramm.programm;
00468 loopStepsPerIteration = rcProgramms[stateDesc->shaderIndex].loopProgramm.fragmentShader.loopIterations;
00469
00470 glUseProgram(rcProgramm);
00471
00472
00473 glBindTexture(GL_TEXTURE_3D, volumeDesc->volumeTexture);
00474 glUniform1i(glGetUniformLocation(rcProgramm, "volumeTexture"), 0);
00475 glActiveTexture(GL_TEXTURE1);
00476 glBindTexture(GL_TEXTURE_1D, transferTexture.getTexture());
00477 glUniform1i(glGetUniformLocation(rcProgramm, "transferTexture"), 1);
00478 glActiveTexture(GL_TEXTURE2);
00479 glBindTexture(GL_TEXTURE_2D, rtBoxFrontBuffer.getTexture()->getTexture());
00480 glUniform1i(glGetUniformLocation(rcProgramm, "frontTexture"), 2);
00481 glActiveTexture(GL_TEXTURE3);
00482 glBindTexture(GL_TEXTURE_2D, rtBoxBackBuffer.getTexture()->getTexture());
00483 glUniform1i(glGetUniformLocation(rcProgramm, "backTexture"), 3);
00484 glActiveTexture(GL_TEXTURE4);
00485 glBindTexture(GL_TEXTURE_2D, rcSmallBuffer.getTexture()->getTexture());
00486 glUniform1i(glGetUniformLocation(rcProgramm, "colorTexture"), 4);
00487 glUniform1f(glGetUniformLocation(rcProgramm, "stepDist"), volumeDesc->stepDist);
00488
00489 for(GLuint i = 0;i < loopIterations;++i) {
00490 glUniform1i(glGetUniformLocation(rcProgramm, "startStep"), i * loopStepsPerIteration);
00491 glBegin(GL_QUADS);
00492 glTexCoord2i(0, 0);
00493 glVertex3f(-1, -1, 0);
00494 glTexCoord2i(1, 0);
00495 glVertex3f(1, -1, 0);
00496 glTexCoord2i(1, 1);
00497 glVertex3f(1, 1, 0);
00498 glTexCoord2i(0, 1);
00499 glVertex3f(-1, 1, 0);
00500 glEnd();
00501
00502 glError = glGetError();
00503 if(glError != GL_NO_ERROR)
00504 {
00505 qDebug() << "paintGL3D error glEnd: " << (char*)gluErrorString(glError);
00506 }
00507 glFinish();
00508 }
00509 }
00510
00511 rcProgramm = rcProgramms[stateDesc->shaderIndex].lastProgramm.programm;
00512
00513 glUseProgram(rcProgramm);
00514
00515
00516 glBindTexture(GL_TEXTURE_3D, volumeDesc->volumeTexture);
00517 glUniform1i(glGetUniformLocation(rcProgramm, "volumeTexture"), 0);
00518 glActiveTexture(GL_TEXTURE1);
00519 glBindTexture(GL_TEXTURE_1D, transferTexture.getTexture());
00520 glUniform1i(glGetUniformLocation(rcProgramm, "transferTexture"), 1);
00521 glActiveTexture(GL_TEXTURE2);
00522 glBindTexture(GL_TEXTURE_2D, rtBoxFrontBuffer.getTexture()->getTexture());
00523 glUniform1i(glGetUniformLocation(rcProgramm, "frontTexture"), 2);
00524 glActiveTexture(GL_TEXTURE3);
00525 glBindTexture(GL_TEXTURE_2D, rtBoxBackBuffer.getTexture()->getTexture());
00526 glUniform1i(glGetUniformLocation(rcProgramm, "backTexture"), 3);
00527 glActiveTexture(GL_TEXTURE4);
00528 glBindTexture(GL_TEXTURE_2D, rcSmallBuffer.getTexture()->getTexture());
00529 glUniform1i(glGetUniformLocation(rcProgramm, "colorTexture"), 4);
00530 glUniform1f(glGetUniformLocation(rcProgramm, "stepDist"), volumeDesc->stepDist);
00531
00532 glUniform1i(glGetUniformLocation(rcProgramm, "startStep"), loopIterations * loopStepsPerIteration);
00533 glBegin(GL_QUADS);
00534 glTexCoord2i(0, 0);
00535 glVertex3f(-1, -1, 0);
00536 glTexCoord2i(1, 0);
00537 glVertex3f(1, -1, 0);
00538 glTexCoord2i(1, 1);
00539 glVertex3f(1, 1, 0);
00540 glTexCoord2i(0, 1);
00541 glVertex3f(-1, 1, 0);
00542 glEnd();
00543
00544 glError = glGetError();
00545 if(glError != GL_NO_ERROR)
00546 {
00547 qDebug() << "paintGL3D error glEnd: " << (char*)gluErrorString(glError);
00548 }
00549 glFinish();
00550
00551 glUseProgram(0);
00552 glActiveTexture(GL_TEXTURE0);
00553
00554 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
00555 glViewport(0, 0, width, height);
00556 }