diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ad83623..12cef6d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,19 +1,14 @@ -add_library( - osgTools STATIC osgTools/StatsHandler.cpp include/osgTools/StatsHandler.h - include/osgTools/Version.h) +set(PUBLIC_HEADERS + include/osgTools/GraphicsOperations.h include/osgTools/PointShaderProgram.h + include/osgTools/StatsHandler.h include/osgTools/Version.h) +add_library(osgTools STATIC osgTools/PointShaderProgram.cpp + osgTools/StatsHandler.cpp "${PUBLIC_HEADERS}") add_library(osgTools::osgTools ALIAS osgTools) target_link_libraries(osgTools PUBLIC ${OPENSCENEGRAPH_LIBRARIES}) -target_sources( - osgTools - PUBLIC FILE_SET - HEADERS - BASE_DIRS - include - FILES - include/osgTools/StatsHandler.h - include/osgTools/Version.h) +target_sources(osgTools PUBLIC FILE_SET HEADERS BASE_DIRS include FILES + "${PUBLIC_HEADERS}") install( TARGETS osgTools diff --git a/src/include/osgTools/GraphicsOperations.h b/src/include/osgTools/GraphicsOperations.h new file mode 100644 index 0000000..72897ab --- /dev/null +++ b/src/include/osgTools/GraphicsOperations.h @@ -0,0 +1,25 @@ +#pragma once + +#include + +namespace osgTools { + // + // Graphics Operations + // + + // UseVertexAttributeAliasing + // + // Enable with: + // viewer.setRealizeOperation(new UseVertexAttributeAliasing()); + // + class UseVertexAttributeAliasing : public osg::GraphicsOperation { + public: + UseVertexAttributeAliasing() + : osg::Referenced(true), + osg::GraphicsOperation("GraphicsOperation", false) {} + + virtual void operator()(osg::GraphicsContext* gc) { + gc->getState()->setUseVertexAttributeAliasing(true); + } + }; +} // namespace osgTools diff --git a/src/include/osgTools/PointShaderProgram.h b/src/include/osgTools/PointShaderProgram.h new file mode 100644 index 0000000..8d32489 --- /dev/null +++ b/src/include/osgTools/PointShaderProgram.h @@ -0,0 +1,8 @@ +#pragma once + +#include +#include + +namespace osgTools { + osg::ref_ptr createPointShaderProgram(osg::Node *targetNode); +}; diff --git a/src/osgTools/PointShaderProgram.cpp b/src/osgTools/PointShaderProgram.cpp new file mode 100644 index 0000000..91491bc --- /dev/null +++ b/src/osgTools/PointShaderProgram.cpp @@ -0,0 +1,60 @@ +#include + +using namespace osgTools; + +const char* vertexShaderSource = R"( + #version 330 core + + in vec4 osg_Vertex; + in vec4 osg_Color; + + uniform mat4 osg_ModelViewProjectionMatrix; + + out vec4 vertexColor; + + void main(void) { + gl_Position = osg_ModelViewProjectionMatrix * osg_Vertex; + + vertexColor = osg_Color; + + // Be sure and call `StateSet::setMode(GL_PROGRAM_POINT_SIZE, osg::StateAttribute::ON)`, or + // this will be a no-op! IMPORTANT! + gl_PointSize = 1.0; + } +)"; + +const char* fragmentShaderSource = R"( + #version 330 core + in vec4 vertexColor; + + out vec4 color; + + void main(void) { + // Convert to [-1, 1] so (0,0) is the center of the point. + vec2 p = gl_PointCoord * 2.0 - 1.0; + + // This gives us a radial coordinate without a costly sqrt(), supposedly. + float r2 = dot(p, p); + + // This explicitly recreates legacy FFP point behavior... + float alpha = exp(-r2 * 2.5); + color = vec4(vertexColor.rgb * alpha, vertexColor.a * alpha); + } +)"; + +osg::ref_ptr osgTools::createPointShaderProgram( + osg::Node* target) { + osg::ref_ptr prg = new osg::Program(); + + prg->addShader(new osg::Shader(osg::Shader::VERTEX, vertexShaderSource)); + prg->addShader( + new osg::Shader(osg::Shader::FRAGMENT, fragmentShaderSource)); + + if (target) { + auto stateSet = target->getOrCreateStateSet(); + stateSet->setAttributeAndModes(prg); + stateSet->setMode(GL_PROGRAM_POINT_SIZE, osg::StateAttribute::ON); + } + + return prg; +}