From 2dab48b85082ea960465e13f07b80a81eb4302f4 Mon Sep 17 00:00:00 2001 From: Hans-Christian Helltegen Date: Wed, 21 May 2014 15:11:13 -0400 Subject: [PATCH 01/49] Updated kameleonwrapper to be able to load several variables into a RGB texture. Added support for 'Variables' tag in .mod scenegraph files which takes 3 variables as an array --- include/openspace/util/kameleonwrapper.h | 2 + src/rendering/renderablevolume.cpp | 154 ++++++++++------- src/rendering/renderablevolumeexpert.cpp | 7 +- src/util/kameleonwrapper.cpp | 205 +++++++++++++++-------- 4 files changed, 235 insertions(+), 133 deletions(-) diff --git a/include/openspace/util/kameleonwrapper.h b/include/openspace/util/kameleonwrapper.h index 3ba0afbbb0..a92483b094 100644 --- a/include/openspace/util/kameleonwrapper.h +++ b/include/openspace/util/kameleonwrapper.h @@ -46,8 +46,10 @@ public: KameleonWrapper(const std::string& filename, Model model); ~KameleonWrapper(); float* getUniformSampledValues(const std::string& var, glm::size3_t outDimensions); + float* getUniformSampledVectorValues(const std::string& xVar, const std::string& yVar, const std::string& zVar, glm::size3_t outDimensions); private: + void getGridVariables(std::string& x, std::string& y, std::string& z); ccmc::Model* _model; Model _type; ccmc::Interpolator* _interpolator; diff --git a/src/rendering/renderablevolume.cpp b/src/rendering/renderablevolume.cpp index c96b8ca7ae..81e58e5180 100644 --- a/src/rendering/renderablevolume.cpp +++ b/src/rendering/renderablevolume.cpp @@ -102,63 +102,103 @@ std::string RenderableVolume::findPath(const std::string& path) { } ghoul::opengl::Texture* RenderableVolume::loadVolume(const std::string& filepath, const ghoul::Dictionary& hintsDictionary) { - if( ! FileSys.fileExists(filepath)) { - LWARNING("Could not load volume, could not find '" << filepath << "'"); - return nullptr; - } - - if(hasExtension(filepath, "raw")) { - ghoul::RawVolumeReader::ReadHints hints = readHints(hintsDictionary); - ghoul::RawVolumeReader rawReader(hints); - return rawReader.read(filepath); - } else if(hasExtension(filepath, "cdf")) { - - std::string modelString; - if (hintsDictionary.hasKey("Model") && hintsDictionary.getValue("Model", modelString)) { - KameleonWrapper::Model model; - if (modelString == "BATSRUS") { - model = KameleonWrapper::Model::BATSRUS; - } else if (modelString == "ENLIL") { - model = KameleonWrapper::Model::ENLIL; - } else { - LWARNING("Hints does not specify a valid 'Model'"); - return nullptr; - } - - std::string variableString; - if (hintsDictionary.hasKey("Variable") && hintsDictionary.getValue("Variable", variableString)) { - glm::size3_t dimensions(1,1,1); - double tempValue; - if (hintsDictionary.hasKey("Dimensions.1") && hintsDictionary.getValue("Dimensions.1", tempValue)) { - int intVal = static_cast(tempValue); - if(intVal > 0) - dimensions[0] = intVal; - } - if (hintsDictionary.hasKey("Dimensions.2") && hintsDictionary.getValue("Dimensions.2", tempValue)) { - int intVal = static_cast(tempValue); - if(intVal > 0) - dimensions[1] = intVal; - } - if (hintsDictionary.hasKey("Dimensions.3") && hintsDictionary.getValue("Dimensions.3", tempValue)) { - int intVal = static_cast(tempValue); - if(intVal > 0) - dimensions[2] = intVal; - } - - KameleonWrapper kw(filepath, model); - float* data = kw.getUniformSampledValues(variableString, dimensions); - return new ghoul::opengl::Texture(data, dimensions, ghoul::opengl::Texture::Format::Red, GL_RED, GL_FLOAT); - } else { - LWARNING("Hints does not specify a 'Variable'"); - } - - - } - LWARNING("Hints does not specify a 'Model'"); - } else { - LWARNING("No valid file extension."); - } - return nullptr; + if( ! FileSys.fileExists(filepath)) { + LWARNING("Could not load volume, could not find '" << filepath << "'"); + return nullptr; + } + + if(hasExtension(filepath, "raw")) { + ghoul::RawVolumeReader::ReadHints hints = readHints(hintsDictionary); + ghoul::RawVolumeReader rawReader(hints); + return rawReader.read(filepath); + } else if(hasExtension(filepath, "cdf")) { + + std::string modelString; + if (hintsDictionary.hasKey("Model") && hintsDictionary.getValue("Model", modelString)) { + KameleonWrapper::Model model; + if (modelString == "BATSRUS") { + model = KameleonWrapper::Model::BATSRUS; + } else if (modelString == "ENLIL") { + model = KameleonWrapper::Model::ENLIL; + } else { + LWARNING("Hints does not specify a valid 'Model'"); + return nullptr; + } + + glm::size3_t dimensions(1,1,1); + double tempValue; + if (hintsDictionary.hasKey("Dimensions.1") && hintsDictionary.getValue("Dimensions.1", tempValue)) { + int intVal = static_cast(tempValue); + if(intVal > 0) + dimensions[0] = intVal; + } + if (hintsDictionary.hasKey("Dimensions.2") && hintsDictionary.getValue("Dimensions.2", tempValue)) { + int intVal = static_cast(tempValue); + if(intVal > 0) + dimensions[1] = intVal; + } + if (hintsDictionary.hasKey("Dimensions.3") && hintsDictionary.getValue("Dimensions.3", tempValue)) { + int intVal = static_cast(tempValue); + if(intVal > 0) + dimensions[2] = intVal; + } + + KameleonWrapper kw(filepath, model); + + std::string variableString; + if (hintsDictionary.hasKey("Variable") && hintsDictionary.getValue("Variable", variableString)) { + float* data = kw.getUniformSampledValues(variableString, dimensions); + return new ghoul::opengl::Texture(data, dimensions, ghoul::opengl::Texture::Format::Red, GL_RED, GL_FLOAT); + + } else if (hintsDictionary.hasKey("Variables")) { + std::string xVariable, yVariable, zVariable; + bool xVar, yVar, zVar; + xVar = hintsDictionary.getValue("Variables.1", xVariable); + yVar = hintsDictionary.getValue("Variables.2", yVariable); + zVar = hintsDictionary.getValue("Variables.3", zVariable); + + if (!xVar || !yVar || !zVar) { + LERROR("Error reading variables! Must be 3 and must exist in CDF data"); + } else { + float* data = kw.getUniformSampledVectorValues(xVariable, yVariable, zVariable, dimensions); + return new ghoul::opengl::Texture(data, dimensions, ghoul::opengl::Texture::Format::RGBA, GL_RGBA, GL_FLOAT); + } + + } else { + LWARNING("Hints does not specify a 'Variable' or 'Variables'"); + } + + + + + // float* data = kw.getUniformSampledVectorValues(variableString, dimensions); + // return new ghoul::opengl::Texture(data, dimensions, ghoul::opengl::Texture::Format::RGBA, GL_RGBA, GL_FLOAT); + + // float* data = kw.getUniformSampledValues(variableString, dimensions); + // new ghoul::opengl::Texture(data, dimensions, ghoul::opengl::Texture::Format::Red, GL_RED, GL_FLOAT); + +// ghoul::opengl::Texture* texture; +// float* data; + + // if (hintsDictionary.hasKey("VectorData") && hintsDictionary.getValue("VectorData", variableString)) { + // if (variableString == "1") { // Vector data + // LDEBUG("VectorData"); + // data = kw.getUniformSampledVectorValues(variableString, dimensions); + // texture = new ghoul::opengl::Texture(data, dimensions, ghoul::opengl::Texture::Format::RGB, GL_RGB8, GL_FLOAT); + // } else { // Scalar data + // LDEBUG("ScalarData"); + // data = kw.getUniformSampledValues(variableString, dimensions); + // texture = new ghoul::opengl::Texture(data, dimensions, ghoul::opengl::Texture::Format::Red, GL_RED, GL_FLOAT); + // } + // } + + + } + LWARNING("Hints does not specify a 'Model'"); + } else { + LWARNING("No valid file extension."); + } + return nullptr; } ghoul::RawVolumeReader::ReadHints RenderableVolume::readHints(const ghoul::Dictionary& dictionary) { diff --git a/src/rendering/renderablevolumeexpert.cpp b/src/rendering/renderablevolumeexpert.cpp index c3f268ae4a..e6a15c7136 100644 --- a/src/rendering/renderablevolumeexpert.cpp +++ b/src/rendering/renderablevolumeexpert.cpp @@ -248,14 +248,17 @@ bool RenderableVolumeExpert::initialize() { for (int i = 0; i < _volumePaths.size(); ++i) { ghoul::opengl::Texture* volume = loadVolume(_volumePaths.at(i), _volumeHints.at(i)); - if(volume) { + if(volume != nullptr) { + LDEBUG("All is well"); volume->uploadTexture(); LDEBUG("Creating CL texture from GL texture with path '" << _volumePaths.at(i) << "'"); cl_mem volumeTexture = _context.createTextureFromGLTexture(CL_MEM_READ_ONLY, *volume); - + _volumes.push_back(volume); _clVolumes.push_back(volumeTexture); + } else { + LDEBUG("nullptr, derp"); } } diff --git a/src/util/kameleonwrapper.cpp b/src/util/kameleonwrapper.cpp index 66db1fb2d9..212761663b 100644 --- a/src/util/kameleonwrapper.cpp +++ b/src/util/kameleonwrapper.cpp @@ -42,19 +42,19 @@ KameleonWrapper::KameleonWrapper(const std::string& filename, Model model): _typ switch (_type) { case Model::BATSRUS: _model = new ccmc::BATSRUS(); - if(!_model) LERROR("BATSRUS:Failed to create model instance"); + if(!_model) LERROR("BATSRUS:Failed to create BATSRUS model instance"); if (_model->open(filename) != ccmc::FileReader::OK) LERROR("BATSRUS:Failed to open "+filename); _interpolator = _model->createNewInterpolator(); - if (!_interpolator) LERROR("BATSRUS:Failed to create interpolator"); + if (!_interpolator) LERROR("BATSRUS:Failed to create BATSRUS interpolator"); break; case Model::ENLIL: _model = new ccmc::ENLIL(); - if(!_model) LERROR("Failed to create model instance"); + if(!_model) LERROR("Failed to create ENLIL model instance"); if (_model->open(filename) != ccmc::FileReader::OK) LERROR("Failed to open "+filename); _interpolator = _model->createNewInterpolator(); - if (!_interpolator) LERROR("Failed to create interpolator"); + if (!_interpolator) LERROR("Failed to create ENLIL interpolator"); break; default: LERROR("No valid model type provided!"); @@ -70,54 +70,14 @@ float* KameleonWrapper::getUniformSampledValues(const std::string& var, glm::siz assert(_model && _interpolator); assert(outDimensions.x > 0 && outDimensions.y > 0 && outDimensions.z > 0); assert(_type == Model::ENLIL || _type == Model::BATSRUS); - LINFO("Loading CDF data"); + LINFO("Loading variable " << var << " from CDF data with a uniform sampling"); int size = outDimensions.x*outDimensions.y*outDimensions.z; float* data = new float[size]; - - // get the grid system string - std::string gridSystem = _model->getGlobalAttribute("grid_system_1").getAttributeString(); - - // remove leading and trailing brackets - gridSystem = gridSystem.substr(1,gridSystem.length()-2); - - // remove all whitespaces - gridSystem.erase(remove_if(gridSystem.begin(), gridSystem.end(), isspace), gridSystem.end()); - - // replace all comma signs with whitespaces - std::replace( gridSystem.begin(), gridSystem.end(), ',', ' '); - - // tokenize - std::istringstream iss(gridSystem); - std::vector tokens{std::istream_iterator{iss},std::istream_iterator{}}; - - // validate - if (tokens.size() != 3) { - LERROR("Something went wrong"); - delete[] data; - return 0; - } - std::string v_x = tokens.at(0), v_y = tokens.at(1), v_z = tokens.at(2); - /* - for(auto t: tokens) - LDEBUG("t: " << t); - */ - /* - LERROR("getVariableAttributeNames"); - std::vector attributeNames = _model->getVariableAttributeNames(); - for(auto name : attributeNames) - LDEBUG(name); - */ - //_model->getVa - - //auto fan = std::find(attributeNames.begin(), attributeNames.end(), ""); - - - //KameleonWrapper (Debug) grid_system_1 - //KameleonWrapper (Debug) grid_1_type - - LDEBUG("Using coordinate system: " << v_x << ", " << v_y << ", " << v_z); + std::string v_x, v_y, v_z; + getGridVariables(v_x, v_y, v_z); + LDEBUG("Using coordinate system variables: " << v_x << ", " << v_y << ", " << v_z); float xMin = _model->getVariableAttribute(v_x, "actual_min").getAttributeFloat(); float xMax = _model->getVariableAttribute(v_x, "actual_max").getAttributeFloat(); @@ -132,7 +92,6 @@ float* KameleonWrapper::getUniformSampledValues(const std::string& var, glm::siz float stepY = (yMax-yMin)/(static_cast(outDimensions.y)); float stepZ = (zMax-zMin)/(static_cast(outDimensions.z)); - LDEBUG(v_x << "Min: " << xMin); LDEBUG(v_x << "Max: " << xMax); LDEBUG(v_y << "Min: " << yMin); @@ -174,10 +133,6 @@ float* KameleonWrapper::getUniformSampledValues(const std::string& var, glm::siz // scale to [0,1] data[index] = (value-varMin)/(varMax-varMin); } else if (_type == Model::ENLIL) { - //LDEBUG("data: " << theval); - - // Calculate array index - //unsigned int index = r + theta*xDim_ + phi*xDim_*yDim_; // Put r in the [0..sqrt(3)] range float rNorm = sqrt(3.0)*(float)x/(float)(outDimensions.x-1); @@ -191,15 +146,12 @@ float* KameleonWrapper::getUniformSampledValues(const std::string& var, glm::siz // Go to physical coordinates before sampling float rPh = xMin + rNorm*(xMax-xMin); float thetaPh = thetaNorm; - //phi range needs to be mapped to the slightly different - // model range to avoid gaps in the data - // Subtract a small term to avoid rounding errors when comparing - // to phiMax. + // phi range needs to be mapped to the slightly different model + // range to avoid gaps in the data Subtract a small term to + // avoid rounding errors when comparing to phiMax. float phiPh = zMin + phiNorm/(2.0*M_PI)*(zMax-zMin-0.000001); - // Hardcoded variables (rho or rho - rho_back) - // TODO Don't hardcode, make more flexible - float varValue = 0.f;//, rho_back = 0.f, diff = 0.f; + float varValue = 0.f; // See if sample point is inside domain if (rPh < xMin || rPh > xMax || thetaPh < yMin || thetaPh > yMax || phiPh < zMin || phiPh > zMax) { @@ -218,22 +170,9 @@ float* KameleonWrapper::getUniformSampledValues(const std::string& var, glm::siz phiPh = phiPh*180.f/M_PI; // Sample varValue = _interpolator->interpolate(var, rPh, thetaPh, phiPh); - //rho_back = _interpolator->interpolate("rho-back",rPh,thetaPh,phiPh); - - // Calculate difference (or just rho) - //diff = rho; - //diff = rho - rho_back; - - // Clamp to 0 - //if (diff < 0.f) diff = 0.f; } - //if(var < 0.0f) var = 0.0f; - //data[index] = var; + data[index] = (varValue-varMin)/(varMax-varMin); - //LDEBUG("varValue:" << varValue); - //LDEBUG("data[index]:" << data[index]); - //data[index] = var; - //data[index] = diff; } } } @@ -244,5 +183,123 @@ float* KameleonWrapper::getUniformSampledValues(const std::string& var, glm::siz return data; } +float* KameleonWrapper::getUniformSampledVectorValues(const std::string& xVar, const std::string& yVar, const std::string& zVar, glm::size3_t outDimensions) { + assert(_model && _interpolator); + assert(outDimensions.x > 0 && outDimensions.y > 0 && outDimensions.z > 0); + assert(_type == Model::ENLIL || _type == Model::BATSRUS); + LINFO("Loading variables " << xVar << " " << yVar << " " << zVar << " from CDF data with a uniform sampling"); + + int size = 4*outDimensions.x*outDimensions.y*outDimensions.z; + float* data = new float[size]; + + std::string v_x, v_y, v_z; + getGridVariables(v_x, v_y, v_z); + LDEBUG("Using coordinate system variables: " << v_x << ", " << v_y << ", " << v_z); + + float xMin = _model->getVariableAttribute(v_x, "actual_min").getAttributeFloat(); + float xMax = _model->getVariableAttribute(v_x, "actual_max").getAttributeFloat(); + float yMin = _model->getVariableAttribute(v_y, "actual_min").getAttributeFloat(); + float yMax = _model->getVariableAttribute(v_y, "actual_max").getAttributeFloat(); + float zMin = _model->getVariableAttribute(v_z, "actual_min").getAttributeFloat(); + float zMax = _model->getVariableAttribute(v_z, "actual_max").getAttributeFloat(); + float varXMin = _model->getVariableAttribute(xVar, "actual_min").getAttributeFloat(); + float varXMax = _model->getVariableAttribute(xVar, "actual_max").getAttributeFloat(); + float varYMin = _model->getVariableAttribute(yVar, "actual_min").getAttributeFloat(); + float varYMax = _model->getVariableAttribute(yVar, "actual_max").getAttributeFloat(); + float varZMin = _model->getVariableAttribute(zVar, "actual_min").getAttributeFloat(); + float varZMax = _model->getVariableAttribute(zVar, "actual_max").getAttributeFloat(); + + float stepX = (xMax-xMin)/(static_cast(outDimensions.x)); + float stepY = (yMax-yMin)/(static_cast(outDimensions.y)); + float stepZ = (zMax-zMin)/(static_cast(outDimensions.z)); + + LDEBUG(v_x << "Min: " << xMin); + LDEBUG(v_x << "Max: " << xMax); + LDEBUG(v_y << "Min: " << yMin); + LDEBUG(v_y << "Max: " << yMax); + LDEBUG(v_z << "Min: " << zMin); + LDEBUG(v_z << "Max: " << zMax); + LDEBUG(xVar << "Min: " << varXMin); + LDEBUG(xVar << "Max: " << varXMax); + LDEBUG(yVar << "Min: " << varYMin); + LDEBUG(yVar << "Max: " << varYMax); + LDEBUG(zVar << "Min: " << varZMin); + LDEBUG(zVar << "Max: " << varZMax); + + int barWidth = 70; + int lastiProgress = -1; + for (int x = 0; x < outDimensions.x; ++x) { + float progress = static_cast(x) / static_cast(outDimensions.x-1); + int iprogress = static_cast(progress*100.0f); + if (iprogress != lastiProgress) { + + int pos = barWidth * progress; + int eqWidth = pos+1; + int spWidth = barWidth - pos + 2; + std::cout << "[" << std::setfill('=') << std::setw(eqWidth) + << ">" << std::setfill(' ') << std::setw(spWidth) + << "] " << iprogress << " % \r" << std::flush; + } + lastiProgress = iprogress; + + for (int y = 0; y < outDimensions.y; ++y) { + for (int z = 0; z < outDimensions.z; ++z) { + + int index = 4*x + 4*y*outDimensions.x + 4*z*outDimensions.x*outDimensions.y; + + if(_type == Model::BATSRUS) { + float xPos = xMin + stepX*x; + float yPos = yMin + stepY*y; + float zPos = zMin + stepZ*z; + + // get interpolated data value for (xPos, yPos, zPos) + float xValue = _interpolator->interpolate(xVar, xPos, yPos, zPos); + float yValue = _interpolator->interpolate(yVar, xPos, yPos, zPos); + float zValue = _interpolator->interpolate(zVar, xPos, yPos, zPos); + + // scale to [0,1] + data[index] = (xValue-varXMin)/(varXMax-varXMin); + data[index + 1] = (yValue-varYMin)/(varYMax-varYMin); + data[index + 2] = (zValue-varZMin)/(varZMax-varZMin); + data[index + 3] = 1.0; + } else { + LERROR("Only BATSRUS supported for getUniformSampledVectorValues"); + } + } + } + } + std::cout << std::endl; + LINFO("Done!"); + + return data; +} + +void KameleonWrapper::getGridVariables(std::string& x, std::string& y, std::string& z) { + // get the grid system string + std::string gridSystem = _model->getGlobalAttribute("grid_system_1").getAttributeString(); + + // remove leading and trailing brackets + gridSystem = gridSystem.substr(1,gridSystem.length()-2); + + // remove all whitespaces + gridSystem.erase(remove_if(gridSystem.begin(), gridSystem.end(), isspace), gridSystem.end()); + + // replace all comma signs with whitespaces + std::replace( gridSystem.begin(), gridSystem.end(), ',', ' '); + + // tokenize + std::istringstream iss(gridSystem); + std::vector tokens{std::istream_iterator{iss},std::istream_iterator{}}; + + // validate + if (tokens.size() != 3) { + LERROR("Something went wrong"); + } + + x = tokens.at(0); + y = tokens.at(1); + z = tokens.at(2); +} + } // namespace openspace From 29b4cffd7882eb3066cb0e743c52f7f1d815d39a Mon Sep 17 00:00:00 2001 From: Hans-Christian Helltegen Date: Wed, 21 May 2014 16:24:47 -0400 Subject: [PATCH 02/49] Code cleaup --- include/openspace/util/kameleonwrapper.h | 4 ++ src/rendering/renderablevolume.cpp | 25 --------- src/util/kameleonwrapper.cpp | 65 ++++++++++-------------- 3 files changed, 31 insertions(+), 63 deletions(-) diff --git a/include/openspace/util/kameleonwrapper.h b/include/openspace/util/kameleonwrapper.h index a92483b094..9c7f55c9bd 100644 --- a/include/openspace/util/kameleonwrapper.h +++ b/include/openspace/util/kameleonwrapper.h @@ -50,9 +50,13 @@ public: private: void getGridVariables(std::string& x, std::string& y, std::string& z); + void progressBar(int current, int end); + ccmc::Model* _model; Model _type; ccmc::Interpolator* _interpolator; + + int _lastiProgress; // for progressbar }; } // namespace openspace diff --git a/src/rendering/renderablevolume.cpp b/src/rendering/renderablevolume.cpp index 81e58e5180..c01b9bb3bd 100644 --- a/src/rendering/renderablevolume.cpp +++ b/src/rendering/renderablevolume.cpp @@ -168,31 +168,6 @@ ghoul::opengl::Texture* RenderableVolume::loadVolume(const std::string& filepath LWARNING("Hints does not specify a 'Variable' or 'Variables'"); } - - - - // float* data = kw.getUniformSampledVectorValues(variableString, dimensions); - // return new ghoul::opengl::Texture(data, dimensions, ghoul::opengl::Texture::Format::RGBA, GL_RGBA, GL_FLOAT); - - // float* data = kw.getUniformSampledValues(variableString, dimensions); - // new ghoul::opengl::Texture(data, dimensions, ghoul::opengl::Texture::Format::Red, GL_RED, GL_FLOAT); - -// ghoul::opengl::Texture* texture; -// float* data; - - // if (hintsDictionary.hasKey("VectorData") && hintsDictionary.getValue("VectorData", variableString)) { - // if (variableString == "1") { // Vector data - // LDEBUG("VectorData"); - // data = kw.getUniformSampledVectorValues(variableString, dimensions); - // texture = new ghoul::opengl::Texture(data, dimensions, ghoul::opengl::Texture::Format::RGB, GL_RGB8, GL_FLOAT); - // } else { // Scalar data - // LDEBUG("ScalarData"); - // data = kw.getUniformSampledValues(variableString, dimensions); - // texture = new ghoul::opengl::Texture(data, dimensions, ghoul::opengl::Texture::Format::Red, GL_RED, GL_FLOAT); - // } - // } - - } LWARNING("Hints does not specify a 'Model'"); } else { diff --git a/src/util/kameleonwrapper.cpp b/src/util/kameleonwrapper.cpp index 212761663b..2e4378fa2a 100644 --- a/src/util/kameleonwrapper.cpp +++ b/src/util/kameleonwrapper.cpp @@ -59,6 +59,7 @@ KameleonWrapper::KameleonWrapper(const std::string& filename, Model model): _typ default: LERROR("No valid model type provided!"); } + _lastiProgress = -1; // for progressbar } KameleonWrapper::~KameleonWrapper() { @@ -101,21 +102,8 @@ float* KameleonWrapper::getUniformSampledValues(const std::string& var, glm::siz LDEBUG(var << "Min: " << varMin); LDEBUG(var << "Max: " << varMax); - int barWidth = 70; - int lastiProgress = -1; for (int x = 0; x < outDimensions.x; ++x) { - float progress = static_cast(x) / static_cast(outDimensions.x-1); - int iprogress = static_cast(progress*100.0f); - if (iprogress != lastiProgress) { - - int pos = barWidth * progress; - int eqWidth = pos+1; - int spWidth = barWidth - pos + 2; - std::cout << "[" << std::setfill('=') << std::setw(eqWidth) - << ">" << std::setfill(' ') << std::setw(spWidth) - << "] " << iprogress << " % \r" << std::flush; - } - lastiProgress = iprogress; + progressBar(x, outDimensions.x); for (int y = 0; y < outDimensions.y; ++y) { for (int z = 0; z < outDimensions.z; ++z) { @@ -189,7 +177,8 @@ float* KameleonWrapper::getUniformSampledVectorValues(const std::string& xVar, c assert(_type == Model::ENLIL || _type == Model::BATSRUS); LINFO("Loading variables " << xVar << " " << yVar << " " << zVar << " from CDF data with a uniform sampling"); - int size = 4*outDimensions.x*outDimensions.y*outDimensions.z; + int channels = 4; + int size = channels*outDimensions.x*outDimensions.y*outDimensions.z; float* data = new float[size]; std::string v_x, v_y, v_z; @@ -226,26 +215,13 @@ float* KameleonWrapper::getUniformSampledVectorValues(const std::string& xVar, c LDEBUG(zVar << "Min: " << varZMin); LDEBUG(zVar << "Max: " << varZMax); - int barWidth = 70; - int lastiProgress = -1; for (int x = 0; x < outDimensions.x; ++x) { - float progress = static_cast(x) / static_cast(outDimensions.x-1); - int iprogress = static_cast(progress*100.0f); - if (iprogress != lastiProgress) { - - int pos = barWidth * progress; - int eqWidth = pos+1; - int spWidth = barWidth - pos + 2; - std::cout << "[" << std::setfill('=') << std::setw(eqWidth) - << ">" << std::setfill(' ') << std::setw(spWidth) - << "] " << iprogress << " % \r" << std::flush; - } - lastiProgress = iprogress; + progressBar(x, outDimensions.x); for (int y = 0; y < outDimensions.y; ++y) { for (int z = 0; z < outDimensions.z; ++z) { - int index = 4*x + 4*y*outDimensions.x + 4*z*outDimensions.x*outDimensions.y; + int index = x*channels + y*channels*outDimensions.x + z*channels*outDimensions.x*outDimensions.y; if(_type == Model::BATSRUS) { float xPos = xMin + stepX*x; @@ -258,12 +234,12 @@ float* KameleonWrapper::getUniformSampledVectorValues(const std::string& xVar, c float zValue = _interpolator->interpolate(zVar, xPos, yPos, zPos); // scale to [0,1] - data[index] = (xValue-varXMin)/(varXMax-varXMin); - data[index + 1] = (yValue-varYMin)/(varYMax-varYMin); - data[index + 2] = (zValue-varZMin)/(varZMax-varZMin); - data[index + 3] = 1.0; + data[index] = (xValue-varXMin)/(varXMax-varXMin); // R + data[index + 1] = (yValue-varYMin)/(varYMax-varYMin); // G + data[index + 2] = (zValue-varZMin)/(varZMax-varZMin); // B + data[index + 3] = 1.0; // GL_RGB refuses to work. Workaround by doing a GL_RGBA with hardcoded alpha } else { - LERROR("Only BATSRUS supported for getUniformSampledVectorValues"); + LERROR("Only BATSRUS supported for getUniformSampledVectorValues (for now)"); } } } @@ -292,14 +268,27 @@ void KameleonWrapper::getGridVariables(std::string& x, std::string& y, std::stri std::vector tokens{std::istream_iterator{iss},std::istream_iterator{}}; // validate - if (tokens.size() != 3) { - LERROR("Something went wrong"); - } + if (tokens.size() != 3) LERROR("Something went wrong"); x = tokens.at(0); y = tokens.at(1); z = tokens.at(2); } +void KameleonWrapper::progressBar(int current, int end) { + float progress = static_cast(current) / static_cast(end-1); + int iprogress = static_cast(progress*100.0f); + int barWidth = 70; + if (iprogress != _lastiProgress) { + int pos = barWidth * progress; + int eqWidth = pos+1; + int spWidth = barWidth - pos + 2; + std::cout << "[" << std::setfill('=') << std::setw(eqWidth) + << ">" << std::setfill(' ') << std::setw(spWidth) + << "] " << iprogress << " % \r" << std::flush; + } + _lastiProgress = iprogress; +} + } // namespace openspace From 48f1b6aa5ceb146bc189085167a4a96ce60c7e82 Mon Sep 17 00:00:00 2001 From: Hans-Christian Helltegen Date: Fri, 23 May 2014 16:20:11 -0400 Subject: [PATCH 03/49] Added basic fieldline implementation in kameleonwrapper --- include/openspace/util/kameleonwrapper.h | 6 ++- src/rendering/renderablevolume.cpp | 19 ++++++- src/rendering/renderablevolumeexpert.cpp | 5 +- src/util/kameleonwrapper.cpp | 68 +++++++++++++++++++++++- 4 files changed, 91 insertions(+), 7 deletions(-) diff --git a/include/openspace/util/kameleonwrapper.h b/include/openspace/util/kameleonwrapper.h index 9c7f55c9bd..e52172b214 100644 --- a/include/openspace/util/kameleonwrapper.h +++ b/include/openspace/util/kameleonwrapper.h @@ -46,7 +46,11 @@ public: KameleonWrapper(const std::string& filename, Model model); ~KameleonWrapper(); float* getUniformSampledValues(const std::string& var, glm::size3_t outDimensions); - float* getUniformSampledVectorValues(const std::string& xVar, const std::string& yVar, const std::string& zVar, glm::size3_t outDimensions); + float* getUniformSampledVectorValues(const std::string& xVar, const std::string& yVar, + const std::string& zVar, glm::size3_t outDimensions); + + float* getFieldLines(const std::string& xVar, const std::string& yVar, + const std::string& zVar, glm::size3_t outDimensions, std::vector seedPoints); private: void getGridVariables(std::string& x, std::string& y, std::string& z); diff --git a/src/rendering/renderablevolume.cpp b/src/rendering/renderablevolume.cpp index c01b9bb3bd..6645357612 100644 --- a/src/rendering/renderablevolume.cpp +++ b/src/rendering/renderablevolume.cpp @@ -160,8 +160,23 @@ ghoul::opengl::Texture* RenderableVolume::loadVolume(const std::string& filepath if (!xVar || !yVar || !zVar) { LERROR("Error reading variables! Must be 3 and must exist in CDF data"); } else { - float* data = kw.getUniformSampledVectorValues(xVariable, yVariable, zVariable, dimensions); - return new ghoul::opengl::Texture(data, dimensions, ghoul::opengl::Texture::Format::RGBA, GL_RGBA, GL_FLOAT); + + // Seed 'em all + std::vector seedPoints; + for (int z = -20; z <= 20; z+=20) { + for (int y = -20; y <= 20; y+=20) + seedPoints.push_back(glm::vec3(-10.0, (float)y, (float)z)); + } + + float* fieldlinesData = kw.getFieldLines(xVariable, yVariable, zVariable, dimensions, seedPoints); + float* rhoData = kw.getUniformSampledValues("rho", dimensions); + + // Combine fieldlines with rhoData, clamp to [0,1] + float* data = new float[dimensions.x*dimensions.y*dimensions.z]; + for (int i = 0; i < dimensions.x*dimensions.y*dimensions.z; ++i) + data[i] = std::min(fieldlinesData[i]+rhoData[i], 1.0f); + + return new ghoul::opengl::Texture(data, dimensions, ghoul::opengl::Texture::Format::Red, GL_RED, GL_FLOAT); } } else { diff --git a/src/rendering/renderablevolumeexpert.cpp b/src/rendering/renderablevolumeexpert.cpp index e6a15c7136..1785c58857 100644 --- a/src/rendering/renderablevolumeexpert.cpp +++ b/src/rendering/renderablevolumeexpert.cpp @@ -248,8 +248,7 @@ bool RenderableVolumeExpert::initialize() { for (int i = 0; i < _volumePaths.size(); ++i) { ghoul::opengl::Texture* volume = loadVolume(_volumePaths.at(i), _volumeHints.at(i)); - if(volume != nullptr) { - LDEBUG("All is well"); + if(volume) { volume->uploadTexture(); LDEBUG("Creating CL texture from GL texture with path '" << _volumePaths.at(i) << "'"); @@ -258,7 +257,7 @@ bool RenderableVolumeExpert::initialize() { _volumes.push_back(volume); _clVolumes.push_back(volumeTexture); } else { - LDEBUG("nullptr, derp"); + LERROR("Invalid volume"); } } diff --git a/src/util/kameleonwrapper.cpp b/src/util/kameleonwrapper.cpp index 2e4378fa2a..60d2ea6aa4 100644 --- a/src/util/kameleonwrapper.cpp +++ b/src/util/kameleonwrapper.cpp @@ -31,7 +31,8 @@ #include #define _USE_MATH_DEFINES #include - +#include +#include #include namespace openspace { @@ -181,6 +182,10 @@ float* KameleonWrapper::getUniformSampledVectorValues(const std::string& xVar, c int size = channels*outDimensions.x*outDimensions.y*outDimensions.z; float* data = new float[size]; +// memset(data, 0.0, sizeof(data)); + + + std::string v_x, v_y, v_z; getGridVariables(v_x, v_y, v_z); LDEBUG("Using coordinate system variables: " << v_x << ", " << v_y << ", " << v_z); @@ -275,6 +280,67 @@ void KameleonWrapper::getGridVariables(std::string& x, std::string& y, std::stri z = tokens.at(2); } +float* KameleonWrapper::getFieldLines(const std::string& xVar, + const std::string& yVar, const std::string& zVar, + glm::size3_t outDimensions, std::vector seedPoints) { + assert(_model && _interpolator); + assert(outDimensions.x > 0 && outDimensions.y > 0 && outDimensions.z > 0); + assert(_type == Model::ENLIL || _type == Model::BATSRUS); + LINFO("Creating " << seedPoints.size() << " fieldlines from variables " << xVar << " " << yVar << " " << zVar); + + std::string v_x, v_y, v_z; + getGridVariables(v_x, v_y, v_z); + LDEBUG("Using coordinate system variables: " << v_x << ", " << v_y << ", " << v_z); + + float xMin = _model->getVariableAttribute(v_x, "actual_min").getAttributeFloat(); + float xMax = _model->getVariableAttribute(v_x, "actual_max").getAttributeFloat(); + float yMin = _model->getVariableAttribute(v_y, "actual_min").getAttributeFloat(); + float yMax = _model->getVariableAttribute(v_y, "actual_max").getAttributeFloat(); + float zMin = _model->getVariableAttribute(v_z, "actual_min").getAttributeFloat(); + float zMax = _model->getVariableAttribute(v_z, "actual_max").getAttributeFloat(); + + float stepSize = 0.001; + float stepX = stepSize*(xMax-xMin)/(static_cast(outDimensions.x)); + float stepY = stepSize*(yMax-yMin)/(static_cast(outDimensions.y)); + float stepZ = stepSize*(zMax-zMin)/(static_cast(outDimensions.z)); + + int size = outDimensions.x*outDimensions.y*outDimensions.z; + float* data = new float[size]; + glm::vec3 dir, pos; + + int highNumber = 100000; + + for (int i = 0; i < seedPoints.size(); ++i) { + progressBar(i, seedPoints.size()); + pos = seedPoints.at(i); + int avoidInfLoopPlz = 0; + while (pos.x < xMax && pos.x > xMin && + pos.y < yMax && pos.y > yMin && + pos.z < zMax && pos.z > zMin) { + + // Save position + int vPosX = std::floor(outDimensions.x*(pos.x-xMin)/(xMax-xMin)); + int vPosY = std::floor(outDimensions.y*(pos.y-yMin)/(yMax-yMin)); + int vPosZ = std::floor(outDimensions.z*(pos.z-zMin)/(zMax-zMin)); + int index = vPosX + vPosY*outDimensions.x + vPosZ*outDimensions.x*outDimensions.y; + data[index] = 1.0; + + // Calculate the next position + dir.x = _interpolator->interpolate(xVar, pos.x, pos.y, pos.z); + dir.y = _interpolator->interpolate(yVar, pos.x, pos.y, pos.z); + dir.z = _interpolator->interpolate(zVar, pos.x, pos.y, pos.z); + pos = glm::vec3(stepX*dir.x+pos.x, stepY*dir.y+pos.y, stepZ*dir.z+pos.z); + ++avoidInfLoopPlz; + + if (avoidInfLoopPlz > highNumber) { + LDEBUG("Inf loop averted"); + break; + } + } + } + return data; +} + void KameleonWrapper::progressBar(int current, int end) { float progress = static_cast(current) / static_cast(end-1); int iprogress = static_cast(progress*100.0f); From 4269282718953ceaffaa708b789b6e15374e80b8 Mon Sep 17 00:00:00 2001 From: Jonas Strandstedt Date: Tue, 27 May 2014 16:28:46 -0400 Subject: [PATCH 04/49] Intermediate ABuffer work --- .../openspace/abuffer/abufferSingleLinked.h | 56 +++++++++++++++++ include/openspace/abuffer/abuffer_i.h | 45 +++++++++++++ src/CMakeLists.txt | 6 ++ src/abuffer/abufferSingleLinked.cpp | 63 +++++++++++++++++++ 4 files changed, 170 insertions(+) create mode 100644 include/openspace/abuffer/abufferSingleLinked.h create mode 100644 include/openspace/abuffer/abuffer_i.h create mode 100644 src/abuffer/abufferSingleLinked.cpp diff --git a/include/openspace/abuffer/abufferSingleLinked.h b/include/openspace/abuffer/abufferSingleLinked.h new file mode 100644 index 0000000000..93edd06924 --- /dev/null +++ b/include/openspace/abuffer/abufferSingleLinked.h @@ -0,0 +1,56 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __ABUFFERSINGLELINKED_H__ +#define __ABUFFERSINGLELINKED_H__ + +#include + + +namespace openspace { + +class ABufferSingleLinked: public ABuffer_I { +public: + + ABufferSingleLinked(); + virtual ~ABufferSingleLinked(); + virtual bool initialize(); + + virtual void clear(); + virtual void preRender(); + virtual void postRender(); + +private: + + + unsigned int width, height, totalPixels, maxFragments; + + ghoul::opengl::Texture* data; + ghoul::opengl::Texture* anchorPointer; + ghoul::opengl::Texture* anchorPointerInitializer; + +}; // ABuffer_I +} // openspace + +#endif // __ABUFFERSINGLELINKED_H__ \ No newline at end of file diff --git a/include/openspace/abuffer/abuffer_i.h b/include/openspace/abuffer/abuffer_i.h new file mode 100644 index 0000000000..9e1644edb0 --- /dev/null +++ b/include/openspace/abuffer/abuffer_i.h @@ -0,0 +1,45 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __ABUFFER_I_H__ +#define __ABUFFER_I_H__ + +#include +#include + +namespace openspace { + +class ABuffer_I { +public: + virtual ~ABuffer_I() {}; + virtual bool initialize() = 0; + + virtual void clear() = 0; + virtual void preRender() = 0; + virtual void postRender() = 0; + +}; // ABuffer_I +} // openspace + +#endif // __ABUFFER_I_H__ \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 310b700bc5..42fe1ebbac 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -34,6 +34,12 @@ file(GLOB CONFIGURATION_HEADER ${HEADER_ROOT_DIR}/openspace/configuration/*.h) set(OPENSPACE_HEADER ${OPENSPACE_HEADER} ${CONFIGURATION_HEADER}) source_group(Configuration FILES ${CONFIGURATION_SOURCE} ${CONFIGURATION_HEADER}) +file(GLOB ABUFFER_SOURCE ${SOURCE_ROOT_DIR}/abuffer/*.cpp) +set(OPENSPACE_SOURCE ${OPENSPACE_SOURCE} ${ABUFFER_SOURCE}) +file(GLOB ABUFFER_HEADER ${HEADER_ROOT_DIR}/openspace/abuffer/*.h) +set(OPENSPACE_HEADER ${OPENSPACE_HEADER} ${ABUFFER_HEADER}) +source_group(ABuffer FILES ${ABUFFER_SOURCE} ${ABUFFER_HEADER}) + file(GLOB ENGINE_SOURCE ${SOURCE_ROOT_DIR}/engine/*.cpp) set(OPENSPACE_SOURCE ${OPENSPACE_SOURCE} ${ENGINE_SOURCE}) file(GLOB ENGINE_HEADER ${HEADER_ROOT_DIR}/openspace/engine/*.h) diff --git a/src/abuffer/abufferSingleLinked.cpp b/src/abuffer/abufferSingleLinked.cpp new file mode 100644 index 0000000000..14645678ce --- /dev/null +++ b/src/abuffer/abufferSingleLinked.cpp @@ -0,0 +1,63 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include + +#include + +#define MAX_LAYERS 10 + +namespace openspace { + +ABufferSingleLinked::ABufferSingleLinked() { + int x1, xSize, y1, ySize; + sgct::Engine::instance()->getActiveWindowPtr()->getCurrentViewportPixelCoords(x1, y1, xSize, ySize); + width = xSize; + height = ySize; + totalPixels = width * height; + maxFragments = totalPixels * MAX_LAYERS; +} + +ABufferSingleLinked::~ABufferSingleLinked() { + +} + +bool ABufferSingleLinked::initialize() { + data = new ghoul::opengl::Texture(glm::size3_t(width, height, 1), ghoul::opengl::Texture::Format::RED, GL_RED, GL_R32UI); + return true; +} + +void ABufferSingleLinked::clear() { + +} + +void ABufferSingleLinked::preRender() { + +} + +void ABufferSingleLinked::postRender() { + +} + +} // openspace \ No newline at end of file From 4379d27cbc106ec75ab31b49492c88d0cf022c5d Mon Sep 17 00:00:00 2001 From: Jonas Strandstedt Date: Thu, 29 May 2014 12:25:04 -0400 Subject: [PATCH 05/49] Single Linked ABuffer implementation --- .../openspace/abuffer/abufferSingleLinked.h | 13 +- include/openspace/engine/openspaceengine.h | 2 +- include/openspace/rendering/renderengine.h | 4 + shaders/ABuffer/abufferResolveFragment.glsl | 77 +++++++++++ shaders/ABuffer/abufferResolveVertex.glsl | 9 ++ shaders/pscstandard_fs.glsl | 26 +++- shaders/pscstandard_vs.glsl | 2 +- src/abuffer/abufferSingleLinked.cpp | 120 +++++++++++++++++- src/rendering/renderengine.cpp | 13 +- 9 files changed, 251 insertions(+), 15 deletions(-) create mode 100644 shaders/ABuffer/abufferResolveFragment.glsl create mode 100644 shaders/ABuffer/abufferResolveVertex.glsl diff --git a/include/openspace/abuffer/abufferSingleLinked.h b/include/openspace/abuffer/abufferSingleLinked.h index 93edd06924..4ff20b2070 100644 --- a/include/openspace/abuffer/abufferSingleLinked.h +++ b/include/openspace/abuffer/abufferSingleLinked.h @@ -27,6 +27,7 @@ #include +#include namespace openspace { @@ -46,9 +47,15 @@ private: unsigned int width, height, totalPixels, maxFragments; - ghoul::opengl::Texture* data; - ghoul::opengl::Texture* anchorPointer; - ghoul::opengl::Texture* anchorPointerInitializer; + GLuint *data; + GLuint anchorPointerTexture; + GLuint anchorPointerTextureInitializer; + GLuint atomicCounterBuffer; + GLuint fragmentBuffer; + GLuint fragmentTexture; + GLuint _screenQuad; + + ghoul::opengl::ProgramObject* resolveShader; }; // ABuffer_I } // openspace diff --git a/include/openspace/engine/openspaceengine.h b/include/openspace/engine/openspaceengine.h index a1b414f606..66fdd720f3 100644 --- a/include/openspace/engine/openspaceengine.h +++ b/include/openspace/engine/openspaceengine.h @@ -34,7 +34,7 @@ #include #include -#define FLARE_ONLY +//#define FLARE_ONLY #include diff --git a/include/openspace/rendering/renderengine.h b/include/openspace/rendering/renderengine.h index da2c74d712..52c32db385 100644 --- a/include/openspace/rendering/renderengine.h +++ b/include/openspace/rendering/renderengine.h @@ -30,6 +30,8 @@ #include #include +#include + namespace openspace { class Camera; @@ -58,6 +60,8 @@ public: private: Camera* _mainCamera; SceneGraph* _sceneGraph; + + ABuffer_I* _abuffer; }; } // namespace openspace diff --git a/shaders/ABuffer/abufferResolveFragment.glsl b/shaders/ABuffer/abufferResolveFragment.glsl new file mode 100644 index 0000000000..d0b46b2968 --- /dev/null +++ b/shaders/ABuffer/abufferResolveFragment.glsl @@ -0,0 +1,77 @@ +#version 430 + +// texture bindings +layout (binding = 0, r32ui) uniform uimage2D anchorPointerTexture; +layout (binding = 1, rgba32ui) uniform uimageBuffer fragmentTexture; + +// atomic buffer bindings +layout (binding = 0, offset = 0) uniform atomic_uint atomicCounterBuffer; + +// uniforms +uniform int SCREEN_WIDTH; +uniform int SCREEN_HEIGHT; + +in vec2 texCoord; +out vec4 color; + +#define MAX_FRAGMENTS 16 +uvec4 fragments[MAX_FRAGMENTS]; + +int build_local_fragments_list() { + uint current; + int frag_count = 0; + + current = imageLoad(anchorPointerTexture, ivec2(gl_FragCoord.xy)).x; + + while(current != 0 && frag_count < MAX_FRAGMENTS) { + uvec4 item = imageLoad(fragmentTexture, int(current)); + current = item.x; + + fragments[frag_count] = item; + + frag_count++; + } + + return frag_count; +} + +void sort_fragments_list(uint frag_count) { + uint i,j; + uvec4 tmp; + + // INSERTION SORT + for(i = 1; i < frag_count; ++i) { + tmp = fragments[i]; + for(j = i; j > 0 && tmp.z > fragments[j-1].z; --j) { + fragments[j] = fragments[j-1]; + } + fragments[j] = tmp; + } +} + +vec4 blend(vec4 current_color, vec4 new_color) { + return mix(current_color, new_color, new_color.a); +} + +vec4 calculate_final_color(uint frag_count) { + + vec4 final_color = vec4(0); + for(uint i = 0; i < frag_count; i++) { + uvec4 item = fragments[i]; + vec4 frag_color = unpackUnorm4x8(item.y); + final_color = blend(final_color, frag_color); + } + + return final_color; + +} + + +void main() { + color = vec4(texCoord,0.0,1.0); + int frag_count = build_local_fragments_list(); + sort_fragments_list(frag_count); + color = calculate_final_color(frag_count); + + //color = vec4(float(frag_count) / 5.0, 0.0, 0.0, 1.0); +} \ No newline at end of file diff --git a/shaders/ABuffer/abufferResolveVertex.glsl b/shaders/ABuffer/abufferResolveVertex.glsl new file mode 100644 index 0000000000..ded6af8a7a --- /dev/null +++ b/shaders/ABuffer/abufferResolveVertex.glsl @@ -0,0 +1,9 @@ +#version 430 + +in vec4 position; +out vec2 texCoord; + +void main() { + gl_Position = position; + texCoord = 0.5 + position.xy / 2.0; +} diff --git a/shaders/pscstandard_fs.glsl b/shaders/pscstandard_fs.glsl index 6a3faef107..eb95f757ba 100644 --- a/shaders/pscstandard_fs.glsl +++ b/shaders/pscstandard_fs.glsl @@ -7,7 +7,11 @@ The above copyright notice and this permission notice shall be included in all c THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#version 400 core +#version 430 + +layout (binding = 0, r32ui) uniform uimage2D anchorPointerTexture; +layout (binding = 1, rgba32ui) uniform uimageBuffer fragmentTexture; +layout (binding = 0, offset = 0) uniform atomic_uint atomicCounterBuffer; uniform mat4 ViewProjection; uniform mat4 ModelTransform; @@ -15,12 +19,8 @@ uniform vec4 campos; uniform vec4 objpos; uniform float time; uniform sampler2D texture1; -uniform sampler2D texture2; -uniform sampler2D texture3; -uniform float TessLevel; -uniform bool Wireframe; -uniform bool Lightsource; -uniform bool UseTexture; + +vec3 light_position = vec3(40.0, 20.0, 100.0); in vec2 vs_st; //in vec3 vs_stp; @@ -97,6 +97,8 @@ void main() // do I need to be discarded? // discard; } + + // set the depth @@ -112,4 +114,14 @@ void main() //diffuse = vec4(depth*5,0.0, 0.0, 1.0); //diffuse = vec4(vs_position.w,0.0, 0.0, 1.0); //diffuse = vec4(1.0,0.0,0.0,1.0); + uint index = atomicCounterIncrement(atomicCounterBuffer); + uint old_head = imageAtomicExchange(anchorPointerTexture, ivec2(gl_FragCoord.xy), index); + uvec4 item; + item.x = old_head; + item.y = packUnorm4x8(diffuse); + item.z = floatBitsToUint(gl_FragCoord.z / gl_FragCoord.w); + item.w = 0; + imageStore(fragmentTexture, int(index), item); + + discard; } \ No newline at end of file diff --git a/shaders/pscstandard_vs.glsl b/shaders/pscstandard_vs.glsl index 0c588a7ccd..5a612667a2 100644 --- a/shaders/pscstandard_vs.glsl +++ b/shaders/pscstandard_vs.glsl @@ -19,7 +19,7 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#version 400 core +#version 430 uniform mat4 ViewProjection; uniform mat4 ModelTransform; diff --git a/src/abuffer/abufferSingleLinked.cpp b/src/abuffer/abufferSingleLinked.cpp index 14645678ce..3d3c7cf7d4 100644 --- a/src/abuffer/abufferSingleLinked.cpp +++ b/src/abuffer/abufferSingleLinked.cpp @@ -24,9 +24,16 @@ #include +#include +#include #include #define MAX_LAYERS 10 +#define BUFFER_OFFSET(i) ((char *)NULL + (i)) + +namespace { + std::string _loggerCat = "ABufferSingleLinked"; +} namespace openspace { @@ -37,27 +44,136 @@ ABufferSingleLinked::ABufferSingleLinked() { height = ySize; totalPixels = width * height; maxFragments = totalPixels * MAX_LAYERS; + data = 0; + anchorPointerTexture = 0; + anchorPointerTextureInitializer = 0; + atomicCounterBuffer = 0; + fragmentBuffer = 0; + fragmentTexture = 0; } ABufferSingleLinked::~ABufferSingleLinked() { + if(data != 0) + delete data; + glDeleteTextures(1,&anchorPointerTexture); + glDeleteTextures(1,&fragmentTexture); + glDeleteBuffers(1,&anchorPointerTextureInitializer); + glDeleteBuffers(1,&atomicCounterBuffer); + glDeleteBuffers(1,&anchorPointerTextureInitializer); } bool ABufferSingleLinked::initialize() { - data = new ghoul::opengl::Texture(glm::size3_t(width, height, 1), ghoul::opengl::Texture::Format::RED, GL_RED, GL_R32UI); + // ============================ + // BUFFERS + // ============================ + glGenTextures(1, &anchorPointerTexture); + glBindTexture(GL_TEXTURE_2D, anchorPointerTexture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, width, height, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, NULL); + + glGenBuffers(1, &anchorPointerTextureInitializer); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, anchorPointerTextureInitializer); + glBufferData(GL_PIXEL_UNPACK_BUFFER, totalPixels * sizeof(GLuint), NULL, GL_STATIC_DRAW); + + data = (GLuint*)glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY); + memset(data, 0x00, totalPixels * sizeof(GLuint)); + glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + + glGenBuffers(1, &atomicCounterBuffer); + glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer); + glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(GLuint), NULL, GL_DYNAMIC_COPY); + + glGenBuffers(1, &fragmentBuffer); + glBindBuffer(GL_TEXTURE_BUFFER, fragmentBuffer); + glBufferData(GL_TEXTURE_BUFFER, MAX_LAYERS*totalPixels*sizeof(GLfloat)*4, NULL, GL_DYNAMIC_COPY); + + glGenTextures(1, &fragmentTexture); + glBindTexture(GL_TEXTURE_BUFFER, fragmentTexture); + glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32UI, fragmentBuffer); + glBindTexture(GL_TEXTURE_BUFFER, 0); + + glBindImageTexture(1, fragmentTexture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32UI); + + // ============================ + // SHADERS + // ============================ + resolveShader = nullptr; + using ghoul::opengl::ShaderObject; + using ghoul::opengl::ProgramObject; + ShaderObject* vs + = new ShaderObject(ShaderObject::ShaderType::ShaderTypeVertex, + absPath("${SHADERS}/ABuffer/abufferResolveVertex.glsl"), "Vertex"); + ShaderObject* fs + = new ShaderObject(ShaderObject::ShaderType::ShaderTypeFragment, + absPath("${SHADERS}/ABuffer/abufferResolveFragment.glsl"), "Fragment"); + + resolveShader = new ProgramObject; + resolveShader->attachObject(vs); + resolveShader->attachObject(fs); + + if (!resolveShader->compileShaderObjects()) { + LERROR("Could not compile shader"); + return false; + } + if (!resolveShader->linkProgramObject()){ + LERROR("Could not link shader"); + return false; + } + + // ============================ + // GEOMETRY (quad) + // ============================ + const GLfloat size = 1.0f; + const GLfloat vertex_data[] = { // square of two triangles (sigh) + // x y z w s t + -size, -size, 0.0f, 1.0f, + size, size, 0.0f, 1.0f, + -size, size, 0.0f, 1.0f, + -size, -size, 0.0f, 1.0f, + size, -size, 0.0f, 1.0f, + size, size, 0.0f, 1.0f, + }; + GLuint vertexPositionBuffer; + glGenVertexArrays(1, &_screenQuad); // generate array + glBindVertexArray(_screenQuad); // bind array + glGenBuffers(1, &vertexPositionBuffer); // generate buffer + glBindBuffer(GL_ARRAY_BUFFER, vertexPositionBuffer); // bind buffer + glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data, GL_STATIC_DRAW); + glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*4, BUFFER_OFFSET(0)); + glEnableVertexAttribArray(0); + return true; } void ABufferSingleLinked::clear() { + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, anchorPointerTextureInitializer); + glBindTexture(GL_TEXTURE_2D, anchorPointerTexture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, width, height, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, NULL); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + + static const GLuint zero = 1; + glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer); + glBufferSubData(GL_ATOMIC_COUNTER_BUFFER, 0, sizeof(zero), &zero); + glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, 0); } void ABufferSingleLinked::preRender() { + // Bind head-pointer image for read-write + glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer); + glBindImageTexture(0, anchorPointerTexture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI); + glBindImageTexture(1, fragmentTexture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32UI); } void ABufferSingleLinked::postRender() { - + resolveShader->activate(); + //resolveShader->setUniform("SCREEN_WIDTH", width); + //resolveShader->setUniform("SCREEN_HEIGHT", height); + glBindVertexArray(_screenQuad); + glDrawArrays(GL_TRIANGLES, 0, 6); + resolveShader->deactivate(); } } // openspace \ No newline at end of file diff --git a/src/rendering/renderengine.cpp b/src/rendering/renderengine.cpp index 86691afd84..5d9380a1d2 100644 --- a/src/rendering/renderengine.cpp +++ b/src/rendering/renderengine.cpp @@ -34,6 +34,8 @@ #include +#include + namespace { const std::string _loggerCat = "RenderEngine"; } @@ -42,6 +44,7 @@ namespace openspace { RenderEngine::RenderEngine() : _mainCamera(nullptr) , _sceneGraph(nullptr) + , _abuffer(nullptr) { } @@ -61,6 +64,8 @@ bool RenderEngine::initialize() //if (sgct::Engine::instance()->isMaster()) OsEng.interactionHandler().setCamera(_mainCamera); + _abuffer = new ABufferSingleLinked(); + return true; } @@ -132,6 +137,8 @@ bool RenderEngine::initializeGL() _mainCamera->setMaxFov(maxFov); } + _abuffer->initialize(); + // successful init return true; } @@ -163,8 +170,11 @@ void RenderEngine::render() sgct::Engine::instance()->getActiveModelViewProjectionMatrix() * view); // render the scene starting from the root node + _abuffer->clear(); + _abuffer->preRender(); _sceneGraph->render(_mainCamera); - + _abuffer->postRender(); +/* // Print some useful information on the master viewport if (sgct::Engine::instance()->isMaster()) { // Apple usually has retina screens @@ -200,6 +210,7 @@ void RenderEngine::render() sgct_text::FontManager::instance()->getFont("SGCTFont", FONT_SIZE), FONT_SIZE, FONT_SIZE * 2, "Scaling: (%.10f, %.2f)", scaling[0], scaling[1]); } + */ } SceneGraph* RenderEngine::sceneGraph() From 281104805cbd8738a0b67c7952de7a08e46631e4 Mon Sep 17 00:00:00 2001 From: Hans-Christian Helltegen Date: Thu, 29 May 2014 16:04:27 -0400 Subject: [PATCH 06/49] Is now a bi-directional fieldline tracer using Runge-Kutta 4th order instead of a forward-only tracer using Euler --- include/openspace/util/kameleonwrapper.h | 15 +- src/rendering/renderablevolume.cpp | 23 ++- src/util/kameleonwrapper.cpp | 240 ++++++++++++----------- 3 files changed, 152 insertions(+), 126 deletions(-) diff --git a/include/openspace/util/kameleonwrapper.h b/include/openspace/util/kameleonwrapper.h index e52172b214..513448b03d 100644 --- a/include/openspace/util/kameleonwrapper.h +++ b/include/openspace/util/kameleonwrapper.h @@ -43,6 +43,11 @@ public: BATSRUS // Magnetosphere }; + enum TraceDirection { + FORWARD = 1, + BACK = -1 + }; + KameleonWrapper(const std::string& filename, Model model); ~KameleonWrapper(); float* getUniformSampledValues(const std::string& var, glm::size3_t outDimensions); @@ -53,6 +58,9 @@ public: const std::string& zVar, glm::size3_t outDimensions, std::vector seedPoints); private: + void traceCartesianFieldlines(const std::string& xVar, const std::string& yVar, + const std::string& zVar, glm::size3_t outDimensions, + std::vector seedPoints, TraceDirection direction, float* data); void getGridVariables(std::string& x, std::string& y, std::string& z); void progressBar(int current, int end); @@ -60,7 +68,12 @@ private: Model _type; ccmc::Interpolator* _interpolator; - int _lastiProgress; // for progressbar + // Model parameters + float _xMin, _xMax, _yMin, _yMax, _zMin, _zMax; + std::string _xCoordVar, _yCoordVar, _zCoordVar; + + // For progressbar + int _lastiProgress; }; } // namespace openspace diff --git a/src/rendering/renderablevolume.cpp b/src/rendering/renderablevolume.cpp index 6645357612..ba4581cf23 100644 --- a/src/rendering/renderablevolume.cpp +++ b/src/rendering/renderablevolume.cpp @@ -163,20 +163,23 @@ ghoul::opengl::Texture* RenderableVolume::loadVolume(const std::string& filepath // Seed 'em all std::vector seedPoints; - for (int z = -20; z <= 20; z+=20) { - for (int y = -20; y <= 20; y+=20) - seedPoints.push_back(glm::vec3(-10.0, (float)y, (float)z)); + for (int z = -5; z <= 5; z+=5) { + for (int y = -5; y <= 5; y+=5) + seedPoints.push_back(glm::vec3(5.0, (float)y, (float)z)); } float* fieldlinesData = kw.getFieldLines(xVariable, yVariable, zVariable, dimensions, seedPoints); - float* rhoData = kw.getUniformSampledValues("rho", dimensions); +// float* rhoData = kw.getUniformSampledValues("rho", dimensions); +// +// // Combine fieldlines with rhoData, clamp to [0,1] +// float* data = new float[dimensions.x*dimensions.y*dimensions.z]; +// for (int i = 0; i < dimensions.x*dimensions.y*dimensions.z; ++i) +// data[i] = std::min(fieldlinesData[i]+rhoData[i], 1.0f); +// +// delete fieldlinesData; +// delete rhoData; - // Combine fieldlines with rhoData, clamp to [0,1] - float* data = new float[dimensions.x*dimensions.y*dimensions.z]; - for (int i = 0; i < dimensions.x*dimensions.y*dimensions.z; ++i) - data[i] = std::min(fieldlinesData[i]+rhoData[i], 1.0f); - - return new ghoul::opengl::Texture(data, dimensions, ghoul::opengl::Texture::Format::Red, GL_RED, GL_FLOAT); + return new ghoul::opengl::Texture(fieldlinesData, dimensions, ghoul::opengl::Texture::Format::Red, GL_RED, GL_FLOAT); } } else { diff --git a/src/util/kameleonwrapper.cpp b/src/util/kameleonwrapper.cpp index 60d2ea6aa4..e360301a4b 100644 --- a/src/util/kameleonwrapper.cpp +++ b/src/util/kameleonwrapper.cpp @@ -60,7 +60,25 @@ KameleonWrapper::KameleonWrapper(const std::string& filename, Model model): _typ default: LERROR("No valid model type provided!"); } - _lastiProgress = -1; // for progressbar + + getGridVariables(_xCoordVar, _yCoordVar, _zCoordVar); + LDEBUG("Using coordinate system variables: " << _xCoordVar << ", " << _yCoordVar << ", " << _zCoordVar); + + _xMin = _model->getVariableAttribute(_xCoordVar, "actual_min").getAttributeFloat(); + _xMax = _model->getVariableAttribute(_xCoordVar, "actual_max").getAttributeFloat(); + _yMin = _model->getVariableAttribute(_yCoordVar, "actual_min").getAttributeFloat(); + _yMax = _model->getVariableAttribute(_yCoordVar, "actual_max").getAttributeFloat(); + _zMin = _model->getVariableAttribute(_zCoordVar, "actual_min").getAttributeFloat(); + _zMax = _model->getVariableAttribute(_zCoordVar, "actual_max").getAttributeFloat(); + + LDEBUG(_xCoordVar << "Min: " << _xMin); + LDEBUG(_xCoordVar << "Max: " << _xMax); + LDEBUG(_yCoordVar << "Min: " << _yMin); + LDEBUG(_yCoordVar << "Max: " << _yMax); + LDEBUG(_zCoordVar << "Min: " << _zMin); + LDEBUG(_zCoordVar << "Max: " << _zMax); + + _lastiProgress = -1; // For progressbar } KameleonWrapper::~KameleonWrapper() { @@ -77,29 +95,13 @@ float* KameleonWrapper::getUniformSampledValues(const std::string& var, glm::siz int size = outDimensions.x*outDimensions.y*outDimensions.z; float* data = new float[size]; - std::string v_x, v_y, v_z; - getGridVariables(v_x, v_y, v_z); - LDEBUG("Using coordinate system variables: " << v_x << ", " << v_y << ", " << v_z); - - float xMin = _model->getVariableAttribute(v_x, "actual_min").getAttributeFloat(); - float xMax = _model->getVariableAttribute(v_x, "actual_max").getAttributeFloat(); - float yMin = _model->getVariableAttribute(v_y, "actual_min").getAttributeFloat(); - float yMax = _model->getVariableAttribute(v_y, "actual_max").getAttributeFloat(); - float zMin = _model->getVariableAttribute(v_z, "actual_min").getAttributeFloat(); - float zMax = _model->getVariableAttribute(v_z, "actual_max").getAttributeFloat(); float varMin = _model->getVariableAttribute(var, "actual_min").getAttributeFloat(); float varMax = _model->getVariableAttribute(var, "actual_max").getAttributeFloat(); - float stepX = (xMax-xMin)/(static_cast(outDimensions.x)); - float stepY = (yMax-yMin)/(static_cast(outDimensions.y)); - float stepZ = (zMax-zMin)/(static_cast(outDimensions.z)); + float stepX = (_xMax-_xMin)/(static_cast(outDimensions.x)); + float stepY = (_yMax-_yMin)/(static_cast(outDimensions.y)); + float stepZ = (_zMax-_zMin)/(static_cast(outDimensions.z)); - LDEBUG(v_x << "Min: " << xMin); - LDEBUG(v_x << "Max: " << xMax); - LDEBUG(v_y << "Min: " << yMin); - LDEBUG(v_y << "Max: " << yMax); - LDEBUG(v_z << "Min: " << zMin); - LDEBUG(v_z << "Max: " << zMax); LDEBUG(var << "Min: " << varMin); LDEBUG(var << "Max: " << varMax); @@ -112,9 +114,9 @@ float* KameleonWrapper::getUniformSampledValues(const std::string& var, glm::siz int index = x + y*outDimensions.x + z*outDimensions.x*outDimensions.y; if(_type == Model::BATSRUS) { - float xPos = xMin + stepX*x; - float yPos = yMin + stepY*y; - float zPos = zMin + stepZ*z; + float xPos = _xMin + stepX*x; + float yPos = _yMin + stepY*y; + float zPos = _zMin + stepZ*z; // get interpolated data value for (xPos, yPos, zPos) float value = _interpolator->interpolate(var, xPos, yPos, zPos); @@ -133,18 +135,18 @@ float* KameleonWrapper::getUniformSampledValues(const std::string& var, glm::siz float phiNorm = 2.0*M_PI*(float)z/(float)(outDimensions.z-1); // Go to physical coordinates before sampling - float rPh = xMin + rNorm*(xMax-xMin); + float rPh = _xMin + rNorm*(_xMax-_xMin); float thetaPh = thetaNorm; // phi range needs to be mapped to the slightly different model // range to avoid gaps in the data Subtract a small term to // avoid rounding errors when comparing to phiMax. - float phiPh = zMin + phiNorm/(2.0*M_PI)*(zMax-zMin-0.000001); + float phiPh = _zMin + phiNorm/(2.0*M_PI)*(_zMax-_zMin-0.000001); float varValue = 0.f; // See if sample point is inside domain - if (rPh < xMin || rPh > xMax || thetaPh < yMin || - thetaPh > yMax || phiPh < zMin || phiPh > zMax) { - if (phiPh > zMax) { + if (rPh < _xMin || rPh > _xMax || thetaPh < _yMin || + thetaPh > _yMax || phiPh < _zMin || phiPh > _zMax) { + if (phiPh > _zMax) { std::cout << "Warning: There might be a gap in the data\n"; } // Leave values at zero if outside domain @@ -182,20 +184,6 @@ float* KameleonWrapper::getUniformSampledVectorValues(const std::string& xVar, c int size = channels*outDimensions.x*outDimensions.y*outDimensions.z; float* data = new float[size]; -// memset(data, 0.0, sizeof(data)); - - - - std::string v_x, v_y, v_z; - getGridVariables(v_x, v_y, v_z); - LDEBUG("Using coordinate system variables: " << v_x << ", " << v_y << ", " << v_z); - - float xMin = _model->getVariableAttribute(v_x, "actual_min").getAttributeFloat(); - float xMax = _model->getVariableAttribute(v_x, "actual_max").getAttributeFloat(); - float yMin = _model->getVariableAttribute(v_y, "actual_min").getAttributeFloat(); - float yMax = _model->getVariableAttribute(v_y, "actual_max").getAttributeFloat(); - float zMin = _model->getVariableAttribute(v_z, "actual_min").getAttributeFloat(); - float zMax = _model->getVariableAttribute(v_z, "actual_max").getAttributeFloat(); float varXMin = _model->getVariableAttribute(xVar, "actual_min").getAttributeFloat(); float varXMax = _model->getVariableAttribute(xVar, "actual_max").getAttributeFloat(); float varYMin = _model->getVariableAttribute(yVar, "actual_min").getAttributeFloat(); @@ -203,16 +191,10 @@ float* KameleonWrapper::getUniformSampledVectorValues(const std::string& xVar, c float varZMin = _model->getVariableAttribute(zVar, "actual_min").getAttributeFloat(); float varZMax = _model->getVariableAttribute(zVar, "actual_max").getAttributeFloat(); - float stepX = (xMax-xMin)/(static_cast(outDimensions.x)); - float stepY = (yMax-yMin)/(static_cast(outDimensions.y)); - float stepZ = (zMax-zMin)/(static_cast(outDimensions.z)); + float stepX = (_xMax-_xMin)/(static_cast(outDimensions.x)); + float stepY = (_yMax-_yMin)/(static_cast(outDimensions.y)); + float stepZ = (_zMax-_zMin)/(static_cast(outDimensions.z)); - LDEBUG(v_x << "Min: " << xMin); - LDEBUG(v_x << "Max: " << xMax); - LDEBUG(v_y << "Min: " << yMin); - LDEBUG(v_y << "Max: " << yMax); - LDEBUG(v_z << "Min: " << zMin); - LDEBUG(v_z << "Max: " << zMax); LDEBUG(xVar << "Min: " << varXMin); LDEBUG(xVar << "Max: " << varXMax); LDEBUG(yVar << "Min: " << varYMin); @@ -229,9 +211,9 @@ float* KameleonWrapper::getUniformSampledVectorValues(const std::string& xVar, c int index = x*channels + y*channels*outDimensions.x + z*channels*outDimensions.x*outDimensions.y; if(_type == Model::BATSRUS) { - float xPos = xMin + stepX*x; - float yPos = yMin + stepY*y; - float zPos = zMin + stepZ*z; + float xPos = _xMin + stepX*x; + float yPos = _yMin + stepY*y; + float zPos = _zMin + stepZ*z; // get interpolated data value for (xPos, yPos, zPos) float xValue = _interpolator->interpolate(xVar, xPos, yPos, zPos); @@ -255,6 +237,95 @@ float* KameleonWrapper::getUniformSampledVectorValues(const std::string& xVar, c return data; } +float* KameleonWrapper::getFieldLines(const std::string& xVar, + const std::string& yVar, const std::string& zVar, + glm::size3_t outDimensions, std::vector seedPoints) { + assert(_model && _interpolator); + assert(outDimensions.x > 0 && outDimensions.y > 0 && outDimensions.z > 0); + assert(_type == Model::ENLIL || _type == Model::BATSRUS); + LINFO("Creating " << seedPoints.size() << " fieldlines from variables " << xVar << " " << yVar << " " << zVar); + + int size = outDimensions.x*outDimensions.y*outDimensions.z; + float* data = new float[size]; + + if (_type == Model::BATSRUS) { + // Bi-directional tracing of fieldlines + traceCartesianFieldlines(xVar, yVar, zVar, outDimensions, seedPoints, TraceDirection::FORWARD, data); + traceCartesianFieldlines(xVar, yVar, zVar, outDimensions, seedPoints, TraceDirection::BACK, data); + } else { + LERROR("Fieldlines are only supported for BATSRUS model"); + } + + return data; +} + +void KameleonWrapper::traceCartesianFieldlines(const std::string& xVar, + const std::string& yVar, const std::string& zVar, + glm::size3_t outDimensions, std::vector seedPoints, + TraceDirection direction, float* data) { + + int highNumber = 100000; + glm::vec3 pos, k1, k2, k3, k4; + + float stepSize = 2.0; + float stepX = stepSize*(_xMax-_xMin)/(static_cast(outDimensions.x)); + float stepY = stepSize*(_yMax-_yMin)/(static_cast(outDimensions.y)); + float stepZ = stepSize*(_zMax-_zMin)/(static_cast(outDimensions.z)); + + for (int i = 0; i < seedPoints.size(); ++i) { + progressBar(i, seedPoints.size()); + pos = seedPoints.at(i); + int avoidInfLoopPlz = 0; + while (pos.x < _xMax && pos.x > _xMin && + pos.y < _yMax && pos.y > _yMin && + pos.z < _zMax && pos.z > _zMin) { + + // Save position + int vPosX = std::floor(outDimensions.x*(pos.x-_xMin)/(_xMax-_xMin)); + int vPosY = std::floor(outDimensions.y*(pos.y-_yMin)/(_yMax-_yMin)); + int vPosZ = std::floor(outDimensions.z*(pos.z-_zMin)/(_zMax-_zMin)); + int index = vPosX + vPosY*outDimensions.x + vPosZ*outDimensions.x*outDimensions.y; + data[index] = 1.0; + + // Calculate the next position + // Euler +// dir.x = _interpolator->interpolate(xVar, pos.x, pos.y, pos.z); +// dir.y = _interpolator->interpolate(yVar, pos.x, pos.y, pos.z); +// dir.z = _interpolator->interpolate(zVar, pos.x, pos.y, pos.z); +// dir = (float)direction*glm::normalize(dir); +// pos = glm::vec3(stepX*dir.x+pos.x, stepY*dir.y+pos.y, stepZ*dir.z+pos.z); + + // Runge-Kutta 4th order + k1.x = _interpolator->interpolate(xVar, pos.x, pos.y, pos.z); + k1.y = _interpolator->interpolate(yVar, pos.x, pos.y, pos.z); + k1.z = _interpolator->interpolate(zVar, pos.x, pos.y, pos.z); + k1 = (float)direction*glm::normalize(k1); + k2.x = _interpolator->interpolate(xVar, pos.x+(stepX/2.0)*k1.x, pos.y+(stepY/2.0)*k1.y, pos.z+(stepZ/2.0)*k1.z); + k2.y = _interpolator->interpolate(yVar, pos.x+(stepX/2.0)*k1.x, pos.y+(stepY/2.0)*k1.y, pos.z+(stepZ/2.0)*k1.z); + k2.z = _interpolator->interpolate(zVar, pos.x+(stepX/2.0)*k1.x, pos.y+(stepY/2.0)*k1.y, pos.z+(stepZ/2.0)*k1.z); + k2 = (float)direction*glm::normalize(k2); + k3.x = _interpolator->interpolate(xVar, pos.x+(stepX/2.0)*k2.x, pos.y+(stepY/2.0)*k2.y, pos.z+(stepZ/2.0)*k2.z); + k3.y = _interpolator->interpolate(yVar, pos.x+(stepX/2.0)*k2.x, pos.y+(stepY/2.0)*k2.y, pos.z+(stepZ/2.0)*k2.z); + k3.z = _interpolator->interpolate(zVar, pos.x+(stepX/2.0)*k2.x, pos.y+(stepY/2.0)*k2.y, pos.z+(stepZ/2.0)*k2.z); + k3 = (float)direction*glm::normalize(k3); + k4.x = _interpolator->interpolate(xVar, pos.x+stepX*k3.x, pos.y+stepY*k3.y, pos.z+stepZ*k3.z); + k4.y = _interpolator->interpolate(yVar, pos.x+stepX*k3.x, pos.y+stepY*k3.y, pos.z+stepZ*k3.z); + k4.z = _interpolator->interpolate(zVar, pos.x+stepX*k3.x, pos.y+stepY*k3.y, pos.z+stepZ*k3.z); + k4 = (float)direction*glm::normalize(k4); + pos.x = pos.x + (stepX/6.0)*(k1.x + 2.0*k2.x + 2.0*k3.x + k4.x); + pos.y = pos.y + (stepY/6.0)*(k1.y + 2.0*k2.y + 2.0*k3.y + k4.y); + pos.z = pos.z + (stepZ/6.0)*(k1.z + 2.0*k2.z + 2.0*k3.z + k4.z); + + ++avoidInfLoopPlz; + + if (avoidInfLoopPlz > highNumber) { + LDEBUG("Inf loop averted"); + break; + } + } + } +} + void KameleonWrapper::getGridVariables(std::string& x, std::string& y, std::string& z) { // get the grid system string std::string gridSystem = _model->getGlobalAttribute("grid_system_1").getAttributeString(); @@ -280,67 +351,6 @@ void KameleonWrapper::getGridVariables(std::string& x, std::string& y, std::stri z = tokens.at(2); } -float* KameleonWrapper::getFieldLines(const std::string& xVar, - const std::string& yVar, const std::string& zVar, - glm::size3_t outDimensions, std::vector seedPoints) { - assert(_model && _interpolator); - assert(outDimensions.x > 0 && outDimensions.y > 0 && outDimensions.z > 0); - assert(_type == Model::ENLIL || _type == Model::BATSRUS); - LINFO("Creating " << seedPoints.size() << " fieldlines from variables " << xVar << " " << yVar << " " << zVar); - - std::string v_x, v_y, v_z; - getGridVariables(v_x, v_y, v_z); - LDEBUG("Using coordinate system variables: " << v_x << ", " << v_y << ", " << v_z); - - float xMin = _model->getVariableAttribute(v_x, "actual_min").getAttributeFloat(); - float xMax = _model->getVariableAttribute(v_x, "actual_max").getAttributeFloat(); - float yMin = _model->getVariableAttribute(v_y, "actual_min").getAttributeFloat(); - float yMax = _model->getVariableAttribute(v_y, "actual_max").getAttributeFloat(); - float zMin = _model->getVariableAttribute(v_z, "actual_min").getAttributeFloat(); - float zMax = _model->getVariableAttribute(v_z, "actual_max").getAttributeFloat(); - - float stepSize = 0.001; - float stepX = stepSize*(xMax-xMin)/(static_cast(outDimensions.x)); - float stepY = stepSize*(yMax-yMin)/(static_cast(outDimensions.y)); - float stepZ = stepSize*(zMax-zMin)/(static_cast(outDimensions.z)); - - int size = outDimensions.x*outDimensions.y*outDimensions.z; - float* data = new float[size]; - glm::vec3 dir, pos; - - int highNumber = 100000; - - for (int i = 0; i < seedPoints.size(); ++i) { - progressBar(i, seedPoints.size()); - pos = seedPoints.at(i); - int avoidInfLoopPlz = 0; - while (pos.x < xMax && pos.x > xMin && - pos.y < yMax && pos.y > yMin && - pos.z < zMax && pos.z > zMin) { - - // Save position - int vPosX = std::floor(outDimensions.x*(pos.x-xMin)/(xMax-xMin)); - int vPosY = std::floor(outDimensions.y*(pos.y-yMin)/(yMax-yMin)); - int vPosZ = std::floor(outDimensions.z*(pos.z-zMin)/(zMax-zMin)); - int index = vPosX + vPosY*outDimensions.x + vPosZ*outDimensions.x*outDimensions.y; - data[index] = 1.0; - - // Calculate the next position - dir.x = _interpolator->interpolate(xVar, pos.x, pos.y, pos.z); - dir.y = _interpolator->interpolate(yVar, pos.x, pos.y, pos.z); - dir.z = _interpolator->interpolate(zVar, pos.x, pos.y, pos.z); - pos = glm::vec3(stepX*dir.x+pos.x, stepY*dir.y+pos.y, stepZ*dir.z+pos.z); - ++avoidInfLoopPlz; - - if (avoidInfLoopPlz > highNumber) { - LDEBUG("Inf loop averted"); - break; - } - } - } - return data; -} - void KameleonWrapper::progressBar(int current, int end) { float progress = static_cast(current) / static_cast(end-1); int iprogress = static_cast(progress*100.0f); From d2ccf6cdfb3ada755e9a63a569dba1e310290d8a Mon Sep 17 00:00:00 2001 From: Jonas Strandstedt Date: Mon, 2 Jun 2014 13:35:17 -0400 Subject: [PATCH 07/49] Intermediate ABuffer with ABufferStruct_t --- shaders/ABuffer/abufferAddToBuffer.hglsl | 9 ++ shaders/ABuffer/abufferResolveFragment.glsl | 38 ++------- shaders/ABuffer/abufferSort.hglsl | 32 ++++++++ shaders/ABuffer/abufferStruct.hglsl | 91 +++++++++++++++++++++ shaders/pscstandard_fs.glsl | 16 +++- src/rendering/renderengine.cpp | 6 +- 6 files changed, 155 insertions(+), 37 deletions(-) create mode 100644 shaders/ABuffer/abufferAddToBuffer.hglsl create mode 100644 shaders/ABuffer/abufferSort.hglsl create mode 100644 shaders/ABuffer/abufferStruct.hglsl diff --git a/shaders/ABuffer/abufferAddToBuffer.hglsl b/shaders/ABuffer/abufferAddToBuffer.hglsl new file mode 100644 index 0000000000..c2421ba3f3 --- /dev/null +++ b/shaders/ABuffer/abufferAddToBuffer.hglsl @@ -0,0 +1,9 @@ + + +void addToBuffer(ABufferStruct_t frag) { + + uint index = atomicCounterIncrement(atomicCounterBuffer); + uint old_head = imageAtomicExchange(anchorPointerTexture, ivec2(gl_FragCoord.xy), index); + _next_(frag,old_head); + imageStore(fragmentTexture, int(index), _uvec4_(frag)); +} \ No newline at end of file diff --git a/shaders/ABuffer/abufferResolveFragment.glsl b/shaders/ABuffer/abufferResolveFragment.glsl index d0b46b2968..a849b99b18 100644 --- a/shaders/ABuffer/abufferResolveFragment.glsl +++ b/shaders/ABuffer/abufferResolveFragment.glsl @@ -13,41 +13,13 @@ uniform int SCREEN_HEIGHT; in vec2 texCoord; out vec4 color; +#include "abufferStruct.hglsl" #define MAX_FRAGMENTS 16 -uvec4 fragments[MAX_FRAGMENTS]; +ABufferStruct_t fragments[MAX_FRAGMENTS]; -int build_local_fragments_list() { - uint current; - int frag_count = 0; +#include "abufferSort.hglsl" - current = imageLoad(anchorPointerTexture, ivec2(gl_FragCoord.xy)).x; - - while(current != 0 && frag_count < MAX_FRAGMENTS) { - uvec4 item = imageLoad(fragmentTexture, int(current)); - current = item.x; - - fragments[frag_count] = item; - - frag_count++; - } - - return frag_count; -} - -void sort_fragments_list(uint frag_count) { - uint i,j; - uvec4 tmp; - - // INSERTION SORT - for(i = 1; i < frag_count; ++i) { - tmp = fragments[i]; - for(j = i; j > 0 && tmp.z > fragments[j-1].z; --j) { - fragments[j] = fragments[j-1]; - } - fragments[j] = tmp; - } -} vec4 blend(vec4 current_color, vec4 new_color) { return mix(current_color, new_color, new_color.a); @@ -57,8 +29,8 @@ vec4 calculate_final_color(uint frag_count) { vec4 final_color = vec4(0); for(uint i = 0; i < frag_count; i++) { - uvec4 item = fragments[i]; - vec4 frag_color = unpackUnorm4x8(item.y); + ABufferStruct_t item = fragments[i]; + vec4 frag_color = _col_(item); final_color = blend(final_color, frag_color); } diff --git a/shaders/ABuffer/abufferSort.hglsl b/shaders/ABuffer/abufferSort.hglsl new file mode 100644 index 0000000000..df61c45353 --- /dev/null +++ b/shaders/ABuffer/abufferSort.hglsl @@ -0,0 +1,32 @@ + +int build_local_fragments_list() { + uint current; + int frag_count = 0; + + current = imageLoad(anchorPointerTexture, ivec2(gl_FragCoord.xy)).x; + + while(current != 0 && frag_count < MAX_FRAGMENTS) { + ABufferStruct_t item = _ABufferStruct_t_(imageLoad(fragmentTexture, int(current))); + current = _next_(item); + + fragments[frag_count] = item; + + frag_count++; + } + + return frag_count; +} + +void sort_fragments_list(uint frag_count) { + uint i,j; + ABufferStruct_t tmp; + + // INSERTION SORT + for(i = 1; i < frag_count; ++i) { + tmp = fragments[i]; + for(j = i; j > 0 && _z_(tmp) > _z_(fragments[j-1]); --j) { + fragments[j] = fragments[j-1]; + } + fragments[j] = tmp; + } +} diff --git a/shaders/ABuffer/abufferStruct.hglsl b/shaders/ABuffer/abufferStruct.hglsl new file mode 100644 index 0000000000..5e343e5176 --- /dev/null +++ b/shaders/ABuffer/abufferStruct.hglsl @@ -0,0 +1,91 @@ +#ifndef ABUFFERSTRUCT_H_HGLSL +#define ABUFFERSTRUCT_H_HGLSL + + +//======================================================= +// ABufferStruct_t declaration +//======================================================= +struct ABufferStruct_t { + uint z; // the depth value + uint id; // bits 0-28 next, bits 29-32 type + uint color; // packed rgba + uint type; // packed position +}; + +//======================================================= +// Bitwise operations +//======================================================= +const uint mask_1 = 1; +const uint mask_8 = 255; +const uint mask_16 = 65535; +const uint mask_24 = 16777215; +const uint mask_29 = 536870911; +const uint mask_30 = 1073741823; +const uint mask_31 = 2147483647; +const uint mask_32 = 4294967295; +const uint mask_id = mask_16; +const uint shift_id = 0; +const uint mask_type = mask_24 - mask_16; +const uint shift_type = 16; +void bitinsert_u(inout uint pack, uint val, uint mask, uint shift) { + pack &= ~mask; + pack |= (val << shift) & mask; +} +uint bitextract_u(in uint pack, uint mask, uint shift) { + return (pack >> shift) & (mask >> shift); +} +void bitinsert_i(inout int pack, int val, uint mask, uint shift) { + pack &= int( ~mask ); + pack |= int( (uint(val) << shift) & mask ); +} +int bitextract_i(in int pack, uint mask, uint shift) { + return int( (uint(pack) >> shift) & (mask >> shift) ); +} + + +//======================================================= +// Access functions +//======================================================= +float _z_(ABufferStruct_t frag) { + return uintBitsToFloat(frag.z); +} +void _z_(inout ABufferStruct_t frag, float z) { + frag.z = floatBitsToUint(z); +} + +uint _next_(ABufferStruct_t frag) { + return frag.id; +} +void _next_(inout ABufferStruct_t frag, uint id) { + frag.id = id; +} + +vec4 _col_(ABufferStruct_t frag) { + return unpackUnorm4x8(frag.color); +} +void _col_(inout ABufferStruct_t frag, vec4 color) { + frag.color = packUnorm4x8(color); +} + +uint _type_(ABufferStruct_t frag) { + return frag.type; +} +void _type_(inout ABufferStruct_t frag, uint type) { + frag.type = type;; +} + +/* +_id_ +_type_ +uint _type_(ABufferStruct_t frag) { + return frag +} +*/ + +ABufferStruct_t _ABufferStruct_t_(uvec4 frag) { + return ABufferStruct_t(frag.x, frag.y, frag.z, frag.w); +}; +uvec4 _uvec4_(ABufferStruct_t frag) { + return uvec4(frag.z, frag.id, frag.color, frag.type); +}; +#endif \ No newline at end of file diff --git a/shaders/pscstandard_fs.glsl b/shaders/pscstandard_fs.glsl index eb95f757ba..c35b40e5f4 100644 --- a/shaders/pscstandard_fs.glsl +++ b/shaders/pscstandard_fs.glsl @@ -31,6 +31,10 @@ out vec4 diffuse; const float k = 10.0; +#include "ABuffer/abufferStruct.hglsl" +#include "ABuffer/abufferAddToBuffer.hglsl" + + vec4 psc_normlization(vec4 invec) { float xymax = max(invec.x,invec.y); @@ -106,7 +110,7 @@ void main() //gl_FragDepth = 0.5; // color - diffuse = texture(texture1, vs_st); + diffuse = texture(texture1, vs_st); //diffuse = vec4(vs_position.z,0.0, 0.0, 1.0); // diffuse = vec4(vs_position.xyz * pow(10, vs_position.w), 1.0); //diffuse = vec4(vs_st, 0.0, 1.0); @@ -114,6 +118,14 @@ void main() //diffuse = vec4(depth*5,0.0, 0.0, 1.0); //diffuse = vec4(vs_position.w,0.0, 0.0, 1.0); //diffuse = vec4(1.0,0.0,0.0,1.0); + + ABufferStruct_t frag; + _col_(frag, diffuse); + _z_(frag, depth); + _type_(frag, 0); + addToBuffer(frag); + + /* uint index = atomicCounterIncrement(atomicCounterBuffer); uint old_head = imageAtomicExchange(anchorPointerTexture, ivec2(gl_FragCoord.xy), index); uvec4 item; @@ -122,6 +134,6 @@ void main() item.z = floatBitsToUint(gl_FragCoord.z / gl_FragCoord.w); item.w = 0; imageStore(fragmentTexture, int(index), item); - +*/ discard; } \ No newline at end of file diff --git a/src/rendering/renderengine.cpp b/src/rendering/renderengine.cpp index 5d9380a1d2..da40fe000f 100644 --- a/src/rendering/renderengine.cpp +++ b/src/rendering/renderengine.cpp @@ -157,8 +157,10 @@ void RenderEngine::postSynchronizationPreDraw() void RenderEngine::render() { // SGCT resets certain settings - glEnable(GL_DEPTH_TEST); - glEnable(GL_CULL_FACE); + //glEnable(GL_DEPTH_TEST); + //glEnable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glDisable(GL_CULL_FACE); // setup the camera for the current frame const glm::vec3 eyePosition From 67778209d214ed6b58dcd0096dcd8c3dfe575720 Mon Sep 17 00:00:00 2001 From: Hans-Christian Helltegen Date: Mon, 2 Jun 2014 14:22:45 -0400 Subject: [PATCH 08/49] Fieldline work. Fixed VolumeRenderableGL --- .../openspace/rendering/renderablevolumegl.h | 25 +--- openspace-data | 2 +- src/rendering/renderablevolumeexpert.cpp | 2 +- src/rendering/renderablevolumegl.cpp | 128 ++++++------------ 4 files changed, 47 insertions(+), 110 deletions(-) diff --git a/include/openspace/rendering/renderablevolumegl.h b/include/openspace/rendering/renderablevolumegl.h index 6cca3f458f..b6b261ebe7 100644 --- a/include/openspace/rendering/renderablevolumegl.h +++ b/include/openspace/rendering/renderablevolumegl.h @@ -27,6 +27,7 @@ // open space includes #include +#include // ghoul includes #include @@ -35,24 +36,16 @@ #include #include -#define SGCT_WINDOWS_INCLUDE -#include - #ifdef __APPLE__ #include #else #include #endif -namespace sgct_utils { - class SGCTBox; -} - namespace openspace { class RenderableVolumeGL: public RenderableVolume { public: - // constructors & destructor RenderableVolumeGL(const ghoul::Dictionary& dictionary); ~RenderableVolumeGL(); @@ -64,18 +57,15 @@ public: virtual void update(); private: - - + ghoul::Dictionary _hintsDictionary; std::string _filename; - ghoul::RawVolumeReader::ReadHints _hints; float _stepSize; - ghoul::opengl::FramebufferObject* _fbo; - ghoul::opengl::Texture* _backTexture; - ghoul::opengl::Texture* _frontTexture; ghoul::opengl::Texture* _volume; - ghoul::opengl::ProgramObject *_fboProgram, *_twopassProgram; - sgct_utils::SGCTBox* _boundingBox; + ghoul::opengl::ProgramObject* _twopassProgram; GLuint _screenQuad; + + VolumeRaycasterBox* _colorBoxRenderer; + glm::vec3 _boxScaling; std::mutex* _shaderMutex; @@ -84,9 +74,8 @@ private: bool _programUpdateOnSave; void safeShaderCompilation(); - }; } // namespace openspace -#endif \ No newline at end of file +#endif diff --git a/openspace-data b/openspace-data index 42865a2858..4af0a41ba1 160000 --- a/openspace-data +++ b/openspace-data @@ -1 +1 @@ -Subproject commit 42865a28580b0195ef7b82b175df8ef9f73f46bc +Subproject commit 4af0a41ba1d5dd1afade5d95495485b7de58c072 diff --git a/src/rendering/renderablevolumeexpert.cpp b/src/rendering/renderablevolumeexpert.cpp index 1785c58857..d1d33c9e51 100644 --- a/src/rendering/renderablevolumeexpert.cpp +++ b/src/rendering/renderablevolumeexpert.cpp @@ -210,7 +210,7 @@ RenderableVolumeExpert::RenderableVolumeExpert(const ghoul::Dictionary& dictiona } } - setBoundingSphere(PowerScaledScalar::CreatePSS(_boxScaling.length())); + setBoundingSphere(PowerScaledScalar::CreatePSS(glm::length(_boxScaling))); } RenderableVolumeExpert::~RenderableVolumeExpert() { diff --git a/src/rendering/renderablevolumegl.cpp b/src/rendering/renderablevolumegl.cpp index 0d1ae60475..52739394b1 100644 --- a/src/rendering/renderablevolumegl.cpp +++ b/src/rendering/renderablevolumegl.cpp @@ -24,15 +24,13 @@ // open space includes #include - #include +#include #include #include #include -#include - #include namespace { @@ -42,8 +40,7 @@ namespace { namespace openspace { RenderableVolumeGL::RenderableVolumeGL(const ghoul::Dictionary& dictionary): - RenderableVolume(dictionary), - _backTexture(nullptr), _frontTexture(nullptr), _screenQuad(0), + RenderableVolume(dictionary), _screenQuad(0), _boxScaling(1.0, 1.0, 1.0), _programUpdateOnSave(false) { _shaderMutex = new std::mutex; @@ -54,13 +51,11 @@ RenderableVolumeGL::RenderableVolumeGL(const ghoul::Dictionary& dictionary): _filename = findPath(_filename); } } - + LDEBUG("filename: " << _filename); - ghoul::Dictionary hintsDictionary; if(dictionary.hasKey("Hints")) - dictionary.getValue("Hints", hintsDictionary); - _hints = readHints(hintsDictionary); + dictionary.getValue("Hints", _hintsDictionary); std::string vshaderpath = ""; std::string fshaderpath = ""; @@ -87,35 +82,43 @@ RenderableVolumeGL::RenderableVolumeGL(const ghoul::Dictionary& dictionary): _twopassProgram->attachObject(vertexShader); _twopassProgram->attachObject(fragmentShader); } - - } if(dictionary.hasKey("UpdateOnSave")) { dictionary.getValue("UpdateOnSave", _programUpdateOnSave); } + double tempValue; + if(dictionary.hasKey("BoxScaling.1") && dictionary.getValue("BoxScaling.1", tempValue)) { + if(tempValue > 0.0) + _boxScaling[0] = tempValue; + } + if(dictionary.hasKey("BoxScaling.2") && dictionary.getValue("BoxScaling.2", tempValue)) { + if(tempValue > 0.0) + _boxScaling[1] = tempValue; + } + if(dictionary.hasKey("BoxScaling.3") && dictionary.getValue("BoxScaling.3", tempValue)) { + if(tempValue > 0.0) + _boxScaling[2] = tempValue; + } + + _colorBoxRenderer = new VolumeRaycasterBox(); + setBoundingSphere(PowerScaledScalar::CreatePSS(glm::length(_boxScaling))); } RenderableVolumeGL::~RenderableVolumeGL() { deinitialize(); - if(_fbo) - delete _fbo; - if(_backTexture) - delete _backTexture; - if(_frontTexture) - delete _frontTexture; if(_volume) delete _volume; - if(_boundingBox) - delete _boundingBox; + if(_colorBoxRenderer) + delete _colorBoxRenderer; } bool RenderableVolumeGL::initialize() { assert(_filename != ""); // ------ VOLUME READING ---------------- - ghoul::RawVolumeReader rawReader(_hints); - _volume = rawReader.read(_filename); + _volume = loadVolume(_filename, _hintsDictionary); + _volume->uploadTexture(); // ------ SETUP GEOMETRY ---------------- const GLfloat size = 1.0f; @@ -149,12 +152,9 @@ bool RenderableVolumeGL::initialize() { glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind buffer glBindVertexArray(0); //unbind array - _boundingBox = new sgct_utils::SGCTBox(1.0f, sgct_utils::SGCTBox::Regular); + _colorBoxRenderer->initialize(); // ------ SETUP SHADERS ----------------- - // TODO error control or better design pattern - OsEng.ref().configurationManager().getValue("RaycastProgram", _fboProgram); - auto privateCallback = [this](const ghoul::filesystem::File& file) { safeShaderCompilation(); }; @@ -168,76 +168,27 @@ bool RenderableVolumeGL::initialize() { _twopassProgram->setUniform("texBack", 0); _twopassProgram->setUniform("texFront", 1); _twopassProgram->setUniform("texVolume", 2); - //OsEng.ref().configurationManager().getValue("TwoPassProgram", _twopassProgram); - - // ------ SETUP FBO --------------------- - _fbo = new ghoul::opengl::FramebufferObject(); - _fbo->activate(); - - int x = sgct::Engine::instance()->getActiveXResolution(); - int y = sgct::Engine::instance()->getActiveYResolution(); - _backTexture = new ghoul::opengl::Texture(glm::size3_t(x,y,1)); - _frontTexture = new ghoul::opengl::Texture(glm::size3_t(x,y,1)); - _backTexture->uploadTexture(); - _frontTexture->uploadTexture(); - _fbo->attachTexture(_backTexture, GL_COLOR_ATTACHMENT0); - _fbo->attachTexture(_frontTexture, GL_COLOR_ATTACHMENT1); - - _fbo->deactivate(); - return true; } bool RenderableVolumeGL::deinitialize() { - - return true; } void RenderableVolumeGL::render(const Camera *camera, const psc &thisPosition) { - - float speed = 50.0f; - float time = sgct::Engine::getTime(); - glm::mat4 transform = camera->viewProjectionMatrix(); - - double factor = pow(10.0,thisPosition[3]); - transform = glm::translate(transform, glm::vec3(thisPosition[0]*factor, thisPosition[1]*factor, thisPosition[2]*factor)); - transform = glm::rotate(transform, time*speed, glm::vec3(0.0f, 1.0f, 0.0f)); - - _stepSize = 0.01f; + + glm::mat4 transform = camera->viewProjectionMatrix(); + glm::mat4 camTransform = camera->viewRotationMatrix(); + psc relative = thisPosition-camera->position(); + + transform = transform*camTransform; + transform = glm::translate(transform, relative.vec3()); + transform = glm::scale(transform, _boxScaling); + + _colorBoxRenderer->render(transform); - // ------ DRAW TO FBO ------------------- - GLuint sgctFBO = ghoul::opengl::FramebufferObject::getActiveObject(); // Save SGCTs main FBO - _fbo->activate(); - _fboProgram->activate(); - _fboProgram->setUniform("modelViewProjection", transform); - - // 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); - _boundingBox->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); - _boundingBox->draw(); - glDisable(GL_CULL_FACE); - - _fboProgram->deactivate(); - _fbo->deactivate(); - - // ------ DRAW TO SCREEN ---------------- - glBindFramebuffer(GL_FRAMEBUFFER, sgctFBO); // Re-bind SGCTs main FBO - // Draw screenquad glClearColor(0.2f, 0.2f, 0.2f, 0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -248,9 +199,9 @@ void RenderableVolumeGL::render(const Camera *camera, const psc &thisPosition) { // Set textures glActiveTexture(GL_TEXTURE0); - _backTexture->bind(); + _colorBoxRenderer->backFace()->bind(); glActiveTexture(GL_TEXTURE1); - _frontTexture->bind(); + _colorBoxRenderer->frontFace()->bind(); glActiveTexture(GL_TEXTURE2); _volume->bind(); @@ -260,7 +211,6 @@ void RenderableVolumeGL::render(const Camera *camera, const psc &thisPosition) { _twopassProgram->deactivate(); _shaderMutex->unlock(); - } void RenderableVolumeGL::update() { @@ -277,7 +227,5 @@ void RenderableVolumeGL::safeShaderCompilation() { _twopassProgram->setUniform("texVolume", 2); _shaderMutex->unlock(); } - - -} // namespace openspace \ No newline at end of file +} // namespace openspace From 2c3f6396ec0c39437574da0d7c304771cb7fb8c8 Mon Sep 17 00:00:00 2001 From: Jonas Strandstedt Date: Mon, 2 Jun 2014 14:51:56 -0400 Subject: [PATCH 09/49] Intermedieate ABuffer, cleaning up shader loading --- shaders/ABuffer/abufferStruct.hglsl | 11 +- shaders/pscvolume_fs.glsl | 139 ++++++++++++++++++++++++ shaders/pscvolume_vs.glsl | 115 ++++++++++++++++++++ src/scenegraph/scenegraph.cpp | 157 ++++++++++++++++------------ 4 files changed, 346 insertions(+), 76 deletions(-) create mode 100644 shaders/pscvolume_fs.glsl create mode 100644 shaders/pscvolume_vs.glsl diff --git a/shaders/ABuffer/abufferStruct.hglsl b/shaders/ABuffer/abufferStruct.hglsl index 5e343e5176..83f212b7fe 100644 --- a/shaders/ABuffer/abufferStruct.hglsl +++ b/shaders/ABuffer/abufferStruct.hglsl @@ -9,7 +9,7 @@ struct ABufferStruct_t { uint z; // the depth value uint id; // bits 0-28 next, bits 29-32 type uint color; // packed rgba - uint type; // packed position + uint type; // packed position }; //======================================================= @@ -42,7 +42,6 @@ int bitextract_i(in int pack, uint mask, uint shift) { return int( (uint(pack) >> shift) & (mask >> shift) ); } - //======================================================= // Access functions //======================================================= @@ -74,14 +73,6 @@ void _type_(inout ABufferStruct_t frag, uint type) { frag.type = type;; } -/* -_id_ -_type_ -uint _type_(ABufferStruct_t frag) { - return frag -} -*/ - ABufferStruct_t _ABufferStruct_t_(uvec4 frag) { return ABufferStruct_t(frag.x, frag.y, frag.z, frag.w); }; diff --git a/shaders/pscvolume_fs.glsl b/shaders/pscvolume_fs.glsl new file mode 100644 index 0000000000..c35b40e5f4 --- /dev/null +++ b/shaders/pscvolume_fs.glsl @@ -0,0 +1,139 @@ +/** +Copyright (C) 2012-2014 Jonas Strandstedt + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ +#version 430 + +layout (binding = 0, r32ui) uniform uimage2D anchorPointerTexture; +layout (binding = 1, rgba32ui) uniform uimageBuffer fragmentTexture; +layout (binding = 0, offset = 0) uniform atomic_uint atomicCounterBuffer; + +uniform mat4 ViewProjection; +uniform mat4 ModelTransform; +uniform vec4 campos; +uniform vec4 objpos; +uniform float time; +uniform sampler2D texture1; + +vec3 light_position = vec3(40.0, 20.0, 100.0); + +in vec2 vs_st; +//in vec3 vs_stp; +in vec4 vs_normal; +in vec4 vs_position; + +out vec4 diffuse; + +const float k = 10.0; + +#include "ABuffer/abufferStruct.hglsl" +#include "ABuffer/abufferAddToBuffer.hglsl" + + +vec4 psc_normlization(vec4 invec) { + + float xymax = max(invec.x,invec.y); + + if(invec.z > 0.0f || invec.z < 0.0f) { + return invec / abs(invec.z); + } else if (xymax != 0.0f) { + return invec / xymax; + } else { + return invec / -.0; + } +} + +void main() +{ + + // Observable universe is 10^27m, setting the far value to extremely high, aka 30!! ERMAHGERD! + float s_far = 27.0; //= gl_DepthRange.far; // 40 + float s_farcutoff = 12.0; + float s_nearcutoff = 7.0; + float s_near = 0.0f;// gl_DepthRange.near; // 0.1 + float depth; + + // the value can be normalized to 1 + + vec4 p = vs_position; + if(vs_position.w <= 0.5) { + //depth = abs(vs_position.z * pow(10, vs_position.w)) / pow(k,s_far); + depth = (vs_position.w+log(abs(vs_position.z)))/pow(k, vs_position.w); + } else if(vs_position.w < 3.0) { + depth = vs_position.w+log(abs(vs_position.z))/pow(k, vs_position.w); + } else { + depth = vs_position.w+log(abs(vs_position.z)); + } + + + // DEBUG + float depth_orig = depth; + float x = 0.0f; + float cutoffs = 0.0; + float orig_z = vs_position.z; + + // calculate a normalized depth [0.0 1.0] + if((depth > s_near && depth <= s_nearcutoff) || (depth > s_farcutoff && depth < s_far)) { + + // completely linear interpolation [s_near .. depth .. s_far] + depth = (depth - s_near) / (s_far - s_near); + + } else if(depth > s_nearcutoff && depth < s_farcutoff) { + + // DEBUG + cutoffs = 1.0; + + // interpolate [10^s_nearcutoff .. 10^depth .. 10^s_farcutoff] + // calculate between 0..1 where the depth is + x = (pow(10,depth) - pow(10, s_nearcutoff)) / (pow(10,s_farcutoff) - pow(10, s_nearcutoff)); + + // remap the depth to the 0..1 depth buffer + depth = s_nearcutoff + x * (s_farcutoff - s_nearcutoff); + depth = (depth - s_near) / (s_far - s_near); + + } else { + // where am I? + // do I need to be discarded? + // discard; + } + + + + + // set the depth + gl_FragDepth = depth; + //gl_FragDepth = 0.5; + + // color + diffuse = texture(texture1, vs_st); + //diffuse = vec4(vs_position.z,0.0, 0.0, 1.0); + // diffuse = vec4(vs_position.xyz * pow(10, vs_position.w), 1.0); + //diffuse = vec4(vs_st, 0.0, 1.0); + //diffuse = vec4(1.0,1.0, 0.0, 1.0); + //diffuse = vec4(depth*5,0.0, 0.0, 1.0); + //diffuse = vec4(vs_position.w,0.0, 0.0, 1.0); + //diffuse = vec4(1.0,0.0,0.0,1.0); + + ABufferStruct_t frag; + _col_(frag, diffuse); + _z_(frag, depth); + _type_(frag, 0); + addToBuffer(frag); + + /* + uint index = atomicCounterIncrement(atomicCounterBuffer); + uint old_head = imageAtomicExchange(anchorPointerTexture, ivec2(gl_FragCoord.xy), index); + uvec4 item; + item.x = old_head; + item.y = packUnorm4x8(diffuse); + item.z = floatBitsToUint(gl_FragCoord.z / gl_FragCoord.w); + item.w = 0; + imageStore(fragmentTexture, int(index), item); +*/ + discard; +} \ No newline at end of file diff --git a/shaders/pscvolume_vs.glsl b/shaders/pscvolume_vs.glsl new file mode 100644 index 0000000000..5a612667a2 --- /dev/null +++ b/shaders/pscvolume_vs.glsl @@ -0,0 +1,115 @@ +/** +Copyright (C) 2012-2014 Jonas Strandstedt + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ +#version 430 + +uniform mat4 ViewProjection; +uniform mat4 ModelTransform; +uniform vec4 campos; +uniform mat4 camrot; +uniform vec2 scaling; +uniform vec4 objpos; +uniform float time; +uniform sampler2D texture1; +uniform sampler2D texture2; +uniform sampler2D texture3; +uniform float TessLevel; +uniform bool Wireframe; +uniform bool Lightsource; +uniform bool UseTexture; + +layout(location = 0) in vec4 in_position; +//in vec3 in_position; +layout(location = 1) in vec2 in_st; +layout(location = 2) in vec3 in_normal; + +out vec2 vs_st; +out vec3 vs_stp; +out vec4 vs_normal; +out vec4 vs_position; + +const float k = 10.0; +const float dgr_to_rad = 0.0174532925; + +vec4 psc_addition(vec4 v1, vec4 v2) { + float ds = v2.w - v1.w; + if(ds >= 0) { + float p = pow(k,-ds); + return vec4(v1.x*p + v2.x, v1.y*p + v2.y, v1.z*p + v2.z, v2.w); + } else { + float p = pow(k,ds); + return vec4(v1.x + v2.x*p, v1.y + v2.y*p, v1.z + v2.z*p, v1.w); + } +} + +vec4 psc_to_meter(vec4 v1, vec2 v2) { + float factor = v2.x * pow(k,v2.y + v1.w); + return vec4(v1.xyz * factor, 1.0); +} + +vec4 psc_scaling(vec4 v1, vec2 v2) { + float ds = v2.y - v1.w; + if(ds >= 0) { + return vec4(v1.xyz * v2.x * pow(k,v1.w), v2.y); + } else { + return vec4(v1.xyz * v2.x * pow(k,v2.y), v1.w); + } +} + +void main() +{ + // set variables + vs_st = in_st; + //vs_stp = in_position.xyz; + vs_normal = normalize(ModelTransform * vec4(in_normal,0)); + + // fetch model and view translation + //vec4 vertex_translate = ModelTransform[3]; + + // rotate and scale vertex with model transform and add the translation + vec3 local_vertex_pos = mat3(ModelTransform) * in_position.xyz; + //vec4 lvp = ModelTransform * in_position; + + // PSC addition; local vertex position and the object power scaled world position + vs_position = psc_addition(vec4(local_vertex_pos,in_position.w),objpos); + //vs_position = psc_addition(lvp,objpos); + + // PSC addition; rotated and viewscaled vertex and the cmaeras negative position + vs_position = psc_addition(vs_position,vec4(-campos.xyz,campos.w)); + + // rotate the camera + local_vertex_pos = mat3(camrot) * vs_position.xyz; + vs_position = vec4(local_vertex_pos, vs_position.w); + //vs_position = camrot* vs_position; + + // rescales the scene to fit inside the view frustum + // is set from the main program, but these are decent values + // scaling = vec2(1.0, -8.0); + + // project using the rescaled coordinates, + //vec4 vs_position_rescaled = psc_scaling(vs_position, scaling); + vec4 vs_position_rescaled = psc_to_meter(vs_position, scaling); + //vs_position = vs_position_rescaled; + + + // project the position to view space + gl_Position = ViewProjection * vs_position_rescaled; +} \ No newline at end of file diff --git a/src/scenegraph/scenegraph.cpp b/src/scenegraph/scenegraph.cpp index 17a55e4158..e0ab7ba128 100644 --- a/src/scenegraph/scenegraph.cpp +++ b/src/scenegraph/scenegraph.cpp @@ -51,18 +51,18 @@ const std::string _loggerCat = "SceneGraph"; const std::string _rootNodeName = "Root"; const std::string _moduleExtension = ".mod"; +void printTree(openspace::SceneGraphNode* node, std::string pre = "") +{ + LDEBUGC("Tree", pre << node->nodeName()); + const std::vector& children = node->children(); + for (openspace::SceneGraphNode* child : children) + printTree(child, pre + " "); +} + } namespace openspace { -void printTree(SceneGraphNode* node, std::string pre = "") -{ - LDEBUGC("Tree", pre << node->nodeName()); - const std::vector& children = node->children(); - for (SceneGraphNode* child : children) - printTree(child, pre + " "); -} - SceneGraph::SceneGraph() : _focus("Root") , _position("Root") @@ -82,69 +82,94 @@ bool SceneGraph::initialize() using ghoul::opengl::ShaderObject; using ghoul::opengl::ProgramObject; - ProgramObject* po = nullptr; - if (OsEng.ref().configurationManager().hasKey("pscShader") - && OsEng.ref().configurationManager().getValue("pscShader", po)) { - LWARNING("pscShader already in ConfigurationManager, deleting."); - delete po; - po = nullptr; + // pscstandard + { + std::string programObjectName = "pscstandard"; + ProgramObject* po = new ProgramObject(programObjectName); + ShaderObject* vs = new ShaderObject( ShaderObject::ShaderType::ShaderTypeVertex, + absPath("${SHADERS}/pscstandard_vs.glsl"), + programObjectName + "Vertex"); + ShaderObject* fs = new ShaderObject( ShaderObject::ShaderType::ShaderTypeFragment, + absPath("${SHADERS}/pscstandard_fs.glsl"), + programObjectName + "Fragment"); + po->attachObject(vs); + po->attachObject(fs); + if ( ! po->compileShaderObjects()) return false; + if ( ! po->linkProgramObject()) return false; + OsEng.ref().configurationManager().setValue("pscShader", po); } - ShaderObject* powerscale_vs - = new ShaderObject(ShaderObject::ShaderType::ShaderTypeVertex, - absPath("${SHADERS}/pscstandard_vs.glsl"), "PS Vertex"); - ShaderObject* powerscale_fs - = new ShaderObject(ShaderObject::ShaderType::ShaderTypeFragment, - absPath("${SHADERS}/pscstandard_fs.glsl"), "PS Fragment"); + // pscVolume + { + std::string programObjectName = "pscVolume"; + ProgramObject* po = new ProgramObject(programObjectName); + ShaderObject* vs = new ShaderObject( ShaderObject::ShaderType::ShaderTypeVertex, + absPath("${SHADERS}/pscvolume_vs.glsl"), + programObjectName + "Vertex"); + ShaderObject* fs = new ShaderObject( ShaderObject::ShaderType::ShaderTypeFragment, + absPath("${SHADERS}/pscvolume_fs.glsl"), + programObjectName + "Fragment"); + po->attachObject(vs); + po->attachObject(fs); + if ( ! po->compileShaderObjects()) return false; + if ( ! po->linkProgramObject()) return false; + OsEng.ref().configurationManager().setValue("pscVolume", po); + } - po = new ProgramObject; - po->attachObject(powerscale_vs); - po->attachObject(powerscale_fs); + // RaycastProgram + { + std::string programObjectName = "RaycastProgram"; + ProgramObject* po = new ProgramObject(programObjectName); + ShaderObject* vs = new ShaderObject( ShaderObject::ShaderType::ShaderTypeVertex, + absPath("${SHADERS}/exitpoints.vert"), + programObjectName + "Vertex"); + ShaderObject* fs = new ShaderObject( ShaderObject::ShaderType::ShaderTypeFragment, + absPath("${SHADERS}/exitpoints.frag"), + programObjectName + "Fragment"); + po->attachObject(vs); + po->attachObject(fs); + if ( ! po->compileShaderObjects()) return false; + if ( ! po->linkProgramObject()) return false; + OsEng.ref().configurationManager().setValue("RaycastProgram", po); + } - if (!po->compileShaderObjects()) - return false; - if (!po->linkProgramObject()) - return false; + // TwoPassProgram + { + std::string programObjectName = "TwoPassProgram"; + ProgramObject* po = new ProgramObject(programObjectName); + ShaderObject* vs = new ShaderObject( ShaderObject::ShaderType::ShaderTypeVertex, + absPath("${SHADERS}/twopassraycaster.vert"), + programObjectName + "Vertex"); + ShaderObject* fs = new ShaderObject( ShaderObject::ShaderType::ShaderTypeFragment, + absPath("${SHADERS}/twopassraycaster.frag"), + programObjectName + "Fragment"); + po->attachObject(vs); + po->attachObject(fs); + if ( ! po->compileShaderObjects()) return false; + if ( ! po->linkProgramObject()) return false; + po->setUniform("texBack", 0); + po->setUniform("texFront", 1); + po->setUniform("texVolume", 2); + OsEng.ref().configurationManager().setValue("TwoPassProgram", po); + } - OsEng.ref().configurationManager().setValue("pscShader", po); - - ProgramObject* _fboProgram = new ProgramObject("RaycastProgram"); - ShaderObject* vertexShader = new ShaderObject(ShaderObject::ShaderTypeVertex, - absPath("${SHADERS}/exitpoints.vert")); - ShaderObject* fragmentShader = new ShaderObject( - ShaderObject::ShaderTypeFragment, absPath("${SHADERS}/exitpoints.frag")); - _fboProgram->attachObject(vertexShader); - _fboProgram->attachObject(fragmentShader); - _fboProgram->compileShaderObjects(); - _fboProgram->linkProgramObject(); - - ProgramObject* _twopassProgram = new ProgramObject("TwoPassProgram"); - vertexShader = new ShaderObject(ShaderObject::ShaderTypeVertex, - absPath("${SHADERS}/twopassraycaster.vert")); - fragmentShader = new ShaderObject(ShaderObject::ShaderTypeFragment, - absPath("${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); - - ProgramObject* quad = new ProgramObject("Quad"); - ShaderObject* quadv = new ShaderObject(ShaderObject::ShaderTypeVertex, - absPath("${SHADERS}/quadVert.glsl")); - ShaderObject* quadf = new ShaderObject(ShaderObject::ShaderTypeFragment, - absPath("${SHADERS}/quadFrag.glsl")); - quad->attachObject(quadv); - quad->attachObject(quadf); - quad->compileShaderObjects(); - quad->linkProgramObject(); - quad->setUniform("quadTex", 0); - - OsEng.ref().configurationManager().setValue("RaycastProgram", _fboProgram); - OsEng.ref().configurationManager().setValue("TwoPassProgram", _twopassProgram); - OsEng.ref().configurationManager().setValue("Quad", quad); + // Quad + { + std::string programObjectName = "Quad"; + ProgramObject* po = new ProgramObject(programObjectName); + ShaderObject* vs = new ShaderObject( ShaderObject::ShaderType::ShaderTypeVertex, + absPath("${SHADERS}/quadVert.glsl"), + programObjectName + "Vertex"); + ShaderObject* fs = new ShaderObject( ShaderObject::ShaderType::ShaderTypeFragment, + absPath("${SHADERS}/quadFrag.glsl"), + programObjectName + "Fragment"); + po->attachObject(vs); + po->attachObject(fs); + if ( ! po->compileShaderObjects()) return false; + if ( ! po->linkProgramObject()) return false; + po->setUniform("quadTex", 0); + OsEng.ref().configurationManager().setValue("Quad", po); + } // Initialize all nodes for (auto node : _nodes) { From b18e8ab713aeb0da46f3c9b0f4fa633097392fa1 Mon Sep 17 00:00:00 2001 From: Jonas Strandstedt Date: Mon, 2 Jun 2014 15:15:36 -0400 Subject: [PATCH 10/49] Pointing to new ghoul changes --- ext/ghoul | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/ghoul b/ext/ghoul index 6448e0542c..1f478d7956 160000 --- a/ext/ghoul +++ b/ext/ghoul @@ -1 +1 @@ -Subproject commit 6448e0542ce84a8dcadd025b16c8a28f30b2cc90 +Subproject commit 1f478d79565c3c7b4343ab5ca1cd3cb30c491173 From 0a539caf41b67b6dba5a583217ef6c9995810adc Mon Sep 17 00:00:00 2001 From: Jonas Strandstedt Date: Mon, 2 Jun 2014 15:52:15 -0400 Subject: [PATCH 11/49] Cleanup and removal of pscVolume shaders --- shaders/ABuffer/abufferAddToBuffer.hglsl | 3 + shaders/exitpoints.frag | 13 ++- shaders/exitpoints.vert | 2 +- shaders/pscstandard_fs.glsl | 4 - shaders/pscvolume_fs.glsl | 139 ----------------------- shaders/pscvolume_vs.glsl | 115 ------------------- src/scenegraph/scenegraph.cpp | 17 --- 7 files changed, 16 insertions(+), 277 deletions(-) delete mode 100644 shaders/pscvolume_fs.glsl delete mode 100644 shaders/pscvolume_vs.glsl diff --git a/shaders/ABuffer/abufferAddToBuffer.hglsl b/shaders/ABuffer/abufferAddToBuffer.hglsl index c2421ba3f3..2127bf8715 100644 --- a/shaders/ABuffer/abufferAddToBuffer.hglsl +++ b/shaders/ABuffer/abufferAddToBuffer.hglsl @@ -1,4 +1,7 @@ +layout (binding = 0, r32ui) uniform uimage2D anchorPointerTexture; +layout (binding = 1, rgba32ui) uniform uimageBuffer fragmentTexture; +layout (binding = 0, offset = 0) uniform atomic_uint atomicCounterBuffer; void addToBuffer(ABufferStruct_t frag) { diff --git a/shaders/exitpoints.frag b/shaders/exitpoints.frag index 1ea86ecb38..47280749fa 100644 --- a/shaders/exitpoints.frag +++ b/shaders/exitpoints.frag @@ -1,8 +1,19 @@ -#version 400 core +#version 430 core in vec3 vPosition; out vec4 fragColor; + +#include "ABuffer/abufferStruct.hglsl" +#include "ABuffer/abufferAddToBuffer.hglsl" void main() { fragColor = vec4(vPosition+0.5, 1.0); + + ABufferStruct_t frag; + _col_(frag, fragColor); + _z_(frag, gl_FragDepth); + _type_(frag, 0); + addToBuffer(frag); + + discard; } \ No newline at end of file diff --git a/shaders/exitpoints.vert b/shaders/exitpoints.vert index 0668ef5618..cc0dd3624d 100644 --- a/shaders/exitpoints.vert +++ b/shaders/exitpoints.vert @@ -1,4 +1,4 @@ -#version 400 core +#version 430 core layout(location = 2) in vec3 vertPosition; uniform mat4 modelViewProjection; diff --git a/shaders/pscstandard_fs.glsl b/shaders/pscstandard_fs.glsl index c35b40e5f4..1d68f801fc 100644 --- a/shaders/pscstandard_fs.glsl +++ b/shaders/pscstandard_fs.glsl @@ -9,10 +9,6 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI */ #version 430 -layout (binding = 0, r32ui) uniform uimage2D anchorPointerTexture; -layout (binding = 1, rgba32ui) uniform uimageBuffer fragmentTexture; -layout (binding = 0, offset = 0) uniform atomic_uint atomicCounterBuffer; - uniform mat4 ViewProjection; uniform mat4 ModelTransform; uniform vec4 campos; diff --git a/shaders/pscvolume_fs.glsl b/shaders/pscvolume_fs.glsl deleted file mode 100644 index c35b40e5f4..0000000000 --- a/shaders/pscvolume_fs.glsl +++ /dev/null @@ -1,139 +0,0 @@ -/** -Copyright (C) 2012-2014 Jonas Strandstedt - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ -#version 430 - -layout (binding = 0, r32ui) uniform uimage2D anchorPointerTexture; -layout (binding = 1, rgba32ui) uniform uimageBuffer fragmentTexture; -layout (binding = 0, offset = 0) uniform atomic_uint atomicCounterBuffer; - -uniform mat4 ViewProjection; -uniform mat4 ModelTransform; -uniform vec4 campos; -uniform vec4 objpos; -uniform float time; -uniform sampler2D texture1; - -vec3 light_position = vec3(40.0, 20.0, 100.0); - -in vec2 vs_st; -//in vec3 vs_stp; -in vec4 vs_normal; -in vec4 vs_position; - -out vec4 diffuse; - -const float k = 10.0; - -#include "ABuffer/abufferStruct.hglsl" -#include "ABuffer/abufferAddToBuffer.hglsl" - - -vec4 psc_normlization(vec4 invec) { - - float xymax = max(invec.x,invec.y); - - if(invec.z > 0.0f || invec.z < 0.0f) { - return invec / abs(invec.z); - } else if (xymax != 0.0f) { - return invec / xymax; - } else { - return invec / -.0; - } -} - -void main() -{ - - // Observable universe is 10^27m, setting the far value to extremely high, aka 30!! ERMAHGERD! - float s_far = 27.0; //= gl_DepthRange.far; // 40 - float s_farcutoff = 12.0; - float s_nearcutoff = 7.0; - float s_near = 0.0f;// gl_DepthRange.near; // 0.1 - float depth; - - // the value can be normalized to 1 - - vec4 p = vs_position; - if(vs_position.w <= 0.5) { - //depth = abs(vs_position.z * pow(10, vs_position.w)) / pow(k,s_far); - depth = (vs_position.w+log(abs(vs_position.z)))/pow(k, vs_position.w); - } else if(vs_position.w < 3.0) { - depth = vs_position.w+log(abs(vs_position.z))/pow(k, vs_position.w); - } else { - depth = vs_position.w+log(abs(vs_position.z)); - } - - - // DEBUG - float depth_orig = depth; - float x = 0.0f; - float cutoffs = 0.0; - float orig_z = vs_position.z; - - // calculate a normalized depth [0.0 1.0] - if((depth > s_near && depth <= s_nearcutoff) || (depth > s_farcutoff && depth < s_far)) { - - // completely linear interpolation [s_near .. depth .. s_far] - depth = (depth - s_near) / (s_far - s_near); - - } else if(depth > s_nearcutoff && depth < s_farcutoff) { - - // DEBUG - cutoffs = 1.0; - - // interpolate [10^s_nearcutoff .. 10^depth .. 10^s_farcutoff] - // calculate between 0..1 where the depth is - x = (pow(10,depth) - pow(10, s_nearcutoff)) / (pow(10,s_farcutoff) - pow(10, s_nearcutoff)); - - // remap the depth to the 0..1 depth buffer - depth = s_nearcutoff + x * (s_farcutoff - s_nearcutoff); - depth = (depth - s_near) / (s_far - s_near); - - } else { - // where am I? - // do I need to be discarded? - // discard; - } - - - - - // set the depth - gl_FragDepth = depth; - //gl_FragDepth = 0.5; - - // color - diffuse = texture(texture1, vs_st); - //diffuse = vec4(vs_position.z,0.0, 0.0, 1.0); - // diffuse = vec4(vs_position.xyz * pow(10, vs_position.w), 1.0); - //diffuse = vec4(vs_st, 0.0, 1.0); - //diffuse = vec4(1.0,1.0, 0.0, 1.0); - //diffuse = vec4(depth*5,0.0, 0.0, 1.0); - //diffuse = vec4(vs_position.w,0.0, 0.0, 1.0); - //diffuse = vec4(1.0,0.0,0.0,1.0); - - ABufferStruct_t frag; - _col_(frag, diffuse); - _z_(frag, depth); - _type_(frag, 0); - addToBuffer(frag); - - /* - uint index = atomicCounterIncrement(atomicCounterBuffer); - uint old_head = imageAtomicExchange(anchorPointerTexture, ivec2(gl_FragCoord.xy), index); - uvec4 item; - item.x = old_head; - item.y = packUnorm4x8(diffuse); - item.z = floatBitsToUint(gl_FragCoord.z / gl_FragCoord.w); - item.w = 0; - imageStore(fragmentTexture, int(index), item); -*/ - discard; -} \ No newline at end of file diff --git a/shaders/pscvolume_vs.glsl b/shaders/pscvolume_vs.glsl deleted file mode 100644 index 5a612667a2..0000000000 --- a/shaders/pscvolume_vs.glsl +++ /dev/null @@ -1,115 +0,0 @@ -/** -Copyright (C) 2012-2014 Jonas Strandstedt - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the "Software"), -to deal in the Software without restriction, including without limitation -the rights to use, copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ -#version 430 - -uniform mat4 ViewProjection; -uniform mat4 ModelTransform; -uniform vec4 campos; -uniform mat4 camrot; -uniform vec2 scaling; -uniform vec4 objpos; -uniform float time; -uniform sampler2D texture1; -uniform sampler2D texture2; -uniform sampler2D texture3; -uniform float TessLevel; -uniform bool Wireframe; -uniform bool Lightsource; -uniform bool UseTexture; - -layout(location = 0) in vec4 in_position; -//in vec3 in_position; -layout(location = 1) in vec2 in_st; -layout(location = 2) in vec3 in_normal; - -out vec2 vs_st; -out vec3 vs_stp; -out vec4 vs_normal; -out vec4 vs_position; - -const float k = 10.0; -const float dgr_to_rad = 0.0174532925; - -vec4 psc_addition(vec4 v1, vec4 v2) { - float ds = v2.w - v1.w; - if(ds >= 0) { - float p = pow(k,-ds); - return vec4(v1.x*p + v2.x, v1.y*p + v2.y, v1.z*p + v2.z, v2.w); - } else { - float p = pow(k,ds); - return vec4(v1.x + v2.x*p, v1.y + v2.y*p, v1.z + v2.z*p, v1.w); - } -} - -vec4 psc_to_meter(vec4 v1, vec2 v2) { - float factor = v2.x * pow(k,v2.y + v1.w); - return vec4(v1.xyz * factor, 1.0); -} - -vec4 psc_scaling(vec4 v1, vec2 v2) { - float ds = v2.y - v1.w; - if(ds >= 0) { - return vec4(v1.xyz * v2.x * pow(k,v1.w), v2.y); - } else { - return vec4(v1.xyz * v2.x * pow(k,v2.y), v1.w); - } -} - -void main() -{ - // set variables - vs_st = in_st; - //vs_stp = in_position.xyz; - vs_normal = normalize(ModelTransform * vec4(in_normal,0)); - - // fetch model and view translation - //vec4 vertex_translate = ModelTransform[3]; - - // rotate and scale vertex with model transform and add the translation - vec3 local_vertex_pos = mat3(ModelTransform) * in_position.xyz; - //vec4 lvp = ModelTransform * in_position; - - // PSC addition; local vertex position and the object power scaled world position - vs_position = psc_addition(vec4(local_vertex_pos,in_position.w),objpos); - //vs_position = psc_addition(lvp,objpos); - - // PSC addition; rotated and viewscaled vertex and the cmaeras negative position - vs_position = psc_addition(vs_position,vec4(-campos.xyz,campos.w)); - - // rotate the camera - local_vertex_pos = mat3(camrot) * vs_position.xyz; - vs_position = vec4(local_vertex_pos, vs_position.w); - //vs_position = camrot* vs_position; - - // rescales the scene to fit inside the view frustum - // is set from the main program, but these are decent values - // scaling = vec2(1.0, -8.0); - - // project using the rescaled coordinates, - //vec4 vs_position_rescaled = psc_scaling(vs_position, scaling); - vec4 vs_position_rescaled = psc_to_meter(vs_position, scaling); - //vs_position = vs_position_rescaled; - - - // project the position to view space - gl_Position = ViewProjection * vs_position_rescaled; -} \ No newline at end of file diff --git a/src/scenegraph/scenegraph.cpp b/src/scenegraph/scenegraph.cpp index e0ab7ba128..75434d2a54 100644 --- a/src/scenegraph/scenegraph.cpp +++ b/src/scenegraph/scenegraph.cpp @@ -99,23 +99,6 @@ bool SceneGraph::initialize() OsEng.ref().configurationManager().setValue("pscShader", po); } - // pscVolume - { - std::string programObjectName = "pscVolume"; - ProgramObject* po = new ProgramObject(programObjectName); - ShaderObject* vs = new ShaderObject( ShaderObject::ShaderType::ShaderTypeVertex, - absPath("${SHADERS}/pscvolume_vs.glsl"), - programObjectName + "Vertex"); - ShaderObject* fs = new ShaderObject( ShaderObject::ShaderType::ShaderTypeFragment, - absPath("${SHADERS}/pscvolume_fs.glsl"), - programObjectName + "Fragment"); - po->attachObject(vs); - po->attachObject(fs); - if ( ! po->compileShaderObjects()) return false; - if ( ! po->linkProgramObject()) return false; - OsEng.ref().configurationManager().setValue("pscVolume", po); - } - // RaycastProgram { std::string programObjectName = "RaycastProgram"; From 08a8e2f3bb5568c647626b087415485930ecd1a7 Mon Sep 17 00:00:00 2001 From: Jonas Strandstedt Date: Tue, 3 Jun 2014 16:50:47 -0400 Subject: [PATCH 12/49] Intermediate ABuffer commit --- .../openspace/rendering/renderablevolumegl.h | 25 +--- include/openspace/scenegraph/scenegraphnode.h | 1 + shaders/ABuffer/abufferResolveFragment.glsl | 58 ++++++-- shaders/ABuffer/abufferSort.hglsl | 9 +- shaders/ABuffer/abufferStruct.hglsl | 39 ++++- shaders/exitpoints.frag | 6 +- shaders/pscstandard_fs.glsl | 2 +- shaders/pscstandard_vs.glsl | 2 +- src/rendering/renderablevolumegl.cpp | 133 ++++++------------ src/scenegraph/scenegraphnode.cpp | 20 ++- 10 files changed, 155 insertions(+), 140 deletions(-) diff --git a/include/openspace/rendering/renderablevolumegl.h b/include/openspace/rendering/renderablevolumegl.h index 6cca3f458f..b6b261ebe7 100644 --- a/include/openspace/rendering/renderablevolumegl.h +++ b/include/openspace/rendering/renderablevolumegl.h @@ -27,6 +27,7 @@ // open space includes #include +#include // ghoul includes #include @@ -35,24 +36,16 @@ #include #include -#define SGCT_WINDOWS_INCLUDE -#include - #ifdef __APPLE__ #include #else #include #endif -namespace sgct_utils { - class SGCTBox; -} - namespace openspace { class RenderableVolumeGL: public RenderableVolume { public: - // constructors & destructor RenderableVolumeGL(const ghoul::Dictionary& dictionary); ~RenderableVolumeGL(); @@ -64,18 +57,15 @@ public: virtual void update(); private: - - + ghoul::Dictionary _hintsDictionary; std::string _filename; - ghoul::RawVolumeReader::ReadHints _hints; float _stepSize; - ghoul::opengl::FramebufferObject* _fbo; - ghoul::opengl::Texture* _backTexture; - ghoul::opengl::Texture* _frontTexture; ghoul::opengl::Texture* _volume; - ghoul::opengl::ProgramObject *_fboProgram, *_twopassProgram; - sgct_utils::SGCTBox* _boundingBox; + ghoul::opengl::ProgramObject* _twopassProgram; GLuint _screenQuad; + + VolumeRaycasterBox* _colorBoxRenderer; + glm::vec3 _boxScaling; std::mutex* _shaderMutex; @@ -84,9 +74,8 @@ private: bool _programUpdateOnSave; void safeShaderCompilation(); - }; } // namespace openspace -#endif \ No newline at end of file +#endif diff --git a/include/openspace/scenegraph/scenegraphnode.h b/include/openspace/scenegraph/scenegraphnode.h index 2269d7d7cf..9a8b847d97 100644 --- a/include/openspace/scenegraph/scenegraphnode.h +++ b/include/openspace/scenegraph/scenegraphnode.h @@ -70,6 +70,7 @@ public: // bounding sphere PowerScaledScalar calculateBoundingSphere(); + PowerScaledScalar boundingSphere() const; SceneGraphNode* get(const std::string& name); diff --git a/shaders/ABuffer/abufferResolveFragment.glsl b/shaders/ABuffer/abufferResolveFragment.glsl index a849b99b18..3a8619d474 100644 --- a/shaders/ABuffer/abufferResolveFragment.glsl +++ b/shaders/ABuffer/abufferResolveFragment.glsl @@ -1,37 +1,64 @@ #version 430 -// texture bindings -layout (binding = 0, r32ui) uniform uimage2D anchorPointerTexture; -layout (binding = 1, rgba32ui) uniform uimageBuffer fragmentTexture; - -// atomic buffer bindings -layout (binding = 0, offset = 0) uniform atomic_uint atomicCounterBuffer; - // uniforms -uniform int SCREEN_WIDTH; -uniform int SCREEN_HEIGHT; in vec2 texCoord; out vec4 color; -#include "abufferStruct.hglsl" +// settings +#define ALPHA_LIMIT 0.51 #define MAX_FRAGMENTS 16 +#define MAX_VOLUMES 4 + +#include "abufferStruct.hglsl" ABufferStruct_t fragments[MAX_FRAGMENTS]; +vec3 volume_direction[MAX_VOLUMES]; +vec3 volume_position[MAX_VOLUMES]; + #include "abufferSort.hglsl" -vec4 blend(vec4 current_color, vec4 new_color) { - return mix(current_color, new_color, new_color.a); +vec4 blend(vec4 src, vec4 dst) { + vec4 o; + o.a = src.a + dst.a * (1.0f - src.a); + o.rgb = (src.rgb*src.a + dst.rgb*dst.a* (1.0f - src.a)); + return o; + //return mix(src, dst, dst.a*(1.0f - src.a)); +} + +vec3 direction(vec4 v1, vec4 v2) { + const float k = 10.0; + float ds = v2.w - v1.w; + if(ds >= 0) { + float p = pow(k,-ds); + return vec4(v1.x*p - v2.x, v1.y*p - v2.y, v1.z*p - v2.z, v2.w).xyz; + } else { + float p = pow(k,ds); + return vec4(v1.x - v2.x*p, v1.y - v2.y*p, v1.z - v2.z*p, v1.w).xyz; + } } vec4 calculate_final_color(uint frag_count) { + int currentVolumeBitmask = 0; vec4 final_color = vec4(0); - for(uint i = 0; i < frag_count; i++) { + for(uint i = 0; i < frag_count && final_color.a < ALPHA_LIMIT; i++) { ABufferStruct_t item = fragments[i]; vec4 frag_color = _col_(item); - final_color = blend(final_color, frag_color); + vec4 position = _pos_(item); + uint type = _type_(item); + + + if(currentVolumeBitmask != 0) { + currentVolumeBitmask = currentVolumeBitmask ^ (1 << type); + } + /* + if(_type_(item) == 1) +*/ + final_color = blend(final_color, frag_color); + //final_color = blend(frag_color, final_color); + } return final_color; @@ -43,6 +70,9 @@ void main() { color = vec4(texCoord,0.0,1.0); int frag_count = build_local_fragments_list(); sort_fragments_list(frag_count); + + + color = calculate_final_color(frag_count); //color = vec4(float(frag_count) / 5.0, 0.0, 0.0, 1.0); diff --git a/shaders/ABuffer/abufferSort.hglsl b/shaders/ABuffer/abufferSort.hglsl index df61c45353..4cdc8bf481 100644 --- a/shaders/ABuffer/abufferSort.hglsl +++ b/shaders/ABuffer/abufferSort.hglsl @@ -1,4 +1,11 @@ +// texture bindings +layout (binding = 0, r32ui) uniform uimage2D anchorPointerTexture; +layout (binding = 1, rgba32ui) uniform uimageBuffer fragmentTexture; + +// atomic buffer bindings +layout (binding = 0, offset = 0) uniform atomic_uint atomicCounterBuffer; + int build_local_fragments_list() { uint current; int frag_count = 0; @@ -24,7 +31,7 @@ void sort_fragments_list(uint frag_count) { // INSERTION SORT for(i = 1; i < frag_count; ++i) { tmp = fragments[i]; - for(j = i; j > 0 && _z_(tmp) > _z_(fragments[j-1]); --j) { + for(j = i; j > 0 && _z_(tmp) < _z_(fragments[j-1]); --j) { fragments[j] = fragments[j-1]; } fragments[j] = tmp; diff --git a/shaders/ABuffer/abufferStruct.hglsl b/shaders/ABuffer/abufferStruct.hglsl index 83f212b7fe..f220fbb02f 100644 --- a/shaders/ABuffer/abufferStruct.hglsl +++ b/shaders/ABuffer/abufferStruct.hglsl @@ -9,7 +9,7 @@ struct ABufferStruct_t { uint z; // the depth value uint id; // bits 0-28 next, bits 29-32 type uint color; // packed rgba - uint type; // packed position + uint position; // packed position }; //======================================================= @@ -27,6 +27,22 @@ const uint mask_id = mask_16; const uint shift_id = 0; const uint mask_type = mask_24 - mask_16; const uint shift_type = 16; +/* +const uint mask_zid_z = mask_24; +const uint shift_zid_z = 0; +const uint mask_zid_id = mask_29 - mask_24; +const uint shift_zid_id = 24; +const uint mask_zid_type = mask_31 - mask_29; +const uint shift_zid_type = 29; +const uint mask_zid_xxx = mask_32 - mask_31; +const uint shift_zid_xxx = 31; +*/ + +const uint mask_id_next = mask_29; +const uint shift_id_next = 0; +const uint mask_id_type = mask_32 - mask_29; +const uint shift_id_type = 29; + void bitinsert_u(inout uint pack, uint val, uint mask, uint shift) { pack &= ~mask; pack |= (val << shift) & mask; @@ -53,10 +69,19 @@ void _z_(inout ABufferStruct_t frag, float z) { } uint _next_(ABufferStruct_t frag) { - return frag.id; + return bitextract_u(frag.id, mask_id_next, shift_id_next); + //return frag.id; } void _next_(inout ABufferStruct_t frag, uint id) { - frag.id = id; + bitinsert_u(frag.id, id, mask_id_next, shift_id_next); + //frag.id = id; +} + +vec4 _pos_(ABufferStruct_t frag) { + return unpackUnorm4x8(frag.position); +} +void _pos_(inout ABufferStruct_t frag, vec4 position) { + frag.position = packUnorm4x8(position); } vec4 _col_(ABufferStruct_t frag) { @@ -67,16 +92,18 @@ void _col_(inout ABufferStruct_t frag, vec4 color) { } uint _type_(ABufferStruct_t frag) { - return frag.type; + return bitextract_u(frag.id, mask_id_type, shift_id_type); + //return frag.type; } void _type_(inout ABufferStruct_t frag, uint type) { - frag.type = type;; + bitinsert_u(frag.id, type, mask_id_type, shift_id_type); + //frag.type = type; } ABufferStruct_t _ABufferStruct_t_(uvec4 frag) { return ABufferStruct_t(frag.x, frag.y, frag.z, frag.w); }; uvec4 _uvec4_(ABufferStruct_t frag) { - return uvec4(frag.z, frag.id, frag.color, frag.type); + return uvec4(frag.z, frag.id, frag.color, frag.position); }; #endif \ No newline at end of file diff --git a/shaders/exitpoints.frag b/shaders/exitpoints.frag index 47280749fa..72041462b2 100644 --- a/shaders/exitpoints.frag +++ b/shaders/exitpoints.frag @@ -7,13 +7,13 @@ out vec4 fragColor; #include "ABuffer/abufferAddToBuffer.hglsl" void main() { - fragColor = vec4(vPosition+0.5, 1.0); + fragColor = vec4(vPosition+0.5, 0.3); ABufferStruct_t frag; _col_(frag, fragColor); _z_(frag, gl_FragDepth); - _type_(frag, 0); + _type_(frag, 1); addToBuffer(frag); - discard; + //discard; } \ No newline at end of file diff --git a/shaders/pscstandard_fs.glsl b/shaders/pscstandard_fs.glsl index 1d68f801fc..b5304ad234 100644 --- a/shaders/pscstandard_fs.glsl +++ b/shaders/pscstandard_fs.glsl @@ -117,7 +117,7 @@ void main() ABufferStruct_t frag; _col_(frag, diffuse); - _z_(frag, depth); + _z_(frag, gl_FragDepth); _type_(frag, 0); addToBuffer(frag); diff --git a/shaders/pscstandard_vs.glsl b/shaders/pscstandard_vs.glsl index 5a612667a2..be3ead04f7 100644 --- a/shaders/pscstandard_vs.glsl +++ b/shaders/pscstandard_vs.glsl @@ -107,7 +107,7 @@ void main() // project using the rescaled coordinates, //vec4 vs_position_rescaled = psc_scaling(vs_position, scaling); vec4 vs_position_rescaled = psc_to_meter(vs_position, scaling); - //vs_position = vs_position_rescaled; + vs_position = vs_position_rescaled; // project the position to view space diff --git a/src/rendering/renderablevolumegl.cpp b/src/rendering/renderablevolumegl.cpp index 0d1ae60475..9e3bdcbf43 100644 --- a/src/rendering/renderablevolumegl.cpp +++ b/src/rendering/renderablevolumegl.cpp @@ -24,15 +24,13 @@ // open space includes #include - #include +#include #include #include #include -#include - #include namespace { @@ -42,8 +40,7 @@ namespace { namespace openspace { RenderableVolumeGL::RenderableVolumeGL(const ghoul::Dictionary& dictionary): - RenderableVolume(dictionary), - _backTexture(nullptr), _frontTexture(nullptr), _screenQuad(0), + RenderableVolume(dictionary), _screenQuad(0), _boxScaling(1.0, 1.0, 1.0), _programUpdateOnSave(false) { _shaderMutex = new std::mutex; @@ -54,13 +51,11 @@ RenderableVolumeGL::RenderableVolumeGL(const ghoul::Dictionary& dictionary): _filename = findPath(_filename); } } - + LDEBUG("filename: " << _filename); - ghoul::Dictionary hintsDictionary; if(dictionary.hasKey("Hints")) - dictionary.getValue("Hints", hintsDictionary); - _hints = readHints(hintsDictionary); + dictionary.getValue("Hints", _hintsDictionary); std::string vshaderpath = ""; std::string fshaderpath = ""; @@ -87,35 +82,43 @@ RenderableVolumeGL::RenderableVolumeGL(const ghoul::Dictionary& dictionary): _twopassProgram->attachObject(vertexShader); _twopassProgram->attachObject(fragmentShader); } - - } if(dictionary.hasKey("UpdateOnSave")) { dictionary.getValue("UpdateOnSave", _programUpdateOnSave); } + double tempValue; + if(dictionary.hasKey("BoxScaling.1") && dictionary.getValue("BoxScaling.1", tempValue)) { + if(tempValue > 0.0) + _boxScaling[0] = tempValue; + } + if(dictionary.hasKey("BoxScaling.2") && dictionary.getValue("BoxScaling.2", tempValue)) { + if(tempValue > 0.0) + _boxScaling[1] = tempValue; + } + if(dictionary.hasKey("BoxScaling.3") && dictionary.getValue("BoxScaling.3", tempValue)) { + if(tempValue > 0.0) + _boxScaling[2] = tempValue; + } + + _colorBoxRenderer = new VolumeRaycasterBox(); + setBoundingSphere(PowerScaledScalar::CreatePSS(glm::length(_boxScaling))); } RenderableVolumeGL::~RenderableVolumeGL() { deinitialize(); - if(_fbo) - delete _fbo; - if(_backTexture) - delete _backTexture; - if(_frontTexture) - delete _frontTexture; if(_volume) delete _volume; - if(_boundingBox) - delete _boundingBox; + if(_colorBoxRenderer) + delete _colorBoxRenderer; } bool RenderableVolumeGL::initialize() { assert(_filename != ""); // ------ VOLUME READING ---------------- - ghoul::RawVolumeReader rawReader(_hints); - _volume = rawReader.read(_filename); + _volume = loadVolume(_filename, _hintsDictionary); + _volume->uploadTexture(); // ------ SETUP GEOMETRY ---------------- const GLfloat size = 1.0f; @@ -149,12 +152,9 @@ bool RenderableVolumeGL::initialize() { glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind buffer glBindVertexArray(0); //unbind array - _boundingBox = new sgct_utils::SGCTBox(1.0f, sgct_utils::SGCTBox::Regular); + _colorBoxRenderer->initialize(); // ------ SETUP SHADERS ----------------- - // TODO error control or better design pattern - OsEng.ref().configurationManager().getValue("RaycastProgram", _fboProgram); - auto privateCallback = [this](const ghoul::filesystem::File& file) { safeShaderCompilation(); }; @@ -168,76 +168,27 @@ bool RenderableVolumeGL::initialize() { _twopassProgram->setUniform("texBack", 0); _twopassProgram->setUniform("texFront", 1); _twopassProgram->setUniform("texVolume", 2); - //OsEng.ref().configurationManager().getValue("TwoPassProgram", _twopassProgram); - - // ------ SETUP FBO --------------------- - _fbo = new ghoul::opengl::FramebufferObject(); - _fbo->activate(); - - int x = sgct::Engine::instance()->getActiveXResolution(); - int y = sgct::Engine::instance()->getActiveYResolution(); - _backTexture = new ghoul::opengl::Texture(glm::size3_t(x,y,1)); - _frontTexture = new ghoul::opengl::Texture(glm::size3_t(x,y,1)); - _backTexture->uploadTexture(); - _frontTexture->uploadTexture(); - _fbo->attachTexture(_backTexture, GL_COLOR_ATTACHMENT0); - _fbo->attachTexture(_frontTexture, GL_COLOR_ATTACHMENT1); - - _fbo->deactivate(); - return true; } bool RenderableVolumeGL::deinitialize() { - - return true; } void RenderableVolumeGL::render(const Camera *camera, const psc &thisPosition) { - - float speed = 50.0f; - float time = sgct::Engine::getTime(); - glm::mat4 transform = camera->viewProjectionMatrix(); - - double factor = pow(10.0,thisPosition[3]); - transform = glm::translate(transform, glm::vec3(thisPosition[0]*factor, thisPosition[1]*factor, thisPosition[2]*factor)); - transform = glm::rotate(transform, time*speed, glm::vec3(0.0f, 1.0f, 0.0f)); - - _stepSize = 0.01f; - - // ------ DRAW TO FBO ------------------- - GLuint sgctFBO = ghoul::opengl::FramebufferObject::getActiveObject(); // Save SGCTs main FBO - _fbo->activate(); - _fboProgram->activate(); - _fboProgram->setUniform("modelViewProjection", transform); - - // 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); - _boundingBox->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); - _boundingBox->draw(); - glDisable(GL_CULL_FACE); - - _fboProgram->deactivate(); - _fbo->deactivate(); - - // ------ DRAW TO SCREEN ---------------- - glBindFramebuffer(GL_FRAMEBUFFER, sgctFBO); // Re-bind SGCTs main FBO - + + glm::mat4 transform = camera->viewProjectionMatrix(); + glm::mat4 camTransform = camera->viewRotationMatrix(); + psc relative = thisPosition-camera->position(); + + transform = transform*camTransform; + transform = glm::translate(transform, relative.vec3()); + transform = glm::scale(transform, _boxScaling); + + _colorBoxRenderer->render(transform); + /* // Draw screenquad glClearColor(0.2f, 0.2f, 0.2f, 0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -248,9 +199,9 @@ void RenderableVolumeGL::render(const Camera *camera, const psc &thisPosition) { // Set textures glActiveTexture(GL_TEXTURE0); - _backTexture->bind(); + _colorBoxRenderer->backFace()->bind(); glActiveTexture(GL_TEXTURE1); - _frontTexture->bind(); + _colorBoxRenderer->frontFace()->bind(); glActiveTexture(GL_TEXTURE2); _volume->bind(); @@ -260,7 +211,7 @@ void RenderableVolumeGL::render(const Camera *camera, const psc &thisPosition) { _twopassProgram->deactivate(); _shaderMutex->unlock(); - + */ } void RenderableVolumeGL::update() { @@ -268,6 +219,7 @@ void RenderableVolumeGL::update() { } void RenderableVolumeGL::safeShaderCompilation() { + /* _shaderMutex->lock(); _twopassProgram->rebuildFromFile(); _twopassProgram->compileShaderObjects(); @@ -276,8 +228,7 @@ void RenderableVolumeGL::safeShaderCompilation() { _twopassProgram->setUniform("texFront", 1); _twopassProgram->setUniform("texVolume", 2); _shaderMutex->unlock(); + */ } - - -} // namespace openspace \ No newline at end of file +} // namespace openspace diff --git a/src/scenegraph/scenegraphnode.cpp b/src/scenegraph/scenegraphnode.cpp index b0b3e752df..b0e5f25616 100644 --- a/src/scenegraph/scenegraphnode.cpp +++ b/src/scenegraph/scenegraphnode.cpp @@ -181,6 +181,7 @@ void SceneGraphNode::evaluate(const Camera* camera, const psc& parentPosition) if (!sphereInsideFrustum(thisPosition, _boundingSphere, camera)) { // the node is completely outside of the camera view, stop evaluating this // node + //LFATAL(_nodeName << " is outside of frustum"); return; } } @@ -198,7 +199,7 @@ void SceneGraphNode::evaluate(const Camera* camera, const psc& parentPosition) // evaluate all the children, tail-recursive function(?) for (auto& child : _children) { - child->evaluate(camera, psc()); + child->evaluate(camera, thisPosition); } } @@ -290,13 +291,22 @@ PowerScaledScalar SceneGraphNode::calculateBoundingSphere() } } _boundingSphere += maxChild; - } else { // leaf + } - // if has a renderable, use that boundingsphere - if (_renderable) - _boundingSphere += _renderable->getBoundingSphere(); + // if has a renderable, use that boundingsphere + if (_renderable ) { + PowerScaledScalar renderableBS = _renderable->getBoundingSphere(); + if(renderableBS > _boundingSphere) + _boundingSphere = renderableBS; } + + LWARNING(_nodeName << ": " << _boundingSphere); + + return _boundingSphere; +} + +PowerScaledScalar SceneGraphNode::boundingSphere() const{ return _boundingSphere; } From 3373ffd10d784b38a63c64e42a9b6687b1b8ec6f Mon Sep 17 00:00:00 2001 From: Hans-Christian Helltegen Date: Thu, 5 Jun 2014 10:12:42 -0400 Subject: [PATCH 13/49] Added renderablefieldlines class which renders fieldlines as geometry --- .../rendering/renderablefieldlines.h | 74 ++++++++ include/openspace/util/kameleonwrapper.h | 15 +- openspace-data | 2 +- src/rendering/renderablefieldlines.cpp | 170 ++++++++++++++++++ src/rendering/renderablevolume.cpp | 3 +- src/rendering/renderablevolumegl.cpp | 3 - src/util/factorymanager.cpp | 4 +- src/util/kameleonwrapper.cpp | 144 ++++++++------- 8 files changed, 344 insertions(+), 71 deletions(-) create mode 100644 include/openspace/rendering/renderablefieldlines.h create mode 100644 src/rendering/renderablefieldlines.cpp diff --git a/include/openspace/rendering/renderablefieldlines.h b/include/openspace/rendering/renderablefieldlines.h new file mode 100644 index 0000000000..a1546b52b6 --- /dev/null +++ b/include/openspace/rendering/renderablefieldlines.h @@ -0,0 +1,74 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef RENDERABLEFIELDLINES_H_ +#define RENDERABLEFIELDLINES_H_ + +// open space includes +#include + +// ghoul includes +#include +#include + +#ifdef __APPLE__ + #include +#else + #include +#endif + +namespace openspace { + +class RenderableFieldlines : public RenderableVolume { +public: + RenderableFieldlines(const ghoul::Dictionary& dictionary); + ~RenderableFieldlines(); + + bool initialize(); + bool deinitialize(); + + virtual void render(const Camera *camera, const psc& thisPosition); + virtual void update(); + +private: + ghoul::Dictionary _hintsDictionary; + std::string _filename; + + ghoul::opengl::ProgramObject* _fieldlinesProgram; + GLuint _VAO; + + std::mutex* _shaderMutex; + + ghoul::filesystem::File* _vertexSourceFile; + ghoul::filesystem::File* _fragmentSourceFile; + bool _programUpdateOnSave; + + void safeShaderCompilation(); + + std::vector _lineStart; + std::vector _lineCount; +}; + +} // namespace openspace +#endif // RENDERABLEFIELDLINES_H_ diff --git a/include/openspace/util/kameleonwrapper.h b/include/openspace/util/kameleonwrapper.h index 513448b03d..55bb1dbbca 100644 --- a/include/openspace/util/kameleonwrapper.h +++ b/include/openspace/util/kameleonwrapper.h @@ -25,7 +25,7 @@ #ifndef KAMELEONWRAPPER_H_ #define KAMELEONWRAPPER_H_ -#include +//#include #include namespace ccmc { @@ -54,13 +54,18 @@ public: float* getUniformSampledVectorValues(const std::string& xVar, const std::string& yVar, const std::string& zVar, glm::size3_t outDimensions); - float* getFieldLines(const std::string& xVar, const std::string& yVar, + float* getVolumeFieldLines(const std::string& xVar, const std::string& yVar, const std::string& zVar, glm::size3_t outDimensions, std::vector seedPoints); + std::vector > getFieldLines(const std::string& xVar, + const std::string& yVar, const std::string& zVar, + std::vector seedPoints); + private: - void traceCartesianFieldlines(const std::string& xVar, const std::string& yVar, - const std::string& zVar, glm::size3_t outDimensions, - std::vector seedPoints, TraceDirection direction, float* data); + std::vector traceCartesianFieldline(const std::string& xVar, + const std::string& yVar, const std::string& zVar, + glm::vec3 seedPoint, TraceDirection direction); + void getGridVariables(std::string& x, std::string& y, std::string& z); void progressBar(int current, int end); diff --git a/openspace-data b/openspace-data index 4af0a41ba1..8c9a21935d 160000 --- a/openspace-data +++ b/openspace-data @@ -1 +1 @@ -Subproject commit 4af0a41ba1d5dd1afade5d95495485b7de58c072 +Subproject commit 8c9a21935d4e1295857997664b0b7b297cce8dda diff --git a/src/rendering/renderablefieldlines.cpp b/src/rendering/renderablefieldlines.cpp new file mode 100644 index 0000000000..203b07f740 --- /dev/null +++ b/src/rendering/renderablefieldlines.cpp @@ -0,0 +1,170 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include +#include +#include +#include + +namespace { + std::string _loggerCat = "RenderableFieldlines"; +} + +namespace openspace { + +RenderableFieldlines::RenderableFieldlines(const ghoul::Dictionary& dictionary) : + RenderableVolume(dictionary), _VAO(0), _programUpdateOnSave(false) { + _shaderMutex = new std::mutex; + + _filename = ""; + if(dictionary.hasKey("Volume")) { + if(dictionary.getValue("Volume", _filename)) { + _filename = findPath(_filename); + } + } + + LDEBUG("filename: " << _filename); + + if(dictionary.hasKey("Hints")) + dictionary.getValue("Hints", _hintsDictionary); + + std::string vshaderpath = ""; + std::string fshaderpath = ""; + + if (dictionary.hasKey("Shaders")) { + ghoul::Dictionary shaderDictionary; + if(dictionary.getValue("Shaders", shaderDictionary)) { + if (shaderDictionary.hasKey("VertexShader")) { + shaderDictionary.getValue("VertexShader", vshaderpath); + } + if (shaderDictionary.hasKey("FragmentShader")) { + shaderDictionary.getValue("FragmentShader", fshaderpath); + } + + vshaderpath = findPath(vshaderpath); + fshaderpath = findPath(fshaderpath); + + _vertexSourceFile = new ghoul::filesystem::File(vshaderpath, false); + _fragmentSourceFile = new ghoul::filesystem::File(fshaderpath, false); + + _fieldlinesProgram = new ghoul::opengl::ProgramObject("FieldlinesProgram"); + ghoul::opengl::ShaderObject* vertexShader = new ghoul::opengl::ShaderObject(ghoul::opengl::ShaderObject::ShaderTypeVertex,vshaderpath); + ghoul::opengl::ShaderObject* fragmentShader = new ghoul::opengl::ShaderObject(ghoul::opengl::ShaderObject::ShaderTypeFragment,fshaderpath); + _fieldlinesProgram->attachObject(vertexShader); + _fieldlinesProgram->attachObject(fragmentShader); + } + } + + if(dictionary.hasKey("UpdateOnSave")) { + dictionary.getValue("UpdateOnSave", _programUpdateOnSave); + } + + setBoundingSphere(PowerScaledScalar::CreatePSS(5)); +} + +RenderableFieldlines::~RenderableFieldlines() { + +} + +bool RenderableFieldlines::initialize() { + assert(_filename != ""); + KameleonWrapper kameleon(_filename, KameleonWrapper::Model::BATSRUS); + std::vector seedPoints; + + for (int x = -3; x <= 3; x+=3) { + for (int y = -3; y <= 3; y+=3) { + for (int z = -3; z <= 3; z+=3) { + seedPoints.push_back(glm::vec3((float)x, (float)y, (float)z)); + } + } + } + + std::vector > fieldlines = kameleon.getFieldLines("bx", "by", "bz", seedPoints); + std::vector vertexData; + LDEBUG("Fieldlines.size() = " << fieldlines.size()); + + int prevEnd = 0; + + for (int i = 0; i < fieldlines.size(); i++) { + _lineStart.push_back(prevEnd); + _lineCount.push_back(fieldlines[i].size()); + prevEnd = prevEnd + fieldlines[i].size(); + + vertexData.insert( vertexData.end(), fieldlines[i].begin(), fieldlines[i].end()); + } + + GLuint vertexPositionBuffer; + glGenVertexArrays(1, &_VAO); // generate array + glBindVertexArray(_VAO); // bind array + glGenBuffers(1, &vertexPositionBuffer); // generate buffer + glBindBuffer(GL_ARRAY_BUFFER, vertexPositionBuffer); // bind buffer + glBufferData(GL_ARRAY_BUFFER, vertexData.size()*sizeof(glm::vec3), &vertexData.front(), GL_STATIC_DRAW); + + // Vertex positions + GLuint vertexLocation = 0; + glEnableVertexAttribArray(vertexLocation); + glVertexAttribPointer(vertexLocation, 3, GL_FLOAT, GL_FALSE, 3*sizeof(GLfloat), reinterpret_cast(0)); + + glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind buffer + glBindVertexArray(0); //unbind array + + _fieldlinesProgram->compileShaderObjects(); + _fieldlinesProgram->linkProgramObject(); + + return true; +} + +bool RenderableFieldlines::deinitialize() { + return true; +} + +void RenderableFieldlines::render(const Camera* camera, const psc& thisPosition) { + glm::mat4 transform = camera->viewProjectionMatrix(); + glm::mat4 camTransform = camera->viewRotationMatrix(); + psc relative = thisPosition-camera->position(); + + transform = transform*camTransform; + transform = glm::translate(transform, relative.vec3()); + transform = glm::scale(transform, glm::vec3(0.1)); + + _shaderMutex->lock(); + _fieldlinesProgram->activate(); + _fieldlinesProgram->setUniform("modelViewProjection", transform); + + + glBindVertexArray(_VAO); + glMultiDrawArrays(GL_LINE_STRIP, &_lineStart[0], &_lineCount[0], _lineStart.size()); + glBindVertexArray(0); + + _fieldlinesProgram->deactivate(); + _shaderMutex->unlock(); +} + +void RenderableFieldlines::update() { +} + +void RenderableFieldlines::safeShaderCompilation() { +} + +} // namespace openspace diff --git a/src/rendering/renderablevolume.cpp b/src/rendering/renderablevolume.cpp index ba4581cf23..a16305b408 100644 --- a/src/rendering/renderablevolume.cpp +++ b/src/rendering/renderablevolume.cpp @@ -163,12 +163,13 @@ ghoul::opengl::Texture* RenderableVolume::loadVolume(const std::string& filepath // Seed 'em all std::vector seedPoints; +// seedPoints.push_back(glm::vec3(5.0, 0.0, 0.0)); for (int z = -5; z <= 5; z+=5) { for (int y = -5; y <= 5; y+=5) seedPoints.push_back(glm::vec3(5.0, (float)y, (float)z)); } - float* fieldlinesData = kw.getFieldLines(xVariable, yVariable, zVariable, dimensions, seedPoints); + float* fieldlinesData = kw.getVolumeFieldLines(xVariable, yVariable, zVariable, dimensions, seedPoints); // float* rhoData = kw.getUniformSampledValues("rho", dimensions); // // // Combine fieldlines with rhoData, clamp to [0,1] diff --git a/src/rendering/renderablevolumegl.cpp b/src/rendering/renderablevolumegl.cpp index 52739394b1..1816da5be7 100644 --- a/src/rendering/renderablevolumegl.cpp +++ b/src/rendering/renderablevolumegl.cpp @@ -190,9 +190,6 @@ void RenderableVolumeGL::render(const Camera *camera, const psc &thisPosition) { _colorBoxRenderer->render(transform); // Draw screenquad - glClearColor(0.2f, 0.2f, 0.2f, 0); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - _shaderMutex->lock(); _twopassProgram->activate(); _twopassProgram->setUniform("stepSize", _stepSize); diff --git a/src/util/factorymanager.cpp b/src/util/factorymanager.cpp index 46561078dc..4a6e71ff59 100644 --- a/src/util/factorymanager.cpp +++ b/src/util/factorymanager.cpp @@ -27,6 +27,7 @@ #include // renderables +#include #include #include #include @@ -62,6 +63,7 @@ void FactoryManager::initialize() _manager->factory()->registerClass( "RenderableVolumeExpert"); _manager->factory()->registerClass("RenderableFlare"); + _manager->factory()->registerClass("RenderableFieldlines"); // Add Ephimerides _manager->addFactory(new ghoul::TemplateFactory); @@ -102,4 +104,4 @@ void FactoryManager::addFactory(ghoul::TemplateFactoryBase* factory) { } -} // namespace openspace \ No newline at end of file +} // namespace openspace diff --git a/src/util/kameleonwrapper.cpp b/src/util/kameleonwrapper.cpp index e360301a4b..b34bee3aeb 100644 --- a/src/util/kameleonwrapper.cpp +++ b/src/util/kameleonwrapper.cpp @@ -237,7 +237,7 @@ float* KameleonWrapper::getUniformSampledVectorValues(const std::string& xVar, c return data; } -float* KameleonWrapper::getFieldLines(const std::string& xVar, +float* KameleonWrapper::getVolumeFieldLines(const std::string& xVar, const std::string& yVar, const std::string& zVar, glm::size3_t outDimensions, std::vector seedPoints) { assert(_model && _interpolator); @@ -247,11 +247,28 @@ float* KameleonWrapper::getFieldLines(const std::string& xVar, int size = outDimensions.x*outDimensions.y*outDimensions.z; float* data = new float[size]; + std::vector line; if (_type == Model::BATSRUS) { - // Bi-directional tracing of fieldlines - traceCartesianFieldlines(xVar, yVar, zVar, outDimensions, seedPoints, TraceDirection::FORWARD, data); - traceCartesianFieldlines(xVar, yVar, zVar, outDimensions, seedPoints, TraceDirection::BACK, data); + for (glm::vec3 seedPoint : seedPoints) { + line = traceCartesianFieldline(xVar, yVar, zVar, seedPoint, TraceDirection::FORWARD); + for (glm::vec3 point : line) { + int vPosX = std::floor(outDimensions.x*(point.x-_xMin)/(_xMax-_xMin)); + int vPosY = std::floor(outDimensions.y*(point.y-_yMin)/(_yMax-_yMin)); + int vPosZ = std::floor(outDimensions.z*(point.z-_zMin)/(_zMax-_zMin)); + int index = vPosX + vPosY*outDimensions.x + vPosZ*outDimensions.x*outDimensions.y; + data[index] = 1.0; + } + + line = traceCartesianFieldline(xVar, yVar, zVar, seedPoint, TraceDirection::BACK); + for (glm::vec3 point : line) { + int vPosX = std::floor(outDimensions.x*(point.x-_xMin)/(_xMax-_xMin)); + int vPosY = std::floor(outDimensions.y*(point.y-_yMin)/(_yMax-_yMin)); + int vPosZ = std::floor(outDimensions.z*(point.z-_zMin)/(_zMax-_zMin)); + int index = vPosX + vPosY*outDimensions.x + vPosZ*outDimensions.x*outDimensions.y; + data[index] = 1.0; + } + } } else { LERROR("Fieldlines are only supported for BATSRUS model"); } @@ -259,71 +276,79 @@ float* KameleonWrapper::getFieldLines(const std::string& xVar, return data; } -void KameleonWrapper::traceCartesianFieldlines(const std::string& xVar, - const std::string& yVar, const std::string& zVar, - glm::size3_t outDimensions, std::vector seedPoints, - TraceDirection direction, float* data) { +std::vector > KameleonWrapper::getFieldLines( + const std::string& xVar, const std::string& yVar, + const std::string& zVar, std::vector seedPoints) { + assert(_model && _interpolator); + assert(_type == Model::ENLIL || _type == Model::BATSRUS); + LINFO("Creating " << seedPoints.size() << " fieldlines from variables " << xVar << " " << yVar << " " << zVar); + + std::vector fLine, bLine; + std::vector > fieldLines; + + if (_type == Model::BATSRUS) { + for (glm::vec3 seedPoint : seedPoints) { + fLine = traceCartesianFieldline(xVar, yVar, zVar, seedPoint, TraceDirection::FORWARD); + bLine = traceCartesianFieldline(xVar, yVar, zVar, seedPoint, TraceDirection::BACK); + bLine.insert(bLine.begin(), fLine.rbegin(), fLine.rend()); + fieldLines.push_back(bLine); + } + } else { + LERROR("Fieldlines are only supported for BATSRUS model"); + } + + return fieldLines; +} + +std::vector KameleonWrapper::traceCartesianFieldline( + const std::string& xVar, const std::string& yVar, + const std::string& zVar, glm::vec3 seedPoint, TraceDirection direction) { - int highNumber = 100000; glm::vec3 pos, k1, k2, k3, k4; + std::vector line; - float stepSize = 2.0; - float stepX = stepSize*(_xMax-_xMin)/(static_cast(outDimensions.x)); - float stepY = stepSize*(_yMax-_yMin)/(static_cast(outDimensions.y)); - float stepZ = stepSize*(_zMax-_zMin)/(static_cast(outDimensions.z)); + float stepX = 0.5, stepY = 0.5, stepZ = 0.5; - for (int i = 0; i < seedPoints.size(); ++i) { - progressBar(i, seedPoints.size()); - pos = seedPoints.at(i); - int avoidInfLoopPlz = 0; - while (pos.x < _xMax && pos.x > _xMin && - pos.y < _yMax && pos.y > _yMin && - pos.z < _zMax && pos.z > _zMin) { + int numSteps = 0; + int maxSteps = 1000; + pos = seedPoint; - // Save position - int vPosX = std::floor(outDimensions.x*(pos.x-_xMin)/(_xMax-_xMin)); - int vPosY = std::floor(outDimensions.y*(pos.y-_yMin)/(_yMax-_yMin)); - int vPosZ = std::floor(outDimensions.z*(pos.z-_zMin)/(_zMax-_zMin)); - int index = vPosX + vPosY*outDimensions.x + vPosZ*outDimensions.x*outDimensions.y; - data[index] = 1.0; + // While we are inside the models boundries and not inside earth + while ((pos.x < _xMax && pos.x > _xMin && pos.y < _yMax && pos.y > _yMin && + pos.z < _zMax && pos.z > _zMin) && !(pos.x < 1.0 && pos.x > -1.0 && + pos.y < 1.0 && pos.y > -1.0 && pos.z < 1.0 && pos.z > -1.0)) { - // Calculate the next position - // Euler -// dir.x = _interpolator->interpolate(xVar, pos.x, pos.y, pos.z); -// dir.y = _interpolator->interpolate(yVar, pos.x, pos.y, pos.z); -// dir.z = _interpolator->interpolate(zVar, pos.x, pos.y, pos.z); -// dir = (float)direction*glm::normalize(dir); -// pos = glm::vec3(stepX*dir.x+pos.x, stepY*dir.y+pos.y, stepZ*dir.z+pos.z); + // Save position + line.push_back(pos); - // Runge-Kutta 4th order - k1.x = _interpolator->interpolate(xVar, pos.x, pos.y, pos.z); - k1.y = _interpolator->interpolate(yVar, pos.x, pos.y, pos.z); - k1.z = _interpolator->interpolate(zVar, pos.x, pos.y, pos.z); - k1 = (float)direction*glm::normalize(k1); - k2.x = _interpolator->interpolate(xVar, pos.x+(stepX/2.0)*k1.x, pos.y+(stepY/2.0)*k1.y, pos.z+(stepZ/2.0)*k1.z); - k2.y = _interpolator->interpolate(yVar, pos.x+(stepX/2.0)*k1.x, pos.y+(stepY/2.0)*k1.y, pos.z+(stepZ/2.0)*k1.z); - k2.z = _interpolator->interpolate(zVar, pos.x+(stepX/2.0)*k1.x, pos.y+(stepY/2.0)*k1.y, pos.z+(stepZ/2.0)*k1.z); - k2 = (float)direction*glm::normalize(k2); - k3.x = _interpolator->interpolate(xVar, pos.x+(stepX/2.0)*k2.x, pos.y+(stepY/2.0)*k2.y, pos.z+(stepZ/2.0)*k2.z); - k3.y = _interpolator->interpolate(yVar, pos.x+(stepX/2.0)*k2.x, pos.y+(stepY/2.0)*k2.y, pos.z+(stepZ/2.0)*k2.z); - k3.z = _interpolator->interpolate(zVar, pos.x+(stepX/2.0)*k2.x, pos.y+(stepY/2.0)*k2.y, pos.z+(stepZ/2.0)*k2.z); - k3 = (float)direction*glm::normalize(k3); - k4.x = _interpolator->interpolate(xVar, pos.x+stepX*k3.x, pos.y+stepY*k3.y, pos.z+stepZ*k3.z); - k4.y = _interpolator->interpolate(yVar, pos.x+stepX*k3.x, pos.y+stepY*k3.y, pos.z+stepZ*k3.z); - k4.z = _interpolator->interpolate(zVar, pos.x+stepX*k3.x, pos.y+stepY*k3.y, pos.z+stepZ*k3.z); - k4 = (float)direction*glm::normalize(k4); - pos.x = pos.x + (stepX/6.0)*(k1.x + 2.0*k2.x + 2.0*k3.x + k4.x); - pos.y = pos.y + (stepY/6.0)*(k1.y + 2.0*k2.y + 2.0*k3.y + k4.y); - pos.z = pos.z + (stepZ/6.0)*(k1.z + 2.0*k2.z + 2.0*k3.z + k4.z); + // Calculate new position with Runge-Kutta 4th order + k1.x = _interpolator->interpolate(xVar, pos.x, pos.y, pos.z); + k1.y = _interpolator->interpolate(yVar, pos.x, pos.y, pos.z); + k1.z = _interpolator->interpolate(zVar, pos.x, pos.y, pos.z); + k1 = (float)direction*glm::normalize(k1); + k2.x = _interpolator->interpolate(xVar, pos.x+(stepX/2.0)*k1.x, pos.y+(stepY/2.0)*k1.y, pos.z+(stepZ/2.0)*k1.z); + k2.y = _interpolator->interpolate(yVar, pos.x+(stepX/2.0)*k1.x, pos.y+(stepY/2.0)*k1.y, pos.z+(stepZ/2.0)*k1.z); + k2.z = _interpolator->interpolate(zVar, pos.x+(stepX/2.0)*k1.x, pos.y+(stepY/2.0)*k1.y, pos.z+(stepZ/2.0)*k1.z); + k2 = (float)direction*glm::normalize(k2); + k3.x = _interpolator->interpolate(xVar, pos.x+(stepX/2.0)*k2.x, pos.y+(stepY/2.0)*k2.y, pos.z+(stepZ/2.0)*k2.z); + k3.y = _interpolator->interpolate(yVar, pos.x+(stepX/2.0)*k2.x, pos.y+(stepY/2.0)*k2.y, pos.z+(stepZ/2.0)*k2.z); + k3.z = _interpolator->interpolate(zVar, pos.x+(stepX/2.0)*k2.x, pos.y+(stepY/2.0)*k2.y, pos.z+(stepZ/2.0)*k2.z); + k3 = (float)direction*glm::normalize(k3); + k4.x = _interpolator->interpolate(xVar, pos.x+stepX*k3.x, pos.y+stepY*k3.y, pos.z+stepZ*k3.z); + k4.y = _interpolator->interpolate(yVar, pos.x+stepX*k3.x, pos.y+stepY*k3.y, pos.z+stepZ*k3.z); + k4.z = _interpolator->interpolate(zVar, pos.x+stepX*k3.x, pos.y+stepY*k3.y, pos.z+stepZ*k3.z); + k4 = (float)direction*glm::normalize(k4); + pos.x = pos.x + (stepX/6.0)*(k1.x + 2.0*k2.x + 2.0*k3.x + k4.x); + pos.y = pos.y + (stepY/6.0)*(k1.y + 2.0*k2.y + 2.0*k3.y + k4.y); + pos.z = pos.z + (stepZ/6.0)*(k1.z + 2.0*k2.z + 2.0*k3.z + k4.z); - ++avoidInfLoopPlz; - - if (avoidInfLoopPlz > highNumber) { - LDEBUG("Inf loop averted"); - break; - } + ++numSteps; + if (numSteps > maxSteps) { + LDEBUG("Max number of steps taken"); + break; } } + return line; } void KameleonWrapper::getGridVariables(std::string& x, std::string& y, std::string& z) { @@ -367,4 +392,3 @@ void KameleonWrapper::progressBar(int current, int end) { } } // namespace openspace - From f4dad8dc1c3b2740d77d892e49c9c56b050e8fca Mon Sep 17 00:00:00 2001 From: Jonas Strandstedt Date: Thu, 5 Jun 2014 13:18:22 -0400 Subject: [PATCH 14/49] Intermediate ABuffer - Raycasting works - TODO: Mix raycasting with fragment list - TODO: Fix PowerScaling --- .../openspace/rendering/volumeraycasterbox.h | 4 +- shaders/ABuffer/abufferResolveFragment.glsl | 109 ++++++++++++++---- shaders/ABuffer/abufferSort.hglsl | 40 +++++++ shaders/exitpoints.frag | 2 + shaders/exitpoints.vert | 5 +- shaders/pscstandard_fs.glsl | 5 +- src/abuffer/abufferSingleLinked.cpp | 7 ++ src/rendering/renderablevolumegl.cpp | 10 +- src/rendering/volumeraycasterbox.cpp | 8 +- 9 files changed, 153 insertions(+), 37 deletions(-) diff --git a/include/openspace/rendering/volumeraycasterbox.h b/include/openspace/rendering/volumeraycasterbox.h index 5792b0e0c3..8597a1c265 100644 --- a/include/openspace/rendering/volumeraycasterbox.h +++ b/include/openspace/rendering/volumeraycasterbox.h @@ -45,7 +45,7 @@ public: VolumeRaycasterBox(); ~VolumeRaycasterBox(); bool initialize(); - void render(const glm::mat4& MVP); + void render(const glm::mat4& MVP,const glm::mat4& transform = glm::mat4(1.0)); ghoul::opengl::Texture* backFace(); ghoul::opengl::Texture* frontFace(); @@ -56,7 +56,7 @@ private: ghoul::opengl::Texture *_backTexture, *_frontTexture; ghoul::opengl::ProgramObject *_boxProgram; sgct_utils::SGCTBox* _boundingBox; - GLint _MVPLocation; + GLint _MVPLocation, _modelTransformLocation; glm::size2_t _dimensions; }; diff --git a/shaders/ABuffer/abufferResolveFragment.glsl b/shaders/ABuffer/abufferResolveFragment.glsl index 3a8619d474..3bd50f984e 100644 --- a/shaders/ABuffer/abufferResolveFragment.glsl +++ b/shaders/ABuffer/abufferResolveFragment.glsl @@ -1,19 +1,20 @@ #version 430 // uniforms +uniform sampler3D volume; in vec2 texCoord; out vec4 color; // settings -#define ALPHA_LIMIT 0.51 +#define ALPHA_LIMIT 1.0 #define MAX_FRAGMENTS 16 #define MAX_VOLUMES 4 #include "abufferStruct.hglsl" ABufferStruct_t fragments[MAX_FRAGMENTS]; - vec3 volume_direction[MAX_VOLUMES]; +float volume_length[MAX_VOLUMES]; vec3 volume_position[MAX_VOLUMES]; #include "abufferSort.hglsl" @@ -26,41 +27,101 @@ vec4 blend(vec4 src, vec4 dst) { return o; //return mix(src, dst, dst.a*(1.0f - src.a)); } - -vec3 direction(vec4 v1, vec4 v2) { - const float k = 10.0; - float ds = v2.w - v1.w; - if(ds >= 0) { - float p = pow(k,-ds); - return vec4(v1.x*p - v2.x, v1.y*p - v2.y, v1.z*p - v2.z, v2.w).xyz; - } else { - float p = pow(k,ds); - return vec4(v1.x - v2.x*p, v1.y - v2.y*p, v1.z - v2.z*p, v1.w).xyz; - } +/* +void blend(inout vec4 dst, in vec4 src, in float stepSize) { + src.a = 1.0 - pow(1.0 - src.a, stepSize ); + dst.rgb = dst.rgb + (1.0 - dst.a) * src.a * src.rgb; + dst.a = dst.a + (1.0 -dst.a) * src.a; } +//Color geometry +void blendGeometry(inout vec4 color, ABufferStruct_t frag) { + //vec4 c; + //c.rg = unpackHalf2x16(frag.rg); + //c.ba = unpackHalf2x16(frag.ba); + vec4 c = _col_(frag); + c.a = clamp(c.a, 0.0,1.0); + blend(color, c, 0.01); + return; +} +*/ + vec4 calculate_final_color(uint frag_count) { int currentVolumeBitmask = 0; vec4 final_color = vec4(0); - for(uint i = 0; i < frag_count && final_color.a < ALPHA_LIMIT; i++) { - ABufferStruct_t item = fragments[i]; - vec4 frag_color = _col_(item); - vec4 position = _pos_(item); - uint type = _type_(item); + + // if(frag_count == 1 && _type_(fragments[0]) == 0) { + // blendGeometry(final_color, fragments[0]); + // return final_color; + // } + + int frag_count_1 = int(frag_count); + for(int i = 0; i < frag_count_1 && final_color.a < ALPHA_LIMIT; i++) { + + //int maxFrags = int(frag_count)-1; + //for(int i = 0; i < frag_count; i++) { + ABufferStruct_t startFrag = fragments[i]; + //ABufferStruct_t endFrag = fragments[i+1]; + //vec4 frag_color = _col_(startFrag); + //vec4 position = _pos_(startFrag); + int type = int(_type_(startFrag)); - if(currentVolumeBitmask != 0) { + if(type != 0) { currentVolumeBitmask = currentVolumeBitmask ^ (1 << type); + if(currentVolumeBitmask != 0) { + float p = 0.0f; + const float stepSize = 0.01; + float l = volume_length[type-1]; + vec3 direction = volume_direction[type-1]; + vec3 position; + vec4 tmp, color = vec4(0); + while(p < l) { + position = volume_position[type-1] + direction*p; + tmp = texture(volume, position); + color = max(color, tmp); + p+= stepSize; + } + vec4 volume_color = vec4(color.r,color.r,color.r,color.r*2.0); + final_color = blend(final_color, volume_color); + } + /* + const vec3 direction = volume_direction[type-1]; + const float l = pscLength(_pos_(fragments[i+1]), _pos_(fragments[i])); + const float stepSize = 0.01; + const float iterationsStop = l / volume_length[type-1]; + //const int iterations = 100; + float p = 0.0f; + int maxit = 500; + int it = 0; + while(p < iterationsStop && it < maxit) { + vec4 sample_color = vec4(0.1, 0.0, 0.0, 0.1); + blend(final_color, sample_color, stepSize); + + p+=stepSize; + ++it; + } + */ + } else { + final_color = blend(final_color, _col_(startFrag)); + //blendGeometry(final_color, startFrag); } - /* - if(_type_(item) == 1) -*/ - final_color = blend(final_color, frag_color); - //final_color = blend(frag_color, final_color); + + + //blendGeometry(final_color, startFrag); + //if(i == maxFrags -1 && _type_(endFrag) == 0) + // blendGeometry(final_color, endFrag); + + // final_color = blend(final_color, frag_color); + //if(i == frag_count_1 && _type_(endFrag) == 0) + // final_color = blend(final_color, _col_(endFrag)); } + //int id =2; + //if(id < frag_count)final_color = blend(final_color, _col_(fragments[id])); + return final_color; } diff --git a/shaders/ABuffer/abufferSort.hglsl b/shaders/ABuffer/abufferSort.hglsl index 4cdc8bf481..4ec61e9cb8 100644 --- a/shaders/ABuffer/abufferSort.hglsl +++ b/shaders/ABuffer/abufferSort.hglsl @@ -24,6 +24,20 @@ int build_local_fragments_list() { return frag_count; } +float pscLength(vec4 v1, vec4 v2) { + const float k = 10.0; + float ds = v2.w - v1.w; + vec4 vector; + if(ds >= 0) { + float p = pow(k,-ds); + vector = vec4(v1.x*p - v2.x, v1.y*p - v2.y, v1.z*p - v2.z, v2.w); + } else { + float p = pow(k,ds); + vector = vec4(v1.x - v2.x*p, v1.y - v2.y*p, v1.z - v2.z*p, v1.w); + } + return length(vector.xyz)*pow(k,vector.w); +} + void sort_fragments_list(uint frag_count) { uint i,j; ABufferStruct_t tmp; @@ -36,4 +50,30 @@ void sort_fragments_list(uint frag_count) { } fragments[j] = tmp; } + + int ii, jj; + for(ii = 0; ii < MAX_VOLUMES; ++ii) { + bool start = true; + vec3 startColor; + vec4 startPosition; + for(jj = 0; jj < frag_count; ++jj) { + int type = int(_type_(fragments[jj])) -1; + if(type== ii) { + if(start) { + startColor = _col_(fragments[jj]).rgb; + startPosition = _pos_(fragments[jj]); + start = false; + } else { + vec3 dir = _col_(fragments[jj]).rgb - startColor; + volume_direction[ii] = normalize(dir); + volume_position[ii] = startColor; + volume_length[ii] = length(dir); + //volume_length[ii] = pscLength(_pos_(fragments[jj]), startPosition); + break; + } + } + } + } + //volume_direction[0] = vec3(1.0,0.0,0.0); + //volume_direction[0] = _col_(fragments[0]).rgb; } diff --git a/shaders/exitpoints.frag b/shaders/exitpoints.frag index 72041462b2..606bfeff10 100644 --- a/shaders/exitpoints.frag +++ b/shaders/exitpoints.frag @@ -1,6 +1,7 @@ #version 430 core in vec3 vPosition; +in vec3 worldPosition; out vec4 fragColor; #include "ABuffer/abufferStruct.hglsl" @@ -13,6 +14,7 @@ void main() { _col_(frag, fragColor); _z_(frag, gl_FragDepth); _type_(frag, 1); + _pos_(frag, vec4(worldPosition,0)); addToBuffer(frag); //discard; diff --git a/shaders/exitpoints.vert b/shaders/exitpoints.vert index cc0dd3624d..15e86a76df 100644 --- a/shaders/exitpoints.vert +++ b/shaders/exitpoints.vert @@ -2,10 +2,13 @@ layout(location = 2) in vec3 vertPosition; uniform mat4 modelViewProjection; +uniform mat4 modelTransform; out vec3 vPosition; +out vec3 worldPosition; void main() { - gl_Position = modelViewProjection * vec4(vertPosition, 1.0); vPosition = vertPosition; + worldPosition = (modelTransform *vec4(vPosition, 1.0)).xyz; + gl_Position = modelViewProjection *vec4(worldPosition, 1.0); } \ No newline at end of file diff --git a/shaders/pscstandard_fs.glsl b/shaders/pscstandard_fs.glsl index b5304ad234..85dc406b22 100644 --- a/shaders/pscstandard_fs.glsl +++ b/shaders/pscstandard_fs.glsl @@ -9,10 +9,6 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI */ #version 430 -uniform mat4 ViewProjection; -uniform mat4 ModelTransform; -uniform vec4 campos; -uniform vec4 objpos; uniform float time; uniform sampler2D texture1; @@ -119,6 +115,7 @@ void main() _col_(frag, diffuse); _z_(frag, gl_FragDepth); _type_(frag, 0); + _pos_(frag, vs_position); addToBuffer(frag); /* diff --git a/src/abuffer/abufferSingleLinked.cpp b/src/abuffer/abufferSingleLinked.cpp index 3d3c7cf7d4..727a023015 100644 --- a/src/abuffer/abufferSingleLinked.cpp +++ b/src/abuffer/abufferSingleLinked.cpp @@ -23,6 +23,7 @@ ****************************************************************************************/ #include +#include #include #include @@ -168,7 +169,13 @@ void ABufferSingleLinked::preRender() { } void ABufferSingleLinked::postRender() { + + ghoul::opengl::Texture* volume; + OsEng.configurationManager().getValue("firstVolume", volume); resolveShader->activate(); + glActiveTexture(GL_TEXTURE0); + volume->bind(); + resolveShader->setUniform("volume", 0); //resolveShader->setUniform("SCREEN_WIDTH", width); //resolveShader->setUniform("SCREEN_HEIGHT", height); glBindVertexArray(_screenQuad); diff --git a/src/rendering/renderablevolumegl.cpp b/src/rendering/renderablevolumegl.cpp index 9e3bdcbf43..051180a773 100644 --- a/src/rendering/renderablevolumegl.cpp +++ b/src/rendering/renderablevolumegl.cpp @@ -33,6 +33,8 @@ #include +#include + namespace { std::string _loggerCat = "RenderableVolumeGL"; } @@ -119,6 +121,8 @@ bool RenderableVolumeGL::initialize() { // ------ VOLUME READING ---------------- _volume = loadVolume(_filename, _hintsDictionary); _volume->uploadTexture(); + OsEng.configurationManager().setValue("firstVolume", _volume); + //glBindImageTexture(2, *_volume, 0, GL_FALSE, 0, GL_READ_ONLY, _volume->type()); // ------ SETUP GEOMETRY ---------------- const GLfloat size = 1.0f; @@ -179,15 +183,15 @@ bool RenderableVolumeGL::deinitialize() { void RenderableVolumeGL::render(const Camera *camera, const psc &thisPosition) { _stepSize = 0.01f; - glm::mat4 transform = camera->viewProjectionMatrix(); + glm::mat4 transform ; glm::mat4 camTransform = camera->viewRotationMatrix(); psc relative = thisPosition-camera->position(); - transform = transform*camTransform; + transform = camTransform; transform = glm::translate(transform, relative.vec3()); transform = glm::scale(transform, _boxScaling); - _colorBoxRenderer->render(transform); + _colorBoxRenderer->render(camera->viewProjectionMatrix(), transform); /* // Draw screenquad glClearColor(0.2f, 0.2f, 0.2f, 0); diff --git a/src/rendering/volumeraycasterbox.cpp b/src/rendering/volumeraycasterbox.cpp index 3e27e0d95d..ad51b1eabd 100644 --- a/src/rendering/volumeraycasterbox.cpp +++ b/src/rendering/volumeraycasterbox.cpp @@ -61,7 +61,8 @@ bool VolumeRaycasterBox::initialize() { // ------ SETUP SHADER ----------------- OsEng.configurationManager().getValue("RaycastProgram", _boxProgram); - _MVPLocation = _boxProgram->uniformLocation("modelViewProjection"); + _MVPLocation = _boxProgram->uniformLocation("modelViewProjection"); + _modelTransformLocation = _boxProgram->uniformLocation("modelTransform"); // ------ SETUP FBO --------------------- _fbo = new FramebufferObject(); @@ -89,11 +90,12 @@ bool VolumeRaycasterBox::initialize() { return true; } -void VolumeRaycasterBox::render(const glm::mat4& MVP) { +void VolumeRaycasterBox::render(const glm::mat4& MVP,const glm::mat4& transform) { GLuint activeFBO = FramebufferObject::getActiveObject(); // Save SGCTs main FBO _fbo->activate(); _boxProgram->activate(); - _boxProgram->setUniform(_MVPLocation, MVP); + _boxProgram->setUniform(_MVPLocation, MVP); + _boxProgram->setUniform(_modelTransformLocation, transform); sgct_core::Frustum::FrustumMode mode = sgct::Engine::instance()-> getActiveWindowPtr()-> From 4a08f10d66c346e7e1a9a41c91d936aaa786133a Mon Sep 17 00:00:00 2001 From: Hans-Christian Helltegen Date: Thu, 5 Jun 2014 13:26:10 -0400 Subject: [PATCH 15/49] You can now specify seedpoints in the mod-file for fieldlines --- include/openspace/rendering/renderable.h | 3 +- .../rendering/renderablefieldlines.h | 13 +-- .../openspace/rendering/renderablevolume.h | 8 +- openspace-data | 2 +- src/rendering/renderable.cpp | 25 +++++- src/rendering/renderablefieldlines.cpp | 89 ++++++++++++++----- src/rendering/renderablevolume.cpp | 32 +------ 7 files changed, 107 insertions(+), 65 deletions(-) diff --git a/include/openspace/rendering/renderable.h b/include/openspace/rendering/renderable.h index 2ff4bda48a..a1959f72aa 100644 --- a/include/openspace/rendering/renderable.h +++ b/include/openspace/rendering/renderable.h @@ -52,9 +52,10 @@ public: virtual void update(); protected: - // Renderable(); + std::string findPath(const std::string& path); private: PowerScaledScalar boundingSphere_; + std::string _relativePath; }; } // namespace openspace diff --git a/include/openspace/rendering/renderablefieldlines.h b/include/openspace/rendering/renderablefieldlines.h index a1546b52b6..ade8173be8 100644 --- a/include/openspace/rendering/renderablefieldlines.h +++ b/include/openspace/rendering/renderablefieldlines.h @@ -26,7 +26,7 @@ #define RENDERABLEFIELDLINES_H_ // open space includes -#include +#include // ghoul includes #include @@ -40,7 +40,7 @@ namespace openspace { -class RenderableFieldlines : public RenderableVolume { +class RenderableFieldlines : public Renderable { public: RenderableFieldlines(const ghoul::Dictionary& dictionary); ~RenderableFieldlines(); @@ -54,6 +54,7 @@ public: private: ghoul::Dictionary _hintsDictionary; std::string _filename; + std::vector _seedPoints; ghoul::opengl::ProgramObject* _fieldlinesProgram; GLuint _VAO; @@ -62,12 +63,14 @@ private: ghoul::filesystem::File* _vertexSourceFile; ghoul::filesystem::File* _fragmentSourceFile; - bool _programUpdateOnSave; - - void safeShaderCompilation(); std::vector _lineStart; std::vector _lineCount; + + bool _programUpdateOnSave; + void safeShaderCompilation(); + + }; } // namespace openspace diff --git a/include/openspace/rendering/renderablevolume.h b/include/openspace/rendering/renderablevolume.h index 00bc8c680b..870b8ee672 100644 --- a/include/openspace/rendering/renderablevolume.h +++ b/include/openspace/rendering/renderablevolume.h @@ -29,7 +29,6 @@ #include // ghoul includes -#include #include #include @@ -37,23 +36,18 @@ namespace openspace { class RenderableVolume: public Renderable { public: - // constructors & destructor RenderableVolume(const ghoul::Dictionary& dictionary); ~RenderableVolume(); protected: - std::string findPath(const std::string& path); ghoul::opengl::Texture* loadVolume(const std::string& filepath, const ghoul::Dictionary& hintsDictionary); ghoul::RawVolumeReader::ReadHints readHints(const ghoul::Dictionary& dictionary); ghoul::opengl::Texture* loadTransferFunction(const std::string& filepath); private: - - // relative path - std::string _relativePath; }; } // namespace openspace -#endif \ No newline at end of file +#endif diff --git a/openspace-data b/openspace-data index 8c9a21935d..3b9a6e638b 160000 --- a/openspace-data +++ b/openspace-data @@ -1 +1 @@ -Subproject commit 8c9a21935d4e1295857997664b0b7b297cce8dda +Subproject commit 3b9a6e638b3018d099f04d8abcac994cb505a542 diff --git a/src/rendering/renderable.cpp b/src/rendering/renderable.cpp index 9a432b02d7..40a9c193a3 100644 --- a/src/rendering/renderable.cpp +++ b/src/rendering/renderable.cpp @@ -27,6 +27,8 @@ #include #include +#include + namespace { const std::string _loggerCat = "Renderable"; } @@ -63,6 +65,13 @@ Renderable::Renderable(const ghoul::Dictionary& dictionary) std::string name; dictionary.getValue(constants::scenegraphnode::keyName, name); setName(name); + + // get path if available + _relativePath = ""; + if(dictionary.hasKey(constants::scenegraph::keyPathModule)) { + dictionary.getValue(constants::scenegraph::keyPathModule, _relativePath); + _relativePath += "/"; + } } Renderable::~Renderable() @@ -83,4 +92,18 @@ void Renderable::update() { } -} // namespace openspace \ No newline at end of file +std::string Renderable::findPath(const std::string& path) { + std::string tmp = absPath(path); + if(FileSys.fileExists(tmp)) + return tmp; + + tmp = absPath(_relativePath + path); + if(FileSys.fileExists(tmp)) + return tmp; + + LERROR("Could not find file '" << path << "'"); + + return ""; +} + +} // namespace openspace diff --git a/src/rendering/renderablefieldlines.cpp b/src/rendering/renderablefieldlines.cpp index 203b07f740..b19740d54d 100644 --- a/src/rendering/renderablefieldlines.cpp +++ b/src/rendering/renderablefieldlines.cpp @@ -34,21 +34,47 @@ namespace { namespace openspace { RenderableFieldlines::RenderableFieldlines(const ghoul::Dictionary& dictionary) : - RenderableVolume(dictionary), _VAO(0), _programUpdateOnSave(false) { + Renderable(dictionary), _VAO(0), _programUpdateOnSave(false) { _shaderMutex = new std::mutex; - _filename = ""; - if(dictionary.hasKey("Volume")) { - if(dictionary.getValue("Volume", _filename)) { - _filename = findPath(_filename); + if(dictionary.hasKey("Fieldlines")) { + ghoul::Dictionary fieldlines; + if(dictionary.getValue("Fieldlines", fieldlines)) { + for(auto key: fieldlines.keys()) { + ghoul::Dictionary fieldline; + if(fieldlines.getValue(key, fieldline)) { + if (fieldline.hasKey("File")) { + std::string file = ""; + if (fieldline.getValue("File", file)) { + file = findPath(file); + if (file != "") { + + // parse hints + ghoul::Dictionary hintsDictionary; + if(fieldline.hasKey("Hints")) + fieldline.getValue("Hints", hintsDictionary); + + // TODO Vectors of filenames and dictionaries + _filename = file; + _hintsDictionary = hintsDictionary; + + ghoul::Dictionary seedpointsDictionary; + if (fieldline.hasKey("Seedpoints") && fieldline.getValue("Seedpoints", seedpointsDictionary)) { + glm::vec3 tmpVal; + for (int i = 0; i < seedpointsDictionary.keys().size(); ++i) { + fieldline.getValue("Seedpoints."+std::to_string(i+1), tmpVal); + _seedPoints.push_back(tmpVal); + } + } + } else + LERROR("File not found!"); + } + } + } + } } } - LDEBUG("filename: " << _filename); - - if(dictionary.hasKey("Hints")) - dictionary.getValue("Hints", _hintsDictionary); - std::string vshaderpath = ""; std::string fshaderpath = ""; @@ -89,31 +115,36 @@ RenderableFieldlines::~RenderableFieldlines() { bool RenderableFieldlines::initialize() { assert(_filename != ""); + +// std::vector seedPoints; +// for (int x = -6; x <= 6; x+=3) { +// for (int y = -6; y <= 6; y+=3) { +// for (int z = -6; z <= 6; z+=3) { +// seedPoints.push_back(glm::vec3((float)x, (float)y, (float)z)); +// } +// } +// } + KameleonWrapper kameleon(_filename, KameleonWrapper::Model::BATSRUS); - std::vector seedPoints; + std::vector > fieldlines = kameleon.getFieldLines("bx", "by", "bz", _seedPoints); - for (int x = -3; x <= 3; x+=3) { - for (int y = -3; y <= 3; y+=3) { - for (int z = -3; z <= 3; z+=3) { - seedPoints.push_back(glm::vec3((float)x, (float)y, (float)z)); - } - } - } - - std::vector > fieldlines = kameleon.getFieldLines("bx", "by", "bz", seedPoints); std::vector vertexData; - LDEBUG("Fieldlines.size() = " << fieldlines.size()); - int prevEnd = 0; + int vertexSum = 0; + for (int i = 0; i < fieldlines.size(); i++) { _lineStart.push_back(prevEnd); _lineCount.push_back(fieldlines[i].size()); prevEnd = prevEnd + fieldlines[i].size(); + vertexSum += fieldlines[i].size(); vertexData.insert( vertexData.end(), fieldlines[i].begin(), fieldlines[i].end()); } + LDEBUG("Vertex size: " << vertexSum); + LDEBUG("Line average : " << (float)vertexSum/(float)fieldlines.size()); + GLuint vertexPositionBuffer; glGenVertexArrays(1, &_VAO); // generate array glBindVertexArray(_VAO); // bind array @@ -129,6 +160,15 @@ bool RenderableFieldlines::initialize() { glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind buffer glBindVertexArray(0); //unbind array + // ------ SETUP SHADERS ----------------- + auto privateCallback = [this](const ghoul::filesystem::File& file) { + safeShaderCompilation(); + }; + if(_programUpdateOnSave) { + _vertexSourceFile->setCallback(privateCallback); + _fragmentSourceFile->setCallback(privateCallback); + } + _fieldlinesProgram->compileShaderObjects(); _fieldlinesProgram->linkProgramObject(); @@ -165,6 +205,11 @@ void RenderableFieldlines::update() { } void RenderableFieldlines::safeShaderCompilation() { + _shaderMutex->lock(); + _fieldlinesProgram->rebuildFromFile(); + _fieldlinesProgram->compileShaderObjects(); + _fieldlinesProgram->linkProgramObject(); + _shaderMutex->unlock(); } } // namespace openspace diff --git a/src/rendering/renderablevolume.cpp b/src/rendering/renderablevolume.cpp index a16305b408..c5ee3d6b16 100644 --- a/src/rendering/renderablevolume.cpp +++ b/src/rendering/renderablevolume.cpp @@ -24,15 +24,13 @@ // open space includes #include - -#include -#include - #include #include #include -#include +// ghoul includes +#include +#include #include #include @@ -73,34 +71,12 @@ namespace { namespace openspace { -RenderableVolume::RenderableVolume(const ghoul::Dictionary& dictionary) - : Renderable(dictionary) -{ - // get path if available - _relativePath = ""; - if(dictionary.hasKey(constants::scenegraph::keyPathModule)) { - dictionary.getValue(constants::scenegraph::keyPathModule, _relativePath); - _relativePath += "/"; - } +RenderableVolume::RenderableVolume(const ghoul::Dictionary& dictionary) : Renderable(dictionary) { } RenderableVolume::~RenderableVolume() { } -std::string RenderableVolume::findPath(const std::string& path) { - std::string tmp = absPath(path); - if(FileSys.fileExists(tmp)) - return tmp; - - tmp = absPath(_relativePath + path); - if(FileSys.fileExists(tmp)) - return tmp; - - LERROR("Could not find file '" << path << "'"); - - return ""; -} - ghoul::opengl::Texture* RenderableVolume::loadVolume(const std::string& filepath, const ghoul::Dictionary& hintsDictionary) { if( ! FileSys.fileExists(filepath)) { LWARNING("Could not load volume, could not find '" << filepath << "'"); From f3f9a5aa1595e33979a61a6e6b054865b2c6fc1b Mon Sep 17 00:00:00 2001 From: Hans-Christian Helltegen Date: Thu, 5 Jun 2014 16:45:24 -0400 Subject: [PATCH 16/49] Renderablefieldliens now properly read hints from .mod file --- src/rendering/renderablefieldlines.cpp | 53 ++++++++++++++++++++------ 1 file changed, 41 insertions(+), 12 deletions(-) diff --git a/src/rendering/renderablefieldlines.cpp b/src/rendering/renderablefieldlines.cpp index b19740d54d..ba8d78f4dc 100644 --- a/src/rendering/renderablefieldlines.cpp +++ b/src/rendering/renderablefieldlines.cpp @@ -115,6 +115,8 @@ RenderableFieldlines::~RenderableFieldlines() { bool RenderableFieldlines::initialize() { assert(_filename != ""); + assert(_hintsDictionary.size() != 0); + assert(_seedPoints.size() != 0); // std::vector seedPoints; // for (int x = -6; x <= 6; x+=3) { @@ -125,26 +127,53 @@ bool RenderableFieldlines::initialize() { // } // } - KameleonWrapper kameleon(_filename, KameleonWrapper::Model::BATSRUS); - std::vector > fieldlines = kameleon.getFieldLines("bx", "by", "bz", _seedPoints); + std::string modelString; + std::vector > fieldlinesData; + + if (_hintsDictionary.hasKey("Model") && _hintsDictionary.getValue("Model", modelString)) { + KameleonWrapper::Model model; + if (modelString == "BATSRUS") { + model = KameleonWrapper::Model::BATSRUS; + } else if (modelString == "ENLIL") { + LWARNING("ENLIL model not supported for fieldlines"); + return false; + } else { + LWARNING("Hints does not specify a valid 'Model'"); + return false; + } + + std::string xVariable, yVariable, zVariable; + if (_hintsDictionary.hasKey("Variables")) { + bool xVar, yVar, zVar; + xVar = _hintsDictionary.getValue("Variables.1", xVariable); + yVar = _hintsDictionary.getValue("Variables.2", yVariable); + zVar = _hintsDictionary.getValue("Variables.3", zVariable); + + if (xVar || yVar || zVar) { + KameleonWrapper kw(_filename, model); + fieldlinesData = kw.getFieldLines(xVariable, yVariable, zVariable, _seedPoints); + + } else { + LWARNING("Error reading variables! Must be 3 and must exist in CDF data"); + return false; + } + } else { + LWARNING("Hints does not specify valid 'Variables'"); + return false; + } + } std::vector vertexData; int prevEnd = 0; - int vertexSum = 0; - - for (int i = 0; i < fieldlines.size(); i++) { + for (int i = 0; i < fieldlinesData.size(); i++) { _lineStart.push_back(prevEnd); - _lineCount.push_back(fieldlines[i].size()); - prevEnd = prevEnd + fieldlines[i].size(); - vertexSum += fieldlines[i].size(); + _lineCount.push_back(fieldlinesData[i].size()); + prevEnd = prevEnd + fieldlinesData[i].size(); - vertexData.insert( vertexData.end(), fieldlines[i].begin(), fieldlines[i].end()); + vertexData.insert( vertexData.end(), fieldlinesData[i].begin(), fieldlinesData[i].end()); } - LDEBUG("Vertex size: " << vertexSum); - LDEBUG("Line average : " << (float)vertexSum/(float)fieldlines.size()); - GLuint vertexPositionBuffer; glGenVertexArrays(1, &_VAO); // generate array glBindVertexArray(_VAO); // bind array From 08f2498e8a7fe6b074988e57c6c034eafd7833b6 Mon Sep 17 00:00:00 2001 From: Hans-Christian Helltegen Date: Fri, 6 Jun 2014 12:18:45 -0400 Subject: [PATCH 17/49] Fieldlines are now created with seedpoints from mod-file. Stepsize can be specified in mod-file aswell --- include/openspace/util/kameleonwrapper.h | 9 ++-- openspace-data | 2 +- src/rendering/renderablefieldlines.cpp | 36 +++++++++------- src/rendering/renderablevolume.cpp | 23 +--------- src/util/kameleonwrapper.cpp | 53 ++++-------------------- 5 files changed, 35 insertions(+), 88 deletions(-) diff --git a/include/openspace/util/kameleonwrapper.h b/include/openspace/util/kameleonwrapper.h index 55bb1dbbca..81023772e8 100644 --- a/include/openspace/util/kameleonwrapper.h +++ b/include/openspace/util/kameleonwrapper.h @@ -54,17 +54,14 @@ public: float* getUniformSampledVectorValues(const std::string& xVar, const std::string& yVar, const std::string& zVar, glm::size3_t outDimensions); - float* getVolumeFieldLines(const std::string& xVar, const std::string& yVar, - const std::string& zVar, glm::size3_t outDimensions, std::vector seedPoints); - std::vector > getFieldLines(const std::string& xVar, const std::string& yVar, const std::string& zVar, - std::vector seedPoints); + std::vector seedPoints, float stepSize); private: std::vector traceCartesianFieldline(const std::string& xVar, - const std::string& yVar, const std::string& zVar, - glm::vec3 seedPoint, TraceDirection direction); + const std::string& yVar, const std::string& zVar, glm::vec3 seedPoint, + float stepSize, TraceDirection direction); void getGridVariables(std::string& x, std::string& y, std::string& z); void progressBar(int current, int end); diff --git a/openspace-data b/openspace-data index 3b9a6e638b..a0e8d47b2d 160000 --- a/openspace-data +++ b/openspace-data @@ -1 +1 @@ -Subproject commit 3b9a6e638b3018d099f04d8abcac994cb505a542 +Subproject commit a0e8d47b2dafa584c2313fe7199ce29030c5e4ae diff --git a/src/rendering/renderablefieldlines.cpp b/src/rendering/renderablefieldlines.cpp index ba8d78f4dc..919d04c68d 100644 --- a/src/rendering/renderablefieldlines.cpp +++ b/src/rendering/renderablefieldlines.cpp @@ -118,20 +118,22 @@ bool RenderableFieldlines::initialize() { assert(_hintsDictionary.size() != 0); assert(_seedPoints.size() != 0); -// std::vector seedPoints; -// for (int x = -6; x <= 6; x+=3) { -// for (int y = -6; y <= 6; y+=3) { -// for (int z = -6; z <= 6; z+=3) { -// seedPoints.push_back(glm::vec3((float)x, (float)y, (float)z)); -// } -// } -// } + std::vector seedPoints; + for (int x = -6; x <= 6; x+=3) { + for (int y = -6; y <= 6; y+=3) { + for (int z = -6; z <= 6; z+=3) { + seedPoints.push_back(glm::vec3((float)x, (float)y, (float)z)); + } + } + } std::string modelString; std::vector > fieldlinesData; + float stepSize; + std::string xVariable, yVariable, zVariable; + KameleonWrapper::Model model; if (_hintsDictionary.hasKey("Model") && _hintsDictionary.getValue("Model", modelString)) { - KameleonWrapper::Model model; if (modelString == "BATSRUS") { model = KameleonWrapper::Model::BATSRUS; } else if (modelString == "ENLIL") { @@ -142,18 +144,13 @@ bool RenderableFieldlines::initialize() { return false; } - std::string xVariable, yVariable, zVariable; if (_hintsDictionary.hasKey("Variables")) { bool xVar, yVar, zVar; xVar = _hintsDictionary.getValue("Variables.1", xVariable); yVar = _hintsDictionary.getValue("Variables.2", yVariable); zVar = _hintsDictionary.getValue("Variables.3", zVariable); - if (xVar || yVar || zVar) { - KameleonWrapper kw(_filename, model); - fieldlinesData = kw.getFieldLines(xVariable, yVariable, zVariable, _seedPoints); - - } else { + if (!xVar || !yVar || !zVar) { LWARNING("Error reading variables! Must be 3 and must exist in CDF data"); return false; } @@ -161,8 +158,16 @@ bool RenderableFieldlines::initialize() { LWARNING("Hints does not specify valid 'Variables'"); return false; } + + if (!_hintsDictionary.hasKey("Stepsize") || !_hintsDictionary.getValue("Stepsize", stepSize)) { + LDEBUG("No stepsize set for fieldlines. Setting to default value (0.5)"); + stepSize = 0.5; + } } + KameleonWrapper kw(_filename, model); + fieldlinesData = kw.getFieldLines(xVariable, yVariable, zVariable, _seedPoints, stepSize); + std::vector vertexData; int prevEnd = 0; @@ -215,6 +220,7 @@ void RenderableFieldlines::render(const Camera* camera, const psc& thisPosition) transform = transform*camTransform; transform = glm::translate(transform, relative.vec3()); + transform = glm::rotate(transform, 90.0f, glm::vec3(1.0, 0.0, 0.0)); transform = glm::scale(transform, glm::vec3(0.1)); _shaderMutex->lock(); diff --git a/src/rendering/renderablevolume.cpp b/src/rendering/renderablevolume.cpp index c5ee3d6b16..0897e291d7 100644 --- a/src/rendering/renderablevolume.cpp +++ b/src/rendering/renderablevolume.cpp @@ -136,27 +136,8 @@ ghoul::opengl::Texture* RenderableVolume::loadVolume(const std::string& filepath if (!xVar || !yVar || !zVar) { LERROR("Error reading variables! Must be 3 and must exist in CDF data"); } else { - - // Seed 'em all - std::vector seedPoints; -// seedPoints.push_back(glm::vec3(5.0, 0.0, 0.0)); - for (int z = -5; z <= 5; z+=5) { - for (int y = -5; y <= 5; y+=5) - seedPoints.push_back(glm::vec3(5.0, (float)y, (float)z)); - } - - float* fieldlinesData = kw.getVolumeFieldLines(xVariable, yVariable, zVariable, dimensions, seedPoints); -// float* rhoData = kw.getUniformSampledValues("rho", dimensions); -// -// // Combine fieldlines with rhoData, clamp to [0,1] -// float* data = new float[dimensions.x*dimensions.y*dimensions.z]; -// for (int i = 0; i < dimensions.x*dimensions.y*dimensions.z; ++i) -// data[i] = std::min(fieldlinesData[i]+rhoData[i], 1.0f); -// -// delete fieldlinesData; -// delete rhoData; - - return new ghoul::opengl::Texture(fieldlinesData, dimensions, ghoul::opengl::Texture::Format::Red, GL_RED, GL_FLOAT); + float* data = kw.getUniformSampledVectorValues(xVariable, yVariable, zVariable, dimensions); + return new ghoul::opengl::Texture(data, dimensions, ghoul::opengl::Texture::Format::RGBA, GL_RGBA, GL_FLOAT); } } else { diff --git a/src/util/kameleonwrapper.cpp b/src/util/kameleonwrapper.cpp index b34bee3aeb..0a4a1f5b21 100644 --- a/src/util/kameleonwrapper.cpp +++ b/src/util/kameleonwrapper.cpp @@ -237,48 +237,10 @@ float* KameleonWrapper::getUniformSampledVectorValues(const std::string& xVar, c return data; } -float* KameleonWrapper::getVolumeFieldLines(const std::string& xVar, - const std::string& yVar, const std::string& zVar, - glm::size3_t outDimensions, std::vector seedPoints) { - assert(_model && _interpolator); - assert(outDimensions.x > 0 && outDimensions.y > 0 && outDimensions.z > 0); - assert(_type == Model::ENLIL || _type == Model::BATSRUS); - LINFO("Creating " << seedPoints.size() << " fieldlines from variables " << xVar << " " << yVar << " " << zVar); - - int size = outDimensions.x*outDimensions.y*outDimensions.z; - float* data = new float[size]; - std::vector line; - - if (_type == Model::BATSRUS) { - for (glm::vec3 seedPoint : seedPoints) { - line = traceCartesianFieldline(xVar, yVar, zVar, seedPoint, TraceDirection::FORWARD); - for (glm::vec3 point : line) { - int vPosX = std::floor(outDimensions.x*(point.x-_xMin)/(_xMax-_xMin)); - int vPosY = std::floor(outDimensions.y*(point.y-_yMin)/(_yMax-_yMin)); - int vPosZ = std::floor(outDimensions.z*(point.z-_zMin)/(_zMax-_zMin)); - int index = vPosX + vPosY*outDimensions.x + vPosZ*outDimensions.x*outDimensions.y; - data[index] = 1.0; - } - - line = traceCartesianFieldline(xVar, yVar, zVar, seedPoint, TraceDirection::BACK); - for (glm::vec3 point : line) { - int vPosX = std::floor(outDimensions.x*(point.x-_xMin)/(_xMax-_xMin)); - int vPosY = std::floor(outDimensions.y*(point.y-_yMin)/(_yMax-_yMin)); - int vPosZ = std::floor(outDimensions.z*(point.z-_zMin)/(_zMax-_zMin)); - int index = vPosX + vPosY*outDimensions.x + vPosZ*outDimensions.x*outDimensions.y; - data[index] = 1.0; - } - } - } else { - LERROR("Fieldlines are only supported for BATSRUS model"); - } - - return data; -} - std::vector > KameleonWrapper::getFieldLines( const std::string& xVar, const std::string& yVar, - const std::string& zVar, std::vector seedPoints) { + const std::string& zVar, std::vector seedPoints, + float stepSize ) { assert(_model && _interpolator); assert(_type == Model::ENLIL || _type == Model::BATSRUS); LINFO("Creating " << seedPoints.size() << " fieldlines from variables " << xVar << " " << yVar << " " << zVar); @@ -288,8 +250,8 @@ std::vector > KameleonWrapper::getFieldLines( if (_type == Model::BATSRUS) { for (glm::vec3 seedPoint : seedPoints) { - fLine = traceCartesianFieldline(xVar, yVar, zVar, seedPoint, TraceDirection::FORWARD); - bLine = traceCartesianFieldline(xVar, yVar, zVar, seedPoint, TraceDirection::BACK); + fLine = traceCartesianFieldline(xVar, yVar, zVar, seedPoint, stepSize, TraceDirection::FORWARD); + bLine = traceCartesianFieldline(xVar, yVar, zVar, seedPoint, stepSize, TraceDirection::BACK); bLine.insert(bLine.begin(), fLine.rbegin(), fLine.rend()); fieldLines.push_back(bLine); } @@ -302,15 +264,16 @@ std::vector > KameleonWrapper::getFieldLines( std::vector KameleonWrapper::traceCartesianFieldline( const std::string& xVar, const std::string& yVar, - const std::string& zVar, glm::vec3 seedPoint, TraceDirection direction) { + const std::string& zVar, glm::vec3 seedPoint, + float stepSize, TraceDirection direction) { glm::vec3 pos, k1, k2, k3, k4; std::vector line; - float stepX = 0.5, stepY = 0.5, stepZ = 0.5; + float stepX = stepSize, stepY = stepSize, stepZ = stepSize; // Should I do different stepsizes? int numSteps = 0; - int maxSteps = 1000; + int maxSteps = 5000; pos = seedPoint; // While we are inside the models boundries and not inside earth From d5e6063670937ff7a56a3e4153a541977c6911f4 Mon Sep 17 00:00:00 2001 From: Jonas Strandstedt Date: Tue, 10 Jun 2014 11:40:49 -0400 Subject: [PATCH 18/49] Bugfixes - Added support for volume caching - Fixed bug when moving camera in the direction or the origin causing position lock - Fixed camera being to only being affected on SGCT_PRESS and SGCT_REPEAT --- config/sgct/single.xml | 3 +- .../openspace/rendering/renderablevolumegl.h | 2 + shaders/ABuffer/abufferResolveFragment.glsl | 115 ++++++----- shaders/ABuffer/abufferSort.hglsl | 2 + shaders/exitpoints.frag | 2 +- src/abuffer/abufferSingleLinked.cpp | 19 +- src/interaction/interactionhandler.cpp | 133 ++++++------- src/rendering/renderablefieldlines.cpp | 2 +- src/rendering/renderablevolume.cpp | 178 +++++++++++------- src/rendering/renderablevolumegl.cpp | 16 ++ 10 files changed, 285 insertions(+), 187 deletions(-) diff --git a/config/sgct/single.xml b/config/sgct/single.xml index 63abb4989c..87e59f7b28 100644 --- a/config/sgct/single.xml +++ b/config/sgct/single.xml @@ -6,7 +6,8 @@ - + + diff --git a/include/openspace/rendering/renderablevolumegl.h b/include/openspace/rendering/renderablevolumegl.h index b6b261ebe7..4aaed2a6c0 100644 --- a/include/openspace/rendering/renderablevolumegl.h +++ b/include/openspace/rendering/renderablevolumegl.h @@ -59,8 +59,10 @@ public: private: ghoul::Dictionary _hintsDictionary; std::string _filename; + std::string _transferFunctionPath; float _stepSize; ghoul::opengl::Texture* _volume; + ghoul::opengl::Texture* _transferFunction; ghoul::opengl::ProgramObject* _twopassProgram; GLuint _screenQuad; diff --git a/shaders/ABuffer/abufferResolveFragment.glsl b/shaders/ABuffer/abufferResolveFragment.glsl index af95d73951..c3fe4d24f0 100644 --- a/shaders/ABuffer/abufferResolveFragment.glsl +++ b/shaders/ABuffer/abufferResolveFragment.glsl @@ -2,12 +2,14 @@ // uniforms uniform sampler3D volume; +uniform sampler1D transferFunction; in vec2 texCoord; out vec4 color; // settings -#define ALPHA_LIMIT 1.0 +#define ALPHA_LIMIT 0.98 +#define LOOP_LIMIT 200 #define MAX_FRAGMENTS 16 #define MAX_VOLUMES 4 @@ -15,6 +17,7 @@ out vec4 color; ABufferStruct_t fragments[MAX_FRAGMENTS]; vec3 volume_direction[MAX_VOLUMES]; float volume_length[MAX_VOLUMES]; +vec2 volume_zlength[MAX_VOLUMES]; vec3 volume_position[MAX_VOLUMES]; #include "abufferSort.hglsl" @@ -27,13 +30,13 @@ vec4 blend(vec4 src, vec4 dst) { return o; //return mix(src, dst, dst.a*(1.0f - src.a)); } -/* -void blend(inout vec4 dst, in vec4 src, in float stepSize) { + +void blendStep(inout vec4 dst, in vec4 src, in float stepSize) { src.a = 1.0 - pow(1.0 - src.a, stepSize ); dst.rgb = dst.rgb + (1.0 - dst.a) * src.a * src.rgb; dst.a = dst.a + (1.0 -dst.a) * src.a; } - +/* //Color geometry void blendGeometry(inout vec4 color, ABufferStruct_t frag) { //vec4 c; @@ -51,75 +54,83 @@ vec4 calculate_final_color(uint frag_count) { int currentVolumeBitmask = 0; vec4 final_color = vec4(0); - // if(frag_count == 1 && _type_(fragments[0]) == 0) { - // blendGeometry(final_color, fragments[0]); - // return final_color; - // } + if(frag_count == 1 && _type_(fragments[0]) == 0) { + final_color = blend(final_color, _col_(fragments[0])); + return final_color; + } - int frag_count_1 = int(frag_count); + int frag_count_1 = int(frag_count)-1; for(int i = 0; i < frag_count_1 && final_color.a < ALPHA_LIMIT; i++) { //int maxFrags = int(frag_count)-1; //for(int i = 0; i < frag_count; i++) { ABufferStruct_t startFrag = fragments[i]; - //ABufferStruct_t endFrag = fragments[i+1]; + ABufferStruct_t endFrag = fragments[i+1]; //vec4 frag_color = _col_(startFrag); //vec4 position = _pos_(startFrag); int type = int(_type_(startFrag)); - - - if(type != 0) { - currentVolumeBitmask = currentVolumeBitmask ^ (1 << type); - if(currentVolumeBitmask != 0) { - float p = 0.0f; - const float stepSize = 0.01; - float l = volume_length[type-1]; - vec3 direction = volume_direction[type-1]; - vec3 position; - vec4 tmp, color = vec4(0); - while(p < l) { - position = volume_position[type-1] + direction*p; - tmp = texture(volume, position); - color = max(color, tmp); - p+= stepSize; - } - vec4 volume_color = vec4(color.r,color.r,color.r,color.r*2.0); - final_color = blend(final_color, volume_color); - } - /* - const vec3 direction = volume_direction[type-1]; - const float l = pscLength(_pos_(fragments[i+1]), _pos_(fragments[i])); - const float stepSize = 0.01; - const float iterationsStop = l / volume_length[type-1]; - //const int iterations = 100; - float p = 0.0f; - int maxit = 500; - int it = 0; - while(p < iterationsStop && it < maxit) { - vec4 sample_color = vec4(0.1, 0.0, 0.0, 0.1); - blend(final_color, sample_color, stepSize); - - p+=stepSize; - ++it; - } - */ - } else { + currentVolumeBitmask = currentVolumeBitmask ^ (type); + + if(type == 0) final_color = blend(final_color, _col_(startFrag)); - //blendGeometry(final_color, startFrag); + + if(bool(currentVolumeBitmask)) { + int volID = type -1; + float p = 0.0f; + + const float stepSize = 0.01; + //const float l = volume_length[volID]; + const float S1 = volume_zlength[volID].x; + const float S2 = volume_zlength[volID].y; + const float L = S1 - S2; + const float l = (_z_(startFrag) - S1) / L - (_z_(endFrag) - S1) / L; + const vec3 direction = volume_direction[volID]; + int iterations = 0; + vec3 position; + + // MIP + // vec4 tmp, color = vec4(0); + // while(p < l && iterations < LOOP_LIMIT) { + // tmp = texture(volume, volume_position[volID]); + // color = max(color, tmp); + // p+= stepSize; + // volume_position[volID] += direction*stepSize; + // ++iterations; + // } + // vec4 volume_color = vec4(color.r,color.r,color.r,color.r*2.0); + // if(volume_color.a < 0.1) volume_color = vec4(0.0,0.0,0.0,0.0); + // final_color = blend(final_color, volume_color); + + + // TransferFunction + vec4 color = vec4(0); + float intensity; + while(p < l && iterations < LOOP_LIMIT) { + intensity = length(texture(volume, volume_position[volID])); + color = texture(transferFunction, intensity); + blendStep(final_color, color, stepSize); + //final_color = blend(final_color, color*stepSize); + p+= stepSize; + volume_position[volID] += direction*stepSize; + ++iterations; + } + } + + //blendGeometry(final_color, startFrag); //if(i == maxFrags -1 && _type_(endFrag) == 0) // blendGeometry(final_color, endFrag); // final_color = blend(final_color, frag_color); - //if(i == frag_count_1 && _type_(endFrag) == 0) - // final_color = blend(final_color, _col_(endFrag)); + if(i == frag_count_1 -1 && _type_(endFrag) == 0) + final_color = blend(final_color, _col_(endFrag)); } // final_color = vec4(0); - // int id =0; + // int id =3; // if(id < frag_count)final_color = blend(final_color, _col_(fragments[id])); return final_color; diff --git a/shaders/ABuffer/abufferSort.hglsl b/shaders/ABuffer/abufferSort.hglsl index 4ec61e9cb8..71e8534100 100644 --- a/shaders/ABuffer/abufferSort.hglsl +++ b/shaders/ABuffer/abufferSort.hglsl @@ -62,12 +62,14 @@ void sort_fragments_list(uint frag_count) { if(start) { startColor = _col_(fragments[jj]).rgb; startPosition = _pos_(fragments[jj]); + volume_zlength[ii].x = _z_(fragments[jj]); start = false; } else { vec3 dir = _col_(fragments[jj]).rgb - startColor; volume_direction[ii] = normalize(dir); volume_position[ii] = startColor; volume_length[ii] = length(dir); + volume_zlength[ii].y = _z_(fragments[jj]); //volume_length[ii] = pscLength(_pos_(fragments[jj]), startPosition); break; } diff --git a/shaders/exitpoints.frag b/shaders/exitpoints.frag index 606bfeff10..fee208094a 100644 --- a/shaders/exitpoints.frag +++ b/shaders/exitpoints.frag @@ -12,7 +12,7 @@ void main() { ABufferStruct_t frag; _col_(frag, fragColor); - _z_(frag, gl_FragDepth); + _z_(frag, gl_FragCoord.z); _type_(frag, 1); _pos_(frag, vec4(worldPosition,0)); addToBuffer(frag); diff --git a/src/abuffer/abufferSingleLinked.cpp b/src/abuffer/abufferSingleLinked.cpp index 727a023015..b28948c5d4 100644 --- a/src/abuffer/abufferSingleLinked.cpp +++ b/src/abuffer/abufferSingleLinked.cpp @@ -121,6 +121,8 @@ bool ABufferSingleLinked::initialize() { LERROR("Could not link shader"); return false; } + resolveShader->setUniform("volume", 0); + resolveShader->setUniform("transferFunction", 1); // ============================ // GEOMETRY (quad) @@ -170,12 +172,21 @@ void ABufferSingleLinked::preRender() { void ABufferSingleLinked::postRender() { - ghoul::opengl::Texture* volume; + ghoul::opengl::Texture* volume = nullptr; + ghoul::opengl::Texture* tf = nullptr; OsEng.configurationManager().getValue("firstVolume", volume); + OsEng.configurationManager().getValue("firstTransferFunction", tf); resolveShader->activate(); - glActiveTexture(GL_TEXTURE0); - volume->bind(); - resolveShader->setUniform("volume", 0); + + if(volume) { + glActiveTexture(GL_TEXTURE0); + volume->bind(); + } + + if(tf) { + glActiveTexture(GL_TEXTURE1); + tf->bind(); + } //resolveShader->setUniform("SCREEN_WIDTH", width); //resolveShader->setUniform("SCREEN_HEIGHT", height); glBindVertexArray(_screenQuad); diff --git a/src/interaction/interactionhandler.cpp b/src/interaction/interactionhandler.cpp index b9a18a634e..fc7cb4ba9c 100644 --- a/src/interaction/interactionhandler.cpp +++ b/src/interaction/interactionhandler.cpp @@ -173,19 +173,21 @@ void InteractionHandler::distance(const PowerScaledScalar &distance) { lockControls(); psc relative = camera_->position(); - psc origin; - if(node_) { - origin = node_->getWorldPosition(); - } + const psc origin = (node_) ? node_->getWorldPosition() : psc(); psc relative_origin_coordinate = relative - origin; - glm::vec3 dir(relative_origin_coordinate.direction()); - dir = dir * distance[0]; - relative_origin_coordinate = dir; + const glm::vec3 dir(relative_origin_coordinate.direction()); + glm:: vec3 newdir = dir * distance[0]; + relative_origin_coordinate = newdir; relative_origin_coordinate[3] = distance[1]; relative = relative + relative_origin_coordinate; - camera_->setPosition(relative); + relative_origin_coordinate = relative - origin; + newdir = relative_origin_coordinate.direction(); + + // update only if on the same side of the origin + if(glm::angle(newdir, dir) < 90.0f) + camera_->setPosition(relative); unlockControls(); } @@ -303,62 +305,65 @@ void InteractionHandler::keyboardCallback(int key, int action) { // TODO package in script const double speed = 2.75; const double dt = getDt(); - if (key == 'S') { - glm::vec3 euler(speed * dt, 0.0, 0.0); - glm::quat rot = glm::quat(euler); - orbit(rot); - } - if (key == 'W') { - glm::vec3 euler(-speed * dt, 0.0, 0.0); - glm::quat rot = glm::quat(euler); - orbit(rot); - } - if (key == 'A') { - glm::vec3 euler(0.0, -speed * dt, 0.0); - glm::quat rot = glm::quat(euler); - orbit(rot); - } - if (key == 'D') { - glm::vec3 euler(0.0, speed * dt, 0.0); - glm::quat rot = glm::quat(euler); - orbit(rot); - } - if (key == 262) { - glm::vec3 euler(0.0, speed * dt, 0.0); - glm::quat rot = glm::quat(euler); - rotate(rot); - } - if (key == 263) { - glm::vec3 euler(0.0, -speed * dt, 0.0); - glm::quat rot = glm::quat(euler); - rotate(rot); - } - if (key == 264) { - glm::vec3 euler(speed * dt, 0.0, 0.0); - glm::quat rot = glm::quat(euler); - rotate(rot); - } - if (key == 265) { - glm::vec3 euler(-speed * dt, 0.0, 0.0); - glm::quat rot = glm::quat(euler); - rotate(rot); - } - if (key == 'R') { - PowerScaledScalar dist(-speed * dt, 0.0); - distance(dist); - } - if (key == 'F') { - PowerScaledScalar dist(speed * dt, 0.0); - distance(dist); - } - if (key == 'T') { - PowerScaledScalar dist(-speed * 100.0 * dt, 0.0); - distance(dist); - } - if (key == 'G') { - PowerScaledScalar dist(speed * 100.0 * dt, 0.0); - distance(dist); - } + + if(action == SGCT_PRESS || action == SGCT_REPEAT) { + if (key == 'S') { + glm::vec3 euler(speed * dt, 0.0, 0.0); + glm::quat rot = glm::quat(euler); + orbit(rot); + } + if (key == 'W') { + glm::vec3 euler(-speed * dt, 0.0, 0.0); + glm::quat rot = glm::quat(euler); + orbit(rot); + } + if (key == 'A') { + glm::vec3 euler(0.0, -speed * dt, 0.0); + glm::quat rot = glm::quat(euler); + orbit(rot); + } + if (key == 'D') { + glm::vec3 euler(0.0, speed * dt, 0.0); + glm::quat rot = glm::quat(euler); + orbit(rot); + } + if (key == 262) { + glm::vec3 euler(0.0, speed * dt, 0.0); + glm::quat rot = glm::quat(euler); + rotate(rot); + } + if (key == 263) { + glm::vec3 euler(0.0, -speed * dt, 0.0); + glm::quat rot = glm::quat(euler); + rotate(rot); + } + if (key == 264) { + glm::vec3 euler(speed * dt, 0.0, 0.0); + glm::quat rot = glm::quat(euler); + rotate(rot); + } + if (key == 265) { + glm::vec3 euler(-speed * dt, 0.0, 0.0); + glm::quat rot = glm::quat(euler); + rotate(rot); + } + if (key == 'R') { + PowerScaledScalar dist(-speed * dt, 0.0); + distance(dist); + } + if (key == 'F') { + PowerScaledScalar dist(speed * dt, 0.0); + distance(dist); + } + if (key == 'T') { + PowerScaledScalar dist(-speed * 100.0 * dt, 0.0); + distance(dist); + } + if (key == 'G') { + PowerScaledScalar dist(speed * 100.0 * dt, 0.0); + distance(dist); + } + } /* if (key == '1') { SceneGraphNode* node = getSceneGraphNode("sun"); diff --git a/src/rendering/renderablefieldlines.cpp b/src/rendering/renderablefieldlines.cpp index b19740d54d..866a76df1d 100644 --- a/src/rendering/renderablefieldlines.cpp +++ b/src/rendering/renderablefieldlines.cpp @@ -186,7 +186,7 @@ void RenderableFieldlines::render(const Camera* camera, const psc& thisPosition) transform = transform*camTransform; transform = glm::translate(transform, relative.vec3()); - transform = glm::scale(transform, glm::vec3(0.1)); + transform = glm::scale(transform, glm::vec3(0.036*0.5*0.5)); _shaderMutex->lock(); _fieldlinesProgram->activate(); diff --git a/src/rendering/renderablevolume.cpp b/src/rendering/renderablevolume.cpp index c5ee3d6b16..dd741cc8b1 100644 --- a/src/rendering/renderablevolume.cpp +++ b/src/rendering/renderablevolume.cpp @@ -89,63 +89,115 @@ ghoul::opengl::Texture* RenderableVolume::loadVolume(const std::string& filepath return rawReader.read(filepath); } else if(hasExtension(filepath, "cdf")) { - std::string modelString; - if (hintsDictionary.hasKey("Model") && hintsDictionary.getValue("Model", modelString)) { - KameleonWrapper::Model model; - if (modelString == "BATSRUS") { - model = KameleonWrapper::Model::BATSRUS; - } else if (modelString == "ENLIL") { - model = KameleonWrapper::Model::ENLIL; + glm::size3_t dimensions(1,1,1); + double tempValue; + if (hintsDictionary.hasKey("Dimensions.1") && hintsDictionary.getValue("Dimensions.1", tempValue)) { + int intVal = static_cast(tempValue); + if(intVal > 0) + dimensions[0] = intVal; + } + if (hintsDictionary.hasKey("Dimensions.2") && hintsDictionary.getValue("Dimensions.2", tempValue)) { + int intVal = static_cast(tempValue); + if(intVal > 0) + dimensions[1] = intVal; + } + if (hintsDictionary.hasKey("Dimensions.3") && hintsDictionary.getValue("Dimensions.3", tempValue)) { + int intVal = static_cast(tempValue); + if(intVal > 0) + dimensions[2] = intVal; + } + + std::string modelString = ""; + if (hintsDictionary.hasKey("Model")) + hintsDictionary.getValue("Model", modelString); + + if(modelString == "") { + LWARNING("Model not specified."); + return nullptr; + } + + std::string variableCacheString = ""; + if (hintsDictionary.hasKey("Variable")) { + hintsDictionary.getValue("Variable", variableCacheString); + } else if(hintsDictionary.hasKey("Variables")) { + std::string xVariable, yVariable, zVariable; + bool xVar, yVar, zVar; + xVar = hintsDictionary.getValue("Variables.1", xVariable); + yVar = hintsDictionary.getValue("Variables.2", yVariable); + zVar = hintsDictionary.getValue("Variables.3", zVariable); + if (xVar && yVar && zVar) { + variableCacheString = xVariable + "." + yVariable + "." + zVariable; + } + } + + bool cache = false; + hintsDictionary.hasKey("Cache"); + if (hintsDictionary.hasKey("Cache")) + hintsDictionary.getValue("Cache", cache); + + std::stringstream ss; + ss << "." << dimensions[0] << "x" << dimensions[1] << "x" << dimensions[2] << "." << modelString << "." << variableCacheString << ".cache"; + std::string cachepath = filepath + ss.str(); + if( cache && FileSys.fileExists(cachepath)) { + + FILE* file = fopen (cachepath.c_str(), "rb"); + + int length = dimensions[0] *dimensions[1] *dimensions[2]; + float* data = new float[length]; + + for(int i = 0; i< length; i++){ + float f; + fread(&f, sizeof(float), 1, file); + data[i] = f; + } + + fclose(file); + return new ghoul::opengl::Texture(data, dimensions, ghoul::opengl::Texture::Format::Red, GL_RED, GL_FLOAT, ghoul::opengl::Texture::FilterMode::Linear, ghoul::opengl::Texture::WrappingMode::ClampToBorder); + } + + KameleonWrapper::Model model; + if (modelString == "BATSRUS") { + model = KameleonWrapper::Model::BATSRUS; + } else if (modelString == "ENLIL") { + model = KameleonWrapper::Model::ENLIL; + } else { + LWARNING("Hints does not specify a valid 'Model'"); + return nullptr; + } + + KameleonWrapper kw(filepath, model); + + std::string variableString; + if (hintsDictionary.hasKey("Variable") && hintsDictionary.getValue("Variable", variableString)) { + float* data = kw.getUniformSampledValues(variableString, dimensions); + if(cache) { + FILE* file = fopen (cachepath.c_str(), "wb"); + int length = dimensions[0] *dimensions[1] *dimensions[2]; + fwrite(data, sizeof(float), length, file); + fclose(file); + } + return new ghoul::opengl::Texture(data, dimensions, ghoul::opengl::Texture::Format::Red, GL_RED, GL_FLOAT, ghoul::opengl::Texture::FilterMode::Linear, ghoul::opengl::Texture::WrappingMode::ClampToBorder); + + } else if (hintsDictionary.hasKey("Variables")) { + std::string xVariable, yVariable, zVariable; + bool xVar, yVar, zVar; + xVar = hintsDictionary.getValue("Variables.1", xVariable); + yVar = hintsDictionary.getValue("Variables.2", yVariable); + zVar = hintsDictionary.getValue("Variables.3", zVariable); + + if (!xVar || !yVar || !zVar) { + LERROR("Error reading variables! Must be 3 and must exist in CDF data"); } else { - LWARNING("Hints does not specify a valid 'Model'"); - return nullptr; - } - glm::size3_t dimensions(1,1,1); - double tempValue; - if (hintsDictionary.hasKey("Dimensions.1") && hintsDictionary.getValue("Dimensions.1", tempValue)) { - int intVal = static_cast(tempValue); - if(intVal > 0) - dimensions[0] = intVal; - } - if (hintsDictionary.hasKey("Dimensions.2") && hintsDictionary.getValue("Dimensions.2", tempValue)) { - int intVal = static_cast(tempValue); - if(intVal > 0) - dimensions[1] = intVal; - } - if (hintsDictionary.hasKey("Dimensions.3") && hintsDictionary.getValue("Dimensions.3", tempValue)) { - int intVal = static_cast(tempValue); - if(intVal > 0) - dimensions[2] = intVal; - } - - KameleonWrapper kw(filepath, model); - - std::string variableString; - if (hintsDictionary.hasKey("Variable") && hintsDictionary.getValue("Variable", variableString)) { - float* data = kw.getUniformSampledValues(variableString, dimensions); - return new ghoul::opengl::Texture(data, dimensions, ghoul::opengl::Texture::Format::Red, GL_RED, GL_FLOAT); - - } else if (hintsDictionary.hasKey("Variables")) { - std::string xVariable, yVariable, zVariable; - bool xVar, yVar, zVar; - xVar = hintsDictionary.getValue("Variables.1", xVariable); - yVar = hintsDictionary.getValue("Variables.2", yVariable); - zVar = hintsDictionary.getValue("Variables.3", zVariable); - - if (!xVar || !yVar || !zVar) { - LERROR("Error reading variables! Must be 3 and must exist in CDF data"); - } else { - - // Seed 'em all - std::vector seedPoints; + // Seed 'em all + std::vector seedPoints; // seedPoints.push_back(glm::vec3(5.0, 0.0, 0.0)); - for (int z = -5; z <= 5; z+=5) { - for (int y = -5; y <= 5; y+=5) - seedPoints.push_back(glm::vec3(5.0, (float)y, (float)z)); - } + for (int z = -5; z <= 5; z+=5) { + for (int y = -5; y <= 5; y+=5) + seedPoints.push_back(glm::vec3(5.0, (float)y, (float)z)); + } - float* fieldlinesData = kw.getVolumeFieldLines(xVariable, yVariable, zVariable, dimensions, seedPoints); + float* fieldlinesData = kw.getVolumeFieldLines(xVariable, yVariable, zVariable, dimensions, seedPoints); // float* rhoData = kw.getUniformSampledValues("rho", dimensions); // // // Combine fieldlines with rhoData, clamp to [0,1] @@ -156,15 +208,12 @@ ghoul::opengl::Texture* RenderableVolume::loadVolume(const std::string& filepath // delete fieldlinesData; // delete rhoData; - return new ghoul::opengl::Texture(fieldlinesData, dimensions, ghoul::opengl::Texture::Format::Red, GL_RED, GL_FLOAT); - } - - } else { - LWARNING("Hints does not specify a 'Variable' or 'Variables'"); + return new ghoul::opengl::Texture(fieldlinesData, dimensions, ghoul::opengl::Texture::Format::Red, GL_RED, GL_FLOAT); } + } else { + LWARNING("Hints does not specify a 'Variable' or 'Variables'"); } - LWARNING("Hints does not specify a 'Model'"); } else { LWARNING("No valid file extension."); } @@ -371,13 +420,14 @@ ghoul::opengl::Texture* RenderableVolume::loadTransferFunction(const std::string //LDEBUG("["<< position <<"] " << value); } -// LDEBUG(weight << ", (" << -// transferFunction[4*i+0] << ", " << -// transferFunction[4*i+1] << ", " << -// transferFunction[4*i+2] << ", " << -// transferFunction[4*i+3] << ")"); + LDEBUG(weight << ", (" << + transferFunction[4*i+0] << ", " << + transferFunction[4*i+1] << ", " << + transferFunction[4*i+2] << ", " << + transferFunction[4*i+3] << ")"); } + return new ghoul::opengl::Texture(transferFunction, glm::size3_t(width,1,1),ghoul::opengl::Texture::Format::RGBA, GL_RGBA, GL_FLOAT);; diff --git a/src/rendering/renderablevolumegl.cpp b/src/rendering/renderablevolumegl.cpp index d002dbea9f..cb52808d40 100644 --- a/src/rendering/renderablevolumegl.cpp +++ b/src/rendering/renderablevolumegl.cpp @@ -85,6 +85,18 @@ RenderableVolumeGL::RenderableVolumeGL(const ghoul::Dictionary& dictionary): _twopassProgram->attachObject(fragmentShader); } } + + _transferFunction = nullptr; + if (dictionary.hasKey("TransferFunction")) { + std::string transferFunctionPath = ""; + if(dictionary.getValue("TransferFunction", transferFunctionPath)) { + _transferFunctionPath = findPath(transferFunctionPath); + } + } + if( _transferFunctionPath == "") { + LERROR("No transferFunction!"); + } + if(dictionary.hasKey("UpdateOnSave")) { dictionary.getValue("UpdateOnSave", _programUpdateOnSave); @@ -121,7 +133,10 @@ bool RenderableVolumeGL::initialize() { // ------ VOLUME READING ---------------- _volume = loadVolume(_filename, _hintsDictionary); _volume->uploadTexture(); + _transferFunction = loadTransferFunction(_transferFunctionPath); + _transferFunction->uploadTexture(); OsEng.configurationManager().setValue("firstVolume", _volume); + OsEng.configurationManager().setValue("firstTransferFunction", _transferFunction); //glBindImageTexture(2, *_volume, 0, GL_FALSE, 0, GL_READ_ONLY, _volume->type()); // ------ SETUP GEOMETRY ---------------- @@ -189,6 +204,7 @@ void RenderableVolumeGL::render(const Camera *camera, const psc &thisPosition) { transform = camTransform; transform = glm::translate(transform, relative.vec3()); + transform = glm::translate(transform, glm::vec3(-1.1,0.0,0.0)); transform = glm::scale(transform, _boxScaling); _colorBoxRenderer->render(camera->viewProjectionMatrix(), transform); From 6f40de5f376cb485ba22c05f0f085fb8a19b6517 Mon Sep 17 00:00:00 2001 From: Hans-Christian Helltegen Date: Tue, 10 Jun 2014 16:59:47 -0400 Subject: [PATCH 19/49] Added classification of fieldlines (closed, open from north, open from south, solar wind) and coloring after classification --- .../rendering/renderablefieldlines.h | 8 +-- include/openspace/util/kameleonwrapper.h | 9 ++- openspace-data | 2 +- src/rendering/renderablefieldlines.cpp | 68 +++++++++++++++---- src/util/kameleonwrapper.cpp | 53 +++++++++++++-- 5 files changed, 115 insertions(+), 25 deletions(-) diff --git a/include/openspace/rendering/renderablefieldlines.h b/include/openspace/rendering/renderablefieldlines.h index ade8173be8..87461bf924 100644 --- a/include/openspace/rendering/renderablefieldlines.h +++ b/include/openspace/rendering/renderablefieldlines.h @@ -56,16 +56,16 @@ private: std::string _filename; std::vector _seedPoints; - ghoul::opengl::ProgramObject* _fieldlinesProgram; - GLuint _VAO; + ghoul::opengl::ProgramObject *_fieldlinesProgram, *_seedpointsProgram; + GLuint _VAO, _seedpointVAO; std::mutex* _shaderMutex; ghoul::filesystem::File* _vertexSourceFile; ghoul::filesystem::File* _fragmentSourceFile; - std::vector _lineStart; - std::vector _lineCount; + std::vector _lineStart, _seedpointStart; + std::vector _lineCount, _seedpointCount; bool _programUpdateOnSave; void safeShaderCompilation(); diff --git a/include/openspace/util/kameleonwrapper.h b/include/openspace/util/kameleonwrapper.h index 81023772e8..4141bdec52 100644 --- a/include/openspace/util/kameleonwrapper.h +++ b/include/openspace/util/kameleonwrapper.h @@ -48,6 +48,12 @@ public: BACK = -1 }; + enum FieldlineEnd { + NORTH, + SOUTH, + OUT + }; + KameleonWrapper(const std::string& filename, Model model); ~KameleonWrapper(); float* getUniformSampledValues(const std::string& var, glm::size3_t outDimensions); @@ -61,10 +67,11 @@ public: private: std::vector traceCartesianFieldline(const std::string& xVar, const std::string& yVar, const std::string& zVar, glm::vec3 seedPoint, - float stepSize, TraceDirection direction); + float stepSize, TraceDirection direction, FieldlineEnd& end); void getGridVariables(std::string& x, std::string& y, std::string& z); void progressBar(int current, int end); + glm::vec3 classifyFieldline(FieldlineEnd fEnd, FieldlineEnd bEnd); ccmc::Model* _model; Model _type; diff --git a/openspace-data b/openspace-data index a0e8d47b2d..4d83eac48d 160000 --- a/openspace-data +++ b/openspace-data @@ -1 +1 @@ -Subproject commit a0e8d47b2dafa584c2313fe7199ce29030c5e4ae +Subproject commit 4d83eac48d185247c293ecdcda1dfc392b8fcd52 diff --git a/src/rendering/renderablefieldlines.cpp b/src/rendering/renderablefieldlines.cpp index 919d04c68d..a2f355ce8f 100644 --- a/src/rendering/renderablefieldlines.cpp +++ b/src/rendering/renderablefieldlines.cpp @@ -102,6 +102,14 @@ RenderableFieldlines::RenderableFieldlines(const ghoul::Dictionary& dictionary) } } + _seedpointsProgram = new ghoul::opengl::ProgramObject("SeedpointsProgram"); + ghoul::opengl::ShaderObject* seedpointVertexShader = new ghoul::opengl::ShaderObject(ghoul::opengl::ShaderObject::ShaderTypeVertex, + "/home/hhellteg/openspace/openspace-data/scene/fieldlines/seedPoints.vert"); + ghoul::opengl::ShaderObject* seedpointFragmentShader = new ghoul::opengl::ShaderObject(ghoul::opengl::ShaderObject::ShaderTypeFragment, + "/home/hhellteg/openspace/openspace-data/scene/fieldlines/seedPoints.frag"); + _seedpointsProgram->attachObject(seedpointVertexShader); + _seedpointsProgram->attachObject(seedpointFragmentShader); + if(dictionary.hasKey("UpdateOnSave")) { dictionary.getValue("UpdateOnSave", _programUpdateOnSave); } @@ -118,15 +126,6 @@ bool RenderableFieldlines::initialize() { assert(_hintsDictionary.size() != 0); assert(_seedPoints.size() != 0); - std::vector seedPoints; - for (int x = -6; x <= 6; x+=3) { - for (int y = -6; y <= 6; y+=3) { - for (int z = -6; z <= 6; z+=3) { - seedPoints.push_back(glm::vec3((float)x, (float)y, (float)z)); - } - } - } - std::string modelString; std::vector > fieldlinesData; float stepSize; @@ -173,12 +172,16 @@ bool RenderableFieldlines::initialize() { for (int i = 0; i < fieldlinesData.size(); i++) { _lineStart.push_back(prevEnd); - _lineCount.push_back(fieldlinesData[i].size()); - prevEnd = prevEnd + fieldlinesData[i].size(); + _lineCount.push_back(fieldlinesData[i].size()/2.0); + prevEnd = prevEnd + fieldlinesData[i].size()/2.0; + + _seedpointStart.push_back(i); + _seedpointCount.push_back(1); vertexData.insert( vertexData.end(), fieldlinesData[i].begin(), fieldlinesData[i].end()); } + // ------ FIELDLINES ----------------- GLuint vertexPositionBuffer; glGenVertexArrays(1, &_VAO); // generate array glBindVertexArray(_VAO); // bind array @@ -189,11 +192,32 @@ bool RenderableFieldlines::initialize() { // Vertex positions GLuint vertexLocation = 0; glEnableVertexAttribArray(vertexLocation); - glVertexAttribPointer(vertexLocation, 3, GL_FLOAT, GL_FALSE, 3*sizeof(GLfloat), reinterpret_cast(0)); + glVertexAttribPointer(vertexLocation, 3, GL_FLOAT, GL_FALSE, 2*sizeof(glm::vec3), reinterpret_cast(0)); + + // Texture coordinates + GLuint texcoordLocation = 1; + glEnableVertexAttribArray(texcoordLocation); + glVertexAttribPointer(texcoordLocation, 3, GL_FLOAT, GL_FALSE, 2*sizeof(glm::vec3), (void*)(sizeof(glm::vec3))); glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind buffer glBindVertexArray(0); //unbind array +// // ------ SEEDPOINTS ----------------- +// GLuint seedpointPositionBuffer; +// glGenVertexArrays(1, &_seedpointVAO); // generate array +// glBindVertexArray(_seedpointVAO); // bind array +// glGenBuffers(1, &seedpointPositionBuffer); // generate buffer +// glBindBuffer(GL_ARRAY_BUFFER, seedpointPositionBuffer); // bind buffer +// glBufferData(GL_ARRAY_BUFFER, _seedPoints.size()*sizeof(glm::vec3), &_seedPoints.front(), GL_STATIC_DRAW); +// +// // Vertex positions +// GLuint seedpointLocation = 0; +// glEnableVertexAttribArray(seedpointLocation); +// glVertexAttribPointer(seedpointLocation, 3, GL_FLOAT, GL_FALSE, 3*sizeof(GLfloat), reinterpret_cast(0)); +// +// glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind buffer +// glBindVertexArray(0); //unbind array + // ------ SETUP SHADERS ----------------- auto privateCallback = [this](const ghoul::filesystem::File& file) { safeShaderCompilation(); @@ -206,6 +230,9 @@ bool RenderableFieldlines::initialize() { _fieldlinesProgram->compileShaderObjects(); _fieldlinesProgram->linkProgramObject(); + _seedpointsProgram->compileShaderObjects(); + _seedpointsProgram->linkProgramObject(); + return true; } @@ -220,20 +247,33 @@ void RenderableFieldlines::render(const Camera* camera, const psc& thisPosition) transform = transform*camTransform; transform = glm::translate(transform, relative.vec3()); - transform = glm::rotate(transform, 90.0f, glm::vec3(1.0, 0.0, 0.0)); + transform = glm::rotate(transform, -90.0f, glm::vec3(1.0, 0.0, 0.0)); transform = glm::scale(transform, glm::vec3(0.1)); + // ------ FIELDLINES ----------------- _shaderMutex->lock(); _fieldlinesProgram->activate(); _fieldlinesProgram->setUniform("modelViewProjection", transform); - glBindVertexArray(_VAO); glMultiDrawArrays(GL_LINE_STRIP, &_lineStart[0], &_lineCount[0], _lineStart.size()); glBindVertexArray(0); _fieldlinesProgram->deactivate(); _shaderMutex->unlock(); + +// // ------ SEEDPOINTS ----------------- +// _shaderMutex->lock(); +// _seedpointsProgram->activate(); +// _seedpointsProgram->setUniform("modelViewProjection", transform); +// +// glBindVertexArray(_seedpointVAO); +// glPointSize(3); +// glMultiDrawArrays(GL_POINTS, &_seedpointStart[0], &_seedpointCount[0], _seedPoints.size()); +// glBindVertexArray(0); +// +// _seedpointsProgram->deactivate(); +// _shaderMutex->unlock(); } void RenderableFieldlines::update() { diff --git a/src/util/kameleonwrapper.cpp b/src/util/kameleonwrapper.cpp index 0a4a1f5b21..985c4328bb 100644 --- a/src/util/kameleonwrapper.cpp +++ b/src/util/kameleonwrapper.cpp @@ -34,6 +34,7 @@ #include #include #include +#include namespace openspace { @@ -247,13 +248,26 @@ std::vector > KameleonWrapper::getFieldLines( std::vector fLine, bLine; std::vector > fieldLines; + glm::vec3 color; + FieldlineEnd forwardEnd, backEnd; if (_type == Model::BATSRUS) { for (glm::vec3 seedPoint : seedPoints) { - fLine = traceCartesianFieldline(xVar, yVar, zVar, seedPoint, stepSize, TraceDirection::FORWARD); - bLine = traceCartesianFieldline(xVar, yVar, zVar, seedPoint, stepSize, TraceDirection::BACK); + fLine = traceCartesianFieldline(xVar, yVar, zVar, seedPoint, stepSize, TraceDirection::FORWARD, forwardEnd); + bLine = traceCartesianFieldline(xVar, yVar, zVar, seedPoint, stepSize, TraceDirection::BACK, backEnd); bLine.insert(bLine.begin(), fLine.rbegin(), fLine.rend()); - fieldLines.push_back(bLine); + + // classify + color = classifyFieldline(forwardEnd, backEnd); + + // write colors + std::vector line; + for (glm::vec3 position : bLine) { + line.push_back(position); + line.push_back(color); + } + + fieldLines.push_back(line); } } else { LERROR("Fieldlines are only supported for BATSRUS model"); @@ -265,9 +279,9 @@ std::vector > KameleonWrapper::getFieldLines( std::vector KameleonWrapper::traceCartesianFieldline( const std::string& xVar, const std::string& yVar, const std::string& zVar, glm::vec3 seedPoint, - float stepSize, TraceDirection direction) { + float stepSize, TraceDirection direction, FieldlineEnd& end) { - glm::vec3 pos, k1, k2, k3, k4; + glm::vec3 color, pos, k1, k2, k3, k4; std::vector line; float stepX = stepSize, stepY = stepSize, stepZ = stepSize; // Should I do different stepsizes? @@ -311,6 +325,14 @@ std::vector KameleonWrapper::traceCartesianFieldline( break; } } + + if (pos.z > 0.0 && pos.x < 1.0 && pos.x > -1.0 && pos.y < 1.0 && pos.y > -1.0) + end = FieldlineEnd::NORTH; + else if (pos.z < 0.0 && pos.x < 1.0 && pos.x > -1.0 && pos.y < 1.0 && pos.y > -1.0) + end = FieldlineEnd::SOUTH; + else + end = FieldlineEnd::OUT; + return line; } @@ -354,4 +376,25 @@ void KameleonWrapper::progressBar(int current, int end) { _lastiProgress = iprogress; } +glm::vec3 KameleonWrapper::classifyFieldline(FieldlineEnd fEnd, FieldlineEnd bEnd) { + glm::vec3 color; + if ( (fEnd == FieldlineEnd::NORTH || fEnd == FieldlineEnd::SOUTH) + && (bEnd == FieldlineEnd::NORTH || bEnd == FieldlineEnd::SOUTH)) { + // closed + color = glm::vec3(1.0, 0.0, 0.0); + } else if ((fEnd == FieldlineEnd::OUT && bEnd == FieldlineEnd::NORTH) + || (bEnd == FieldlineEnd::OUT && fEnd == FieldlineEnd::NORTH)) { + // north + color = glm::vec3(1.0, 1.0, 0.0); + } else if ((fEnd == FieldlineEnd::OUT && bEnd == FieldlineEnd::SOUTH) + || (bEnd == FieldlineEnd::OUT && fEnd == FieldlineEnd::SOUTH)) { + // south + color = glm::vec3(0.0, 1.0, 0.0); + } else if (fEnd == FieldlineEnd::OUT && bEnd == FieldlineEnd::OUT) { + // solar wind + color = glm::vec3(0.0, 0.0, 1.0); + } + return color; +} + } // namespace openspace From 56c5c259fbc4c28ebdf0415761c9685f780a1359 Mon Sep 17 00:00:00 2001 From: Hans-Christian Helltegen Date: Mon, 16 Jun 2014 11:39:10 -0400 Subject: [PATCH 20/49] Added support for multiple fieldlines in a single module. Stepsize is now adaptive based on the local grid size in the model --- .../rendering/renderablefieldlines.h | 8 +- openspace-data | 2 +- src/rendering/renderablefieldlines.cpp | 190 +++++++++--------- src/util/kameleonwrapper.cpp | 57 +++--- 4 files changed, 132 insertions(+), 125 deletions(-) diff --git a/include/openspace/rendering/renderablefieldlines.h b/include/openspace/rendering/renderablefieldlines.h index 87461bf924..e26c7c2b54 100644 --- a/include/openspace/rendering/renderablefieldlines.h +++ b/include/openspace/rendering/renderablefieldlines.h @@ -52,8 +52,10 @@ public: virtual void update(); private: - ghoul::Dictionary _hintsDictionary; - std::string _filename; + std::vector > getFieldlinesData(std::string filename, ghoul::Dictionary hintsDictionary); + + std::vector _hintsDictionaries; + std::vector _filenames; std::vector _seedPoints; ghoul::opengl::ProgramObject *_fieldlinesProgram, *_seedpointsProgram; @@ -69,8 +71,6 @@ private: bool _programUpdateOnSave; void safeShaderCompilation(); - - }; } // namespace openspace diff --git a/openspace-data b/openspace-data index 4d83eac48d..afbca6e2a5 160000 --- a/openspace-data +++ b/openspace-data @@ -1 +1 @@ -Subproject commit 4d83eac48d185247c293ecdcda1dfc392b8fcd52 +Subproject commit afbca6e2a5375a5899aed4855e45d26991c0d450 diff --git a/src/rendering/renderablefieldlines.cpp b/src/rendering/renderablefieldlines.cpp index a2f355ce8f..64dab8daaa 100644 --- a/src/rendering/renderablefieldlines.cpp +++ b/src/rendering/renderablefieldlines.cpp @@ -49,23 +49,15 @@ RenderableFieldlines::RenderableFieldlines(const ghoul::Dictionary& dictionary) file = findPath(file); if (file != "") { - // parse hints + // read hints into dictionary ghoul::Dictionary hintsDictionary; if(fieldline.hasKey("Hints")) fieldline.getValue("Hints", hintsDictionary); // TODO Vectors of filenames and dictionaries - _filename = file; - _hintsDictionary = hintsDictionary; + _filenames.push_back(file); + _hintsDictionaries.push_back(hintsDictionary); - ghoul::Dictionary seedpointsDictionary; - if (fieldline.hasKey("Seedpoints") && fieldline.getValue("Seedpoints", seedpointsDictionary)) { - glm::vec3 tmpVal; - for (int i = 0; i < seedpointsDictionary.keys().size(); ++i) { - fieldline.getValue("Seedpoints."+std::to_string(i+1), tmpVal); - _seedPoints.push_back(tmpVal); - } - } } else LERROR("File not found!"); } @@ -122,65 +114,30 @@ RenderableFieldlines::~RenderableFieldlines() { } bool RenderableFieldlines::initialize() { - assert(_filename != ""); - assert(_hintsDictionary.size() != 0); - assert(_seedPoints.size() != 0); + assert(_filenames.size() != 0); + assert(_hintsDictionaries.size() != 0); - std::string modelString; - std::vector > fieldlinesData; - float stepSize; - std::string xVariable, yVariable, zVariable; - KameleonWrapper::Model model; - - if (_hintsDictionary.hasKey("Model") && _hintsDictionary.getValue("Model", modelString)) { - if (modelString == "BATSRUS") { - model = KameleonWrapper::Model::BATSRUS; - } else if (modelString == "ENLIL") { - LWARNING("ENLIL model not supported for fieldlines"); - return false; - } else { - LWARNING("Hints does not specify a valid 'Model'"); - return false; - } - - if (_hintsDictionary.hasKey("Variables")) { - bool xVar, yVar, zVar; - xVar = _hintsDictionary.getValue("Variables.1", xVariable); - yVar = _hintsDictionary.getValue("Variables.2", yVariable); - zVar = _hintsDictionary.getValue("Variables.3", zVariable); - - if (!xVar || !yVar || !zVar) { - LWARNING("Error reading variables! Must be 3 and must exist in CDF data"); - return false; - } - } else { - LWARNING("Hints does not specify valid 'Variables'"); - return false; - } - - if (!_hintsDictionary.hasKey("Stepsize") || !_hintsDictionary.getValue("Stepsize", stepSize)) { - LDEBUG("No stepsize set for fieldlines. Setting to default value (0.5)"); - stepSize = 0.5; - } - } - - KameleonWrapper kw(_filename, model); - fieldlinesData = kw.getFieldLines(xVariable, yVariable, zVariable, _seedPoints, stepSize); - - std::vector vertexData; int prevEnd = 0; + std::vector vertexData; + std::vector > fieldlinesData; - for (int i = 0; i < fieldlinesData.size(); i++) { - _lineStart.push_back(prevEnd); - _lineCount.push_back(fieldlinesData[i].size()/2.0); - prevEnd = prevEnd + fieldlinesData[i].size()/2.0; + for (int i = 0; i < _filenames.size(); ++i) { + fieldlinesData = getFieldlinesData(_filenames[i], _hintsDictionaries[i]); - _seedpointStart.push_back(i); - _seedpointCount.push_back(1); + for (int j = 0; j < fieldlinesData.size(); j++) { + _lineStart.push_back(prevEnd); + _lineCount.push_back(fieldlinesData[j].size()/2.0); + prevEnd = prevEnd + fieldlinesData[j].size()/2.0; - vertexData.insert( vertexData.end(), fieldlinesData[i].begin(), fieldlinesData[i].end()); + _seedpointStart.push_back(j); + _seedpointCount.push_back(1); + + vertexData.insert( vertexData.end(), fieldlinesData[j].begin(), fieldlinesData[j].end()); + } } + LDEBUG("Vertex orginal : " << vertexData.size()/2.0); + // ------ FIELDLINES ----------------- GLuint vertexPositionBuffer; glGenVertexArrays(1, &_VAO); // generate array @@ -203,20 +160,20 @@ bool RenderableFieldlines::initialize() { glBindVertexArray(0); //unbind array // // ------ SEEDPOINTS ----------------- -// GLuint seedpointPositionBuffer; -// glGenVertexArrays(1, &_seedpointVAO); // generate array -// glBindVertexArray(_seedpointVAO); // bind array -// glGenBuffers(1, &seedpointPositionBuffer); // generate buffer -// glBindBuffer(GL_ARRAY_BUFFER, seedpointPositionBuffer); // bind buffer -// glBufferData(GL_ARRAY_BUFFER, _seedPoints.size()*sizeof(glm::vec3), &_seedPoints.front(), GL_STATIC_DRAW); -// -// // Vertex positions -// GLuint seedpointLocation = 0; -// glEnableVertexAttribArray(seedpointLocation); -// glVertexAttribPointer(seedpointLocation, 3, GL_FLOAT, GL_FALSE, 3*sizeof(GLfloat), reinterpret_cast(0)); -// -// glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind buffer -// glBindVertexArray(0); //unbind array + GLuint seedpointPositionBuffer; + glGenVertexArrays(1, &_seedpointVAO); // generate array + glBindVertexArray(_seedpointVAO); // bind array + glGenBuffers(1, &seedpointPositionBuffer); // generate buffer + glBindBuffer(GL_ARRAY_BUFFER, seedpointPositionBuffer); // bind buffer + glBufferData(GL_ARRAY_BUFFER, _seedPoints.size()*sizeof(glm::vec3), &_seedPoints.front(), GL_STATIC_DRAW); + + // Vertex positions + GLuint seedpointLocation = 0; + glEnableVertexAttribArray(seedpointLocation); + glVertexAttribPointer(seedpointLocation, 3, GL_FLOAT, GL_FALSE, sizeof(glm::vec3), reinterpret_cast(0)); + + glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind buffer + glBindVertexArray(0); //unbind array // ------ SETUP SHADERS ----------------- auto privateCallback = [this](const ghoul::filesystem::File& file) { @@ -247,8 +204,8 @@ void RenderableFieldlines::render(const Camera* camera, const psc& thisPosition) transform = transform*camTransform; transform = glm::translate(transform, relative.vec3()); - transform = glm::rotate(transform, -90.0f, glm::vec3(1.0, 0.0, 0.0)); - transform = glm::scale(transform, glm::vec3(0.1)); + transform = glm::rotate(transform, -90.0f, glm::vec3(1.0, 0.0, 0.0)); // Model has positive Z as up + transform = glm::scale(transform, glm::vec3(0.1)); // Scale to avoid depth buffer problems // ------ FIELDLINES ----------------- _shaderMutex->lock(); @@ -262,18 +219,18 @@ void RenderableFieldlines::render(const Camera* camera, const psc& thisPosition) _fieldlinesProgram->deactivate(); _shaderMutex->unlock(); -// // ------ SEEDPOINTS ----------------- -// _shaderMutex->lock(); -// _seedpointsProgram->activate(); -// _seedpointsProgram->setUniform("modelViewProjection", transform); -// -// glBindVertexArray(_seedpointVAO); -// glPointSize(3); -// glMultiDrawArrays(GL_POINTS, &_seedpointStart[0], &_seedpointCount[0], _seedPoints.size()); -// glBindVertexArray(0); -// -// _seedpointsProgram->deactivate(); -// _shaderMutex->unlock(); + // ------ SEEDPOINTS ----------------- + _shaderMutex->lock(); + _seedpointsProgram->activate(); + _seedpointsProgram->setUniform("modelViewProjection", transform); + + glBindVertexArray(_seedpointVAO); + glPointSize(5); + glMultiDrawArrays(GL_POINTS, &_lineStart[0], &_lineCount[0], _seedPoints.size()); + glBindVertexArray(0); + + _seedpointsProgram->deactivate(); + _shaderMutex->unlock(); } void RenderableFieldlines::update() { @@ -287,4 +244,55 @@ void RenderableFieldlines::safeShaderCompilation() { _shaderMutex->unlock(); } +std::vector > RenderableFieldlines::getFieldlinesData(std::string filename, ghoul::Dictionary hintsDictionary) { + std::string modelString; + float stepSize = 0.5; // default if no stepsize is specified in hints + std::string xVariable, yVariable, zVariable; + KameleonWrapper::Model model; + std::vector > fieldlinesData; + + if (hintsDictionary.hasKey("Model") && hintsDictionary.getValue("Model", modelString)) { + if (modelString == "BATSRUS") { + model = KameleonWrapper::Model::BATSRUS; + } else if (modelString == "ENLIL") { + LWARNING("ENLIL model not supported for fieldlines"); + return fieldlinesData; + } else { + LWARNING("Hints does not specify a valid 'Model'"); + return fieldlinesData; + } + + if (hintsDictionary.hasKey("Variables")) { + bool xVar, yVar, zVar; + xVar = hintsDictionary.getValue("Variables.1", xVariable); + yVar = hintsDictionary.getValue("Variables.2", yVariable); + zVar = hintsDictionary.getValue("Variables.3", zVariable); + + if (!xVar || !yVar || !zVar) { + LWARNING("Error reading variables! Must be 3 and must exist in CDF data"); + return fieldlinesData; + } + } else { + LWARNING("Hints does not specify valid 'Variables'"); + return fieldlinesData; + } + + if (!hintsDictionary.hasKey("Stepsize") || !hintsDictionary.getValue("Stepsize", stepSize)) { + LDEBUG("No stepsize set for fieldlines. Setting to default value (" << stepSize << ")"); + } + ghoul::Dictionary seedpointsDictionary; + if (hintsDictionary.hasKey("Seedpoints") && hintsDictionary.getValue("Seedpoints", seedpointsDictionary)) { + glm::vec3 seedPos; + for (auto index : seedpointsDictionary.keys()) { + hintsDictionary.getValue("Seedpoints."+index, seedPos); + _seedPoints.push_back(seedPos); + } + } + } + + KameleonWrapper kw(filename, model); + fieldlinesData = kw.getFieldLines(xVariable, yVariable, zVariable, _seedPoints, stepSize); + return fieldlinesData; +} + } // namespace openspace diff --git a/src/util/kameleonwrapper.cpp b/src/util/kameleonwrapper.cpp index 985c4328bb..314074c0a0 100644 --- a/src/util/kameleonwrapper.cpp +++ b/src/util/kameleonwrapper.cpp @@ -63,8 +63,6 @@ KameleonWrapper::KameleonWrapper(const std::string& filename, Model model): _typ } getGridVariables(_xCoordVar, _yCoordVar, _zCoordVar); - LDEBUG("Using coordinate system variables: " << _xCoordVar << ", " << _yCoordVar << ", " << _zCoordVar); - _xMin = _model->getVariableAttribute(_xCoordVar, "actual_min").getAttributeFloat(); _xMax = _model->getVariableAttribute(_xCoordVar, "actual_max").getAttributeFloat(); _yMin = _model->getVariableAttribute(_yCoordVar, "actual_min").getAttributeFloat(); @@ -72,13 +70,6 @@ KameleonWrapper::KameleonWrapper(const std::string& filename, Model model): _typ _zMin = _model->getVariableAttribute(_zCoordVar, "actual_min").getAttributeFloat(); _zMax = _model->getVariableAttribute(_zCoordVar, "actual_max").getAttributeFloat(); - LDEBUG(_xCoordVar << "Min: " << _xMin); - LDEBUG(_xCoordVar << "Max: " << _xMax); - LDEBUG(_yCoordVar << "Min: " << _yMin); - LDEBUG(_yCoordVar << "Max: " << _yMax); - LDEBUG(_zCoordVar << "Min: " << _zMin); - LDEBUG(_zCoordVar << "Max: " << _zMax); - _lastiProgress = -1; // For progressbar } @@ -255,6 +246,7 @@ std::vector > KameleonWrapper::getFieldLines( for (glm::vec3 seedPoint : seedPoints) { fLine = traceCartesianFieldline(xVar, yVar, zVar, seedPoint, stepSize, TraceDirection::FORWARD, forwardEnd); bLine = traceCartesianFieldline(xVar, yVar, zVar, seedPoint, stepSize, TraceDirection::BACK, backEnd); + bLine.insert(bLine.begin(), fLine.rbegin(), fLine.rend()); // classify @@ -283,37 +275,43 @@ std::vector KameleonWrapper::traceCartesianFieldline( glm::vec3 color, pos, k1, k2, k3, k4; std::vector line; - - float stepX = stepSize, stepY = stepSize, stepZ = stepSize; // Should I do different stepsizes? - + float stepX, stepY, stepZ; int numSteps = 0; int maxSteps = 5000; pos = seedPoint; + _model->loadVariable(xVar); + _model->loadVariable(yVar); + _model->loadVariable(zVar); + + long int xID = _model->getVariableID(xVar); + long int yID = _model->getVariableID(yVar); + long int zID = _model->getVariableID(zVar); + // While we are inside the models boundries and not inside earth while ((pos.x < _xMax && pos.x > _xMin && pos.y < _yMax && pos.y > _yMin && - pos.z < _zMax && pos.z > _zMin) && !(pos.x < 1.0 && pos.x > -1.0 && - pos.y < 1.0 && pos.y > -1.0 && pos.z < 1.0 && pos.z > -1.0)) { + pos.z < _zMax && pos.z > _zMin) && !(pos.x*pos.x + pos.y*pos.y + pos.z*pos.z < 1.0)) { // Save position line.push_back(pos); // Calculate new position with Runge-Kutta 4th order - k1.x = _interpolator->interpolate(xVar, pos.x, pos.y, pos.z); - k1.y = _interpolator->interpolate(yVar, pos.x, pos.y, pos.z); - k1.z = _interpolator->interpolate(zVar, pos.x, pos.y, pos.z); + k1.x = _interpolator->interpolate(xID, pos.x, pos.y, pos.z, stepX, stepY, stepZ); + k1.y = _interpolator->interpolate(yID, pos.x, pos.y, pos.z); + k1.z = _interpolator->interpolate(zID, pos.x, pos.y, pos.z); k1 = (float)direction*glm::normalize(k1); - k2.x = _interpolator->interpolate(xVar, pos.x+(stepX/2.0)*k1.x, pos.y+(stepY/2.0)*k1.y, pos.z+(stepZ/2.0)*k1.z); - k2.y = _interpolator->interpolate(yVar, pos.x+(stepX/2.0)*k1.x, pos.y+(stepY/2.0)*k1.y, pos.z+(stepZ/2.0)*k1.z); - k2.z = _interpolator->interpolate(zVar, pos.x+(stepX/2.0)*k1.x, pos.y+(stepY/2.0)*k1.y, pos.z+(stepZ/2.0)*k1.z); +// stepX*=stepSize, stepY*=stepSize, stepZ*=stepSize; + k2.x = _interpolator->interpolate(xID, pos.x+(stepX/2.0)*k1.x, pos.y+(stepY/2.0)*k1.y, pos.z+(stepZ/2.0)*k1.z); + k2.y = _interpolator->interpolate(yID, pos.x+(stepX/2.0)*k1.x, pos.y+(stepY/2.0)*k1.y, pos.z+(stepZ/2.0)*k1.z); + k2.z = _interpolator->interpolate(zID, pos.x+(stepX/2.0)*k1.x, pos.y+(stepY/2.0)*k1.y, pos.z+(stepZ/2.0)*k1.z); k2 = (float)direction*glm::normalize(k2); - k3.x = _interpolator->interpolate(xVar, pos.x+(stepX/2.0)*k2.x, pos.y+(stepY/2.0)*k2.y, pos.z+(stepZ/2.0)*k2.z); - k3.y = _interpolator->interpolate(yVar, pos.x+(stepX/2.0)*k2.x, pos.y+(stepY/2.0)*k2.y, pos.z+(stepZ/2.0)*k2.z); - k3.z = _interpolator->interpolate(zVar, pos.x+(stepX/2.0)*k2.x, pos.y+(stepY/2.0)*k2.y, pos.z+(stepZ/2.0)*k2.z); + k3.x = _interpolator->interpolate(xID, pos.x+(stepX/2.0)*k2.x, pos.y+(stepY/2.0)*k2.y, pos.z+(stepZ/2.0)*k2.z); + k3.y = _interpolator->interpolate(yID, pos.x+(stepX/2.0)*k2.x, pos.y+(stepY/2.0)*k2.y, pos.z+(stepZ/2.0)*k2.z); + k3.z = _interpolator->interpolate(zID, pos.x+(stepX/2.0)*k2.x, pos.y+(stepY/2.0)*k2.y, pos.z+(stepZ/2.0)*k2.z); k3 = (float)direction*glm::normalize(k3); - k4.x = _interpolator->interpolate(xVar, pos.x+stepX*k3.x, pos.y+stepY*k3.y, pos.z+stepZ*k3.z); - k4.y = _interpolator->interpolate(yVar, pos.x+stepX*k3.x, pos.y+stepY*k3.y, pos.z+stepZ*k3.z); - k4.z = _interpolator->interpolate(zVar, pos.x+stepX*k3.x, pos.y+stepY*k3.y, pos.z+stepZ*k3.z); + k4.x = _interpolator->interpolate(xID, pos.x+stepX*k3.x, pos.y+stepY*k3.y, pos.z+stepZ*k3.z); + k4.y = _interpolator->interpolate(yID, pos.x+stepX*k3.x, pos.y+stepY*k3.y, pos.z+stepZ*k3.z); + k4.z = _interpolator->interpolate(zID, pos.x+stepX*k3.x, pos.y+stepY*k3.y, pos.z+stepZ*k3.z); k4 = (float)direction*glm::normalize(k4); pos.x = pos.x + (stepX/6.0)*(k1.x + 2.0*k2.x + 2.0*k3.x + k4.x); pos.y = pos.y + (stepY/6.0)*(k1.y + 2.0*k2.y + 2.0*k3.y + k4.y); @@ -321,14 +319,15 @@ std::vector KameleonWrapper::traceCartesianFieldline( ++numSteps; if (numSteps > maxSteps) { - LDEBUG("Max number of steps taken"); + LDEBUG("Max number of steps taken (" << maxSteps <<")"); break; } } + line.push_back(pos); - if (pos.z > 0.0 && pos.x < 1.0 && pos.x > -1.0 && pos.y < 1.0 && pos.y > -1.0) + if (pos.z > 0.0 && (pos.x*pos.x + pos.y*pos.y + pos.z*pos.z < 1.0)) end = FieldlineEnd::NORTH; - else if (pos.z < 0.0 && pos.x < 1.0 && pos.x > -1.0 && pos.y < 1.0 && pos.y > -1.0) + else if (pos.z < 0.0 && (pos.x*pos.x + pos.y*pos.y + pos.z*pos.z < 1.0)) end = FieldlineEnd::SOUTH; else end = FieldlineEnd::OUT; From 6419f34b5a0b7f66d1ef11053053f420c3bc68d0 Mon Sep 17 00:00:00 2001 From: Jonas Strandstedt Date: Wed, 18 Jun 2014 10:34:40 -0400 Subject: [PATCH 21/49] ABuffer working with small issues - Pointing to bugfixed Ghoul - Pointing to Ghoul with Linux file callback - Fixed interaction distance control bug when moving to close - Distance control with mouse wheel added - Kameleonwrapper normalization based on histogram - ABuffer seems to work with small issues --- .gitignore | 3 + ext/ghoul | 2 +- .../openspace/abuffer/abufferSingleLinked.h | 10 +- include/openspace/abuffer/abuffer_i.h | 1 + .../openspace/rendering/renderablevolumegl.h | 15 +- openspace-data | 2 +- shaders/ABuffer/abufferResolveFragment.glsl | 95 ++++++++-- shaders/ABuffer/abufferSort.hglsl | 7 +- src/abuffer/abufferSingleLinked.cpp | 177 ++++++++++++++---- src/engine/openspaceengine.cpp | 4 +- src/interaction/interactionhandler.cpp | 25 ++- src/main.cpp | 4 +- src/rendering/renderablevolume.cpp | 54 ++++-- src/rendering/renderablevolumegl.cpp | 140 +++----------- src/rendering/renderengine.cpp | 1 + src/util/kameleonwrapper.cpp | 75 ++++++-- 16 files changed, 377 insertions(+), 238 deletions(-) diff --git a/.gitignore b/.gitignore index dc6c035a1a..b86c3ed18d 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,9 @@ ext/SGCT .DS_Store *.swp +# generated glsl files +*.gglsl + # CMake stuff CMakeCache.txt CMakeFiles diff --git a/ext/ghoul b/ext/ghoul index 1f478d7956..a616a2ce84 160000 --- a/ext/ghoul +++ b/ext/ghoul @@ -1 +1 @@ -Subproject commit 1f478d79565c3c7b4343ab5ca1cd3cb30c491173 +Subproject commit a616a2ce84ec0fd9d6573ef6690707ef4a841669 diff --git a/include/openspace/abuffer/abufferSingleLinked.h b/include/openspace/abuffer/abufferSingleLinked.h index 4ff20b2070..5e946af48a 100644 --- a/include/openspace/abuffer/abufferSingleLinked.h +++ b/include/openspace/abuffer/abufferSingleLinked.h @@ -28,6 +28,7 @@ #include #include +#include namespace openspace { @@ -41,6 +42,7 @@ public: virtual void clear(); virtual void preRender(); virtual void postRender(); + virtual void resolve(); private: @@ -55,7 +57,13 @@ private: GLuint fragmentTexture; GLuint _screenQuad; - ghoul::opengl::ProgramObject* resolveShader; + ghoul::opengl::ProgramObject* _resolveShader; + ghoul::filesystem::File* _fragmentShaderFile; + std::string _fragmentShaderPath; + bool _updateShader; + + void generateShaderSource(); + bool updateShader(); }; // ABuffer_I } // openspace diff --git a/include/openspace/abuffer/abuffer_i.h b/include/openspace/abuffer/abuffer_i.h index 9e1644edb0..8ee04eedb7 100644 --- a/include/openspace/abuffer/abuffer_i.h +++ b/include/openspace/abuffer/abuffer_i.h @@ -38,6 +38,7 @@ public: virtual void clear() = 0; virtual void preRender() = 0; virtual void postRender() = 0; + virtual void resolve() = 0; }; // ABuffer_I } // openspace diff --git a/include/openspace/rendering/renderablevolumegl.h b/include/openspace/rendering/renderablevolumegl.h index 4aaed2a6c0..eb39fe3065 100644 --- a/include/openspace/rendering/renderablevolumegl.h +++ b/include/openspace/rendering/renderablevolumegl.h @@ -58,24 +58,19 @@ public: private: ghoul::Dictionary _hintsDictionary; + std::string _filename; std::string _transferFunctionPath; - float _stepSize; + + ghoul::filesystem::File* _transferFunctionFile; + ghoul::opengl::Texture* _volume; ghoul::opengl::Texture* _transferFunction; - ghoul::opengl::ProgramObject* _twopassProgram; - GLuint _screenQuad; VolumeRaycasterBox* _colorBoxRenderer; glm::vec3 _boxScaling; - std::mutex* _shaderMutex; - - ghoul::filesystem::File* _vertexSourceFile; - ghoul::filesystem::File* _fragmentSourceFile; - bool _programUpdateOnSave; - - void safeShaderCompilation(); + bool _updateTransferfunction; }; } // namespace openspace diff --git a/openspace-data b/openspace-data index 840edd3a81..835261f477 160000 --- a/openspace-data +++ b/openspace-data @@ -1 +1 @@ -Subproject commit 840edd3a81db2957825abe9e49a524d490b7332f +Subproject commit 835261f4775ac7a7e5fcd000b1e254d4c947e389 diff --git a/shaders/ABuffer/abufferResolveFragment.glsl b/shaders/ABuffer/abufferResolveFragment.glsl index c3fe4d24f0..84c7720f25 100644 --- a/shaders/ABuffer/abufferResolveFragment.glsl +++ b/shaders/ABuffer/abufferResolveFragment.glsl @@ -1,17 +1,28 @@ #version 430 -// uniforms -uniform sampler3D volume; -uniform sampler1D transferFunction; +uniform int SCREEN_WIDTH; +uniform int SCREEN_HEIGHT; +uniform float ALPHA_LIMIT = 0.95; in vec2 texCoord; out vec4 color; // settings -#define ALPHA_LIMIT 0.98 -#define LOOP_LIMIT 200 +#define LOOP_LIMIT 800 #define MAX_FRAGMENTS 16 -#define MAX_VOLUMES 4 +#define SHOWFUNC + +// GENERATED CONTENT +#pragma openspace insert HEADERS +// END GENERATED CONTENT + + +const float stepSize = 0.01; +const float samplingRate = 1.0; +float volumeStepSize[] = { + stepSize +}; + #include "abufferStruct.hglsl" ABufferStruct_t fragments[MAX_FRAGMENTS]; @@ -49,8 +60,22 @@ void blendGeometry(inout vec4 color, ABufferStruct_t frag) { } */ +float globz(float z) { + return z; + // return log(2.0*z-1.0); + // return exp(2.0*z-1.0); + // const float zNear = 0.1f; + // const float zFar = 1.0f; + // //float z_b = texture2D(depthBuffTex, vTexCoord).x; + // float z_b = z; + // float z_n = 2.0 * z_b - 1.0; + // float z_e = 2.0 * zNear * zFar / (zFar + zNear - z_n * (zFar - zNear)); + // return z_e; + //return (2.0 * z - near - far) / (far - near); +} + vec4 calculate_final_color(uint frag_count) { - + // volumeStepSize[volID] = 0.01; int currentVolumeBitmask = 0; vec4 final_color = vec4(0); @@ -72,19 +97,23 @@ vec4 calculate_final_color(uint frag_count) { currentVolumeBitmask = currentVolumeBitmask ^ (type); if(type == 0) + //blendStep(final_color, _col_(startFrag), stepSize); final_color = blend(final_color, _col_(startFrag)); if(bool(currentVolumeBitmask)) { int volID = type -1; float p = 0.0f; - const float stepSize = 0.01; //const float l = volume_length[volID]; const float S1 = volume_zlength[volID].x; const float S2 = volume_zlength[volID].y; const float L = S1 - S2; - const float l = (_z_(startFrag) - S1) / L - (_z_(endFrag) - S1) / L; - const vec3 direction = volume_direction[volID]; + const float z1 = globz(_z_(startFrag)); + const float z2 = globz(_z_(endFrag)); + // const float z1 = _z_(startFrag); + // const float z2 = _z_(endFrag); + const float l = ((z1 - S1) / L - (z2 - S1) / L) * volume_length[volID]; + int max_iterations = int(l / volumeStepSize[volID]); int iterations = 0; vec3 position; @@ -104,15 +133,18 @@ vec4 calculate_final_color(uint frag_count) { // TransferFunction vec4 color = vec4(0); - float intensity; - while(p < l && iterations < LOOP_LIMIT) { - intensity = length(texture(volume, volume_position[volID])); - color = texture(transferFunction, intensity); - blendStep(final_color, color, stepSize); + for(int k = 0; k < max_iterations && k < LOOP_LIMIT; ++k) { + //while(p < l && iterations < LOOP_LIMIT) { + +// GENERATED CONTENT +#pragma openspace insert SAMPLERCALLS +// END GENERATED CONTENT + //final_color = blend(final_color, color*stepSize); - p+= stepSize; - volume_position[volID] += direction*stepSize; - ++iterations; + + volume_position[volID] += volume_direction[volID]*volumeStepSize[volID]; + //p+= stepSize; + //++iterations; } } @@ -125,7 +157,8 @@ vec4 calculate_final_color(uint frag_count) { // blendGeometry(final_color, endFrag); // final_color = blend(final_color, frag_color); - if(i == frag_count_1 -1 && _type_(endFrag) == 0) + if(i == frag_count_1 -1 && _type_(endFrag) == 0) + // if(i == frag_count_1 -1) final_color = blend(final_color, _col_(endFrag)); } @@ -133,6 +166,20 @@ vec4 calculate_final_color(uint frag_count) { // int id =3; // if(id < frag_count)final_color = blend(final_color, _col_(fragments[id])); + // if(frag_count > 0) + // final_color = _col_(fragments[0]); +#ifdef SHOWFUNC + float showfunc_size = 20.0; + if(gl_FragCoord.y > float(SCREEN_HEIGHT) - showfunc_size) { + float normalizedIntensity = gl_FragCoord.x / float(SCREEN_WIDTH) ; + vec4 tfc = texture(transferFunction, normalizedIntensity); + final_color = tfc; + } else if(ceil(gl_FragCoord.y) == float(SCREEN_HEIGHT) - showfunc_size) { + const float intensity = 0.4; + final_color = vec4(intensity,intensity,intensity,1.0); + } +#endif + return final_color; } @@ -148,4 +195,12 @@ void main() { color = calculate_final_color(frag_count); //color = vec4(float(frag_count) / 5.0, 0.0, 0.0, 1.0); -} \ No newline at end of file +} + +// GENERATED CONTENT +#pragma openspace insert SAMPLERS +// END GENERATED CONTENT + + + + diff --git a/shaders/ABuffer/abufferSort.hglsl b/shaders/ABuffer/abufferSort.hglsl index 71e8534100..c8becb8b00 100644 --- a/shaders/ABuffer/abufferSort.hglsl +++ b/shaders/ABuffer/abufferSort.hglsl @@ -56,8 +56,8 @@ void sort_fragments_list(uint frag_count) { bool start = true; vec3 startColor; vec4 startPosition; - for(jj = 0; jj < frag_count; ++jj) { - int type = int(_type_(fragments[jj])) -1; + for(jj = ii; jj < frag_count; ++jj) { + int type = int(_type_(fragments[jj])) - 1; if(type== ii) { if(start) { startColor = _col_(fragments[jj]).rgb; @@ -66,10 +66,11 @@ void sort_fragments_list(uint frag_count) { start = false; } else { vec3 dir = _col_(fragments[jj]).rgb - startColor; - volume_direction[ii] = normalize(dir); volume_position[ii] = startColor; volume_length[ii] = length(dir); + volume_direction[ii] = normalize(dir); volume_zlength[ii].y = _z_(fragments[jj]); + volumeStepSize[ii] = 1.0/(length(volume_direction[ii]*volume_dim[ii])); //volume_length[ii] = pscLength(_pos_(fragments[jj]), startPosition); break; } diff --git a/src/abuffer/abufferSingleLinked.cpp b/src/abuffer/abufferSingleLinked.cpp index b28948c5d4..8b64a1ae6f 100644 --- a/src/abuffer/abufferSingleLinked.cpp +++ b/src/abuffer/abufferSingleLinked.cpp @@ -29,11 +29,43 @@ #include #include +#include +#include + #define MAX_LAYERS 10 #define BUFFER_OFFSET(i) ((char *)NULL + (i)) namespace { std::string _loggerCat = "ABufferSingleLinked"; + +const std::string openspaceHeaders = R"( +#define MAX_VOLUMES 1 +// VOLUME1 +uniform sampler3D volume; +uniform sampler1D transferFunction; +void sampleVolume1(inout vec4 finalColor, vec3 position); + + +const vec3 volume_dim[] = { + vec3(300.0,100.0,100.0) +}; +)"; + +const std::string openspaceSamplerCalls = R"( +if((currentVolumeBitmask & (1 << 0)) == 1) + sampleVolume1(final_color,volume_position[volID]); +)"; + +const std::string openspaceSamplers = R"( +void sampleVolume1(inout vec4 finalColor, vec3 position) { + float intensity = texture(volume, position).x; + //intensity *=25.0; + //intensity = clamp(intensity*100.0, 0.0, 1.0); + vec4 color = texture(transferFunction, intensity); + blendStep(finalColor, color, stepSize); +} +)"; + } namespace openspace { @@ -51,12 +83,27 @@ ABufferSingleLinked::ABufferSingleLinked() { atomicCounterBuffer = 0; fragmentBuffer = 0; fragmentTexture = 0; + + const std::string fragmentShaderSourcePath = absPath("${SHADERS}/ABuffer/abufferResolveFragment.glsl"); + _fragmentShaderFile = new ghoul::filesystem::File(fragmentShaderSourcePath, true); + _updateShader = false; + _fragmentShaderPath = fragmentShaderSourcePath + ".ABuffer.gglsl"; + + generateShaderSource(); + + } ABufferSingleLinked::~ABufferSingleLinked() { if(data != 0) delete data; + if(_fragmentShaderFile) + delete _fragmentShaderFile; + + if(_resolveShader) + delete _resolveShader; + glDeleteTextures(1,&anchorPointerTexture); glDeleteTextures(1,&fragmentTexture); glDeleteBuffers(1,&anchorPointerTextureInitializer); @@ -99,30 +146,13 @@ bool ABufferSingleLinked::initialize() { // ============================ // SHADERS // ============================ - resolveShader = nullptr; - using ghoul::opengl::ShaderObject; - using ghoul::opengl::ProgramObject; - ShaderObject* vs - = new ShaderObject(ShaderObject::ShaderType::ShaderTypeVertex, - absPath("${SHADERS}/ABuffer/abufferResolveVertex.glsl"), "Vertex"); - ShaderObject* fs - = new ShaderObject(ShaderObject::ShaderType::ShaderTypeFragment, - absPath("${SHADERS}/ABuffer/abufferResolveFragment.glsl"), "Fragment"); + auto shaderCallback = [this](const ghoul::filesystem::File& file) { + _updateShader = true; + }; + _fragmentShaderFile->setCallback(shaderCallback); - resolveShader = new ProgramObject; - resolveShader->attachObject(vs); - resolveShader->attachObject(fs); - - if (!resolveShader->compileShaderObjects()) { - LERROR("Could not compile shader"); - return false; - } - if (!resolveShader->linkProgramObject()){ - LERROR("Could not link shader"); - return false; - } - resolveShader->setUniform("volume", 0); - resolveShader->setUniform("transferFunction", 1); + _resolveShader = nullptr; + updateShader(); // ============================ // GEOMETRY (quad) @@ -172,26 +202,95 @@ void ABufferSingleLinked::preRender() { void ABufferSingleLinked::postRender() { - ghoul::opengl::Texture* volume = nullptr; - ghoul::opengl::Texture* tf = nullptr; - OsEng.configurationManager().getValue("firstVolume", volume); - OsEng.configurationManager().getValue("firstTransferFunction", tf); - resolveShader->activate(); + if(_updateShader) { + _updateShader = false; + generateShaderSource(); + updateShader(); - if(volume) { - glActiveTexture(GL_TEXTURE0); - volume->bind(); } +} - if(tf) { - glActiveTexture(GL_TEXTURE1); - tf->bind(); +void ABufferSingleLinked::resolve() { + + if(_resolveShader) { + ghoul::opengl::Texture* volume = nullptr; + ghoul::opengl::Texture* tf = nullptr; + OsEng.configurationManager().getValue("firstVolume", volume); + OsEng.configurationManager().getValue("firstTransferFunction", tf); + _resolveShader->activate(); + + if(volume) { + glActiveTexture(GL_TEXTURE0); + volume->bind(); + } + + if(tf) { + glActiveTexture(GL_TEXTURE1); + tf->bind(); + } + //LDEBUG("SCREEN_WIDTH" << width); + glBindVertexArray(_screenQuad); + glDrawArrays(GL_TRIANGLES, 0, 6); + _resolveShader->deactivate(); } - //resolveShader->setUniform("SCREEN_WIDTH", width); - //resolveShader->setUniform("SCREEN_HEIGHT", height); - glBindVertexArray(_screenQuad); - glDrawArrays(GL_TRIANGLES, 0, 6); - resolveShader->deactivate(); + +} + +bool ABufferSingleLinked::updateShader() { + + using ghoul::opengl::ShaderObject; + using ghoul::opengl::ProgramObject; + ShaderObject* vs + = new ShaderObject(ShaderObject::ShaderType::ShaderTypeVertex, + absPath("${SHADERS}/ABuffer/abufferResolveVertex.glsl"), "Vertex"); + ShaderObject* fs + = new ShaderObject(ShaderObject::ShaderType::ShaderTypeFragment,_fragmentShaderPath, "Fragment"); + + ghoul::opengl::ProgramObject* resolveShader = new ProgramObject; + resolveShader->attachObject(vs); + resolveShader->attachObject(fs); + + if (!resolveShader->compileShaderObjects()) { + LERROR("Could not compile shader"); + return false; + } + if (!resolveShader->linkProgramObject()){ + LERROR("Could not link shader"); + return false; + } + resolveShader->setUniform("volume", 0); + resolveShader->setUniform("transferFunction", 1); + resolveShader->setUniform("SCREEN_WIDTH", static_cast(width)); + resolveShader->setUniform("SCREEN_HEIGHT", static_cast(height)); + + if(_resolveShader) + delete _resolveShader; + + _resolveShader = resolveShader; + LDEBUG("Successfully updated shader!"); + return true; +} + +void ABufferSingleLinked::generateShaderSource() { + std::string line, source = ""; + std::ifstream fragmentShaderFile(_fragmentShaderFile->path()); + if(fragmentShaderFile.is_open()) { + while(std::getline(fragmentShaderFile, line)) { + if(line == "#pragma openspace insert HEADERS") { + line = openspaceHeaders; + } else if(line == "#pragma openspace insert SAMPLERCALLS") { + line = openspaceSamplerCalls; + } else if(line == "#pragma openspace insert SAMPLERS") { + line = openspaceSamplers; + } + source += line + "\n"; + } + } + fragmentShaderFile.close(); + + std::ofstream fragmentShaderOut(_fragmentShaderPath); + fragmentShaderOut << source; + fragmentShaderOut.close(); } } // openspace \ No newline at end of file diff --git a/src/engine/openspaceengine.cpp b/src/engine/openspaceengine.cpp index 55e29ad495..ca1e7bbbab 100644 --- a/src/engine/openspaceengine.cpp +++ b/src/engine/openspaceengine.cpp @@ -124,9 +124,9 @@ bool OpenSpaceEngine::registerBasePathFromConfigurationFile(const std::string& f bool OpenSpaceEngine::findConfiguration(std::string& filename) { - if (!filename.empty()) + if (!filename.empty()) { return FileSys.fileExists(filename); - else { + } else { std::string currentDirectory = FileSys.absolutePath(FileSys.currentDirectory()); size_t occurrences = std::count(currentDirectory.begin(), currentDirectory.end(), ghoul::filesystem::FileSystem::PathSeparator); diff --git a/src/interaction/interactionhandler.cpp b/src/interaction/interactionhandler.cpp index fc7cb4ba9c..020ba82d3f 100644 --- a/src/interaction/interactionhandler.cpp +++ b/src/interaction/interactionhandler.cpp @@ -307,22 +307,22 @@ void InteractionHandler::keyboardCallback(int key, int action) { const double dt = getDt(); if(action == SGCT_PRESS || action == SGCT_REPEAT) { - if (key == 'S') { + if (key == SGCT_KEY_S) { glm::vec3 euler(speed * dt, 0.0, 0.0); glm::quat rot = glm::quat(euler); orbit(rot); } - if (key == 'W') { + if (key == SGCT_KEY_W) { glm::vec3 euler(-speed * dt, 0.0, 0.0); glm::quat rot = glm::quat(euler); orbit(rot); } - if (key == 'A') { + if (key == SGCT_KEY_A) { glm::vec3 euler(0.0, -speed * dt, 0.0); glm::quat rot = glm::quat(euler); orbit(rot); } - if (key == 'D') { + if (key == SGCT_KEY_D) { glm::vec3 euler(0.0, speed * dt, 0.0); glm::quat rot = glm::quat(euler); orbit(rot); @@ -347,19 +347,19 @@ void InteractionHandler::keyboardCallback(int key, int action) { glm::quat rot = glm::quat(euler); rotate(rot); } - if (key == 'R') { + if (key == SGCT_KEY_R) { PowerScaledScalar dist(-speed * dt, 0.0); distance(dist); } - if (key == 'F') { + if (key == SGCT_KEY_F) { PowerScaledScalar dist(speed * dt, 0.0); distance(dist); } - if (key == 'T') { + if (key == SGCT_KEY_T) { PowerScaledScalar dist(-speed * 100.0 * dt, 0.0); distance(dist); } - if (key == 'G') { + if (key == SGCT_KEY_G) { PowerScaledScalar dist(speed * 100.0 * dt, 0.0); distance(dist); } @@ -417,6 +417,15 @@ void InteractionHandler::mouseScrollWheelCallback(int pos) { //if(mouseControl_ != nullptr) { // mouseControl_->mouseScrollCallback(pos); //} + const double speed = 4.75; + const double dt = getDt(); + if(pos < 0) { + PowerScaledScalar dist(speed * dt, 0.0); + distance(dist); + } else if(pos > 0) { + PowerScaledScalar dist(-speed * dt, 0.0); + distance(dist); + } } diff --git a/src/main.cpp b/src/main.cpp index cf97ebe9ff..ac958ba03d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -159,11 +159,11 @@ void mainMousePosCallback(double x, double y) OsEng.mousePositionCallback(static_cast(x), static_cast(y)); } -void mainMouseScrollCallback(double pos, double /*pos2*/) +void mainMouseScrollCallback(double posX, double posY) { // TODO use float instead if (_sgctEngine->isMaster()) - OsEng.mouseScrollWheelCallback(static_cast(pos)); + OsEng.mouseScrollWheelCallback(static_cast(posY)); } void mainEncodeFun() diff --git a/src/rendering/renderablevolume.cpp b/src/rendering/renderablevolume.cpp index dd741cc8b1..45324afa40 100644 --- a/src/rendering/renderablevolume.cpp +++ b/src/rendering/renderablevolume.cpp @@ -77,7 +77,10 @@ RenderableVolume::RenderableVolume(const ghoul::Dictionary& dictionary) : Render RenderableVolume::~RenderableVolume() { } -ghoul::opengl::Texture* RenderableVolume::loadVolume(const std::string& filepath, const ghoul::Dictionary& hintsDictionary) { +ghoul::opengl::Texture* RenderableVolume::loadVolume( + const std::string& filepath, + const ghoul::Dictionary& hintsDictionary) +{ if( ! FileSys.fileExists(filepath)) { LWARNING("Could not load volume, could not find '" << filepath << "'"); return nullptr; @@ -91,17 +94,20 @@ ghoul::opengl::Texture* RenderableVolume::loadVolume(const std::string& filepath glm::size3_t dimensions(1,1,1); double tempValue; - if (hintsDictionary.hasKey("Dimensions.1") && hintsDictionary.getValue("Dimensions.1", tempValue)) { + if (hintsDictionary.hasKey("Dimensions.1") && + hintsDictionary.getValue("Dimensions.1", tempValue)) { int intVal = static_cast(tempValue); if(intVal > 0) dimensions[0] = intVal; } - if (hintsDictionary.hasKey("Dimensions.2") && hintsDictionary.getValue("Dimensions.2", tempValue)) { + if (hintsDictionary.hasKey("Dimensions.2") && + hintsDictionary.getValue("Dimensions.2", tempValue)) { int intVal = static_cast(tempValue); if(intVal > 0) dimensions[1] = intVal; } - if (hintsDictionary.hasKey("Dimensions.3") && hintsDictionary.getValue("Dimensions.3", tempValue)) { + if (hintsDictionary.hasKey("Dimensions.3") && + hintsDictionary.getValue("Dimensions.3", tempValue)) { int intVal = static_cast(tempValue); if(intVal > 0) dimensions[2] = intVal; @@ -152,7 +158,9 @@ ghoul::opengl::Texture* RenderableVolume::loadVolume(const std::string& filepath } fclose(file); - return new ghoul::opengl::Texture(data, dimensions, ghoul::opengl::Texture::Format::Red, GL_RED, GL_FLOAT, ghoul::opengl::Texture::FilterMode::Linear, ghoul::opengl::Texture::WrappingMode::ClampToBorder); + ghoul::opengl::Texture* t = new ghoul::opengl::Texture(data, dimensions, ghoul::opengl::Texture::Format::Red, GL_RED, GL_FLOAT, ghoul::opengl::Texture::FilterMode::Linear, ghoul::opengl::Texture::WrappingMode::ClampToBorder); + t->setWrapping(ghoul::opengl::Texture::WrappingMode::ClampToBorder); + return t; } KameleonWrapper::Model model; @@ -176,8 +184,9 @@ ghoul::opengl::Texture* RenderableVolume::loadVolume(const std::string& filepath fwrite(data, sizeof(float), length, file); fclose(file); } - return new ghoul::opengl::Texture(data, dimensions, ghoul::opengl::Texture::Format::Red, GL_RED, GL_FLOAT, ghoul::opengl::Texture::FilterMode::Linear, ghoul::opengl::Texture::WrappingMode::ClampToBorder); - + ghoul::opengl::Texture* t = new ghoul::opengl::Texture(data, dimensions, ghoul::opengl::Texture::Format::Red, GL_RED, GL_FLOAT, ghoul::opengl::Texture::FilterMode::Linear, ghoul::opengl::Texture::WrappingMode::ClampToBorder); + t->setWrapping(ghoul::opengl::Texture::WrappingMode::ClampToBorder); + return t; } else if (hintsDictionary.hasKey("Variables")) { std::string xVariable, yVariable, zVariable; bool xVar, yVar, zVar; @@ -207,8 +216,16 @@ ghoul::opengl::Texture* RenderableVolume::loadVolume(const std::string& filepath // // delete fieldlinesData; // delete rhoData; + if(cache) { + FILE* file = fopen (cachepath.c_str(), "wb"); + int length = dimensions[0] *dimensions[1] *dimensions[2]; + fwrite(fieldlinesData, sizeof(float), length, file); + fclose(file); + } - return new ghoul::opengl::Texture(fieldlinesData, dimensions, ghoul::opengl::Texture::Format::Red, GL_RED, GL_FLOAT); + ghoul::opengl::Texture* t = new ghoul::opengl::Texture(fieldlinesData, dimensions, ghoul::opengl::Texture::Format::Red, GL_RED, GL_FLOAT); + t->setWrapping(ghoul::opengl::Texture::WrappingMode::ClampToBorder); + return t; } } else { @@ -290,7 +307,9 @@ ghoul::opengl::Texture* RenderableVolume::loadTransferFunction(const std::string // check if not a txt based texture if ( ! hasExtension(filepath, "txt")) { - return ghoul::opengl::loadTexture(f); + ghoul::opengl::Texture* t = ghoul::opengl::loadTexture(f); + t->setWrapping(ghoul::opengl::Texture::WrappingMode::ClampToBorder); + return t; } // it is a txt based texture @@ -420,17 +439,18 @@ ghoul::opengl::Texture* RenderableVolume::loadTransferFunction(const std::string //LDEBUG("["<< position <<"] " << value); } - LDEBUG(weight << ", (" << - transferFunction[4*i+0] << ", " << - transferFunction[4*i+1] << ", " << - transferFunction[4*i+2] << ", " << - transferFunction[4*i+3] << ")"); + // LDEBUG(weight << ", (" << + // transferFunction[4*i+0] << ", " << + // transferFunction[4*i+1] << ", " << + // transferFunction[4*i+2] << ", " << + // transferFunction[4*i+3] << ")"); } - - return new ghoul::opengl::Texture(transferFunction, + ghoul::opengl::Texture* t = new ghoul::opengl::Texture(transferFunction, glm::size3_t(width,1,1),ghoul::opengl::Texture::Format::RGBA, - GL_RGBA, GL_FLOAT);; + GL_RGBA, GL_FLOAT, ghoul::opengl::Texture::FilterMode::Linear, + ghoul::opengl::Texture::WrappingMode::ClampToBorder); + return t; } } // namespace openspace diff --git a/src/rendering/renderablevolumegl.cpp b/src/rendering/renderablevolumegl.cpp index cb52808d40..64b9ec3772 100644 --- a/src/rendering/renderablevolumegl.cpp +++ b/src/rendering/renderablevolumegl.cpp @@ -42,10 +42,9 @@ namespace { namespace openspace { RenderableVolumeGL::RenderableVolumeGL(const ghoul::Dictionary& dictionary): - RenderableVolume(dictionary), _screenQuad(0), _boxScaling(1.0, 1.0, 1.0), - _programUpdateOnSave(false) { + RenderableVolume(dictionary), _boxScaling(1.0, 1.0, 1.0), + _updateTransferfunction(false) { - _shaderMutex = new std::mutex; _filename = ""; if(dictionary.hasKey("Volume")) { @@ -59,34 +58,8 @@ RenderableVolumeGL::RenderableVolumeGL(const ghoul::Dictionary& dictionary): if(dictionary.hasKey("Hints")) dictionary.getValue("Hints", _hintsDictionary); - std::string vshaderpath = ""; - std::string fshaderpath = ""; - - if (dictionary.hasKey("Shaders")) { - ghoul::Dictionary shaderDictionary; - if(dictionary.getValue("Shaders", shaderDictionary)) { - if (shaderDictionary.hasKey("VertexShader")) { - shaderDictionary.getValue("VertexShader", vshaderpath); - } - if (shaderDictionary.hasKey("FragmentShader")) { - shaderDictionary.getValue("FragmentShader", fshaderpath); - } - - vshaderpath = findPath(vshaderpath); - fshaderpath = findPath(fshaderpath); - - _vertexSourceFile = new ghoul::filesystem::File(vshaderpath, false); - _fragmentSourceFile = new ghoul::filesystem::File(fshaderpath, false); - - _twopassProgram = new ghoul::opengl::ProgramObject("TwoPassProgram"); - ghoul::opengl::ShaderObject* vertexShader = new ghoul::opengl::ShaderObject(ghoul::opengl::ShaderObject::ShaderTypeVertex,vshaderpath); - ghoul::opengl::ShaderObject* fragmentShader = new ghoul::opengl::ShaderObject(ghoul::opengl::ShaderObject::ShaderTypeFragment,fshaderpath); - _twopassProgram->attachObject(vertexShader); - _twopassProgram->attachObject(fragmentShader); - } - } - _transferFunction = nullptr; + _transferFunctionFile = nullptr; if (dictionary.hasKey("TransferFunction")) { std::string transferFunctionPath = ""; if(dictionary.getValue("TransferFunction", transferFunctionPath)) { @@ -95,12 +68,10 @@ RenderableVolumeGL::RenderableVolumeGL(const ghoul::Dictionary& dictionary): } if( _transferFunctionPath == "") { LERROR("No transferFunction!"); + } else { + _transferFunctionFile = new ghoul::filesystem::File(_transferFunctionPath, true); } - - if(dictionary.hasKey("UpdateOnSave")) { - dictionary.getValue("UpdateOnSave", _programUpdateOnSave); - } double tempValue; if(dictionary.hasKey("BoxScaling.1") && dictionary.getValue("BoxScaling.1", tempValue)) { @@ -137,56 +108,14 @@ bool RenderableVolumeGL::initialize() { _transferFunction->uploadTexture(); OsEng.configurationManager().setValue("firstVolume", _volume); OsEng.configurationManager().setValue("firstTransferFunction", _transferFunction); - //glBindImageTexture(2, *_volume, 0, GL_FALSE, 0, GL_READ_ONLY, _volume->type()); - - // ------ SETUP GEOMETRY ---------------- - const GLfloat size = 1.0f; - const GLfloat vertex_texcoord_data[] = { // square of two triangles (sigh) - // x y z s t - -size, -size, 0.0f, 0.0f, 0.0f, - size, size, 0.0f, 1.0f, 1.0f, - -size, size, 0.0f, 0.0f, 1.0f, - -size, -size, 0.0f, 0.0f, 0.0f, - size, -size, 0.0f, 1.0f, 0.0f, - size, size, 0.0f, 1.0f, 1.0f + + auto textureCallback = [this](const ghoul::filesystem::File& file) { + _updateTransferfunction = true; }; - - GLuint vertexPositionBuffer; - glGenVertexArrays(1, &_screenQuad); // generate array - glBindVertexArray(_screenQuad); // bind array - glGenBuffers(1, &vertexPositionBuffer); // generate buffer - glBindBuffer(GL_ARRAY_BUFFER, vertexPositionBuffer); // bind buffer - glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_texcoord_data), vertex_texcoord_data, GL_STATIC_DRAW); - - // Vertex positions - GLuint vertexLocation = 2; - glEnableVertexAttribArray(vertexLocation); - glVertexAttribPointer(vertexLocation, 3, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), reinterpret_cast(0)); - - // Texture coordinates - GLuint texcoordLocation = 0; - glEnableVertexAttribArray(texcoordLocation); - glVertexAttribPointer(texcoordLocation, 2, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (void*)(3*sizeof(GLfloat))); - - glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind buffer - glBindVertexArray(0); //unbind array - + _transferFunctionFile->setCallback(textureCallback); + _colorBoxRenderer->initialize(); - // ------ SETUP SHADERS ----------------- - auto privateCallback = [this](const ghoul::filesystem::File& file) { - safeShaderCompilation(); - }; - if(_programUpdateOnSave) { - _vertexSourceFile->setCallback(privateCallback); - _fragmentSourceFile->setCallback(privateCallback); - } - - _twopassProgram->compileShaderObjects(); - _twopassProgram->linkProgramObject(); - _twopassProgram->setUniform("texBack", 0); - _twopassProgram->setUniform("texFront", 1); - _twopassProgram->setUniform("texVolume", 2); return true; } @@ -196,7 +125,20 @@ bool RenderableVolumeGL::deinitialize() { } void RenderableVolumeGL::render(const Camera *camera, const psc &thisPosition) { - _stepSize = 0.01f; + if(_updateTransferfunction) { + _updateTransferfunction = false; + ghoul::opengl::Texture* transferFunction = loadTransferFunction(_transferFunctionPath); + if(transferFunction) { + const void* data = transferFunction->pixelData(); + glBindBuffer(GL_COPY_READ_BUFFER, *transferFunction); + _transferFunction->bind(); + glTexImage1D(GL_TEXTURE_1D, 0, _transferFunction->internalFormat(), _transferFunction->width(),0, _transferFunction->format(), _transferFunction->dataType(), data); + //delete data; + delete transferFunction; + LDEBUG("Updated transferfunction!"); + + } + } glm::mat4 transform ; glm::mat4 camTransform = camera->viewRotationMatrix(); @@ -208,44 +150,12 @@ void RenderableVolumeGL::render(const Camera *camera, const psc &thisPosition) { transform = glm::scale(transform, _boxScaling); _colorBoxRenderer->render(camera->viewProjectionMatrix(), transform); - /* - // Draw screenquad - _shaderMutex->lock(); - _twopassProgram->activate(); - _twopassProgram->setUniform("stepSize", _stepSize); - - // Set textures - glActiveTexture(GL_TEXTURE0); - _colorBoxRenderer->backFace()->bind(); - glActiveTexture(GL_TEXTURE1); - _colorBoxRenderer->frontFace()->bind(); - glActiveTexture(GL_TEXTURE2); - _volume->bind(); - - glBindVertexArray(_screenQuad); - glDrawArrays(GL_TRIANGLES, 0, 6); - glBindVertexArray(0); - - _twopassProgram->deactivate(); - _shaderMutex->unlock(); - */ + } void RenderableVolumeGL::update() { } -void RenderableVolumeGL::safeShaderCompilation() { - /* - _shaderMutex->lock(); - _twopassProgram->rebuildFromFile(); - _twopassProgram->compileShaderObjects(); - _twopassProgram->linkProgramObject(); - _twopassProgram->setUniform("texBack", 0); - _twopassProgram->setUniform("texFront", 1); - _twopassProgram->setUniform("texVolume", 2); - _shaderMutex->unlock(); - */ -} } // namespace openspace diff --git a/src/rendering/renderengine.cpp b/src/rendering/renderengine.cpp index da40fe000f..96891951c7 100644 --- a/src/rendering/renderengine.cpp +++ b/src/rendering/renderengine.cpp @@ -176,6 +176,7 @@ void RenderEngine::render() _abuffer->preRender(); _sceneGraph->render(_mainCamera); _abuffer->postRender(); + _abuffer->resolve(); /* // Print some useful information on the master viewport if (sgct::Engine::instance()->isMaster()) { diff --git a/src/util/kameleonwrapper.cpp b/src/util/kameleonwrapper.cpp index b34bee3aeb..0b2d4419c0 100644 --- a/src/util/kameleonwrapper.cpp +++ b/src/util/kameleonwrapper.cpp @@ -94,16 +94,27 @@ float* KameleonWrapper::getUniformSampledValues(const std::string& var, glm::siz int size = outDimensions.x*outDimensions.y*outDimensions.z; float* data = new float[size]; + double* doubleData = new double[size]; - float varMin = _model->getVariableAttribute(var, "actual_min").getAttributeFloat(); - float varMax = _model->getVariableAttribute(var, "actual_max").getAttributeFloat(); - - float stepX = (_xMax-_xMin)/(static_cast(outDimensions.x)); - float stepY = (_yMax-_yMin)/(static_cast(outDimensions.y)); - float stepZ = (_zMax-_zMin)/(static_cast(outDimensions.z)); + double varMin = _model->getVariableAttribute(var, "actual_min").getAttributeFloat(); + double varMax = _model->getVariableAttribute(var, "actual_max").getAttributeFloat(); + + double stepX = (_xMax-_xMin)/(static_cast(outDimensions.x)); + double stepY = (_yMax-_yMin)/(static_cast(outDimensions.y)); + double stepZ = (_zMax-_zMin)/(static_cast(outDimensions.z)); LDEBUG(var << "Min: " << varMin); LDEBUG(var << "Max: " << varMax); + + // HISTOGRAM + const int bins = 200; + const float truncLim = 0.9; + std::vector histogram (bins,0); + auto mapToHistogram = [varMin, varMax, bins](double val) { + double zeroToOne = (val-varMin)/(varMax-varMin); + zeroToOne *= static_cast(bins); + return static_cast(zeroToOne); + }; for (int x = 0; x < outDimensions.x; ++x) { progressBar(x, outDimensions.x); @@ -114,35 +125,37 @@ float* KameleonWrapper::getUniformSampledValues(const std::string& var, glm::siz int index = x + y*outDimensions.x + z*outDimensions.x*outDimensions.y; if(_type == Model::BATSRUS) { - float xPos = _xMin + stepX*x; - float yPos = _yMin + stepY*y; - float zPos = _zMin + stepZ*z; + double xPos = _xMin + stepX*x; + double yPos = _yMin + stepY*y; + double zPos = _zMin + stepZ*z; // get interpolated data value for (xPos, yPos, zPos) - float value = _interpolator->interpolate(var, xPos, yPos, zPos); + double value = _interpolator->interpolate(var, xPos, yPos, zPos); // scale to [0,1] - data[index] = (value-varMin)/(varMax-varMin); + //doubleData[index] = (value-varMin)/(varMax-varMin); + doubleData[index] = value; + histogram[mapToHistogram(value)]++; } else if (_type == Model::ENLIL) { // Put r in the [0..sqrt(3)] range - float rNorm = sqrt(3.0)*(float)x/(float)(outDimensions.x-1); + double rNorm = sqrt(3.0)*(double)x/(double)(outDimensions.x-1); // Put theta in the [0..PI] range - float thetaNorm = M_PI*(float)y/(float)(outDimensions.y-1); + double thetaNorm = M_PI*(double)y/(double)(outDimensions.y-1); // Put phi in the [0..2PI] range - float phiNorm = 2.0*M_PI*(float)z/(float)(outDimensions.z-1); + double phiNorm = 2.0*M_PI*(double)z/(double)(outDimensions.z-1); // Go to physical coordinates before sampling - float rPh = _xMin + rNorm*(_xMax-_xMin); - float thetaPh = thetaNorm; + double rPh = _xMin + rNorm*(_xMax-_xMin); + double thetaPh = thetaNorm; // phi range needs to be mapped to the slightly different model // range to avoid gaps in the data Subtract a small term to // avoid rounding errors when comparing to phiMax. - float phiPh = _zMin + phiNorm/(2.0*M_PI)*(_zMax-_zMin-0.000001); + double phiPh = _zMin + phiNorm/(2.0*M_PI)*(_zMax-_zMin-0.000001); - float varValue = 0.f; + double varValue = 0.f; // See if sample point is inside domain if (rPh < _xMin || rPh > _xMax || thetaPh < _yMin || thetaPh > _yMax || phiPh < _zMin || phiPh > _zMax) { @@ -163,7 +176,7 @@ float* KameleonWrapper::getUniformSampledValues(const std::string& var, glm::siz varValue = _interpolator->interpolate(var, rPh, thetaPh, phiPh); } - data[index] = (varValue-varMin)/(varMax-varMin); + doubleData[index] = (varValue-varMin)/(varMax-varMin); } } } @@ -171,6 +184,30 @@ float* KameleonWrapper::getUniformSampledValues(const std::string& var, glm::siz std::cout << std::endl; LINFO("Done!"); + int sum = 0; + int stop; + const int sumuntil = size * truncLim; + for(int i = 0; i < bins-1; ++i) { + sum += histogram[i]; + if(sum + histogram[i+1] > sumuntil) { + stop = i; + LDEBUG("===================="); + break; + } + LDEBUG(histogram[i]); + } + + double dist = varMax - varMin; + dist = (dist / static_cast(bins)) * static_cast(stop); + + varMax = varMin + dist; + for(int i = 0; i < size; ++i) { + double normalizedVal = (doubleData[i]-varMin)/(varMax-varMin); + + data[i] = static_cast(glm::clamp(normalizedVal, 0.0, 1.0)); + } + delete[] doubleData; + return data; } From 1bbf2e0148152232bc70204fade7067dd922a2f1 Mon Sep 17 00:00:00 2001 From: Jonas Strandstedt Date: Wed, 18 Jun 2014 11:13:20 -0400 Subject: [PATCH 22/49] Pointed to latest Openspace-data --- openspace-data | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openspace-data b/openspace-data index 835261f477..df25ff25dd 160000 --- a/openspace-data +++ b/openspace-data @@ -1 +1 @@ -Subproject commit 835261f4775ac7a7e5fcd000b1e254d4c947e389 +Subproject commit df25ff25dd392ed68dfff075bd8babce7fb5c5e1 From 9226c6818123a57e49577ee1950114ba6c7a5855 Mon Sep 17 00:00:00 2001 From: Jonas Strandstedt Date: Wed, 18 Jun 2014 11:45:35 -0400 Subject: [PATCH 23/49] Pointing to latest Openspace-data --- openspace-data | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openspace-data b/openspace-data index df25ff25dd..7b9a59556d 160000 --- a/openspace-data +++ b/openspace-data @@ -1 +1 @@ -Subproject commit df25ff25dd392ed68dfff075bd8babce7fb5c5e1 +Subproject commit 7b9a59556dd521ce3f7a17a1b81ab39610c1758b From 3fe447274f53061f829e29f290b57596a448d493 Mon Sep 17 00:00:00 2001 From: Jonas Strandstedt Date: Mon, 23 Jun 2014 16:59:19 -0400 Subject: [PATCH 24/49] Added intermediate ABuffer class to handle shader - Refactored a lot of stuff --- include/openspace/abuffer/abuffer.h | 81 ++++++ .../openspace/abuffer/abufferSingleLinked.h | 31 +-- include/openspace/abuffer/abuffer_i.h | 3 - .../rendering/renderablefieldlines.h | 9 +- include/openspace/rendering/renderengine.h | 4 +- shaders/ABuffer/abufferAddToBuffer.hglsl | 30 +- shaders/ABuffer/abufferResolveFragment.glsl | 123 ++++++--- shaders/ABuffer/abufferSort.hglsl | 12 +- shaders/ABuffer/abufferStruct.hglsl | 34 ++- src/abuffer/abuffer.cpp | 241 ++++++++++++++++ src/abuffer/abufferSingleLinked.cpp | 258 ++++-------------- src/engine/openspaceengine.cpp | 1 - src/rendering/renderablefieldlines.cpp | 41 ++- src/rendering/renderengine.cpp | 2 + 14 files changed, 555 insertions(+), 315 deletions(-) create mode 100644 include/openspace/abuffer/abuffer.h create mode 100644 src/abuffer/abuffer.cpp diff --git a/include/openspace/abuffer/abuffer.h b/include/openspace/abuffer/abuffer.h new file mode 100644 index 0000000000..17eb4f4592 --- /dev/null +++ b/include/openspace/abuffer/abuffer.h @@ -0,0 +1,81 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __ABUFFER_H__ +#define __ABUFFER_H__ + +#include + +#include +#include + +#include +#include + +namespace ghoul { + namespace opengl { + class Texture; + } +} + +namespace openspace { + +class ABuffer: public ABuffer_I { +public: + ABuffer(); + virtual ~ABuffer() {}; + virtual void resolve(); + +protected: + virtual std::string settings() = 0; + + bool initializeABuffer(); + + void generateShaderSource(); + bool updateShader(); + + std::string openspaceHeaders(); + std::string openspaceSamplerCalls(); + std::string openspaceSamplers(); + + unsigned int _width, _height, _totalPixels; + GLuint _screenQuad; + + bool _validShader; + std::string _fragmentShaderPath; + ghoul::filesystem::File* _fragmentShaderFile; + ghoul::opengl::ProgramObject* _resolveShader; + + std::vector > _volumes; + std::vector > _transferFunctions; + std::vector _samplers; + +private: + + + +}; // ABuffer +} // openspace + +#endif // __ABUFFER_H__ \ No newline at end of file diff --git a/include/openspace/abuffer/abufferSingleLinked.h b/include/openspace/abuffer/abufferSingleLinked.h index 5e946af48a..b800dfb856 100644 --- a/include/openspace/abuffer/abufferSingleLinked.h +++ b/include/openspace/abuffer/abufferSingleLinked.h @@ -25,14 +25,11 @@ #ifndef __ABUFFERSINGLELINKED_H__ #define __ABUFFERSINGLELINKED_H__ -#include - -#include -#include +#include namespace openspace { -class ABufferSingleLinked: public ABuffer_I { +class ABufferSingleLinked: public ABuffer { public: ABufferSingleLinked(); @@ -42,28 +39,20 @@ public: virtual void clear(); virtual void preRender(); virtual void postRender(); - virtual void resolve(); + + virtual std::string settings(); private: + GLuint *_data; + GLuint _anchorPointerTexture; + GLuint _anchorPointerTextureInitializer; + GLuint _atomicCounterBuffer; + GLuint _fragmentBuffer; + GLuint _fragmentTexture; - unsigned int width, height, totalPixels, maxFragments; - GLuint *data; - GLuint anchorPointerTexture; - GLuint anchorPointerTextureInitializer; - GLuint atomicCounterBuffer; - GLuint fragmentBuffer; - GLuint fragmentTexture; - GLuint _screenQuad; - ghoul::opengl::ProgramObject* _resolveShader; - ghoul::filesystem::File* _fragmentShaderFile; - std::string _fragmentShaderPath; - bool _updateShader; - - void generateShaderSource(); - bool updateShader(); }; // ABuffer_I } // openspace diff --git a/include/openspace/abuffer/abuffer_i.h b/include/openspace/abuffer/abuffer_i.h index 8ee04eedb7..04a8e4277c 100644 --- a/include/openspace/abuffer/abuffer_i.h +++ b/include/openspace/abuffer/abuffer_i.h @@ -25,9 +25,6 @@ #ifndef __ABUFFER_I_H__ #define __ABUFFER_I_H__ -#include -#include - namespace openspace { class ABuffer_I { diff --git a/include/openspace/rendering/renderablefieldlines.h b/include/openspace/rendering/renderablefieldlines.h index e26c7c2b54..1b0941b750 100644 --- a/include/openspace/rendering/renderablefieldlines.h +++ b/include/openspace/rendering/renderablefieldlines.h @@ -32,12 +32,6 @@ #include #include -#ifdef __APPLE__ - #include -#else - #include -#endif - namespace openspace { class RenderableFieldlines : public Renderable { @@ -61,8 +55,6 @@ private: ghoul::opengl::ProgramObject *_fieldlinesProgram, *_seedpointsProgram; GLuint _VAO, _seedpointVAO; - std::mutex* _shaderMutex; - ghoul::filesystem::File* _vertexSourceFile; ghoul::filesystem::File* _fragmentSourceFile; @@ -70,6 +62,7 @@ private: std::vector _lineCount, _seedpointCount; bool _programUpdateOnSave; + bool _update; void safeShaderCompilation(); }; diff --git a/include/openspace/rendering/renderengine.h b/include/openspace/rendering/renderengine.h index 52c32db385..be597cb8b0 100644 --- a/include/openspace/rendering/renderengine.h +++ b/include/openspace/rendering/renderengine.h @@ -30,7 +30,7 @@ #include #include -#include +#include namespace openspace { @@ -61,7 +61,7 @@ private: Camera* _mainCamera; SceneGraph* _sceneGraph; - ABuffer_I* _abuffer; + ABuffer* _abuffer; }; } // namespace openspace diff --git a/shaders/ABuffer/abufferAddToBuffer.hglsl b/shaders/ABuffer/abufferAddToBuffer.hglsl index 2127bf8715..2833d59425 100644 --- a/shaders/ABuffer/abufferAddToBuffer.hglsl +++ b/shaders/ABuffer/abufferAddToBuffer.hglsl @@ -3,10 +3,38 @@ layout (binding = 0, r32ui) uniform uimage2D anchorPointerTexture; layout (binding = 1, rgba32ui) uniform uimageBuffer fragmentTexture; layout (binding = 0, offset = 0) uniform atomic_uint atomicCounterBuffer; +ABufferStruct_t createGeometryFragment(vec4 fragColor, vec4 position = vec4(0), float z = gl_FragCoord.z) { + ABufferStruct_t frag; + _col_(frag, fragColor); + _z_(frag, z); + _type_(frag, 0); + _pos_(frag, position); + return frag; +} + void addToBuffer(ABufferStruct_t frag) { uint index = atomicCounterIncrement(atomicCounterBuffer); + index *= 2; uint old_head = imageAtomicExchange(anchorPointerTexture, ivec2(gl_FragCoord.xy), index); _next_(frag,old_head); - imageStore(fragmentTexture, int(index), _uvec4_(frag)); + + uvec4 p1 = uvec4(frag.z, frag.id, frag.rg, frag.ba); + uvec4 p2 = uvec4(floatBitsToUint(frag.position.x),floatBitsToUint(frag.position.y),floatBitsToUint(frag.position.z),floatBitsToUint(frag.position.w)); + + imageStore(fragmentTexture, int(index), p1); + imageStore(fragmentTexture, int(index+1), p2); +} + +ABufferStruct_t loadFromBuffer(uint id) { + + uvec4 u1 = imageLoad(fragmentTexture, int(id)); + uvec4 u2 = imageLoad(fragmentTexture, int(id+1)); + + vec4 position = vec4( uintBitsToFloat(u2.x), + uintBitsToFloat(u2.y), + uintBitsToFloat(u2.z), + uintBitsToFloat(u2.w)); + + return ABufferStruct_t(u1.x, u1.y, u1.z, u1.w, position); } \ No newline at end of file diff --git a/shaders/ABuffer/abufferResolveFragment.glsl b/shaders/ABuffer/abufferResolveFragment.glsl index 84c7720f25..f795c12475 100644 --- a/shaders/ABuffer/abufferResolveFragment.glsl +++ b/shaders/ABuffer/abufferResolveFragment.glsl @@ -1,39 +1,73 @@ +/***************************************************************************************** +* * +* OpenSpace * +* * +* Copyright (c) 2014 * +* * +* Permission is hereby granted, free of charge, to any person obtaining a copy of this * +* software and associated documentation files (the "Software"), to deal in the Software * +* without restriction, including without limitation the rights to use, copy, modify, * +* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * +* permit persons to whom the Software is furnished to do so, subject to the following * +* conditions: * +* * +* The above copyright notice and this permission notice shall be included in all copies * +* or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * +* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * +* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * +* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * +* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * +* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * +****************************************************************************************/ + #version 430 +// ================================================================================ +// Settings +// ================================================================================ +#pragma openspace insert SETTINGS +#define LOOP_LIMIT 800 +#define MAX_FRAGMENTS 16 +#define SHOWFUNC +const float stepSize = 0.01; +const float samplingRate = 1.0; + uniform int SCREEN_WIDTH; uniform int SCREEN_HEIGHT; -uniform float ALPHA_LIMIT = 0.95; +uniform float ALPHA_LIMIT = 0.98; in vec2 texCoord; out vec4 color; -// settings -#define LOOP_LIMIT 800 -#define MAX_FRAGMENTS 16 -#define SHOWFUNC - -// GENERATED CONTENT +// ================================================================================ +// Headers, +// volume and transferfunctions uniforms +// ================================================================================ #pragma openspace insert HEADERS -// END GENERATED CONTENT -const float stepSize = 0.01; -const float samplingRate = 1.0; float volumeStepSize[] = { stepSize }; - +// ================================================================================ +// The ABuffer specific includes and definitions +// ================================================================================ #include "abufferStruct.hglsl" ABufferStruct_t fragments[MAX_FRAGMENTS]; vec3 volume_direction[MAX_VOLUMES]; float volume_length[MAX_VOLUMES]; vec2 volume_zlength[MAX_VOLUMES]; +// float volume_zlength[MAX_VOLUMES]; vec3 volume_position[MAX_VOLUMES]; #include "abufferSort.hglsl" - +// ================================================================================ +// Blend functions +// ================================================================================ vec4 blend(vec4 src, vec4 dst) { vec4 o; o.a = src.a + dst.a * (1.0f - src.a); @@ -104,7 +138,7 @@ vec4 calculate_final_color(uint frag_count) { int volID = type -1; float p = 0.0f; - //const float l = volume_length[volID]; + // const float l = volume_length[volID]; const float S1 = volume_zlength[volID].x; const float S2 = volume_zlength[volID].y; const float L = S1 - S2; @@ -116,6 +150,21 @@ vec4 calculate_final_color(uint frag_count) { int max_iterations = int(l / volumeStepSize[volID]); int iterations = 0; vec3 position; + + + // const float S1 = volume_zlength[volID].x; + // const float S2 = volume_zlength[volID].y; + + // const float L = volume_zlength[volID]; + // const vec4 p1 = _pos_(startFrag); + // const vec4 p2 = _pos_(endFrag); + // const float dist = pscLength(p1, p2); + // // const float z1 = _z_(startFrag); + // // const float z2 = _z_(endFrag); + // const float l = (dist / L) * volume_length[volID]; + // int max_iterations = int(l / volumeStepSize[volID]); + // int iterations = 0; + // vec3 position; // MIP // vec4 tmp, color = vec4(0); @@ -136,13 +185,11 @@ vec4 calculate_final_color(uint frag_count) { for(int k = 0; k < max_iterations && k < LOOP_LIMIT; ++k) { //while(p < l && iterations < LOOP_LIMIT) { -// GENERATED CONTENT #pragma openspace insert SAMPLERCALLS -// END GENERATED CONTENT //final_color = blend(final_color, color*stepSize); - volume_position[volID] += volume_direction[volID]*volumeStepSize[volID]; + //volume_position[volID] += volume_direction[volID]*volumeStepSize[volID]; //p+= stepSize; //++iterations; } @@ -168,38 +215,48 @@ vec4 calculate_final_color(uint frag_count) { // if(frag_count > 0) // final_color = _col_(fragments[0]); + +// ================================================================================ +// Transferfunction visualizer +// ================================================================================ #ifdef SHOWFUNC - float showfunc_size = 20.0; - if(gl_FragCoord.y > float(SCREEN_HEIGHT) - showfunc_size) { - float normalizedIntensity = gl_FragCoord.x / float(SCREEN_WIDTH) ; - vec4 tfc = texture(transferFunction, normalizedIntensity); - final_color = tfc; - } else if(ceil(gl_FragCoord.y) == float(SCREEN_HEIGHT) - showfunc_size) { - const float intensity = 0.4; - final_color = vec4(intensity,intensity,intensity,1.0); - } + float showfunc_size = 20.0; + if(gl_FragCoord.y > float(SCREEN_HEIGHT) - showfunc_size) { + float normalizedIntensity = gl_FragCoord.x / float(SCREEN_WIDTH) ; + vec4 tfc = texture(transferFunction1, normalizedIntensity); + final_color = tfc; + } else if(ceil(gl_FragCoord.y) == float(SCREEN_HEIGHT) - showfunc_size) { + const float intensity = 0.4; + final_color = vec4(intensity,intensity,intensity,1.0); + } #endif + // if(frag_count == 1) { + // final_color = vec4(0.0,0.0,1.0,1.0); + // } else if(frag_count == 2) { + // final_color = vec4(volume_direction[0],1.0); + // } else { + // final_color = vec4(1.0,1.0,1.0,1.0); + // } + return final_color; } - +// ================================================================================ +// Main function +// ================================================================================ void main() { color = vec4(texCoord,0.0,1.0); int frag_count = build_local_fragments_list(); sort_fragments_list(frag_count); - - - color = calculate_final_color(frag_count); - - //color = vec4(float(frag_count) / 5.0, 0.0, 0.0, 1.0); } -// GENERATED CONTENT +// ================================================================================ +// The samplers implementations +// ================================================================================ #pragma openspace insert SAMPLERS -// END GENERATED CONTENT diff --git a/shaders/ABuffer/abufferSort.hglsl b/shaders/ABuffer/abufferSort.hglsl index c8becb8b00..a37bd85df2 100644 --- a/shaders/ABuffer/abufferSort.hglsl +++ b/shaders/ABuffer/abufferSort.hglsl @@ -1,10 +1,5 @@ -// texture bindings -layout (binding = 0, r32ui) uniform uimage2D anchorPointerTexture; -layout (binding = 1, rgba32ui) uniform uimageBuffer fragmentTexture; - -// atomic buffer bindings -layout (binding = 0, offset = 0) uniform atomic_uint atomicCounterBuffer; +#include "abufferAddToBuffer.hglsl" int build_local_fragments_list() { uint current; @@ -13,7 +8,7 @@ int build_local_fragments_list() { current = imageLoad(anchorPointerTexture, ivec2(gl_FragCoord.xy)).x; while(current != 0 && frag_count < MAX_FRAGMENTS) { - ABufferStruct_t item = _ABufferStruct_t_(imageLoad(fragmentTexture, int(current))); + ABufferStruct_t item = loadFromBuffer(current); current = _next_(item); fragments[frag_count] = item; @@ -70,8 +65,9 @@ void sort_fragments_list(uint frag_count) { volume_length[ii] = length(dir); volume_direction[ii] = normalize(dir); volume_zlength[ii].y = _z_(fragments[jj]); + // volume_zlength[ii] = pscLength(_pos_(fragments[jj]), startPosition); volumeStepSize[ii] = 1.0/(length(volume_direction[ii]*volume_dim[ii])); - //volume_length[ii] = pscLength(_pos_(fragments[jj]), startPosition); + // volume_length[ii] = pscLength(_pos_(fragments[jj]), startPosition); break; } } diff --git a/shaders/ABuffer/abufferStruct.hglsl b/shaders/ABuffer/abufferStruct.hglsl index f220fbb02f..6e050ffe05 100644 --- a/shaders/ABuffer/abufferStruct.hglsl +++ b/shaders/ABuffer/abufferStruct.hglsl @@ -5,13 +5,23 @@ //======================================================= // ABufferStruct_t declaration //======================================================= +// struct ABufferStruct_t { +// uint z; // the depth value +// uint id; // bits 0-28 next, bits 29-32 type +// vec4 color; // packed rgba +// //vec4 position; // packed position +// // uint padding1; +// // uint padding2; +// }; struct ABufferStruct_t { uint z; // the depth value uint id; // bits 0-28 next, bits 29-32 type - uint color; // packed rgba - uint position; // packed position + uint rg; // packed red green color + uint ba; // packed blue alpha color + vec4 position; // position }; + //======================================================= // Bitwise operations //======================================================= @@ -78,17 +88,23 @@ void _next_(inout ABufferStruct_t frag, uint id) { } vec4 _pos_(ABufferStruct_t frag) { - return unpackUnorm4x8(frag.position); + // return vec4(0.0,0.0,0.0,0.0); + return frag.position; + //return unpackUnorm4x8(frag.position); } void _pos_(inout ABufferStruct_t frag, vec4 position) { - frag.position = packUnorm4x8(position); + frag.position = position; + // frag.position = packUnorm4x8(position); } vec4 _col_(ABufferStruct_t frag) { - return unpackUnorm4x8(frag.color); + return vec4(unpackUnorm2x16(frag.rg),unpackUnorm2x16(frag.ba)); + //return unpackUnorm4x8(frag.color); } void _col_(inout ABufferStruct_t frag, vec4 color) { - frag.color = packUnorm4x8(color); + frag.rg = packUnorm2x16(color.rg); + frag.ba = packUnorm2x16(color.ba); + //frag.color = packUnorm4x8(color); } uint _type_(ABufferStruct_t frag) { @@ -100,10 +116,4 @@ void _type_(inout ABufferStruct_t frag, uint type) { //frag.type = type; } -ABufferStruct_t _ABufferStruct_t_(uvec4 frag) { - return ABufferStruct_t(frag.x, frag.y, frag.z, frag.w); -}; -uvec4 _uvec4_(ABufferStruct_t frag) { - return uvec4(frag.z, frag.id, frag.color, frag.position); -}; #endif \ No newline at end of file diff --git a/src/abuffer/abuffer.cpp b/src/abuffer/abuffer.cpp new file mode 100644 index 0000000000..8b9630f63e --- /dev/null +++ b/src/abuffer/abuffer.cpp @@ -0,0 +1,241 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include +#include + +#include +#include +#include + +#include +#include +#include + +namespace { + std::string _loggerCat = "ABuffer"; + +std::string padGeneratedString(const std::string& content) { + std::string _content_ = "// GENERATED CONTENT\n" + content + "\n// END GENERATED CONTENT"; + return _content_; +} + +} + +namespace openspace { + +ABuffer::ABuffer(): _validShader(true) { + int x1, xSize, y1, ySize; + sgct::Engine::instance()->getActiveWindowPtr()->getCurrentViewportPixelCoords(x1, y1, xSize, ySize); + _width = xSize; + _height = ySize; + _totalPixels = _width * _height; + const std::string fragmentShaderSourcePath = absPath("${SHADERS}/ABuffer/abufferResolveFragment.glsl"); + _fragmentShaderFile = new ghoul::filesystem::File(fragmentShaderSourcePath, true); + _fragmentShaderPath = fragmentShaderSourcePath.substr(0, fragmentShaderSourcePath.length()-4) + "gglsl"; +} + +bool ABuffer::initializeABuffer() { + // ============================ + // SHADERS + // ============================ + auto shaderCallback = [this](const ghoul::filesystem::File& file) { + _validShader = false; + }; + _fragmentShaderFile->setCallback(shaderCallback); + + _resolveShader = nullptr; + generateShaderSource(); + updateShader(); + + // ============================ + // GEOMETRY (quad) + // ============================ + const GLfloat size = 1.0f; + const GLfloat vertex_data[] = { // square of two triangles (sigh) + // x y z w s t + -size, -size, 0.0f, 1.0f, + size, size, 0.0f, 1.0f, + -size, size, 0.0f, 1.0f, + -size, -size, 0.0f, 1.0f, + size, -size, 0.0f, 1.0f, + size, size, 0.0f, 1.0f, + }; + GLuint vertexPositionBuffer; + glGenVertexArrays(1, &_screenQuad); // generate array + glBindVertexArray(_screenQuad); // bind array + glGenBuffers(1, &vertexPositionBuffer); // generate buffer + glBindBuffer(GL_ARRAY_BUFFER, vertexPositionBuffer); // bind buffer + glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data, GL_STATIC_DRAW); + glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*4, reinterpret_cast(0)); + glEnableVertexAttribArray(0); + + return true; +} + +void ABuffer::resolve() { + if( ! _validShader) { + _validShader = true; + generateShaderSource(); + updateShader(); + + } + + if(_resolveShader) { + _resolveShader->activate(); + int startAt = 0; + for(int i = 0; i < _volumes.size(); ++i) { + glActiveTexture(GL_TEXTURE0 + i); + _volumes.at(i).second->bind(); + startAt = i + 1; + } + for(int i = 0; i < _transferFunctions.size(); ++i) { + glActiveTexture(GL_TEXTURE0 + startAt + i); + _transferFunctions.at(i).second->bind(); + } + + glBindVertexArray(_screenQuad); + glDrawArrays(GL_TRIANGLES, 0, 6); + + _resolveShader->deactivate(); + } +} + +bool ABuffer::updateShader() { + + using ghoul::opengl::ShaderObject; + using ghoul::opengl::ProgramObject; + ShaderObject* vs + = new ShaderObject(ShaderObject::ShaderType::ShaderTypeVertex, + absPath("${SHADERS}/ABuffer/abufferResolveVertex.glsl"), "Vertex"); + ShaderObject* fs + = new ShaderObject(ShaderObject::ShaderType::ShaderTypeFragment,_fragmentShaderPath, "Fragment"); + + ghoul::opengl::ProgramObject* resolveShader = new ProgramObject; + resolveShader->attachObject(vs); + resolveShader->attachObject(fs); + + if (!resolveShader->compileShaderObjects()) { + LERROR("Could not compile shader"); + return false; + } + if (!resolveShader->linkProgramObject()){ + LERROR("Could not link shader"); + return false; + } + + int startAt = 0; + for(int i = 0; i < _volumes.size(); ++i) { + resolveShader->setUniform(_volumes.at(i).first, i); + startAt = i + 1; + } + for(int i = 0; i < _transferFunctions.size(); ++i) { + resolveShader->setUniform(_transferFunctions.at(i).first, startAt + i); + } + + resolveShader->setUniform("SCREEN_WIDTH", static_cast(_width)); + resolveShader->setUniform("SCREEN_HEIGHT", static_cast(_height)); + + if(_resolveShader) + delete _resolveShader; + + _resolveShader = resolveShader; + LDEBUG("Successfully updated shader!"); + return true; +} + +void ABuffer::generateShaderSource() { + std::string line, source = ""; + std::ifstream fragmentShaderFile(_fragmentShaderFile->path()); + if(fragmentShaderFile.is_open()) { + while(std::getline(fragmentShaderFile, line)) { + if(line == "#pragma openspace insert HEADERS") { + line = padGeneratedString(openspaceHeaders()); + } else if(line == "#pragma openspace insert SAMPLERCALLS") { + line = padGeneratedString(openspaceSamplerCalls()); + } else if(line == "#pragma openspace insert SAMPLERS") { + line = padGeneratedString(openspaceSamplers()); + } else if(line == "#pragma openspace insert SETTINGS") { + line = padGeneratedString(settings()); + } + source += line + "\n"; + } + } + fragmentShaderFile.close(); + + std::ofstream fragmentShaderOut(_fragmentShaderPath); + fragmentShaderOut << source; + fragmentShaderOut.close(); +} + +std::string ABuffer::openspaceHeaders() { + + std::string headers; + headers += "#define MAX_VOLUMES " + std::to_string(_volumes.size()) + "\n"; + for (int i = 0; i < _volumes.size(); ++i) { + headers += "uniform sampler3D " + _volumes.at(i).first + ";\n"; + //headers += "void sampleVolume" + std::to_string(i+1) + "(inout vec4, vec3);\n"; + } + for (int i = 0; i < _transferFunctions.size(); ++i) { + headers += "uniform sampler1D " + _transferFunctions.at(i).first + ";\n"; + } + + for (int i = 0; i < _samplers.size(); ++i) { + auto found = _samplers.at(i).find_first_of('{'); + if(found!=std::string::npos) { + headers += _samplers.at(i).substr(0, found) + ";\n"; + } + } + + headers += "const vec3 volume_dim[] = {\n"; + for (int i = 0; i < _volumes.size(); ++i) { + glm::size3_t size = _volumes.at(i).second->dimensions(); + headers += " vec3(" + std::to_string(size[0]) + ".0," + std::to_string(size[1]) + ".0," + + std::to_string(size[2]) + ".0),\n"; + } + headers += "};\n"; + return headers; +} + +std::string ABuffer::openspaceSamplerCalls() { + std::string samplercalls; + for (int i = 0; i < _volumes.size(); ++i) { + samplercalls += "if((currentVolumeBitmask & (1 << " + std::to_string(i) + ")) == 1) {\n"; + samplercalls += "sampleVolume" + std::to_string(i + 1) + "(final_color,volume_position[" + std::to_string(i) + "]);\n"; + samplercalls += "volume_position[" + std::to_string(i) + "] += volume_direction[" + std::to_string(i) + "]*volumeStepSize[" + std::to_string(i) + "];;\n"; + samplercalls += "}\n"; + } + return samplercalls; +} + +std::string ABuffer::openspaceSamplers() { + std::string samplers; + for (int i = 0; i < _samplers.size(); ++i) { + samplers += _samplers.at(i) + "\n"; + } + return samplers; +} + + +} // openspace \ No newline at end of file diff --git a/src/abuffer/abufferSingleLinked.cpp b/src/abuffer/abufferSingleLinked.cpp index 8b64a1ae6f..fef69a2524 100644 --- a/src/abuffer/abufferSingleLinked.cpp +++ b/src/abuffer/abufferSingleLinked.cpp @@ -27,76 +27,28 @@ #include #include -#include #include #include +#include #define MAX_LAYERS 10 #define BUFFER_OFFSET(i) ((char *)NULL + (i)) namespace { std::string _loggerCat = "ABufferSingleLinked"; - -const std::string openspaceHeaders = R"( -#define MAX_VOLUMES 1 -// VOLUME1 -uniform sampler3D volume; -uniform sampler1D transferFunction; -void sampleVolume1(inout vec4 finalColor, vec3 position); - - -const vec3 volume_dim[] = { - vec3(300.0,100.0,100.0) -}; -)"; - -const std::string openspaceSamplerCalls = R"( -if((currentVolumeBitmask & (1 << 0)) == 1) - sampleVolume1(final_color,volume_position[volID]); -)"; - -const std::string openspaceSamplers = R"( -void sampleVolume1(inout vec4 finalColor, vec3 position) { - float intensity = texture(volume, position).x; - //intensity *=25.0; - //intensity = clamp(intensity*100.0, 0.0, 1.0); - vec4 color = texture(transferFunction, intensity); - blendStep(finalColor, color, stepSize); -} -)"; - } namespace openspace { -ABufferSingleLinked::ABufferSingleLinked() { - int x1, xSize, y1, ySize; - sgct::Engine::instance()->getActiveWindowPtr()->getCurrentViewportPixelCoords(x1, y1, xSize, ySize); - width = xSize; - height = ySize; - totalPixels = width * height; - maxFragments = totalPixels * MAX_LAYERS; - data = 0; - anchorPointerTexture = 0; - anchorPointerTextureInitializer = 0; - atomicCounterBuffer = 0; - fragmentBuffer = 0; - fragmentTexture = 0; - - const std::string fragmentShaderSourcePath = absPath("${SHADERS}/ABuffer/abufferResolveFragment.glsl"); - _fragmentShaderFile = new ghoul::filesystem::File(fragmentShaderSourcePath, true); - _updateShader = false; - _fragmentShaderPath = fragmentShaderSourcePath + ".ABuffer.gglsl"; - - generateShaderSource(); - - -} +ABufferSingleLinked::ABufferSingleLinked(): _data(0), _anchorPointerTexture(0), + _anchorPointerTextureInitializer(0), _atomicCounterBuffer(0), _fragmentBuffer(0), + _fragmentTexture(0) +{} ABufferSingleLinked::~ABufferSingleLinked() { - if(data != 0) - delete data; + if(_data != 0) + delete _data; if(_fragmentShaderFile) delete _fragmentShaderFile; @@ -104,90 +56,76 @@ ABufferSingleLinked::~ABufferSingleLinked() { if(_resolveShader) delete _resolveShader; - glDeleteTextures(1,&anchorPointerTexture); - glDeleteTextures(1,&fragmentTexture); - glDeleteBuffers(1,&anchorPointerTextureInitializer); - glDeleteBuffers(1,&atomicCounterBuffer); - glDeleteBuffers(1,&anchorPointerTextureInitializer); + glDeleteTextures(1,&_anchorPointerTexture); + glDeleteTextures(1,&_fragmentTexture); + glDeleteBuffers(1,&_anchorPointerTextureInitializer); + glDeleteBuffers(1,&_atomicCounterBuffer); + glDeleteBuffers(1,&_anchorPointerTextureInitializer); } bool ABufferSingleLinked::initialize() { // ============================ // BUFFERS // ============================ - glGenTextures(1, &anchorPointerTexture); - glBindTexture(GL_TEXTURE_2D, anchorPointerTexture); - glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, width, height, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, NULL); + glGenTextures(1, &_anchorPointerTexture); + glBindTexture(GL_TEXTURE_2D, _anchorPointerTexture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, _width, _height, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, NULL); - glGenBuffers(1, &anchorPointerTextureInitializer); - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, anchorPointerTextureInitializer); - glBufferData(GL_PIXEL_UNPACK_BUFFER, totalPixels * sizeof(GLuint), NULL, GL_STATIC_DRAW); + glGenBuffers(1, &_anchorPointerTextureInitializer); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, _anchorPointerTextureInitializer); + glBufferData(GL_PIXEL_UNPACK_BUFFER, _totalPixels * sizeof(GLuint), NULL, GL_STATIC_DRAW); - data = (GLuint*)glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY); - memset(data, 0x00, totalPixels * sizeof(GLuint)); + _data = (GLuint*)glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY); + memset(_data, 0x00, _totalPixels * sizeof(GLuint)); glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); - glGenBuffers(1, &atomicCounterBuffer); - glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer); + glGenBuffers(1, &_atomicCounterBuffer); + glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, _atomicCounterBuffer); glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(GLuint), NULL, GL_DYNAMIC_COPY); - glGenBuffers(1, &fragmentBuffer); - glBindBuffer(GL_TEXTURE_BUFFER, fragmentBuffer); - glBufferData(GL_TEXTURE_BUFFER, MAX_LAYERS*totalPixels*sizeof(GLfloat)*4, NULL, GL_DYNAMIC_COPY); + glGenBuffers(1, &_fragmentBuffer); + glBindBuffer(GL_TEXTURE_BUFFER, _fragmentBuffer); + glBufferData(GL_TEXTURE_BUFFER, MAX_LAYERS*_totalPixels*sizeof(GLfloat)*4, NULL, GL_DYNAMIC_COPY); - glGenTextures(1, &fragmentTexture); - glBindTexture(GL_TEXTURE_BUFFER, fragmentTexture); - glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32UI, fragmentBuffer); + glGenTextures(1, &_fragmentTexture); + glBindTexture(GL_TEXTURE_BUFFER, _fragmentTexture); + glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32UI, _fragmentBuffer); glBindTexture(GL_TEXTURE_BUFFER, 0); - glBindImageTexture(1, fragmentTexture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32UI); + glBindImageTexture(1, _fragmentTexture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32UI); + // ============================ + // Volume and transferfunction data // ============================ - // SHADERS - // ============================ - auto shaderCallback = [this](const ghoul::filesystem::File& file) { - _updateShader = true; - }; - _fragmentShaderFile->setCallback(shaderCallback); + ghoul::opengl::Texture* volume = nullptr; + ghoul::opengl::Texture* tf = nullptr; + OsEng.configurationManager().getValue("firstVolume", volume); + OsEng.configurationManager().getValue("firstTransferFunction", tf); + if(volume) + _volumes.push_back(std::make_pair(std::string("volume1"), volume)); + if(tf) + _transferFunctions.push_back(std::make_pair(std::string("transferFunction1"), tf)); + _samplers.push_back(R"( +void sampleVolume1(inout vec4 finalColor, vec3 position) { + float intensity = texture(volume1, position).x; + vec4 color = texture(transferFunction1, intensity); + blendStep(finalColor, color, stepSize); +} +)"); - _resolveShader = nullptr; - updateShader(); - - // ============================ - // GEOMETRY (quad) - // ============================ - const GLfloat size = 1.0f; - const GLfloat vertex_data[] = { // square of two triangles (sigh) - // x y z w s t - -size, -size, 0.0f, 1.0f, - size, size, 0.0f, 1.0f, - -size, size, 0.0f, 1.0f, - -size, -size, 0.0f, 1.0f, - size, -size, 0.0f, 1.0f, - size, size, 0.0f, 1.0f, - }; - GLuint vertexPositionBuffer; - glGenVertexArrays(1, &_screenQuad); // generate array - glBindVertexArray(_screenQuad); // bind array - glGenBuffers(1, &vertexPositionBuffer); // generate buffer - glBindBuffer(GL_ARRAY_BUFFER, vertexPositionBuffer); // bind buffer - glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data, GL_STATIC_DRAW); - glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*4, BUFFER_OFFSET(0)); - glEnableVertexAttribArray(0); - - return true; + return initializeABuffer(); } void ABufferSingleLinked::clear() { - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, anchorPointerTextureInitializer); - glBindTexture(GL_TEXTURE_2D, anchorPointerTexture); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, _anchorPointerTextureInitializer); + glBindTexture(GL_TEXTURE_2D, _anchorPointerTexture); - glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, width, height, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, NULL); + glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, _width, _height, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, NULL); glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); static const GLuint zero = 1; - glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer); + glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, _atomicCounterBuffer); glBufferSubData(GL_ATOMIC_COUNTER_BUFFER, 0, sizeof(zero), &zero); glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, 0); } @@ -195,102 +133,18 @@ void ABufferSingleLinked::clear() { void ABufferSingleLinked::preRender() { // Bind head-pointer image for read-write - glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer); - glBindImageTexture(0, anchorPointerTexture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI); - glBindImageTexture(1, fragmentTexture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32UI); + glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, _atomicCounterBuffer); + glBindImageTexture(0, _anchorPointerTexture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI); + glBindImageTexture(1, _fragmentTexture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32UI); } void ABufferSingleLinked::postRender() { - if(_updateShader) { - _updateShader = false; - generateShaderSource(); - updateShader(); - - } } -void ABufferSingleLinked::resolve() { - - if(_resolveShader) { - ghoul::opengl::Texture* volume = nullptr; - ghoul::opengl::Texture* tf = nullptr; - OsEng.configurationManager().getValue("firstVolume", volume); - OsEng.configurationManager().getValue("firstTransferFunction", tf); - _resolveShader->activate(); - - if(volume) { - glActiveTexture(GL_TEXTURE0); - volume->bind(); - } - - if(tf) { - glActiveTexture(GL_TEXTURE1); - tf->bind(); - } - //LDEBUG("SCREEN_WIDTH" << width); - glBindVertexArray(_screenQuad); - glDrawArrays(GL_TRIANGLES, 0, 6); - _resolveShader->deactivate(); - } - +std::string ABufferSingleLinked::settings() { + return R"(#define SINGLE_LINKED)"; } -bool ABufferSingleLinked::updateShader() { - - using ghoul::opengl::ShaderObject; - using ghoul::opengl::ProgramObject; - ShaderObject* vs - = new ShaderObject(ShaderObject::ShaderType::ShaderTypeVertex, - absPath("${SHADERS}/ABuffer/abufferResolveVertex.glsl"), "Vertex"); - ShaderObject* fs - = new ShaderObject(ShaderObject::ShaderType::ShaderTypeFragment,_fragmentShaderPath, "Fragment"); - - ghoul::opengl::ProgramObject* resolveShader = new ProgramObject; - resolveShader->attachObject(vs); - resolveShader->attachObject(fs); - - if (!resolveShader->compileShaderObjects()) { - LERROR("Could not compile shader"); - return false; - } - if (!resolveShader->linkProgramObject()){ - LERROR("Could not link shader"); - return false; - } - resolveShader->setUniform("volume", 0); - resolveShader->setUniform("transferFunction", 1); - resolveShader->setUniform("SCREEN_WIDTH", static_cast(width)); - resolveShader->setUniform("SCREEN_HEIGHT", static_cast(height)); - - if(_resolveShader) - delete _resolveShader; - - _resolveShader = resolveShader; - LDEBUG("Successfully updated shader!"); - return true; -} - -void ABufferSingleLinked::generateShaderSource() { - std::string line, source = ""; - std::ifstream fragmentShaderFile(_fragmentShaderFile->path()); - if(fragmentShaderFile.is_open()) { - while(std::getline(fragmentShaderFile, line)) { - if(line == "#pragma openspace insert HEADERS") { - line = openspaceHeaders; - } else if(line == "#pragma openspace insert SAMPLERCALLS") { - line = openspaceSamplerCalls; - } else if(line == "#pragma openspace insert SAMPLERS") { - line = openspaceSamplers; - } - source += line + "\n"; - } - } - fragmentShaderFile.close(); - - std::ofstream fragmentShaderOut(_fragmentShaderPath); - fragmentShaderOut << source; - fragmentShaderOut.close(); -} } // openspace \ No newline at end of file diff --git a/src/engine/openspaceengine.cpp b/src/engine/openspaceengine.cpp index ca1e7bbbab..3e63603abe 100644 --- a/src/engine/openspaceengine.cpp +++ b/src/engine/openspaceengine.cpp @@ -275,7 +275,6 @@ bool OpenSpaceEngine::initialize() _renderEngine->initialize(); sceneGraph->loadScene(sceneDescriptionPath, scenePath); sceneGraph->initialize(); - _renderEngine->setSceneGraph(sceneGraph); #ifdef FLARE_ONLY _flare = new Flare(); diff --git a/src/rendering/renderablefieldlines.cpp b/src/rendering/renderablefieldlines.cpp index 5d2882c467..135c610b24 100644 --- a/src/rendering/renderablefieldlines.cpp +++ b/src/rendering/renderablefieldlines.cpp @@ -34,8 +34,7 @@ namespace { namespace openspace { RenderableFieldlines::RenderableFieldlines(const ghoul::Dictionary& dictionary) : - Renderable(dictionary), _VAO(0), _programUpdateOnSave(false) { - _shaderMutex = new std::mutex; + Renderable(dictionary), _VAO(0), _programUpdateOnSave(false),_update(false) { if(dictionary.hasKey("Fieldlines")) { ghoul::Dictionary fieldlines; @@ -177,8 +176,9 @@ bool RenderableFieldlines::initialize() { // ------ SETUP SHADERS ----------------- auto privateCallback = [this](const ghoul::filesystem::File& file) { - safeShaderCompilation(); + _update = true; }; + if(_programUpdateOnSave) { _vertexSourceFile->setCallback(privateCallback); _fragmentSourceFile->setCallback(privateCallback); @@ -187,9 +187,6 @@ bool RenderableFieldlines::initialize() { _fieldlinesProgram->compileShaderObjects(); _fieldlinesProgram->linkProgramObject(); - //_seedpointsProgram->compileShaderObjects(); - //_seedpointsProgram->linkProgramObject(); - return true; } @@ -198,6 +195,12 @@ bool RenderableFieldlines::deinitialize() { } void RenderableFieldlines::render(const Camera* camera, const psc& thisPosition) { + + if(_update) { + _update = false; + safeShaderCompilation(); + } + glm::mat4 transform = camera->viewProjectionMatrix(); glm::mat4 camTransform = camera->viewRotationMatrix(); psc relative = thisPosition-camera->position(); @@ -208,43 +211,33 @@ void RenderableFieldlines::render(const Camera* camera, const psc& thisPosition) transform = glm::scale(transform, glm::vec3(0.036*0.5*0.5)); //transform = glm::scale(transform, glm::vec3(0.1)); // Scale to avoid depth buffer problems - - // ------ FIELDLINES ----------------- - _shaderMutex->lock(); + // Activate shader _fieldlinesProgram->activate(); _fieldlinesProgram->setUniform("modelViewProjection", transform); + // ------ FIELDLINES ----------------- glBindVertexArray(_VAO); glMultiDrawArrays(GL_LINE_STRIP, &_lineStart[0], &_lineCount[0], _lineStart.size()); glBindVertexArray(0); - _fieldlinesProgram->deactivate(); - _shaderMutex->unlock(); -/* // ------ SEEDPOINTS ----------------- - _shaderMutex->lock(); - _seedpointsProgram->activate(); - _seedpointsProgram->setUniform("modelViewProjection", transform); + // glBindVertexArray(_seedpointVAO); + // glPointSize(5); + // glMultiDrawArrays(GL_POINTS, &_lineStart[0], &_lineCount[0], _seedPoints.size()); + // glBindVertexArray(0); - glBindVertexArray(_seedpointVAO); - glPointSize(5); - glMultiDrawArrays(GL_POINTS, &_lineStart[0], &_lineCount[0], _seedPoints.size()); - glBindVertexArray(0); - _seedpointsProgram->deactivate(); - _shaderMutex->unlock(); -*/ + // Deactivate shader + _fieldlinesProgram->deactivate(); } void RenderableFieldlines::update() { } void RenderableFieldlines::safeShaderCompilation() { - _shaderMutex->lock(); _fieldlinesProgram->rebuildFromFile(); _fieldlinesProgram->compileShaderObjects(); _fieldlinesProgram->linkProgramObject(); - _shaderMutex->unlock(); } std::vector > RenderableFieldlines::getFieldlinesData(std::string filename, ghoul::Dictionary hintsDictionary) { diff --git a/src/rendering/renderengine.cpp b/src/rendering/renderengine.cpp index 96891951c7..323d764e8e 100644 --- a/src/rendering/renderengine.cpp +++ b/src/rendering/renderengine.cpp @@ -55,6 +55,7 @@ RenderEngine::~RenderEngine() bool RenderEngine::initialize() { + // LDEBUG("RenderEngine::initialize()"); // init camera and set temporary position and scaling _mainCamera = new Camera(); _mainCamera->setScaling(glm::vec2(1.0, -8.0)); @@ -71,6 +72,7 @@ bool RenderEngine::initialize() bool RenderEngine::initializeGL() { + // LDEBUG("RenderEngine::initializeGL()"); sgct::SGCTWindow* wPtr = sgct::Engine::instance()->getActiveWindowPtr(); // TODO: Fix the power scaled coordinates in such a way that these values can be From fe701ddc5a8355a4b43d694bc82388fcb8ea893b Mon Sep 17 00:00:00 2001 From: Jonas Strandstedt Date: Tue, 24 Jun 2014 11:31:06 -0400 Subject: [PATCH 25/49] ABuffer uses sampler files - RenderableVolumeGL provides a filepath to sampler - ABuffer reloads all sampler files for each recompilation - ABuffer has mostly private members --- include/openspace/abuffer/abuffer.h | 12 ++++-- .../openspace/rendering/renderablevolumegl.h | 7 +--- openspace-data | 2 +- src/abuffer/abuffer.cpp | 42 +++++++++++++++++++ src/abuffer/abufferSingleLinked.cpp | 21 +++------- src/rendering/renderablevolumegl.cpp | 10 +++++ 6 files changed, 69 insertions(+), 25 deletions(-) diff --git a/include/openspace/abuffer/abuffer.h b/include/openspace/abuffer/abuffer.h index 17eb4f4592..c23422ebb4 100644 --- a/include/openspace/abuffer/abuffer.h +++ b/include/openspace/abuffer/abuffer.h @@ -43,10 +43,15 @@ namespace openspace { class ABuffer: public ABuffer_I { public: + ABuffer(); - virtual ~ABuffer() {}; + virtual ~ABuffer(); virtual void resolve(); + void addVolume(const std::string& tag,ghoul::opengl::Texture* volume); + void addTransferFunction(const std::string& tag,ghoul::opengl::Texture* transferFunction); + void addSamplerfile(const std::string& filename); + protected: virtual std::string settings() = 0; @@ -60,6 +65,8 @@ protected: std::string openspaceSamplers(); unsigned int _width, _height, _totalPixels; + +private: GLuint _screenQuad; bool _validShader; @@ -69,10 +76,9 @@ protected: std::vector > _volumes; std::vector > _transferFunctions; + std::vector _samplerFiles; std::vector _samplers; -private: - }; // ABuffer diff --git a/include/openspace/rendering/renderablevolumegl.h b/include/openspace/rendering/renderablevolumegl.h index eb39fe3065..35083fc23a 100644 --- a/include/openspace/rendering/renderablevolumegl.h +++ b/include/openspace/rendering/renderablevolumegl.h @@ -36,12 +36,6 @@ #include #include -#ifdef __APPLE__ - #include -#else - #include -#endif - namespace openspace { class RenderableVolumeGL: public RenderableVolume { @@ -61,6 +55,7 @@ private: std::string _filename; std::string _transferFunctionPath; + std::string _samplerFilename; ghoul::filesystem::File* _transferFunctionFile; diff --git a/openspace-data b/openspace-data index 7b9a59556d..b4199564cb 160000 --- a/openspace-data +++ b/openspace-data @@ -1 +1 @@ -Subproject commit 7b9a59556dd521ce3f7a17a1b81ab39610c1758b +Subproject commit b4199564cb227d8896b23016f53b5317943cbdad diff --git a/src/abuffer/abuffer.cpp b/src/abuffer/abuffer.cpp index 8b9630f63e..709aecff7a 100644 --- a/src/abuffer/abuffer.cpp +++ b/src/abuffer/abuffer.cpp @@ -56,6 +56,14 @@ ABuffer::ABuffer(): _validShader(true) { _fragmentShaderPath = fragmentShaderSourcePath.substr(0, fragmentShaderSourcePath.length()-4) + "gglsl"; } +ABuffer::~ABuffer() { + if(_fragmentShaderFile) + delete _fragmentShaderFile; + + if(_resolveShader) + delete _resolveShader; +} + bool ABuffer::initializeABuffer() { // ============================ // SHADERS @@ -122,6 +130,27 @@ void ABuffer::resolve() { } } +void ABuffer::addVolume(const std::string& tag,ghoul::opengl::Texture* volume) { + _volumes.push_back(std::make_pair(tag, volume)); +} + +void ABuffer::addTransferFunction(const std::string& tag,ghoul::opengl::Texture* transferFunction) { + _transferFunctions.push_back(std::make_pair(tag, transferFunction)); +} + +void ABuffer::addSamplerfile(const std::string& filename) { + if( ! FileSys.fileExists(filename)) + return; + + auto fileCallback = [this](const ghoul::filesystem::File& file) { + _validShader = false; + }; + ghoul::filesystem::File* file = new ghoul::filesystem::File(filename); + file->setCallback(fileCallback); + _samplerFiles.push_back(file); + _samplers.push_back(""); +} + bool ABuffer::updateShader() { using ghoul::opengl::ShaderObject; @@ -166,6 +195,19 @@ bool ABuffer::updateShader() { } void ABuffer::generateShaderSource() { + + for(int i = 0; i < _samplerFiles.size(); ++i) { + std::string line, source = ""; + std::ifstream samplerFile(_samplerFiles.at(i)->path()); + if(samplerFile.is_open()) { + while(std::getline(samplerFile, line)) { + source += line + "\n"; + } + } + samplerFile.close(); + _samplers.at(i) = source; + } + std::string line, source = ""; std::ifstream fragmentShaderFile(_fragmentShaderFile->path()); if(fragmentShaderFile.is_open()) { diff --git a/src/abuffer/abufferSingleLinked.cpp b/src/abuffer/abufferSingleLinked.cpp index fef69a2524..41180baa91 100644 --- a/src/abuffer/abufferSingleLinked.cpp +++ b/src/abuffer/abufferSingleLinked.cpp @@ -50,12 +50,6 @@ ABufferSingleLinked::~ABufferSingleLinked() { if(_data != 0) delete _data; - if(_fragmentShaderFile) - delete _fragmentShaderFile; - - if(_resolveShader) - delete _resolveShader; - glDeleteTextures(1,&_anchorPointerTexture); glDeleteTextures(1,&_fragmentTexture); glDeleteBuffers(1,&_anchorPointerTextureInitializer); @@ -100,19 +94,16 @@ bool ABufferSingleLinked::initialize() { // ============================ ghoul::opengl::Texture* volume = nullptr; ghoul::opengl::Texture* tf = nullptr; + std::string sampler = ""; OsEng.configurationManager().getValue("firstVolume", volume); OsEng.configurationManager().getValue("firstTransferFunction", tf); + OsEng.configurationManager().getValue("firstSampler", sampler); if(volume) - _volumes.push_back(std::make_pair(std::string("volume1"), volume)); + addVolume("volume1", volume); if(tf) - _transferFunctions.push_back(std::make_pair(std::string("transferFunction1"), tf)); - _samplers.push_back(R"( -void sampleVolume1(inout vec4 finalColor, vec3 position) { - float intensity = texture(volume1, position).x; - vec4 color = texture(transferFunction1, intensity); - blendStep(finalColor, color, stepSize); -} -)"); + addTransferFunction("transferFunction1", tf); + if(sampler != "") + addSamplerfile(sampler); return initializeABuffer(); } diff --git a/src/rendering/renderablevolumegl.cpp b/src/rendering/renderablevolumegl.cpp index 64b9ec3772..55fee5bb38 100644 --- a/src/rendering/renderablevolumegl.cpp +++ b/src/rendering/renderablevolumegl.cpp @@ -66,11 +66,20 @@ RenderableVolumeGL::RenderableVolumeGL(const ghoul::Dictionary& dictionary): _transferFunctionPath = findPath(transferFunctionPath); } } + _samplerFilename = ""; + if (dictionary.hasKey("Sampler")) { + if(dictionary.getValue("Sampler", _samplerFilename)) { + _samplerFilename = findPath(_samplerFilename); + } + } if( _transferFunctionPath == "") { LERROR("No transferFunction!"); } else { _transferFunctionFile = new ghoul::filesystem::File(_transferFunctionPath, true); } + if( _samplerFilename == "") { + LERROR("No samplerfile!"); + } double tempValue; @@ -108,6 +117,7 @@ bool RenderableVolumeGL::initialize() { _transferFunction->uploadTexture(); OsEng.configurationManager().setValue("firstVolume", _volume); OsEng.configurationManager().setValue("firstTransferFunction", _transferFunction); + OsEng.configurationManager().setValue("firstSampler", _samplerFilename); auto textureCallback = [this](const ghoul::filesystem::File& file) { _updateTransferfunction = true; From 4033303fd026d1e9cbc0e1c4a432a83dc742d0e9 Mon Sep 17 00:00:00 2001 From: Jonas Strandstedt Date: Tue, 24 Jun 2014 12:07:03 -0400 Subject: [PATCH 26/49] Maade the solution slightly more robust to changes --- src/abuffer/abuffer.cpp | 16 ++++++++++++---- src/rendering/renderablevolumegl.cpp | 4 ++++ 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/abuffer/abuffer.cpp b/src/abuffer/abuffer.cpp index 709aecff7a..2746c42949 100644 --- a/src/abuffer/abuffer.cpp +++ b/src/abuffer/abuffer.cpp @@ -263,10 +263,18 @@ std::string ABuffer::openspaceHeaders() { std::string ABuffer::openspaceSamplerCalls() { std::string samplercalls; for (int i = 0; i < _volumes.size(); ++i) { - samplercalls += "if((currentVolumeBitmask & (1 << " + std::to_string(i) + ")) == 1) {\n"; - samplercalls += "sampleVolume" + std::to_string(i + 1) + "(final_color,volume_position[" + std::to_string(i) + "]);\n"; - samplercalls += "volume_position[" + std::to_string(i) + "] += volume_direction[" + std::to_string(i) + "]*volumeStepSize[" + std::to_string(i) + "];;\n"; - samplercalls += "}\n"; + + auto found1 = _samplers.at(i).find_first_not_of("void "); + auto found2 = _samplers.at(i).find_first_of("(",found1); + if(found1 != std::string::npos && found2 != std::string::npos) { + std::string functionName = _samplers.at(i).substr(found1, found2 - found1); + samplercalls += "if((currentVolumeBitmask & (1 << " + std::to_string(i) + ")) == 1) {\n"; + samplercalls += functionName + "(final_color,volume_position[" + std::to_string(i) + "]);\n"; + samplercalls += "volume_position[" + std::to_string(i) + "] += volume_direction[" + std::to_string(i) + "]*volumeStepSize[" + std::to_string(i) + "];;\n"; + samplercalls += "}\n"; + } + + } return samplercalls; } diff --git a/src/rendering/renderablevolumegl.cpp b/src/rendering/renderablevolumegl.cpp index 55fee5bb38..722ffc0802 100644 --- a/src/rendering/renderablevolumegl.cpp +++ b/src/rendering/renderablevolumegl.cpp @@ -106,6 +106,10 @@ RenderableVolumeGL::~RenderableVolumeGL() { delete _volume; if(_colorBoxRenderer) delete _colorBoxRenderer; + if(_transferFunctionFile) + delete _transferFunctionFile; + if(_transferFunction) + delete _transferFunction; } bool RenderableVolumeGL::initialize() { From 633c95a44b1cb20489fa3f1c55fcc10c6b2d92bd Mon Sep 17 00:00:00 2001 From: Jonas Strandstedt Date: Tue, 24 Jun 2014 14:45:08 -0400 Subject: [PATCH 27/49] Started work on Samplers having IDs --- include/openspace/abuffer/abuffer.h | 2 +- .../openspace/rendering/renderablevolumegl.h | 1 + include/openspace/rendering/renderengine.h | 1 + shaders/ABuffer/abufferResolveFragment.glsl | 5 ----- src/abuffer/abuffer.cpp | 20 ++++++++++++++----- src/abuffer/abufferSingleLinked.cpp | 16 --------------- src/rendering/renderablevolumegl.cpp | 19 ++++++++++-------- src/rendering/renderengine.cpp | 4 ++++ 8 files changed, 33 insertions(+), 35 deletions(-) diff --git a/include/openspace/abuffer/abuffer.h b/include/openspace/abuffer/abuffer.h index c23422ebb4..0ba2c49782 100644 --- a/include/openspace/abuffer/abuffer.h +++ b/include/openspace/abuffer/abuffer.h @@ -50,7 +50,7 @@ public: void addVolume(const std::string& tag,ghoul::opengl::Texture* volume); void addTransferFunction(const std::string& tag,ghoul::opengl::Texture* transferFunction); - void addSamplerfile(const std::string& filename); + int addSamplerfile(const std::string& filename); protected: virtual std::string settings() = 0; diff --git a/include/openspace/rendering/renderablevolumegl.h b/include/openspace/rendering/renderablevolumegl.h index 35083fc23a..25a2629a77 100644 --- a/include/openspace/rendering/renderablevolumegl.h +++ b/include/openspace/rendering/renderablevolumegl.h @@ -66,6 +66,7 @@ private: glm::vec3 _boxScaling; bool _updateTransferfunction; + int _id; }; } // namespace openspace diff --git a/include/openspace/rendering/renderengine.h b/include/openspace/rendering/renderengine.h index be597cb8b0..2c64e84e5b 100644 --- a/include/openspace/rendering/renderengine.h +++ b/include/openspace/rendering/renderengine.h @@ -47,6 +47,7 @@ public: SceneGraph* sceneGraph(); Camera* camera() const; + ABuffer* abuffer() const; // sgct wrapped functions bool initializeGL(); diff --git a/shaders/ABuffer/abufferResolveFragment.glsl b/shaders/ABuffer/abufferResolveFragment.glsl index f795c12475..c4d61bf654 100644 --- a/shaders/ABuffer/abufferResolveFragment.glsl +++ b/shaders/ABuffer/abufferResolveFragment.glsl @@ -47,11 +47,6 @@ out vec4 color; // ================================================================================ #pragma openspace insert HEADERS - -float volumeStepSize[] = { - stepSize -}; - // ================================================================================ // The ABuffer specific includes and definitions // ================================================================================ diff --git a/src/abuffer/abuffer.cpp b/src/abuffer/abuffer.cpp index 2746c42949..8df9b833c2 100644 --- a/src/abuffer/abuffer.cpp +++ b/src/abuffer/abuffer.cpp @@ -138,9 +138,9 @@ void ABuffer::addTransferFunction(const std::string& tag,ghoul::opengl::Texture* _transferFunctions.push_back(std::make_pair(tag, transferFunction)); } -void ABuffer::addSamplerfile(const std::string& filename) { +int ABuffer::addSamplerfile(const std::string& filename) { if( ! FileSys.fileExists(filename)) - return; + return -1; auto fileCallback = [this](const ghoul::filesystem::File& file) { _validShader = false; @@ -148,7 +148,10 @@ void ABuffer::addSamplerfile(const std::string& filename) { ghoul::filesystem::File* file = new ghoul::filesystem::File(filename); file->setCallback(fileCallback); _samplerFiles.push_back(file); + + int size = _samplers.size(); _samplers.push_back(""); + return size; } bool ABuffer::updateShader() { @@ -234,10 +237,9 @@ void ABuffer::generateShaderSource() { std::string ABuffer::openspaceHeaders() { std::string headers; - headers += "#define MAX_VOLUMES " + std::to_string(_volumes.size()) + "\n"; + headers += "#define MAX_VOLUMES " + std::to_string(_samplers.size()) + "\n"; for (int i = 0; i < _volumes.size(); ++i) { headers += "uniform sampler3D " + _volumes.at(i).first + ";\n"; - //headers += "void sampleVolume" + std::to_string(i+1) + "(inout vec4, vec3);\n"; } for (int i = 0; i < _transferFunctions.size(); ++i) { headers += "uniform sampler1D " + _transferFunctions.at(i).first + ";\n"; @@ -257,12 +259,20 @@ std::string ABuffer::openspaceHeaders() { + std::to_string(size[2]) + ".0),\n"; } headers += "};\n"; + + headers += "float volumeStepSize[] = {\n"; + for (int i = 0; i < _volumes.size(); ++i) { + glm::size3_t size = _volumes.at(i).second->dimensions(); + headers += " stepSize,\n"; + } + headers += "};\n"; + return headers; } std::string ABuffer::openspaceSamplerCalls() { std::string samplercalls; - for (int i = 0; i < _volumes.size(); ++i) { + for (int i = 0; i < _samplers.size(); ++i) { auto found1 = _samplers.at(i).find_first_not_of("void "); auto found2 = _samplers.at(i).find_first_of("(",found1); diff --git a/src/abuffer/abufferSingleLinked.cpp b/src/abuffer/abufferSingleLinked.cpp index 41180baa91..84158f87d7 100644 --- a/src/abuffer/abufferSingleLinked.cpp +++ b/src/abuffer/abufferSingleLinked.cpp @@ -89,22 +89,6 @@ bool ABufferSingleLinked::initialize() { glBindImageTexture(1, _fragmentTexture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32UI); - // ============================ - // Volume and transferfunction data - // ============================ - ghoul::opengl::Texture* volume = nullptr; - ghoul::opengl::Texture* tf = nullptr; - std::string sampler = ""; - OsEng.configurationManager().getValue("firstVolume", volume); - OsEng.configurationManager().getValue("firstTransferFunction", tf); - OsEng.configurationManager().getValue("firstSampler", sampler); - if(volume) - addVolume("volume1", volume); - if(tf) - addTransferFunction("transferFunction1", tf); - if(sampler != "") - addSamplerfile(sampler); - return initializeABuffer(); } diff --git a/src/rendering/renderablevolumegl.cpp b/src/rendering/renderablevolumegl.cpp index 722ffc0802..99f27a8883 100644 --- a/src/rendering/renderablevolumegl.cpp +++ b/src/rendering/renderablevolumegl.cpp @@ -43,7 +43,7 @@ namespace openspace { RenderableVolumeGL::RenderableVolumeGL(const ghoul::Dictionary& dictionary): RenderableVolume(dictionary), _boxScaling(1.0, 1.0, 1.0), - _updateTransferfunction(false) { + _updateTransferfunction(false), _id(-1) { _filename = ""; @@ -119,9 +119,11 @@ bool RenderableVolumeGL::initialize() { _volume->uploadTexture(); _transferFunction = loadTransferFunction(_transferFunctionPath); _transferFunction->uploadTexture(); - OsEng.configurationManager().setValue("firstVolume", _volume); - OsEng.configurationManager().setValue("firstTransferFunction", _transferFunction); - OsEng.configurationManager().setValue("firstSampler", _samplerFilename); + + // TODO: fix volume an transferfunction names + OsEng.renderEngine().abuffer()->addVolume("volume1", _volume); + OsEng.renderEngine().abuffer()->addTransferFunction("transferFunction1", _transferFunction); + _id = OsEng.renderEngine().abuffer()->addSamplerfile(_samplerFilename); auto textureCallback = [this](const ghoul::filesystem::File& file) { _updateTransferfunction = true; @@ -146,7 +148,9 @@ void RenderableVolumeGL::render(const Camera *camera, const psc &thisPosition) { const void* data = transferFunction->pixelData(); glBindBuffer(GL_COPY_READ_BUFFER, *transferFunction); _transferFunction->bind(); - glTexImage1D(GL_TEXTURE_1D, 0, _transferFunction->internalFormat(), _transferFunction->width(),0, _transferFunction->format(), _transferFunction->dataType(), data); + glTexImage1D( GL_TEXTURE_1D, 0, _transferFunction->internalFormat(), + _transferFunction->width(),0, _transferFunction->format(), + _transferFunction->dataType(), data); //delete data; delete transferFunction; LDEBUG("Updated transferfunction!"); @@ -154,15 +158,14 @@ void RenderableVolumeGL::render(const Camera *camera, const psc &thisPosition) { } } - glm::mat4 transform ; - glm::mat4 camTransform = camera->viewRotationMatrix(); psc relative = thisPosition-camera->position(); - transform = camTransform; + glm::mat4 transform = camera->viewRotationMatrix(); transform = glm::translate(transform, relative.vec3()); transform = glm::translate(transform, glm::vec3(-1.1,0.0,0.0)); transform = glm::scale(transform, _boxScaling); + // TODO: Use _id to identify this volume _colorBoxRenderer->render(camera->viewProjectionMatrix(), transform); } diff --git a/src/rendering/renderengine.cpp b/src/rendering/renderengine.cpp index 323d764e8e..70fd59661d 100644 --- a/src/rendering/renderengine.cpp +++ b/src/rendering/renderengine.cpp @@ -404,4 +404,8 @@ Camera* RenderEngine::camera() const { return _mainCamera; } +ABuffer* RenderEngine::abuffer() const { + return _abuffer; +} + } // namespace openspace From ec115030a46ce0adc20e6c0ad280c2a0c84a2a6b Mon Sep 17 00:00:00 2001 From: Jonas Strandstedt Date: Tue, 24 Jun 2014 15:29:31 -0400 Subject: [PATCH 28/49] Added ID for sampler --- include/openspace/rendering/volumeraycasterbox.h | 4 ++-- shaders/exitpoints.frag | 4 +++- src/abuffer/abuffer.cpp | 6 +++--- src/rendering/renderablevolumegl.cpp | 2 +- src/rendering/volumeraycasterbox.cpp | 6 +++--- 5 files changed, 12 insertions(+), 10 deletions(-) diff --git a/include/openspace/rendering/volumeraycasterbox.h b/include/openspace/rendering/volumeraycasterbox.h index 8597a1c265..4e0a3018d5 100644 --- a/include/openspace/rendering/volumeraycasterbox.h +++ b/include/openspace/rendering/volumeraycasterbox.h @@ -45,7 +45,7 @@ public: VolumeRaycasterBox(); ~VolumeRaycasterBox(); bool initialize(); - void render(const glm::mat4& MVP,const glm::mat4& transform = glm::mat4(1.0)); + void render(const glm::mat4& MVP, const glm::mat4& transform = glm::mat4(1.0), int type = 0); ghoul::opengl::Texture* backFace(); ghoul::opengl::Texture* frontFace(); @@ -56,7 +56,7 @@ private: ghoul::opengl::Texture *_backTexture, *_frontTexture; ghoul::opengl::ProgramObject *_boxProgram; sgct_utils::SGCTBox* _boundingBox; - GLint _MVPLocation, _modelTransformLocation; + GLint _MVPLocation, _modelTransformLocation, _typeLocation; glm::size2_t _dimensions; }; diff --git a/shaders/exitpoints.frag b/shaders/exitpoints.frag index fee208094a..de2db8ee15 100644 --- a/shaders/exitpoints.frag +++ b/shaders/exitpoints.frag @@ -1,5 +1,7 @@ #version 430 core +uniform int volumeType; + in vec3 vPosition; in vec3 worldPosition; out vec4 fragColor; @@ -13,7 +15,7 @@ void main() { ABufferStruct_t frag; _col_(frag, fragColor); _z_(frag, gl_FragCoord.z); - _type_(frag, 1); + _type_(frag, volumeType); _pos_(frag, vec4(worldPosition,0)); addToBuffer(frag); diff --git a/src/abuffer/abuffer.cpp b/src/abuffer/abuffer.cpp index 8df9b833c2..b1af47bc7e 100644 --- a/src/abuffer/abuffer.cpp +++ b/src/abuffer/abuffer.cpp @@ -148,10 +148,10 @@ int ABuffer::addSamplerfile(const std::string& filename) { ghoul::filesystem::File* file = new ghoul::filesystem::File(filename); file->setCallback(fileCallback); _samplerFiles.push_back(file); - - int size = _samplers.size(); _samplers.push_back(""); - return size; + + // ID is one more than "actual" position since ID=0 is considered geometry + return _samplers.size(); } bool ABuffer::updateShader() { diff --git a/src/rendering/renderablevolumegl.cpp b/src/rendering/renderablevolumegl.cpp index 99f27a8883..518120649c 100644 --- a/src/rendering/renderablevolumegl.cpp +++ b/src/rendering/renderablevolumegl.cpp @@ -166,7 +166,7 @@ void RenderableVolumeGL::render(const Camera *camera, const psc &thisPosition) { transform = glm::scale(transform, _boxScaling); // TODO: Use _id to identify this volume - _colorBoxRenderer->render(camera->viewProjectionMatrix(), transform); + _colorBoxRenderer->render(camera->viewProjectionMatrix(), transform, _id); } diff --git a/src/rendering/volumeraycasterbox.cpp b/src/rendering/volumeraycasterbox.cpp index ad51b1eabd..4fb33a1bde 100644 --- a/src/rendering/volumeraycasterbox.cpp +++ b/src/rendering/volumeraycasterbox.cpp @@ -63,6 +63,7 @@ bool VolumeRaycasterBox::initialize() { OsEng.configurationManager().getValue("RaycastProgram", _boxProgram); _MVPLocation = _boxProgram->uniformLocation("modelViewProjection"); _modelTransformLocation = _boxProgram->uniformLocation("modelTransform"); + _typeLocation = _boxProgram->uniformLocation("volumeType"); // ------ SETUP FBO --------------------- _fbo = new FramebufferObject(); @@ -70,8 +71,6 @@ bool VolumeRaycasterBox::initialize() { // changed from getActiveXResolution to getCurrentViewportPixelCoords because // if there are more viewports in the same screen. - //size_t x = sgct::Engine::instance()->getActiveXResolution(); - //size_t y = sgct::Engine::instance()->getActiveYResolution(); int x1, xSize, y1, ySize; sgct::Engine::instance()->getActiveWindowPtr()->getCurrentViewportPixelCoords(x1, y1, xSize, ySize); size_t x = xSize; @@ -90,12 +89,13 @@ bool VolumeRaycasterBox::initialize() { return true; } -void VolumeRaycasterBox::render(const glm::mat4& MVP,const glm::mat4& transform) { +void VolumeRaycasterBox::render(const glm::mat4& MVP,const glm::mat4& transform, int type) { GLuint activeFBO = FramebufferObject::getActiveObject(); // Save SGCTs main FBO _fbo->activate(); _boxProgram->activate(); _boxProgram->setUniform(_MVPLocation, MVP); _boxProgram->setUniform(_modelTransformLocation, transform); + _boxProgram->setUniform(_typeLocation, type); sgct_core::Frustum::FrustumMode mode = sgct::Engine::instance()-> getActiveWindowPtr()-> From 437f511f48e943dd3c30da89422aac5602f1059f Mon Sep 17 00:00:00 2001 From: Jonas Strandstedt Date: Wed, 25 Jun 2014 10:21:06 -0400 Subject: [PATCH 29/49] Cleaned up fragment shader in power scaling - Added Licence to shaders --- shaders/ABuffer/abufferAddToBuffer.hglsl | 23 ++++ shaders/ABuffer/abufferResolveFragment.glsl | 44 +++---- shaders/ABuffer/abufferResolveVertex.glsl | 24 ++++ shaders/ABuffer/abufferSort.hglsl | 25 +++- shaders/ABuffer/abufferStruct.hglsl | 24 ++++ shaders/PowerScaling/powerScaling.hglsl | 90 +++++++++++++ shaders/cubeFrag.glsl | 24 ++++ shaders/cubeVert.glsl | 24 ++++ shaders/exitpoints.frag | 24 ++++ shaders/exitpoints.vert | 24 ++++ shaders/pscstandard_fs.glsl | 139 ++++---------------- shaders/pscstandard_vs.glsl | 43 +++--- shaders/quadFrag.glsl | 24 ++++ shaders/quadVert.glsl | 24 ++++ shaders/quadVertFlare.glsl | 24 ++++ shaders/singlepassraycaster.frag | 24 ++++ shaders/singlepassraycaster.gs | 24 ++++ shaders/singlepassraycaster.vert | 24 ++++ shaders/twopassraycaster.frag | 24 ++++ shaders/twopassraycaster.vert | 24 ++++ 20 files changed, 545 insertions(+), 155 deletions(-) create mode 100644 shaders/PowerScaling/powerScaling.hglsl diff --git a/shaders/ABuffer/abufferAddToBuffer.hglsl b/shaders/ABuffer/abufferAddToBuffer.hglsl index 2833d59425..3ee940f0d7 100644 --- a/shaders/ABuffer/abufferAddToBuffer.hglsl +++ b/shaders/ABuffer/abufferAddToBuffer.hglsl @@ -1,3 +1,26 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ layout (binding = 0, r32ui) uniform uimage2D anchorPointerTexture; layout (binding = 1, rgba32ui) uniform uimageBuffer fragmentTexture; diff --git a/shaders/ABuffer/abufferResolveFragment.glsl b/shaders/ABuffer/abufferResolveFragment.glsl index c4d61bf654..bbe589e045 100644 --- a/shaders/ABuffer/abufferResolveFragment.glsl +++ b/shaders/ABuffer/abufferResolveFragment.glsl @@ -1,26 +1,26 @@ /***************************************************************************************** -* * -* OpenSpace * -* * -* Copyright (c) 2014 * -* * -* Permission is hereby granted, free of charge, to any person obtaining a copy of this * -* software and associated documentation files (the "Software"), to deal in the Software * -* without restriction, including without limitation the rights to use, copy, modify, * -* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * -* permit persons to whom the Software is furnished to do so, subject to the following * -* conditions: * -* * -* The above copyright notice and this permission notice shall be included in all copies * -* or substantial portions of the Software. * -* * -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * -* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * -* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * -* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * -* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * -* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * -****************************************************************************************/ + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ #version 430 diff --git a/shaders/ABuffer/abufferResolveVertex.glsl b/shaders/ABuffer/abufferResolveVertex.glsl index ded6af8a7a..301a151753 100644 --- a/shaders/ABuffer/abufferResolveVertex.glsl +++ b/shaders/ABuffer/abufferResolveVertex.glsl @@ -1,3 +1,27 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + #version 430 in vec4 position; diff --git a/shaders/ABuffer/abufferSort.hglsl b/shaders/ABuffer/abufferSort.hglsl index a37bd85df2..2827499b11 100644 --- a/shaders/ABuffer/abufferSort.hglsl +++ b/shaders/ABuffer/abufferSort.hglsl @@ -1,4 +1,27 @@ - +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + #include "abufferAddToBuffer.hglsl" int build_local_fragments_list() { diff --git a/shaders/ABuffer/abufferStruct.hglsl b/shaders/ABuffer/abufferStruct.hglsl index 6e050ffe05..a63499ef6d 100644 --- a/shaders/ABuffer/abufferStruct.hglsl +++ b/shaders/ABuffer/abufferStruct.hglsl @@ -1,3 +1,27 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + #ifndef ABUFFERSTRUCT_H_HGLSL #define ABUFFERSTRUCT_H_HGLSL diff --git a/shaders/PowerScaling/powerScaling.hglsl b/shaders/PowerScaling/powerScaling.hglsl new file mode 100644 index 0000000000..66ddf647b1 --- /dev/null +++ b/shaders/PowerScaling/powerScaling.hglsl @@ -0,0 +1,90 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef POWERSCALING_H_HGLSL +#define POWERSCALING_H_HGLSL + +// Observable universe is 10^27m, setting the far value to extremely high, aka 30!! ERMAHGERD! + +const float k = 10.0; +const float s_far = 27.0f; //= gl_DepthRange.far; // 40 +const float s_farcutoff = 12.0f; +const float s_nearcutoff = 7.00f; +const float s_near = 0.00f;// gl_DepthRange.near; // 0.1 + +vec4 psc_normlization(vec4 invec) { + + float xymax = max(invec.x,invec.y); + + if(invec.z > 0.0f || invec.z < 0.0f) { + return invec / abs(invec.z); + } else if (xymax != 0.0f) { + return invec / xymax; + } else { + return invec / -.0; + } +} + +float pscDepth(vec4 position) { + float depth = 0.0f; + if(position.w <= 0.5) { + //depth = abs(position.z * pow(10, position.w)) / pow(k,s_far); + depth = (position.w+log(abs(position.z)))/pow(k, position.w); + } else if(position.w < 3.0) { + depth = position.w+log(abs(position.z))/pow(k, position.w); + } else { + depth = position.w+log(abs(position.z)); + } + + + // DEBUG + float depth_orig = depth; + float x = 0.0f; + float cutoffs = 0.0; + float orig_z = position.z; + + // calculate a normalized depth [0.0 1.0] + if((depth > s_near && depth <= s_nearcutoff) || (depth > s_farcutoff && depth < s_far)) { + + // completely linear interpolation [s_near .. depth .. s_far] + depth = (depth - s_near) / (s_far - s_near); + + } else if(depth > s_nearcutoff && depth < s_farcutoff) { + + // DEBUG + cutoffs = 1.0; + + // interpolate [10^s_nearcutoff .. 10^depth .. 10^s_farcutoff] + // calculate between 0..1 where the depth is + x = (pow(10,depth) - pow(10, s_nearcutoff)) / (pow(10,s_farcutoff) - pow(10, s_nearcutoff)); + + // remap the depth to the 0..1 depth buffer + depth = s_nearcutoff + x * (s_farcutoff - s_nearcutoff); + depth = (depth - s_near) / (s_far - s_near); + + } + return depth; +} + +#endif \ No newline at end of file diff --git a/shaders/cubeFrag.glsl b/shaders/cubeFrag.glsl index 0b6be3de9a..292f1396c8 100644 --- a/shaders/cubeFrag.glsl +++ b/shaders/cubeFrag.glsl @@ -1,3 +1,27 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + #version 330 in vec4 color; diff --git a/shaders/cubeVert.glsl b/shaders/cubeVert.glsl index 68a1d89d43..38393b3e3f 100644 --- a/shaders/cubeVert.glsl +++ b/shaders/cubeVert.glsl @@ -1,3 +1,27 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + #version 330 uniform mat4 projectionMatrix; diff --git a/shaders/exitpoints.frag b/shaders/exitpoints.frag index de2db8ee15..cc58d29e35 100644 --- a/shaders/exitpoints.frag +++ b/shaders/exitpoints.frag @@ -1,3 +1,27 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + #version 430 core uniform int volumeType; diff --git a/shaders/exitpoints.vert b/shaders/exitpoints.vert index 15e86a76df..80145134b3 100644 --- a/shaders/exitpoints.vert +++ b/shaders/exitpoints.vert @@ -1,3 +1,27 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + #version 430 core layout(location = 2) in vec3 vertPosition; diff --git a/shaders/pscstandard_fs.glsl b/shaders/pscstandard_fs.glsl index 85dc406b22..394ca42fc9 100644 --- a/shaders/pscstandard_fs.glsl +++ b/shaders/pscstandard_fs.glsl @@ -1,132 +1,47 @@ -/** -Copyright (C) 2012-2014 Jonas Strandstedt +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ #version 430 uniform float time; uniform sampler2D texture1; -vec3 light_position = vec3(40.0, 20.0, 100.0); - in vec2 vs_st; -//in vec3 vs_stp; in vec4 vs_normal; in vec4 vs_position; -out vec4 diffuse; - -const float k = 10.0; - #include "ABuffer/abufferStruct.hglsl" #include "ABuffer/abufferAddToBuffer.hglsl" - - -vec4 psc_normlization(vec4 invec) { - - float xymax = max(invec.x,invec.y); - - if(invec.z > 0.0f || invec.z < 0.0f) { - return invec / abs(invec.z); - } else if (xymax != 0.0f) { - return invec / xymax; - } else { - return invec / -.0; - } -} +#include "PowerScaling/powerScaling.hglsl" void main() { + float depth = pscDepth(vs_position); + vec4 diffuse = texture(texture1, vs_st); - // Observable universe is 10^27m, setting the far value to extremely high, aka 30!! ERMAHGERD! - float s_far = 27.0; //= gl_DepthRange.far; // 40 - float s_farcutoff = 12.0; - float s_nearcutoff = 7.0; - float s_near = 0.0f;// gl_DepthRange.near; // 0.1 - float depth; - - // the value can be normalized to 1 - - vec4 p = vs_position; - if(vs_position.w <= 0.5) { - //depth = abs(vs_position.z * pow(10, vs_position.w)) / pow(k,s_far); - depth = (vs_position.w+log(abs(vs_position.z)))/pow(k, vs_position.w); - } else if(vs_position.w < 3.0) { - depth = vs_position.w+log(abs(vs_position.z))/pow(k, vs_position.w); - } else { - depth = vs_position.w+log(abs(vs_position.z)); - } - - - // DEBUG - float depth_orig = depth; - float x = 0.0f; - float cutoffs = 0.0; - float orig_z = vs_position.z; - - // calculate a normalized depth [0.0 1.0] - if((depth > s_near && depth <= s_nearcutoff) || (depth > s_farcutoff && depth < s_far)) { - - // completely linear interpolation [s_near .. depth .. s_far] - depth = (depth - s_near) / (s_far - s_near); - - } else if(depth > s_nearcutoff && depth < s_farcutoff) { - - // DEBUG - cutoffs = 1.0; - - // interpolate [10^s_nearcutoff .. 10^depth .. 10^s_farcutoff] - // calculate between 0..1 where the depth is - x = (pow(10,depth) - pow(10, s_nearcutoff)) / (pow(10,s_farcutoff) - pow(10, s_nearcutoff)); - - // remap the depth to the 0..1 depth buffer - depth = s_nearcutoff + x * (s_farcutoff - s_nearcutoff); - depth = (depth - s_near) / (s_far - s_near); - - } else { - // where am I? - // do I need to be discarded? - // discard; - } - - - - - // set the depth - gl_FragDepth = depth; - //gl_FragDepth = 0.5; - - // color - diffuse = texture(texture1, vs_st); - //diffuse = vec4(vs_position.z,0.0, 0.0, 1.0); - // diffuse = vec4(vs_position.xyz * pow(10, vs_position.w), 1.0); - //diffuse = vec4(vs_st, 0.0, 1.0); - //diffuse = vec4(1.0,1.0, 0.0, 1.0); - //diffuse = vec4(depth*5,0.0, 0.0, 1.0); - //diffuse = vec4(vs_position.w,0.0, 0.0, 1.0); - //diffuse = vec4(1.0,0.0,0.0,1.0); - - ABufferStruct_t frag; - _col_(frag, diffuse); - _z_(frag, gl_FragDepth); - _type_(frag, 0); - _pos_(frag, vs_position); + ABufferStruct_t frag = createGeometryFragment(diffuse, vs_position, depth); addToBuffer(frag); - /* - uint index = atomicCounterIncrement(atomicCounterBuffer); - uint old_head = imageAtomicExchange(anchorPointerTexture, ivec2(gl_FragCoord.xy), index); - uvec4 item; - item.x = old_head; - item.y = packUnorm4x8(diffuse); - item.z = floatBitsToUint(gl_FragCoord.z / gl_FragCoord.w); - item.w = 0; - imageStore(fragmentTexture, int(index), item); -*/ discard; } \ No newline at end of file diff --git a/shaders/pscstandard_vs.glsl b/shaders/pscstandard_vs.glsl index be3ead04f7..c3de39f9dc 100644 --- a/shaders/pscstandard_vs.glsl +++ b/shaders/pscstandard_vs.glsl @@ -1,24 +1,27 @@ -/** -Copyright (C) 2012-2014 Jonas Strandstedt +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the "Software"), -to deal in the Software without restriction, including without limitation -the rights to use, copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ #version 430 uniform mat4 ViewProjection; diff --git a/shaders/quadFrag.glsl b/shaders/quadFrag.glsl index 0b4adc27c0..a52ce0a5f5 100644 --- a/shaders/quadFrag.glsl +++ b/shaders/quadFrag.glsl @@ -1,3 +1,27 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + #version 330 uniform sampler2D quadTex; diff --git a/shaders/quadVert.glsl b/shaders/quadVert.glsl index 2140173049..3221517490 100644 --- a/shaders/quadVert.glsl +++ b/shaders/quadVert.glsl @@ -1,3 +1,27 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + #version 330 layout(location = 0) in vec2 texCoordinate; diff --git a/shaders/quadVertFlare.glsl b/shaders/quadVertFlare.glsl index a3c9b18411..12b7b9fe41 100644 --- a/shaders/quadVertFlare.glsl +++ b/shaders/quadVertFlare.glsl @@ -1,3 +1,27 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + #version 330 in vec4 position; diff --git a/shaders/singlepassraycaster.frag b/shaders/singlepassraycaster.frag index 222c459ae3..e910176269 100644 --- a/shaders/singlepassraycaster.frag +++ b/shaders/singlepassraycaster.frag @@ -1,3 +1,27 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + #version 400 core // Based on http://prideout.net/blog/?p=64 diff --git a/shaders/singlepassraycaster.gs b/shaders/singlepassraycaster.gs index a393169a32..fea6d6b415 100644 --- a/shaders/singlepassraycaster.gs +++ b/shaders/singlepassraycaster.gs @@ -1,3 +1,27 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + #version 400 core // Based on http://prideout.net/blog/?p=64 diff --git a/shaders/singlepassraycaster.vert b/shaders/singlepassraycaster.vert index c33d4689b9..df013c63ae 100644 --- a/shaders/singlepassraycaster.vert +++ b/shaders/singlepassraycaster.vert @@ -1,3 +1,27 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + #version 400 core // Based on http://prideout.net/blog/?p=64 diff --git a/shaders/twopassraycaster.frag b/shaders/twopassraycaster.frag index 1e9daf5cdb..1641c013dd 100644 --- a/shaders/twopassraycaster.frag +++ b/shaders/twopassraycaster.frag @@ -1,3 +1,27 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + #version 400 core uniform sampler2D texBack, texFront; diff --git a/shaders/twopassraycaster.vert b/shaders/twopassraycaster.vert index 164a5e8643..f8453e0f57 100644 --- a/shaders/twopassraycaster.vert +++ b/shaders/twopassraycaster.vert @@ -1,3 +1,27 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + #version 400 core layout(location = 0) in vec2 texCoordinate; From 83205d6de1bb2858ea4c33d6d12e44653a1c1e87 Mon Sep 17 00:00:00 2001 From: Jonas Strandstedt Date: Wed, 25 Jun 2014 15:10:05 -0400 Subject: [PATCH 30/49] Volume raycasting jittering - Added jitter to volume rendering, reducing artefacts - Added tracking of more shader files to update the resolve shader --- include/openspace/abuffer/abuffer.h | 3 +++ shaders/ABuffer/abufferSort.hglsl | 15 ++++++++++++++ shaders/pscstandard_fs.glsl | 8 +++++--- shaders/pscstandard_vs.glsl | 31 ++++++++++++----------------- src/abuffer/abuffer.cpp | 19 ++++++++++++++++++ src/abuffer/abufferSingleLinked.cpp | 1 - 6 files changed, 55 insertions(+), 22 deletions(-) diff --git a/include/openspace/abuffer/abuffer.h b/include/openspace/abuffer/abuffer.h index 0ba2c49782..96e35ec9dd 100644 --- a/include/openspace/abuffer/abuffer.h +++ b/include/openspace/abuffer/abuffer.h @@ -79,6 +79,9 @@ private: std::vector _samplerFiles; std::vector _samplers; + // Development functionality to update shader for changes in several files + std::vector _shaderFiles; + }; // ABuffer diff --git a/shaders/ABuffer/abufferSort.hglsl b/shaders/ABuffer/abufferSort.hglsl index 2827499b11..6eaf03eed4 100644 --- a/shaders/ABuffer/abufferSort.hglsl +++ b/shaders/ABuffer/abufferSort.hglsl @@ -56,6 +56,10 @@ float pscLength(vec4 v1, vec4 v2) { return length(vector.xyz)*pow(k,vector.w); } +float permute(float i) { + return mod((62.0*i*i + i), 961.0); // permutation polynomial; 62=2*31; 961=31*31 +} + void sort_fragments_list(uint frag_count) { uint i,j; ABufferStruct_t tmp; @@ -91,6 +95,17 @@ void sort_fragments_list(uint frag_count) { // volume_zlength[ii] = pscLength(_pos_(fragments[jj]), startPosition); volumeStepSize[ii] = 1.0/(length(volume_direction[ii]*volume_dim[ii])); // volume_length[ii] = pscLength(_pos_(fragments[jj]), startPosition); + + if(volumeStepSize[ii] < volume_length[ii]) { + // jittering + float x = gl_FragCoord.x; + float y = gl_FragCoord.y; + float jitterValue = float(permute(x + permute(y))) / 961.0; + jitterValue *= 0.004; + vec3 frontPosNew = startColor + (jitterValue*volume_length[ii])*volume_direction[ii]; + volume_position[ii] = frontPosNew; + } + break; } } diff --git a/shaders/pscstandard_fs.glsl b/shaders/pscstandard_fs.glsl index 394ca42fc9..380ca7f096 100644 --- a/shaders/pscstandard_fs.glsl +++ b/shaders/pscstandard_fs.glsl @@ -29,7 +29,8 @@ uniform sampler2D texture1; in vec2 vs_st; in vec4 vs_normal; -in vec4 vs_position; +in vec3 vs_position; +in float s; #include "ABuffer/abufferStruct.hglsl" #include "ABuffer/abufferAddToBuffer.hglsl" @@ -37,10 +38,11 @@ in vec4 vs_position; void main() { - float depth = pscDepth(vs_position); + vec4 position = vec4(vs_position,s); + float depth = pscDepth(position); vec4 diffuse = texture(texture1, vs_st); - ABufferStruct_t frag = createGeometryFragment(diffuse, vs_position, depth); + ABufferStruct_t frag = createGeometryFragment(diffuse, position, depth); addToBuffer(frag); discard; diff --git a/shaders/pscstandard_vs.glsl b/shaders/pscstandard_vs.glsl index c3de39f9dc..83ba34bbfd 100644 --- a/shaders/pscstandard_vs.glsl +++ b/shaders/pscstandard_vs.glsl @@ -31,13 +31,6 @@ uniform mat4 camrot; uniform vec2 scaling; uniform vec4 objpos; uniform float time; -uniform sampler2D texture1; -uniform sampler2D texture2; -uniform sampler2D texture3; -uniform float TessLevel; -uniform bool Wireframe; -uniform bool Lightsource; -uniform bool UseTexture; layout(location = 0) in vec4 in_position; //in vec3 in_position; @@ -47,10 +40,10 @@ layout(location = 2) in vec3 in_normal; out vec2 vs_st; out vec3 vs_stp; out vec4 vs_normal; -out vec4 vs_position; +out vec3 vs_position; +out float s; const float k = 10.0; -const float dgr_to_rad = 0.0174532925; vec4 psc_addition(vec4 v1, vec4 v2) { float ds = v2.w - v1.w; @@ -92,25 +85,27 @@ void main() //vec4 lvp = ModelTransform * in_position; // PSC addition; local vertex position and the object power scaled world position - vs_position = psc_addition(vec4(local_vertex_pos,in_position.w),objpos); - //vs_position = psc_addition(lvp,objpos); + vec4 position = psc_addition(vec4(local_vertex_pos,in_position.w),objpos); + //position = psc_addition(lvp,objpos); // PSC addition; rotated and viewscaled vertex and the cmaeras negative position - vs_position = psc_addition(vs_position,vec4(-campos.xyz,campos.w)); + position = psc_addition(position,vec4(-campos.xyz,campos.w)); // rotate the camera - local_vertex_pos = mat3(camrot) * vs_position.xyz; - vs_position = vec4(local_vertex_pos, vs_position.w); - //vs_position = camrot* vs_position; + local_vertex_pos = mat3(camrot) * position.xyz; + position = vec4(local_vertex_pos, position.w); + //position = camrot* position; // rescales the scene to fit inside the view frustum // is set from the main program, but these are decent values // scaling = vec2(1.0, -8.0); // project using the rescaled coordinates, - //vec4 vs_position_rescaled = psc_scaling(vs_position, scaling); - vec4 vs_position_rescaled = psc_to_meter(vs_position, scaling); - vs_position = vs_position_rescaled; + //vec4 vs_position_rescaled = psc_scaling(position, scaling); + vec4 vs_position_rescaled = psc_to_meter(position, scaling); + position = vs_position_rescaled; + vs_position = vs_position_rescaled.xyz; + s = vs_position_rescaled.w; // project the position to view space diff --git a/src/abuffer/abuffer.cpp b/src/abuffer/abuffer.cpp index b1af47bc7e..dbb26e40fc 100644 --- a/src/abuffer/abuffer.cpp +++ b/src/abuffer/abuffer.cpp @@ -62,6 +62,14 @@ ABuffer::~ABuffer() { if(_resolveShader) delete _resolveShader; + + for(auto file: _samplerFiles) { + delete file; + } + for(auto file: _shaderFiles) { + delete file; + } + } bool ABuffer::initializeABuffer() { @@ -73,6 +81,17 @@ bool ABuffer::initializeABuffer() { }; _fragmentShaderFile->setCallback(shaderCallback); + // Development functionality to update shader for changes in several files + auto addFunc = [this, shaderCallback](const std::string& path) { + ghoul::filesystem::File* f = new ghoul::filesystem::File(path, false); + f->setCallback(shaderCallback); + _shaderFiles.push_back(f); + }; + addFunc("${SHADERS}/ABuffer/abufferSort.hglsl"); + addFunc("${SHADERS}/ABuffer/abufferAddToBuffer.hglsl"); + addFunc("${SHADERS}/ABuffer/abufferStruct.hglsl"); + + _resolveShader = nullptr; generateShaderSource(); updateShader(); diff --git a/src/abuffer/abufferSingleLinked.cpp b/src/abuffer/abufferSingleLinked.cpp index 84158f87d7..166ded0302 100644 --- a/src/abuffer/abufferSingleLinked.cpp +++ b/src/abuffer/abufferSingleLinked.cpp @@ -33,7 +33,6 @@ #include #define MAX_LAYERS 10 -#define BUFFER_OFFSET(i) ((char *)NULL + (i)) namespace { std::string _loggerCat = "ABufferSingleLinked"; From b6b6a7f51bde1995263468b61a58e290249f0510 Mon Sep 17 00:00:00 2001 From: Jonas Strandstedt Date: Wed, 25 Jun 2014 15:27:22 -0400 Subject: [PATCH 31/49] Small jitterbug fix --- shaders/ABuffer/abufferSort.hglsl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/shaders/ABuffer/abufferSort.hglsl b/shaders/ABuffer/abufferSort.hglsl index 6eaf03eed4..fd4de48f84 100644 --- a/shaders/ABuffer/abufferSort.hglsl +++ b/shaders/ABuffer/abufferSort.hglsl @@ -101,8 +101,7 @@ void sort_fragments_list(uint frag_count) { float x = gl_FragCoord.x; float y = gl_FragCoord.y; float jitterValue = float(permute(x + permute(y))) / 961.0; - jitterValue *= 0.004; - vec3 frontPosNew = startColor + (jitterValue*volume_length[ii])*volume_direction[ii]; + vec3 frontPosNew = startColor + (jitterValue*volumeStepSize[ii])*volume_direction[ii]; volume_position[ii] = frontPosNew; } From adec1fc215cfd92d7dcfeb458658bca0e09092fd Mon Sep 17 00:00:00 2001 From: Jonas Strandstedt Date: Wed, 25 Jun 2014 16:44:07 -0400 Subject: [PATCH 32/49] Moved powescaling shader funcitonality - Added separete files for the power scaling algorithms - Added shader tracking and updating for the new files --- ...werScaling.hglsl => powerScaling_fs.hglsl} | 4 +- shaders/PowerScaling/powerScaling_vs.hglsl | 80 +++++++++++++++++++ shaders/pscstandard_fs.glsl | 2 +- shaders/pscstandard_vs.glsl | 63 ++------------- src/abuffer/abuffer.cpp | 3 + 5 files changed, 93 insertions(+), 59 deletions(-) rename shaders/PowerScaling/{powerScaling.hglsl => powerScaling_fs.hglsl} (98%) create mode 100644 shaders/PowerScaling/powerScaling_vs.hglsl diff --git a/shaders/PowerScaling/powerScaling.hglsl b/shaders/PowerScaling/powerScaling_fs.hglsl similarity index 98% rename from shaders/PowerScaling/powerScaling.hglsl rename to shaders/PowerScaling/powerScaling_fs.hglsl index 66ddf647b1..c227016f1d 100644 --- a/shaders/PowerScaling/powerScaling.hglsl +++ b/shaders/PowerScaling/powerScaling_fs.hglsl @@ -22,8 +22,8 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ -#ifndef POWERSCALING_H_HGLSL -#define POWERSCALING_H_HGLSL +#ifndef POWERSCALING_FS_H_HGLSL +#define POWERSCALING_FS_H_HGLSL // Observable universe is 10^27m, setting the far value to extremely high, aka 30!! ERMAHGERD! diff --git a/shaders/PowerScaling/powerScaling_vs.hglsl b/shaders/PowerScaling/powerScaling_vs.hglsl new file mode 100644 index 0000000000..0ec24564b7 --- /dev/null +++ b/shaders/PowerScaling/powerScaling_vs.hglsl @@ -0,0 +1,80 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef POWERSCALING_VS_H_HGLSL +#define POWERSCALING_VS_H_HGLSL + +const float k = 10.0; + +vec4 psc_addition(vec4 v1, vec4 v2) { + float ds = v2.w - v1.w; + if(ds >= 0) { + float p = pow(k,-ds); + return vec4(v1.x*p + v2.x, v1.y*p + v2.y, v1.z*p + v2.z, v2.w); + } else { + float p = pow(k,ds); + return vec4(v1.x + v2.x*p, v1.y + v2.y*p, v1.z + v2.z*p, v1.w); + } +} + +vec4 psc_to_meter(vec4 v1, vec2 v2) { + float factor = v2.x * pow(k,v2.y + v1.w); + return vec4(v1.xyz * factor, 1.0); +} + +vec4 psc_scaling(vec4 v1, vec2 v2) { + float ds = v2.y - v1.w; + if(ds >= 0) { + return vec4(v1.xyz * v2.x * pow(k,v1.w), v2.y); + } else { + return vec4(v1.xyz * v2.x * pow(k,v2.y), v1.w); + } +} + +vec4 pscTransform(vec4 vertexPosition, vec4 cameraPosition, vec2 scaling, mat4 modelTransform) { + vec3 local_vertex_pos = mat3(modelTransform) * vertexPosition.xyz; + //vec4 lvp = ModelTransform * vertexPosition; + + // PSC addition; local vertex position and the object power scaled world position + vec4 position = psc_addition(vec4(local_vertex_pos,vertexPosition.w),objpos); + //position = psc_addition(lvp,objpos); + + // PSC addition; rotated and viewscaled vertex and the cmaeras negative position + position = psc_addition(position,vec4(-cameraPosition.xyz,cameraPosition.w)); + + // rotate the camera + local_vertex_pos = mat3(camrot) * position.xyz; + position = vec4(local_vertex_pos, position.w); + //position = camrot* position; + + // rescales the scene to fit inside the view frustum + // is set from the main program, but these are decent values + // scaling = vec2(1.0, -8.0); + + // project using the rescaled coordinates, + //vec4 vs_position_rescaled = psc_scaling(position, scaling); + return psc_to_meter(position, scaling); +} + +#endif \ No newline at end of file diff --git a/shaders/pscstandard_fs.glsl b/shaders/pscstandard_fs.glsl index 380ca7f096..26a3d1987d 100644 --- a/shaders/pscstandard_fs.glsl +++ b/shaders/pscstandard_fs.glsl @@ -34,7 +34,7 @@ in float s; #include "ABuffer/abufferStruct.hglsl" #include "ABuffer/abufferAddToBuffer.hglsl" -#include "PowerScaling/powerScaling.hglsl" +#include "PowerScaling/powerScaling_fs.hglsl" void main() { diff --git a/shaders/pscstandard_vs.glsl b/shaders/pscstandard_vs.glsl index 83ba34bbfd..431602229b 100644 --- a/shaders/pscstandard_vs.glsl +++ b/shaders/pscstandard_vs.glsl @@ -43,71 +43,22 @@ out vec4 vs_normal; out vec3 vs_position; out float s; -const float k = 10.0; -vec4 psc_addition(vec4 v1, vec4 v2) { - float ds = v2.w - v1.w; - if(ds >= 0) { - float p = pow(k,-ds); - return vec4(v1.x*p + v2.x, v1.y*p + v2.y, v1.z*p + v2.z, v2.w); - } else { - float p = pow(k,ds); - return vec4(v1.x + v2.x*p, v1.y + v2.y*p, v1.z + v2.z*p, v1.w); - } -} - -vec4 psc_to_meter(vec4 v1, vec2 v2) { - float factor = v2.x * pow(k,v2.y + v1.w); - return vec4(v1.xyz * factor, 1.0); -} - -vec4 psc_scaling(vec4 v1, vec2 v2) { - float ds = v2.y - v1.w; - if(ds >= 0) { - return vec4(v1.xyz * v2.x * pow(k,v1.w), v2.y); - } else { - return vec4(v1.xyz * v2.x * pow(k,v2.y), v1.w); - } -} +#include "PowerScaling/powerScaling_vs.hglsl" void main() { // set variables vs_st = in_st; //vs_stp = in_position.xyz; + + // this is wrong for the normal. The normal transform is the transposed inverse of the model transform vs_normal = normalize(ModelTransform * vec4(in_normal,0)); - // fetch model and view translation - //vec4 vertex_translate = ModelTransform[3]; - - // rotate and scale vertex with model transform and add the translation - vec3 local_vertex_pos = mat3(ModelTransform) * in_position.xyz; - //vec4 lvp = ModelTransform * in_position; - - // PSC addition; local vertex position and the object power scaled world position - vec4 position = psc_addition(vec4(local_vertex_pos,in_position.w),objpos); - //position = psc_addition(lvp,objpos); - - // PSC addition; rotated and viewscaled vertex and the cmaeras negative position - position = psc_addition(position,vec4(-campos.xyz,campos.w)); - - // rotate the camera - local_vertex_pos = mat3(camrot) * position.xyz; - position = vec4(local_vertex_pos, position.w); - //position = camrot* position; - - // rescales the scene to fit inside the view frustum - // is set from the main program, but these are decent values - // scaling = vec2(1.0, -8.0); - - // project using the rescaled coordinates, - //vec4 vs_position_rescaled = psc_scaling(position, scaling); - vec4 vs_position_rescaled = psc_to_meter(position, scaling); - position = vs_position_rescaled; - vs_position = vs_position_rescaled.xyz; - s = vs_position_rescaled.w; - + vec4 position = pscTransform(in_position, campos, scaling, ModelTransform); + vs_position = position.xyz; + s = position.w; // project the position to view space - gl_Position = ViewProjection * vs_position_rescaled; + gl_Position = ViewProjection * position; } \ No newline at end of file diff --git a/src/abuffer/abuffer.cpp b/src/abuffer/abuffer.cpp index dbb26e40fc..97313125d9 100644 --- a/src/abuffer/abuffer.cpp +++ b/src/abuffer/abuffer.cpp @@ -90,6 +90,9 @@ bool ABuffer::initializeABuffer() { addFunc("${SHADERS}/ABuffer/abufferSort.hglsl"); addFunc("${SHADERS}/ABuffer/abufferAddToBuffer.hglsl"); addFunc("${SHADERS}/ABuffer/abufferStruct.hglsl"); + addFunc("${SHADERS}/PowerScaling/powerScaling_fs.hglsl"); + addFunc("${SHADERS}/PowerScaling/powerScaling_vs.hglsl"); + _resolveShader = nullptr; From d378428dc4ad662812dbad997de4ce6c505ab8c1 Mon Sep 17 00:00:00 2001 From: Jonas Strandstedt Date: Thu, 26 Jun 2014 15:25:49 -0400 Subject: [PATCH 33/49] Crude PowerScale implementations - Added PowerScaling to RenderableVolumeGL and RenderableFieldlines - Removed the use of volumeraycasterbox since it used FBO and textures which was not used anymore. - Added a simple box implementation to RenderableVolumeGL that can have PowerScaled vertex positions TODO: The #include command needs to be extended in some way since the FieldLines passthrough shader can't access the PowerScaled includes in a good way. --- .../openspace/rendering/renderablevolumegl.h | 10 +- openspace-data | 2 +- shaders/exitpoints.frag | 13 +- shaders/exitpoints.vert | 33 ++++- shaders/pscstandard_vs.glsl | 1 - src/rendering/renderablefieldlines.cpp | 17 ++- src/rendering/renderablevolumegl.cpp | 121 ++++++++++++++++-- 7 files changed, 171 insertions(+), 26 deletions(-) diff --git a/include/openspace/rendering/renderablevolumegl.h b/include/openspace/rendering/renderablevolumegl.h index 25a2629a77..c368e41cfc 100644 --- a/include/openspace/rendering/renderablevolumegl.h +++ b/include/openspace/rendering/renderablevolumegl.h @@ -27,7 +27,6 @@ // open space includes #include -#include // ghoul includes #include @@ -36,6 +35,10 @@ #include #include + namespace sgct_utils { + class SGCTBox; +} + namespace openspace { class RenderableVolumeGL: public RenderableVolume { @@ -62,8 +65,11 @@ private: ghoul::opengl::Texture* _volume; ghoul::opengl::Texture* _transferFunction; - VolumeRaycasterBox* _colorBoxRenderer; + GLuint _boxArray; + ghoul::opengl::ProgramObject *_boxProgram; + sgct_utils::SGCTBox* _box; glm::vec3 _boxScaling; + GLint _MVPLocation, _modelTransformLocation, _typeLocation; bool _updateTransferfunction; int _id; diff --git a/openspace-data b/openspace-data index b4199564cb..8fa226790e 160000 --- a/openspace-data +++ b/openspace-data @@ -1 +1 @@ -Subproject commit b4199564cb227d8896b23016f53b5317943cbdad +Subproject commit 8fa226790e939667b31c0e2020ba42708e3de7e6 diff --git a/shaders/exitpoints.frag b/shaders/exitpoints.frag index cc58d29e35..89fe78224b 100644 --- a/shaders/exitpoints.frag +++ b/shaders/exitpoints.frag @@ -28,20 +28,23 @@ uniform int volumeType; in vec3 vPosition; in vec3 worldPosition; -out vec4 fragColor; +in float s; #include "ABuffer/abufferStruct.hglsl" #include "ABuffer/abufferAddToBuffer.hglsl" +#include "PowerScaling/powerScaling_fs.hglsl" void main() { - fragColor = vec4(vPosition+0.5, 0.3); + vec4 fragColor = vec4(vPosition+0.5, 0.3); + vec4 position = vec4(worldPosition,s); + float depth = pscDepth(position); ABufferStruct_t frag; _col_(frag, fragColor); - _z_(frag, gl_FragCoord.z); + _z_(frag, depth); _type_(frag, volumeType); - _pos_(frag, vec4(worldPosition,0)); + _pos_(frag, position); addToBuffer(frag); - //discard; + discard; } \ No newline at end of file diff --git a/shaders/exitpoints.vert b/shaders/exitpoints.vert index 80145134b3..f8895ba4b3 100644 --- a/shaders/exitpoints.vert +++ b/shaders/exitpoints.vert @@ -24,15 +24,40 @@ #version 430 core -layout(location = 2) in vec3 vertPosition; +layout(location = 0) in vec4 vertPosition; + uniform mat4 modelViewProjection; uniform mat4 modelTransform; +uniform vec4 campos; +uniform mat4 camrot; +uniform vec2 scaling; +uniform vec4 objpos; +uniform float time; out vec3 vPosition; out vec3 worldPosition; +out float s; + +#include "PowerScaling/powerScaling_vs.hglsl" void main() { - vPosition = vertPosition; - worldPosition = (modelTransform *vec4(vPosition, 1.0)).xyz; - gl_Position = modelViewProjection *vec4(worldPosition, 1.0); + + //vs_st = in_st; + //vs_stp = in_position.xyz; + + vPosition = vertPosition.xyz; + + // this is wrong for the normal. The normal transform is the transposed inverse of the model transform + //vs_normal = normalize(modelTransform * vec4(in_normal,0)); + + vec4 position = pscTransform(vertPosition, campos, scaling, modelTransform); + worldPosition = position.xyz; + s = position.w; + + // project the position to view space + gl_Position = modelViewProjection * position; + + // vPosition = vertPosition.xyz; + // worldPosition = (modelTransform *vec4(vPosition, 1.0)).xyz; + // gl_Position = modelViewProjection *vec4(worldPosition, 1.0); } \ No newline at end of file diff --git a/shaders/pscstandard_vs.glsl b/shaders/pscstandard_vs.glsl index 431602229b..e9e1745dc9 100644 --- a/shaders/pscstandard_vs.glsl +++ b/shaders/pscstandard_vs.glsl @@ -43,7 +43,6 @@ out vec4 vs_normal; out vec3 vs_position; out float s; - #include "PowerScaling/powerScaling_vs.hglsl" void main() diff --git a/src/rendering/renderablefieldlines.cpp b/src/rendering/renderablefieldlines.cpp index 135c610b24..0b3fa49749 100644 --- a/src/rendering/renderablefieldlines.cpp +++ b/src/rendering/renderablefieldlines.cpp @@ -206,14 +206,27 @@ void RenderableFieldlines::render(const Camera* camera, const psc& thisPosition) psc relative = thisPosition-camera->position(); transform = transform*camTransform; - transform = glm::translate(transform, relative.vec3()); + //transform = glm::translate(transform, relative.vec3()); + transform = glm::mat4(1.0); transform = glm::rotate(transform, -90.0f, glm::vec3(1.0, 0.0, 0.0)); // Model has positive Z as up transform = glm::scale(transform, glm::vec3(0.036*0.5*0.5)); //transform = glm::scale(transform, glm::vec3(0.1)); // Scale to avoid depth buffer problems + psc currentPosition = thisPosition; + psc campos = camera->position(); + glm::mat4 camrot = camera->viewRotationMatrix(); + PowerScaledScalar scaling = camera->scaling(); + // Activate shader _fieldlinesProgram->activate(); - _fieldlinesProgram->setUniform("modelViewProjection", transform); + //_fieldlinesProgram->setUniform("modelViewProjection", transform); + + _fieldlinesProgram->setUniform("modelViewProjection", camera->viewProjectionMatrix()); + _fieldlinesProgram->setUniform("modelTransform", transform); + _fieldlinesProgram->setUniform("campos", campos.vec4()); + _fieldlinesProgram->setUniform("objpos", currentPosition.vec4()); + _fieldlinesProgram->setUniform("camrot", camrot); + _fieldlinesProgram->setUniform("scaling", scaling.vec2()); // ------ FIELDLINES ----------------- glBindVertexArray(_VAO); diff --git a/src/rendering/renderablevolumegl.cpp b/src/rendering/renderablevolumegl.cpp index 518120649c..bdcdc9ae79 100644 --- a/src/rendering/renderablevolumegl.cpp +++ b/src/rendering/renderablevolumegl.cpp @@ -34,6 +34,7 @@ #include #include +#include namespace { std::string _loggerCat = "RenderableVolumeGL"; @@ -42,7 +43,7 @@ namespace { namespace openspace { RenderableVolumeGL::RenderableVolumeGL(const ghoul::Dictionary& dictionary): - RenderableVolume(dictionary), _boxScaling(1.0, 1.0, 1.0), + RenderableVolume(dictionary), _box(nullptr), _boxScaling(1.0, 1.0, 1.0), _updateTransferfunction(false), _id(-1) { @@ -96,7 +97,6 @@ RenderableVolumeGL::RenderableVolumeGL(const ghoul::Dictionary& dictionary): _boxScaling[2] = tempValue; } - _colorBoxRenderer = new VolumeRaycasterBox(); setBoundingSphere(PowerScaledScalar::CreatePSS(glm::length(_boxScaling))); } @@ -104,12 +104,12 @@ RenderableVolumeGL::~RenderableVolumeGL() { deinitialize(); if(_volume) delete _volume; - if(_colorBoxRenderer) - delete _colorBoxRenderer; if(_transferFunctionFile) delete _transferFunctionFile; if(_transferFunction) delete _transferFunction; + if(_box) + delete _box; } bool RenderableVolumeGL::initialize() { @@ -130,7 +130,70 @@ bool RenderableVolumeGL::initialize() { }; _transferFunctionFile->setCallback(textureCallback); - _colorBoxRenderer->initialize(); + _box = new sgct_utils::SGCTBox(1.0f, sgct_utils::SGCTBox::Regular); + OsEng.configurationManager().getValue("RaycastProgram", _boxProgram); + _MVPLocation = _boxProgram->uniformLocation("modelViewProjection"); + _modelTransformLocation = _boxProgram->uniformLocation("modelTransform"); + _typeLocation = _boxProgram->uniformLocation("volumeType"); + + // ============================ + // GEOMETRY (quad) + // ============================ + const GLfloat size = 0.5f; + const GLfloat vertex_data[] = { // square of two triangles (sigh) + // x, y, z, s, + -size, -size, size, 0.0f, + size, size, size, 0.0f, + -size, size, size, 0.0f, + -size, -size, size, 0.0f, + size, -size, size, 0.0f, + size, size, size, 0.0f, + + -size, -size, -size, 0.0f, + size, size, -size, 0.0f, + -size, size, -size, 0.0f, + -size, -size, -size, 0.0f, + size, -size, -size, 0.0f, + size, size, -size, 0.0f, + + size, -size, -size, 0.0f, + size, size, size, 0.0f, + size, -size, size, 0.0f, + size, -size, -size, 0.0f, + size, size, -size, 0.0f, + size, size, size, 0.0f, + + -size, -size, -size, 0.0f, + -size, size, size, 0.0f, + -size, -size, size, 0.0f, + -size, -size, -size, 0.0f, + -size, size, -size, 0.0f, + -size, size, size, 0.0f, + + -size, size, -size, 0.0f, + size, size, size, 0.0f, + -size, size, size, 0.0f, + -size, size, -size, 0.0f, + size, size, -size, 0.0f, + size, size, size, 0.0f, + + -size, -size, -size, 0.0f, + size, -size, size, 0.0f, + -size, -size, size, 0.0f, + -size, -size, -size, 0.0f, + size, -size, -size, 0.0f, + size, -size, size, 0.0f, + }; + GLuint vertexPositionBuffer; + glGenVertexArrays(1, &_boxArray); // generate array + glBindVertexArray(_boxArray); // bind array + glGenBuffers(1, &vertexPositionBuffer); // generate buffer + glBindBuffer(GL_ARRAY_BUFFER, vertexPositionBuffer); // bind buffer + glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data, GL_STATIC_DRAW); + glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*4, reinterpret_cast(0)); + //glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*7, reinterpret_cast(0)); + glEnableVertexAttribArray(0); + //glEnableVertexAttribArray(1); return true; @@ -151,22 +214,58 @@ void RenderableVolumeGL::render(const Camera *camera, const psc &thisPosition) { glTexImage1D( GL_TEXTURE_1D, 0, _transferFunction->internalFormat(), _transferFunction->width(),0, _transferFunction->format(), _transferFunction->dataType(), data); - //delete data; delete transferFunction; LDEBUG("Updated transferfunction!"); } } - psc relative = thisPosition-camera->position(); + //psc relative = thisPosition-camera->position(); - glm::mat4 transform = camera->viewRotationMatrix(); - transform = glm::translate(transform, relative.vec3()); - transform = glm::translate(transform, glm::vec3(-1.1,0.0,0.0)); + // glm::mat4 transform = camera->viewRotationMatrix(); + // transform = glm::translate(transform, relative.vec3()); + // transform = glm::translate(transform, glm::vec3(-1.1,0.0,0.0)); + // transform = glm::scale(transform, _boxScaling); + glm::mat4 transform = glm::mat4(1.0); transform = glm::scale(transform, _boxScaling); + // fetch data + psc currentPosition = thisPosition; + psc campos = camera->position(); + glm::mat4 camrot = camera->viewRotationMatrix(); + PowerScaledScalar scaling = camera->scaling(); + + psc addon(-1.1,0.0,0.0,0.0); + currentPosition += addon; + // TODO: Use _id to identify this volume - _colorBoxRenderer->render(camera->viewProjectionMatrix(), transform, _id); + _boxProgram->activate(); + // _boxProgram->setUniform(_MVPLocation, camera->viewProjectionMatrix()); + // _boxProgram->setUniform(_modelTransformLocation, transform); + _boxProgram->setUniform(_typeLocation, _id); + + _boxProgram->setUniform("modelViewProjection", camera->viewProjectionMatrix()); + _boxProgram->setUniform("modelTransform", transform); + _boxProgram->setUniform("campos", campos.vec4()); + _boxProgram->setUniform("objpos", currentPosition.vec4()); + _boxProgram->setUniform("camrot", camrot); + _boxProgram->setUniform("scaling", scaling.vec2()); + + // make sure GL_CULL_FACE is enabled (it should be) + glEnable(GL_CULL_FACE); + + // Draw backface + glCullFace(GL_FRONT); + glBindVertexArray(_boxArray); + glDrawArrays(GL_TRIANGLES, 0, 6*6); + // _box->draw(); + + // Draw frontface (now the normal cull face is is set) + glCullFace(GL_BACK); + glDrawArrays(GL_TRIANGLES, 0, 6*6); + // _box->draw(); + + _boxProgram->deactivate(); } From 24d38d0296f8913b49e2b44975226906f0bdd7fa Mon Sep 17 00:00:00 2001 From: Hans-Christian Helltegen Date: Fri, 27 Jun 2014 15:18:34 -0400 Subject: [PATCH 34/49] Implemented tracing for Lorentz force trajectories --- .../rendering/renderablefieldlines.h | 6 +- include/openspace/util/kameleonwrapper.h | 17 +- src/rendering/renderablefieldlines.cpp | 87 ++++++---- src/util/kameleonwrapper.cpp | 158 +++++++++++++++++- 4 files changed, 220 insertions(+), 48 deletions(-) diff --git a/include/openspace/rendering/renderablefieldlines.h b/include/openspace/rendering/renderablefieldlines.h index e26c7c2b54..3f663c4f73 100644 --- a/include/openspace/rendering/renderablefieldlines.h +++ b/include/openspace/rendering/renderablefieldlines.h @@ -58,7 +58,7 @@ private: std::vector _filenames; std::vector _seedPoints; - ghoul::opengl::ProgramObject *_fieldlinesProgram, *_seedpointsProgram; + ghoul::opengl::ProgramObject *_fieldlinesProgram; GLuint _VAO, _seedpointVAO; std::mutex* _shaderMutex; @@ -66,8 +66,8 @@ private: ghoul::filesystem::File* _vertexSourceFile; ghoul::filesystem::File* _fragmentSourceFile; - std::vector _lineStart, _seedpointStart; - std::vector _lineCount, _seedpointCount; + std::vector _lineStart; + std::vector _lineCount; bool _programUpdateOnSave; void safeShaderCompilation(); diff --git a/include/openspace/util/kameleonwrapper.h b/include/openspace/util/kameleonwrapper.h index 4141bdec52..6b85680231 100644 --- a/include/openspace/util/kameleonwrapper.h +++ b/include/openspace/util/kameleonwrapper.h @@ -25,7 +25,6 @@ #ifndef KAMELEONWRAPPER_H_ #define KAMELEONWRAPPER_H_ -//#include #include namespace ccmc { @@ -43,12 +42,12 @@ public: BATSRUS // Magnetosphere }; - enum TraceDirection { + enum class TraceDirection { FORWARD = 1, BACK = -1 }; - enum FieldlineEnd { + enum class FieldlineEnd { NORTH, SOUTH, OUT @@ -60,15 +59,25 @@ public: float* getUniformSampledVectorValues(const std::string& xVar, const std::string& yVar, const std::string& zVar, glm::size3_t outDimensions); - std::vector > getFieldLines(const std::string& xVar, + std::vector > getClassifiedFieldLines(const std::string& xVar, const std::string& yVar, const std::string& zVar, std::vector seedPoints, float stepSize); + std::vector > getFieldLines(const std::string& xVar, + const std::string& yVar, const std::string& zVar, + std::vector seedPoints, float stepSize, glm::vec3 color); + + std::vector > getLorentzTrajectories(std::vector seedPoints, + glm::vec3 color, float stepsize); + private: std::vector traceCartesianFieldline(const std::string& xVar, const std::string& yVar, const std::string& zVar, glm::vec3 seedPoint, float stepSize, TraceDirection direction, FieldlineEnd& end); + std::vector traceLorentzTrajectory(glm::vec3 seedPoint, + float stepsize, float eCharge); + void getGridVariables(std::string& x, std::string& y, std::string& z); void progressBar(int current, int end); glm::vec3 classifyFieldline(FieldlineEnd fEnd, FieldlineEnd bEnd); diff --git a/src/rendering/renderablefieldlines.cpp b/src/rendering/renderablefieldlines.cpp index 64dab8daaa..4527ad2cc6 100644 --- a/src/rendering/renderablefieldlines.cpp +++ b/src/rendering/renderablefieldlines.cpp @@ -94,14 +94,6 @@ RenderableFieldlines::RenderableFieldlines(const ghoul::Dictionary& dictionary) } } - _seedpointsProgram = new ghoul::opengl::ProgramObject("SeedpointsProgram"); - ghoul::opengl::ShaderObject* seedpointVertexShader = new ghoul::opengl::ShaderObject(ghoul::opengl::ShaderObject::ShaderTypeVertex, - "/home/hhellteg/openspace/openspace-data/scene/fieldlines/seedPoints.vert"); - ghoul::opengl::ShaderObject* seedpointFragmentShader = new ghoul::opengl::ShaderObject(ghoul::opengl::ShaderObject::ShaderTypeFragment, - "/home/hhellteg/openspace/openspace-data/scene/fieldlines/seedPoints.frag"); - _seedpointsProgram->attachObject(seedpointVertexShader); - _seedpointsProgram->attachObject(seedpointFragmentShader); - if(dictionary.hasKey("UpdateOnSave")) { dictionary.getValue("UpdateOnSave", _programUpdateOnSave); } @@ -129,14 +121,17 @@ bool RenderableFieldlines::initialize() { _lineCount.push_back(fieldlinesData[j].size()/2.0); prevEnd = prevEnd + fieldlinesData[j].size()/2.0; - _seedpointStart.push_back(j); - _seedpointCount.push_back(1); - vertexData.insert( vertexData.end(), fieldlinesData[j].begin(), fieldlinesData[j].end()); } } + LDEBUG("Number of vertices : " << vertexData.size()/2.0); - LDEBUG("Vertex orginal : " << vertexData.size()/2.0); + // Give seedpoints a color for visualizing as GL_POINTS + std::vector seedPointsData; + for (int i = 0; i < _seedPoints.size(); ++i) { + seedPointsData.push_back(_seedPoints[i]); + seedPointsData.push_back(glm::vec3(1.0, 0.0, 1.0)); + } // ------ FIELDLINES ----------------- GLuint vertexPositionBuffer; @@ -159,22 +154,27 @@ bool RenderableFieldlines::initialize() { glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind buffer glBindVertexArray(0); //unbind array -// // ------ SEEDPOINTS ----------------- + // ------ SEEDPOINTS ----------------- GLuint seedpointPositionBuffer; glGenVertexArrays(1, &_seedpointVAO); // generate array glBindVertexArray(_seedpointVAO); // bind array glGenBuffers(1, &seedpointPositionBuffer); // generate buffer glBindBuffer(GL_ARRAY_BUFFER, seedpointPositionBuffer); // bind buffer - glBufferData(GL_ARRAY_BUFFER, _seedPoints.size()*sizeof(glm::vec3), &_seedPoints.front(), GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, seedPointsData.size()*sizeof(glm::vec3), &seedPointsData.front(), GL_STATIC_DRAW); // Vertex positions - GLuint seedpointLocation = 0; - glEnableVertexAttribArray(seedpointLocation); - glVertexAttribPointer(seedpointLocation, 3, GL_FLOAT, GL_FALSE, sizeof(glm::vec3), reinterpret_cast(0)); + glEnableVertexAttribArray(vertexLocation); + glVertexAttribPointer(vertexLocation, 3, GL_FLOAT, GL_FALSE, 2*sizeof(glm::vec3), reinterpret_cast(0)); + + // Texture coordinates + glEnableVertexAttribArray(texcoordLocation); + glVertexAttribPointer(texcoordLocation, 3, GL_FLOAT, GL_FALSE, 2*sizeof(glm::vec3), (void*)(sizeof(glm::vec3))); glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind buffer glBindVertexArray(0); //unbind array + glPointSize(5); // size of seedpoints + // ------ SETUP SHADERS ----------------- auto privateCallback = [this](const ghoul::filesystem::File& file) { safeShaderCompilation(); @@ -187,9 +187,6 @@ bool RenderableFieldlines::initialize() { _fieldlinesProgram->compileShaderObjects(); _fieldlinesProgram->linkProgramObject(); - _seedpointsProgram->compileShaderObjects(); - _seedpointsProgram->linkProgramObject(); - return true; } @@ -211,25 +208,15 @@ void RenderableFieldlines::render(const Camera* camera, const psc& thisPosition) _shaderMutex->lock(); _fieldlinesProgram->activate(); _fieldlinesProgram->setUniform("modelViewProjection", transform); - glBindVertexArray(_VAO); glMultiDrawArrays(GL_LINE_STRIP, &_lineStart[0], &_lineCount[0], _lineStart.size()); - glBindVertexArray(0); - - _fieldlinesProgram->deactivate(); - _shaderMutex->unlock(); // ------ SEEDPOINTS ----------------- - _shaderMutex->lock(); - _seedpointsProgram->activate(); - _seedpointsProgram->setUniform("modelViewProjection", transform); - glBindVertexArray(_seedpointVAO); - glPointSize(5); glMultiDrawArrays(GL_POINTS, &_lineStart[0], &_lineCount[0], _seedPoints.size()); glBindVertexArray(0); - _seedpointsProgram->deactivate(); + _fieldlinesProgram->deactivate(); _shaderMutex->unlock(); } @@ -251,7 +238,11 @@ std::vector > RenderableFieldlines::getFieldlinesData(std KameleonWrapper::Model model; std::vector > fieldlinesData; + bool classification = false, lorentz = false; + glm::vec3 fieldlineColor = glm::vec3(1.0, 1.0, 1.0); // default color if no color or classification is specified + if (hintsDictionary.hasKey("Model") && hintsDictionary.getValue("Model", modelString)) { + // ------ MODEL ----------------- if (modelString == "BATSRUS") { model = KameleonWrapper::Model::BATSRUS; } else if (modelString == "ENLIL") { @@ -262,25 +253,35 @@ std::vector > RenderableFieldlines::getFieldlinesData(std return fieldlinesData; } + // ------ VARIBLES / LORENTZ ----------------- if (hintsDictionary.hasKey("Variables")) { bool xVar, yVar, zVar; xVar = hintsDictionary.getValue("Variables.1", xVariable); - yVar = hintsDictionary.getValue("Variables.2", yVariable); - zVar = hintsDictionary.getValue("Variables.3", zVariable); + if (xVar && xVariable == "Lorentz") { + lorentz = true; + } else { - if (!xVar || !yVar || !zVar) { - LWARNING("Error reading variables! Must be 3 and must exist in CDF data"); - return fieldlinesData; + yVar = hintsDictionary.getValue("Variables.2", yVariable); + zVar = hintsDictionary.getValue("Variables.3", zVariable); + + if (!xVar || !yVar || !zVar) { + LWARNING("Error reading variables! Must be 3 and must exist in CDF data"); + return fieldlinesData; + } } } else { LWARNING("Hints does not specify valid 'Variables'"); return fieldlinesData; } + // ------ STEPSIZE ----------------- if (!hintsDictionary.hasKey("Stepsize") || !hintsDictionary.getValue("Stepsize", stepSize)) { LDEBUG("No stepsize set for fieldlines. Setting to default value (" << stepSize << ")"); } + + // ------ SEEDPOINTS --------------- ghoul::Dictionary seedpointsDictionary; + _seedPoints.clear(); if (hintsDictionary.hasKey("Seedpoints") && hintsDictionary.getValue("Seedpoints", seedpointsDictionary)) { glm::vec3 seedPos; for (auto index : seedpointsDictionary.keys()) { @@ -288,10 +289,22 @@ std::vector > RenderableFieldlines::getFieldlinesData(std _seedPoints.push_back(seedPos); } } + + // ------ CLASSIFICATION & COLOR ----------- + hintsDictionary.getValue("Color", fieldlineColor); + hintsDictionary.getValue("Classification", classification); } KameleonWrapper kw(filename, model); - fieldlinesData = kw.getFieldLines(xVariable, yVariable, zVariable, _seedPoints, stepSize); + if (lorentz) { + fieldlinesData = kw.getLorentzTrajectories(_seedPoints, fieldlineColor, stepSize); + } else { + if (classification) + fieldlinesData = kw.getClassifiedFieldLines(xVariable, yVariable, zVariable, _seedPoints, stepSize); + else + fieldlinesData = kw.getFieldLines(xVariable, yVariable, zVariable, _seedPoints, stepSize, fieldlineColor); + } + return fieldlinesData; } diff --git a/src/util/kameleonwrapper.cpp b/src/util/kameleonwrapper.cpp index 314074c0a0..ead509d8e0 100644 --- a/src/util/kameleonwrapper.cpp +++ b/src/util/kameleonwrapper.cpp @@ -229,7 +229,7 @@ float* KameleonWrapper::getUniformSampledVectorValues(const std::string& xVar, c return data; } -std::vector > KameleonWrapper::getFieldLines( +std::vector > KameleonWrapper::getClassifiedFieldLines( const std::string& xVar, const std::string& yVar, const std::string& zVar, std::vector seedPoints, float stepSize ) { @@ -268,6 +268,67 @@ std::vector > KameleonWrapper::getFieldLines( return fieldLines; } +std::vector > KameleonWrapper::getFieldLines( + const std::string& xVar, const std::string& yVar, + const std::string& zVar, std::vector seedPoints, + float stepSize, glm::vec3 color ) { + assert(_model && _interpolator); + assert(_type == Model::ENLIL || _type == Model::BATSRUS); + LINFO("Creating " << seedPoints.size() << " fieldlines from variables " << xVar << " " << yVar << " " << zVar); + + std::vector fLine, bLine; + std::vector > fieldLines; + FieldlineEnd forwardEnd, backEnd; + + if (_type == Model::BATSRUS) { + for (glm::vec3 seedPoint : seedPoints) { + fLine = traceCartesianFieldline(xVar, yVar, zVar, seedPoint, stepSize, TraceDirection::FORWARD, forwardEnd); + bLine = traceCartesianFieldline(xVar, yVar, zVar, seedPoint, stepSize, TraceDirection::BACK, backEnd); + + bLine.insert(bLine.begin(), fLine.rbegin(), fLine.rend()); + + // write colors + std::vector line; + for (glm::vec3 position : bLine) { + line.push_back(position); + line.push_back(color); + } + + fieldLines.push_back(line); + } + } else { + LERROR("Fieldlines are only supported for BATSRUS model"); + } + + return fieldLines; +} + +std::vector > KameleonWrapper::getLorentzTrajectories( + std::vector seedPoints, glm::vec3 color, float stepsize) { + LINFO("Creating " << seedPoints.size() << " Lorentz force trajectories"); + + std::vector > trajectories; + std::vector plusTraj, minusTraj; + + for (auto seedPoint : seedPoints) { + plusTraj = traceLorentzTrajectory(seedPoint, stepsize, 1.0); + minusTraj = traceLorentzTrajectory(seedPoint, stepsize, -1.0); + + minusTraj.insert(minusTraj.begin(), plusTraj.rbegin(), plusTraj.rend()); + + // write colors + std::vector trajectory; + for (glm::vec3 position : minusTraj) { + trajectory.push_back(position); + trajectory.push_back(color); + } + trajectories.push_back(trajectory); + + } + + return trajectories; +} + std::vector KameleonWrapper::traceCartesianFieldline( const std::string& xVar, const std::string& yVar, const std::string& zVar, glm::vec3 seedPoint, @@ -276,8 +337,7 @@ std::vector KameleonWrapper::traceCartesianFieldline( glm::vec3 color, pos, k1, k2, k3, k4; std::vector line; float stepX, stepY, stepZ; - int numSteps = 0; - int maxSteps = 5000; + int numSteps = 0, maxSteps = 5000; pos = seedPoint; _model->loadVariable(xVar); @@ -300,7 +360,7 @@ std::vector KameleonWrapper::traceCartesianFieldline( k1.y = _interpolator->interpolate(yID, pos.x, pos.y, pos.z); k1.z = _interpolator->interpolate(zID, pos.x, pos.y, pos.z); k1 = (float)direction*glm::normalize(k1); -// stepX*=stepSize, stepY*=stepSize, stepZ*=stepSize; + stepX=stepX*stepSize, stepY=stepY*stepSize, stepZ=stepZ*stepSize; k2.x = _interpolator->interpolate(xID, pos.x+(stepX/2.0)*k1.x, pos.y+(stepY/2.0)*k1.y, pos.z+(stepZ/2.0)*k1.z); k2.y = _interpolator->interpolate(yID, pos.x+(stepX/2.0)*k1.x, pos.y+(stepY/2.0)*k1.y, pos.z+(stepZ/2.0)*k1.z); k2.z = _interpolator->interpolate(zID, pos.x+(stepX/2.0)*k1.x, pos.y+(stepY/2.0)*k1.y, pos.z+(stepZ/2.0)*k1.z); @@ -335,6 +395,96 @@ std::vector KameleonWrapper::traceCartesianFieldline( return line; } +std::vector KameleonWrapper::traceLorentzTrajectory(glm::vec3 seedPoint, + float stepsize, float eCharge) { + glm::vec3 B, E, v0, k1, k2, k3, k4, sPos, tmpV; + float stepX = stepsize, stepY = stepsize, stepZ = stepsize; + + long int bxID = _model->getVariableID("bx"); + long int byID = _model->getVariableID("by"); + long int bzID = _model->getVariableID("bz"); + long int jxID = _model->getVariableID("jx"); + long int jyID = _model->getVariableID("jy"); + long int jzID = _model->getVariableID("jz"); + + std::vector trajectory; + glm::vec3 pos = seedPoint; + int numSteps = 0, maxSteps = 5000; + v0.x = _interpolator->interpolate("ux", pos.x, pos.y, pos.z); + v0.y = _interpolator->interpolate("uy", pos.x, pos.y, pos.z); + v0.z = _interpolator->interpolate("uz", pos.x, pos.y, pos.z); + v0 = glm::normalize(v0); + + // While we are inside the models boundries and not inside earth + while ((pos.x < _xMax && pos.x > _xMin && pos.y < _yMax && pos.y > _yMin && + pos.z < _zMax && pos.z > _zMin) && !(pos.x*pos.x + pos.y*pos.y + pos.z*pos.z < 1.0)) { + + // Save position + trajectory.push_back(pos); + + // Calculate new position with Lorentz force quation and Runge-Kutta 4th order + B.x = _interpolator->interpolate(bxID, pos.x, pos.y, pos.z); + B.y = _interpolator->interpolate(byID, pos.x, pos.y, pos.z); + B.z = _interpolator->interpolate(bzID, pos.x, pos.y, pos.z); + E.x = _interpolator->interpolate(jxID, pos.x, pos.y, pos.z); + E.y = _interpolator->interpolate(jyID, pos.x, pos.y, pos.z); + E.z = _interpolator->interpolate(jzID, pos.x, pos.y, pos.z); + k1 = eCharge*(E + glm::cross(v0, B)); + k1 = glm::normalize(k1); + + sPos = glm::vec3( pos.x+(stepX/2.0)*v0.x+(stepX*stepX/8.0)*k1.x, + pos.y+(stepY/2.0)*v0.y+(stepY*stepY/8.0)*k1.y, + pos.z+(stepZ/2.0)*v0.z+(stepZ*stepZ/8.0)*k1.z); + B.x = _interpolator->interpolate(bxID, sPos.x, sPos.y, sPos.z); + B.y = _interpolator->interpolate(byID, sPos.x, sPos.y, sPos.z); + B.z = _interpolator->interpolate(bzID, sPos.x, sPos.y, sPos.z); + E.x = _interpolator->interpolate(jxID, sPos.x, sPos.y, sPos.z); + E.y = _interpolator->interpolate(jyID, sPos.x, sPos.y, sPos.z); + E.z = _interpolator->interpolate(jzID, sPos.x, sPos.y, sPos.z); + tmpV = v0+(stepX/2.0f)*k1; + k2 = eCharge*(E + glm::cross(tmpV, B)); + k2 = glm::normalize(k2); + + B.x = _interpolator->interpolate(bxID, sPos.x, sPos.y, sPos.z); + B.y = _interpolator->interpolate(byID, sPos.x, sPos.y, sPos.z); + B.z = _interpolator->interpolate(bzID, sPos.x, sPos.y, sPos.z); + E.x = _interpolator->interpolate(jxID, sPos.x, sPos.y, sPos.z); + E.y = _interpolator->interpolate(jyID, sPos.x, sPos.y, sPos.z); + E.z = _interpolator->interpolate(jzID, sPos.x, sPos.y, sPos.z); + tmpV = v0+(stepX/2.0f)*k2; + k3 = eCharge*(E + glm::cross(tmpV, B)); + k3 = glm::normalize(k3); + + sPos = glm::vec3( pos.x+stepX*v0.x+(stepX*stepX/2.0)*k1.x, + pos.y+stepY*v0.y+(stepY*stepY/2.0)*k1.y, + pos.z+stepZ*v0.z+(stepZ*stepZ/2.0)*k1.z); + B.x = _interpolator->interpolate(bxID, sPos.x, sPos.y, sPos.z); + B.y = _interpolator->interpolate(byID, sPos.x, sPos.y, sPos.z); + B.z = _interpolator->interpolate(bzID, sPos.x, sPos.y, sPos.z); + E.x = _interpolator->interpolate(jxID, sPos.x, sPos.y, sPos.z); + E.y = _interpolator->interpolate(jyID, sPos.x, sPos.y, sPos.z); + E.z = _interpolator->interpolate(jzID, sPos.x, sPos.y, sPos.z); + tmpV = v0+stepX*k3; + k4 = eCharge*(E + glm::cross(tmpV, B)); + k4 = glm::normalize(k4); + + pos.x = pos.x + stepX*v0.x + (stepX*stepX/6.0)*(k1.x + k2.x + k3.x); + pos.y = pos.y + stepY*v0.y + (stepY*stepY/6.0)*(k1.y + k2.y + k3.y); + pos.z = pos.z + stepZ*v0.z + (stepZ*stepZ/6.0)*(k1.z + k2.z + k3.z); + + v0.x = v0.x + (stepX/6.0)*(k1.x + 2.0*k2.x + 2.0*k3.x + k4.z); + v0.y = v0.y + (stepY/6.0)*(k1.y + 2.0*k2.y + 2.0*k3.y + k4.y); + v0.z = v0.z + (stepZ/6.0)*(k1.z + 2.0*k2.z + 2.0*k3.z + k4.z); + + ++numSteps; + if (numSteps > maxSteps) { + LDEBUG("Max number of steps taken (" << maxSteps <<")"); + break; + } + } + return trajectory; +} + void KameleonWrapper::getGridVariables(std::string& x, std::string& y, std::string& z) { // get the grid system string std::string gridSystem = _model->getGlobalAttribute("grid_system_1").getAttributeString(); From 4dca06e776d6bc947d8e3951e9a2b6b595c709ae Mon Sep 17 00:00:00 2001 From: Hans-Christian Helltegen Date: Tue, 1 Jul 2014 09:53:10 -0400 Subject: [PATCH 35/49] Fixed alignment of data in kameleonwrapper. This version is installed in the CCMC-lab --- src/rendering/renderablefieldlines.cpp | 6 +++--- src/util/kameleonwrapper.cpp | 19 ++++++++++++------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/rendering/renderablefieldlines.cpp b/src/rendering/renderablefieldlines.cpp index b249f336eb..ff4e76c669 100644 --- a/src/rendering/renderablefieldlines.cpp +++ b/src/rendering/renderablefieldlines.cpp @@ -129,7 +129,7 @@ bool RenderableFieldlines::initialize() { std::vector seedPointsData; for (int i = 0; i < _seedPoints.size(); ++i) { seedPointsData.push_back(_seedPoints[i]); - seedPointsData.push_back(glm::vec3(1.0, 0.0, 1.0)); + seedPointsData.push_back(glm::vec3(1.0, 0.5, 0.0)); } // ------ FIELDLINES ----------------- @@ -207,8 +207,8 @@ void RenderableFieldlines::render(const Camera* camera, const psc& thisPosition) transform = transform*camTransform; //transform = glm::translate(transform, relative.vec3()); transform = glm::mat4(1.0); - transform = glm::rotate(transform, -90.0f, glm::vec3(1.0, 0.0, 0.0)); // Model has positive Z as up - transform = glm::scale(transform, glm::vec3(0.036*0.5*0.5)); +// transform = glm::scale(transform, glm::vec3(0.036*0.5*0.5)); + transform = glm::scale(transform, glm::vec3(0.01)); //transform = glm::scale(transform, glm::vec3(0.1)); // Scale to avoid depth buffer problems psc currentPosition = thisPosition; diff --git a/src/util/kameleonwrapper.cpp b/src/util/kameleonwrapper.cpp index 4331eed914..1fa2b423f6 100644 --- a/src/util/kameleonwrapper.cpp +++ b/src/util/kameleonwrapper.cpp @@ -36,6 +36,8 @@ #include #include +#include + namespace openspace { std::string _loggerCat = "KameleonWrapper"; @@ -122,7 +124,8 @@ float* KameleonWrapper::getUniformSampledValues(const std::string& var, glm::siz double zPos = _zMin + stepZ*z; // get interpolated data value for (xPos, yPos, zPos) - double value = _interpolator->interpolate(var, xPos, yPos, zPos); + // swap yPos and zPos because model has Z as up + double value = _interpolator->interpolate(var, xPos, zPos, yPos); // scale to [0,1] //doubleData[index] = (value-varMin)/(varMax-varMin); @@ -360,7 +363,6 @@ std::vector > KameleonWrapper::getLorentzTrajectories( trajectory.push_back(color); } trajectories.push_back(trajectory); - } return trajectories; @@ -389,8 +391,8 @@ std::vector KameleonWrapper::traceCartesianFieldline( while ((pos.x < _xMax && pos.x > _xMin && pos.y < _yMax && pos.y > _yMin && pos.z < _zMax && pos.z > _zMin) && !(pos.x*pos.x + pos.y*pos.y + pos.z*pos.z < 1.0)) { - // Save position - line.push_back(pos); + // Save position. Model has +Z as up + line.push_back(glm::vec3(pos.x, pos.z, pos.y)); // Calculate new position with Runge-Kutta 4th order k1.x = _interpolator->interpolate(xID, pos.x, pos.y, pos.z, stepX, stepY, stepZ); @@ -420,7 +422,8 @@ std::vector KameleonWrapper::traceCartesianFieldline( break; } } - line.push_back(pos); + // Save last position. Model has +Z as up + line.push_back(glm::vec3(pos.x, pos.z, pos.y)); if (pos.z > 0.0 && (pos.x*pos.x + pos.y*pos.y + pos.z*pos.z < 1.0)) end = FieldlineEnd::NORTH; @@ -456,8 +459,8 @@ std::vector KameleonWrapper::traceLorentzTrajectory(glm::vec3 seedPoi while ((pos.x < _xMax && pos.x > _xMin && pos.y < _yMax && pos.y > _yMin && pos.z < _zMax && pos.z > _zMin) && !(pos.x*pos.x + pos.y*pos.y + pos.z*pos.z < 1.0)) { - // Save position - trajectory.push_back(pos); + // Save position. Model has +Z as up + trajectory.push_back(glm::vec3(pos.x, pos.z, pos.y)); // Calculate new position with Lorentz force quation and Runge-Kutta 4th order B.x = _interpolator->interpolate(bxID, pos.x, pos.y, pos.z); @@ -519,6 +522,8 @@ std::vector KameleonWrapper::traceLorentzTrajectory(glm::vec3 seedPoi break; } } + // Save last position. Model has +Z as up + trajectory.push_back(glm::vec3(pos.x, pos.z, pos.y)); return trajectory; } From 610d5d5427c4b8e57225317d0a2745d29d17a104 Mon Sep 17 00:00:00 2001 From: Jonas Strandstedt Date: Tue, 1 Jul 2014 10:01:54 -0400 Subject: [PATCH 36/49] Added variable stepsize for volumes - When holding right mouse button the stepsize for volumes will be 1/5 - Added configuration files for ccmc lab --- config/sgct/ccmc_lab_all.xml | 65 +++++++++++++++++++++ config/sgct/ccmc_lab_work.xml | 47 +++++++++++++++ shaders/ABuffer/abufferResolveFragment.glsl | 51 +++++++++------- shaders/ABuffer/abufferSort.hglsl | 12 +++- src/abuffer/abuffer.cpp | 14 +++++ src/interaction/interactionhandler.cpp | 4 +- 6 files changed, 167 insertions(+), 26 deletions(-) create mode 100644 config/sgct/ccmc_lab_all.xml create mode 100644 config/sgct/ccmc_lab_work.xml diff --git a/config/sgct/ccmc_lab_all.xml b/config/sgct/ccmc_lab_all.xml new file mode 100644 index 0000000000..9c2fcd4958 --- /dev/null +++ b/config/sgct/ccmc_lab_all.xml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/config/sgct/ccmc_lab_work.xml b/config/sgct/ccmc_lab_work.xml new file mode 100644 index 0000000000..0c9f4069b6 --- /dev/null +++ b/config/sgct/ccmc_lab_work.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/shaders/ABuffer/abufferResolveFragment.glsl b/shaders/ABuffer/abufferResolveFragment.glsl index bbe589e045..7e2c233a83 100644 --- a/shaders/ABuffer/abufferResolveFragment.glsl +++ b/shaders/ABuffer/abufferResolveFragment.glsl @@ -28,15 +28,20 @@ // Settings // ================================================================================ #pragma openspace insert SETTINGS -#define LOOP_LIMIT 800 +// #define LOOP_LIMIT 500 #define MAX_FRAGMENTS 16 -#define SHOWFUNC + +#define SHOWFUNC 0 + +#define PSCDEPTH 1 +#define ZDEPTH 2 +#define ZTYPE PSCDEPTH const float stepSize = 0.01; const float samplingRate = 1.0; uniform int SCREEN_WIDTH; uniform int SCREEN_HEIGHT; -uniform float ALPHA_LIMIT = 0.98; +uniform float ALPHA_LIMIT = 0.95; in vec2 texCoord; out vec4 color; @@ -54,10 +59,15 @@ out vec4 color; ABufferStruct_t fragments[MAX_FRAGMENTS]; vec3 volume_direction[MAX_VOLUMES]; float volume_length[MAX_VOLUMES]; -vec2 volume_zlength[MAX_VOLUMES]; -// float volume_zlength[MAX_VOLUMES]; vec3 volume_position[MAX_VOLUMES]; +#if ZTYPE == ZDEPTH + vec2 volume_zlength[MAX_VOLUMES]; +#elif ZTYPE == PSCDEPTH + float volume_zlength[MAX_VOLUMES]; +#endif + + #include "abufferSort.hglsl" // ================================================================================ @@ -132,8 +142,7 @@ vec4 calculate_final_color(uint frag_count) { if(bool(currentVolumeBitmask)) { int volID = type -1; float p = 0.0f; - - // const float l = volume_length[volID]; +#if ZTYPE == ZDEPTH const float S1 = volume_zlength[volID].x; const float S2 = volume_zlength[volID].y; const float L = S1 - S2; @@ -145,21 +154,21 @@ vec4 calculate_final_color(uint frag_count) { int max_iterations = int(l / volumeStepSize[volID]); int iterations = 0; vec3 position; +#elif ZTYPE == PSCDEPTH + const float L = volume_zlength[volID]; + const vec4 p1 = _pos_(startFrag); + const vec4 p2 = _pos_(endFrag); + const float dist = pscLength(p1, p2); + // const float z1 = _z_(startFrag); + // const float z2 = _z_(endFrag); + const float l = (dist / L) * volume_length[volID]; + int max_iterations = int(l / volumeStepSize[volID]); + int iterations = 0; + vec3 position; +#endif - // const float S1 = volume_zlength[volID].x; - // const float S2 = volume_zlength[volID].y; - // const float L = volume_zlength[volID]; - // const vec4 p1 = _pos_(startFrag); - // const vec4 p2 = _pos_(endFrag); - // const float dist = pscLength(p1, p2); - // // const float z1 = _z_(startFrag); - // // const float z2 = _z_(endFrag); - // const float l = (dist / L) * volume_length[volID]; - // int max_iterations = int(l / volumeStepSize[volID]); - // int iterations = 0; - // vec3 position; // MIP // vec4 tmp, color = vec4(0); @@ -177,7 +186,7 @@ vec4 calculate_final_color(uint frag_count) { // TransferFunction vec4 color = vec4(0); - for(int k = 0; k < max_iterations && k < LOOP_LIMIT; ++k) { + for(int k = 0; k < max_iterations && final_color.a < ALPHA_LIMIT && k < LOOP_LIMIT; ++k) { //while(p < l && iterations < LOOP_LIMIT) { #pragma openspace insert SAMPLERCALLS @@ -214,7 +223,7 @@ vec4 calculate_final_color(uint frag_count) { // ================================================================================ // Transferfunction visualizer // ================================================================================ -#ifdef SHOWFUNC +#if (SHOWFUNC >= 0) && (SHOWFUNC < MAX_TF) float showfunc_size = 20.0; if(gl_FragCoord.y > float(SCREEN_HEIGHT) - showfunc_size) { float normalizedIntensity = gl_FragCoord.x / float(SCREEN_WIDTH) ; diff --git a/shaders/ABuffer/abufferSort.hglsl b/shaders/ABuffer/abufferSort.hglsl index fd4de48f84..61381bc7d1 100644 --- a/shaders/ABuffer/abufferSort.hglsl +++ b/shaders/ABuffer/abufferSort.hglsl @@ -24,6 +24,8 @@ #include "abufferAddToBuffer.hglsl" +uniform float volumeStepFactor = 1.0f; + int build_local_fragments_list() { uint current; int frag_count = 0; @@ -84,17 +86,21 @@ void sort_fragments_list(uint frag_count) { if(start) { startColor = _col_(fragments[jj]).rgb; startPosition = _pos_(fragments[jj]); +#if ZTYPE == ZDEPTH volume_zlength[ii].x = _z_(fragments[jj]); +#endif start = false; } else { vec3 dir = _col_(fragments[jj]).rgb - startColor; volume_position[ii] = startColor; volume_length[ii] = length(dir); volume_direction[ii] = normalize(dir); + volumeStepSize[ii] = 1.0/(volumeStepFactor * length(volume_direction[ii]*volume_dim[ii])); +#if ZTYPE == ZDEPTH volume_zlength[ii].y = _z_(fragments[jj]); - // volume_zlength[ii] = pscLength(_pos_(fragments[jj]), startPosition); - volumeStepSize[ii] = 1.0/(length(volume_direction[ii]*volume_dim[ii])); - // volume_length[ii] = pscLength(_pos_(fragments[jj]), startPosition); +#elif ZTYPE == PSCDEPTH + volume_zlength[ii] = pscLength(_pos_(fragments[jj]), startPosition); +#endif if(volumeStepSize[ii] < volume_length[ii]) { // jittering diff --git a/src/abuffer/abuffer.cpp b/src/abuffer/abuffer.cpp index 97313125d9..f8f8063726 100644 --- a/src/abuffer/abuffer.cpp +++ b/src/abuffer/abuffer.cpp @@ -145,6 +145,15 @@ void ABuffer::resolve() { _transferFunctions.at(i).second->bind(); } + // Decrease stepsize in volumes if right click is pressed + // TODO: Let the interactionhandler handle this + int val = sgct::Engine::getMouseButton(0, SGCT_MOUSE_BUTTON_RIGHT); + if(val) { + _resolveShader->setUniform("volumeStepFactor", 0.2f); + } else { + _resolveShader->setUniform("volumeStepFactor", 1.0f); + } + glBindVertexArray(_screenQuad); glDrawArrays(GL_TRIANGLES, 0, 6); @@ -260,6 +269,7 @@ std::string ABuffer::openspaceHeaders() { std::string headers; headers += "#define MAX_VOLUMES " + std::to_string(_samplers.size()) + "\n"; + headers += "#define MAX_TF " + std::to_string(_transferFunctions.size()) + "\n"; for (int i = 0; i < _volumes.size(); ++i) { headers += "uniform sampler3D " + _volumes.at(i).first + ";\n"; } @@ -274,13 +284,17 @@ std::string ABuffer::openspaceHeaders() { } } + size_t maxLoop = 0; headers += "const vec3 volume_dim[] = {\n"; for (int i = 0; i < _volumes.size(); ++i) { glm::size3_t size = _volumes.at(i).second->dimensions(); + for(int k = 0; k < 3; ++k) + maxLoop = glm::max(maxLoop, size[k]); headers += " vec3(" + std::to_string(size[0]) + ".0," + std::to_string(size[1]) + ".0," + std::to_string(size[2]) + ".0),\n"; } headers += "};\n"; + headers += "#define LOOP_LIMIT " + std::to_string(maxLoop) + "\n"; headers += "float volumeStepSize[] = {\n"; for (int i = 0; i < _volumes.size(); ++i) { diff --git a/src/interaction/interactionhandler.cpp b/src/interaction/interactionhandler.cpp index 020ba82d3f..5a4dc136f0 100644 --- a/src/interaction/interactionhandler.cpp +++ b/src/interaction/interactionhandler.cpp @@ -396,9 +396,9 @@ void InteractionHandler::mouseButtonCallback(int key, int action) { //if(mouseControl_ != nullptr) { // mouseControl_->mouseButtonCallback(key,action); //} - if (key == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS) + if (key == SGCT_MOUSE_BUTTON_LEFT && action == SGCT_PRESS) _leftMouseButtonDown = true; - else if (key == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_RELEASE) { + else if (key == SGCT_MOUSE_BUTTON_LEFT && action == SGCT_RELEASE) { _leftMouseButtonDown = false; _isMouseBeingPressedAndHeld = false; } From 1996acf997fcb8465f96d167a5684470c5510f0c Mon Sep 17 00:00:00 2001 From: Hans-Christian Helltegen Date: Thu, 3 Jul 2014 14:42:43 -0400 Subject: [PATCH 37/49] Fieldline and seedpoint color now in RGBA instead of RGB --- .../rendering/renderablefieldlines.h | 3 +- include/openspace/util/kameleonwrapper.h | 22 +++++-- openspace-data | 2 +- src/rendering/renderablefieldlines.cpp | 60 ++++++++----------- src/util/kameleonwrapper.cpp | 45 +++++++------- 5 files changed, 64 insertions(+), 68 deletions(-) diff --git a/include/openspace/rendering/renderablefieldlines.h b/include/openspace/rendering/renderablefieldlines.h index c37f5649b6..e250a7e4d5 100644 --- a/include/openspace/rendering/renderablefieldlines.h +++ b/include/openspace/rendering/renderablefieldlines.h @@ -33,6 +33,7 @@ #include namespace openspace { + struct LinePoint; class RenderableFieldlines : public Renderable { public: @@ -46,7 +47,7 @@ public: virtual void update(); private: - std::vector > getFieldlinesData(std::string filename, ghoul::Dictionary hintsDictionary); + std::vector > getFieldlinesData(std::string filename, ghoul::Dictionary hintsDictionary); std::vector _hintsDictionaries; std::vector _filenames; diff --git a/include/openspace/util/kameleonwrapper.h b/include/openspace/util/kameleonwrapper.h index 6b85680231..fd8903f7a2 100644 --- a/include/openspace/util/kameleonwrapper.h +++ b/include/openspace/util/kameleonwrapper.h @@ -34,6 +34,16 @@ namespace ccmc { namespace openspace { +struct LinePoint { + glm::vec3 position; + glm::vec4 color; + + LinePoint(glm::vec3 pos, glm::vec4 col) { + position = pos; + color = col; + } +}; + class KameleonWrapper { public: @@ -59,16 +69,16 @@ public: float* getUniformSampledVectorValues(const std::string& xVar, const std::string& yVar, const std::string& zVar, glm::size3_t outDimensions); - std::vector > getClassifiedFieldLines(const std::string& xVar, + std::vector > getClassifiedFieldLines(const std::string& xVar, const std::string& yVar, const std::string& zVar, std::vector seedPoints, float stepSize); - std::vector > getFieldLines(const std::string& xVar, + std::vector > getFieldLines(const std::string& xVar, const std::string& yVar, const std::string& zVar, - std::vector seedPoints, float stepSize, glm::vec3 color); + std::vector seedPoints, float stepSize, glm::vec4 color); - std::vector > getLorentzTrajectories(std::vector seedPoints, - glm::vec3 color, float stepsize); + std::vector > getLorentzTrajectories(std::vector seedPoints, + glm::vec4 color, float stepsize); private: std::vector traceCartesianFieldline(const std::string& xVar, @@ -80,7 +90,7 @@ private: void getGridVariables(std::string& x, std::string& y, std::string& z); void progressBar(int current, int end); - glm::vec3 classifyFieldline(FieldlineEnd fEnd, FieldlineEnd bEnd); + glm::vec4 classifyFieldline(FieldlineEnd fEnd, FieldlineEnd bEnd); ccmc::Model* _model; Model _type; diff --git a/openspace-data b/openspace-data index 8fa226790e..f858de10c6 160000 --- a/openspace-data +++ b/openspace-data @@ -1 +1 @@ -Subproject commit 8fa226790e939667b31c0e2020ba42708e3de7e6 +Subproject commit f858de10c6b9b30df2aa855e337063ecee9d8ee9 diff --git a/src/rendering/renderablefieldlines.cpp b/src/rendering/renderablefieldlines.cpp index ff4e76c669..50314e5838 100644 --- a/src/rendering/renderablefieldlines.cpp +++ b/src/rendering/renderablefieldlines.cpp @@ -53,10 +53,8 @@ RenderableFieldlines::RenderableFieldlines(const ghoul::Dictionary& dictionary) if(fieldline.hasKey("Hints")) fieldline.getValue("Hints", hintsDictionary); - // TODO Vectors of filenames and dictionaries _filenames.push_back(file); _hintsDictionaries.push_back(hintsDictionary); - } else LERROR("File not found!"); } @@ -72,12 +70,11 @@ RenderableFieldlines::RenderableFieldlines(const ghoul::Dictionary& dictionary) if (dictionary.hasKey("Shaders")) { ghoul::Dictionary shaderDictionary; if(dictionary.getValue("Shaders", shaderDictionary)) { - if (shaderDictionary.hasKey("VertexShader")) { + if (shaderDictionary.hasKey("VertexShader")) shaderDictionary.getValue("VertexShader", vshaderpath); - } - if (shaderDictionary.hasKey("FragmentShader")) { + + if (shaderDictionary.hasKey("FragmentShader")) shaderDictionary.getValue("FragmentShader", fshaderpath); - } vshaderpath = findPath(vshaderpath); fshaderpath = findPath(fshaderpath); @@ -97,11 +94,10 @@ RenderableFieldlines::RenderableFieldlines(const ghoul::Dictionary& dictionary) dictionary.getValue("UpdateOnSave", _programUpdateOnSave); } - setBoundingSphere(PowerScaledScalar::CreatePSS(5)); + setBoundingSphere(PowerScaledScalar::CreatePSS(5)); // FIXME a non-magic number perhaps } RenderableFieldlines::~RenderableFieldlines() { - } bool RenderableFieldlines::initialize() { @@ -109,28 +105,25 @@ bool RenderableFieldlines::initialize() { assert(_hintsDictionaries.size() != 0); int prevEnd = 0; - std::vector vertexData; - std::vector > fieldlinesData; + std::vector vertexData, seedPointsData; + std::vector > fieldlinesData; + glm::vec4 seedPointsColor = glm::vec4(1.0, 0.5, 0.0, 1.0); for (int i = 0; i < _filenames.size(); ++i) { fieldlinesData = getFieldlinesData(_filenames[i], _hintsDictionaries[i]); - for (int j = 0; j < fieldlinesData.size(); j++) { + for (int j = 0; j < fieldlinesData.size(); ++j) { _lineStart.push_back(prevEnd); - _lineCount.push_back(fieldlinesData[j].size()/2.0); - prevEnd = prevEnd + fieldlinesData[j].size()/2.0; - + _lineCount.push_back(fieldlinesData[j].size()); + prevEnd = prevEnd + fieldlinesData[j].size(); vertexData.insert( vertexData.end(), fieldlinesData[j].begin(), fieldlinesData[j].end()); } + // Give seedpoints a color for visualizing as GL_POINTS + for (glm::vec3 seedPoint : _seedPoints) { + seedPointsData.push_back(LinePoint(seedPoint, seedPointsColor)); + } } - LDEBUG("Number of vertices : " << vertexData.size()/2.0); - - // Give seedpoints a color for visualizing as GL_POINTS - std::vector seedPointsData; - for (int i = 0; i < _seedPoints.size(); ++i) { - seedPointsData.push_back(_seedPoints[i]); - seedPointsData.push_back(glm::vec3(1.0, 0.5, 0.0)); - } + LDEBUG("Number of vertices : " << vertexData.size()); // ------ FIELDLINES ----------------- GLuint vertexPositionBuffer; @@ -138,17 +131,17 @@ bool RenderableFieldlines::initialize() { glBindVertexArray(_VAO); // bind array glGenBuffers(1, &vertexPositionBuffer); // generate buffer glBindBuffer(GL_ARRAY_BUFFER, vertexPositionBuffer); // bind buffer - glBufferData(GL_ARRAY_BUFFER, vertexData.size()*sizeof(glm::vec3), &vertexData.front(), GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, vertexData.size()*sizeof(LinePoint), &vertexData.front(), GL_STATIC_DRAW); // Vertex positions GLuint vertexLocation = 0; glEnableVertexAttribArray(vertexLocation); - glVertexAttribPointer(vertexLocation, 3, GL_FLOAT, GL_FALSE, 2*sizeof(glm::vec3), reinterpret_cast(0)); + glVertexAttribPointer(vertexLocation, 3, GL_FLOAT, GL_FALSE, sizeof(LinePoint), reinterpret_cast(0)); // Texture coordinates GLuint texcoordLocation = 1; glEnableVertexAttribArray(texcoordLocation); - glVertexAttribPointer(texcoordLocation, 3, GL_FLOAT, GL_FALSE, 2*sizeof(glm::vec3), (void*)(sizeof(glm::vec3))); + glVertexAttribPointer(texcoordLocation, 4, GL_FLOAT, GL_FALSE, sizeof(LinePoint), (void*)(sizeof(glm::vec3))); glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind buffer glBindVertexArray(0); //unbind array @@ -159,15 +152,15 @@ bool RenderableFieldlines::initialize() { glBindVertexArray(_seedpointVAO); // bind array glGenBuffers(1, &seedpointPositionBuffer); // generate buffer glBindBuffer(GL_ARRAY_BUFFER, seedpointPositionBuffer); // bind buffer - glBufferData(GL_ARRAY_BUFFER, seedPointsData.size()*sizeof(glm::vec3), &seedPointsData.front(), GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, seedPointsData.size()*sizeof(LinePoint), &seedPointsData.front(), GL_STATIC_DRAW); // Vertex positions glEnableVertexAttribArray(vertexLocation); - glVertexAttribPointer(vertexLocation, 3, GL_FLOAT, GL_FALSE, 2*sizeof(glm::vec3), reinterpret_cast(0)); + glVertexAttribPointer(vertexLocation, 3, GL_FLOAT, GL_FALSE, sizeof(LinePoint), reinterpret_cast(0)); // Texture coordinates glEnableVertexAttribArray(texcoordLocation); - glVertexAttribPointer(texcoordLocation, 3, GL_FLOAT, GL_FALSE, 2*sizeof(glm::vec3), (void*)(sizeof(glm::vec3))); + glVertexAttribPointer(texcoordLocation, 4, GL_FLOAT, GL_FALSE, sizeof(LinePoint), (void*)(3*sizeof(float))); glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind buffer glBindVertexArray(0); //unbind array @@ -194,7 +187,6 @@ bool RenderableFieldlines::deinitialize() { } void RenderableFieldlines::render(const Camera* camera, const psc& thisPosition) { - if(_update) { _update = false; safeShaderCompilation(); @@ -205,11 +197,8 @@ void RenderableFieldlines::render(const Camera* camera, const psc& thisPosition) psc relative = thisPosition-camera->position(); transform = transform*camTransform; - //transform = glm::translate(transform, relative.vec3()); transform = glm::mat4(1.0); -// transform = glm::scale(transform, glm::vec3(0.036*0.5*0.5)); transform = glm::scale(transform, glm::vec3(0.01)); - //transform = glm::scale(transform, glm::vec3(0.1)); // Scale to avoid depth buffer problems psc currentPosition = thisPosition; psc campos = camera->position(); @@ -218,7 +207,6 @@ void RenderableFieldlines::render(const Camera* camera, const psc& thisPosition) // Activate shader _fieldlinesProgram->activate(); - //_fieldlinesProgram->setUniform("modelViewProjection", transform); _fieldlinesProgram->setUniform("modelViewProjection", camera->viewProjectionMatrix()); _fieldlinesProgram->setUniform("modelTransform", transform); @@ -249,15 +237,15 @@ void RenderableFieldlines::safeShaderCompilation() { _fieldlinesProgram->linkProgramObject(); } -std::vector > RenderableFieldlines::getFieldlinesData(std::string filename, ghoul::Dictionary hintsDictionary) { +std::vector > RenderableFieldlines::getFieldlinesData(std::string filename, ghoul::Dictionary hintsDictionary) { std::string modelString; float stepSize = 0.5; // default if no stepsize is specified in hints std::string xVariable, yVariable, zVariable; KameleonWrapper::Model model; - std::vector > fieldlinesData; + std::vector > fieldlinesData; bool classification = false, lorentz = false; - glm::vec3 fieldlineColor = glm::vec3(1.0, 1.0, 1.0); // default color if no color or classification is specified + glm::vec4 fieldlineColor = glm::vec4(1.0, 1.0, 1.0, 1.0); // default color if no color or classification is specified if (hintsDictionary.hasKey("Model") && hintsDictionary.getValue("Model", modelString)) { // ------ MODEL ----------------- diff --git a/src/util/kameleonwrapper.cpp b/src/util/kameleonwrapper.cpp index 1fa2b423f6..0ca5a7d9b5 100644 --- a/src/util/kameleonwrapper.cpp +++ b/src/util/kameleonwrapper.cpp @@ -269,7 +269,7 @@ float* KameleonWrapper::getUniformSampledVectorValues(const std::string& xVar, c return data; } -std::vector > KameleonWrapper::getClassifiedFieldLines( +std::vector > KameleonWrapper::getClassifiedFieldLines( const std::string& xVar, const std::string& yVar, const std::string& zVar, std::vector seedPoints, float stepSize ) { @@ -278,8 +278,8 @@ std::vector > KameleonWrapper::getClassifiedFieldLines( LINFO("Creating " << seedPoints.size() << " fieldlines from variables " << xVar << " " << yVar << " " << zVar); std::vector fLine, bLine; - std::vector > fieldLines; - glm::vec3 color; + std::vector > fieldLines; + glm::vec4 color; FieldlineEnd forwardEnd, backEnd; if (_type == Model::BATSRUS) { @@ -293,10 +293,9 @@ std::vector > KameleonWrapper::getClassifiedFieldLines( color = classifyFieldline(forwardEnd, backEnd); // write colors - std::vector line; + std::vector line; for (glm::vec3 position : bLine) { - line.push_back(position); - line.push_back(color); + line.push_back(LinePoint(position, color)); } fieldLines.push_back(line); @@ -308,16 +307,16 @@ std::vector > KameleonWrapper::getClassifiedFieldLines( return fieldLines; } -std::vector > KameleonWrapper::getFieldLines( +std::vector > KameleonWrapper::getFieldLines( const std::string& xVar, const std::string& yVar, const std::string& zVar, std::vector seedPoints, - float stepSize, glm::vec3 color ) { + float stepSize, glm::vec4 color ) { assert(_model && _interpolator); assert(_type == Model::ENLIL || _type == Model::BATSRUS); LINFO("Creating " << seedPoints.size() << " fieldlines from variables " << xVar << " " << yVar << " " << zVar); std::vector fLine, bLine; - std::vector > fieldLines; + std::vector > fieldLines; FieldlineEnd forwardEnd, backEnd; if (_type == Model::BATSRUS) { @@ -328,10 +327,9 @@ std::vector > KameleonWrapper::getFieldLines( bLine.insert(bLine.begin(), fLine.rbegin(), fLine.rend()); // write colors - std::vector line; + std::vector line; for (glm::vec3 position : bLine) { - line.push_back(position); - line.push_back(color); + line.push_back(LinePoint(position, color)); } fieldLines.push_back(line); @@ -343,11 +341,11 @@ std::vector > KameleonWrapper::getFieldLines( return fieldLines; } -std::vector > KameleonWrapper::getLorentzTrajectories( - std::vector seedPoints, glm::vec3 color, float stepsize) { +std::vector > KameleonWrapper::getLorentzTrajectories( + std::vector seedPoints, glm::vec4 color, float stepsize) { LINFO("Creating " << seedPoints.size() << " Lorentz force trajectories"); - std::vector > trajectories; + std::vector > trajectories; std::vector plusTraj, minusTraj; for (auto seedPoint : seedPoints) { @@ -357,10 +355,9 @@ std::vector > KameleonWrapper::getLorentzTrajectories( minusTraj.insert(minusTraj.begin(), plusTraj.rbegin(), plusTraj.rend()); // write colors - std::vector trajectory; + std::vector trajectory; for (glm::vec3 position : minusTraj) { - trajectory.push_back(position); - trajectory.push_back(color); + trajectory.push_back(LinePoint(position, color)); } trajectories.push_back(trajectory); } @@ -567,23 +564,23 @@ void KameleonWrapper::progressBar(int current, int end) { _lastiProgress = iprogress; } -glm::vec3 KameleonWrapper::classifyFieldline(FieldlineEnd fEnd, FieldlineEnd bEnd) { - glm::vec3 color; +glm::vec4 KameleonWrapper::classifyFieldline(FieldlineEnd fEnd, FieldlineEnd bEnd) { + glm::vec4 color; if ( (fEnd == FieldlineEnd::NORTH || fEnd == FieldlineEnd::SOUTH) && (bEnd == FieldlineEnd::NORTH || bEnd == FieldlineEnd::SOUTH)) { // closed - color = glm::vec3(1.0, 0.0, 0.0); + color = glm::vec4(1.0, 0.0, 0.0, 1.0); } else if ((fEnd == FieldlineEnd::OUT && bEnd == FieldlineEnd::NORTH) || (bEnd == FieldlineEnd::OUT && fEnd == FieldlineEnd::NORTH)) { // north - color = glm::vec3(1.0, 1.0, 0.0); + color = glm::vec4(1.0, 1.0, 0.0, 1.0); } else if ((fEnd == FieldlineEnd::OUT && bEnd == FieldlineEnd::SOUTH) || (bEnd == FieldlineEnd::OUT && fEnd == FieldlineEnd::SOUTH)) { // south - color = glm::vec3(0.0, 1.0, 0.0); + color = glm::vec4(0.0, 1.0, 0.0, 1.0); } else if (fEnd == FieldlineEnd::OUT && bEnd == FieldlineEnd::OUT) { // solar wind - color = glm::vec3(0.0, 0.0, 1.0); + color = glm::vec4(0.0, 0.0, 1.0, 1.0); } return color; } From aff61620c8d1b8d1b698f81dd830cdcb6fd722f7 Mon Sep 17 00:00:00 2001 From: Hans-Christian Helltegen Date: Mon, 7 Jul 2014 14:26:22 -0400 Subject: [PATCH 38/49] Added functionality for getting the model barycenter in kameleonwrapper and moving the raycasting box by an offset. Also cleaned up renderablevolumegl a bit --- .../openspace/rendering/renderablevolume.h | 1 + .../openspace/rendering/renderablevolumegl.h | 7 +--- src/rendering/renderablevolume.cpp | 32 +++++++++++++++++-- src/rendering/renderablevolumegl.cpp | 32 ++++--------------- src/util/kameleonwrapper.cpp | 21 ++++++++---- 5 files changed, 52 insertions(+), 41 deletions(-) diff --git a/include/openspace/rendering/renderablevolume.h b/include/openspace/rendering/renderablevolume.h index 870b8ee672..9c9c1c4b9c 100644 --- a/include/openspace/rendering/renderablevolume.h +++ b/include/openspace/rendering/renderablevolume.h @@ -42,6 +42,7 @@ public: protected: ghoul::opengl::Texture* loadVolume(const std::string& filepath, const ghoul::Dictionary& hintsDictionary); + glm::vec3 getVolumeOffset(const std::string& filepath, const ghoul::Dictionary& hintsDictionary); ghoul::RawVolumeReader::ReadHints readHints(const ghoul::Dictionary& dictionary); ghoul::opengl::Texture* loadTransferFunction(const std::string& filepath); diff --git a/include/openspace/rendering/renderablevolumegl.h b/include/openspace/rendering/renderablevolumegl.h index c368e41cfc..b13ed7cc5a 100644 --- a/include/openspace/rendering/renderablevolumegl.h +++ b/include/openspace/rendering/renderablevolumegl.h @@ -35,10 +35,6 @@ #include #include - namespace sgct_utils { - class SGCTBox; -} - namespace openspace { class RenderableVolumeGL: public RenderableVolume { @@ -67,8 +63,7 @@ private: GLuint _boxArray; ghoul::opengl::ProgramObject *_boxProgram; - sgct_utils::SGCTBox* _box; - glm::vec3 _boxScaling; + glm::vec3 _boxScaling, _boxOffset; GLint _MVPLocation, _modelTransformLocation, _typeLocation; bool _updateTransferfunction; diff --git a/src/rendering/renderablevolume.cpp b/src/rendering/renderablevolume.cpp index 7d6efbd93f..e21d6edde8 100644 --- a/src/rendering/renderablevolume.cpp +++ b/src/rendering/renderablevolume.cpp @@ -79,8 +79,8 @@ RenderableVolume::~RenderableVolume() { ghoul::opengl::Texture* RenderableVolume::loadVolume( const std::string& filepath, - const ghoul::Dictionary& hintsDictionary) -{ + const ghoul::Dictionary& hintsDictionary) { + if( ! FileSys.fileExists(filepath)) { LWARNING("Could not load volume, could not find '" << filepath << "'"); return nullptr; @@ -174,7 +174,6 @@ ghoul::opengl::Texture* RenderableVolume::loadVolume( } KameleonWrapper kw(filepath, model); - std::string variableString; if (hintsDictionary.hasKey("Variable") && hintsDictionary.getValue("Variable", variableString)) { float* data = kw.getUniformSampledValues(variableString, dimensions); @@ -220,6 +219,33 @@ ghoul::opengl::Texture* RenderableVolume::loadVolume( return nullptr; } +glm::vec3 RenderableVolume::getVolumeOffset( + const std::string& filepath, + const ghoul::Dictionary& hintsDictionary) { + + std::string modelString = ""; + if (hintsDictionary.hasKey("Model")) + hintsDictionary.getValue("Model", modelString); + + if(modelString == "") { + LWARNING("Model not specified."); + return glm::vec3(0); + } + KameleonWrapper::Model model; + if (modelString == "BATSRUS") { + model = KameleonWrapper::Model::BATSRUS; + } else if (modelString == "ENLIL") { + model = KameleonWrapper::Model::ENLIL; + } else { + LWARNING("Hints does not specify a valid 'Model'"); + return glm::vec3(0); + } + + KameleonWrapper kw(filepath, model); + + return kw.getModelBarycenterOffset(); +} + ghoul::RawVolumeReader::ReadHints RenderableVolume::readHints(const ghoul::Dictionary& dictionary) { ghoul::RawVolumeReader::ReadHints hints; hints._dimensions = glm::ivec3(1, 1, 1); diff --git a/src/rendering/renderablevolumegl.cpp b/src/rendering/renderablevolumegl.cpp index bdcdc9ae79..a888b241d4 100644 --- a/src/rendering/renderablevolumegl.cpp +++ b/src/rendering/renderablevolumegl.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -34,7 +35,6 @@ #include #include -#include namespace { std::string _loggerCat = "RenderableVolumeGL"; @@ -43,9 +43,8 @@ namespace { namespace openspace { RenderableVolumeGL::RenderableVolumeGL(const ghoul::Dictionary& dictionary): - RenderableVolume(dictionary), _box(nullptr), _boxScaling(1.0, 1.0, 1.0), + RenderableVolume(dictionary), _boxScaling(1.0, 1.0, 1.0), _updateTransferfunction(false), _id(-1) { - _filename = ""; if(dictionary.hasKey("Volume")) { @@ -80,8 +79,7 @@ RenderableVolumeGL::RenderableVolumeGL(const ghoul::Dictionary& dictionary): } if( _samplerFilename == "") { LERROR("No samplerfile!"); - } - + } double tempValue; if(dictionary.hasKey("BoxScaling.1") && dictionary.getValue("BoxScaling.1", tempValue)) { @@ -108,14 +106,13 @@ RenderableVolumeGL::~RenderableVolumeGL() { delete _transferFunctionFile; if(_transferFunction) delete _transferFunction; - if(_box) - delete _box; } bool RenderableVolumeGL::initialize() { assert(_filename != ""); // ------ VOLUME READING ---------------- _volume = loadVolume(_filename, _hintsDictionary); + _boxOffset = getVolumeOffset(_filename, _hintsDictionary); _volume->uploadTexture(); _transferFunction = loadTransferFunction(_transferFunctionPath); _transferFunction->uploadTexture(); @@ -130,7 +127,6 @@ bool RenderableVolumeGL::initialize() { }; _transferFunctionFile->setCallback(textureCallback); - _box = new sgct_utils::SGCTBox(1.0f, sgct_utils::SGCTBox::Regular); OsEng.configurationManager().getValue("RaycastProgram", _boxProgram); _MVPLocation = _boxProgram->uniformLocation("modelViewProjection"); _modelTransformLocation = _boxProgram->uniformLocation("modelTransform"); @@ -191,10 +187,7 @@ bool RenderableVolumeGL::initialize() { glBindBuffer(GL_ARRAY_BUFFER, vertexPositionBuffer); // bind buffer glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data, GL_STATIC_DRAW); glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*4, reinterpret_cast(0)); - //glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*7, reinterpret_cast(0)); glEnableVertexAttribArray(0); - //glEnableVertexAttribArray(1); - return true; } @@ -220,12 +213,6 @@ void RenderableVolumeGL::render(const Camera *camera, const psc &thisPosition) { } } - //psc relative = thisPosition-camera->position(); - - // glm::mat4 transform = camera->viewRotationMatrix(); - // transform = glm::translate(transform, relative.vec3()); - // transform = glm::translate(transform, glm::vec3(-1.1,0.0,0.0)); - // transform = glm::scale(transform, _boxScaling); glm::mat4 transform = glm::mat4(1.0); transform = glm::scale(transform, _boxScaling); @@ -235,13 +222,11 @@ void RenderableVolumeGL::render(const Camera *camera, const psc &thisPosition) { glm::mat4 camrot = camera->viewRotationMatrix(); PowerScaledScalar scaling = camera->scaling(); - psc addon(-1.1,0.0,0.0,0.0); - currentPosition += addon; + psc addon(_boxOffset/100.0f); // TODO: Proper scaling/units + currentPosition += addon; // Move box to model barycenter // TODO: Use _id to identify this volume _boxProgram->activate(); - // _boxProgram->setUniform(_MVPLocation, camera->viewProjectionMatrix()); - // _boxProgram->setUniform(_modelTransformLocation, transform); _boxProgram->setUniform(_typeLocation, _id); _boxProgram->setUniform("modelViewProjection", camera->viewProjectionMatrix()); @@ -258,20 +243,15 @@ void RenderableVolumeGL::render(const Camera *camera, const psc &thisPosition) { glCullFace(GL_FRONT); glBindVertexArray(_boxArray); glDrawArrays(GL_TRIANGLES, 0, 6*6); - // _box->draw(); // Draw frontface (now the normal cull face is is set) glCullFace(GL_BACK); glDrawArrays(GL_TRIANGLES, 0, 6*6); - // _box->draw(); _boxProgram->deactivate(); - } void RenderableVolumeGL::update() { - } - } // namespace openspace diff --git a/src/util/kameleonwrapper.cpp b/src/util/kameleonwrapper.cpp index 0ca5a7d9b5..3d2918d84c 100644 --- a/src/util/kameleonwrapper.cpp +++ b/src/util/kameleonwrapper.cpp @@ -65,12 +65,12 @@ KameleonWrapper::KameleonWrapper(const std::string& filename, Model model): _typ } getGridVariables(_xCoordVar, _yCoordVar, _zCoordVar); - _xMin = _model->getVariableAttribute(_xCoordVar, "actual_min").getAttributeFloat(); - _xMax = _model->getVariableAttribute(_xCoordVar, "actual_max").getAttributeFloat(); - _yMin = _model->getVariableAttribute(_yCoordVar, "actual_min").getAttributeFloat(); - _yMax = _model->getVariableAttribute(_yCoordVar, "actual_max").getAttributeFloat(); - _zMin = _model->getVariableAttribute(_zCoordVar, "actual_min").getAttributeFloat(); - _zMax = _model->getVariableAttribute(_zCoordVar, "actual_max").getAttributeFloat(); + _xMin = _model->getVariableAttribute(_xCoordVar, "actual_min").getAttributeFloat(); + _xMax = _model->getVariableAttribute(_xCoordVar, "actual_max").getAttributeFloat(); + _yMin = _model->getVariableAttribute(_yCoordVar, "actual_min").getAttributeFloat(); + _yMax = _model->getVariableAttribute(_yCoordVar, "actual_max").getAttributeFloat(); + _zMin = _model->getVariableAttribute(_zCoordVar, "actual_min").getAttributeFloat(); + _zMax = _model->getVariableAttribute(_zCoordVar, "actual_max").getAttributeFloat(); _lastiProgress = -1; // For progressbar } @@ -259,6 +259,7 @@ float* KameleonWrapper::getUniformSampledVectorValues(const std::string& xVar, c data[index + 3] = 1.0; // GL_RGB refuses to work. Workaround by doing a GL_RGBA with hardcoded alpha } else { LERROR("Only BATSRUS supported for getUniformSampledVectorValues (for now)"); + return data; } } } @@ -365,6 +366,14 @@ std::vector > KameleonWrapper::getLorentzTrajectories( return trajectories; } +glm::vec3 KameleonWrapper::getModelBarycenterOffset() { + glm::vec3 offset; + offset.x = _xMin+(std::abs(_xMin)+std::abs(_xMax))/2.0f; + offset.y = _yMin+(std::abs(_yMin)+std::abs(_yMax))/2.0f; + offset.z = _zMin+(std::abs(_zMin)+std::abs(_zMax))/2.0f; + return offset; +} + std::vector KameleonWrapper::traceCartesianFieldline( const std::string& xVar, const std::string& yVar, const std::string& zVar, glm::vec3 seedPoint, From 576710f1efd353e56fabb453678e4d0975125a3b Mon Sep 17 00:00:00 2001 From: Jonas Strandstedt Date: Tue, 8 Jul 2014 13:29:15 -0400 Subject: [PATCH 39/49] Added fixed ABuffer implementation --- include/openspace/abuffer/abuffer.h | 3 + .../openspace/abuffer/abufferSingleLinked.h | 2 +- include/openspace/abuffer/abufferdynamic.h | 60 ++++++++ include/openspace/abuffer/abufferfixed.h | 61 ++++++++ .../openspace/rendering/renderablevolumegl.h | 4 + shaders/ABuffer/abufferAddToBuffer.hglsl | 45 +++++- shaders/ABuffer/abufferResolveFragment.glsl | 93 ++++++++---- shaders/ABuffer/abufferSort.hglsl | 23 ++- shaders/ABuffer/abufferStruct.hglsl | 56 ++++--- shaders/exitpoints.frag | 4 +- src/abuffer/abuffer.cpp | 71 +++++++-- src/abuffer/abufferSingleLinked.cpp | 2 +- src/abuffer/abufferdynamic.cpp | 124 ++++++++++++++++ src/abuffer/abufferfixed.cpp | 137 ++++++++++++++++++ src/rendering/renderablevolumegl.cpp | 15 +- src/rendering/renderengine.cpp | 6 +- src/scenegraph/scenegraph.cpp | 110 ++++++-------- src/scenegraph/scenegraphnode.cpp | 5 +- src/util/kameleonwrapper.cpp | 45 ++++-- 19 files changed, 723 insertions(+), 143 deletions(-) create mode 100644 include/openspace/abuffer/abufferdynamic.h create mode 100644 include/openspace/abuffer/abufferfixed.h create mode 100644 src/abuffer/abufferdynamic.cpp create mode 100644 src/abuffer/abufferfixed.cpp diff --git a/include/openspace/abuffer/abuffer.h b/include/openspace/abuffer/abuffer.h index 96e35ec9dd..f7c2f9e032 100644 --- a/include/openspace/abuffer/abuffer.h +++ b/include/openspace/abuffer/abuffer.h @@ -63,6 +63,7 @@ protected: std::string openspaceHeaders(); std::string openspaceSamplerCalls(); std::string openspaceSamplers(); + std::string openspaceTransferFunction(); unsigned int _width, _height, _totalPixels; @@ -82,6 +83,8 @@ private: // Development functionality to update shader for changes in several files std::vector _shaderFiles; + float _volumeStepFactor; + }; // ABuffer diff --git a/include/openspace/abuffer/abufferSingleLinked.h b/include/openspace/abuffer/abufferSingleLinked.h index b800dfb856..c348abee52 100644 --- a/include/openspace/abuffer/abufferSingleLinked.h +++ b/include/openspace/abuffer/abufferSingleLinked.h @@ -54,7 +54,7 @@ private: -}; // ABuffer_I +}; // ABufferSingleLinked } // openspace #endif // __ABUFFERSINGLELINKED_H__ \ No newline at end of file diff --git a/include/openspace/abuffer/abufferdynamic.h b/include/openspace/abuffer/abufferdynamic.h new file mode 100644 index 0000000000..23959f08f1 --- /dev/null +++ b/include/openspace/abuffer/abufferdynamic.h @@ -0,0 +1,60 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __ABUFFERDYNAMIC_H__ +#define __ABUFFERDYNAMIC_H__ + +#include + +namespace openspace { + +class ABufferDynamic: public ABuffer { +public: + + ABufferDynamic(); + virtual ~ABufferDynamic(); + virtual bool initialize(); + + virtual void clear(); + virtual void preRender(); + virtual void postRender(); + + virtual std::string settings(); + +private: + + GLuint *_data; + GLuint _anchorPointerTexture; + GLuint _anchorPointerTextureInitializer; + GLuint _atomicCounterBuffer; + GLuint _fragmentBuffer; + GLuint _fragmentTexture; + + + + +}; // ABufferDynamic +} // openspace + +#endif // __ABUFFERDYNAMIC_H__ \ No newline at end of file diff --git a/include/openspace/abuffer/abufferfixed.h b/include/openspace/abuffer/abufferfixed.h new file mode 100644 index 0000000000..cc211e0b57 --- /dev/null +++ b/include/openspace/abuffer/abufferfixed.h @@ -0,0 +1,61 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __ABUFFERFIXED_H__ +#define __ABUFFERFIXED_H__ + +#include + +namespace openspace { + +class ABufferFixed: public ABuffer { +public: + + ABufferFixed(); + virtual ~ABufferFixed(); + virtual bool initialize(); + + virtual void clear(); + virtual void preRender(); + virtual void postRender(); + + virtual std::string settings(); + +private: + + GLuint *_data; + GLuint _anchorPointerTexture; + GLuint _anchorPointerTextureInitializer; + GLuint _atomicCounterBuffer; + GLuint _atomicCounterTexture; + GLuint _fragmentBuffer; + GLuint _fragmentTexture; + + + + +}; // ABufferFixed +} // openspace + +#endif // __ABUFFERFIXED_H__ \ No newline at end of file diff --git a/include/openspace/rendering/renderablevolumegl.h b/include/openspace/rendering/renderablevolumegl.h index c368e41cfc..56792624bc 100644 --- a/include/openspace/rendering/renderablevolumegl.h +++ b/include/openspace/rendering/renderablevolumegl.h @@ -57,6 +57,10 @@ private: ghoul::Dictionary _hintsDictionary; std::string _filename; + + std::string _transferFunctionName; + std::string _volumeName; + std::string _transferFunctionPath; std::string _samplerFilename; diff --git a/shaders/ABuffer/abufferAddToBuffer.hglsl b/shaders/ABuffer/abufferAddToBuffer.hglsl index 3ee940f0d7..92248796c0 100644 --- a/shaders/ABuffer/abufferAddToBuffer.hglsl +++ b/shaders/ABuffer/abufferAddToBuffer.hglsl @@ -22,11 +22,22 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ +#if ABUFFER_IMPLEMENTATION == ABUFFER_SINGLE_LINKED layout (binding = 0, r32ui) uniform uimage2D anchorPointerTexture; layout (binding = 1, rgba32ui) uniform uimageBuffer fragmentTexture; layout (binding = 0, offset = 0) uniform atomic_uint atomicCounterBuffer; +#endif -ABufferStruct_t createGeometryFragment(vec4 fragColor, vec4 position = vec4(0), float z = gl_FragCoord.z) { +#if ABUFFER_IMPLEMENTATION == ABUFFER_FIXED +layout (binding = 0, r32ui) uniform uimage2D anchorPointerTexture; +layout (binding = 1, rgba32ui) uniform uimageBuffer fragmentTexture; + + #define _MAX_LAYERS_ 16 + #define _SCREEN_WIDTH_ 1280 + #define _SCREEN_HEIGHT_ 720 +#endif + +ABufferStruct_t createGeometryFragment(vec4 fragColor, vec4 position, float z = gl_FragCoord.z) { ABufferStruct_t frag; _col_(frag, fragColor); _z_(frag, z); @@ -37,6 +48,7 @@ ABufferStruct_t createGeometryFragment(vec4 fragColor, vec4 position = vec4(0), void addToBuffer(ABufferStruct_t frag) { +#if ABUFFER_IMPLEMENTATION == ABUFFER_SINGLE_LINKED uint index = atomicCounterIncrement(atomicCounterBuffer); index *= 2; uint old_head = imageAtomicExchange(anchorPointerTexture, ivec2(gl_FragCoord.xy), index); @@ -47,17 +59,44 @@ void addToBuffer(ABufferStruct_t frag) { imageStore(fragmentTexture, int(index), p1); imageStore(fragmentTexture, int(index+1), p2); +#endif + +#if ABUFFER_IMPLEMENTATION == ABUFFER_FIXED + uint index = imageAtomicAdd(anchorPointerTexture, ivec2(gl_FragCoord.xy), 1); + if(index < _MAX_LAYERS_) { + int offset = (int(gl_FragCoord.y) * _SCREEN_WIDTH_ + int(gl_FragCoord.x))*_MAX_LAYERS_ + int(index)*2; + + uvec4 p1 = uvec4(frag.z, frag.id, frag.rg, frag.ba); + uvec4 p2 = uvec4(floatBitsToUint(frag.position.x),floatBitsToUint(frag.position.y),floatBitsToUint(frag.position.z),floatBitsToUint(frag.position.w)); + + imageStore(fragmentTexture, int(offset ), p1); + imageStore(fragmentTexture, int(offset+1), p2); + } else { + imageAtomicAdd(anchorPointerTexture, ivec2(gl_FragCoord.xy), -1); + } + +#endif + } ABufferStruct_t loadFromBuffer(uint id) { +#if ABUFFER_IMPLEMENTATION == ABUFFER_SINGLE_LINKED uvec4 u1 = imageLoad(fragmentTexture, int(id)); - uvec4 u2 = imageLoad(fragmentTexture, int(id+1)); - + uvec4 u2 = imageLoad(fragmentTexture, int(id+1)); +#endif + +#if ABUFFER_IMPLEMENTATION == ABUFFER_FIXED + int offset = (int(gl_FragCoord.y) * _SCREEN_WIDTH_ + int(gl_FragCoord.x))*_MAX_LAYERS_ + int(id)*2; + uvec4 u1 = imageLoad(fragmentTexture, int(offset)); + uvec4 u2 = imageLoad(fragmentTexture, int(offset+1)); +#endif + vec4 position = vec4( uintBitsToFloat(u2.x), uintBitsToFloat(u2.y), uintBitsToFloat(u2.z), uintBitsToFloat(u2.w)); return ABufferStruct_t(u1.x, u1.y, u1.z, u1.w, position); + } \ No newline at end of file diff --git a/shaders/ABuffer/abufferResolveFragment.glsl b/shaders/ABuffer/abufferResolveFragment.glsl index 7e2c233a83..b230a51e23 100644 --- a/shaders/ABuffer/abufferResolveFragment.glsl +++ b/shaders/ABuffer/abufferResolveFragment.glsl @@ -28,15 +28,32 @@ // Settings // ================================================================================ #pragma openspace insert SETTINGS -// #define LOOP_LIMIT 500 #define MAX_FRAGMENTS 16 -#define SHOWFUNC 0 +#define SHOWFUNC +// #define JITTERING #define PSCDEPTH 1 #define ZDEPTH 2 -#define ZTYPE PSCDEPTH -const float stepSize = 0.01; +#define ZTYPE ZDEPTH + +// Math defintions +#define M_E 2.7182818284590452354 +#define M_LOG2E 1.4426950408889634074 /* log_2 e */ +#define M_LOG10E 0.43429448190325182765 /* log_10 e */ +#define M_LN2 0.69314718055994530942 /* log_e 2 */ +#define M_LN10 2.30258509299404568402 /* log_e 10 */ +#define M_PI 3.14159265358979323846 /* pi */ +// #define M_PI 3.141592653589793238462643383279 /* pi */ +#define M_PI_2 1.57079632679489661923 /* pi/2 */ +#define M_PI_4 0.78539816339744830962 /* pi/4 */ +#define M_1_PI 0.31830988618379067154 /* 1/pi */ +#define M_2_PI 0.63661977236758134308 /* 2/pi */ +#define M_2_SQRTPI 1.12837916709551257390 /* 2/sqrt(pi) */ +#define M_SQRT2 1.41421356237309504880 /* sqrt(2) */ +#define M_SQRT1_2 0.70710678118654752440 /* 1/sqrt(2) */ + +const float stepSize = 0.01; const float samplingRate = 1.0; uniform int SCREEN_WIDTH; @@ -52,11 +69,36 @@ out vec4 color; // ================================================================================ #pragma openspace insert HEADERS +vec3 CartesianToSpherical(vec3 _cartesian) { + // Put cartesian in [-1..1] range first + vec3 cartesian = vec3(-1.0,-1.0,-1.0) + _cartesian * 2.0f; + + float r = length(cartesian); + float theta, phi; + + if (r == 0.0) { + theta = phi = 0.0; + } else { + theta = acos(cartesian.z/r) / M_PI; + phi = (M_PI + atan(cartesian.y, cartesian.x)) / (2.0*M_PI); + // phi = (M_PI + atan(cartesian.x, cartesian.y)) / (2.0*M_PI); + } + // r *= 0.57735026919; + r = r / sqrt(3.0f); + + // Sampler ignores w component + // return vec3(r, phi, theta); + return vec3(r, theta, phi); + // return vec3(r, phi*0.7, theta); +} + // ================================================================================ // The ABuffer specific includes and definitions // ================================================================================ #include "abufferStruct.hglsl" ABufferStruct_t fragments[MAX_FRAGMENTS]; + +#if MAX_VOLUMES > 0 vec3 volume_direction[MAX_VOLUMES]; float volume_length[MAX_VOLUMES]; vec3 volume_position[MAX_VOLUMES]; @@ -66,8 +108,7 @@ vec3 volume_position[MAX_VOLUMES]; #elif ZTYPE == PSCDEPTH float volume_zlength[MAX_VOLUMES]; #endif - - +#endif #include "abufferSort.hglsl" // ================================================================================ @@ -83,6 +124,7 @@ vec4 blend(vec4 src, vec4 dst) { void blendStep(inout vec4 dst, in vec4 src, in float stepSize) { src.a = 1.0 - pow(1.0 - src.a, stepSize ); + // src.a = 1.0 -(1.0 - src.a*stepSize); dst.rgb = dst.rgb + (1.0 - dst.a) * src.a * src.rgb; dst.a = dst.a + (1.0 -dst.a) * src.a; } @@ -126,20 +168,18 @@ vec4 calculate_final_color(uint frag_count) { int frag_count_1 = int(frag_count)-1; for(int i = 0; i < frag_count_1 && final_color.a < ALPHA_LIMIT; i++) { - //int maxFrags = int(frag_count)-1; - //for(int i = 0; i < frag_count; i++) { ABufferStruct_t startFrag = fragments[i]; ABufferStruct_t endFrag = fragments[i+1]; - //vec4 frag_color = _col_(startFrag); - //vec4 position = _pos_(startFrag); int type = int(_type_(startFrag)); - currentVolumeBitmask = currentVolumeBitmask ^ (type); if(type == 0) //blendStep(final_color, _col_(startFrag), stepSize); final_color = blend(final_color, _col_(startFrag)); - if(bool(currentVolumeBitmask)) { + +#if MAX_VOLUMES > 0 + currentVolumeBitmask = currentVolumeBitmask ^ type; + if(currentVolumeBitmask != 0) { int volID = type -1; float p = 0.0f; #if ZTYPE == ZDEPTH @@ -152,7 +192,6 @@ vec4 calculate_final_color(uint frag_count) { // const float z2 = _z_(endFrag); const float l = ((z1 - S1) / L - (z2 - S1) / L) * volume_length[volID]; int max_iterations = int(l / volumeStepSize[volID]); - int iterations = 0; vec3 position; #elif ZTYPE == PSCDEPTH const float L = volume_zlength[volID]; @@ -163,7 +202,6 @@ vec4 calculate_final_color(uint frag_count) { // const float z2 = _z_(endFrag); const float l = (dist / L) * volume_length[volID]; int max_iterations = int(l / volumeStepSize[volID]); - int iterations = 0; vec3 position; #endif @@ -199,6 +237,7 @@ vec4 calculate_final_color(uint frag_count) { } } +#endif @@ -223,26 +262,28 @@ vec4 calculate_final_color(uint frag_count) { // ================================================================================ // Transferfunction visualizer // ================================================================================ -#if (SHOWFUNC >= 0) && (SHOWFUNC < MAX_TF) - float showfunc_size = 20.0; - if(gl_FragCoord.y > float(SCREEN_HEIGHT) - showfunc_size) { - float normalizedIntensity = gl_FragCoord.x / float(SCREEN_WIDTH) ; - vec4 tfc = texture(transferFunction1, normalizedIntensity); - final_color = tfc; - } else if(ceil(gl_FragCoord.y) == float(SCREEN_HEIGHT) - showfunc_size) { - const float intensity = 0.4; - final_color = vec4(intensity,intensity,intensity,1.0); - } +#ifdef SHOWFUNC +#pragma openspace insert TRANSFERFUNC #endif // if(frag_count == 1) { - // final_color = vec4(0.0,0.0,1.0,1.0); + // final_color = vec4(1.0,0.0,0.0,1.0); // } else if(frag_count == 2) { - // final_color = vec4(volume_direction[0],1.0); + // final_color = vec4(0.0,1.0,0.0,1.0); + // // final_color = vec4(volume_direction[0],1.0); + // } else if(frag_count == 3) { + // final_color = vec4(0.0,0.0,1.0,1.0); + // // final_color = vec4(volume_direction[0],1.0); + // } else if(frag_count == 4) { + // final_color = vec4(1.0,1.0,0.0,1.0); + // // final_color = vec4(volume_direction[0],1.0); // } else { // final_color = vec4(1.0,1.0,1.0,1.0); // } + final_color.rgb = final_color.rgb * final_color.a; + final_color.a = 1.0; + return final_color; } diff --git a/shaders/ABuffer/abufferSort.hglsl b/shaders/ABuffer/abufferSort.hglsl index 61381bc7d1..5d05460117 100644 --- a/shaders/ABuffer/abufferSort.hglsl +++ b/shaders/ABuffer/abufferSort.hglsl @@ -27,6 +27,8 @@ uniform float volumeStepFactor = 1.0f; int build_local_fragments_list() { + +#if ABUFFER_IMPLEMENTATION == ABUFFER_SINGLE_LINKED uint current; int frag_count = 0; @@ -42,6 +44,19 @@ int build_local_fragments_list() { } return frag_count; +#endif + +#if ABUFFER_IMPLEMENTATION == ABUFFER_FIXED + uint frag_count = imageLoad(anchorPointerTexture, ivec2(gl_FragCoord.xy)).x; + + int i; + for(i = 0; i < frag_count && i < MAX_FRAGMENTS; ++i) { + fragments[i] = loadFromBuffer(i); + } + + return int(frag_count); +#endif + } float pscLength(vec4 v1, vec4 v2) { @@ -75,12 +90,13 @@ void sort_fragments_list(uint frag_count) { fragments[j] = tmp; } +#if MAX_VOLUMES > 0 int ii, jj; for(ii = 0; ii < MAX_VOLUMES; ++ii) { bool start = true; vec3 startColor; vec4 startPosition; - for(jj = ii; jj < frag_count; ++jj) { + for(jj = 0; jj < frag_count; ++jj) { int type = int(_type_(fragments[jj])) - 1; if(type== ii) { if(start) { @@ -96,12 +112,13 @@ void sort_fragments_list(uint frag_count) { volume_length[ii] = length(dir); volume_direction[ii] = normalize(dir); volumeStepSize[ii] = 1.0/(volumeStepFactor * length(volume_direction[ii]*volume_dim[ii])); + volumeStepSizeOriginal[ii] = volumeStepSize[ii]; #if ZTYPE == ZDEPTH volume_zlength[ii].y = _z_(fragments[jj]); #elif ZTYPE == PSCDEPTH volume_zlength[ii] = pscLength(_pos_(fragments[jj]), startPosition); #endif - +#ifdef JITTERING if(volumeStepSize[ii] < volume_length[ii]) { // jittering float x = gl_FragCoord.x; @@ -110,12 +127,14 @@ void sort_fragments_list(uint frag_count) { vec3 frontPosNew = startColor + (jitterValue*volumeStepSize[ii])*volume_direction[ii]; volume_position[ii] = frontPosNew; } +#endif break; } } } } +#endif //volume_direction[0] = vec3(1.0,0.0,0.0); //volume_direction[0] = _col_(fragments[0]).rgb; } diff --git a/shaders/ABuffer/abufferStruct.hglsl b/shaders/ABuffer/abufferStruct.hglsl index a63499ef6d..0153aecad6 100644 --- a/shaders/ABuffer/abufferStruct.hglsl +++ b/shaders/ABuffer/abufferStruct.hglsl @@ -25,10 +25,17 @@ #ifndef ABUFFERSTRUCT_H_HGLSL #define ABUFFERSTRUCT_H_HGLSL +// The different kinds of implementation +#define ABUFFER_SINGLE_LINKED 1 +#define ABUFFER_FIXED 2 +#define ABUFFER_DYNAMIC 3 -//======================================================= +#define ABUFFER_IMPLEMENTATION ABUFFER_SINGLE_LINKED + + +//======================================================================================== // ABufferStruct_t declaration -//======================================================= +//======================================================================================== // struct ABufferStruct_t { // uint z; // the depth value // uint id; // bits 0-28 next, bits 29-32 type @@ -46,9 +53,9 @@ struct ABufferStruct_t { }; -//======================================================= +//======================================================================================== // Bitwise operations -//======================================================= +//======================================================================================== const uint mask_1 = 1; const uint mask_8 = 255; const uint mask_16 = 65535; @@ -92,9 +99,9 @@ int bitextract_i(in int pack, uint mask, uint shift) { return int( (uint(pack) >> shift) & (mask >> shift) ); } -//======================================================= +//======================================================================================== // Access functions -//======================================================= +//======================================================================================== float _z_(ABufferStruct_t frag) { return uintBitsToFloat(frag.z); } @@ -102,15 +109,6 @@ void _z_(inout ABufferStruct_t frag, float z) { frag.z = floatBitsToUint(z); } -uint _next_(ABufferStruct_t frag) { - return bitextract_u(frag.id, mask_id_next, shift_id_next); - //return frag.id; -} -void _next_(inout ABufferStruct_t frag, uint id) { - bitinsert_u(frag.id, id, mask_id_next, shift_id_next); - //frag.id = id; -} - vec4 _pos_(ABufferStruct_t frag) { // return vec4(0.0,0.0,0.0,0.0); return frag.position; @@ -132,12 +130,34 @@ void _col_(inout ABufferStruct_t frag, vec4 color) { } uint _type_(ABufferStruct_t frag) { - return bitextract_u(frag.id, mask_id_type, shift_id_type); - //return frag.type; +#if ABUFFER_IMPLEMENTATION == ABUFFER_SINGLE_LINKED + return bitextract_u(frag.id, mask_id_type, shift_id_type); +#else + return frag.id; +#endif } void _type_(inout ABufferStruct_t frag, uint type) { +#if ABUFFER_IMPLEMENTATION == ABUFFER_SINGLE_LINKED bitinsert_u(frag.id, type, mask_id_type, shift_id_type); - //frag.type = type; +#else + frag.id = type; +#endif } +//======================================================================================== +// Implementation specific functions +//======================================================================================== + +// _next_ is only needed for the single linked implementation +#if ABUFFER_IMPLEMENTATION == ABUFFER_SINGLE_LINKED +uint _next_(ABufferStruct_t frag) { + return bitextract_u(frag.id, mask_id_next, shift_id_next); + //return frag.id; +} +void _next_(inout ABufferStruct_t frag, uint id) { + bitinsert_u(frag.id, id, mask_id_next, shift_id_next); + //frag.id = id; +} +#endif + #endif \ No newline at end of file diff --git a/shaders/exitpoints.frag b/shaders/exitpoints.frag index 89fe78224b..71dac97245 100644 --- a/shaders/exitpoints.frag +++ b/shaders/exitpoints.frag @@ -35,10 +35,12 @@ in float s; #include "PowerScaling/powerScaling_fs.hglsl" void main() { - vec4 fragColor = vec4(vPosition+0.5, 0.3); + vec4 fragColor = vec4(vPosition+0.5, 1.0); vec4 position = vec4(worldPosition,s); float depth = pscDepth(position); + gl_FragDepth = depth; + ABufferStruct_t frag; _col_(frag, fragColor); _z_(frag, depth); diff --git a/src/abuffer/abuffer.cpp b/src/abuffer/abuffer.cpp index f8f8063726..744e27a402 100644 --- a/src/abuffer/abuffer.cpp +++ b/src/abuffer/abuffer.cpp @@ -91,9 +91,7 @@ bool ABuffer::initializeABuffer() { addFunc("${SHADERS}/ABuffer/abufferAddToBuffer.hglsl"); addFunc("${SHADERS}/ABuffer/abufferStruct.hglsl"); addFunc("${SHADERS}/PowerScaling/powerScaling_fs.hglsl"); - addFunc("${SHADERS}/PowerScaling/powerScaling_vs.hglsl"); - - + addFunc("${SHADERS}/PowerScaling/powerScaling_vs.hglsl"); _resolveShader = nullptr; generateShaderSource(); @@ -148,10 +146,10 @@ void ABuffer::resolve() { // Decrease stepsize in volumes if right click is pressed // TODO: Let the interactionhandler handle this int val = sgct::Engine::getMouseButton(0, SGCT_MOUSE_BUTTON_RIGHT); - if(val) { - _resolveShader->setUniform("volumeStepFactor", 0.2f); - } else { - _resolveShader->setUniform("volumeStepFactor", 1.0f); + float volumeStepFactor = (val) ? 0.2: 1.0; + if(volumeStepFactor != _volumeStepFactor) { + _volumeStepFactor = volumeStepFactor; + _resolveShader->setUniform("volumeStepFactor", _volumeStepFactor); } glBindVertexArray(_screenQuad); @@ -254,6 +252,8 @@ void ABuffer::generateShaderSource() { line = padGeneratedString(openspaceSamplers()); } else if(line == "#pragma openspace insert SETTINGS") { line = padGeneratedString(settings()); + } else if(line == "#pragma openspace insert TRANSFERFUNC") { + line = padGeneratedString(openspaceTransferFunction()); } source += line + "\n"; } @@ -270,6 +270,8 @@ std::string ABuffer::openspaceHeaders() { std::string headers; headers += "#define MAX_VOLUMES " + std::to_string(_samplers.size()) + "\n"; headers += "#define MAX_TF " + std::to_string(_transferFunctions.size()) + "\n"; + + for (int i = 0; i < _volumes.size(); ++i) { headers += "uniform sampler3D " + _volumes.at(i).first + ";\n"; } @@ -284,6 +286,9 @@ std::string ABuffer::openspaceHeaders() { } } + if(_volumes.size() < 1) + return headers; + size_t maxLoop = 0; headers += "const vec3 volume_dim[] = {\n"; for (int i = 0; i < _volumes.size(); ++i) { @@ -294,6 +299,7 @@ std::string ABuffer::openspaceHeaders() { + std::to_string(size[2]) + ".0),\n"; } headers += "};\n"; + headers += "#define LOOP_LIMIT " + std::to_string(maxLoop) + "\n"; headers += "float volumeStepSize[] = {\n"; @@ -303,6 +309,13 @@ std::string ABuffer::openspaceHeaders() { } headers += "};\n"; + headers += "float volumeStepSizeOriginal[] = {\n"; + for (int i = 0; i < _volumes.size(); ++i) { + glm::size3_t size = _volumes.at(i).second->dimensions(); + headers += " stepSize,\n"; + } + headers += "};\n"; + return headers; } @@ -310,13 +323,23 @@ std::string ABuffer::openspaceSamplerCalls() { std::string samplercalls; for (int i = 0; i < _samplers.size(); ++i) { - auto found1 = _samplers.at(i).find_first_not_of("void "); + auto found1 = _samplers.at(i).find_first_not_of("vec4 "); auto found2 = _samplers.at(i).find_first_of("(",found1); if(found1 != std::string::npos && found2 != std::string::npos) { std::string functionName = _samplers.at(i).substr(found1, found2 - found1); - samplercalls += "if((currentVolumeBitmask & (1 << " + std::to_string(i) + ")) == 1) {\n"; - samplercalls += functionName + "(final_color,volume_position[" + std::to_string(i) + "]);\n"; - samplercalls += "volume_position[" + std::to_string(i) + "] += volume_direction[" + std::to_string(i) + "]*volumeStepSize[" + std::to_string(i) + "];;\n"; + samplercalls += "if((currentVolumeBitmask & (1 << " + std::to_string(i) + ")) == "+std::to_string(i+1)+") {\n"; + samplercalls += " vec4 c = " + functionName + "(final_color,volume_position[" + std::to_string(i) + "]);\n"; + // samplercalls += " if(c.a < 0.1) { \n"; + // samplercalls += " if( volumeStepSize[" + std::to_string(i) + "] < 16.0*volumeStepSizeOriginal[" + std::to_string(i) + "]) \n"; + // samplercalls += " volumeStepSize[" + std::to_string(i) + "] *= 2.0; \n"; + // samplercalls += " } else {\n"; + // samplercalls += " //volume_position[" + std::to_string(i) + "] -= volume_direction[" + std::to_string(i) + "]*volumeStepSize[" + std::to_string(i) + "];\n"; + // samplercalls += " volumeStepSize[" + std::to_string(i) + "] = volumeStepSizeOriginal[" + std::to_string(i) + "]; \n"; + // samplercalls += " //c = " + functionName + "(final_color,volume_position[" + std::to_string(i) + "]);\n"; + // samplercalls += " } \n"; + samplercalls += " blendStep(final_color, c, volumeStepSize[" + std::to_string(i) + "]);\n"; + // samplercalls += " blendStep(final_color, c, stepSize);\n"; + samplercalls += " volume_position[" + std::to_string(i) + "] += volume_direction[" + std::to_string(i) + "]*volumeStepSize[" + std::to_string(i) + "];\n"; samplercalls += "}\n"; } @@ -333,5 +356,31 @@ std::string ABuffer::openspaceSamplers() { return samplers; } +std::string ABuffer::openspaceTransferFunction() { + std::string tf; + tf += "float showfunc_size = 20.0;\n"; + tf += "float SCREEN_HEIGHTf = float(SCREEN_HEIGHT);\n"; + tf += "float SCREEN_WIDTHf = float(SCREEN_WIDTH);\n"; + for(int i = 0; i < _transferFunctions.size(); ++i) { + tf += "if( gl_FragCoord.y > SCREEN_HEIGHTf-showfunc_size*"+std::to_string(i+1)+ + " && gl_FragCoord.y < SCREEN_HEIGHTf-showfunc_size*"+std::to_string(i)+") {\n"; + tf += " float normalizedIntensity = gl_FragCoord.x / SCREEN_WIDTHf ;\n"; + tf += " vec4 tfc = texture("+ _transferFunctions.at(i).first +", normalizedIntensity);\n"; + tf += " final_color = tfc;\n"; + tf += " float cmpf = SCREEN_HEIGHTf-showfunc_size*"+std::to_string(i+1)+" + tfc.a*showfunc_size;\n"; + tf += " if(gl_FragCoord.y > cmpf) {\n"; + tf += " final_color = vec4(0,0,0,0);\n"; + tf += " } else {\n"; + tf += " final_color.a = 1.0;\n"; + tf += " }\n"; + tf += "} else if(ceil(gl_FragCoord.y) == SCREEN_HEIGHTf - showfunc_size*"+std::to_string(i+1)+") {\n"; + tf += " const float intensity = 0.4;\n"; + tf += " final_color = vec4(intensity,intensity,intensity,1.0);\n"; + tf += "}\n"; + } + + return tf; +} + } // openspace \ No newline at end of file diff --git a/src/abuffer/abufferSingleLinked.cpp b/src/abuffer/abufferSingleLinked.cpp index 166ded0302..f1a09b3c2d 100644 --- a/src/abuffer/abufferSingleLinked.cpp +++ b/src/abuffer/abufferSingleLinked.cpp @@ -117,7 +117,7 @@ void ABufferSingleLinked::postRender() { } std::string ABufferSingleLinked::settings() { - return R"(#define SINGLE_LINKED)"; + return R"()"; } diff --git a/src/abuffer/abufferdynamic.cpp b/src/abuffer/abufferdynamic.cpp new file mode 100644 index 0000000000..8943905eda --- /dev/null +++ b/src/abuffer/abufferdynamic.cpp @@ -0,0 +1,124 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include +#include + +#include +#include + +#include +#include +#include + +#define MAX_LAYERS 10 + +namespace { + std::string _loggerCat = "ABufferDynamic"; +} + +namespace openspace { + +ABufferDynamic::ABufferDynamic(): _data(0), _anchorPointerTexture(0), + _anchorPointerTextureInitializer(0), _atomicCounterBuffer(0), _fragmentBuffer(0), + _fragmentTexture(0) +{} + +ABufferDynamic::~ABufferDynamic() { + if(_data != 0) + delete _data; + + glDeleteTextures(1,&_anchorPointerTexture); + glDeleteTextures(1,&_fragmentTexture); + glDeleteBuffers(1,&_anchorPointerTextureInitializer); + glDeleteBuffers(1,&_atomicCounterBuffer); + glDeleteBuffers(1,&_anchorPointerTextureInitializer); +} + +bool ABufferDynamic::initialize() { + // ============================ + // BUFFERS + // ============================ + glGenTextures(1, &_anchorPointerTexture); + glBindTexture(GL_TEXTURE_2D, _anchorPointerTexture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, _width, _height, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, NULL); + + glGenBuffers(1, &_anchorPointerTextureInitializer); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, _anchorPointerTextureInitializer); + glBufferData(GL_PIXEL_UNPACK_BUFFER, _totalPixels * sizeof(GLuint), NULL, GL_STATIC_DRAW); + + _data = (GLuint*)glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY); + memset(_data, 0x00, _totalPixels * sizeof(GLuint)); + glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + + glGenBuffers(1, &_atomicCounterBuffer); + glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, _atomicCounterBuffer); + glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(GLuint), NULL, GL_DYNAMIC_COPY); + + glGenBuffers(1, &_fragmentBuffer); + glBindBuffer(GL_TEXTURE_BUFFER, _fragmentBuffer); + glBufferData(GL_TEXTURE_BUFFER, MAX_LAYERS*_totalPixels*sizeof(GLfloat)*4, NULL, GL_DYNAMIC_COPY); + + glGenTextures(1, &_fragmentTexture); + glBindTexture(GL_TEXTURE_BUFFER, _fragmentTexture); + glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32UI, _fragmentBuffer); + glBindTexture(GL_TEXTURE_BUFFER, 0); + + glBindImageTexture(1, _fragmentTexture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32UI); + + return initializeABuffer(); +} + +void ABufferDynamic::clear() { + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, _anchorPointerTextureInitializer); + glBindTexture(GL_TEXTURE_2D, _anchorPointerTexture); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, _width, _height, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, NULL); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + + static const GLuint zero = 1; + glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, _atomicCounterBuffer); + glBufferSubData(GL_ATOMIC_COUNTER_BUFFER, 0, sizeof(zero), &zero); + glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, 0); +} + +void ABufferDynamic::preRender() { + + // Bind head-pointer image for read-write + glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, _atomicCounterBuffer); + glBindImageTexture(0, _anchorPointerTexture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI); + glBindImageTexture(1, _fragmentTexture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32UI); +} + +void ABufferDynamic::postRender() { + +} + +std::string ABufferDynamic::settings() { + return R"(#define ABUFFER_SINGLE_LINKED)"; +} + + +} // openspace \ No newline at end of file diff --git a/src/abuffer/abufferfixed.cpp b/src/abuffer/abufferfixed.cpp new file mode 100644 index 0000000000..36c5a7aeae --- /dev/null +++ b/src/abuffer/abufferfixed.cpp @@ -0,0 +1,137 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include +#include + +#include +#include + +#include +#include +#include + +#define MAX_LAYERS 32 + +namespace { + std::string _loggerCat = "ABufferFixed"; +} + +namespace openspace { + +ABufferFixed::ABufferFixed(): _data(0), _anchorPointerTexture(0), + _anchorPointerTextureInitializer(0), _atomicCounterBuffer(0), _fragmentBuffer(0), + _fragmentTexture(0) +{} + +ABufferFixed::~ABufferFixed() { + if(_data != 0) + delete _data; + + glDeleteTextures(1,&_anchorPointerTexture); + glDeleteTextures(1,&_fragmentTexture); + // glDeleteTextures(1,&_atomicCounterTexture); + glDeleteBuffers(1,&_anchorPointerTextureInitializer); + // glDeleteBuffers(1,&_atomicCounterBuffer); + glDeleteBuffers(1,&_anchorPointerTextureInitializer); +} + +bool ABufferFixed::initialize() { + // ============================ + // BUFFERS + // ============================ + glGenTextures(1, &_anchorPointerTexture); + glBindTexture(GL_TEXTURE_2D, _anchorPointerTexture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, _width, _height, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, NULL); + + glGenBuffers(1, &_anchorPointerTextureInitializer); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, _anchorPointerTextureInitializer); + glBufferData(GL_PIXEL_UNPACK_BUFFER, _totalPixels * sizeof(GLuint), NULL, GL_STATIC_DRAW); + + _data = (GLuint*)glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY); + memset(_data, 0x00, _totalPixels * sizeof(GLuint)); + glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + + + // glGenBuffers(1, &_atomicCounterBuffer); + // glBindBuffer(GL_TEXTURE_BUFFER, _atomicCounterBuffer); + // glBufferData(GL_TEXTURE_BUFFER, _totalPixels*sizeof(GLuint), NULL, GL_DYNAMIC_COPY); + + // glGenTextures(1, &_atomicCounterTexture); + // glBindTexture(GL_TEXTURE_2D, _atomicCounterTexture); + // glTexBuffer(GL_TEXTURE_BUFFER, GL_R32UI, _atomicCounterBuffer); + // glBindTexture(GL_TEXTURE_BUFFER, 0); + + + glGenBuffers(1, &_fragmentBuffer); + glBindBuffer(GL_TEXTURE_BUFFER, _fragmentBuffer); + glBufferData(GL_TEXTURE_BUFFER, MAX_LAYERS*_totalPixels*sizeof(GLfloat)*4, NULL, GL_DYNAMIC_COPY); + + glGenTextures(1, &_fragmentTexture); + glBindTexture(GL_TEXTURE_BUFFER, _fragmentTexture); + glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32UI, _fragmentBuffer); + glBindTexture(GL_TEXTURE_BUFFER, 0); + + glBindImageTexture(1, _fragmentTexture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32UI); + + return initializeABuffer(); +} + +void ABufferFixed::clear() { + + // Bind texture initializer + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, _anchorPointerTextureInitializer); + + // clear _anchorPointerTexture + glBindTexture(GL_TEXTURE_2D, _anchorPointerTexture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, _width, _height, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, NULL); + + // // clear _atomicCounterTexture + // glBindTexture(GL_TEXTURE_2D, _atomicCounterTexture); + // glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, _width, _height, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, NULL); + + // reset GL_PIXEL_UNPACK_BUFFER + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + +} + +void ABufferFixed::preRender() { + + // Bind head-pointer image for read-write + glBindImageTexture(0, _anchorPointerTexture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI); + glBindImageTexture(1, _fragmentTexture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32UI); + // glBindImageTexture(2, _atomicCounterTexture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI); +} + +void ABufferFixed::postRender() { + +} + +std::string ABufferFixed::settings() { + return R"()"; +} + + +} // openspace \ No newline at end of file diff --git a/src/rendering/renderablevolumegl.cpp b/src/rendering/renderablevolumegl.cpp index bdcdc9ae79..ddbf548138 100644 --- a/src/rendering/renderablevolumegl.cpp +++ b/src/rendering/renderablevolumegl.cpp @@ -97,6 +97,13 @@ RenderableVolumeGL::RenderableVolumeGL(const ghoul::Dictionary& dictionary): _boxScaling[2] = tempValue; } + _volumeName = ""; + if (dictionary.hasKey("VolumeName")) + dictionary.getValue("VolumeName", _volumeName); + _transferFunctionName = ""; + if (dictionary.hasKey("TransferFunctionName")) + dictionary.getValue("TransferFunctionName", _transferFunctionName); + setBoundingSphere(PowerScaledScalar::CreatePSS(glm::length(_boxScaling))); } @@ -121,8 +128,8 @@ bool RenderableVolumeGL::initialize() { _transferFunction->uploadTexture(); // TODO: fix volume an transferfunction names - OsEng.renderEngine().abuffer()->addVolume("volume1", _volume); - OsEng.renderEngine().abuffer()->addTransferFunction("transferFunction1", _transferFunction); + OsEng.renderEngine().abuffer()->addVolume(_volumeName, _volume); + OsEng.renderEngine().abuffer()->addTransferFunction(_transferFunctionName, _transferFunction); _id = OsEng.renderEngine().abuffer()->addSamplerfile(_samplerFilename); auto textureCallback = [this](const ghoul::filesystem::File& file) { @@ -235,8 +242,8 @@ void RenderableVolumeGL::render(const Camera *camera, const psc &thisPosition) { glm::mat4 camrot = camera->viewRotationMatrix(); PowerScaledScalar scaling = camera->scaling(); - psc addon(-1.1,0.0,0.0,0.0); - currentPosition += addon; + // psc addon(-1.1,0.0,0.0,0.0); + // currentPosition += addon; // TODO: Use _id to identify this volume _boxProgram->activate(); diff --git a/src/rendering/renderengine.cpp b/src/rendering/renderengine.cpp index 70fd59661d..4e1123d11c 100644 --- a/src/rendering/renderengine.cpp +++ b/src/rendering/renderengine.cpp @@ -35,6 +35,8 @@ #include #include +#include +#include namespace { const std::string _loggerCat = "RenderEngine"; @@ -66,6 +68,8 @@ bool RenderEngine::initialize() OsEng.interactionHandler().setCamera(_mainCamera); _abuffer = new ABufferSingleLinked(); + // _abuffer = new ABufferFixed(); + // _abuffer = new ABufferDynamic(); return true; } @@ -82,7 +86,7 @@ bool RenderEngine::initializeGL() // set the close clip plane and the far clip plane to extreme values while in // development // sgct::Engine::instance()->setNearAndFarClippingPlanes(0.1f,100.0f); - sgct::Engine::instance()->setNearAndFarClippingPlanes(0.00001f, 100.0f); + sgct::Engine::instance()->setNearAndFarClippingPlanes(0.1f, 200.0f); // calculating the maximum field of view for the camera, used to // determine visibility of objects in the scene graph diff --git a/src/scenegraph/scenegraph.cpp b/src/scenegraph/scenegraph.cpp index 75434d2a54..be80e87ac9 100644 --- a/src/scenegraph/scenegraph.cpp +++ b/src/scenegraph/scenegraph.cpp @@ -82,77 +82,63 @@ bool SceneGraph::initialize() using ghoul::opengl::ShaderObject; using ghoul::opengl::ProgramObject; - // pscstandard + auto programCreator = [] ( const std::string& name, + const std::string& vpath, + const std::string& fpath) { - std::string programObjectName = "pscstandard"; - ProgramObject* po = new ProgramObject(programObjectName); - ShaderObject* vs = new ShaderObject( ShaderObject::ShaderType::ShaderTypeVertex, - absPath("${SHADERS}/pscstandard_vs.glsl"), - programObjectName + "Vertex"); - ShaderObject* fs = new ShaderObject( ShaderObject::ShaderType::ShaderTypeFragment, - absPath("${SHADERS}/pscstandard_fs.glsl"), - programObjectName + "Fragment"); + const std::string vsPath = absPath(vpath); + const std::string fsPath = absPath(fpath); + const ShaderObject::ShaderType vsType = ShaderObject::ShaderType::ShaderTypeVertex; + const ShaderObject::ShaderType fsType = ShaderObject::ShaderType::ShaderTypeFragment; + + ProgramObject* po = new ProgramObject(name); + ShaderObject* vs = new ShaderObject(vsType, vsPath, name + "Vertex"); + ShaderObject* fs = new ShaderObject(fsType, fsPath, name + "Fragment"); po->attachObject(vs); po->attachObject(fs); - if ( ! po->compileShaderObjects()) return false; - if ( ! po->linkProgramObject()) return false; - OsEng.ref().configurationManager().setValue("pscShader", po); - } + if ( po->compileShaderObjects() && po->linkProgramObject()) + return po; + + // unsuccessful compilation, cleanup and return nullptr + delete po; + po = nullptr; + return po; + }; + + ProgramObject* tmpProgram; + + // pscstandard + tmpProgram = programCreator("pscstandard", + "${SHADERS}/pscstandard_vs.glsl", + "${SHADERS}/pscstandard_fs.glsl"); + if( ! tmpProgram) return false; + OsEng.ref().configurationManager().setValue("pscShader", tmpProgram); // RaycastProgram - { - std::string programObjectName = "RaycastProgram"; - ProgramObject* po = new ProgramObject(programObjectName); - ShaderObject* vs = new ShaderObject( ShaderObject::ShaderType::ShaderTypeVertex, - absPath("${SHADERS}/exitpoints.vert"), - programObjectName + "Vertex"); - ShaderObject* fs = new ShaderObject( ShaderObject::ShaderType::ShaderTypeFragment, - absPath("${SHADERS}/exitpoints.frag"), - programObjectName + "Fragment"); - po->attachObject(vs); - po->attachObject(fs); - if ( ! po->compileShaderObjects()) return false; - if ( ! po->linkProgramObject()) return false; - OsEng.ref().configurationManager().setValue("RaycastProgram", po); - } + tmpProgram = programCreator("RaycastProgram", + "${SHADERS}/exitpoints.vert", + "${SHADERS}/exitpoints.frag"); + if( ! tmpProgram) return false; + OsEng.ref().configurationManager().setValue("RaycastProgram", tmpProgram); + // TwoPassProgram - { - std::string programObjectName = "TwoPassProgram"; - ProgramObject* po = new ProgramObject(programObjectName); - ShaderObject* vs = new ShaderObject( ShaderObject::ShaderType::ShaderTypeVertex, - absPath("${SHADERS}/twopassraycaster.vert"), - programObjectName + "Vertex"); - ShaderObject* fs = new ShaderObject( ShaderObject::ShaderType::ShaderTypeFragment, - absPath("${SHADERS}/twopassraycaster.frag"), - programObjectName + "Fragment"); - po->attachObject(vs); - po->attachObject(fs); - if ( ! po->compileShaderObjects()) return false; - if ( ! po->linkProgramObject()) return false; - po->setUniform("texBack", 0); - po->setUniform("texFront", 1); - po->setUniform("texVolume", 2); - OsEng.ref().configurationManager().setValue("TwoPassProgram", po); - } + tmpProgram = programCreator("TwoPassProgram", + "${SHADERS}/twopassraycaster.vert", + "${SHADERS}/twopassraycaster.frag"); + if( ! tmpProgram) return false; + tmpProgram->setUniform("texBack", 0); + tmpProgram->setUniform("texFront", 1); + tmpProgram->setUniform("texVolume", 2); + OsEng.ref().configurationManager().setValue("TwoPassProgram", tmpProgram); // Quad - { - std::string programObjectName = "Quad"; - ProgramObject* po = new ProgramObject(programObjectName); - ShaderObject* vs = new ShaderObject( ShaderObject::ShaderType::ShaderTypeVertex, - absPath("${SHADERS}/quadVert.glsl"), - programObjectName + "Vertex"); - ShaderObject* fs = new ShaderObject( ShaderObject::ShaderType::ShaderTypeFragment, - absPath("${SHADERS}/quadFrag.glsl"), - programObjectName + "Fragment"); - po->attachObject(vs); - po->attachObject(fs); - if ( ! po->compileShaderObjects()) return false; - if ( ! po->linkProgramObject()) return false; - po->setUniform("quadTex", 0); - OsEng.ref().configurationManager().setValue("Quad", po); - } + tmpProgram = programCreator("Quad", + "${SHADERS}/quadVert.glsl", + "${SHADERS}/quadFrag.glsl"); + if( ! tmpProgram) return false; + tmpProgram->setUniform("quadTex", 0); + OsEng.ref().configurationManager().setValue("Quad", tmpProgram); // Initialize all nodes for (auto node : _nodes) { diff --git a/src/scenegraph/scenegraphnode.cpp b/src/scenegraph/scenegraphnode.cpp index b0e5f25616..146f922a87 100644 --- a/src/scenegraph/scenegraphnode.cpp +++ b/src/scenegraph/scenegraphnode.cpp @@ -193,8 +193,9 @@ void SceneGraphNode::evaluate(const Camera* camera, const psc& parentPosition) // this node has an renderable if (_renderable) { // check if the renderable boundingsphere is visible - _renderableVisible = sphereInsideFrustum( - thisPosition, _renderable->getBoundingSphere(), camera); + // _renderableVisible = sphereInsideFrustum( + // thisPosition, _renderable->getBoundingSphere(), camera); + _renderableVisible = true; } // evaluate all the children, tail-recursive function(?) diff --git a/src/util/kameleonwrapper.cpp b/src/util/kameleonwrapper.cpp index 1fa2b423f6..f9157f681f 100644 --- a/src/util/kameleonwrapper.cpp +++ b/src/util/kameleonwrapper.cpp @@ -126,11 +126,9 @@ float* KameleonWrapper::getUniformSampledValues(const std::string& var, glm::siz // get interpolated data value for (xPos, yPos, zPos) // swap yPos and zPos because model has Z as up double value = _interpolator->interpolate(var, xPos, zPos, yPos); - - // scale to [0,1] - //doubleData[index] = (value-varMin)/(varMax-varMin); doubleData[index] = value; histogram[mapToHistogram(value)]++; + } else if (_type == Model::ENLIL) { // Put r in the [0..sqrt(3)] range @@ -150,7 +148,7 @@ float* KameleonWrapper::getUniformSampledValues(const std::string& var, glm::siz // avoid rounding errors when comparing to phiMax. double phiPh = _zMin + phiNorm/(2.0*M_PI)*(_zMax-_zMin-0.000001); - double varValue = 0.f; + double value = 0.0; // See if sample point is inside domain if (rPh < _xMin || rPh > _xMax || thetaPh < _yMin || thetaPh > _yMax || phiPh < _zMin || phiPh > _zMax) { @@ -168,10 +166,12 @@ float* KameleonWrapper::getUniformSampledValues(const std::string& var, glm::siz // Convert from [0, 2pi] rad to [0, 360] degrees phiPh = phiPh*180.f/M_PI; // Sample - varValue = _interpolator->interpolate(var, rPh, thetaPh, phiPh); + value = _interpolator->interpolate(var, rPh, thetaPh, phiPh); + // value = _interpolator->interpolate(var, rPh, phiPh, thetaPh); } - doubleData[index] = (varValue-varMin)/(varMax-varMin); + doubleData[index] = value; + histogram[mapToHistogram(value)]++; } } } @@ -179,17 +179,34 @@ float* KameleonWrapper::getUniformSampledValues(const std::string& var, glm::siz std::cout << std::endl; LINFO("Done!"); + // for (int i = 0; i < outDimensions.x * outDimensions.y * outDimensions.z; ++i) + // { + // std::cout << std::setfill(' ') << std::setw(15) << doubleData[i] << ", "; + // if(i % 10 == 0) + // std::cout << std::endl; + // } + // + // for(int i = 0; i < bins-1; ++i) { + // // sum += histogram[i]; + // // if(sum + histogram[i+1] > sumuntil) { + // // stop = i; + // // LDEBUG("===================="); + // // break; + // // } + // LDEBUG("histogram[" << i << "]: " << histogram[i]); + // } + int sum = 0; int stop; const int sumuntil = size * truncLim; - for(int i = 0; i < bins-1; ++i) { + for(int i = 0; i < bins; ++i) { sum += histogram[i]; - if(sum + histogram[i+1] > sumuntil) { + if(sum > sumuntil) { stop = i; - LDEBUG("===================="); + // LDEBUG("===================="); break; } - LDEBUG(histogram[i]); + // LDEBUG("histogram[" << i << "]: " << histogram[i]); } double dist = varMax - varMin; @@ -201,8 +218,14 @@ float* KameleonWrapper::getUniformSampledValues(const std::string& var, glm::siz data[i] = static_cast(glm::clamp(normalizedVal, 0.0, 1.0)); } - delete[] doubleData; + // for(int i = 0; i < size; ++i) { + // double normalizedVal = (doubleData[i]-varMin)/(varMax-varMin); + // // data[i] = static_cast(glm::clamp(normalizedVal, 0.0, 1.0)); + // data[i] = static_cast(normalizedVal); + // } + + delete[] doubleData; return data; } From 114af3fb5b12d5f6f87a8a8fcdbdcc7340df9a1a Mon Sep 17 00:00:00 2001 From: Jonas Strandstedt Date: Thu, 10 Jul 2014 15:22:57 -0400 Subject: [PATCH 40/49] Added an OpenSpace ShaderCreator - Global shader settings can now be added. - ShaderCreator builds the shader and stores a generated shader file with all included source. - Small TransferFunction bugfix --- .gitignore | 1 + ext/ghoul | 2 +- include/openspace/engine/openspaceengine.h | 10 +- include/openspace/util/shadercreator.h | 60 +++++++ shaders/ABuffer/abufferResolveFragment.glsl | 18 +- shaders/ABuffer/abufferStruct.hglsl | 11 +- src/abuffer/abuffer.cpp | 27 +-- src/engine/openspaceengine.cpp | 19 +++ src/rendering/renderablefieldlines.cpp | 8 +- src/rendering/renderablevolume.cpp | 8 +- src/rendering/renderengine.cpp | 9 +- src/scenegraph/scenegraph.cpp | 57 ++++++- src/util/shadercreator.cpp | 180 ++++++++++++++++++++ 13 files changed, 355 insertions(+), 55 deletions(-) create mode 100644 include/openspace/util/shadercreator.h create mode 100644 src/util/shadercreator.cpp diff --git a/.gitignore b/.gitignore index b86c3ed18d..eb0db62a4f 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ ext/SGCT # generated glsl files *.gglsl +*.OpenSpaceGenerated.glsl # CMake stuff CMakeCache.txt diff --git a/ext/ghoul b/ext/ghoul index a616a2ce84..9199e2da7a 160000 --- a/ext/ghoul +++ b/ext/ghoul @@ -1 +1 @@ -Subproject commit a616a2ce84ec0fd9d6573ef6690707ef4a841669 +Subproject commit 9199e2da7a2df7e4fe50437ba8a775f3178d8612 diff --git a/include/openspace/engine/openspaceengine.h b/include/openspace/engine/openspaceengine.h index 66fdd720f3..3e1759955d 100644 --- a/include/openspace/engine/openspaceengine.h +++ b/include/openspace/engine/openspaceengine.h @@ -34,9 +34,15 @@ #include #include -//#define FLARE_ONLY +// #define FLARE_ONLY #include +#include + +#define ABUFFER_SINGLE_LINKED 1 +#define ABUFFER_FIXED 2 +#define ABUFFER_DYNAMIC 3 +#define ABUFFER_IMPLEMENTATION ABUFFER_SINGLE_LINKED namespace openspace { @@ -59,6 +65,7 @@ public: ghoul::opencl::CLContext& clContext(); InteractionHandler& interactionHandler(); RenderEngine& renderEngine(); + ShaderCreator& shaderBuilder(); // SGCT callbacks bool initializeGL(); @@ -90,6 +97,7 @@ private: ghoul::opencl::CLContext _context; sgct::SharedVector _synchronizationBuffer; + ShaderCreator _shaderBuilder; }; #define OsEng (openspace::OpenSpaceEngine::ref()) diff --git a/include/openspace/util/shadercreator.h b/include/openspace/util/shadercreator.h new file mode 100644 index 0000000000..9274d60715 --- /dev/null +++ b/include/openspace/util/shadercreator.h @@ -0,0 +1,60 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __SHADERCREATOR_H__ +#define __SHADERCREATOR_H__ + + +#include + +#include + +namespace openspace { +class ShaderCreator { + +public: + ShaderCreator(); + ~ShaderCreator(); + + void createSourceFile(bool b); + void sourceFileExtension(const std::string& extension); + void sourceFileHeader(const std::string& header); + + ghoul::opengl::ProgramObject* buildShader(const std::string& name, const std::string& vpath, const std::string& fpath); + +private: + + void _generateSource(const std::string& filename); + std::string _loadSource(const std::string& filename, unsigned int depth = 0); + std::string _generateFilename(const std::string& filename); + + bool _createSourceFile; + std::string _sourceFileExtension; + std::string _sourceFileHeader; + unsigned int _maxDepth; + +}; +} + +#endif \ No newline at end of file diff --git a/shaders/ABuffer/abufferResolveFragment.glsl b/shaders/ABuffer/abufferResolveFragment.glsl index b230a51e23..75b1a615be 100644 --- a/shaders/ABuffer/abufferResolveFragment.glsl +++ b/shaders/ABuffer/abufferResolveFragment.glsl @@ -35,7 +35,7 @@ #define PSCDEPTH 1 #define ZDEPTH 2 -#define ZTYPE ZDEPTH +#define ZTYPE PSCDEPTH // Math defintions #define M_E 2.7182818284590452354 @@ -56,8 +56,8 @@ const float stepSize = 0.01; const float samplingRate = 1.0; -uniform int SCREEN_WIDTH; -uniform int SCREEN_HEIGHT; +// uniform int SCREEN_WIDTH; +// uniform int SCREEN_HEIGHT; uniform float ALPHA_LIMIT = 0.95; in vec2 texCoord; @@ -146,13 +146,12 @@ float globz(float z) { // return log(2.0*z-1.0); // return exp(2.0*z-1.0); // const float zNear = 0.1f; - // const float zFar = 1.0f; - // //float z_b = texture2D(depthBuffTex, vTexCoord).x; + // const float zFar = 100.0f; // float z_b = z; // float z_n = 2.0 * z_b - 1.0; // float z_e = 2.0 * zNear * zFar / (zFar + zNear - z_n * (zFar - zNear)); // return z_e; - //return (2.0 * z - near - far) / (far - near); + // return (2.0 * z - near - far) / (far - near); } vec4 calculate_final_color(uint frag_count) { @@ -192,7 +191,6 @@ vec4 calculate_final_color(uint frag_count) { // const float z2 = _z_(endFrag); const float l = ((z1 - S1) / L - (z2 - S1) / L) * volume_length[volID]; int max_iterations = int(l / volumeStepSize[volID]); - vec3 position; #elif ZTYPE == PSCDEPTH const float L = volume_zlength[volID]; const vec4 p1 = _pos_(startFrag); @@ -202,7 +200,6 @@ vec4 calculate_final_color(uint frag_count) { // const float z2 = _z_(endFrag); const float l = (dist / L) * volume_length[volID]; int max_iterations = int(l / volumeStepSize[volID]); - vec3 position; #endif @@ -281,8 +278,8 @@ vec4 calculate_final_color(uint frag_count) { // final_color = vec4(1.0,1.0,1.0,1.0); // } - final_color.rgb = final_color.rgb * final_color.a; - final_color.a = 1.0; + // final_color.rgb = final_color.rgb * final_color.a; + // final_color.a = 1.0; return final_color; @@ -305,4 +302,3 @@ void main() { - diff --git a/shaders/ABuffer/abufferStruct.hglsl b/shaders/ABuffer/abufferStruct.hglsl index 0153aecad6..5c510c4bd0 100644 --- a/shaders/ABuffer/abufferStruct.hglsl +++ b/shaders/ABuffer/abufferStruct.hglsl @@ -25,12 +25,11 @@ #ifndef ABUFFERSTRUCT_H_HGLSL #define ABUFFERSTRUCT_H_HGLSL -// The different kinds of implementation -#define ABUFFER_SINGLE_LINKED 1 -#define ABUFFER_FIXED 2 -#define ABUFFER_DYNAMIC 3 - -#define ABUFFER_IMPLEMENTATION ABUFFER_SINGLE_LINKED +// The different kinds of implementation, set from OpenSpace +// #define ABUFFER_SINGLE_LINKED 1 +// #define ABUFFER_FIXED 2 +// #define ABUFFER_DYNAMIC 3 +// #define ABUFFER_IMPLEMENTATION ABUFFER_SINGLE_LINKED //======================================================================================== diff --git a/src/abuffer/abuffer.cpp b/src/abuffer/abuffer.cpp index 744e27a402..7c2207d6fa 100644 --- a/src/abuffer/abuffer.cpp +++ b/src/abuffer/abuffer.cpp @@ -187,23 +187,11 @@ bool ABuffer::updateShader() { using ghoul::opengl::ShaderObject; using ghoul::opengl::ProgramObject; - ShaderObject* vs - = new ShaderObject(ShaderObject::ShaderType::ShaderTypeVertex, - absPath("${SHADERS}/ABuffer/abufferResolveVertex.glsl"), "Vertex"); - ShaderObject* fs - = new ShaderObject(ShaderObject::ShaderType::ShaderTypeFragment,_fragmentShaderPath, "Fragment"); - - ghoul::opengl::ProgramObject* resolveShader = new ProgramObject; - resolveShader->attachObject(vs); - resolveShader->attachObject(fs); - - if (!resolveShader->compileShaderObjects()) { - LERROR("Could not compile shader"); - return false; - } - if (!resolveShader->linkProgramObject()){ - LERROR("Could not link shader"); - return false; + ShaderCreator sc = OsEng.shaderBuilder(); + ghoul::opengl::ProgramObject* resolveShader = sc.buildShader("ABuffer resolve", absPath("${SHADERS}/ABuffer/abufferResolveVertex.glsl"), _fragmentShaderPath); + if( ! resolveShader) { + LERROR("Resolve shader not updated"); + return false; } int startAt = 0; @@ -215,9 +203,6 @@ bool ABuffer::updateShader() { resolveShader->setUniform(_transferFunctions.at(i).first, startAt + i); } - resolveShader->setUniform("SCREEN_WIDTH", static_cast(_width)); - resolveShader->setUniform("SCREEN_HEIGHT", static_cast(_height)); - if(_resolveShader) delete _resolveShader; @@ -321,7 +306,7 @@ std::string ABuffer::openspaceHeaders() { std::string ABuffer::openspaceSamplerCalls() { std::string samplercalls; - for (int i = 0; i < _samplers.size(); ++i) { + for (int i = 1; i < 2; ++i) { auto found1 = _samplers.at(i).find_first_not_of("vec4 "); auto found2 = _samplers.at(i).find_first_of("(",found1); diff --git a/src/engine/openspaceengine.cpp b/src/engine/openspaceengine.cpp index 3e63603abe..1ec31e84ce 100644 --- a/src/engine/openspaceengine.cpp +++ b/src/engine/openspaceengine.cpp @@ -225,6 +225,18 @@ bool OpenSpaceEngine::initialize() GLFWwindow* win = sgct::Engine::instance()->getActiveWindowPtr()->getWindowHandle(); glfwSwapBuffers(win); + int x1, xSize, y1, ySize; + sgct::Engine::instance()->getActiveWindowPtr()->getCurrentViewportPixelCoords(x1, y1, xSize, ySize); + std::string sourceHeader = ""; + sourceHeader += "#define SCREEN_WIDTH " + std::to_string(xSize) + "\n"; + sourceHeader += "#define SCREEN_HEIGHT " + std::to_string(ySize) + "\n"; + sourceHeader += "#define ABUFFER_SINGLE_LINKED " + std::to_string(ABUFFER_SINGLE_LINKED) + "\n"; + sourceHeader += "#define ABUFFER_FIXED " + std::to_string(ABUFFER_FIXED) + "\n"; + sourceHeader += "#define ABUFFER_DYNAMIC " + std::to_string(ABUFFER_DYNAMIC) + "\n"; + sourceHeader += "#define ABUFFER_IMPLEMENTATION " + std::to_string(ABUFFER_IMPLEMENTATION) + "\n"; + _shaderBuilder.createSourceFile(true); + _shaderBuilder.sourceFileHeader(sourceHeader); + // Register the filepaths from static function enables easy testing // registerFilePaths(); _context.createContextFromGLContext(); @@ -315,6 +327,13 @@ RenderEngine& OpenSpaceEngine::renderEngine() return *_renderEngine; } + +ShaderCreator& OpenSpaceEngine::shaderBuilder() +{ + // TODO custom assert (ticket #5) + return _shaderBuilder; +} + bool OpenSpaceEngine::initializeGL() { return _renderEngine->initializeGL(); diff --git a/src/rendering/renderablefieldlines.cpp b/src/rendering/renderablefieldlines.cpp index ff4e76c669..7fa62f4d0a 100644 --- a/src/rendering/renderablefieldlines.cpp +++ b/src/rendering/renderablefieldlines.cpp @@ -85,11 +85,9 @@ RenderableFieldlines::RenderableFieldlines(const ghoul::Dictionary& dictionary) _vertexSourceFile = new ghoul::filesystem::File(vshaderpath, false); _fragmentSourceFile = new ghoul::filesystem::File(fshaderpath, false); - _fieldlinesProgram = new ghoul::opengl::ProgramObject("FieldlinesProgram"); - ghoul::opengl::ShaderObject* vertexShader = new ghoul::opengl::ShaderObject(ghoul::opengl::ShaderObject::ShaderTypeVertex,vshaderpath); - ghoul::opengl::ShaderObject* fragmentShader = new ghoul::opengl::ShaderObject(ghoul::opengl::ShaderObject::ShaderTypeFragment,fshaderpath); - _fieldlinesProgram->attachObject(vertexShader); - _fieldlinesProgram->attachObject(fragmentShader); + + ShaderCreator sc = OsEng.shaderBuilder(); + _fieldlinesProgram = sc.buildShader("FieldlinesProgram", vshaderpath, fshaderpath); } } diff --git a/src/rendering/renderablevolume.cpp b/src/rendering/renderablevolume.cpp index 7d6efbd93f..2a7b04da9f 100644 --- a/src/rendering/renderablevolume.cpp +++ b/src/rendering/renderablevolume.cpp @@ -371,8 +371,8 @@ ghoul::opengl::Texture* RenderableVolume::loadTransferFunction(const std::string transferFunction[i] = 0.0f; } - size_t lowerIndex = static_cast(floorf(lower*static_cast(width))); - size_t upperIndex = static_cast(floorf(upper*static_cast(width))); + size_t lowerIndex = static_cast(floorf(lower*static_cast(width-1))); + size_t upperIndex = static_cast(floorf(upper*static_cast(width-1))); // LDEBUG("width: " << width); // LDEBUG("lower: " << lower); @@ -385,9 +385,9 @@ ghoul::opengl::Texture* RenderableVolume::loadTransferFunction(const std::string auto currentKey = prevKey + 1; auto lastKey = mappingKeys.end() -1; - for (size_t i=lowerIndex; i(i)/static_cast(width); + float fpos = static_cast(i)/static_cast(width-1); if (fpos > (*currentKey).position) { prevKey = currentKey; diff --git a/src/rendering/renderengine.cpp b/src/rendering/renderengine.cpp index 4e1123d11c..a4aeee8566 100644 --- a/src/rendering/renderengine.cpp +++ b/src/rendering/renderengine.cpp @@ -67,10 +67,13 @@ bool RenderEngine::initialize() //if (sgct::Engine::instance()->isMaster()) OsEng.interactionHandler().setCamera(_mainCamera); +#if ABUFFER_IMPLEMENTATION == ABUFFER_SINGLE_LINKED _abuffer = new ABufferSingleLinked(); - // _abuffer = new ABufferFixed(); - // _abuffer = new ABufferDynamic(); - +#elif ABUFFER_IMPLEMENTATION == ABUFFER_FIXED + _abuffer = new ABufferFixed(); +#elif ABUFFER_IMPLEMENTATION == ABUFFER_DYNAMIC + _abuffer = new ABufferDynamic(); +#endif return true; } diff --git a/src/scenegraph/scenegraph.cpp b/src/scenegraph/scenegraph.cpp index be80e87ac9..e9d7623f98 100644 --- a/src/scenegraph/scenegraph.cpp +++ b/src/scenegraph/scenegraph.cpp @@ -29,6 +29,7 @@ #include #include #include +#include // ghoul includes #include "ghoul/opengl/programobject.h" @@ -46,6 +47,9 @@ #include #include +#include + #include + namespace { const std::string _loggerCat = "SceneGraph"; const std::string _rootNodeName = "Root"; @@ -82,6 +86,55 @@ bool SceneGraph::initialize() using ghoul::opengl::ShaderObject; using ghoul::opengl::ProgramObject; + ShaderCreator sc = OsEng.shaderBuilder(); + ProgramObject* tmpProgram; + + typedef std::chrono::high_resolution_clock clock_; + typedef std::chrono::duration > second_; + + std::chrono::time_point beg_(clock_::now()); + + + // pscstandard + tmpProgram = sc.buildShader("pscstandard", + "${SHADERS}/pscstandard_vs.glsl", + "${SHADERS}/pscstandard_fs.glsl"); + if( ! tmpProgram) return false; + OsEng.ref().configurationManager().setValue("pscShader", tmpProgram); + + // RaycastProgram + tmpProgram = sc.buildShader("RaycastProgram", + "${SHADERS}/exitpoints.vert", + "${SHADERS}/exitpoints.frag"); + if( ! tmpProgram) return false; + OsEng.ref().configurationManager().setValue("RaycastProgram", tmpProgram); + + + // // TwoPassProgram + // tmpProgram = sc.buildShader("TwoPassProgram", + // "${SHADERS}/twopassraycaster.vert", + // "${SHADERS}/twopassraycaster.frag"); + // if( ! tmpProgram) return false; + // tmpProgram->setUniform("texBack", 0); + // tmpProgram->setUniform("texFront", 1); + // tmpProgram->setUniform("texVolume", 2); + // OsEng.ref().configurationManager().setValue("TwoPassProgram", tmpProgram); + + // Quad + tmpProgram = sc.buildShader("Quad", + "${SHADERS}/quadVert.glsl", + "${SHADERS}/quadFrag.glsl"); + if( ! tmpProgram) return false; + tmpProgram->setUniform("quadTex", 0); + OsEng.ref().configurationManager().setValue("Quad", tmpProgram); + + + + double elapsed = std::chrono::duration_cast(clock_::now() - beg_).count(); + LERROR("Time to load shaders: " << elapsed); + + /* + auto programCreator = [] ( const std::string& name, const std::string& vpath, const std::string& fpath) @@ -104,9 +157,6 @@ bool SceneGraph::initialize() po = nullptr; return po; }; - - ProgramObject* tmpProgram; - // pscstandard tmpProgram = programCreator("pscstandard", "${SHADERS}/pscstandard_vs.glsl", @@ -139,6 +189,7 @@ bool SceneGraph::initialize() if( ! tmpProgram) return false; tmpProgram->setUniform("quadTex", 0); OsEng.ref().configurationManager().setValue("Quad", tmpProgram); + */ // Initialize all nodes for (auto node : _nodes) { diff --git a/src/util/shadercreator.cpp b/src/util/shadercreator.cpp new file mode 100644 index 0000000000..b4b1b0d930 --- /dev/null +++ b/src/util/shadercreator.cpp @@ -0,0 +1,180 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include + +#include +#include +#include + +#include +#include +#include +// #include +// #include + +using ghoul::opengl::ProgramObject; +using ghoul::opengl::ShaderObject; + +namespace { + const std::string _loggerCat = "ShaderCreator"; + const std::string defaultSourceFileExtension = "OpenSpaceGenerated.glsl"; + const std::string separator = "//=====================================================================\n"; + const ShaderObject::ShaderType vsType = ShaderObject::ShaderType::ShaderTypeVertex; + const ShaderObject::ShaderType fsType = ShaderObject::ShaderType::ShaderTypeFragment; +} + +namespace openspace { +ShaderCreator::ShaderCreator(): + _createSourceFile(false), + _sourceFileExtension(defaultSourceFileExtension), + _sourceFileHeader(""), + _maxDepth(2) +{ + +} + +ShaderCreator::~ShaderCreator() { + +} + +void ShaderCreator::createSourceFile(bool b) { + _createSourceFile = b; +} + +void ShaderCreator::sourceFileExtension(const std::string& extension) { + if(extension != "") { + _sourceFileExtension = extension; + } +} + +void ShaderCreator::sourceFileHeader(const std::string& header) { + _sourceFileHeader = header; +} + +ghoul::opengl::ProgramObject* ShaderCreator::buildShader( + const std::string& name, const std::string& vpath, const std::string& fpath) +{ + std::string vsPath = absPath(vpath); + std::string fsPath = absPath(fpath); + + if( ! FileSys.fileExists(vsPath)) + return nullptr; + if( ! FileSys.fileExists(fsPath)) + return nullptr; + + if(_createSourceFile) { + _generateSource(vsPath); + _generateSource(fsPath); + + vsPath = _generateFilename(vsPath); + fsPath = _generateFilename(fsPath); + } + + ProgramObject* po = new ProgramObject(name); + ShaderObject* vs = new ShaderObject(vsType, vsPath, name + " Vertex"); + ShaderObject* fs = new ShaderObject(fsType, fsPath, name + " Fragment"); + po->attachObject(vs); + po->attachObject(fs); + if ( po->compileShaderObjects() && po->linkProgramObject()) + return po; + + // unsuccessful compilation, cleanup and return nullptr + delete po; + po = nullptr; + return po; +} + +void ShaderCreator::_generateSource(const std::string& filename) { + std::string generatedSource = ""; + if(_sourceFileHeader != "") + generatedSource += separator + "// HEADER\n" + separator + _sourceFileHeader + "\n"; + generatedSource += _loadSource(filename); + + std::ofstream of(_generateFilename(filename)); + of << generatedSource; + of.close(); +} + +std::string ShaderCreator::_loadSource(const std::string& filename, unsigned int depth) { + std::string contents = "", line; + std::ifstream f(filename); + + // Pre-allocate memory so the return string doesn't have to resize too often + // f.seekg( 0, std::ios::end ); + // unsigned int fsize = f.tellg(); + // f.seekg( 0); + // contents.reserve(fsize*3); + // line.reserve(fsize*3); + + contents += "\n"; + contents += separator; + contents += "// Filename: " + filename + "\n"; + // contents += "// Size: " + std::to_string(fsize) + "\n"; + contents += separator; + if(depth > _maxDepth) { + contents += "// TOO DEEP"; + return contents; + } + + if( ! FileSys.fileExists(filename)){ + contents += "// FILE NOT FOUND\n"; + return contents; + } + + boost::regex e1(R"(^\s*#include \"(.+)\"\s*)"); + boost::regex e2(R"(^\s*#include <(.+)>\s*)"); + while(std::getline(f, line)) { + boost::smatch m; + if(boost::regex_search(line, m, e1)) { + std::string includeFilename = m[1]; + includeFilename = filename.substr(0, filename.find_last_of("/")+1) + includeFilename; + line = _loadSource(includeFilename, depth + 1); + } else if(boost::regex_search(line, m, e2)) { + std::string includeFilename = m[1]; + line = _loadSource(absPath(includeFilename), depth + 1); + } + + contents += line + "\n"; + } + f.close(); + + return contents; +} + +std::string ShaderCreator::_generateFilename(const std::string& filename) { + // If way of confirming and creating a directory this could be a good solution + // to avoid cluttering in folders + // if(_cacheFolder != "") { + // size_t delimiter = filename.find_last_of("/"); + // std::string file = filename.substr(delimiter+1, filename.length() - delimiter); + // std::string path = filename.substr(0, filename.find_last_of("/")); + + // return path + "/" + _cacheFolder + "/" + file + "." + _sourceFileExtension; + // } + + return filename + "." + _sourceFileExtension; +} + +} \ No newline at end of file From bd38dd124e82aa4f6e98d3b7ab65e35385890fd9 Mon Sep 17 00:00:00 2001 From: Jonas Strandstedt Date: Mon, 14 Jul 2014 11:58:12 -0400 Subject: [PATCH 41/49] ABuffer bugfix, now supporting multiple (3+) volumes --- shaders/ABuffer/abufferResolveFragment.glsl | 7 +++-- shaders/exitpoints.vert | 1 - src/abuffer/abuffer.cpp | 9 ++++-- src/rendering/renderablevolumegl.cpp | 33 +++++++++++++-------- 4 files changed, 32 insertions(+), 18 deletions(-) diff --git a/shaders/ABuffer/abufferResolveFragment.glsl b/shaders/ABuffer/abufferResolveFragment.glsl index 75b1a615be..23746f32cb 100644 --- a/shaders/ABuffer/abufferResolveFragment.glsl +++ b/shaders/ABuffer/abufferResolveFragment.glsl @@ -32,6 +32,7 @@ #define SHOWFUNC // #define JITTERING +#define SHOWENLIL #define PSCDEPTH 1 #define ZDEPTH 2 @@ -171,13 +172,15 @@ vec4 calculate_final_color(uint frag_count) { ABufferStruct_t endFrag = fragments[i+1]; int type = int(_type_(startFrag)); - if(type == 0) + if(type == 0) { //blendStep(final_color, _col_(startFrag), stepSize); final_color = blend(final_color, _col_(startFrag)); + } else { + currentVolumeBitmask = currentVolumeBitmask ^ (1 << (type-1)); + } #if MAX_VOLUMES > 0 - currentVolumeBitmask = currentVolumeBitmask ^ type; if(currentVolumeBitmask != 0) { int volID = type -1; float p = 0.0f; diff --git a/shaders/exitpoints.vert b/shaders/exitpoints.vert index f8895ba4b3..a3295d3a6f 100644 --- a/shaders/exitpoints.vert +++ b/shaders/exitpoints.vert @@ -32,7 +32,6 @@ uniform vec4 campos; uniform mat4 camrot; uniform vec2 scaling; uniform vec4 objpos; -uniform float time; out vec3 vPosition; out vec3 worldPosition; diff --git a/src/abuffer/abuffer.cpp b/src/abuffer/abuffer.cpp index 7c2207d6fa..98d4244691 100644 --- a/src/abuffer/abuffer.cpp +++ b/src/abuffer/abuffer.cpp @@ -180,6 +180,7 @@ int ABuffer::addSamplerfile(const std::string& filename) { _samplers.push_back(""); // ID is one more than "actual" position since ID=0 is considered geometry + //return 1 << (_samplers.size()-1); return _samplers.size(); } @@ -306,13 +307,15 @@ std::string ABuffer::openspaceHeaders() { std::string ABuffer::openspaceSamplerCalls() { std::string samplercalls; - for (int i = 1; i < 2; ++i) { + for (int i = 0; i < _samplers.size(); ++i) { auto found1 = _samplers.at(i).find_first_not_of("vec4 "); auto found2 = _samplers.at(i).find_first_of("(",found1); if(found1 != std::string::npos && found2 != std::string::npos) { std::string functionName = _samplers.at(i).substr(found1, found2 - found1); - samplercalls += "if((currentVolumeBitmask & (1 << " + std::to_string(i) + ")) == "+std::to_string(i+1)+") {\n"; + if(i == 0) + samplercalls += "#ifdef SHOWENLIL\n"; + samplercalls += "if((currentVolumeBitmask & (1 << " + std::to_string(i) + ")) == "+std::to_string(1 << i)+") {\n"; samplercalls += " vec4 c = " + functionName + "(final_color,volume_position[" + std::to_string(i) + "]);\n"; // samplercalls += " if(c.a < 0.1) { \n"; // samplercalls += " if( volumeStepSize[" + std::to_string(i) + "] < 16.0*volumeStepSizeOriginal[" + std::to_string(i) + "]) \n"; @@ -326,6 +329,8 @@ std::string ABuffer::openspaceSamplerCalls() { // samplercalls += " blendStep(final_color, c, stepSize);\n"; samplercalls += " volume_position[" + std::to_string(i) + "] += volume_direction[" + std::to_string(i) + "]*volumeStepSize[" + std::to_string(i) + "];\n"; samplercalls += "}\n"; + if(i == 0) + samplercalls += "#endif\n"; } diff --git a/src/rendering/renderablevolumegl.cpp b/src/rendering/renderablevolumegl.cpp index ddbf548138..80c96dd39c 100644 --- a/src/rendering/renderablevolumegl.cpp +++ b/src/rendering/renderablevolumegl.cpp @@ -61,6 +61,7 @@ RenderableVolumeGL::RenderableVolumeGL(const ghoul::Dictionary& dictionary): _transferFunction = nullptr; _transferFunctionFile = nullptr; + _transferFunctionPath = ""; if (dictionary.hasKey("TransferFunction")) { std::string transferFunctionPath = ""; if(dictionary.getValue("TransferFunction", transferFunctionPath)) { @@ -120,22 +121,28 @@ RenderableVolumeGL::~RenderableVolumeGL() { } bool RenderableVolumeGL::initialize() { - assert(_filename != ""); + // assert(_filename != ""); // ------ VOLUME READING ---------------- - _volume = loadVolume(_filename, _hintsDictionary); - _volume->uploadTexture(); - _transferFunction = loadTransferFunction(_transferFunctionPath); - _transferFunction->uploadTexture(); - // TODO: fix volume an transferfunction names - OsEng.renderEngine().abuffer()->addVolume(_volumeName, _volume); - OsEng.renderEngine().abuffer()->addTransferFunction(_transferFunctionName, _transferFunction); - _id = OsEng.renderEngine().abuffer()->addSamplerfile(_samplerFilename); + if(_filename != "") { + _volume = loadVolume(_filename, _hintsDictionary); + _volume->uploadTexture(); + OsEng.renderEngine().abuffer()->addVolume(_volumeName, _volume); + } - auto textureCallback = [this](const ghoul::filesystem::File& file) { - _updateTransferfunction = true; - }; - _transferFunctionFile->setCallback(textureCallback); + if(_transferFunctionPath != "") { + _transferFunction = loadTransferFunction(_transferFunctionPath); + _transferFunction->uploadTexture(); + OsEng.renderEngine().abuffer()->addTransferFunction(_transferFunctionName, _transferFunction); + + auto textureCallback = [this](const ghoul::filesystem::File& file) { + _updateTransferfunction = true; + }; + _transferFunctionFile->setCallback(textureCallback); + } + + // add the sampler and get the ID + _id = OsEng.renderEngine().abuffer()->addSamplerfile(_samplerFilename); _box = new sgct_utils::SGCTBox(1.0f, sgct_utils::SGCTBox::Regular); OsEng.configurationManager().getValue("RaycastProgram", _boxProgram); From e8ac32b8306b9481e724e046a28fb9e77a48f960 Mon Sep 17 00:00:00 2001 From: Jonas Strandstedt Date: Fri, 18 Jul 2014 12:17:45 -0400 Subject: [PATCH 42/49] Updated ghoul, initial volumes with different stepsize --- ext/ghoul | 2 +- shaders/ABuffer/abufferResolveFragment.glsl | 23 +++++++++++++++++---- src/abuffer/abuffer.cpp | 4 ++++ 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/ext/ghoul b/ext/ghoul index 9199e2da7a..5c1957e9e2 160000 --- a/ext/ghoul +++ b/ext/ghoul @@ -1 +1 @@ -Subproject commit 9199e2da7a2df7e4fe50437ba8a775f3178d8612 +Subproject commit 5c1957e9e2e7bfd79d72788decc099e74043cf25 diff --git a/shaders/ABuffer/abufferResolveFragment.glsl b/shaders/ABuffer/abufferResolveFragment.glsl index 23746f32cb..63b89cf709 100644 --- a/shaders/ABuffer/abufferResolveFragment.glsl +++ b/shaders/ABuffer/abufferResolveFragment.glsl @@ -31,12 +31,12 @@ #define MAX_FRAGMENTS 16 #define SHOWFUNC -// #define JITTERING +#define JITTERING #define SHOWENLIL #define PSCDEPTH 1 #define ZDEPTH 2 -#define ZTYPE PSCDEPTH +#define ZTYPE ZDEPTH // Math defintions #define M_E 2.7182818284590452354 @@ -181,9 +181,24 @@ vec4 calculate_final_color(uint frag_count) { #if MAX_VOLUMES > 0 - if(currentVolumeBitmask != 0) { + if(currentVolumeBitmask > 0) { + + // TODO: Fix this non-working normalization for volumes with different stepsize + // float myMaxSteps = 0.0000001; + // for(int v = 0; v < MAX_VOLUMES; ++v) { + // if((currentVolumeBitmask & (1 << v)) > 0) { + // myMaxSteps = max(myMaxSteps, volume_length[v]/volumeStepSize[v]); + // } + // } + // for(int v = 0; v < MAX_VOLUMES; ++v) { + // if((currentVolumeBitmask & (1 << v)) > 0) { + // float aaa = volume_length[v]/myMaxSteps; + // volumeStepSize[v] = volumeStepSizeOriginal[v]*vec3(aaa); + // } + // } + + int volID = type -1; - float p = 0.0f; #if ZTYPE == ZDEPTH const float S1 = volume_zlength[volID].x; const float S2 = volume_zlength[volID].y; diff --git a/src/abuffer/abuffer.cpp b/src/abuffer/abuffer.cpp index 98d4244691..274aa9859e 100644 --- a/src/abuffer/abuffer.cpp +++ b/src/abuffer/abuffer.cpp @@ -327,7 +327,11 @@ std::string ABuffer::openspaceSamplerCalls() { // samplercalls += " } \n"; samplercalls += " blendStep(final_color, c, volumeStepSize[" + std::to_string(i) + "]);\n"; // samplercalls += " blendStep(final_color, c, stepSize);\n"; + // samplercalls += " float aaa = volume_length[i]/myMaxSteps;\n"; samplercalls += " volume_position[" + std::to_string(i) + "] += volume_direction[" + std::to_string(i) + "]*volumeStepSize[" + std::to_string(i) + "];\n"; + // float aaa = ray[v].w/myMaxSteps; + // pos[v] += vec4(ray[v].xyz*vec3(aaa),aaa); + // samplercalls += " volume_position[" + std::to_string(i) + "] += volume_direction[" + std::to_string(i) + "]*volumeStepSize[" + std::to_string(i) + "];\n"; samplercalls += "}\n"; if(i == 0) samplercalls += "#endif\n"; From eb9863046752e58dfc713d2990a483bd50603704 Mon Sep 17 00:00:00 2001 From: Jonas Strandstedt Date: Fri, 18 Jul 2014 13:28:48 -0400 Subject: [PATCH 43/49] Added new openspace data --- openspace-data | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openspace-data b/openspace-data index 8fa226790e..73b2b86788 160000 --- a/openspace-data +++ b/openspace-data @@ -1 +1 @@ -Subproject commit 8fa226790e939667b31c0e2020ba42708e3de7e6 +Subproject commit 73b2b86788038628721898e08a367588069afbac From ecf3a8539a4b23e3e4db03594f9391e85129f165 Mon Sep 17 00:00:00 2001 From: Jonas Strandstedt Date: Fri, 18 Jul 2014 14:00:09 -0400 Subject: [PATCH 44/49] Added missing file --- include/openspace/util/kameleonwrapper.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/openspace/util/kameleonwrapper.h b/include/openspace/util/kameleonwrapper.h index fd8903f7a2..1bd768e72a 100644 --- a/include/openspace/util/kameleonwrapper.h +++ b/include/openspace/util/kameleonwrapper.h @@ -80,6 +80,8 @@ public: std::vector > getLorentzTrajectories(std::vector seedPoints, glm::vec4 color, float stepsize); + glm::vec3 getModelBarycenterOffset(); + private: std::vector traceCartesianFieldline(const std::string& xVar, const std::string& yVar, const std::string& zVar, glm::vec3 seedPoint, From e99a98224c43e8a40f1a215ca3c72ec865a455eb Mon Sep 17 00:00:00 2001 From: Jonas Strandstedt Date: Wed, 23 Jul 2014 16:06:49 -0400 Subject: [PATCH 45/49] Working ABuffer - Fixed the ABuffer rendering for intersecting volumes - Added keyboard callback for toggling renderables - Changed textures from ClampToBorder to ClampToEdge - Fixed transferfunctions to clamp to edge instead of fade to black --- config/sgct/single.xml | 2 +- .../interaction/interactionhandler.h | 6 + .../openspace/rendering/renderablevolumegl.h | 1 + include/openspace/scenegraph/scenegraphnode.h | 1 + openspace-data | 2 +- shaders/ABuffer/abufferResolveFragment.glsl | 153 ++++++++++++------ src/abuffer/abuffer.cpp | 5 +- src/interaction/interactionhandler.cpp | 13 ++ src/rendering/renderablevolume.cpp | 75 +++++---- src/rendering/renderablevolumegl.cpp | 81 +++++----- src/scenegraph/scenegraphnode.cpp | 22 ++- src/util/kameleonwrapper.cpp | 8 + 12 files changed, 246 insertions(+), 123 deletions(-) diff --git a/config/sgct/single.xml b/config/sgct/single.xml index 87e59f7b28..3ec20dd5db 100644 --- a/config/sgct/single.xml +++ b/config/sgct/single.xml @@ -8,7 +8,7 @@ - + diff --git a/include/openspace/interaction/interactionhandler.h b/include/openspace/interaction/interactionhandler.h index b8505beda2..80b867dd91 100644 --- a/include/openspace/interaction/interactionhandler.h +++ b/include/openspace/interaction/interactionhandler.h @@ -11,6 +11,8 @@ #include #include #include +#include +#include namespace openspace { @@ -56,6 +58,8 @@ public: void mouseButtonCallback(int key, int action); void mousePositionCallback(int x, int y); void mouseScrollWheelCallback(int pos); + + void addKeyCallback(int key, std::function f); private: glm::vec3 mapToTrackball(glm::vec2 mousePos); @@ -77,6 +81,8 @@ private: // for locking and unlocking std::mutex cameraGuard_; + + std::multimap > _keyCallbacks; }; diff --git a/include/openspace/rendering/renderablevolumegl.h b/include/openspace/rendering/renderablevolumegl.h index f7b82028fc..dce4c1942b 100644 --- a/include/openspace/rendering/renderablevolumegl.h +++ b/include/openspace/rendering/renderablevolumegl.h @@ -68,6 +68,7 @@ private: GLuint _boxArray; ghoul::opengl::ProgramObject *_boxProgram; glm::vec3 _boxScaling, _boxOffset; + float _w; GLint _MVPLocation, _modelTransformLocation, _typeLocation; bool _updateTransferfunction; diff --git a/include/openspace/scenegraph/scenegraphnode.h b/include/openspace/scenegraph/scenegraphnode.h index 9a8b847d97..531ca23089 100644 --- a/include/openspace/scenegraph/scenegraphnode.h +++ b/include/openspace/scenegraph/scenegraphnode.h @@ -90,6 +90,7 @@ private: // renderable Renderable* _renderable; bool _renderableVisible; + bool _renderableToggle; // bounding sphere bool _boundingSphereVisible; diff --git a/openspace-data b/openspace-data index 73b2b86788..2642f7b929 160000 --- a/openspace-data +++ b/openspace-data @@ -1 +1 @@ -Subproject commit 73b2b86788038628721898e08a367588069afbac +Subproject commit 2642f7b929d2fb6573f81ecec5d2823ef5506092 diff --git a/shaders/ABuffer/abufferResolveFragment.glsl b/shaders/ABuffer/abufferResolveFragment.glsl index 63b89cf709..1eb46ac089 100644 --- a/shaders/ABuffer/abufferResolveFragment.glsl +++ b/shaders/ABuffer/abufferResolveFragment.glsl @@ -30,9 +30,10 @@ #pragma openspace insert SETTINGS #define MAX_FRAGMENTS 16 -#define SHOWFUNC -#define JITTERING -#define SHOWENLIL +// #define SHOWFUNC +// #define JITTERING +#define SAMPLEFIRSTVOLUME +// #define COLORNORMALIZATION #define PSCDEPTH 1 #define ZDEPTH 2 @@ -59,7 +60,8 @@ const float samplingRate = 1.0; // uniform int SCREEN_WIDTH; // uniform int SCREEN_HEIGHT; -uniform float ALPHA_LIMIT = 0.95; +uniform float ALPHA_LIMIT = 0.99; +uniform float EPSILON = 0.01; in vec2 texCoord; out vec4 color; @@ -81,7 +83,9 @@ vec3 CartesianToSpherical(vec3 _cartesian) { theta = phi = 0.0; } else { theta = acos(cartesian.z/r) / M_PI; - phi = (M_PI + atan(cartesian.y, cartesian.x)) / (2.0*M_PI); + // float diff = -.0f; + phi = (M_PI + atan(cartesian.y, cartesian.x)) / (2.0*M_PI ); + // phi = (M_PI+radians(diff) + atan(cartesian.y, cartesian.x)) / (2.0*M_PI+radians(diff) ); // phi = (M_PI + atan(cartesian.x, cartesian.y)) / (2.0*M_PI); } // r *= 0.57735026919; @@ -142,6 +146,27 @@ void blendGeometry(inout vec4 color, ABufferStruct_t frag) { } */ +float volumeRaycastingDistance(in int id, in ABufferStruct_t startFrag, in ABufferStruct_t endFrag) { +#if ZTYPE == ZDEPTH + const float S1 = volume_zlength[id].x; + const float S2 = volume_zlength[id].y; + const float L = S1 - S2; + // const float z1 = globz(_z_(startFrag)); + // const float z2 = globz(_z_(endFrag)); + const float z1 = _z_(startFrag); + const float z2 = _z_(endFrag); + return ((z1 - S1) / L - (z2 - S1) / L) * volume_length[id]; +#elif ZTYPE == PSCDEPTH + const float L = volume_zlength[id]; + const vec4 p1 = _pos_(startFrag); + const vec4 p2 = _pos_(endFrag); + const float dist = pscLength(p1, p2); + // const float z1 = _z_(startFrag); + // const float z2 = _z_(endFrag); + return (dist / L) * volume_length[id]; +#endif +} + float globz(float z) { return z; // return log(2.0*z-1.0); @@ -183,59 +208,81 @@ vec4 calculate_final_color(uint frag_count) { #if MAX_VOLUMES > 0 if(currentVolumeBitmask > 0) { + int volbit = currentVolumeBitmask; + int endbittype = int(_type_(endFrag)); + if(endbittype > 0) + volbit = volbit ^ (1 << (endbittype-1)); + + // int volID = type -1; + // int volID = type-1; + int volID; + // TODO: Fix this non-working normalization for volumes with different stepsize - // float myMaxSteps = 0.0000001; - // for(int v = 0; v < MAX_VOLUMES; ++v) { - // if((currentVolumeBitmask & (1 << v)) > 0) { - // myMaxSteps = max(myMaxSteps, volume_length[v]/volumeStepSize[v]); - // } - // } + float myMaxSteps = 0.0000001; + float vlength; + for(int v = 0; v < MAX_VOLUMES; ++v) { + if((currentVolumeBitmask & (1 << v)) > 0) { + + // float l = volume_length[v]/volumeStepSize[v]; + // if(myMaxSteps < l) { + // myMaxSteps = l; + // volID = v; + // } + float l = volumeRaycastingDistance(v, startFrag, endFrag); + // myMaxSteps = max(myMaxSteps, L/volumeStepSizeOriginal[v]); + myMaxSteps = max(myMaxSteps, l/volumeStepSizeOriginal[v]); + + // if((volbit & (1 << v)) > 0) + // volID = v; + // if(volbit == 0) + // volID = v; + // if(type - 1 != v && type == endbittype) + // volID = v; + + // if(volID < 0) volID = v; + // volID = v; + } + } // for(int v = 0; v < MAX_VOLUMES; ++v) { // if((currentVolumeBitmask & (1 << v)) > 0) { // float aaa = volume_length[v]/myMaxSteps; // volumeStepSize[v] = volumeStepSizeOriginal[v]*vec3(aaa); // } // } - - - int volID = type -1; -#if ZTYPE == ZDEPTH - const float S1 = volume_zlength[volID].x; - const float S2 = volume_zlength[volID].y; - const float L = S1 - S2; - const float z1 = globz(_z_(startFrag)); - const float z2 = globz(_z_(endFrag)); - // const float z1 = _z_(startFrag); - // const float z2 = _z_(endFrag); - const float l = ((z1 - S1) / L - (z2 - S1) / L) * volume_length[volID]; - int max_iterations = int(l / volumeStepSize[volID]); -#elif ZTYPE == PSCDEPTH - const float L = volume_zlength[volID]; - const vec4 p1 = _pos_(startFrag); - const vec4 p2 = _pos_(endFrag); - const float dist = pscLength(p1, p2); - // const float z1 = _z_(startFrag); - // const float z2 = _z_(endFrag); - const float l = (dist / L) * volume_length[volID]; - int max_iterations = int(l / volumeStepSize[volID]); -#endif - - - - - // MIP - // vec4 tmp, color = vec4(0); - // while(p < l && iterations < LOOP_LIMIT) { - // tmp = texture(volume, volume_position[volID]); - // color = max(color, tmp); - // p+= stepSize; - // volume_position[volID] += direction*stepSize; - // ++iterations; + // float myMaxSteps = stepSize; + // for(int v = 0; v < MAX_VOLUMES; ++v) { + // if((currentVolumeBitmask & (1 << v)) > 0) { + // myMaxSteps = min(myMaxSteps, volumeStepSize[v]); + // } // } - // vec4 volume_color = vec4(color.r,color.r,color.r,color.r*2.0); - // if(volume_color.a < 0.1) volume_color = vec4(0.0,0.0,0.0,0.0); - // final_color = blend(final_color, volume_color); - + + for(int v = 0; v < MAX_VOLUMES; ++v) { + if((currentVolumeBitmask & (1 << v)) > 0) { + // float aaa = myMaxSteps; + float l = volumeRaycastingDistance(v, startFrag, endFrag); + float aaa = l/myMaxSteps; + // float aaa = volume_length[v]/myMaxSteps; + // volumeStepSize[v] = volumeStepSizeOriginal[v]*vec3(aaa); + // float aaa = volume_length[v]/volumeStepSizeOriginal[v]; + volumeStepSize[v] = aaa; + + // if(vlength >= volume_length[v]) { + // // vlength = volume_length[v]; + // const float S1 = volume_zlength[v].x; + // const float S2 = volume_zlength[v].y; + // const float L = S1 - S2; + // vlength = volume_length[v]; + // vlength = L; + // volID = v; + // } + // if(volID < 0) volID = v; + volID = v; + } + } + + + float l = volumeRaycastingDistance(volID, startFrag, endFrag); + int max_iterations = int(l / volumeStepSize[volID]); // TransferFunction vec4 color = vec4(0); @@ -296,8 +343,10 @@ vec4 calculate_final_color(uint frag_count) { // final_color = vec4(1.0,1.0,1.0,1.0); // } - // final_color.rgb = final_color.rgb * final_color.a; - // final_color.a = 1.0; +#ifdef COLORNORMALIZATION + final_color.rgb = final_color.rgb * final_color.a; + final_color.a = 1.0; +#endif return final_color; diff --git a/src/abuffer/abuffer.cpp b/src/abuffer/abuffer.cpp index 274aa9859e..42a7367721 100644 --- a/src/abuffer/abuffer.cpp +++ b/src/abuffer/abuffer.cpp @@ -314,7 +314,7 @@ std::string ABuffer::openspaceSamplerCalls() { if(found1 != std::string::npos && found2 != std::string::npos) { std::string functionName = _samplers.at(i).substr(found1, found2 - found1); if(i == 0) - samplercalls += "#ifdef SHOWENLIL\n"; + samplercalls += "#ifdef SAMPLEFIRSTVOLUME\n"; samplercalls += "if((currentVolumeBitmask & (1 << " + std::to_string(i) + ")) == "+std::to_string(1 << i)+") {\n"; samplercalls += " vec4 c = " + functionName + "(final_color,volume_position[" + std::to_string(i) + "]);\n"; // samplercalls += " if(c.a < 0.1) { \n"; @@ -325,6 +325,7 @@ std::string ABuffer::openspaceSamplerCalls() { // samplercalls += " volumeStepSize[" + std::to_string(i) + "] = volumeStepSizeOriginal[" + std::to_string(i) + "]; \n"; // samplercalls += " //c = " + functionName + "(final_color,volume_position[" + std::to_string(i) + "]);\n"; // samplercalls += " } \n"; + samplercalls += " if(c.a > EPSILON)\n"; samplercalls += " blendStep(final_color, c, volumeStepSize[" + std::to_string(i) + "]);\n"; // samplercalls += " blendStep(final_color, c, stepSize);\n"; // samplercalls += " float aaa = volume_length[i]/myMaxSteps;\n"; @@ -358,7 +359,7 @@ std::string ABuffer::openspaceTransferFunction() { for(int i = 0; i < _transferFunctions.size(); ++i) { tf += "if( gl_FragCoord.y > SCREEN_HEIGHTf-showfunc_size*"+std::to_string(i+1)+ " && gl_FragCoord.y < SCREEN_HEIGHTf-showfunc_size*"+std::to_string(i)+") {\n"; - tf += " float normalizedIntensity = gl_FragCoord.x / SCREEN_WIDTHf ;\n"; + tf += " float normalizedIntensity = gl_FragCoord.x / (SCREEN_WIDTHf-1) ;\n"; tf += " vec4 tfc = texture("+ _transferFunctions.at(i).first +", normalizedIntensity);\n"; tf += " final_color = tfc;\n"; tf += " float cmpf = SCREEN_HEIGHTf-showfunc_size*"+std::to_string(i+1)+" + tfc.a*showfunc_size;\n"; diff --git a/src/interaction/interactionhandler.cpp b/src/interaction/interactionhandler.cpp index 5a4dc136f0..9443a1f286 100644 --- a/src/interaction/interactionhandler.cpp +++ b/src/interaction/interactionhandler.cpp @@ -390,6 +390,14 @@ void InteractionHandler::keyboardCallback(int key, int action) { getCamera()->setCameraDirection(glm::vec3(0.0, 0.0, -1.0)); } */ + // std::pair >::iterator, std::multimap >::iterator> ret; + if(action == SGCT_PRESS) { + auto ret = _keyCallbacks.equal_range(key); + for (auto it=ret.first; it!=ret.second; ++it) + it->second(); + } + + } void InteractionHandler::mouseButtonCallback(int key, int action) { @@ -428,5 +436,10 @@ void InteractionHandler::mouseScrollWheelCallback(int pos) { } } +void InteractionHandler::addKeyCallback(int key, std::function f) { + //std::map > > _keyCallbacks; + + _keyCallbacks.insert(std::make_pair(key, f)); +} } // namespace openspace diff --git a/src/rendering/renderablevolume.cpp b/src/rendering/renderablevolume.cpp index e7463558cd..7ecaf4274f 100644 --- a/src/rendering/renderablevolume.cpp +++ b/src/rendering/renderablevolume.cpp @@ -33,6 +33,7 @@ #include #include +#include #include #include #include @@ -81,6 +82,7 @@ ghoul::opengl::Texture* RenderableVolume::loadVolume( const std::string& filepath, const ghoul::Dictionary& hintsDictionary) { + if( ! FileSys.fileExists(filepath)) { LWARNING("Could not load volume, could not find '" << filepath << "'"); return nullptr; @@ -92,6 +94,9 @@ ghoul::opengl::Texture* RenderableVolume::loadVolume( return rawReader.read(filepath); } else if(hasExtension(filepath, "cdf")) { + ghoul::opengl::Texture::FilterMode filtermode = ghoul::opengl::Texture::FilterMode::Linear; + ghoul::opengl::Texture::WrappingMode wrappingmode = ghoul::opengl::Texture::WrappingMode::ClampToEdge; + glm::size3_t dimensions(1,1,1); double tempValue; if (hintsDictionary.hasKey("Dimensions.1") && @@ -158,9 +163,7 @@ ghoul::opengl::Texture* RenderableVolume::loadVolume( } fclose(file); - ghoul::opengl::Texture* t = new ghoul::opengl::Texture(data, dimensions, ghoul::opengl::Texture::Format::Red, GL_RED, GL_FLOAT, ghoul::opengl::Texture::FilterMode::Linear, ghoul::opengl::Texture::WrappingMode::ClampToBorder); - t->setWrapping(ghoul::opengl::Texture::WrappingMode::ClampToBorder); - return t; + return new ghoul::opengl::Texture(data, dimensions, ghoul::opengl::Texture::Format::Red, GL_RED, GL_FLOAT, filtermode, wrappingmode); } KameleonWrapper::Model model; @@ -183,9 +186,7 @@ ghoul::opengl::Texture* RenderableVolume::loadVolume( fwrite(data, sizeof(float), length, file); fclose(file); } - ghoul::opengl::Texture* t = new ghoul::opengl::Texture(data, dimensions, ghoul::opengl::Texture::Format::Red, GL_RED, GL_FLOAT, ghoul::opengl::Texture::FilterMode::Linear, ghoul::opengl::Texture::WrappingMode::ClampToBorder); - t->setWrapping(ghoul::opengl::Texture::WrappingMode::ClampToBorder); - return t; + return new ghoul::opengl::Texture(data, dimensions, ghoul::opengl::Texture::Format::Red, GL_RED, GL_FLOAT, filtermode, wrappingmode); } else if (hintsDictionary.hasKey("Variables")) { std::string xVariable, yVariable, zVariable; bool xVar, yVar, zVar; @@ -205,9 +206,7 @@ ghoul::opengl::Texture* RenderableVolume::loadVolume( fclose(file); } - ghoul::opengl::Texture* t = new ghoul::opengl::Texture(data, dimensions, ghoul::opengl::Texture::Format::RGBA, GL_RGBA, GL_FLOAT); - t->setWrapping(ghoul::opengl::Texture::WrappingMode::ClampToBorder); - return t; + return new ghoul::opengl::Texture(data, dimensions, ghoul::opengl::Texture::Format::RGBA, GL_RGBA, GL_FLOAT, filtermode, wrappingmode); } } else { @@ -236,6 +235,7 @@ glm::vec3 RenderableVolume::getVolumeOffset( model = KameleonWrapper::Model::BATSRUS; } else if (modelString == "ENLIL") { model = KameleonWrapper::Model::ENLIL; + return glm::vec3(0); } else { LWARNING("Hints does not specify a valid 'Model'"); return glm::vec3(0); @@ -313,11 +313,14 @@ ghoul::opengl::Texture* RenderableVolume::loadTransferFunction(const std::string if ( ! FileSys.fileExists(f)) { return nullptr; } + ghoul::opengl::Texture::FilterMode filtermode = ghoul::opengl::Texture::FilterMode::Linear; + ghoul::opengl::Texture::WrappingMode wrappingmode = ghoul::opengl::Texture::WrappingMode::ClampToEdge; + // check if not a txt based texture if ( ! hasExtension(filepath, "txt")) { ghoul::opengl::Texture* t = ghoul::opengl::loadTexture(f); - t->setWrapping(ghoul::opengl::Texture::WrappingMode::ClampToBorder); + t->setWrapping(wrappingmode); return t; } @@ -346,7 +349,7 @@ ghoul::opengl::Texture* RenderableVolume::loadTransferFunction(const std::string auto widthValidator = [](size_t in) { if(in > 0) return in; return static_cast(1); }; auto upperLowerValidator = [](float in) { return glm::clamp(in, 0.0f, 1.0f); }; - auto intensityValidator = [](float in) { if(in > 0.0f) return in; return 1.0f; }; + auto intensityValidator = [](float in) { return glm::clamp(in, 0.0f, 1.0f); }; std::string line; while (std::getline(in, line)) { @@ -381,15 +384,26 @@ ghoul::opengl::Texture* RenderableVolume::loadTransferFunction(const std::string if (mappingKeys.size() < 1) { return nullptr; } + + // for(auto key: mappingKeys) { + // glm::vec4 rgba = key.color; + // LDEBUG("i: " << key.position << ", rgba: (" << rgba[0] << ", " << rgba[1] << ", " << rgba[2] << ", " << rgba[3] << ")"); + // } + // LDEBUG("insert...."); - mappingKeys.insert(mappingKeys.begin(), {lower}); - mappingKeys.push_back({upper}); - - - for(auto key: mappingKeys) { - glm::vec4 rgba = key.color; -// LDEBUG("i: " << key.position << ", rgba: (" << rgba[0] << ", " << rgba[1] << ", " << rgba[2] << ", " << rgba[3] << ")"); + if (mappingKeys.front().position > lower){ + mappingKeys.insert(mappingKeys.begin(), {lower,mappingKeys.front().color}); } + + if (mappingKeys.back().position < upper){ + mappingKeys.push_back({upper,mappingKeys.back().color}); + } + + + // for(auto key: mappingKeys) { + // glm::vec4 rgba = key.color; + // LDEBUG("i: " << key.position << ", rgba: (" << rgba[0] << ", " << rgba[1] << ", " << rgba[2] << ", " << rgba[3] << ")"); + // } // allocate new float array with zeros float* transferFunction = new float[width*4](); @@ -448,18 +462,25 @@ ghoul::opengl::Texture* RenderableVolume::loadTransferFunction(const std::string //LDEBUG("["<< position <<"] " << value); } - // LDEBUG(weight << ", (" << - // transferFunction[4*i+0] << ", " << - // transferFunction[4*i+1] << ", " << - // transferFunction[4*i+2] << ", " << - // transferFunction[4*i+3] << ")"); + // LDEBUG(std::fixed << std::setw(10) << std::left << std::setprecision(8) << weight << ", (" << + // std::setw(10) << std::left << std::setprecision(8) << transferFunction[4*i+0] << ", " << + // std::setw(10) << std::left << std::setprecision(8) << transferFunction[4*i+1] << ", " << + // std::setw(10) << std::left << std::setprecision(8) << transferFunction[4*i+2] << ", " << + // std::setw(10) << std::left << std::setprecision(8) << transferFunction[4*i+3] << ")"); } - ghoul::opengl::Texture* t = new ghoul::opengl::Texture(transferFunction, + // for (int i = 0; i <= width; ++i) { + + // LDEBUG(std::fixed << "(" << + // std::setw(10) << std::left << std::setprecision(8) << transferFunction[4*i+0] << ", " << + // std::setw(10) << std::left << std::setprecision(8) << transferFunction[4*i+1] << ", " << + // std::setw(10) << std::left << std::setprecision(8) << transferFunction[4*i+2] << ", " << + // std::setw(10) << std::left << std::setprecision(8) << transferFunction[4*i+3] << ")"); + // } + + return new ghoul::opengl::Texture(transferFunction, glm::size3_t(width,1,1),ghoul::opengl::Texture::Format::RGBA, - GL_RGBA, GL_FLOAT, ghoul::opengl::Texture::FilterMode::Linear, - ghoul::opengl::Texture::WrappingMode::ClampToBorder); - return t; + GL_RGBA, GL_FLOAT,filtermode, wrappingmode); } } // namespace openspace diff --git a/src/rendering/renderablevolumegl.cpp b/src/rendering/renderablevolumegl.cpp index ed0e62a719..9e4bca99a0 100644 --- a/src/rendering/renderablevolumegl.cpp +++ b/src/rendering/renderablevolumegl.cpp @@ -92,8 +92,11 @@ RenderableVolumeGL::RenderableVolumeGL(const ghoul::Dictionary& dictionary): _boxScaling[1] = tempValue; } if(dictionary.hasKey("BoxScaling.3") && dictionary.getValue("BoxScaling.3", tempValue)) { - if(tempValue > 0.0) - _boxScaling[2] = tempValue; + if(tempValue > 0.0) + _boxScaling[2] = tempValue; + } + if(dictionary.hasKey("BoxScaling.4") && dictionary.getValue("BoxScaling.4", tempValue)) { + _w = tempValue; } _volumeName = ""; @@ -103,7 +106,7 @@ RenderableVolumeGL::RenderableVolumeGL(const ghoul::Dictionary& dictionary): if (dictionary.hasKey("TransferFunctionName")) dictionary.getValue("TransferFunctionName", _transferFunctionName); - setBoundingSphere(PowerScaledScalar::CreatePSS(glm::length(_boxScaling))); + setBoundingSphere(PowerScaledScalar::CreatePSS(glm::length(_boxScaling)*pow(10,_w))); } RenderableVolumeGL::~RenderableVolumeGL() { @@ -160,47 +163,47 @@ bool RenderableVolumeGL::initialize() { const GLfloat size = 0.5f; const GLfloat vertex_data[] = { // square of two triangles (sigh) // x, y, z, s, - -size, -size, size, 0.0f, - size, size, size, 0.0f, - -size, size, size, 0.0f, - -size, -size, size, 0.0f, - size, -size, size, 0.0f, - size, size, size, 0.0f, + -size, -size, size, _w, + size, size, size, _w, + -size, size, size, _w, + -size, -size, size, _w, + size, -size, size, _w, + size, size, size, _w, - -size, -size, -size, 0.0f, - size, size, -size, 0.0f, - -size, size, -size, 0.0f, - -size, -size, -size, 0.0f, - size, -size, -size, 0.0f, - size, size, -size, 0.0f, + -size, -size, -size, _w, + size, size, -size, _w, + -size, size, -size, _w, + -size, -size, -size, _w, + size, -size, -size, _w, + size, size, -size, _w, - size, -size, -size, 0.0f, - size, size, size, 0.0f, - size, -size, size, 0.0f, - size, -size, -size, 0.0f, - size, size, -size, 0.0f, - size, size, size, 0.0f, + size, -size, -size, _w, + size, size, size, _w, + size, -size, size, _w, + size, -size, -size, _w, + size, size, -size, _w, + size, size, size, _w, - -size, -size, -size, 0.0f, - -size, size, size, 0.0f, - -size, -size, size, 0.0f, - -size, -size, -size, 0.0f, - -size, size, -size, 0.0f, - -size, size, size, 0.0f, + -size, -size, -size, _w, + -size, size, size, _w, + -size, -size, size, _w, + -size, -size, -size, _w, + -size, size, -size, _w, + -size, size, size, _w, - -size, size, -size, 0.0f, - size, size, size, 0.0f, - -size, size, size, 0.0f, - -size, size, -size, 0.0f, - size, size, -size, 0.0f, - size, size, size, 0.0f, + -size, size, -size, _w, + size, size, size, _w, + -size, size, size, _w, + -size, size, -size, _w, + size, size, -size, _w, + size, size, size, _w, - -size, -size, -size, 0.0f, - size, -size, size, 0.0f, - -size, -size, size, 0.0f, - -size, -size, -size, 0.0f, - size, -size, -size, 0.0f, - size, -size, size, 0.0f, + -size, -size, -size, _w, + size, -size, size, _w, + -size, -size, size, _w, + -size, -size, -size, _w, + size, -size, -size, _w, + size, -size, size, _w, }; GLuint vertexPositionBuffer; glGenVertexArrays(1, &_boxArray); // generate array diff --git a/src/scenegraph/scenegraphnode.cpp b/src/scenegraph/scenegraphnode.cpp index 146f922a87..45f78eeb71 100644 --- a/src/scenegraph/scenegraphnode.cpp +++ b/src/scenegraph/scenegraphnode.cpp @@ -77,6 +77,25 @@ SceneGraphNode* SceneGraphNode::createFromDictionary(const ghoul::Dictionary& di } LDEBUG("Successfully create renderable for '" << result->_nodeName << "'"); } + + if (dictionary.hasKey("RenderableToggle")) { + std::string val; + dictionary.getValue("RenderableToggle", val); + + if(val.length() == 1) { + char c = std::toupper(val[0]); + int key = static_cast(c); + auto func = [result]() { + result->_renderableToggle = ! result->_renderableToggle; + }; + LERROR("Found key:" << key); + OsEng.interactionHandler().addKeyCallback(key, func); + } + + // LERROR("Found key:" << val); + // LERROR("key 1:" << static_cast('1')); + } + if (dictionary.hasKey(keyEphemeris)) { ghoul::Dictionary ephemerisDictionary; dictionary.getValue(keyEphemeris, ephemerisDictionary); @@ -116,6 +135,7 @@ SceneGraphNode::SceneGraphNode() , _ephemeris(new StaticEphemeris) , _renderable(nullptr) , _renderableVisible(false) + , _renderableToggle(true) , _boundingSphereVisible(false) { } @@ -212,7 +232,7 @@ void SceneGraphNode::render(const Camera* camera, const psc& parentPosition) if (!_boundingSphereVisible) { return; } - if (_renderableVisible) { + if (_renderableVisible && _renderableToggle) { // LDEBUG("Render"); _renderable->render(camera, thisPosition); } diff --git a/src/util/kameleonwrapper.cpp b/src/util/kameleonwrapper.cpp index 023f96a698..ce0acd5376 100644 --- a/src/util/kameleonwrapper.cpp +++ b/src/util/kameleonwrapper.cpp @@ -213,10 +213,18 @@ float* KameleonWrapper::getUniformSampledValues(const std::string& var, glm::siz dist = (dist / static_cast(bins)) * static_cast(stop); varMax = varMin + dist; + LDEBUG(var << "Min: " << varMin); + LDEBUG(var << "Max: " << varMax); for(int i = 0; i < size; ++i) { double normalizedVal = (doubleData[i]-varMin)/(varMax-varMin); data[i] = static_cast(glm::clamp(normalizedVal, 0.0, 1.0)); + if(data[i] < 0.0) { + LERROR("Datapoint " << i << " less than 0"); + } + if(data[i] > 1.0) { + LERROR("Datapoint " << i << " more than 1"); + } } // for(int i = 0; i < size; ++i) { From 258e62caa21457231652078c757eea970a6d7348 Mon Sep 17 00:00:00 2001 From: Jonas Strandstedt Date: Thu, 24 Jul 2014 16:12:37 -0400 Subject: [PATCH 46/49] Cleaned up before beginning ABuffer dynamic impl. - Added support for more keys in RenderableToggle - Switched to Fixed ABuffer (needs to be fixed) - Removed commented code --- include/openspace/engine/openspaceengine.h | 2 +- shaders/ABuffer/abufferResolveFragment.glsl | 210 ++++++-------------- shaders/ABuffer/abufferSort.hglsl | 3 +- src/abuffer/abuffer.cpp | 8 +- src/scenegraph/scenegraphnode.cpp | 48 ++++- 5 files changed, 110 insertions(+), 161 deletions(-) diff --git a/include/openspace/engine/openspaceengine.h b/include/openspace/engine/openspaceengine.h index 3e1759955d..8e6d8da45b 100644 --- a/include/openspace/engine/openspaceengine.h +++ b/include/openspace/engine/openspaceengine.h @@ -42,7 +42,7 @@ #define ABUFFER_SINGLE_LINKED 1 #define ABUFFER_FIXED 2 #define ABUFFER_DYNAMIC 3 -#define ABUFFER_IMPLEMENTATION ABUFFER_SINGLE_LINKED +#define ABUFFER_IMPLEMENTATION ABUFFER_FIXED namespace openspace { diff --git a/shaders/ABuffer/abufferResolveFragment.glsl b/shaders/ABuffer/abufferResolveFragment.glsl index 1eb46ac089..6c3245cdff 100644 --- a/shaders/ABuffer/abufferResolveFragment.glsl +++ b/shaders/ABuffer/abufferResolveFragment.glsl @@ -28,16 +28,29 @@ // Settings // ================================================================================ #pragma openspace insert SETTINGS -#define MAX_FRAGMENTS 16 -// #define SHOWFUNC -// #define JITTERING -#define SAMPLEFIRSTVOLUME -// #define COLORNORMALIZATION +// Select type of depth calculations +#define PSCDEPTH 1 +#define ZDEPTH 2 +#define ZTYPE ZDEPTH + +// Maximum number of fragments +#define MAX_FRAGMENTS 16 // The size of the local fragment list +// #define VISUALIZE_TRANSFERFUNCTIONS // +#define USE_JITTERING // +// #define USE_COLORNORMALIZATION // + +// If you need to render a volume box but not sample the volume (debug purpose) +// #define SKIP_VOLUME_0 +// #define SKIP_VOLUME_1 +// #define SKIP_VOLUME_2 +// #define SKIP_VOLUME_3 + +// constants +const float stepSize = 0.01; +const float samplingRate = 1.0; +uniform float ALPHA_LIMIT = 0.99; -#define PSCDEPTH 1 -#define ZDEPTH 2 -#define ZTYPE ZDEPTH // Math defintions #define M_E 2.7182818284590452354 @@ -46,7 +59,6 @@ #define M_LN2 0.69314718055994530942 /* log_e 2 */ #define M_LN10 2.30258509299404568402 /* log_e 10 */ #define M_PI 3.14159265358979323846 /* pi */ -// #define M_PI 3.141592653589793238462643383279 /* pi */ #define M_PI_2 1.57079632679489661923 /* pi/2 */ #define M_PI_4 0.78539816339744830962 /* pi/4 */ #define M_1_PI 0.31830988618379067154 /* 1/pi */ @@ -54,17 +66,10 @@ #define M_2_SQRTPI 1.12837916709551257390 /* 2/sqrt(pi) */ #define M_SQRT2 1.41421356237309504880 /* sqrt(2) */ #define M_SQRT1_2 0.70710678118654752440 /* 1/sqrt(2) */ - -const float stepSize = 0.01; -const float samplingRate = 1.0; - -// uniform int SCREEN_WIDTH; -// uniform int SCREEN_HEIGHT; -uniform float ALPHA_LIMIT = 0.99; -uniform float EPSILON = 0.01; +#define M_SQRT1_3 0.57735026919 /* 1/sqrt(3) */ in vec2 texCoord; -out vec4 color; +out vec4 out_color; // ================================================================================ // Headers, @@ -72,6 +77,30 @@ out vec4 color; // ================================================================================ #pragma openspace insert HEADERS +// ================================================================================ +// The ABuffer specific includes and definitions +// ================================================================================ +#include "abufferStruct.hglsl" +ABufferStruct_t fragments[MAX_FRAGMENTS]; + +#if MAX_VOLUMES > 0 + vec3 volume_direction[MAX_VOLUMES]; + float volume_length[MAX_VOLUMES]; + vec3 volume_position[MAX_VOLUMES]; + int volumes_in_fragment[MAX_VOLUMES]; + int volume_count = 0; + + #if ZTYPE == ZDEPTH + vec2 volume_zlength[MAX_VOLUMES]; + #elif ZTYPE == PSCDEPTH + float volume_zlength[MAX_VOLUMES]; + #endif +#endif +#include "abufferSort.hglsl" + +// ================================================================================ +// Helper functions functions +// ================================================================================ vec3 CartesianToSpherical(vec3 _cartesian) { // Put cartesian in [-1..1] range first vec3 cartesian = vec3(-1.0,-1.0,-1.0) + _cartesian * 2.0f; @@ -83,42 +112,15 @@ vec3 CartesianToSpherical(vec3 _cartesian) { theta = phi = 0.0; } else { theta = acos(cartesian.z/r) / M_PI; - // float diff = -.0f; phi = (M_PI + atan(cartesian.y, cartesian.x)) / (2.0*M_PI ); - // phi = (M_PI+radians(diff) + atan(cartesian.y, cartesian.x)) / (2.0*M_PI+radians(diff) ); - // phi = (M_PI + atan(cartesian.x, cartesian.y)) / (2.0*M_PI); } - // r *= 0.57735026919; - r = r / sqrt(3.0f); + r *= M_SQRT1_3; + // r = r / sqrt(3.0f); // Sampler ignores w component - // return vec3(r, phi, theta); return vec3(r, theta, phi); - // return vec3(r, phi*0.7, theta); } -// ================================================================================ -// The ABuffer specific includes and definitions -// ================================================================================ -#include "abufferStruct.hglsl" -ABufferStruct_t fragments[MAX_FRAGMENTS]; - -#if MAX_VOLUMES > 0 -vec3 volume_direction[MAX_VOLUMES]; -float volume_length[MAX_VOLUMES]; -vec3 volume_position[MAX_VOLUMES]; - -#if ZTYPE == ZDEPTH - vec2 volume_zlength[MAX_VOLUMES]; -#elif ZTYPE == PSCDEPTH - float volume_zlength[MAX_VOLUMES]; -#endif -#endif -#include "abufferSort.hglsl" - -// ================================================================================ -// Blend functions -// ================================================================================ vec4 blend(vec4 src, vec4 dst) { vec4 o; o.a = src.a + dst.a * (1.0f - src.a); @@ -133,18 +135,6 @@ void blendStep(inout vec4 dst, in vec4 src, in float stepSize) { dst.rgb = dst.rgb + (1.0 - dst.a) * src.a * src.rgb; dst.a = dst.a + (1.0 -dst.a) * src.a; } -/* -//Color geometry -void blendGeometry(inout vec4 color, ABufferStruct_t frag) { - //vec4 c; - //c.rg = unpackHalf2x16(frag.rg); - //c.ba = unpackHalf2x16(frag.ba); - vec4 c = _col_(frag); - c.a = clamp(c.a, 0.0,1.0); - blend(color, c, 0.01); - return; -} -*/ float volumeRaycastingDistance(in int id, in ABufferStruct_t startFrag, in ABufferStruct_t endFrag) { #if ZTYPE == ZDEPTH @@ -167,19 +157,6 @@ float volumeRaycastingDistance(in int id, in ABufferStruct_t startFrag, in ABuff #endif } -float globz(float z) { - return z; - // return log(2.0*z-1.0); - // return exp(2.0*z-1.0); - // const float zNear = 0.1f; - // const float zFar = 100.0f; - // float z_b = z; - // float z_n = 2.0 * z_b - 1.0; - // float z_e = 2.0 * zNear * zFar / (zFar + zNear - z_n * (zFar - zNear)); - // return z_e; - // return (2.0 * z - near - far) / (far - near); -} - vec4 calculate_final_color(uint frag_count) { // volumeStepSize[volID] = 0.01; int currentVolumeBitmask = 0; @@ -208,94 +185,37 @@ vec4 calculate_final_color(uint frag_count) { #if MAX_VOLUMES > 0 if(currentVolumeBitmask > 0) { - int volbit = currentVolumeBitmask; - int endbittype = int(_type_(endFrag)); - if(endbittype > 0) - volbit = volbit ^ (1 << (endbittype-1)); - // int volID = type -1; - // int volID = type-1; int volID; - - // TODO: Fix this non-working normalization for volumes with different stepsize float myMaxSteps = 0.0000001; - float vlength; - for(int v = 0; v < MAX_VOLUMES; ++v) { - if((currentVolumeBitmask & (1 << v)) > 0) { - - // float l = volume_length[v]/volumeStepSize[v]; - // if(myMaxSteps < l) { - // myMaxSteps = l; - // volID = v; - // } - float l = volumeRaycastingDistance(v, startFrag, endFrag); - // myMaxSteps = max(myMaxSteps, L/volumeStepSizeOriginal[v]); - myMaxSteps = max(myMaxSteps, l/volumeStepSizeOriginal[v]); - - // if((volbit & (1 << v)) > 0) - // volID = v; - // if(volbit == 0) - // volID = v; - // if(type - 1 != v && type == endbittype) - // volID = v; - - // if(volID < 0) volID = v; - // volID = v; + if(volume_count > 1) { + for(int v = 0; v < volume_count; ++v) { + int vol = volumes_in_fragment[v]; + float l = volumeRaycastingDistance(vol, startFrag, endFrag); + myMaxSteps = max(myMaxSteps, l/volumeStepSizeOriginal[vol]); } - } - // for(int v = 0; v < MAX_VOLUMES; ++v) { - // if((currentVolumeBitmask & (1 << v)) > 0) { - // float aaa = volume_length[v]/myMaxSteps; - // volumeStepSize[v] = volumeStepSizeOriginal[v]*vec3(aaa); - // } - // } - // float myMaxSteps = stepSize; - // for(int v = 0; v < MAX_VOLUMES; ++v) { - // if((currentVolumeBitmask & (1 << v)) > 0) { - // myMaxSteps = min(myMaxSteps, volumeStepSize[v]); - // } - // } - for(int v = 0; v < MAX_VOLUMES; ++v) { - if((currentVolumeBitmask & (1 << v)) > 0) { - // float aaa = myMaxSteps; - float l = volumeRaycastingDistance(v, startFrag, endFrag); + for(int v = 0; v < volume_count; ++v) { + int vol = volumes_in_fragment[v]; + float l = volumeRaycastingDistance(vol, startFrag, endFrag); float aaa = l/myMaxSteps; - // float aaa = volume_length[v]/myMaxSteps; - // volumeStepSize[v] = volumeStepSizeOriginal[v]*vec3(aaa); - // float aaa = volume_length[v]/volumeStepSizeOriginal[v]; - volumeStepSize[v] = aaa; - - // if(vlength >= volume_length[v]) { - // // vlength = volume_length[v]; - // const float S1 = volume_zlength[v].x; - // const float S2 = volume_zlength[v].y; - // const float L = S1 - S2; - // vlength = volume_length[v]; - // vlength = L; - // volID = v; - // } - // if(volID < 0) volID = v; - volID = v; + volumeStepSize[vol] = aaa; + volID = vol; } + } else { + volID = type -1; } - float l = volumeRaycastingDistance(volID, startFrag, endFrag); int max_iterations = int(l / volumeStepSize[volID]); // TransferFunction vec4 color = vec4(0); for(int k = 0; k < max_iterations && final_color.a < ALPHA_LIMIT && k < LOOP_LIMIT; ++k) { - //while(p < l && iterations < LOOP_LIMIT) { #pragma openspace insert SAMPLERCALLS - //final_color = blend(final_color, color*stepSize); - //volume_position[volID] += volume_direction[volID]*volumeStepSize[volID]; - //p+= stepSize; - //++iterations; } } @@ -324,7 +244,7 @@ vec4 calculate_final_color(uint frag_count) { // ================================================================================ // Transferfunction visualizer // ================================================================================ -#ifdef SHOWFUNC +#ifdef VISUALIZE_TRANSFERFUNCTIONS #pragma openspace insert TRANSFERFUNC #endif @@ -343,7 +263,7 @@ vec4 calculate_final_color(uint frag_count) { // final_color = vec4(1.0,1.0,1.0,1.0); // } -#ifdef COLORNORMALIZATION +#ifdef USE_COLORNORMALIZATION final_color.rgb = final_color.rgb * final_color.a; final_color.a = 1.0; #endif @@ -356,10 +276,10 @@ vec4 calculate_final_color(uint frag_count) { // Main function // ================================================================================ void main() { - color = vec4(texCoord,0.0,1.0); + out_color = vec4(texCoord,0.0,1.0); int frag_count = build_local_fragments_list(); sort_fragments_list(frag_count); - color = calculate_final_color(frag_count); + out_color = calculate_final_color(frag_count); } // ================================================================================ diff --git a/shaders/ABuffer/abufferSort.hglsl b/shaders/ABuffer/abufferSort.hglsl index 5d05460117..71acc355b7 100644 --- a/shaders/ABuffer/abufferSort.hglsl +++ b/shaders/ABuffer/abufferSort.hglsl @@ -107,6 +107,7 @@ void sort_fragments_list(uint frag_count) { #endif start = false; } else { + volumes_in_fragment[volume_count++] = ii; vec3 dir = _col_(fragments[jj]).rgb - startColor; volume_position[ii] = startColor; volume_length[ii] = length(dir); @@ -118,7 +119,7 @@ void sort_fragments_list(uint frag_count) { #elif ZTYPE == PSCDEPTH volume_zlength[ii] = pscLength(_pos_(fragments[jj]), startPosition); #endif -#ifdef JITTERING +#ifdef USE_JITTERING if(volumeStepSize[ii] < volume_length[ii]) { // jittering float x = gl_FragCoord.x; diff --git a/src/abuffer/abuffer.cpp b/src/abuffer/abuffer.cpp index 42a7367721..920a87b24d 100644 --- a/src/abuffer/abuffer.cpp +++ b/src/abuffer/abuffer.cpp @@ -313,8 +313,7 @@ std::string ABuffer::openspaceSamplerCalls() { auto found2 = _samplers.at(i).find_first_of("(",found1); if(found1 != std::string::npos && found2 != std::string::npos) { std::string functionName = _samplers.at(i).substr(found1, found2 - found1); - if(i == 0) - samplercalls += "#ifdef SAMPLEFIRSTVOLUME\n"; + samplercalls += "#ifndef SKIP_VOLUME_"+std::to_string(i)+"\n"; samplercalls += "if((currentVolumeBitmask & (1 << " + std::to_string(i) + ")) == "+std::to_string(1 << i)+") {\n"; samplercalls += " vec4 c = " + functionName + "(final_color,volume_position[" + std::to_string(i) + "]);\n"; // samplercalls += " if(c.a < 0.1) { \n"; @@ -325,7 +324,7 @@ std::string ABuffer::openspaceSamplerCalls() { // samplercalls += " volumeStepSize[" + std::to_string(i) + "] = volumeStepSizeOriginal[" + std::to_string(i) + "]; \n"; // samplercalls += " //c = " + functionName + "(final_color,volume_position[" + std::to_string(i) + "]);\n"; // samplercalls += " } \n"; - samplercalls += " if(c.a > EPSILON)\n"; + // samplercalls += " if(c.a > EPSILON)\n"; samplercalls += " blendStep(final_color, c, volumeStepSize[" + std::to_string(i) + "]);\n"; // samplercalls += " blendStep(final_color, c, stepSize);\n"; // samplercalls += " float aaa = volume_length[i]/myMaxSteps;\n"; @@ -334,8 +333,7 @@ std::string ABuffer::openspaceSamplerCalls() { // pos[v] += vec4(ray[v].xyz*vec3(aaa),aaa); // samplercalls += " volume_position[" + std::to_string(i) + "] += volume_direction[" + std::to_string(i) + "]*volumeStepSize[" + std::to_string(i) + "];\n"; samplercalls += "}\n"; - if(i == 0) - samplercalls += "#endif\n"; + samplercalls += "#endif\n"; } diff --git a/src/scenegraph/scenegraphnode.cpp b/src/scenegraph/scenegraphnode.cpp index 45f78eeb71..c62f15f8f1 100644 --- a/src/scenegraph/scenegraphnode.cpp +++ b/src/scenegraph/scenegraphnode.cpp @@ -40,6 +40,8 @@ #include #include +#include + namespace { const std::string _loggerCat = "SceneGraphNode"; } @@ -79,21 +81,49 @@ SceneGraphNode* SceneGraphNode::createFromDictionary(const ghoul::Dictionary& di } if (dictionary.hasKey("RenderableToggle")) { - std::string val; + std::string val = ""; dictionary.getValue("RenderableToggle", val); - if(val.length() == 1) { - char c = std::toupper(val[0]); - int key = static_cast(c); + if(val.length() > 0) { auto func = [result]() { result->_renderableToggle = ! result->_renderableToggle; }; - LERROR("Found key:" << key); - OsEng.interactionHandler().addKeyCallback(key, func); - } + int key = SGCT_KEY_UNKNOWN; - // LERROR("Found key:" << val); - // LERROR("key 1:" << static_cast('1')); + if(val.length() == 1) { + char c = std::toupper(val[0]); + key = static_cast(c); + } else if (boost::iequals(val, "left")) { + key = SGCT_KEY_LEFT; + } else if (boost::iequals(val, "right")) { + key = SGCT_KEY_RIGHT; + } else if (boost::iequals(val, "up")) { + key = SGCT_KEY_UP; + } else if (boost::iequals(val, "down")) { + key = SGCT_KEY_DOWN; + } else if (boost::iequals(val, "space")) { + key = SGCT_KEY_SPACE; + } else if (boost::iequals(val, "enter")) { + key = SGCT_KEY_ENTER; + } else if (boost::iequals(val, "backspace")) { + key = SGCT_KEY_BACKSPACE; + } else if (boost::iequals(val, "del")) { + key = SGCT_KEY_DEL; + } else if (boost::iequals(val, "delete")) { + key = SGCT_KEY_DELETE; + } else { + // Loop through all F keys + for(int i = 0; i < 25; ++i) { + std::string stringKey = "F" + std::to_string(i+1); + if(boost::iequals(val, stringKey)) { + key = SGCT_KEY_F1 + i; + } + } + } + + if(key != SGCT_KEY_UNKNOWN) + OsEng.interactionHandler().addKeyCallback(key, func); + } } if (dictionary.hasKey(keyEphemeris)) { From 3006c304860c8896abfacb7dfa5d776923c09901 Mon Sep 17 00:00:00 2001 From: Jonas Strandstedt Date: Mon, 28 Jul 2014 15:53:14 -0400 Subject: [PATCH 47/49] Added video export mode --- config/sgct/single.xml | 9 +++++++-- include/openspace/engine/openspaceengine.h | 7 ++++++- src/engine/openspaceengine.cpp | 23 ++++++++++++++++++++++ src/rendering/renderengine.cpp | 6 ++++-- src/scenegraph/scenegraphnode.cpp | 2 ++ 5 files changed, 42 insertions(+), 5 deletions(-) diff --git a/config/sgct/single.xml b/config/sgct/single.xml index 3ec20dd5db..eec3b163c1 100644 --- a/config/sgct/single.xml +++ b/config/sgct/single.xml @@ -1,12 +1,17 @@ - + - + + + + + + diff --git a/include/openspace/engine/openspaceengine.h b/include/openspace/engine/openspaceengine.h index 8e6d8da45b..dae55381ab 100644 --- a/include/openspace/engine/openspaceengine.h +++ b/include/openspace/engine/openspaceengine.h @@ -42,7 +42,9 @@ #define ABUFFER_SINGLE_LINKED 1 #define ABUFFER_FIXED 2 #define ABUFFER_DYNAMIC 3 -#define ABUFFER_IMPLEMENTATION ABUFFER_FIXED +#define ABUFFER_IMPLEMENTATION ABUFFER_SINGLE_LINKED + +// #define OPENSPACE_VIDEO_EXPORT namespace openspace { @@ -90,6 +92,9 @@ private: ghoul::Dictionary* _configurationManager; InteractionHandler* _interactionHandler; RenderEngine* _renderEngine; +#ifdef OPENSPACE_VIDEO_EXPORT + bool _doVideoExport; +#endif #ifdef FLARE_ONLY Flare* _flare; #endif diff --git a/src/engine/openspaceengine.cpp b/src/engine/openspaceengine.cpp index 1ec31e84ce..952f20b03e 100644 --- a/src/engine/openspaceengine.cpp +++ b/src/engine/openspaceengine.cpp @@ -224,6 +224,8 @@ bool OpenSpaceEngine::initialize() glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); GLFWwindow* win = sgct::Engine::instance()->getActiveWindowPtr()->getWindowHandle(); glfwSwapBuffers(win); + int samples = sqrt(sgct::Engine::instance()->getActiveWindowPtr()->getNumberOfAASamples()); + LDEBUG("samples: " << samples); int x1, xSize, y1, ySize; sgct::Engine::instance()->getActiveWindowPtr()->getCurrentViewportPixelCoords(x1, y1, xSize, ySize); @@ -298,6 +300,10 @@ bool OpenSpaceEngine::initialize() DeviceIdentifier::ref().scanDevices(); _engine->_interactionHandler->connectDevices(); +#ifdef OPENSPACE_VIDEO_EXPORT + LINFO("OpenSpace compiled with video export; press Print Screen to start/stop recording"); +#endif + return true; } @@ -378,6 +384,17 @@ void OpenSpaceEngine::postDraw() if (sgct::Engine::instance()->isMaster()) { _interactionHandler->unlockControls(); } +#ifdef OPENSPACE_VIDEO_EXPORT + float speed = 0.01; + glm::vec3 euler(0.0, speed, 0.0); + glm::quat rot = glm::quat(euler); + glm::vec3 euler2(0.0, -speed, 0.0); + glm::quat rot2 = glm::quat(euler2); + _interactionHandler->orbit(rot); + _interactionHandler->rotate(rot2); + if(_doVideoExport) + sgct::Engine::instance()->takeScreenshot(); +#endif #ifdef FLARE_ONLY _flare->postDraw(); #endif @@ -388,6 +405,12 @@ void OpenSpaceEngine::keyboardCallback(int key, int action) if (sgct::Engine::instance()->isMaster()) { _interactionHandler->keyboardCallback(key, action); } +#ifdef OPENSPACE_VIDEO_EXPORT + // LDEBUG("key: " << key); + // LDEBUG("SGCT_KEY_PRINT_SCREEN: " << SGCT_KEY_PRINT_SCREEN); + if(action == SGCT_PRESS && key == SGCT_KEY_PRINT_SCREEN) + _doVideoExport = !_doVideoExport; +#endif #ifdef FLARE_ONLY _flare->keyboard(key, action); #endif diff --git a/src/rendering/renderengine.cpp b/src/rendering/renderengine.cpp index a4aeee8566..349df7d373 100644 --- a/src/rendering/renderengine.cpp +++ b/src/rendering/renderengine.cpp @@ -186,7 +186,8 @@ void RenderEngine::render() _sceneGraph->render(_mainCamera); _abuffer->postRender(); _abuffer->resolve(); -/* + +#ifndef OPENSPACE_VIDEO_EXPORT // Print some useful information on the master viewport if (sgct::Engine::instance()->isMaster()) { // Apple usually has retina screens @@ -222,7 +223,8 @@ void RenderEngine::render() sgct_text::FontManager::instance()->getFont("SGCTFont", FONT_SIZE), FONT_SIZE, FONT_SIZE * 2, "Scaling: (%.10f, %.2f)", scaling[0], scaling[1]); } - */ +#endif + } SceneGraph* RenderEngine::sceneGraph() diff --git a/src/scenegraph/scenegraphnode.cpp b/src/scenegraph/scenegraphnode.cpp index c62f15f8f1..14a5d80be1 100644 --- a/src/scenegraph/scenegraphnode.cpp +++ b/src/scenegraph/scenegraphnode.cpp @@ -225,6 +225,7 @@ void SceneGraphNode::evaluate(const Camera* camera, const psc& parentPosition) _boundingSphereVisible = false; _renderableVisible = false; +#ifndef OPENSPACE_VIDEO_EXPORT // check if camera is outside the node boundingsphere if (toCamera.length() > _boundingSphere) { // check if the boudningsphere is visible before avaluating children @@ -235,6 +236,7 @@ void SceneGraphNode::evaluate(const Camera* camera, const psc& parentPosition) return; } } +#endif // inside boudningsphere or parts of the sphere is visible, individual // children needs to be evaluated From 98677d99a7a7015d40a080754927ae754bb1bb66 Mon Sep 17 00:00:00 2001 From: Jonas Strandstedt Date: Tue, 29 Jul 2014 09:20:58 -0400 Subject: [PATCH 48/49] Added presentation scene --- openspace-data | 2 +- openspace.cfg | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/openspace-data b/openspace-data index 2642f7b929..97facd7529 160000 --- a/openspace-data +++ b/openspace-data @@ -1 +1 @@ -Subproject commit 2642f7b929d2fb6573f81ecec5d2823ef5506092 +Subproject commit 97facd7529857a70a49b3b34d47df2b9d4311ba8 diff --git a/openspace.cfg b/openspace.cfg index 4becaf05a8..bd8e9588fa 100644 --- a/openspace.cfg +++ b/openspace.cfg @@ -6,7 +6,8 @@ return { SHADERS = "${BASE_PATH}/shaders", OPENSPACE_DATA = "${BASE_PATH}/openspace-data", TESTDIR = "${BASE_PATH}/src/tests", - SCENEPATH = "${OPENSPACE_DATA}/scene", + -- SCENEPATH = "${OPENSPACE_DATA}/scene", + SCENEPATH = "${OPENSPACE_DATA}/ABufferVolumes", CONFIG = "${BASE_PATH}/config" }, SGCTConfig = "${SGCT}/single.xml", From 033880080f4fd0958cf6f53e577e754d0ee01218 Mon Sep 17 00:00:00 2001 From: Hans-Christian Helltegen Date: Tue, 29 Jul 2014 09:39:08 -0400 Subject: [PATCH 49/49] Added Ashers seedpoints --- openspace-data | 2 +- src/rendering/renderablefieldlines.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/openspace-data b/openspace-data index 2642f7b929..6548d06674 160000 --- a/openspace-data +++ b/openspace-data @@ -1 +1 @@ -Subproject commit 2642f7b929d2fb6573f81ecec5d2823ef5506092 +Subproject commit 6548d06674595fea03588d82d84ba606f4d132f0 diff --git a/src/rendering/renderablefieldlines.cpp b/src/rendering/renderablefieldlines.cpp index 8f9d68bca7..c750ddcd9a 100644 --- a/src/rendering/renderablefieldlines.cpp +++ b/src/rendering/renderablefieldlines.cpp @@ -217,9 +217,9 @@ void RenderableFieldlines::render(const Camera* camera, const psc& thisPosition) glBindVertexArray(_VAO); glMultiDrawArrays(GL_LINE_STRIP, &_lineStart[0], &_lineCount[0], _lineStart.size()); - // ------ SEEDPOINTS ----------------- - glBindVertexArray(_seedpointVAO); - glMultiDrawArrays(GL_POINTS, &_lineStart[0], &_lineCount[0], _seedPoints.size()); +// // ------ SEEDPOINTS ----------------- +// glBindVertexArray(_seedpointVAO); +// glMultiDrawArrays(GL_POINTS, &_lineStart[0], &_lineCount[0], _seedPoints.size()); glBindVertexArray(0); // Deactivate shader