diff --git a/examples/osgvolume/osgvolume.cpp b/examples/osgvolume/osgvolume.cpp index 59aed5237..9fcfbbba7 100644 --- a/examples/osgvolume/osgvolume.cpp +++ b/examples/osgvolume/osgvolume.cpp @@ -59,6 +59,14 @@ typedef std::vector< osg::ref_ptr > ImageList; +enum ShadingModel +{ + Standard, + Light, + Isosurface, + MaximumIntensityProjection +}; + // example ReadOperator // struct ReadOperator // { @@ -802,13 +810,14 @@ class FollowMouseCallback : public osgGA::GUIEventHandler, public osg::StateSet: }; -osg::Node* createShaderModel(osg::ref_ptr& image_3d, +osg::Node* createShaderModel(ShadingModel shadingModel, + osg::ref_ptr& image_3d, osg::Image* normalmap_3d, osg::TransferFunction1D* tf, osg::Texture::InternalFormatMode internalFormatMode, float xSize, float ySize, float zSize, float /*xMultiplier*/, float /*yMultiplier*/, float /*zMultiplier*/, - unsigned int /*numSlices*/=500, float /*sliceEnd*/=1.0f, float alphaFuncValue=0.02f, bool maximumIntensityProjection = false) + unsigned int /*numSlices*/=500, float /*sliceEnd*/=1.0f, float alphaFuncValue=0.02f) { osg::Texture::FilterMode minFilter = osg::Texture::LINEAR; osg::Texture::FilterMode magFilter = osg::Texture::LINEAR; @@ -840,7 +849,6 @@ osg::Node* createShaderModel(osg::ref_ptr& image_3d, #include "volume_vert.cpp" program->addShader(new osg::Shader(osg::Shader::VERTEX, volume_vert)); } - if (!(normalmap_3d && tf)) { @@ -871,7 +879,88 @@ osg::Node* createShaderModel(osg::ref_ptr& image_3d, } - if (normalmap_3d) + if (shadingModel==MaximumIntensityProjection) + { + if (tf) + { + osg::Texture1D* texture1D = new osg::Texture1D; + texture1D->setImage(tf->getImage()); + stateset->setTextureAttributeAndModes(1,texture1D,osg::StateAttribute::ON); + + osg::Shader* fragmentShader = osgDB::readShaderFile(osg::Shader::FRAGMENT, "volume_tf_mip.frag"); + if (fragmentShader) + { + program->addShader(fragmentShader); + } + else + { + #include "volume_tf_mip_frag.cpp" + program->addShader(new osg::Shader(osg::Shader::FRAGMENT, volume_tf_mip_frag)); + } + + osg::Uniform* tfTextureSampler = new osg::Uniform("tfTexture",1); + stateset->addUniform(tfTextureSampler); + + } + else + { + osg::Shader* fragmentShader = osgDB::readShaderFile(osg::Shader::FRAGMENT, "volume_mip.frag"); + if (fragmentShader) + { + program->addShader(fragmentShader); + } + else + { + #include "volume_mip_frag.cpp" + program->addShader(new osg::Shader(osg::Shader::FRAGMENT, volume_mip_frag)); + } + } + } + else if (shadingModel==Isosurface) + { + osg::Uniform* normalMapSampler = new osg::Uniform("normalMap",1); + stateset->addUniform(normalMapSampler); + + osg::Texture3D* normalMap = new osg::Texture3D; + normalMap->setImage(normalmap_3d); + stateset->setTextureAttributeAndModes(1,normalMap,osg::StateAttribute::ON); + + if (tf) + { + osg::Texture1D* texture1D = new osg::Texture1D; + texture1D->setImage(tf->getImage()); + stateset->setTextureAttributeAndModes(0,texture1D,osg::StateAttribute::ON); + + osg::Shader* fragmentShader = osgDB::readShaderFile(osg::Shader::FRAGMENT, "volume-tf-iso.frag"); + if (fragmentShader) + { + program->addShader(fragmentShader); + } + else + { + #include "volume_tf_iso_frag.cpp" + program->addShader(new osg::Shader(osg::Shader::FRAGMENT, volume_tf_iso_frag)); + } + + osg::Uniform* tfTextureSampler = new osg::Uniform("tfTexture",0); + stateset->addUniform(tfTextureSampler); + + } + else + { + osg::Shader* fragmentShader = osgDB::readShaderFile(osg::Shader::FRAGMENT, "volume_iso.frag"); + if (fragmentShader) + { + program->addShader(fragmentShader); + } + else + { + #include "volume_iso_frag.cpp" + program->addShader(new osg::Shader(osg::Shader::FRAGMENT, volume_iso_frag)); + } + } + } + else if (normalmap_3d) { osg::notify(osg::NOTICE)<<"Setting up normalmapping shader"<& image_3d, return root; } -osg::Node* createModel(osg::ref_ptr& image_3d, +osg::Node* createModel(ShadingModel shadeModel, + osg::ref_ptr& image_3d, osg::ref_ptr& normalmap_3d, osg::Texture::InternalFormatMode internalFormatMode, float xSize, float ySize, float zSize, @@ -1133,7 +1223,7 @@ osg::Node* createModel(osg::ref_ptr& image_3d, material->setDiffuse(osg::Material::FRONT_AND_BACK,osg::Vec4(1.0f,1.0f,1.0f,1.0f)); stateset->setAttributeAndModes(material); - if (maximumIntensityProjection) + if (shadeModel==MaximumIntensityProjection) { stateset->setAttribute(new osg::BlendFunc(osg::BlendFunc::ONE, osg::BlendFunc::ONE)); stateset->setAttribute(new osg::BlendEquation(osg::BlendEquation::RGBA_MAX)); @@ -1214,7 +1304,6 @@ osg::Node* createModel(osg::ref_ptr& image_3d, } else { - osg::ref_ptr normalmap_3d = createNormalMapTexture(image_3d.get()); osg::Texture3D* bump_texture3D = new osg::Texture3D; bump_texture3D->setResizeNonPowerOfTwoHint(false); bump_texture3D->setFilter(osg::Texture3D::MIN_FILTER,minFilter); @@ -1714,11 +1803,24 @@ int main( int argc, char **argv ) while (arguments.read("--alphaFunc",alphaFunc)) {} - bool createNormalMap = false; - while (arguments.read("-n")) createNormalMap=true; + + ShadingModel shadingModel = Standard; bool maximumIntensityProjection = false; - while(arguments.read("--mip")) maximumIntensityProjection = true; + while(arguments.read("--mip")) shadingModel = MaximumIntensityProjection; + + bool createNormalMap = false; + while (arguments.read("-n")) + { + shadingModel = Light; + createNormalMap=true; + } + + while (arguments.read("--isosurface")) + { + shadingModel = Isosurface; + createNormalMap=true; + } float xSize=1.0f, ySize=1.0f, zSize=1.0f; while (arguments.read("--xSize",xSize)) {} @@ -2009,20 +2111,22 @@ int main( int argc, char **argv ) if (useShader) { - rootNode = createShaderModel(image_3d, normalmap_3d.get(), + rootNode = createShaderModel(shadingModel, + image_3d, normalmap_3d.get(), (gpuTransferFunction ? transferFunction.get() : 0), internalFormatMode, xSize, ySize, zSize, xMultiplier, yMultiplier, zMultiplier, - numSlices, sliceEnd, alphaFunc, maximumIntensityProjection); + numSlices, sliceEnd, alphaFunc); } else { - rootNode = createModel(image_3d, normalmap_3d, + rootNode = createModel(shadingModel, + image_3d, normalmap_3d, internalFormatMode, xSize, ySize, zSize, xMultiplier, yMultiplier, zMultiplier, - numSlices, sliceEnd, alphaFunc, maximumIntensityProjection); + numSlices, sliceEnd, alphaFunc); } if (!outputFile.empty()) diff --git a/examples/osgvolume/volume_iso_frag.cpp b/examples/osgvolume/volume_iso_frag.cpp new file mode 100644 index 000000000..9268bb96c --- /dev/null +++ b/examples/osgvolume/volume_iso_frag.cpp @@ -0,0 +1,105 @@ +char volume_iso_frag[] = "uniform sampler3D baseTexture;\n" + "uniform sampler3D normalMap;\n" + "uniform float sampleDensity;\n" + "uniform float transparency;\n" + "uniform float alphaCutOff;\n" + "\n" + "varying vec4 cameraPos;\n" + "varying vec4 vertexPos;\n" + "varying mat4 texgen;\n" + "\n" + "void main(void)\n" + "{ \n" + "\n" + " vec3 t0 = (texgen * vertexPos).xyz;\n" + " vec3 te = (texgen * cameraPos).xyz;\n" + "\n" + " vec3 eyeDirection = normalize(te-t0);\n" + "\n" + " if (te.x>=0.0 && te.x<=1.0 &&\n" + " te.y>=0.0 && te.y<=1.0 &&\n" + " te.z>=0.0 && te.z<=1.0)\n" + " {\n" + " // do nothing... te inside volume\n" + " }\n" + " else\n" + " {\n" + " if (te.x<0.0)\n" + " {\n" + " float r = -te.x / (t0.x-te.x);\n" + " te = te + (t0-te)*r;\n" + " }\n" + "\n" + " if (te.x>1.0)\n" + " {\n" + " float r = (1.0-te.x) / (t0.x-te.x);\n" + " te = te + (t0-te)*r;\n" + " }\n" + "\n" + " if (te.y<0.0)\n" + " {\n" + " float r = -te.y / (t0.y-te.y);\n" + " te = te + (t0-te)*r;\n" + " }\n" + "\n" + " if (te.y>1.0)\n" + " {\n" + " float r = (1.0-te.y) / (t0.y-te.y);\n" + " te = te + (t0-te)*r;\n" + " }\n" + "\n" + " if (te.z<0.0)\n" + " {\n" + " float r = -te.z / (t0.z-te.z);\n" + " te = te + (t0-te)*r;\n" + " }\n" + "\n" + " if (te.z>1.0)\n" + " {\n" + " float r = (1.0-te.z) / (t0.z-te.z);\n" + " te = te + (t0-te)*r;\n" + " }\n" + " }\n" + "\n" + " const float max_iteratrions = 2048.0;\n" + " float num_iterations = ceil(length(te-t0)/sampleDensity);\n" + " if (num_iterations<2.0) num_iterations = 2.0;\n" + "\n" + " if (num_iterations>max_iteratrions) \n" + " {\n" + " num_iterations = max_iteratrions;\n" + " }\n" + "\n" + " vec3 deltaTexCoord=(te-t0)/float(num_iterations-1.0);\n" + " vec3 texcoord = t0;\n" + "\n" + " vec4 fragColor = vec4(0.0, 0.0, 0.0, 0.0); \n" + " while(num_iterations>0.0)\n" + " {\n" + " vec4 normal = texture3D( normalMap, texcoord);\n" + " vec4 color = texture3D( baseTexture, texcoord);\n" + "\n" + " normal.x = normal.x*2.0-1.0;\n" + " normal.y = normal.y*2.0-1.0;\n" + " normal.z = normal.z*2.0-1.0;\n" + " \n" + " float lightScale = 0.1 + max(dot(normal.xyz, eyeDirection), 0.0);\n" + " color.x *= lightScale;\n" + " color.y *= lightScale;\n" + " color.z *= lightScale;\n" + "\n" + " float r = normal[3];\n" + " if (r>alphaCutOff)\n" + " {\n" + " fragColor = vec4(lightScale, lightScale, lightScale, 1.0);\n" + " }\n" + " texcoord += deltaTexCoord; \n" + "\n" + " --num_iterations;\n" + " }\n" + "\n" + " if (fragColor.w>1.0) fragColor.w = 1.0; \n" + " //if (fragColor.w=0.0 && te.x<=1.0 &&\n" + " te.y>=0.0 && te.y<=1.0 &&\n" + " te.z>=0.0 && te.z<=1.0)\n" + " {\n" + " // do nothing... te inside volume\n" + " }\n" + " else\n" + " {\n" + " if (te.x<0.0)\n" + " {\n" + " float r = -te.x / (t0.x-te.x);\n" + " te = te + (t0-te)*r;\n" + " }\n" + "\n" + " if (te.x>1.0)\n" + " {\n" + " float r = (1.0-te.x) / (t0.x-te.x);\n" + " te = te + (t0-te)*r;\n" + " }\n" + "\n" + " if (te.y<0.0)\n" + " {\n" + " float r = -te.y / (t0.y-te.y);\n" + " te = te + (t0-te)*r;\n" + " }\n" + "\n" + " if (te.y>1.0)\n" + " {\n" + " float r = (1.0-te.y) / (t0.y-te.y);\n" + " te = te + (t0-te)*r;\n" + " }\n" + "\n" + " if (te.z<0.0)\n" + " {\n" + " float r = -te.z / (t0.z-te.z);\n" + " te = te + (t0-te)*r;\n" + " }\n" + "\n" + " if (te.z>1.0)\n" + " {\n" + " float r = (1.0-te.z) / (t0.z-te.z);\n" + " te = te + (t0-te)*r;\n" + " }\n" + " }\n" + "\n" + " const float max_iteratrions = 2048.0;\n" + " float num_iterations = ceil(length(te-t0)/sampleDensity);\n" + " if (num_iterations<2.0) num_iterations = 2.0;\n" + "\n" + " if (num_iterations>max_iteratrions) \n" + " {\n" + " num_iterations = max_iteratrions;\n" + " }\n" + "\n" + " vec3 deltaTexCoord=(te-t0)/float(num_iterations-1.0);\n" + " vec3 texcoord = t0;\n" + "\n" + " vec4 fragColor = vec4(0.0, 0.0, 0.0, 0.0); \n" + " while(num_iterations>0.0)\n" + " {\n" + " vec4 color = texture3D( baseTexture, texcoord);\n" + " if (fragColor.w1.0) fragColor.w = 1.0; \n" + " if (fragColor.w=0.0 && te.x<=1.0 &&\n" + " te.y>=0.0 && te.y<=1.0 &&\n" + " te.z>=0.0 && te.z<=1.0)\n" + " {\n" + " // do nothing... te inside volume\n" + " }\n" + " else\n" + " {\n" + " if (te.x<0.0)\n" + " {\n" + " float r = -te.x / (t0.x-te.x);\n" + " te = te + (t0-te)*r;\n" + " }\n" + "\n" + " if (te.x>1.0)\n" + " {\n" + " float r = (1.0-te.x) / (t0.x-te.x);\n" + " te = te + (t0-te)*r;\n" + " }\n" + "\n" + " if (te.y<0.0)\n" + " {\n" + " float r = -te.y / (t0.y-te.y);\n" + " te = te + (t0-te)*r;\n" + " }\n" + "\n" + " if (te.y>1.0)\n" + " {\n" + " float r = (1.0-te.y) / (t0.y-te.y);\n" + " te = te + (t0-te)*r;\n" + " }\n" + "\n" + " if (te.z<0.0)\n" + " {\n" + " float r = -te.z / (t0.z-te.z);\n" + " te = te + (t0-te)*r;\n" + " }\n" + "\n" + " if (te.z>1.0)\n" + " {\n" + " float r = (1.0-te.z) / (t0.z-te.z);\n" + " te = te + (t0-te)*r;\n" + " }\n" + " }\n" + "\n" + " const float max_iteratrions = 2048.0;\n" + " float num_iterations = ceil(length(te-t0)/sampleDensity);\n" + " if (num_iterations<2.0) num_iterations = 2.0;\n" + " \n" + " if (num_iterations>max_iteratrions) \n" + " {\n" + " num_iterations = max_iteratrions;\n" + " }\n" + "\n" + " vec3 deltaTexCoord=(te-t0)/float(num_iterations-1.0);\n" + " vec3 texcoord = t0;\n" + "\n" + " vec4 fragColor = vec4(0.0, 0.0, 0.0, 0.0); \n" + " while(num_iterations>0.0)\n" + " {\n" + " float v = texture3D( baseTexture, texcoord).s;\n" + " vec4 color = texture1D( tfTexture, v);\n" + " if (alphaCutOff1.0) fragColor.w = 1.0; \n" + " if (fragColor.w=0.0 && te.x<=1.0 &&\n" + " te.y>=0.0 && te.y<=1.0 &&\n" + " te.z>=0.0 && te.z<=1.0)\n" + " {\n" + " // do nothing... te inside volume\n" + " }\n" + " else\n" + " {\n" + " if (te.x<0.0)\n" + " {\n" + " float r = -te.x / (t0.x-te.x);\n" + " te = te + (t0-te)*r;\n" + " }\n" + "\n" + " if (te.x>1.0)\n" + " {\n" + " float r = (1.0-te.x) / (t0.x-te.x);\n" + " te = te + (t0-te)*r;\n" + " }\n" + "\n" + " if (te.y<0.0)\n" + " {\n" + " float r = -te.y / (t0.y-te.y);\n" + " te = te + (t0-te)*r;\n" + " }\n" + "\n" + " if (te.y>1.0)\n" + " {\n" + " float r = (1.0-te.y) / (t0.y-te.y);\n" + " te = te + (t0-te)*r;\n" + " }\n" + "\n" + " if (te.z<0.0)\n" + " {\n" + " float r = -te.z / (t0.z-te.z);\n" + " te = te + (t0-te)*r;\n" + " }\n" + "\n" + " if (te.z>1.0)\n" + " {\n" + " float r = (1.0-te.z) / (t0.z-te.z);\n" + " te = te + (t0-te)*r;\n" + " }\n" + " }\n" + "\n" + " const float max_iteratrions = 2048.0;\n" + " float num_iterations = ceil(length(te-t0)/sampleDensity);\n" + " if (num_iterations<2.0) num_iterations = 2.0;\n" + " \n" + " if (num_iterations>max_iteratrions) \n" + " {\n" + " num_iterations = max_iteratrions;\n" + " }\n" + "\n" + " vec3 deltaTexCoord=(te-t0)/float(num_iterations-1.0);\n" + " vec3 texcoord = t0;\n" + "\n" + " vec4 fragColor = vec4(0.0, 0.0, 0.0, 0.0); \n" + " while(num_iterations>0.0)\n" + " {\n" + " float v = texture3D( baseTexture, texcoord).s;\n" + " vec4 color = texture1D( tfTexture, v);\n" + " if (fragColor.w1.0) fragColor.w = 1.0; \n" + " if (fragColor.w