From 986c7a764f813726e2e7663e2639b7a283633ca2 Mon Sep 17 00:00:00 2001 From: Hans-Christian Helltegen Date: Fri, 28 Feb 2014 21:41:56 +0000 Subject: [PATCH] Improved twopass raycaster. Started working on singlepassraycaster --- shaders/exitpoints.frag | 11 - shaders/exitpoints.vert | 3 - shaders/singlepassraycaster.frag | 2 + shaders/singlepassraycaster.gs | 6 +- shaders/singlepassraycaster.vert | 12 +- ...dertoscreen.frag => twopassraycaster.frag} | 13 +- ...dertoscreen.vert => twopassraycaster.vert} | 0 src/rendering/volumeraycaster.cpp | 270 ++++++++++++------ src/rendering/volumeraycaster.h | 8 +- 9 files changed, 197 insertions(+), 128 deletions(-) rename shaders/{rendertoscreen.frag => twopassraycaster.frag} (73%) rename shaders/{rendertoscreen.vert => twopassraycaster.vert} (100%) diff --git a/shaders/exitpoints.frag b/shaders/exitpoints.frag index 5ddaaa0ad3..1ea86ecb38 100644 --- a/shaders/exitpoints.frag +++ b/shaders/exitpoints.frag @@ -1,19 +1,8 @@ #version 400 core -// uniform sampler2D texUnit; - in vec3 vPosition; -in vec2 texCoords; out vec4 fragColor; void main() { fragColor = vec4(vPosition+0.5, 1.0); - // if (fragColor.x <= 0.55 && fragColor.x >= 0.45) - // fragColor = vec4(1.0); - // else if (fragColor.y <= 0.55 && fragColor.y >= 0.45) - // fragColor = vec4(1.0); - - // fragColor = vec4(texCoords.x, texCoords.y, 0.0, 1.0); - - // fragColor = texture(texUnit, -texCoords+1); } \ No newline at end of file diff --git a/shaders/exitpoints.vert b/shaders/exitpoints.vert index d5afded9d6..0668ef5618 100644 --- a/shaders/exitpoints.vert +++ b/shaders/exitpoints.vert @@ -1,14 +1,11 @@ #version 400 core -layout(location = 0) in vec2 texCoordinate; layout(location = 2) in vec3 vertPosition; uniform mat4 modelViewProjection; out vec3 vPosition; -out vec2 texCoords; void main() { gl_Position = modelViewProjection * vec4(vertPosition, 1.0); vPosition = vertPosition; - texCoords = texCoordinate; } \ No newline at end of file diff --git a/shaders/singlepassraycaster.frag b/shaders/singlepassraycaster.frag index b455b78902..0aa3b04703 100644 --- a/shaders/singlepassraycaster.frag +++ b/shaders/singlepassraycaster.frag @@ -94,4 +94,6 @@ void main() FragColor.rgb = Lo; FragColor.a = 1-T; + + FragColor = vec4(1.0, 0.0, 1.0, 1.0); } \ No newline at end of file diff --git a/shaders/singlepassraycaster.gs b/shaders/singlepassraycaster.gs index 02e839040f..0fa9be32e2 100644 --- a/shaders/singlepassraycaster.gs +++ b/shaders/singlepassraycaster.gs @@ -6,9 +6,9 @@ layout(triangle_strip, max_vertices = 24) out; in vec4 vPosition[1]; uniform mat4 modelViewProjection; -// uniform mat4 ProjectionMatrix; -// uniform mat4 ViewMatrix; -// uniform mat4 Modelview; +uniform mat4 ProjectionMatrix; +uniform mat4 ViewMatrix; +uniform mat4 Modelview; vec4 objCube[8]; // Object space coordinate of cube corner vec4 ndcCube[8]; // Normalized device coordinate of cube corner diff --git a/shaders/singlepassraycaster.vert b/shaders/singlepassraycaster.vert index 2d209d0ccb..0f7c30d7fc 100644 --- a/shaders/singlepassraycaster.vert +++ b/shaders/singlepassraycaster.vert @@ -1,11 +1,13 @@ #version 400 core +layout(location = 5) in vec3 vertPosition; +uniform mat4 modelViewProjection; + in vec4 Position; out vec4 vPosition; -uniform mat4 modelViewProjection; -void main() -{ - gl_Position = modelViewProjection * Position; - vPosition = Position; +void main() { + vec4 vPos = vec4(vertPosition, 1.0); + gl_Position = modelViewProjection * vPos; + vPosition = vPos; } \ No newline at end of file diff --git a/shaders/rendertoscreen.frag b/shaders/twopassraycaster.frag similarity index 73% rename from shaders/rendertoscreen.frag rename to shaders/twopassraycaster.frag index b16026dc4c..7e271b9a24 100644 --- a/shaders/rendertoscreen.frag +++ b/shaders/twopassraycaster.frag @@ -3,6 +3,7 @@ uniform sampler2D texBack, texFront; uniform sampler3D texVolume; uniform int screenWidth, screenHeight; +uniform float stepSize; in vec3 vPosition; in vec2 texCoords; @@ -14,18 +15,14 @@ void main() {; vec3 front = texture(texFront, texCoords).xyz; vec3 back = texture(texBack, texCoords).xyz; vec3 direction = back-front; + float directionLength = length(direction); direction = normalize(direction); vec3 position = front; - float stepSize = 0.05; - vec4 color = vec4(0); - vec4 tmp; - + vec4 tmp, color = vec4(0); - for (int i = 0; i < 100; ++i) { + while (length(position-front) < directionLength && color.r != 1.0) { tmp = texture(texVolume, position); - if (tmp.r > color.r) - color = tmp; - + color = max(color, tmp); // MIP position = position + direction * stepSize; } diff --git a/shaders/rendertoscreen.vert b/shaders/twopassraycaster.vert similarity index 100% rename from shaders/rendertoscreen.vert rename to shaders/twopassraycaster.vert diff --git a/src/rendering/volumeraycaster.cpp b/src/rendering/volumeraycaster.cpp index 1c942c990e..38c9b9474c 100644 --- a/src/rendering/volumeraycaster.cpp +++ b/src/rendering/volumeraycaster.cpp @@ -3,11 +3,26 @@ #include #include #include +#include namespace openspace { GLuint vertexArray = GL_FALSE; GLuint vertexPositionBuffer = GL_FALSE; +GLuint CubeCenterVbo, SlotPosition; +float _stepSize = 0.05f; +sgct::SharedDouble curr_time(0.0); + +void keyCallback(int key, int action); + +GLuint CreatePointVbo(float x, float y, float z) { + float p[] = {x, y, z}; + GLuint vbo; + glGenBuffers(1, &vbo); + glBindBuffer(GL_ARRAY_BUFFER, vbo); + glBufferData(GL_ARRAY_BUFFER, sizeof(p), &p[0], GL_STATIC_DRAW); + return vbo; +} VolumeRaycaster::VolumeRaycaster() { initialize(); @@ -46,42 +61,69 @@ void VolumeRaycaster::initialize() { glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind buffer glBindVertexArray(0); //unbind array - myBox = new sgct_utils::SGCTBox(1.0f, sgct_utils::SGCTBox::Regular); +// myBox = new sgct_utils::SGCTBox(1.0f, sgct_utils::SGCTBox::Regular); // ------ VOLUME READING ---------------- - const char* filename = "../openspace-data/skull_256x256x256_8.raw"; - int dimensions[3]; - dimensions[0] = 256;dimensions[1] = 256;dimensions[2] = 256; - createVolumetexture(filename, dimensions); + const char* filename = absPath("${BASE_PATH}/openspace-data/skull_256x256x256_8.raw").c_str(); + glm::ivec3 dimensions = glm::ivec3(256); + _volume = createVolumetexture(filename, dimensions); // ------ SETUP SHADERS ----------------- - _FBOProgram = new ProgramObject("RaycastProgram"); - ShaderObject* vertexShader = new ShaderObject(ShaderObject::ShaderTypeVertex, absPath("${BASE_PATH}/shaders/exitpoints.vert")); - ShaderObject* fragmentShader = new ShaderObject(ShaderObject::ShaderTypeFragment, absPath("${BASE_PATH}/shaders/exitpoints.frag")); - _FBOProgram->attachObject(vertexShader); - _FBOProgram->attachObject(fragmentShader); - _FBOProgram->compileShaderObjects(); - _FBOProgram->linkProgramObject(); + _fboProgram = new ProgramObject("RaycastProgram"); + ShaderObject* vertexShader = new ShaderObject(ShaderObject::ShaderTypeVertex, + absPath("${BASE_PATH}/shaders/exitpoints.vert")); + ShaderObject* fragmentShader = new ShaderObject(ShaderObject::ShaderTypeFragment, + absPath("${BASE_PATH}/shaders/exitpoints.frag")); + _fboProgram->attachObject(vertexShader); + _fboProgram->attachObject(fragmentShader); + _fboProgram->compileShaderObjects(); + _fboProgram->linkProgramObject(); - _screenProgram = new ProgramObject("RaycastProgram"); - vertexShader = new ShaderObject(ShaderObject::ShaderTypeVertex, absPath("${BASE_PATH}/shaders/rendertoscreen.vert")); - fragmentShader = new ShaderObject(ShaderObject::ShaderTypeFragment, absPath("${BASE_PATH}/shaders/rendertoscreen.frag")); - _screenProgram->attachObject(vertexShader); - _screenProgram->attachObject(fragmentShader); - _screenProgram->compileShaderObjects(); - _screenProgram->linkProgramObject(); - _screenProgram->setUniform("texBack", 0); - _screenProgram->setUniform("texFront", 1); - _screenProgram->setUniform("texVolume", 2); - _screenProgram->setUniform("screenWidth", sgct::Engine::instance()->getActiveXResolution()); - _screenProgram->setUniform("screenHeight", sgct::Engine::instance()->getActiveYResolution()); + _twopassProgram = new ProgramObject("RaycastProgram"); + vertexShader = new ShaderObject(ShaderObject::ShaderTypeVertex, + absPath("${BASE_PATH}/shaders/twopassraycaster.vert")); + fragmentShader = new ShaderObject(ShaderObject::ShaderTypeFragment, + absPath("${BASE_PATH}/shaders/twopassraycaster.frag")); + _twopassProgram->attachObject(vertexShader); + _twopassProgram->attachObject(fragmentShader); + _twopassProgram->compileShaderObjects(); + _twopassProgram->linkProgramObject(); + _twopassProgram->setUniform("texBack", 0); + _twopassProgram->setUniform("texFront", 1); + _twopassProgram->setUniform("texVolume", 2); + _twopassProgram->setUniform("screenWidth", sgct::Engine::instance()->getActiveXResolution()); + _twopassProgram->setUniform("screenHeight", sgct::Engine::instance()->getActiveYResolution()); + _twopassProgram->setUniform("stepSize", _stepSize); + float top = sgct::Engine::instance()->getActiveWindowPtr()->getCurrentViewport()->getFrustum()->getTop(); + float near = sgct::Engine::instance()->getActiveWindowPtr()->getCurrentViewport()->getFrustum()->getNear(); + float FOV = float(atan(top / near)) * (180.0 / 3.141592653589793) * 2.0f; + float focalLength = 1.0f / tan(FOV / 2); + int x = sgct::Engine::instance()->getActiveXResolution(); + int y = sgct::Engine::instance()->getActiveYResolution(); + CubeCenterVbo = CreatePointVbo(0, 0, 0); + + _singlepassProgram = new ProgramObject("RaycastProgram"); + vertexShader = new ShaderObject(ShaderObject::ShaderTypeVertex, + absPath("${BASE_PATH}/shaders/singlepassraycaster.vert")); + fragmentShader = new ShaderObject(ShaderObject::ShaderTypeFragment, + absPath("${BASE_PATH}/shaders/singlepassraycaster.frag")); + ShaderObject* geometryShader = new ShaderObject(ShaderObject::ShaderTypeGeometry, + absPath("${BASE_PATH}/shaders/singlepassraycaster.gs")); + _singlepassProgram->attachObject(vertexShader); + _singlepassProgram->attachObject(fragmentShader); + _singlepassProgram->attachObject(geometryShader); + _singlepassProgram->compileShaderObjects(); + _singlepassProgram->linkProgramObject(); + _singlepassProgram->setUniform("FocalLength", focalLength); + _singlepassProgram->setUniform("WindowSize", glm::vec2(x,y)); + _singlepassProgram->setUniform("Density", 2); + + sgct::Engine::instance()->setKeyboardCallbackFunction(keyCallback); // ------ SETUP FBO --------------------- _fbo = new FramebufferObject(); _fbo->activate(); - int x = sgct::Engine::instance()->getActiveXResolution(); - int y = sgct::Engine::instance()->getActiveYResolution(); _backTexture = new Texture(glm::size3_t(x,y,1)); _frontTexture = new Texture(glm::size3_t(x,y,1)); _backTexture->uploadTexture(); @@ -92,85 +134,125 @@ void VolumeRaycaster::initialize() { _fbo->deactivate(); } -void VolumeRaycaster::render() { - glm::mat4 modelViewProjectionMatrix = sgct::Engine::instance()->getActiveModelViewProjectionMatrix(); - _FBOProgram->setUniform("modelViewProjection", modelViewProjectionMatrix); +void keyCallback(int key, int action) { + switch( key ) { + case GLFW_KEY_UP: + case 'W': + _stepSize += 0.01; + std::cout << "Stepsize: " << _stepSize << std::endl; + break; -// ------ DRAW TO FBO ------------------- - _sgctFBO = FramebufferObject::getActiveObject(); // Save SGCTs main FBO - _fbo->activate(); - _FBOProgram->activate(); + case GLFW_KEY_DOWN: + case 'S': + if (_stepSize > 0.015) + _stepSize -= 0.01; -// Draw backface - glDrawBuffer(GL_COLOR_ATTACHMENT0); - glClearColor(0.2f, 0.2f, 0.2f, 0); - glClear(GL_COLOR_BUFFER_BIT); - glEnable(GL_CULL_FACE); - glCullFace(GL_FRONT); - myBox->draw(); - glDisable(GL_CULL_FACE); - -// Draw frontface - glDrawBuffer(GL_COLOR_ATTACHMENT1); - glClear(GL_COLOR_BUFFER_BIT); - glClearColor(0.2f, 0.2f, 0.2f, 0); - glEnable(GL_CULL_FACE); - glCullFace(GL_BACK); - myBox->draw(); - glDisable(GL_CULL_FACE); - - _FBOProgram->deactivate(); - _fbo->deactivate(); - -// ------ DRAW TO SCREEN ---------------- - glBindFramebuffer(GL_FRAMEBUFFER, _sgctFBO); // Re-bind SGCTs main FBO - _screenProgram->activate(); - -// Set textures - glActiveTexture(GL_TEXTURE0); - _backTexture->bind(); - glActiveTexture(GL_TEXTURE1); - _frontTexture->bind(); - glActiveTexture(GL_TEXTURE2); - glBindTexture(GL_TEXTURE_3D, _volumeTexture); - -// Draw screenquad - glClearColor(0.2f, 0.2f, 0.2f, 0); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glBindVertexArray(vertexArray); - glDrawArrays(GL_TRIANGLES, 0, 6); - glBindVertexArray(0); - - _screenProgram->deactivate(); + std::cout << "Stepsize: " << _stepSize << std::endl; + break; + } } -void VolumeRaycaster::createVolumetexture(const char *filename, int dimensions[3]) { - // Make sure that the texture is not used - if(glIsTexture(_volumeTexture)) - glDeleteTextures(1, &_volumeTexture); +void VolumeRaycaster::render() { + float speed = 50.0f; + curr_time.setVal(sgct::Engine::getTime()); + glm::mat4 scene_mat = glm::rotate( glm::mat4(1.0f), static_cast( curr_time.getVal() ) * speed, glm::vec3(0.0f, 1.0f, 0.0f)); + glm::mat4 modelViewProjectionMatrix = sgct::Engine::instance()->getActiveModelViewProjectionMatrix() * scene_mat; - int size = dimensions[0]*dimensions[1]*dimensions[2]; +//// ------ TWO PASS ---------------------- +//// ------ DRAW TO FBO ------------------- +// _sgctFBO = FramebufferObject::getActiveObject(); // Save SGCTs main FBO +// _fbo->activate(); +// _fboProgram->activate(); +// _fboProgram->setUniform("modelViewProjection", modelViewProjectionMatrix); +// +//// Draw backface +// glDrawBuffer(GL_COLOR_ATTACHMENT0); +// glClearColor(0.2f, 0.2f, 0.2f, 0); +// glClear(GL_COLOR_BUFFER_BIT); +// glEnable(GL_CULL_FACE); +// glCullFace(GL_FRONT); +// myBox->draw(); +// glDisable(GL_CULL_FACE); +// +//// Draw frontface +// glDrawBuffer(GL_COLOR_ATTACHMENT1); +// glClear(GL_COLOR_BUFFER_BIT); +// glClearColor(0.2f, 0.2f, 0.2f, 0); +// glEnable(GL_CULL_FACE); +// glCullFace(GL_BACK); +// myBox->draw(); +// glDisable(GL_CULL_FACE); +// +// _fboProgram->deactivate(); +// _fbo->deactivate(); +// +//// ------ DRAW TO SCREEN ---------------- +// glBindFramebuffer(GL_FRAMEBUFFER, _sgctFBO); // Re-bind SGCTs main FBO +// _twopassProgram->activate(); +// _twopassProgram->setUniform("stepSize", _stepSize); +// +//// Set textures +// glActiveTexture(GL_TEXTURE0); +// _backTexture->bind(); +// glActiveTexture(GL_TEXTURE1); +// _frontTexture->bind(); +// glActiveTexture(GL_TEXTURE2); +// _volume->bind(); +// +//// Draw screenquad +// glClearColor(0.2f, 0.2f, 0.2f, 0); +// glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); +// glBindVertexArray(vertexArray); +// glDrawArrays(GL_TRIANGLES, 0, 6); +// glBindVertexArray(0); +// +// _twopassProgram->deactivate(); + +// ------ SINGLE PASS ------------------- + glm::mat4 modelView = sgct::Engine::instance()->getActiveModelViewMatrix(); + glm::vec3 eyePos = *sgct::Engine::instance()->getUserPtr()->getPosPtr(); + _singlepassProgram->setUniform("modelViewProjection", modelViewProjectionMatrix); + _singlepassProgram->setUniform("Modelview", modelView); + _singlepassProgram->setUniform("RayOrigin", glm::transpose(modelView)*glm::vec4(eyePos, 1.0)); + _singlepassProgram->setUniform("ProjectionMatrix", sgct::Engine::instance()->getActiveProjectionMatrix()); + _singlepassProgram->setUniform("ViewMatrix", sgct::Engine::instance()->getActiveViewMatrix()); + + CubeCenterVbo = CreatePointVbo(0, 0, 0); + glBindBuffer(GL_ARRAY_BUFFER, CubeCenterVbo); + GLuint SlotPosition = 5; + glEnableVertexAttribArray(SlotPosition); + glVertexAttribPointer(SlotPosition, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), 0); + glEnableVertexAttribArray(SlotPosition); + glClearColor(0.2f, 0.2f, 0.2f, 0); + glClear(GL_COLOR_BUFFER_BIT); + _singlepassProgram->activate(); + + glActiveTexture(GL_TEXTURE2); + _volume->bind(); + + glDrawArrays(GL_POINTS, 0, 1); + + _singlepassProgram->deactivate(); +} + +Texture* VolumeRaycaster::createVolumetexture(const char *filename, glm::ivec3 dimensions) { + int size = dimensions.x*dimensions.y*dimensions.z; GLubyte *data = new GLubyte[size]; if( FILE *fin = fopen(filename, "rb") ){ - fread(data, sizeof(unsigned char), size, fin); - fclose(fin); + fread(data, sizeof(unsigned char), size, fin); + fclose(fin); + } else { + fprintf( stderr, "Could not open file '%s'\n", filename ); } - else - fprintf( stderr, "Could not open file '%s'\n", filename ); - glPixelStorei(GL_UNPACK_ALIGNMENT,1); - glGenTextures(1, &_volumeTexture); - glBindTexture(GL_TEXTURE_3D, _volumeTexture); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_BORDER); - glTexImage3D(GL_TEXTURE_3D, 0, GL_R8, dimensions[0], dimensions[1],dimensions[2],0, GL_RED, GL_UNSIGNED_BYTE,data); - glBindTexture(GL_TEXTURE_3D, 0); + Texture* texture = new Texture(data, glm::size3_t(dimensions), + Texture::Format::Red, GL_R8, GL_UNSIGNED_BYTE, + Texture::FilterMode::Linear, Texture::WrappingMode::ClampToBorder); + texture->uploadTexture(); + delete []data; - std::cout << "Volume texture created" << std::endl; + return texture; } }// namespace openspace diff --git a/src/rendering/volumeraycaster.h b/src/rendering/volumeraycaster.h index f9c760bde9..9d427cb73e 100644 --- a/src/rendering/volumeraycaster.h +++ b/src/rendering/volumeraycaster.h @@ -19,19 +19,19 @@ public: void render(); private: - void createVolumetexture(const char *filename, int dimensions[3]); + Texture* createVolumetexture(const char *filename, glm::ivec3 dimensions); FramebufferObject* _fbo; Texture* _backTexture; Texture* _frontTexture; Texture* _volume; - GLuint _volumeTexture; GLuint _sgctFBO; - ProgramObject* _FBOProgram; - ProgramObject* _screenProgram; + ProgramObject *_fboProgram, *_twopassProgram, *_singlepassProgram; sgct_utils::SGCTBox* myBox; + + }; } // namespace openspace