Spherical surface displayed via TransparentColoredSurface module.
Display a triangular surface as transparent object with a pretty shader using conventional depth-sorting (NOT depth-peeling).
The most simple version of a surface rendered is demonstrated by MonochromeSurface .
#include <ocean/plankton/VPipeline.hpp> #include <ocean/GLvish/VGLRenderObject.hpp> #include <ocean/GLvish/BoundingBox.hpp> #include <ocean/GLvish/ArrayTypes.hpp> #include <ocean/GLvish/colors.hpp> #include <ocean/shrimp/VObjectStatus.hpp> #include <ocean/shrimp/VEnum.hpp> #include <ocean/eagle/PhysicalSpace.hpp> #include <field/Cell.hpp> #include <GL/fiberGL.hpp> #include <GL/FieldBuffer.hpp> #include <baseop/ExpandBBox.hpp> #include <eye/retina/VSkeletonRenderObject.hpp> #include <grid/types/TriangularSurface.hpp> #include <bundle/BundleProperty.hpp> #include <bone/GridActor.hpp> #include <GL/PartialElementRenderer.hpp> #include <GLvish/Programmable.hpp> #include <bone/FishField.hpp> #include <ocean/GLvish/Colormap.hpp> #include <baseop/GridField.hpp> using namespace Wizt; using namespace Fiber; using namespace Eagle; namespace { #define FSHADER_COLORMAP_NAME "ColormapTexture" class TransparentColoredSurface : public VSkeletonRenderObject, public Programmable { public: override string vertex_shader(VRenderContext&Context) const { return #include "TransparentColoredSurface.vcpp" ; } override string fragment_shader(VRenderContext&Context) const { return #include "TransparentColoredSurface.fcpp" ; } struct MyState : State, TriangularSurface { RefPtr<Field> ColorField; string ColorFieldName, ErrorMessage; using TriangularSurface::operator=; }; override RefPtr<State> newState() const { return new MyState(); } TypedSlot<double> Transparency, Shininess, Alpha, Speculartransparency; TypedSlot<Range> InputRange; TypedSlot<VColormap> Colormap; TypedSlot<Field> SurfaceColorField; enum { NumberOfInputFields = 1 }; // typedef LIST<double, LIST<float> > InputTypes; typedef LIST<double> InputTypes; TransparentColoredSurface(const string&name, int, const RefPtr<VCreationPreferences>&VP) : VGLRenderObject(name, DEFAULT_OBJECT, VP) , Fish<VObject>(this) , VSkeletonRenderObject(name, DEFAULT_OBJECT, VP) , Transparency(this, "transparency", 0.0, 0) , Shininess(this, "shininess", 0.5, 0) , Alpha(this, "alpha", 1.0, 2) , Speculartransparency(this, "speculartransparency", 0.0,3) , InputRange(this, "range", Range(0,1), 0 ) , Colormap(this, "colormap", NullPtr() ) , SurfaceColorField(this, "field" ) {} override void render(VGLRenderContext&Context) const; override bool update(VRequest&R, double precision); static string createChildname(const string&parent_name) { return "TransparentColoredSurface(" + parent_name + ")"; } }; bool TransparentColoredSurface::update(VRequest&Context, double precision) { FieldSelector FS; SurfaceColorField << Context >> FS; GridSelector GS; MyGrid << Context >> GS; GridField GF(GS, FS, getTime(Context) ); /* Fiber::Bundle::GridInfo_t GI = findMostRecentGrid( Context ); RefPtr<Grid> G = GI; if (!G) { G = FS.getGrid(); if (!G) { removeState(Context); return setStatusError(Context, "No Grid found."); } } */ RefPtr<MyState> S = myState(Context); *S = GF; if (!*S) return setStatusError(Context, "No surface available."); if (!S->CartesianVertices) return setStatusError(Context, "No vertices on the surface available."); S->ColorFieldName = FS(); S->ColorField = GF; if (S->ColorField) { puts("YAYYYYYYYY HAVE COLORFIELD"); printf("And it should have a name: %s\n", S->ColorFieldName.c_str() ); } else puts("NOPE. NO COLORFIELD"); setBoundingBall(Context, getBoundingBox( S->CoordField ) ); if (S->ErrorMessage.length()>0) return setStatusError(Context, S->ErrorMessage ); return setStatusInfo(Context, "Surface ready to render."); } struct TriangleRenderer : GL::PartialElementRenderer { RefPtr<TriangularSurface::CellArray_t> Cells; TriangleRenderer(const MemCore::RefPtr<Fiber::MemBase>&FieldCoordinates, const RefPtr<TriangularSurface::CellArray_t>&TriangleCells) : GL::PartialElementRenderer( FieldCoordinates, NullPtr() ) , Cells(TriangleCells) { assert( TriangleCells ); assert( Cells->getTypedStorage() ); const std::vector<TriangleCell>&Cls = Cells->getTypedStorage()->get_vector(); this->CurrentIBO = new IndexBuffer<TriangleCell>( Cls ); draw_mode = GL_TRIANGLES; } // TODO: Add modus with alpha clamping and depth buffer writing override void prefix() { glEnable(GL_DEPTH_TEST); // see depth buffer // glDepthMask(GL_FALSE); // but don't write to it glDepthMask(GL_TRUE); // and write to it glEnable(GL_NORMALIZE); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable( GL_BLEND ); } void postfix() { glDepthMask(GL_TRUE); } }; void TransparentColoredSurface::render(VGLRenderContext&Context) const { RefPtr<MyState> myState = getState(Context); if (!myState) return; myState->ErrorMessage = ""; TriangularSurface&Surface = *myState; if (!Surface) { myState->ErrorMessage = "Grid is not a surface"; return; } if (!Surface.CoordField) { printf("Did not find coordinates :( \n"); myState->ErrorMessage = "Did not find surface coordinates."; return; } if (!Surface.CellField) { printf("Did not find triangles :( \n"); myState->ErrorMessage = "Did not find triangles."; return; } if (!myState->CellField->getData() ) { printf("Did not find triangles indices :( \n"); myState->ErrorMessage = "Did not find triangle indices (no data in triangle field)"; return; } // // Check for a named color field. // RefPtr<Field> Colors = myState->ColorField; if (!Colors) { myState->ErrorMessage = "No such field: \"" + myState->ColorFieldName + "\""; return; } // // Generic OpenGL section, these settings affect all VBO's rendered later // glEnable(GL_LIGHTING); double Shine = 0.5; Shininess << Context >> Shine; glMaterialf( GL_FRONT, GL_SHININESS, Shine ); glMaterialf( GL_BACK , GL_SHININESS, Shine ); glMaterial( GL::FRONT_AND_BACK, GL::AMBIENT , makeColor( 0,0,.01,0) ); glMaterial( GL::FRONT_AND_BACK, GL::SPECULAR, makeColor( 0.5,0.5,.53, 0) ); glMaterial( GL::FRONT_AND_BACK, GL::EMISSION, makeColor( 0., 0.,0., 0) ); glColor4f(1,0,0, 0.5); glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); // glColorMaterial( GL_FRONT_AND_BACK, GL_DIFFUSE); // glEnable( GL_COLOR_MATERIAL ); // printf(">>>>> TransparentColoredSurface: RENDER cells for t=%ld, %lu Triangles\n", // myState->CellField->time_value(), Cells->nElements() ); RefPtr<Field> Tmp = Surface.getTriangleBaryCenters(); RefPtr<CreativeArrayBase> BaryCenters = Tmp->getCreator(); glEnable( GL_VERTEX_PROGRAM_TWO_SIDE ); RefPtr<GLProgram> MyProgram = CompileShader( Context, "TransparentColoredSurface" ); assert( MyProgram ); MyProgram->use(); Transparency << Context > MyProgram; Alpha << Context > MyProgram; Speculartransparency << Context > MyProgram; // // VBO Access via GLCache, // retrieve and re-use or generate new VBO. // // The caching mechanism is part of the "Visualization Cascade" and // described in the article: // // http://sciviz.cct.lsu.edu/papers/2009/VizCascade.pdf // string VBOKey = myState->ColorFieldName ; RefPtr<ValueSet> V;// = ScaleFactor(Context); RefPtr<VBO> myVBO; RefPtr<TriangleRenderer> MyTriangleRenderer; // // Colormap handling // VColormap Cmap; Colormap << Context >> Cmap; RefPtr<GLTexture1D> CMapTexture = new GLTexture1D(1); RefPtr<ValueSet> CmapValues = new ValueSet(Colormap(Context) ); TextureCreator&TC = Context[ *myState ][ this ][ CmapValues ]( TEXTURE() ); if (Cmap) { // true: clamp values, not repeating RefPtr<GLTexture1D> CmapTexture = Cmap->Enable(TC, 1, true); MyProgram->setUniformTexture( FSHADER_COLORMAP_NAME , *CmapTexture); } Range ColorMapRange(0,1); InputRange << Context >> ColorMapRange; // Set the data mapping as the INVERSE of the color map Range DataRange = ~ColorMapRange; unsigned ViewCacheSize = 1; try { myVBO = Context( *Surface )( typeid(*this) )( V )(VERTEXBUFFER(), VBOKey); // Call the VBO if it's there and all ready to go. if (myVBO && !myVBO->isOlderThan( *Surface.CellField) && !myVBO->isOlderThan( *Surface.CoordField) && !myVBO->isOlderThan( InputRange->age(Context) ) && (Colors && !myVBO->isOlderThan( *Colors) ) ) { if (RefPtr<TriangleRenderer> TR = myVBO->getRenderer() ) { assert( TR->MyElementSorter ); TR->CurrentIBO = TR->sortByDepth(Context, BaryCenters, ViewCacheSize ); if (myVBO->call() ) { myState->ErrorMessage = ""; return; } } } } catch(const GLCacheError&Err) {} if (!myVBO) myVBO = Context[*Surface][ typeid(*this) ][ V ]( VERTEXBUFFER(), VBOKey); assert( myVBO ); myVBO->clear(); // // Loading fields as vertex arrays and append them to the VBO. // using namespace Eagle::PhysicalSpace; myVBO->append( new TypedVertexArray<point3>( myState->getCoords()->myChunk() ) ); if (RefPtr<TriangularSurface::NormalVectorArray_t> VertexNormals = Surface.getNormals() ) { myVBO->append( new TypedNormalArray<bivector3>( VertexNormals->myChunk() )); } #if 0 // no color field found, set something artifical here if (!Colors) { index_t nVertices = Surface.CartesianVertices->getPositions()->getData()->nElements(); Ref<MemArray<1,double> > SurfaceColors(nVertices); for(index_t i=0; i<nVertices; i++) { // a floating point index, which ranges from 0.0 to 1.0 double fi = i/(nVertices-1.0); // some simple and stupid, but colorful formula // to map an index to colors. (*SurfaceColors)[ MIndex(i) ] = fi; } Colors = new Field(SurfaceColors); } #endif assert(Colors); if (RefPtr<TypedArray<rgba_float_t> > colordata = Colors->getData() ) { myVBO->append( ColorArray::newArray( colordata->myChunk() )); } else if (RefPtr<TypedArray<double> > colordata = Colors->getData() ) { RefPtr<MemBase> FieldData = Colors->getData(); if (!DataRange.isIdentity() ) { FieldData = colordata->applyOperator(DataRange, NullPtr() ); } else FieldData = colordata; RefPtr<TexCoordArray> TCA = GL::FieldBuffer<TypedTexCoordArray<double> >::createParam( 1, FieldData, false, NullPtr() ); myVBO->append( TCA ); } else if( RefPtr<TypedArray<float> > colordata = Colors->getData() ) { puts("TransparentColoredSurface::render() Apparently this is not called!?!?"); RefPtr<MemBase> FieldData = Colors->getData(); if (!DataRange.isIdentity() ) { FieldData = colordata->applyOperator(DataRange, NullPtr() ); } else FieldData = colordata; RefPtr<TexCoordArray> TCA = GL::FieldBuffer<TypedTexCoordArray<float> >::createParam( 1, FieldData, false, NullPtr() ); myVBO->append( TCA ); } else { puts("TransparentColoredSurface::render() Apparently this IS called!?!?"); myState->ErrorMessage = "Color field has unsupported type " + Typename(Colors->getElementType()) + ", only RGB or double supported"; return; } RefPtr<TriangleRenderer> TR = new TriangleRenderer(myState->getCoords(), myState->CellField->getData() ); TR->MyElementSorter = new GL::TypedElementSorter<TriangleCell>(myState->CellField->getCreator() ); TR->CurrentIBO = TR->sortByDepth(Context, BaryCenters, ViewCacheSize ); myVBO->setRenderer( TR ); myVBO->call(); } // // Object Creation // struct GridInspector { static SkeletonExistence InspectionProperty() { return SkeletonExistence( TriangularSurface::ID() ); } }; static Ref<GridActor<GridInspector, TransparentColoredSurface> > MyTransparentColoredSurfaceCreator("Display/TransparentColoredSurface", ObjectQuality::MATURE); //static VSink<Field, TransparentColoredSurface> static Ref<TypedFieldInputCreator<TransparentColoredSurface> > MmmmyTransparentColoredSurfaceCreator("Display/ColoredSurface", ObjectQuality::MATURE); } // anon namespace