├── applications ├── vsgnodes │ ├── CMakeLists.txt │ └── vsgnodes.cpp ├── CMakeLists.txt ├── vsgobjects │ ├── CMakeLists.txt │ └── vsgobjects.cpp ├── vsgwithosg │ ├── CMakeLists.txt │ ├── GLMemoryExtensions.cpp │ ├── GLSemaphore.h │ ├── GLSemaphore.cpp │ ├── SharedTexture.h │ ├── GLMemoryExtensions.h │ ├── SyncTextureDrawCallbacks.h │ ├── SharedTexture.cpp │ └── vsgwithosg.cpp ├── osggroups │ ├── CMakeLists.txt │ └── osggroups.cpp └── osgmaths │ ├── CMakeLists.txt │ └── osgmaths.cpp ├── README.md ├── src ├── osg2vsg │ ├── osg2vsgConfig.cmake │ ├── Optimize.h │ ├── ShaderUtils.h │ ├── SceneAnalysis.h │ ├── ImageUtils.h │ ├── BuildOptions.h │ ├── CMakeLists.txt │ ├── shaders │ │ ├── defaultshader_vert.cpp │ │ ├── defaultshader_frag.cpp │ │ ├── fbxshader_frag.cpp │ │ └── fbxshader_vert.cpp │ ├── GeometryUtils.h │ ├── ConvertToVsg.h │ ├── ShaderUtils.cpp │ ├── SceneBuilder.h │ ├── SceneAnalysis.cpp │ ├── Optimize.cpp │ ├── convert.cpp │ ├── OSG.cpp │ ├── BuildOptions.cpp │ ├── ImageUtils.cpp │ └── GeometryUtils.cpp └── osgPlugins │ └── vsg │ ├── CMakeLists.txt │ └── ReaderWriterVSG.cpp ├── LICENSE.md ├── .gitignore ├── data └── shaders │ ├── defaultshader.vert │ ├── defaultshader.frag │ ├── fbxshader.frag │ └── fbxshader.vert ├── include └── osg2vsg │ ├── Export.h │ ├── OSG.h │ └── convert.h └── CMakeLists.txt /applications/vsgnodes/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(SOURCES vsgnodes.cpp) 2 | 3 | add_executable(vsgnodes ${SOURCES}) 4 | target_include_directories(vsgnodes PRIVATE ${OSG_INCLUDE_DIR}) 5 | target_link_libraries(vsgnodes vsg::vsg ${OSG_LIBRARIES}) 6 | -------------------------------------------------------------------------------- /applications/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # set the use of C++17 globally as all examples require it 2 | add_subdirectory(osggroups) 3 | add_subdirectory(osgmaths) 4 | add_subdirectory(vsgnodes) 5 | add_subdirectory(vsgobjects) 6 | add_subdirectory(vsgwithosg) 7 | -------------------------------------------------------------------------------- /applications/vsgobjects/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(SOURCES vsgobjects.cpp) 2 | 3 | add_executable(vsgobjects ${SOURCES}) 4 | target_include_directories(vsgobjects PRIVATE ${OSG_INCLUDE_DIR}) 5 | target_link_libraries(vsgobjects vsg::vsg ${OSG_LIBRARIES}) 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | osg2vsg is a small utility library with tools that convert OpenSceneGraph images and 3D models into [VSG](https://github.com/vsg-dev/VulkanSceneGraph)/Vulkan equivalents and provide integration between OpenSceneGraph/OpenGL and VulkanSceneGraph/Vulkan. 2 | -------------------------------------------------------------------------------- /src/osg2vsg/osg2vsgConfig.cmake: -------------------------------------------------------------------------------- 1 | include(CMakeFindDependencyMacro) 2 | 3 | find_dependency(vsg) 4 | find_dependency(OpenThreads) 5 | find_dependency(osg) 6 | find_dependency(osgUtil) 7 | find_dependency(osgDB) 8 | 9 | include("${CMAKE_CURRENT_LIST_DIR}/osg2vsgTargets.cmake") 10 | -------------------------------------------------------------------------------- /applications/vsgwithosg/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(SOURCES 2 | GLMemoryExtensions.cpp 3 | GLSemaphore.cpp 4 | SharedTexture.cpp 5 | vsgwithosg.cpp 6 | ) 7 | 8 | add_executable(vsgwithosg ${SOURCES}) 9 | 10 | target_include_directories(vsgwithosg PRIVATE ${OSG_INCLUDE_DIR}) 11 | target_link_libraries(vsgwithosg 12 | vsg::vsg 13 | osg2vsg 14 | ${OPENTHREADS_LIBRARIES} 15 | ${OSG_LIBRARIES} 16 | ${OSGUTIL_LIBRARIES} 17 | ${OSGDB_LIBRARIES} 18 | ${OSGGA_LIBRARIES} 19 | ${OSGVIEWER_LIBRARIES} 20 | ${OPENGL_LIBRARIES} 21 | ) 22 | -------------------------------------------------------------------------------- /applications/osggroups/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | find_package(OpenGL) 2 | 3 | if(WIN32) 4 | set(OPENGL_LIBRARY ${OPENGL_gl_LIBRARY}) 5 | else() 6 | set(OPENGL_LIBRARY OpenGL::GL) 7 | endif() 8 | 9 | if(NOT ANDROID) 10 | find_package(Threads) 11 | endif() 12 | 13 | if (UNIX) 14 | find_library(DL_LIBRARY dl) 15 | endif() 16 | 17 | set(SOURCES osggroups.cpp) 18 | 19 | add_executable(osggroups ${SOURCES}) 20 | target_include_directories(osggroups PRIVATE ${OSG_INCLUDE_DIR}) 21 | target_link_libraries(osggroups ${OSGDB_LIBRARIES} ${OSG_LIBRARIES} ${OPENTHREADS_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} ${OPENGL_LIBRARY} ${DL_LIBRARY}) 22 | 23 | -------------------------------------------------------------------------------- /applications/osgmaths/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | find_package(OpenGL) 2 | 3 | if(WIN32) 4 | set(OPENGL_LIBRARY ${OPENGL_gl_LIBRARY}) 5 | else() 6 | set(OPENGL_LIBRARY OpenGL::GL) 7 | endif() 8 | 9 | if(NOT ANDROID) 10 | find_package(Threads) 11 | endif() 12 | 13 | if (UNIX) 14 | find_library(DL_LIBRARY dl) 15 | endif() 16 | 17 | set(SOURCES osgmaths.cpp) 18 | 19 | add_executable(osgmaths ${SOURCES}) 20 | target_include_directories(osgmaths PRIVATE ${OSG_INCLUDE_DIR}) 21 | target_link_libraries(osgmaths 22 | vsg::vsg 23 | ${OSGDB_LIBRARIES} ${OSG_LIBRARIES} ${OPENTHREADS_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} ${OPENGL_LIBRARY} ${DL_LIBRARY} 24 | ) 25 | 26 | -------------------------------------------------------------------------------- /src/osg2vsg/Optimize.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | namespace osg2vsg 9 | { 10 | 11 | class OptimizeOsgBillboards : public osg::NodeVisitor 12 | { 13 | public: 14 | OptimizeOsgBillboards(); 15 | 16 | void apply(osg::Node& node); 17 | void apply(osg::Group& group); 18 | void apply(osg::Transform& transform); 19 | void apply(osg::Billboard& billboard); 20 | void apply(osg::Geometry& geometry); 21 | 22 | using TransformStack = std::stack>; 23 | TransformStack transformStack; 24 | 25 | using NodeSet = std::set; 26 | using TransformSubgraph = std::map; 27 | 28 | TransformSubgraph transformSubgraph; 29 | 30 | void optimize(); 31 | }; 32 | } // namespace osg2vsg 33 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright(c) 2018 Robert Osfield 4 | 5 | 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: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | 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. 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | cmake_uninstall.cmake 3 | 4 | lib/ 5 | bin/ 6 | 7 | # Autogenerated files 8 | 9 | *.pc 10 | *.conf 11 | *.backup 12 | CMakeCache.txt 13 | CMakeFiles 14 | CMakeScripts 15 | Makefile 16 | cmake_install.cmake 17 | install_manifest.txt 18 | src/osg2vsg/osg2vsgConfigVersion.cmake 19 | CMakeDoxyfile.in 20 | CMakeDoxygenDefaults.cmake 21 | Doxyfile.docs-osg2vsg 22 | 23 | # Compiled Object files 24 | *.slo 25 | *.lo 26 | *.o 27 | *.obj 28 | 29 | # Precompiled Headers 30 | *.gch 31 | *.pch 32 | 33 | # Compiled Dynamic libraries 34 | *.so 35 | *.dylib 36 | *.dll 37 | 38 | # Fortran module files 39 | *.mod 40 | 41 | # Compiled Static libraries 42 | *.lai 43 | *.la 44 | *.a 45 | *.lib 46 | 47 | # Executables 48 | *.exe 49 | *.out 50 | *.app 51 | 52 | # Visual Studio files 53 | *.sln 54 | *.vcxproj 55 | *.vcxproj.filters 56 | *.vcxproj.user 57 | *.lastbuildstate 58 | *.tlog 59 | *.log 60 | *.pdb 61 | .vs/ 62 | x64/ 63 | src/vsg/vsg.dir/ 64 | 65 | #xcode 66 | DerivedData/ 67 | *.build 68 | *.xcodeproj 69 | 70 | # Gradle 71 | .gradle/ 72 | .idea/ 73 | .externalNativeBuild/ 74 | *.iml 75 | build/ 76 | local.properties 77 | -------------------------------------------------------------------------------- /src/osgPlugins/vsg/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(SOURCES 2 | ReaderWriterVSG.cpp 3 | ) 4 | 5 | add_library(osgdb_vsg MODULE ${SOURCES}) 6 | 7 | target_include_directories(osgdb_vsg PUBLIC 8 | $ 9 | $ 10 | ${OSG_INCLUDE_DIR} 11 | ) 12 | 13 | target_link_libraries(osgdb_vsg PUBLIC 14 | osg2vsg 15 | vsg::vsg 16 | ${OPENTHREADS_LIBRARIES} ${OSG_LIBRARIES} ${OSGUTIL_LIBRARIES} ${OSGDB_LIBRARIES} 17 | ) 18 | 19 | # osg plugins related 20 | set(OSG_PLUGINS_DIRECTORY osgPlugins-${OPENSCENEGRAPH_VERSION}) 21 | if(CYGWIN) 22 | set(OSG_PLUGIN_PREFIX "cygwin_") 23 | elseif(MINGW) 24 | set(OSG_PLUGIN_PREFIX "mingw_") 25 | else() 26 | set(OSG_PLUGIN_PREFIX "") 27 | endif() 28 | set(CMAKE_SHARED_MODULE_PREFIX ${OSG_PLUGIN_PREFIX}) 29 | 30 | if(WIN32) 31 | set(OSG_PLUGIN_INSTALL_LIBDIR ${CMAKE_INSTALL_BINDIR}) 32 | else() 33 | set(OSG_PLUGIN_INSTALL_LIBDIR ${CMAKE_INSTALL_LIBDIR}) 34 | endif() 35 | 36 | # do not use INSTALL_TARGETS_DEFAULT_FLAGS, it does not match 37 | install(TARGETS osgdb_vsg EXPORT osg2vsgTargets 38 | LIBRARY DESTINATION ${OSG_PLUGIN_INSTALL_LIBDIR}/${OSG_PLUGINS_DIRECTORY} 39 | ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/${OSG_PLUGINS_DIRECTORY} 40 | RUNTIME DESTINATION bin 41 | INCLUDES DESTINATION include 42 | ) 43 | -------------------------------------------------------------------------------- /src/osg2vsg/ShaderUtils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | namespace osg2vsg 9 | { 10 | enum ShaderModeMask : uint32_t 11 | { 12 | NONE = 0, 13 | LIGHTING = 1, 14 | MATERIAL = 2, 15 | BLEND = 4, 16 | BILLBOARD = 8, 17 | DIFFUSE_MAP = 16, 18 | OPACITY_MAP = 32, 19 | AMBIENT_MAP = 64, 20 | NORMAL_MAP = 128, 21 | SPECULAR_MAP = 256, 22 | SHADER_TRANSLATE = 512, 23 | ALL_SHADER_MODE_MASK = LIGHTING | MATERIAL | BLEND | BILLBOARD | DIFFUSE_MAP | OPACITY_MAP | AMBIENT_MAP | NORMAL_MAP | SPECULAR_MAP | SHADER_TRANSLATE 24 | }; 25 | 26 | // taken from osg fbx plugin 27 | enum TextureUnit : uint32_t 28 | { 29 | DIFFUSE_TEXTURE_UNIT = 0, 30 | OPACITY_TEXTURE_UNIT, 31 | REFLECTION_TEXTURE_UNIT, 32 | EMISSIVE_TEXTURE_UNIT, 33 | AMBIENT_TEXTURE_UNIT, 34 | NORMAL_TEXTURE_UNIT, 35 | SPECULAR_TEXTURE_UNIT, 36 | SHININESS_TEXTURE_UNIT, 37 | MATERIAL_BINDING = 10 // same value as used in the shader 38 | }; 39 | 40 | uint32_t calculateShaderModeMask(const osg::StateSet* stateSet); 41 | 42 | std::set createPSCDefineStrings(const uint32_t& shaderModeMask, const uint32_t& geometryAttrbutes); 43 | 44 | } // namespace osg2vsg 45 | -------------------------------------------------------------------------------- /data/shaders/defaultshader.vert: -------------------------------------------------------------------------------- 1 | #version 450 2 | #pragma import_defines ( VSG_NORMAL, VSG_COLOR, VSG_TEXCOORD0, VSG_LIGHTING ) 3 | #extension GL_ARB_separate_shader_objects : enable 4 | layout(push_constant) uniform PushConstants { 5 | mat4 projection; 6 | mat4 moddelview; 7 | //mat3 normal; 8 | } pc; 9 | layout(location = 0) in vec3 osg_Vertex; 10 | #ifdef VSG_NORMAL 11 | layout(location = 1) in vec3 osg_Normal; 12 | layout(location = 1) out vec3 normalDir; 13 | #endif 14 | #ifdef VSG_COLOR 15 | layout(location = 3) in vec4 osg_Color; 16 | layout(location = 3) out vec4 vertColor; 17 | #endif\n 18 | #ifdef VSG_TEXCOORD0 19 | layout(location = 4) in vec2 osg_MultiTexCoord0; 20 | layout(location = 4) out vec2 texCoord0; 21 | #endif\n 22 | #ifdef VSG_LIGHTING 23 | layout(location = 5) out vec3 viewDir; 24 | layout(location = 6) out vec3 lightDir; 25 | #endif 26 | out gl_PerVertex{ vec4 gl_Position; }; 27 | 28 | void main() 29 | { 30 | gl_Position = (pc.projection * pc.modelview) * vec4(osg_Vertex, 1.0); 31 | #ifdef VSG_TEXCOORD0 32 | texCoord0 = osg_MultiTexCoord0.st; 33 | #endif 34 | #ifdef VSG_NORMAL 35 | vec3 n = ((pc.mdoelview) * vec4(osg_Normal, 0.0)).xyz; 36 | normalDir = n; 37 | #endif 38 | #ifdef VSG_LIGHTING 39 | vec4 lpos = /*osg_LightSource.position*/ vec4(0.0, 0.25, 1.0, 0.0); 40 | viewDir = -vec3((pc.modelview) * vec4(osg_Vertex, 1.0)); 41 | if (lpos.w == 0.0) 42 | lightDir = lpos.xyz; 43 | else 44 | lightDir = lpos.xyz + viewDir; 45 | #endif 46 | #ifdef VSG_COLOR 47 | vertColor = osg_Color; 48 | #endif 49 | } 50 | -------------------------------------------------------------------------------- /include/osg2vsg/Export.h: -------------------------------------------------------------------------------- 1 | #ifndef OSG2VSG_EXPORT_H 2 | #define OSG2VSG_EXPORT_H 3 | 4 | /* 5 | 6 | Copyright(c) 2018 Robert Osfield 7 | 8 | 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: 9 | 10 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | 12 | 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. 13 | 14 | */ 15 | 16 | #if (defined(_MSC_VER) || defined(__CYGWIN__) || defined(__MINGW32__)) 17 | #if defined(osg2vsg_EXPORTS) 18 | #define OSG2VSG_DECLSPEC __declspec(dllexport) 19 | #elif defined(OSG2VSG_SHARED_LIBRARY) 20 | #define OSG2VSG_DECLSPEC __declspec(dllimport) 21 | #else 22 | #define OSG2VSG_DECLSPEC 23 | #endif 24 | #else 25 | #define OSG2VSG_DECLSPEC 26 | #endif 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /src/osg2vsg/SceneAnalysis.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | 7 | #include 8 | 9 | namespace osg2vsg 10 | { 11 | struct SceneStats : public vsg::Object 12 | { 13 | using ObjectFrequencyMap = std::map; 14 | using TypeFrequencyMap = std::map; 15 | 16 | TypeFrequencyMap typeFrequencyMap; 17 | 18 | template 19 | void insert(const T* object) 20 | { 21 | if (object) 22 | { 23 | ++typeFrequencyMap[object->className()][object]; 24 | } 25 | } 26 | 27 | void print(std::ostream& out); 28 | }; 29 | 30 | class OsgSceneAnalysis : public osg::NodeVisitor 31 | { 32 | public: 33 | vsg::ref_ptr _sceneStats; 34 | 35 | OsgSceneAnalysis(); 36 | OsgSceneAnalysis(SceneStats* sceneStats); 37 | 38 | void apply(osg::Node& node); 39 | void apply(osg::Geometry& geometry); 40 | void apply(osg::StateSet& stateset); 41 | }; 42 | 43 | class VsgSceneAnalysis : public vsg::ConstVisitor 44 | { 45 | public: 46 | vsg::ref_ptr _sceneStats; 47 | 48 | VsgSceneAnalysis(); 49 | VsgSceneAnalysis(SceneStats* sceneStats); 50 | 51 | void apply(const vsg::Object& object) override; 52 | void apply(const vsg::Geometry& geometry) override; 53 | void apply(const vsg::StateGroup& stategroup) override; 54 | //void apply(const vsg::Commands& commands) override; 55 | }; 56 | 57 | } // namespace osg2vsg 58 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.7) 2 | 3 | project(osg2vsg 4 | VERSION 0.4.0 5 | DESCRIPTION "OpenSceneGraph/VulkanSceneGraph integration library" 6 | LANGUAGES CXX 7 | ) 8 | set(OSG2VSG_SOVERSION 0) 9 | SET(OSG2VSG_RELEASE_CANDIDATE 0) 10 | 11 | set(OpenGL_GL_PREFERENCE "GLVND") 12 | find_package(OpenGL REQUIRED) 13 | 14 | # Find OpenSceneGraph packages for reference 15 | # set preference for using modern OpenGL library. 16 | find_package(OpenSceneGraph REQUIRED COMPONENTS osgDB osgTerrain osgUtil osgGA osgViewer) 17 | 18 | if (VULKAN_SDK) 19 | set(ENV{VULKAN_SDK} ${VULKAN_SDK}) 20 | endif() 21 | 22 | find_package(vsg 1.1.13) 23 | 24 | vsg_setup_dir_vars() 25 | vsg_setup_build_vars() 26 | 27 | vsg_add_target_clang_format( 28 | FILES 29 | ${PROJECT_SOURCE_DIR}/include/*/*.h 30 | ${PROJECT_SOURCE_DIR}/src/*/*.cpp 31 | ) 32 | vsg_add_target_clobber() 33 | vsg_add_target_cppcheck( 34 | FILES 35 | ${PROJECT_SOURCE_DIR}/include/*/*.h 36 | ${PROJECT_SOURCE_DIR}/src/*/*.cpp 37 | -I ${PROJECT_SOURCE_DIR}/include/ 38 | ) 39 | vsg_add_target_docs( 40 | FILES 41 | ${PROJECT_SOURCE_DIR}/include/ 42 | ) 43 | vsg_add_target_uninstall() 44 | 45 | 46 | # only provide custom targets if not building as a submodule/FetchContent 47 | if (${CMAKE_CURRENT_SOURCE_DIR} STREQUAL ${CMAKE_SOURCE_DIR}) 48 | 49 | vsg_add_option_maintainer( 50 | PREFIX v 51 | RCLEVEL ${OSG2VSG_RELEASE_CANDIDATE} 52 | ) 53 | 54 | endif() 55 | 56 | # src directory contains all the example applications etc. 57 | add_subdirectory(src/osg2vsg) 58 | add_subdirectory(src/osgPlugins/vsg) 59 | add_subdirectory(applications) 60 | -------------------------------------------------------------------------------- /src/osg2vsg/ImageUtils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /* 4 | 5 | Copyright(c) 2018 Robert Osfield 6 | 7 | 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: 8 | 9 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | 11 | 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. 12 | 13 | */ 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | namespace osg2vsg 24 | { 25 | VkFormat convertGLImageFormatToVulkan(GLenum dataType, GLenum pixelFormat); 26 | 27 | osg::ref_ptr formatImageToRGBA(const osg::Image* image); 28 | 29 | vsg::ref_ptr convertToVsg(const osg::Image* image, bool mapRGBtoRGBAHint); 30 | } // namespace osg2vsg 31 | -------------------------------------------------------------------------------- /data/shaders/defaultshader.frag: -------------------------------------------------------------------------------- 1 | #version 450 2 | #pragma import_defines ( VSG_NORMAL, VSG_COLOR, VSG_TEXCOORD0, VSG_LIGHTING, VSG_DIFFUSE_MAP ) 3 | #extension GL_ARB_separate_shader_objects : enable 4 | #ifdef VSG_DIFFUSE_MAP 5 | layout(binding = 0) uniform sampler2D diffuseMap; 6 | #endif 7 | 8 | #ifdef VSG_NORMAL 9 | layout(location = 1) in vec3 normalDir; 10 | #endif 11 | #ifdef VSG_COLOR 12 | layout(location = 3) in vec4 vertColor; 13 | #endif 14 | #ifdef VSG_TEXCOORD0 15 | layout(location = 4) in vec2 texCoord0; 16 | #endif 17 | #ifdef VSG_LIGHTING 18 | layout(location = 5) in vec3 viewDir; 19 | layout(location = 6) in vec3 lightDir; 20 | #endif 21 | layout(location = 0) out vec4 outColor; 22 | 23 | void main() 24 | { 25 | #ifdef VSG_DIFFUSE_MAP 26 | vec4 base = texture(diffuseMap, texCoord0.st); 27 | #else 28 | vec4 base = vec4(1.0,1.0,1.0,1.0); 29 | #endif 30 | #ifdef VSG_COLOR 31 | base = base * vertColor; 32 | #endif 33 | float ambientOcclusion = 1.0; 34 | vec3 specularColor = vec3(0.2,0.2,0.2); 35 | #ifdef VSG_LIGHTING 36 | vec3 nDir = normalDir; 37 | vec3 nd = normalize(nDir); 38 | vec3 ld = normalize(lightDir); 39 | vec3 vd = normalize(viewDir); 40 | vec4 color = vec4(0.01, 0.01, 0.01, 1.0); 41 | color += /*osg_Material.ambient*/ vec4(0.1, 0.1, 0.1, 0.0); 42 | float diff = max(dot(ld, nd), 0.0); 43 | color += /*osg_Material.diffuse*/ vec4(0.8, 0.8, 0.8, 0.0) * diff; 44 | color *= ambientOcclusion; 45 | color *= base; 46 | if (diff > 0.0) 47 | { 48 | vec3 halfDir = normalize(ld + vd); 49 | color.rgb += base.a * specularColor * 50 | pow(max(dot(halfDir, nd), 0.0), 16.0/*osg_Material.shininess*/); 51 | } 52 | #else 53 | vec4 color = base; 54 | #endif 55 | outColor = color; 56 | if (outColor.a==0.0) discard; 57 | } 58 | 59 | -------------------------------------------------------------------------------- /applications/vsgnodes/vsgnodes.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | struct PrintVisitor : public vsg::Visitor 15 | { 16 | using Visitor::apply; 17 | 18 | void apply(vsg::Object& object) override 19 | { 20 | std::cout<<"apply(vsg::Object& "<<&object<<")"< 11 | { 12 | using Key = std::tuple; 13 | using PipelineMap = std::map>; 14 | 15 | std::mutex mutex; 16 | PipelineMap pipelineMap; 17 | 18 | vsg::ref_ptr getOrCreateBindGraphicsPipeline(uint32_t shaderModeMask, uint32_t geometryMask, const vsg::Path& vertShaderPath, const vsg::Path& fragShaderPath, vsg::ref_ptr options); 19 | }; 20 | 21 | struct BuildOptions : public vsg::Inherit 22 | { 23 | vsg::ref_ptr options; 24 | 25 | virtual void read(vsg::Input& input); 26 | virtual void write(vsg::Output& output) const; 27 | 28 | bool insertCullGroups = true; 29 | bool insertCullNodes = true; 30 | bool useBindDescriptorSet = true; 31 | bool billboardTransform = false; 32 | 33 | GeometryTarget geometryTarget = VSG_VERTEXINDEXDRAW; 34 | 35 | uint32_t supportedGeometryAttributes = GeometryAttributes::ALL_ATTS; 36 | uint32_t supportedShaderModeMask = ShaderModeMask::ALL_SHADER_MODE_MASK; 37 | uint32_t overrideGeomAttributes = 0; 38 | uint32_t overrideShaderModeMask = ShaderModeMask::NONE; 39 | bool useDepthSorted = true; 40 | 41 | bool mapRGBtoRGBAHint = true; 42 | bool copyNames = true; 43 | 44 | std::string vertexShaderPath = ""; 45 | std::string fragmentShaderPath = ""; 46 | 47 | vsg::Path extension = "vsgb"; 48 | 49 | vsg::ref_ptr pipelineCache; 50 | }; 51 | } // namespace osg2vsg 52 | 53 | EVSG_type_name(osg2vsg::BuildOptions); 54 | -------------------------------------------------------------------------------- /src/osg2vsg/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | SET(HEADER_PATH ${PROJECT_SOURCE_DIR}/include/osg2vsg) 3 | 4 | set(HEADERS 5 | ${HEADER_PATH}/Export.h 6 | ${HEADER_PATH}/OSG.h 7 | ) 8 | 9 | set(SOURCES 10 | convert.cpp 11 | BuildOptions.cpp 12 | ConvertToVsg.cpp 13 | GeometryUtils.cpp 14 | ImageUtils.cpp 15 | Optimize.cpp 16 | OSG.cpp 17 | SceneAnalysis.cpp 18 | SceneBuilder.cpp 19 | ShaderUtils.cpp 20 | ) 21 | 22 | add_library(osg2vsg ${HEADERS} ${SOURCES}) 23 | 24 | # add definitions to enable building osg2vsg as part of submodule 25 | add_library(osg2vsg::osg2vsg ALIAS osg2vsg) 26 | set(osg2vsg_FOUND TRUE CACHE INTERNAL "osg2vsg found.") 27 | set(CMAKE_DISABLE_FIND_PACKAGE_osg2vsg TRUE CACHE INTERNAL "Disable find_package(osg2vsg) as it's not necessary.") 28 | 29 | set_property(TARGET osg2vsg PROPERTY VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}) 30 | set_property(TARGET osg2vsg PROPERTY SOVERSION ${OSG2VSG_SOVERSION}) 31 | set_property(TARGET osg2vsg PROPERTY POSITION_INDEPENDENT_CODE ON) 32 | set_property(TARGET osg2vsg PROPERTY CXX_STANDARD 17) 33 | 34 | target_include_directories(osg2vsg PUBLIC 35 | $ 36 | $ 37 | $ 38 | ${OSG_INCLUDE_DIR} 39 | ) 40 | 41 | target_link_libraries(osg2vsg 42 | PUBLIC 43 | vsg::vsg 44 | PRIVATE 45 | ${OPENTHREADS_LIBRARIES} ${OSG_LIBRARIES} ${OSGUTIL_LIBRARIES} ${OSGDB_LIBRARIES} ${OSGTERRAIN_LIBRARIES} 46 | ) 47 | 48 | 49 | install(TARGETS osg2vsg ${INSTALL_TARGETS_DEFAULT_FLAGS}) 50 | 51 | target_compile_definitions(osg2vsg PRIVATE ${EXTRA_DEFINES}) 52 | 53 | if (BUILD_SHARED_LIBS) 54 | target_compile_definitions(osg2vsg INTERFACE OSG2VSG_SHARED_LIBRARY) 55 | endif() 56 | 57 | install(DIRECTORY ${HEADER_PATH} DESTINATION include) 58 | 59 | vsg_add_cmake_support_files( 60 | CONFIG_TEMPLATE osg2vsgConfig.cmake 61 | ) 62 | -------------------------------------------------------------------------------- /src/osg2vsg/shaders/defaultshader_vert.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | static auto defaultshader_vert = []() {std::istringstream str( 3 | R"(#vsga 0.5.4 4 | Root id=1 vsg::ShaderStage 5 | { 6 | userObjects 0 7 | stage 1 8 | entryPointName "main" 9 | module id=2 vsg::ShaderModule 10 | { 11 | userObjects 0 12 | hints id=0 13 | source "#version 450 14 | #pragma import_defines ( VSG_NORMAL, VSG_COLOR, VSG_TEXCOORD0, VSG_LIGHTING ) 15 | #extension GL_ARB_separate_shader_objects : enable 16 | layout(push_constant) uniform PushConstants { 17 | mat4 projection; 18 | mat4 moddelview; 19 | //mat3 normal; 20 | } pc; 21 | layout(location = 0) in vec3 osg_Vertex; 22 | #ifdef VSG_NORMAL 23 | layout(location = 1) in vec3 osg_Normal; 24 | layout(location = 1) out vec3 normalDir; 25 | #endif 26 | #ifdef VSG_COLOR 27 | layout(location = 3) in vec4 osg_Color; 28 | layout(location = 3) out vec4 vertColor; 29 | #endif\n 30 | #ifdef VSG_TEXCOORD0 31 | layout(location = 4) in vec2 osg_MultiTexCoord0; 32 | layout(location = 4) out vec2 texCoord0; 33 | #endif\n 34 | #ifdef VSG_LIGHTING 35 | layout(location = 5) out vec3 viewDir; 36 | layout(location = 6) out vec3 lightDir; 37 | #endif 38 | out gl_PerVertex{ vec4 gl_Position; }; 39 | 40 | void main() 41 | { 42 | gl_Position = (pc.projection * pc.modelview) * vec4(osg_Vertex, 1.0); 43 | #ifdef VSG_TEXCOORD0 44 | texCoord0 = osg_MultiTexCoord0.st; 45 | #endif 46 | #ifdef VSG_NORMAL 47 | vec3 n = ((pc.mdoelview) * vec4(osg_Normal, 0.0)).xyz; 48 | normalDir = n; 49 | #endif 50 | #ifdef VSG_LIGHTING 51 | vec4 lpos = /*osg_LightSource.position*/ vec4(0.0, 0.25, 1.0, 0.0); 52 | viewDir = -vec3((pc.modelview) * vec4(osg_Vertex, 1.0)); 53 | if (lpos.w == 0.0) 54 | lightDir = lpos.xyz; 55 | else 56 | lightDir = lpos.xyz + viewDir; 57 | #endif 58 | #ifdef VSG_COLOR 59 | vertColor = osg_Color; 60 | #endif 61 | } 62 | " 63 | code 0 64 | 65 | } 66 | NumSpecializationConstants 0 67 | } 68 | )"); 69 | vsg::VSG io; 70 | return io.read_cast(str); 71 | }; 72 | -------------------------------------------------------------------------------- /src/osg2vsg/shaders/defaultshader_frag.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | static auto defaultshader_frag = []() {std::istringstream str( 3 | R"(#vsga 0.5.4 4 | Root id=1 vsg::ShaderStage 5 | { 6 | userObjects 0 7 | stage 16 8 | entryPointName "main" 9 | module id=2 vsg::ShaderModule 10 | { 11 | userObjects 0 12 | hints id=0 13 | source "#version 450 14 | #pragma import_defines ( VSG_NORMAL, VSG_COLOR, VSG_TEXCOORD0, VSG_LIGHTING, VSG_DIFFUSE_MAP ) 15 | #extension GL_ARB_separate_shader_objects : enable 16 | #ifdef VSG_DIFFUSE_MAP 17 | layout(binding = 0) uniform sampler2D diffuseMap; 18 | #endif 19 | 20 | #ifdef VSG_NORMAL 21 | layout(location = 1) in vec3 normalDir; 22 | #endif 23 | #ifdef VSG_COLOR 24 | layout(location = 3) in vec4 vertColor; 25 | #endif 26 | #ifdef VSG_TEXCOORD0 27 | layout(location = 4) in vec2 texCoord0; 28 | #endif 29 | #ifdef VSG_LIGHTING 30 | layout(location = 5) in vec3 viewDir; 31 | layout(location = 6) in vec3 lightDir; 32 | #endif 33 | layout(location = 0) out vec4 outColor; 34 | 35 | void main() 36 | { 37 | #ifdef VSG_DIFFUSE_MAP 38 | vec4 base = texture(diffuseMap, texCoord0.st); 39 | #else 40 | vec4 base = vec4(1.0,1.0,1.0,1.0); 41 | #endif 42 | #ifdef VSG_COLOR 43 | base = base * vertColor; 44 | #endif 45 | float ambientOcclusion = 1.0; 46 | vec3 specularColor = vec3(0.2,0.2,0.2); 47 | #ifdef VSG_LIGHTING 48 | vec3 nDir = normalDir; 49 | vec3 nd = normalize(nDir); 50 | vec3 ld = normalize(lightDir); 51 | vec3 vd = normalize(viewDir); 52 | vec4 color = vec4(0.01, 0.01, 0.01, 1.0); 53 | color += /*osg_Material.ambient*/ vec4(0.1, 0.1, 0.1, 0.0); 54 | float diff = max(dot(ld, nd), 0.0); 55 | color += /*osg_Material.diffuse*/ vec4(0.8, 0.8, 0.8, 0.0) * diff; 56 | color *= ambientOcclusion; 57 | color *= base; 58 | if (diff > 0.0) 59 | { 60 | vec3 halfDir = normalize(ld + vd); 61 | color.rgb += base.a * specularColor * 62 | pow(max(dot(halfDir, nd), 0.0), 16.0/*osg_Material.shininess*/); 63 | } 64 | #else 65 | vec4 color = base; 66 | #endif 67 | outColor = color; 68 | if (outColor.a==0.0) discard; 69 | } 70 | 71 | " 72 | code 0 73 | 74 | } 75 | NumSpecializationConstants 0 76 | } 77 | )"); 78 | vsg::VSG io; 79 | return io.read_cast(str); 80 | }; 81 | -------------------------------------------------------------------------------- /applications/vsgwithosg/GLMemoryExtensions.cpp: -------------------------------------------------------------------------------- 1 | #include "GLMemoryExtensions.h" 2 | 3 | #include 4 | 5 | using namespace osg; 6 | 7 | typedef osg::buffered_object< osg::ref_ptr > BufferedMemoryExtensions; 8 | static BufferedMemoryExtensions s_memoryExtensions; 9 | 10 | GLMemoryExtensions* GLMemoryExtensions::Get(unsigned int contextID, bool createIfNotInitalized) 11 | { 12 | if (!s_memoryExtensions[contextID] && createIfNotInitalized) 13 | s_memoryExtensions[contextID] = new GLMemoryExtensions(contextID); 14 | 15 | return s_memoryExtensions[contextID].get(); 16 | } 17 | 18 | GLMemoryExtensions::GLMemoryExtensions(unsigned int /*in_contextID*/) 19 | { 20 | // general 21 | osg::setGLExtensionFuncPtr(glGetInternalformativ, "glGetInternalformativ"); 22 | 23 | osg::setGLExtensionFuncPtr(glCreateTextures, "glCreateTextures"); 24 | osg::setGLExtensionFuncPtr(glTextureParameteri, "glTextureParameteri"); 25 | 26 | osg::setGLExtensionFuncPtr(glCopyImageSubData, "glCopyImageSubData"); 27 | 28 | 29 | // memory objects 30 | osg::setGLExtensionFuncPtr(glCreateMemoryObjectsEXT, "glCreateMemoryObjectsEXT"); 31 | osg::setGLExtensionFuncPtr(glMemoryObjectParameterivEXT, "glMemoryObjectParameterivEXT"); 32 | 33 | #if WIN32 34 | osg::setGLExtensionFuncPtr(glImportMemoryWin32HandleEXT, "glImportMemoryWin32HandleEXT"); 35 | #else 36 | osg::setGLExtensionFuncPtr(glImportMemoryFdEXT, "glImportMemoryFdEXT"); 37 | #endif 38 | 39 | osg::setGLExtensionFuncPtr(glTextureStorageMem2DEXT, "glTextureStorageMem2DEXT"); 40 | 41 | // semaphores 42 | osg::setGLExtensionFuncPtr(glGenSemaphoresEXT, "glGenSemaphoresEXT"); 43 | osg::setGLExtensionFuncPtr(glDeleteSemaphoresEXT, "glDeleteSemaphoresEXT"); 44 | osg::setGLExtensionFuncPtr(glIsSemaphoreEXT, "glIsSemaphoreEXT"); 45 | osg::setGLExtensionFuncPtr(glSemaphoreParameterui64vEXT, "glSemaphoreParameterui64vEXT"); 46 | osg::setGLExtensionFuncPtr(glGetSemaphoreParameterui64vEXT, "glGetSemaphoreParameterui64vEXT"); 47 | osg::setGLExtensionFuncPtr(glWaitSemaphoreEXT, "glWaitSemaphoreEXT"); 48 | osg::setGLExtensionFuncPtr(glSignalSemaphoreEXT, "glSignalSemaphoreEXT"); 49 | 50 | #if WIN32 51 | osg::setGLExtensionFuncPtr(glImportSemaphoreWin32HandleEXT, "glImportSemaphoreWin32HandleEXT"); 52 | #else 53 | osg::setGLExtensionFuncPtr(glImportSemaphoreFdEXT, "glImportSemaphoreFdEXT"); 54 | #endif 55 | } 56 | -------------------------------------------------------------------------------- /applications/vsgwithosg/GLSemaphore.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright(c) 2019 Thomas Hogarth 4 | 5 | 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: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | 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. 10 | 11 | */ 12 | 13 | #pragma once 14 | 15 | #include 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | #if WIN32 22 | #include 23 | #endif 24 | 25 | namespace osg 26 | { 27 | class GLSemaphore : public osg::Referenced 28 | { 29 | public: 30 | #if WIN32 31 | typedef HANDLE HandleType; 32 | #else 33 | typedef int HandleType; 34 | #endif 35 | 36 | GLSemaphore(HandleType handle); 37 | 38 | void compileGLObjects(State& state); 39 | 40 | void wait(State& state, const std::vector& buffers, const std::vector& textures, const std::vector& srcLayouts); 41 | void wait(State& state, GLuint numBufferBarriers, const GLuint *buffers, GLuint numTextureBarriers, const GLuint *textures, const GLenum *srcLayouts); 42 | 43 | void signal(State& state, const std::vector& buffers, const std::vector& textures, const std::vector& srcLayouts); 44 | void signal(State& state, GLuint numBufferBarriers, const GLuint *buffers, GLuint numTextureBarriers, const GLuint *textures, const GLenum *srcLayouts); 45 | 46 | protected: 47 | ~GLSemaphore(); 48 | 49 | HandleType _handle; 50 | GLuint _semaphore; 51 | }; 52 | } 53 | 54 | -------------------------------------------------------------------------------- /include/osg2vsg/OSG.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /* 4 | 5 | Copyright(c) 2021 Robert Osfield 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | this software and associated documentation files (the "Software"), to deal in 9 | the Software without restriction, including without limitation the rights to 10 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | the Software, and to permit persons to whom the Software is furnished to do so, 12 | subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shimages be included in images 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | */ 25 | 26 | #include 27 | #include 28 | 29 | namespace osg2vsg 30 | { 31 | // forward declare 32 | class PipelineCache; 33 | 34 | /// optional OSG ReaderWriter 35 | class OSG2VSG_DECLSPEC OSG : public vsg::Inherit 36 | { 37 | public: 38 | OSG(); 39 | 40 | vsg::ref_ptr read(const vsg::Path&, vsg::ref_ptr) const override; 41 | 42 | bool getFeatures(Features& features) const override; 43 | 44 | // vsg::Options::setValue(str, value) supported options: 45 | static constexpr const char* original_converter = "original_converter"; // select early osg2vsg implementation 46 | static constexpr const char* read_build_options = "read_build_options"; // read build options from specified file 47 | static constexpr const char* write_build_options = "write_build_options"; // write build options to specified file 48 | 49 | bool readOptions(vsg::Options& options, vsg::CommandLine& arguments) const override; 50 | 51 | protected: 52 | 53 | vsg::ref_ptr pipelineCache; 54 | 55 | ~OSG(); 56 | }; 57 | 58 | } // namespace vsgXchange 59 | 60 | EVSG_type_name(osg2vsg::OSG); 61 | -------------------------------------------------------------------------------- /src/osg2vsg/GeometryUtils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | namespace osg2vsg 10 | { 11 | enum GeometryAttributes : uint32_t 12 | { 13 | VERTEX = 1, 14 | NORMAL = 2, 15 | NORMAL_OVERALL = 4, 16 | TANGENT = 8, 17 | TANGENT_OVERALL = 16, 18 | COLOR = 32, 19 | COLOR_OVERALL = 64, 20 | TEXCOORD0 = 128, 21 | TEXCOORD1 = 256, 22 | TEXCOORD2 = 512, 23 | TRANSLATE = 1024, 24 | TRANSLATE_OVERALL = 2048, 25 | STANDARD_ATTS = VERTEX | NORMAL | TANGENT | COLOR | TEXCOORD0, 26 | ALL_ATTS = VERTEX | NORMAL | NORMAL_OVERALL | TANGENT | TANGENT_OVERALL | COLOR | COLOR_OVERALL | TEXCOORD0 | TEXCOORD1 | TEXCOORD2 | TRANSLATE | TRANSLATE_OVERALL 27 | }; 28 | 29 | enum AttributeChannels : uint32_t 30 | { 31 | VERTEX_CHANNEL = 0, // osg 0 32 | NORMAL_CHANNEL = 1, // osg 1 33 | TANGENT_CHANNEL = 2, //osg 6 34 | COLOR_CHANNEL = 3, // osg 2 35 | TEXCOORD0_CHANNEL = 4, //osg 3 36 | TEXCOORD1_CHANNEL = 5, 37 | TEXCOORD2_CHANNEL = 6, 38 | TRANSLATE_CHANNEL = 7 39 | }; 40 | 41 | enum GeometryTarget : uint32_t 42 | { 43 | VSG_GEOMETRY, 44 | VSG_VERTEXINDEXDRAW, 45 | VSG_COMMANDS 46 | }; 47 | 48 | vsg::ref_ptr convertToVsg(const osg::Vec2Array* inarray, uint32_t bindOverallPaddingCount); 49 | 50 | vsg::ref_ptr convertToVsg(const osg::Vec3Array* inarray, uint32_t bindOverallPaddingCount); 51 | 52 | vsg::ref_ptr convertToVsg(const osg::Vec4Array* inarray, uint32_t bindOverallPaddingCount); 53 | 54 | vsg::ref_ptr convertToVsg(const osg::Array* inarray, uint32_t bindOverallPaddingCount); 55 | 56 | uint32_t calculateAttributesMask(const osg::Geometry* geometry); 57 | 58 | VkSamplerAddressMode covertToSamplerAddressMode(osg::Texture::WrapMode wrapmode); 59 | 60 | std::pair convertToFilterAndMipmapMode(osg::Texture::FilterMode filtermode); 61 | 62 | vsg::ref_ptr convertToSampler(const osg::Texture* texture); 63 | 64 | vsg::ref_ptr convertToMaterialValue(const osg::Material* material); 65 | 66 | vsg::ref_ptr convertToVsg(osg::Geometry* geometry, uint32_t requiredAttributesMask, GeometryTarget geometryTarget); 67 | 68 | } // namespace osg2vsg 69 | -------------------------------------------------------------------------------- /include/osg2vsg/convert.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /* 4 | 5 | Copyright(c) 2021 Robert Osfield 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | this software and associated documentation files (the "Software"), to deal in 9 | the Software without restriction, including without limitation the rights to 10 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | the Software, and to permit persons to whom the Software is furnished to do so, 12 | subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shimages be included in images 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | */ 25 | 26 | #include 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #include 34 | 35 | namespace osg2vsg 36 | { 37 | 38 | inline vsg::dmat4 convert(const osg::Matrixd& m) 39 | { 40 | return vsg::dmat4(m(0, 0), m(0, 1), m(0, 2), m(0, 3), 41 | m(1, 0), m(1, 1), m(1, 2), m(1, 3), 42 | m(2, 0), m(2, 1), m(2, 2), m(2, 3), 43 | m(3, 0), m(3, 1), m(3, 2), m(3, 3)); 44 | } 45 | 46 | inline vsg::mat4 convert(const osg::Matrixf& m) 47 | { 48 | return vsg::mat4(m(0, 0), m(0, 1), m(0, 2), m(0, 3), 49 | m(1, 0), m(1, 1), m(1, 2), m(1, 3), 50 | m(2, 0), m(2, 1), m(2, 2), m(2, 3), 51 | m(3, 0), m(3, 1), m(3, 2), m(3, 3)); 52 | } 53 | 54 | template 55 | vsg::ref_ptr convert(const osg::Array& array) 56 | { 57 | auto new_array = T::create(array.getNumElements()); 58 | std::memcpy(new_array->dataPointer(), array.getDataPointer(), array.getTotalDataSize()); 59 | return new_array; 60 | } 61 | 62 | OSG2VSG_DECLSPEC extern vsg::ref_ptr convert(const osg::Array& array, vsg::ref_ptr options = {}); 63 | OSG2VSG_DECLSPEC extern vsg::ref_ptr convert(const osg::Image& image, vsg::ref_ptr options = {}); 64 | OSG2VSG_DECLSPEC extern vsg::ref_ptr convert(const osg::Node& node, vsg::ref_ptr options = {}); 65 | 66 | } // namespace vsgXchange 67 | -------------------------------------------------------------------------------- /data/shaders/fbxshader.frag: -------------------------------------------------------------------------------- 1 | #version 450 2 | #pragma import_defines ( VSG_NORMAL, VSG_COLOR, VSG_TEXCOORD0, VSG_LIGHTING, VSG_MATERIAL, VSG_DIFFUSE_MAP, VSG_OPACITY_MAP, VSG_AMBIENT_MAP, VSG_NORMAL_MAP, VSG_SPECULAR_MAP ) 3 | #extension GL_ARB_separate_shader_objects : enable 4 | #ifdef VSG_DIFFUSE_MAP 5 | layout(binding = 0) uniform sampler2D diffuseMap; 6 | #endif 7 | #ifdef VSG_OPACITY_MAP 8 | layout(binding = 1) uniform sampler2D opacityMap; 9 | #endif 10 | #ifdef VSG_AMBIENT_MAP 11 | layout(binding = 4) uniform sampler2D ambientMap; 12 | #endif 13 | #ifdef VSG_NORMAL_MAP 14 | layout(binding = 5) uniform sampler2D normalMap; 15 | #endif 16 | #ifdef VSG_SPECULAR_MAP 17 | layout(binding = 6) uniform sampler2D specularMap; 18 | #endif 19 | 20 | #ifdef VSG_MATERIAL 21 | layout(binding = 10) uniform MaterialData 22 | { 23 | vec4 ambientColor; 24 | vec4 diffuseColor; 25 | vec4 specularColor; 26 | float shininess; 27 | } material; 28 | #endif 29 | 30 | #ifdef VSG_NORMAL 31 | layout(location = 1) in vec3 normalDir; 32 | #endif 33 | #ifdef VSG_COLOR 34 | layout(location = 3) in vec4 vertColor; 35 | #endif 36 | #ifdef VSG_TEXCOORD0 37 | layout(location = 4) in vec2 texCoord0; 38 | #endif 39 | #ifdef VSG_LIGHTING 40 | layout(location = 5) in vec3 viewDir; 41 | layout(location = 6) in vec3 lightDir; 42 | #endif 43 | layout(location = 0) out vec4 outColor; 44 | 45 | void main() 46 | { 47 | #ifdef VSG_DIFFUSE_MAP 48 | vec4 base = texture(diffuseMap, texCoord0.st); 49 | #else 50 | vec4 base = vec4(1.0,1.0,1.0,1.0); 51 | #endif 52 | #ifdef VSG_COLOR 53 | base = base * vertColor; 54 | #endif 55 | #ifdef VSG_MATERIAL 56 | vec3 ambientColor = material.ambientColor.rgb; 57 | vec3 diffuseColor = material.diffuseColor.rgb; 58 | vec3 specularColor = material.specularColor.rgb; 59 | float shininess = material.shininess; 60 | #else 61 | vec3 ambientColor = vec3(0.1,0.1,0.1); 62 | vec3 diffuseColor = vec3(1.0,1.0,1.0); 63 | vec3 specularColor = vec3(0.3,0.3,0.3); 64 | float shininess = 16.0; 65 | #endif 66 | #ifdef VSG_AMBIENT_MAP 67 | ambientColor *= texture(ambientMap, texCoord0.st).r; 68 | #endif 69 | #ifdef VSG_SPECULAR_MAP 70 | specularColor = texture(specularMap, texCoord0.st).rrr; 71 | #endif 72 | #ifdef VSG_LIGHTING 73 | #ifdef VSG_NORMAL_MAP 74 | vec3 nDir = texture(normalMap, texCoord0.st).xyz*2.0 - 1.0; 75 | nDir.g = -nDir.g; 76 | #else 77 | vec3 nDir = normalDir; 78 | #endif 79 | vec3 nd = normalize(nDir); 80 | vec3 ld = normalize(lightDir); 81 | vec3 vd = normalize(viewDir); 82 | vec4 color = vec4(0.01, 0.01, 0.01, 1.0); 83 | color.rgb += ambientColor; 84 | float diff = max(dot(ld, nd), 0.0); 85 | color.rgb += diffuseColor * diff; 86 | color *= base; 87 | if (diff > 0.0) 88 | { 89 | vec3 halfDir = normalize(ld + vd); 90 | color.rgb += base.a * specularColor * 91 | pow(max(dot(halfDir, nd), 0.0), shininess); 92 | } 93 | #else 94 | vec4 color = base; 95 | color.rgb *= diffuseColor; 96 | #endif 97 | outColor = color; 98 | #ifdef VSG_OPACITY_MAP 99 | outColor.a *= texture(opacityMap, texCoord0.st).r; 100 | #endif 101 | 102 | // crude version of AlphaFunc 103 | if (outColor.a==0.0) discard; 104 | } 105 | -------------------------------------------------------------------------------- /data/shaders/fbxshader.vert: -------------------------------------------------------------------------------- 1 | #version 450 2 | #pragma import_defines ( VSG_NORMAL, VSG_TANGENT, VSG_COLOR, VSG_TEXCOORD0, VSG_LIGHTING, VSG_NORMAL_MAP, VSG_BILLBOARD, VSG_TRANSLATE ) 3 | #extension GL_ARB_separate_shader_objects : enable 4 | layout(push_constant) uniform PushConstants { 5 | mat4 projection; 6 | mat4 modelView; 7 | //mat3 normal; 8 | } pc; 9 | layout(location = 0) in vec3 osg_Vertex; 10 | #ifdef VSG_NORMAL 11 | layout(location = 1) in vec3 osg_Normal; 12 | layout(location = 1) out vec3 normalDir; 13 | #endif 14 | #ifdef VSG_TANGENT 15 | layout(location = 2) in vec4 osg_Tangent; 16 | #endif 17 | #ifdef VSG_COLOR 18 | layout(location = 3) in vec4 osg_Color; 19 | layout(location = 3) out vec4 vertColor; 20 | #endif 21 | #ifdef VSG_TEXCOORD0 22 | layout(location = 4) in vec2 osg_MultiTexCoord0; 23 | layout(location = 4) out vec2 texCoord0; 24 | #endif 25 | #ifdef VSG_LIGHTING 26 | layout(location = 5) out vec3 viewDir; 27 | layout(location = 6) out vec3 lightDir; 28 | #endif 29 | #ifdef VSG_TRANSLATE 30 | layout(location = 7) in vec3 translate; 31 | #endif 32 | 33 | 34 | out gl_PerVertex{ vec4 gl_Position; }; 35 | 36 | void main() 37 | { 38 | mat4 modelView = pc.modelView; 39 | 40 | #ifdef VSG_TRANSLATE 41 | mat4 translate_mat = mat4(1.0, 0.0, 0.0, 0.0, 42 | 0.0, 1.0, 0.0, 0.0, 43 | 0.0, 0.0, 1.0, 0.0, 44 | translate.x, translate.y, translate.z, 1.0); 45 | 46 | modelView = modelView * translate_mat; 47 | #endif 48 | 49 | #ifdef VSG_BILLBOARD 50 | vec3 lookDir = vec3(-modelView[0][2], -modelView[1][2], -modelView[2][2]); 51 | 52 | // rotate around local z axis 53 | float l = length(lookDir.xy); 54 | if (l>0.0) 55 | { 56 | float inv = 1.0/l; 57 | float c = lookDir.y * inv; 58 | float s = lookDir.x * inv; 59 | 60 | mat4 rotation_z = mat4(c, -s, 0.0, 0.0, 61 | s, c, 0.0, 0.0, 62 | 0.0, 0.0, 1.0, 0.0, 63 | 0.0, 0.0, 0.0, 1.0); 64 | 65 | modelView = modelView * rotation_z; 66 | } 67 | #endif 68 | 69 | gl_Position = (pc.projection * modelView) * vec4(osg_Vertex, 1.0); 70 | 71 | #ifdef VSG_TEXCOORD0 72 | texCoord0 = osg_MultiTexCoord0.st; 73 | #endif 74 | #ifdef VSG_NORMAL 75 | vec3 n = (modelView * vec4(osg_Normal, 0.0)).xyz; 76 | normalDir = n; 77 | #endif 78 | #ifdef VSG_LIGHTING 79 | vec4 lpos = /*osg_LightSource.position*/ vec4(0.0, 0.25, 1.0, 0.0); 80 | #ifdef VSG_NORMAL_MAP 81 | vec3 t = (modelView * vec4(osg_Tangent.xyz, 0.0)).xyz; 82 | vec3 b = cross(n, t); 83 | vec3 dir = -vec3(modelView * vec4(osg_Vertex, 1.0)); 84 | viewDir.x = dot(dir, t); 85 | viewDir.y = dot(dir, b); 86 | viewDir.z = dot(dir, n); 87 | if (lpos.w == 0.0) 88 | dir = lpos.xyz; 89 | else 90 | dir += lpos.xyz; 91 | lightDir.x = dot(dir, t); 92 | lightDir.y = dot(dir, b); 93 | lightDir.z = dot(dir, n); 94 | #else 95 | viewDir = -vec3(modelView * vec4(osg_Vertex, 1.0)); 96 | if (lpos.w == 0.0) 97 | lightDir = lpos.xyz; 98 | else 99 | lightDir = lpos.xyz + viewDir; 100 | #endif 101 | #endif 102 | #ifdef VSG_COLOR 103 | vertColor = osg_Color; 104 | #endif 105 | } 106 | -------------------------------------------------------------------------------- /applications/vsgwithosg/GLSemaphore.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright(c) 2019 Thomas Hogarth 4 | 5 | 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: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | 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. 10 | 11 | */ 12 | 13 | #include "GLSemaphore.h" 14 | 15 | #include "GLMemoryExtensions.h" 16 | 17 | #include 18 | 19 | using namespace osg; 20 | 21 | GLSemaphore::GLSemaphore(HandleType handle) : 22 | Referenced(), 23 | _handle(handle), 24 | _semaphore(0) 25 | { 26 | } 27 | 28 | 29 | GLSemaphore::~GLSemaphore() 30 | { 31 | } 32 | 33 | void GLSemaphore::compileGLObjects(State& state) 34 | { 35 | if(_handle == 0 || _semaphore != 0) return; 36 | 37 | GLMemoryExtensions* extensions = GLMemoryExtensions::Get(state.getContextID(), true); 38 | if(!extensions->glGenSemaphoresEXT) return; 39 | 40 | extensions->glGenSemaphoresEXT(1, &_semaphore); 41 | #if WIN32 42 | extensions->glImportSemaphoreWin32HandleEXT(_semaphore, GL_HANDLE_TYPE_OPAQUE_WIN32_EXT, _handle); 43 | #else 44 | extensions->glImportSemaphoreFdEXT(_semaphore, GL_HANDLE_TYPE_OPAQUE_FD_EXT, _handle); 45 | #endif 46 | } 47 | 48 | void GLSemaphore::wait(State& state, const std::vector& buffers, const std::vector& textures, const std::vector& srcLayouts) 49 | { 50 | wait(state, buffers.size(), buffers.data(), textures.size(), textures.data(), srcLayouts.data()); 51 | } 52 | 53 | void GLSemaphore::wait(State& state, GLuint numBufferBarriers, const GLuint *buffers, GLuint numTextureBarriers, const GLuint *textures, const GLenum *srcLayouts) 54 | { 55 | GLMemoryExtensions* extensions = GLMemoryExtensions::Get(state.getContextID(), true); 56 | 57 | extensions->glWaitSemaphoreEXT(_semaphore, numBufferBarriers, buffers, numTextureBarriers, textures, srcLayouts); 58 | } 59 | 60 | void GLSemaphore::signal(State& state, const std::vector& buffers, const std::vector& textures, const std::vector& srcLayouts) 61 | { 62 | signal(state, buffers.size(), buffers.data(), textures.size(), textures.data(), srcLayouts.data()); 63 | } 64 | 65 | void GLSemaphore::signal(State& state, GLuint numBufferBarriers, const GLuint *buffers, GLuint numTextureBarriers, const GLuint *textures, const GLenum *srcLayouts) 66 | { 67 | GLMemoryExtensions* extensions = GLMemoryExtensions::Get(state.getContextID(), true); 68 | 69 | extensions->glSignalSemaphoreEXT(_semaphore, numBufferBarriers, buffers, numTextureBarriers, textures, srcLayouts); 70 | } 71 | -------------------------------------------------------------------------------- /src/osg2vsg/ConvertToVsg.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "GeometryUtils.h" 13 | #include "Optimize.h" 14 | #include "SceneBuilder.h" 15 | #include "ShaderUtils.h" 16 | 17 | namespace osg2vsg 18 | { 19 | 20 | using FileNameMap = std::map; 21 | 22 | class ConvertToVsg : public osg::NodeVisitor, public osg2vsg::SceneBuilderBase 23 | { 24 | public: 25 | ConvertToVsg(vsg::ref_ptr options, vsg::ref_ptr in_inheritedStateGroup = {}) : 26 | osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN), 27 | SceneBuilderBase(options), 28 | inheritedStateGroup(in_inheritedStateGroup) 29 | { 30 | } 31 | 32 | vsg::ref_ptr root; 33 | 34 | using osg::NodeVisitor::apply; 35 | using MasksAndState = std::tuple>; 36 | using BindDescriptorSetMap = std::map>; 37 | BindDescriptorSetMap bindDescriptorSetMap; 38 | vsg::ref_ptr inheritedStateGroup; 39 | 40 | using NodeMap = std::map>; 41 | NodeMap nodeMap; 42 | 43 | size_t numOfPagedLOD = 0; 44 | FileNameMap filenameMap; 45 | 46 | vsg::ref_ptr getOrCreateBindGraphicsPipeline(uint32_t shaderModeMask, uint32_t geometryMask); 47 | 48 | vsg::ref_ptr getOrCreateBindDescriptorSet(uint32_t shaderModeMask, uint32_t geometryMask, osg::StateSet* stateset); 49 | 50 | vsg::Path mapFileName(const std::string& filename); 51 | 52 | void optimize(osg::Node* osg_scene); 53 | 54 | vsg::ref_ptr convert(osg::Node* node); 55 | 56 | template 57 | vsg::ref_ptr copyArray(const osg::Array* array) 58 | { 59 | vsg::ref_ptr new_array = V::create(array->getNumElements()); 60 | 61 | std::memcpy(new_array->dataPointer(), array->getDataPointer(), array->getTotalDataSize()); 62 | 63 | return new_array; 64 | } 65 | 66 | vsg::ref_ptr copy(osg::Array* src_array); 67 | 68 | struct ScopedPushPop 69 | { 70 | ConvertToVsg& convertToVsg; 71 | osg::StateSet* stateset; 72 | 73 | ScopedPushPop(ConvertToVsg& conv, osg::StateSet* ss) : 74 | convertToVsg(conv), 75 | stateset(ss) 76 | { 77 | if (stateset) convertToVsg.statestack.push_back(stateset); 78 | } 79 | 80 | ~ScopedPushPop() 81 | { 82 | if (stateset) convertToVsg.statestack.pop_back(); 83 | } 84 | }; 85 | 86 | uint32_t calculateShaderModeMask(); 87 | 88 | void apply(osg::Geometry& geometry); 89 | void apply(osg::Group& group); 90 | void apply(osg::MatrixTransform& transform); 91 | void apply(osg::CoordinateSystemNode& cs); 92 | void apply(osg::Billboard& billboard); 93 | void apply(osg::LOD& lod); 94 | void apply(osg::PagedLOD& plod); 95 | void apply(osg::Switch& sw); 96 | void apply(osgTerrain::TerrainTile& terrainTile); 97 | }; 98 | 99 | } // namespace osg2vsg 100 | -------------------------------------------------------------------------------- /src/osg2vsg/shaders/fbxshader_frag.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | static auto fbxshader_frag = []() {std::istringstream str( 3 | R"(#vsga 0.5.4 4 | Root id=1 vsg::ShaderStage 5 | { 6 | userObjects 0 7 | stage 16 8 | entryPointName "main" 9 | module id=2 vsg::ShaderModule 10 | { 11 | userObjects 0 12 | hints id=0 13 | source "#version 450 14 | #pragma import_defines ( VSG_NORMAL, VSG_COLOR, VSG_TEXCOORD0, VSG_LIGHTING, VSG_MATERIAL, VSG_DIFFUSE_MAP, VSG_OPACITY_MAP, VSG_AMBIENT_MAP, VSG_NORMAL_MAP, VSG_SPECULAR_MAP ) 15 | #extension GL_ARB_separate_shader_objects : enable 16 | #ifdef VSG_DIFFUSE_MAP 17 | layout(binding = 0) uniform sampler2D diffuseMap; 18 | #endif 19 | #ifdef VSG_OPACITY_MAP 20 | layout(binding = 1) uniform sampler2D opacityMap; 21 | #endif 22 | #ifdef VSG_AMBIENT_MAP 23 | layout(binding = 4) uniform sampler2D ambientMap; 24 | #endif 25 | #ifdef VSG_NORMAL_MAP 26 | layout(binding = 5) uniform sampler2D normalMap; 27 | #endif 28 | #ifdef VSG_SPECULAR_MAP 29 | layout(binding = 6) uniform sampler2D specularMap; 30 | #endif 31 | 32 | #ifdef VSG_MATERIAL 33 | layout(binding = 10) uniform MaterialData 34 | { 35 | vec4 ambientColor; 36 | vec4 diffuseColor; 37 | vec4 specularColor; 38 | float shininess; 39 | } material; 40 | #endif 41 | 42 | #ifdef VSG_NORMAL 43 | layout(location = 1) in vec3 normalDir; 44 | #endif 45 | #ifdef VSG_COLOR 46 | layout(location = 3) in vec4 vertColor; 47 | #endif 48 | #ifdef VSG_TEXCOORD0 49 | layout(location = 4) in vec2 texCoord0; 50 | #endif 51 | #ifdef VSG_LIGHTING 52 | layout(location = 5) in vec3 viewDir; 53 | layout(location = 6) in vec3 lightDir; 54 | #endif 55 | layout(location = 0) out vec4 outColor; 56 | 57 | void main() 58 | { 59 | #ifdef VSG_DIFFUSE_MAP 60 | vec4 base = texture(diffuseMap, texCoord0.st); 61 | #else 62 | vec4 base = vec4(1.0,1.0,1.0,1.0); 63 | #endif 64 | #ifdef VSG_COLOR 65 | base = base * vertColor; 66 | #endif 67 | #ifdef VSG_MATERIAL 68 | vec3 ambientColor = material.ambientColor.rgb; 69 | vec3 diffuseColor = material.diffuseColor.rgb; 70 | vec3 specularColor = material.specularColor.rgb; 71 | float shininess = material.shininess; 72 | #else 73 | vec3 ambientColor = vec3(0.1,0.1,0.1); 74 | vec3 diffuseColor = vec3(1.0,1.0,1.0); 75 | vec3 specularColor = vec3(0.3,0.3,0.3); 76 | float shininess = 16.0; 77 | #endif 78 | #ifdef VSG_AMBIENT_MAP 79 | ambientColor *= texture(ambientMap, texCoord0.st).r; 80 | #endif 81 | #ifdef VSG_SPECULAR_MAP 82 | specularColor = texture(specularMap, texCoord0.st).rrr; 83 | #endif 84 | #ifdef VSG_LIGHTING 85 | #ifdef VSG_NORMAL_MAP 86 | vec3 nDir = texture(normalMap, texCoord0.st).xyz*2.0 - 1.0; 87 | nDir.g = -nDir.g; 88 | #else 89 | vec3 nDir = normalDir; 90 | #endif 91 | vec3 nd = normalize(nDir); 92 | vec3 ld = normalize(lightDir); 93 | vec3 vd = normalize(viewDir); 94 | vec4 color = vec4(0.01, 0.01, 0.01, 1.0); 95 | color.rgb += ambientColor; 96 | float diff = max(dot(ld, nd), 0.0); 97 | color.rgb += diffuseColor * diff; 98 | color *= base; 99 | if (diff > 0.0) 100 | { 101 | vec3 halfDir = normalize(ld + vd); 102 | color.rgb += base.a * specularColor * 103 | pow(max(dot(halfDir, nd), 0.0), shininess); 104 | } 105 | #else 106 | vec4 color = base; 107 | color.rgb *= diffuseColor; 108 | #endif 109 | outColor = color; 110 | #ifdef VSG_OPACITY_MAP 111 | outColor.a *= texture(opacityMap, texCoord0.st).r; 112 | #endif 113 | 114 | // crude version of AlphaFunc 115 | if (outColor.a==0.0) discard; 116 | } 117 | " 118 | code 0 119 | 120 | } 121 | NumSpecializationConstants 0 122 | } 123 | )"); 124 | vsg::VSG io; 125 | return io.read_cast(str); 126 | }; 127 | -------------------------------------------------------------------------------- /src/osg2vsg/shaders/fbxshader_vert.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | static auto fbxshader_vert = []() {std::istringstream str( 3 | R"(#vsga 0.5.4 4 | Root id=1 vsg::ShaderStage 5 | { 6 | userObjects 0 7 | stage 1 8 | entryPointName "main" 9 | module id=2 vsg::ShaderModule 10 | { 11 | userObjects 0 12 | hints id=0 13 | source "#version 450 14 | #pragma import_defines ( VSG_NORMAL, VSG_TANGENT, VSG_COLOR, VSG_TEXCOORD0, VSG_LIGHTING, VSG_NORMAL_MAP, VSG_BILLBOARD, VSG_TRANSLATE ) 15 | #extension GL_ARB_separate_shader_objects : enable 16 | layout(push_constant) uniform PushConstants { 17 | mat4 projection; 18 | mat4 modelView; 19 | //mat3 normal; 20 | } pc; 21 | layout(location = 0) in vec3 osg_Vertex; 22 | #ifdef VSG_NORMAL 23 | layout(location = 1) in vec3 osg_Normal; 24 | layout(location = 1) out vec3 normalDir; 25 | #endif 26 | #ifdef VSG_TANGENT 27 | layout(location = 2) in vec4 osg_Tangent; 28 | #endif 29 | #ifdef VSG_COLOR 30 | layout(location = 3) in vec4 osg_Color; 31 | layout(location = 3) out vec4 vertColor; 32 | #endif 33 | #ifdef VSG_TEXCOORD0 34 | layout(location = 4) in vec2 osg_MultiTexCoord0; 35 | layout(location = 4) out vec2 texCoord0; 36 | #endif 37 | #ifdef VSG_LIGHTING 38 | layout(location = 5) out vec3 viewDir; 39 | layout(location = 6) out vec3 lightDir; 40 | #endif 41 | #ifdef VSG_TRANSLATE 42 | layout(location = 7) in vec3 translate; 43 | #endif 44 | 45 | 46 | out gl_PerVertex{ vec4 gl_Position; }; 47 | 48 | void main() 49 | { 50 | mat4 modelView = pc.modelView; 51 | 52 | #ifdef VSG_TRANSLATE 53 | mat4 translate_mat = mat4(1.0, 0.0, 0.0, 0.0, 54 | 0.0, 1.0, 0.0, 0.0, 55 | 0.0, 0.0, 1.0, 0.0, 56 | translate.x, translate.y, translate.z, 1.0); 57 | 58 | modelView = modelView * translate_mat; 59 | #endif 60 | 61 | #ifdef VSG_BILLBOARD 62 | vec3 lookDir = vec3(-modelView[0][2], -modelView[1][2], -modelView[2][2]); 63 | 64 | // rotate around local z axis 65 | float l = length(lookDir.xy); 66 | if (l>0.0) 67 | { 68 | float inv = 1.0/l; 69 | float c = lookDir.y * inv; 70 | float s = lookDir.x * inv; 71 | 72 | mat4 rotation_z = mat4(c, -s, 0.0, 0.0, 73 | s, c, 0.0, 0.0, 74 | 0.0, 0.0, 1.0, 0.0, 75 | 0.0, 0.0, 0.0, 1.0); 76 | 77 | modelView = modelView * rotation_z; 78 | } 79 | #endif 80 | 81 | gl_Position = (pc.projection * modelView) * vec4(osg_Vertex, 1.0); 82 | 83 | #ifdef VSG_TEXCOORD0 84 | texCoord0 = osg_MultiTexCoord0.st; 85 | #endif 86 | #ifdef VSG_NORMAL 87 | vec3 n = (modelView * vec4(osg_Normal, 0.0)).xyz; 88 | normalDir = n; 89 | #endif 90 | #ifdef VSG_LIGHTING 91 | vec4 lpos = /*osg_LightSource.position*/ vec4(0.0, 0.25, 1.0, 0.0); 92 | #ifdef VSG_NORMAL_MAP 93 | vec3 t = (modelView * vec4(osg_Tangent.xyz, 0.0)).xyz; 94 | vec3 b = cross(n, t); 95 | vec3 dir = -vec3(modelView * vec4(osg_Vertex, 1.0)); 96 | viewDir.x = dot(dir, t); 97 | viewDir.y = dot(dir, b); 98 | viewDir.z = dot(dir, n); 99 | if (lpos.w == 0.0) 100 | dir = lpos.xyz; 101 | else 102 | dir += lpos.xyz; 103 | lightDir.x = dot(dir, t); 104 | lightDir.y = dot(dir, b); 105 | lightDir.z = dot(dir, n); 106 | #else 107 | viewDir = -vec3(modelView * vec4(osg_Vertex, 1.0)); 108 | if (lpos.w == 0.0) 109 | lightDir = lpos.xyz; 110 | else 111 | lightDir = lpos.xyz + viewDir; 112 | #endif 113 | #endif 114 | #ifdef VSG_COLOR 115 | vertColor = osg_Color; 116 | #endif 117 | } 118 | " 119 | code 0 120 | 121 | } 122 | NumSpecializationConstants 0 123 | } 124 | )"); 125 | vsg::VSG io; 126 | return io.read_cast(str); 127 | }; 128 | -------------------------------------------------------------------------------- /applications/vsgwithosg/SharedTexture.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright(c) 2019 Thomas Hogarth 4 | 5 | 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: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | 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. 10 | 11 | */ 12 | 13 | #pragma once 14 | 15 | #include 16 | #include 17 | 18 | #if WIN32 19 | #include 20 | #endif 21 | 22 | namespace osg 23 | { 24 | class /*OSG_EXPORT*/ SharedTexture : public Texture 25 | { 26 | public: 27 | 28 | #if WIN32 29 | typedef HANDLE HandleType; 30 | #else 31 | typedef int HandleType; 32 | #endif 33 | 34 | SharedTexture(); 35 | SharedTexture(HandleType handle, GLuint64 byteSize, int width, int height, GLenum format, GLuint tiling, bool isDedicated); 36 | 37 | /** Copy constructor using CopyOp to manage deep vs shallow copy. */ 38 | SharedTexture(const SharedTexture& text, const CopyOp& copyop = CopyOp::SHALLOW_COPY) : 39 | Texture(text, copyop) {} 40 | 41 | META_StateAttribute(osg, SharedTexture, TEXTURE); 42 | 43 | /** Return -1 if *this < *rhs, 0 if *this==*rhs, 1 if *this>*rhs. */ 44 | virtual int compare(const StateAttribute& rhs) const { return (this<&rhs) ? -1 : ((this==&rhs) ? 0 : 1 ); } 45 | 46 | virtual GLenum getTextureTarget() const { return GL_TEXTURE_2D; } 47 | 48 | 49 | /** Sets the texture image. */ 50 | void setImage(Image* image) { _image = image; } 51 | 52 | template void setImage(const ref_ptr& image) { setImage(image.get()); } 53 | 54 | /** Gets the texture image. */ 55 | Image* getImage() { return _image.get(); } 56 | 57 | /** Gets the const texture image. */ 58 | inline const Image* getImage() const { return _image.get(); } 59 | 60 | /** Sets the texture image, ignoring face. */ 61 | virtual void setImage(unsigned int, Image* image) { setImage(image); } 62 | 63 | template void setImage(unsigned int, const ref_ptr& image) { setImage(image.get()); } 64 | 65 | /** Gets the texture image, ignoring face. */ 66 | virtual Image* getImage(unsigned int) { return _image.get(); } 67 | 68 | /** Gets the const texture image, ignoring face. */ 69 | virtual const Image* getImage(unsigned int) const { return _image.get(); } 70 | 71 | /** Gets the number of images that can be assigned to the Texture. */ 72 | virtual unsigned int getNumImages() const { return 1; } 73 | 74 | 75 | virtual void apply(State& state) const; 76 | 77 | static std::vector getSupportedTilingTypesForFormat(const osg::State& state, GLenum format = GL_RGBA8); 78 | 79 | protected: 80 | virtual ~SharedTexture(); 81 | 82 | virtual void computeInternalFormat() const { computeInternalFormatType(); } 83 | void allocateMipmap(State& /*state*/) const {} 84 | 85 | GLuint64 _byteSize; 86 | GLsizei _textureWidth; 87 | GLsizei _textureHeight; 88 | 89 | HandleType _handle; 90 | GLuint _tiling; 91 | //GLuint _memory; 92 | bool _isDedicated; 93 | 94 | osg::ref_ptr _image; 95 | }; 96 | } 97 | 98 | -------------------------------------------------------------------------------- /src/osg2vsg/ShaderUtils.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright(c) 2019 Thomas Hogarth and Robert Osfield 4 | 5 | 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: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | 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. 10 | 11 | */ 12 | 13 | #include "ShaderUtils.h" 14 | #include "GeometryUtils.h" 15 | 16 | #include 17 | #include 18 | 19 | using namespace osg2vsg; 20 | 21 | uint32_t osg2vsg::calculateShaderModeMask(const osg::StateSet* stateSet) 22 | { 23 | uint32_t stateMask = 0; 24 | if (stateSet) 25 | { 26 | if (stateSet->getMode(GL_BLEND) & osg::StateAttribute::ON) stateMask |= BLEND; 27 | if (stateSet->getMode(GL_LIGHTING) & osg::StateAttribute::ON) stateMask |= LIGHTING; 28 | 29 | auto asMaterial = dynamic_cast(stateSet->getAttribute(osg::StateAttribute::Type::MATERIAL)); 30 | if (asMaterial && stateSet->getMode(GL_COLOR_MATERIAL) == osg::StateAttribute::Values::ON) stateMask |= MATERIAL; 31 | 32 | auto hasTextureWithImageInChannel = [stateSet](unsigned int channel) { 33 | auto asTex = dynamic_cast(stateSet->getTextureAttribute(channel, osg::StateAttribute::TEXTURE)); 34 | if (asTex && asTex->getImage(0)) return true; 35 | return false; 36 | }; 37 | 38 | if (hasTextureWithImageInChannel(DIFFUSE_TEXTURE_UNIT)) stateMask |= DIFFUSE_MAP; 39 | if (hasTextureWithImageInChannel(OPACITY_TEXTURE_UNIT)) stateMask |= OPACITY_MAP; 40 | if (hasTextureWithImageInChannel(AMBIENT_TEXTURE_UNIT)) stateMask |= AMBIENT_MAP; 41 | if (hasTextureWithImageInChannel(NORMAL_TEXTURE_UNIT)) stateMask |= NORMAL_MAP; 42 | if (hasTextureWithImageInChannel(SPECULAR_TEXTURE_UNIT)) stateMask |= SPECULAR_MAP; 43 | } 44 | return stateMask; 45 | } 46 | 47 | // create defines string based on shader mask 48 | 49 | std::set osg2vsg::createPSCDefineStrings(const uint32_t& shaderModeMask, const uint32_t& geometryAttrbutes) 50 | { 51 | bool hasnormal = geometryAttrbutes & NORMAL; 52 | bool hastangent = geometryAttrbutes & TANGENT; 53 | bool hascolor = geometryAttrbutes & COLOR; 54 | bool hastex0 = geometryAttrbutes & TEXCOORD0; 55 | 56 | std::set defines; 57 | 58 | // vertex inputs 59 | if (hasnormal) defines.insert("VSG_NORMAL"); 60 | if (hascolor) defines.insert("VSG_COLOR"); 61 | if (hastex0) defines.insert("VSG_TEXCOORD0"); 62 | if (hastangent) defines.insert("VSG_TANGENT"); 63 | 64 | // shading modes/maps 65 | if (hasnormal && (shaderModeMask & LIGHTING)) defines.insert("VSG_LIGHTING"); 66 | 67 | if (shaderModeMask & MATERIAL) defines.insert("VSG_MATERIAL"); 68 | 69 | if (hastex0 && (shaderModeMask & DIFFUSE_MAP)) defines.insert("VSG_DIFFUSE_MAP"); 70 | if (hastex0 && (shaderModeMask & OPACITY_MAP)) defines.insert("VSG_OPACITY_MAP"); 71 | if (hastex0 && (shaderModeMask & AMBIENT_MAP)) defines.insert("VSG_AMBIENT_MAP"); 72 | if (hastex0 && (shaderModeMask & NORMAL_MAP)) defines.insert("VSG_NORMAL_MAP"); 73 | if (hastex0 && (shaderModeMask & SPECULAR_MAP)) defines.insert("VSG_SPECULAR_MAP"); 74 | 75 | if (shaderModeMask & BILLBOARD) defines.insert("VSG_BILLBOARD"); 76 | 77 | if (shaderModeMask & SHADER_TRANSLATE) defines.insert("VSG_TRANSLATE"); 78 | 79 | return defines; 80 | } 81 | -------------------------------------------------------------------------------- /src/osgPlugins/vsg/ReaderWriterVSG.cpp: -------------------------------------------------------------------------------- 1 | // Released under the OSGPL license, as part of the OpenSceneGraph distribution. 2 | // 3 | // ReaderWriter for converting and writing scenes to vsgt/vsgb files. Reading files back in is not currently implemented. 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | namespace osg2vsg 16 | { 17 | vsg::ref_ptr convertToVsg(const osg::Image* osg_image) 18 | { 19 | vsg::info("convertToVsg(", osg_image, ")"); 20 | return {}; 21 | } 22 | 23 | vsg::ref_ptr convertToVsg(const osg::Node* osg_node) 24 | { 25 | vsg::info("convertToVsg(", osg_node, ")"); 26 | return {}; 27 | } 28 | } 29 | 30 | 31 | class ReaderWriterVSG : public osgDB::ReaderWriter 32 | { 33 | public: 34 | 35 | ReaderWriterVSG() 36 | { 37 | supportsExtension("vsga","vsg ascii format"); 38 | supportsExtension("vsgt","vsg ascii format"); 39 | supportsExtension("vsgb","vsg binary format"); 40 | } 41 | 42 | virtual const char* className() const { return "VSG Reader/Writer"; } 43 | 44 | 45 | virtual ReadResult readObject(const std::string& file, const osgDB::ReaderWriter::Options* options) const 46 | { 47 | std::string ext = osgDB::getLowerCaseFileExtension(file); 48 | if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED; 49 | 50 | std::string filename = osgDB::findDataFile( file, options ); 51 | if (filename.empty()) return ReadResult::FILE_NOT_FOUND; 52 | 53 | auto object = vsg::read(filename); 54 | 55 | OSG_NOTICE<<"VSG data loaded "< vsg_options; 84 | 85 | if (vsg_data) return vsg::write(vsg_data, filename, vsg_options) ? WriteResult::FILE_SAVED : WriteResult::FILE_NOT_HANDLED; 86 | else return WriteResult::FILE_NOT_HANDLED; 87 | } 88 | 89 | virtual WriteResult writeNode(const osg::Node& node, const std::string& filename, const osgDB::ReaderWriter::Options* /*options*/) const 90 | { 91 | std::string ext = osgDB::getFileExtension(filename); 92 | if (!acceptsExtension(ext)) return WriteResult::FILE_NOT_HANDLED; 93 | 94 | auto vsg_node = osg2vsg::convertToVsg(&node); 95 | vsg::ref_ptr vsg_options; 96 | 97 | if (vsg_node) return vsg::write(vsg_node, filename, vsg_options) ? WriteResult::FILE_SAVED : WriteResult::FILE_NOT_HANDLED; 98 | else return WriteResult::FILE_NOT_HANDLED; 99 | } 100 | 101 | }; 102 | 103 | // now register with Registry to instantiate the above 104 | // reader/writer. 105 | REGISTER_OSGPLUGIN(vsg, ReaderWriterVSG) 106 | -------------------------------------------------------------------------------- /applications/vsgwithosg/GLMemoryExtensions.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright(c) 2019 Thomas Hogarth 4 | 5 | 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: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | 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. 10 | 11 | */ 12 | 13 | #pragma once 14 | 15 | #include 16 | 17 | 18 | #ifndef GL_EXT_memory_object 19 | #define GL_TEXTURE_TILING_EXT 0x9580 20 | #define GL_DEDICATED_MEMORY_OBJECT_EXT 0x9581 21 | #define GL_PROTECTED_MEMORY_OBJECT_EXT 0x959B 22 | #define GL_NUM_TILING_TYPES_EXT 0x9582 23 | #define GL_TILING_TYPES_EXT 0x9583 24 | #define GL_OPTIMAL_TILING_EXT 0x9584 25 | #define GL_LINEAR_TILING_EXT 0x9585 26 | #endif 27 | 28 | #if WIN32 29 | #ifndef GL_EXT_memory_object_win32 30 | #define GL_HANDLE_TYPE_OPAQUE_WIN32_EXT 0x9587 31 | #endif 32 | #else 33 | #ifndef GL_EXT_memory_object_fd 34 | #define GL_HANDLE_TYPE_OPAQUE_FD_EXT 0x9586 35 | #endif 36 | #endif 37 | 38 | #ifndef GL_EXT_semaphore 39 | #define GL_LAYOUT_GENERAL_EXT 0x958D 40 | #define GL_LAYOUT_COLOR_ATTACHMENT_EXT 0x958E 41 | #define GL_LAYOUT_DEPTH_STENCIL_ATTACHMENT_EXT 0x958F 42 | #define GL_LAYOUT_DEPTH_STENCIL_READ_ONLY_EXT 0x9590 43 | #define GL_LAYOUT_SHADER_READ_ONLY_EXT 0x9591 44 | #define GL_LAYOUT_TRANSFER_SRC_EXT 0x9592 45 | #define GL_LAYOUT_TRANSFER_DST_EXT 0x9593 46 | #define GL_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_EXT 0x9530 47 | #define GL_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_EXT 0x9531 48 | #endif 49 | 50 | namespace osg 51 | { 52 | 53 | class GLMemoryExtensions : public osg::Referenced 54 | { 55 | public: 56 | static GLMemoryExtensions* Get(unsigned int contextID, bool createIfNotInitalized); 57 | 58 | GLMemoryExtensions(unsigned int in_contextID); 59 | 60 | void (GL_APIENTRY * glGetInternalformativ) (GLenum, GLenum, GLenum, GLsizei, GLint*); 61 | 62 | void (GL_APIENTRY * glCreateTextures) (GLenum, GLsizei, GLuint*); 63 | void (GL_APIENTRY * glTextureParameteri) (GLenum, GLenum, GLint); 64 | 65 | void (GL_APIENTRY * glCopyImageSubData) (GLuint, GLenum, GLint, GLint, GLint, GLint, GLuint, GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei); 66 | 67 | // memory objects 68 | void (GL_APIENTRY * glCreateMemoryObjectsEXT) (GLsizei, GLuint*); 69 | void (GL_APIENTRY * glMemoryObjectParameterivEXT) (GLuint, GLenum, const GLint*); 70 | #if WIN32 71 | void (GL_APIENTRY * glImportMemoryWin32HandleEXT) (GLuint, GLuint64, GLenum, void*); 72 | #else 73 | void (GL_APIENTRY * glImportMemoryFdEXT) (GLuint, GLuint64, GLenum, GLint); 74 | #endif 75 | 76 | void (GL_APIENTRY * glTextureStorageMem2DEXT) (GLuint, GLsizei, GLenum, GLsizei, GLsizei, GLuint, GLuint64); 77 | 78 | // semaphores 79 | void (GL_APIENTRY * glGenSemaphoresEXT) (GLsizei, GLuint*); 80 | void (GL_APIENTRY * glDeleteSemaphoresEXT) (GLsizei, const GLuint*); 81 | GLboolean (GL_APIENTRY * glIsSemaphoreEXT) (GLuint); 82 | void (GL_APIENTRY * glSemaphoreParameterui64vEXT) (GLuint, GLenum, const GLuint64*); 83 | void (GL_APIENTRY * glGetSemaphoreParameterui64vEXT) (GLuint, GLenum, GLuint64*); 84 | void (GL_APIENTRY * glWaitSemaphoreEXT) (GLuint, GLuint, const GLuint*, GLuint, const GLuint*, const GLenum*); 85 | void (GL_APIENTRY * glSignalSemaphoreEXT) (GLuint, GLuint, const GLuint*, GLuint, const GLuint*, const GLenum*); 86 | 87 | #if WIN32 88 | void (GL_APIENTRY * glImportSemaphoreWin32HandleEXT) (GLuint, GLenum, void*); 89 | #else 90 | void (GL_APIENTRY * glImportSemaphoreFdEXT) (GLuint, GLenum, GLint); 91 | #endif 92 | }; 93 | } 94 | 95 | -------------------------------------------------------------------------------- /applications/osggroups/osggroups.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | //#define INLINE_TRAVERSE 14 | 15 | class OsgVisitor: public osg::NodeVisitor 16 | { 17 | public: 18 | 19 | OsgVisitor(): 20 | osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN), 21 | numNodes(0) 22 | {} 23 | 24 | unsigned int numNodes; 25 | 26 | using NodeVisitor::apply; 27 | 28 | void apply(osg::Node& node) override 29 | { 30 | ++numNodes; 31 | traverse(node); 32 | } 33 | 34 | }; 35 | 36 | osg::Node* createOsgQuadTree(unsigned int numLevels, unsigned int& numNodes, unsigned int& numBytes) 37 | { 38 | if (numLevels==0) 39 | { 40 | numNodes += 1; 41 | numBytes += sizeof(osg::Node); 42 | 43 | return new osg::Node; 44 | } 45 | 46 | osg::Group* t = new osg::Group; 47 | 48 | numNodes += 1; 49 | numBytes += sizeof(osg::Group) + 4*sizeof(osg::ref_ptr); 50 | 51 | --numLevels; 52 | 53 | t->addChild(createOsgQuadTree(numLevels, numNodes, numBytes)); 54 | t->addChild(createOsgQuadTree(numLevels, numNodes, numBytes)); 55 | t->addChild(createOsgQuadTree(numLevels, numNodes, numBytes)); 56 | t->addChild(createOsgQuadTree(numLevels, numNodes, numBytes)); 57 | 58 | return t; 59 | } 60 | 61 | int main(int argc, char** argv) 62 | { 63 | osg::ArgumentParser arguments(&argc, argv); 64 | 65 | uint32_t numLevels = 11; 66 | uint32_t numTraversals = 10; 67 | if (arguments.read("-l",numLevels)) {} 68 | if (arguments.read("-t",numTraversals)) {} 69 | 70 | bool quiet = arguments.read("-q"); 71 | 72 | std::string inputFilename, outputFilename; 73 | if (arguments.read("-i", inputFilename)) {} 74 | if (arguments.read("-o", outputFilename)) {} 75 | 76 | 77 | using clock = std::chrono::high_resolution_clock; 78 | clock::time_point start = clock::now(); 79 | 80 | unsigned int numNodes = 0; 81 | unsigned int numBytes = 0; 82 | osg::ref_ptr osg_root; 83 | 84 | if (!inputFilename.empty()) 85 | { 86 | osg_root = osgDB::readNodeFile(inputFilename); 87 | } 88 | else 89 | { 90 | osg_root = createOsgQuadTree(numLevels, numNodes, numBytes); 91 | } 92 | 93 | clock::time_point after_construction = clock::now(); 94 | 95 | unsigned int numNodesVisited = 0; 96 | 97 | std::cout<<"using OsgVisitor"<accept(visitor); 102 | numNodesVisited += visitor.numNodes; 103 | } 104 | 105 | clock::time_point after_traversal = clock::now(); 106 | 107 | if (!outputFilename.empty()) 108 | { 109 | osgDB::writeNodeFile(*osg_root, outputFilename); 110 | } 111 | 112 | clock::time_point after_write = clock::now(); 113 | 114 | osg_root = 0; 115 | 116 | clock::time_point after_destruction = clock::now(); 117 | 118 | if (!quiet) 119 | { 120 | std::cout<<"numNodes : "<(after_construction-start).count()<(after_construction-start).count()<(after_traversal-after_construction).count()<(after_write-after_traversal).count()<(after_destruction-after_write).count()<(after_destruction-start).count()<(after_construction-start).count()<(after_traversal-after_construction).count()<(after_destruction-after_traversal).count()< 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "BuildOptions.h" 13 | 14 | namespace osg2vsg 15 | { 16 | class SceneBuilderBase 17 | { 18 | public: 19 | SceneBuilderBase() {} 20 | 21 | SceneBuilderBase(vsg::ref_ptr options) : 22 | buildOptions(options) {} 23 | 24 | using StateStack = std::vector>; 25 | using StateSets = std::set; 26 | using StatePair = std::pair, osg::ref_ptr>; 27 | using StateMap = std::map; 28 | using GeometriesMap = std::map>; 29 | 30 | using TexturesMap = std::map>; 31 | 32 | struct UniqueStateSet 33 | { 34 | bool operator()(const osg::ref_ptr& lhs, const osg::ref_ptr& rhs) const 35 | { 36 | if (!lhs) return true; 37 | if (!rhs) return false; 38 | return lhs->compare(*rhs) < 0; 39 | } 40 | }; 41 | 42 | using UniqueStats = std::set, UniqueStateSet>; 43 | 44 | vsg::ref_ptr buildOptions = BuildOptions::create(); 45 | 46 | uint32_t nodeShaderModeMasks = ShaderModeMask::NONE; 47 | 48 | StateStack statestack; 49 | StateMap stateMap; 50 | UniqueStats uniqueStateSets; 51 | TexturesMap texturesMap; 52 | bool writeToFileProgramAndDataSetSets = false; 53 | 54 | osg::ref_ptr uniqueState(osg::ref_ptr stateset, bool programStateSet); 55 | 56 | StatePair computeStatePair(osg::StateSet* stateset); 57 | StatePair& getStatePair(); 58 | 59 | // core VSG style usage 60 | vsg::ref_ptr convertToVsgTexture(const osg::Texture* osgtexture); 61 | 62 | vsg::ref_ptr createVsgStateSet(vsg::ref_ptr descriptorSetLayout, const osg::StateSet* stateset, uint32_t shaderModeMask); 63 | }; 64 | 65 | class SceneBuilder : public osg::NodeVisitor, public SceneBuilderBase 66 | { 67 | public: 68 | SceneBuilder() : 69 | osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN) {} 70 | 71 | SceneBuilder(vsg::ref_ptr options) : 72 | osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN), 73 | SceneBuilderBase(options) {} 74 | 75 | using Geometries = std::vector>; 76 | using StateGeometryMap = std::map, Geometries>; 77 | using TransformGeometryMap = std::map; 78 | using MatrixStack = std::vector; 79 | 80 | struct TransformStatePair 81 | { 82 | std::map matrixStateGeometryMap; 83 | std::map, TransformGeometryMap> stateTransformMap; 84 | }; 85 | 86 | using Masks = std::pair; 87 | using MasksTransformStateMap = std::map; 88 | 89 | using ProgramTransformStateMap = std::map, TransformStatePair>; 90 | 91 | MatrixStack matrixstack; 92 | ProgramTransformStateMap programTransformStateMap; 93 | MasksTransformStateMap masksTransformStateMap; 94 | GeometriesMap geometriesMap; 95 | 96 | osg::ref_ptr createStateGeometryGraphOSG(StateGeometryMap& stateGeometryMap); 97 | osg::ref_ptr createTransformGeometryGraphOSG(TransformGeometryMap& transformGeometryMap); 98 | osg::ref_ptr createOSG(); 99 | 100 | vsg::ref_ptr createTransformGeometryGraphVSG(TransformGeometryMap& transformGeometryMap, vsg::Paths& searchPaths, uint32_t requiredGeomAttributesMask); 101 | 102 | vsg::ref_ptr createVSG(vsg::Paths& searchPaths); 103 | 104 | void apply(osg::Node& node); 105 | void apply(osg::Group& group); 106 | void apply(osg::Transform& transform); 107 | void apply(osg::Billboard& billboard); 108 | void apply(osg::Geometry& geometry); 109 | 110 | void pushStateSet(osg::StateSet& stateset); 111 | void popStateSet(); 112 | 113 | void pushMatrix(const osg::Matrix& matrix); 114 | void popMatrix(); 115 | 116 | void print(); 117 | 118 | vsg::ref_ptr optimizeAndConvertToVsg(osg::ref_ptr scene, vsg::Paths& searchPaths); 119 | }; 120 | } // namespace osg2vsg 121 | -------------------------------------------------------------------------------- /applications/vsgobjects/vsgobjects.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | 15 | class MyVisitor : public vsg::Visitor 16 | { 17 | public: 18 | MyVisitor() {} 19 | 20 | using vsg::Visitor::apply; 21 | 22 | void apply(vsg::Object& object) final 23 | { 24 | std::cout<<"MyVisitor::apply(Object& "<<&object<<")"< global; 59 | { 60 | std::cout<<"---- Start of block"<addChild(vsg::Node::create()); 66 | group->addChild(vsg::Group::create()); 67 | 68 | //std::cout<<"++++ Removing child from group"<removeChild(pos); 70 | 71 | group->setObject("userdata", vsg::Object::create()); 72 | group->setObject(vsg::make_string(10), vsg::Object::create()); 73 | group->setObject(vsg::make_string("list",5), vsg::Object::create()); 74 | 75 | group->setValue("name", std::string("[first node]")); 76 | group->setValue("height", 1.52f); 77 | 78 | 79 | //vsg::ref_ptr osg = new OsgClass; 80 | 81 | 82 | global = group; 83 | std::cout<<"---- End of block"<accept(visitor); 88 | 89 | 90 | std::cout<<" global->getObject(\"userdata\") = "<getObject("userdata")<getValue("name", name)) std::cout<<" global->getValue(\"name\") = "<getValue(\"name\") failed "<getValue("height", height)) std::cout<<" global->getValue(\"height\") = "<getValue(\"height\") failed "< observer; 101 | 102 | //observer = global.get(); 103 | observer = global; 104 | 105 | std::cout<<"******"< access = observer; 108 | std::cout<<"++++ access.get() "<referenceCount()<referenceCount()<(end-start).count(); 119 | std::cout<<"-- After, elapsed time "< "< "< "< "< "< "< "< "< "< "< "< "< 2 | 3 | Copyright(c) 2019 Thomas Hogarth 4 | 5 | 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: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | 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. 10 | 11 | */ 12 | 13 | #pragma once 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | #include "SharedSemaphore.h" 20 | #include "GLMemoryExtensions.h" 21 | 22 | namespace osg 23 | { 24 | class SemaphoreDrawCallback : public osg::Camera::DrawCallback 25 | { 26 | public: 27 | 28 | SemaphoreDrawCallback(SharedTexture* tex, GLenum layout, ref_ptr semaphore, bool wait) : 29 | osg::Camera::DrawCallback(), 30 | _texture(tex), 31 | _layout(layout), 32 | _semaphore(semaphore), 33 | _wait(wait) 34 | { 35 | } 36 | 37 | virtual void operator () (osg::RenderInfo& renderInfo) const 38 | { 39 | GLMemoryExtensions* extensions = GLMemoryExtensions::Get(renderInfo.getContextID(), true); 40 | 41 | std::vector semaphoreBuffers; 42 | std::vector semaphoreTextures; 43 | semaphoreTextures.push_back(_texture->getTextureObject(renderInfo.getContextID())->id()); 44 | 45 | if(_wait) 46 | { 47 | // wait on the semaphone 48 | _semaphore->wait(*renderInfo.getState(), semaphoreBuffers, semaphoreTextures, {_layout}); 49 | } 50 | else 51 | { 52 | // signal complete semaphone 53 | _semaphore->signal(*renderInfo.getState(), semaphoreBuffers, semaphoreTextures, {_layout}); 54 | } 55 | 56 | } 57 | 58 | protected: 59 | virtual ~SemaphoreDrawCallback() {} 60 | 61 | osg::ref_ptr _texture; 62 | GLenum _layout; 63 | 64 | ref_ptr _semaphore; 65 | bool _wait; 66 | }; 67 | 68 | class SyncTextureDrawCallback : public osg::Camera::DrawCallback 69 | { 70 | public: 71 | using SyncTextureMappings = std::map; 72 | 73 | SyncTextureDrawCallback(SyncTextureMappings mappings, bool syncTo, std::vector srcLayouts, std::vector dstLayouts, ref_ptr waitSemaphore, ref_ptr completeSemaphore) : 74 | osg::Camera::DrawCallback(), 75 | _mappings(mappings), 76 | _syncTo(syncTo), 77 | _srcLayouts(srcLayouts), 78 | _dstLayouts(dstLayouts), 79 | _waitSemaphore(waitSemaphore), 80 | _completeSemaphore(completeSemaphore) 81 | { 82 | } 83 | 84 | virtual void operator () (osg::RenderInfo& renderInfo) const 85 | { 86 | GLMemoryExtensions* extensions = GLMemoryExtensions::Get(renderInfo.getContextID(), true); 87 | 88 | std::vector semaphoreBuffers; 89 | std::vector semaphoreTextures; 90 | for (auto const& texpair : _mappings) 91 | { 92 | semaphoreTextures.push_back(texpair.second->getTextureObject(renderInfo.getContextID())->id()); 93 | } 94 | 95 | // wait on the semaphone 96 | _waitSemaphore->wait(*renderInfo.getState(), semaphoreBuffers, semaphoreTextures, _srcLayouts); 97 | 98 | // copy the textures into the shared textures 99 | for (auto const& texpair : _mappings) 100 | { 101 | GLenum srcId = _syncTo ? texpair.first->getTextureObject(renderInfo.getContextID())->id() : texpair.second->getTextureObject(renderInfo.getContextID())->id(); 102 | GLenum dstId = _syncTo ? texpair.second->getTextureObject(renderInfo.getContextID())->id() : texpair.first->getTextureObject(renderInfo.getContextID())->id(); 103 | extensions->glCopyImageSubData(srcId, GL_TEXTURE_2D, 0, 0, 0, 0, dstId, GL_TEXTURE_2D, 0, 0, 0, 0, texpair.first->getTextureWidth(), texpair.first->getTextureHeight(), 1); 104 | } 105 | 106 | // signal complete semaphone 107 | _completeSemaphore->signal(*renderInfo.getState(), semaphoreBuffers, semaphoreTextures, _dstLayouts); 108 | } 109 | 110 | protected: 111 | virtual ~SyncTextureDrawCallback() {} 112 | 113 | SyncTextureMappings _mappings; 114 | bool _syncTo; 115 | 116 | std::vector _srcLayouts; 117 | std::vector _dstLayouts; 118 | 119 | ref_ptr _waitSemaphore; 120 | ref_ptr _completeSemaphore; 121 | }; 122 | } 123 | 124 | -------------------------------------------------------------------------------- /applications/vsgwithosg/SharedTexture.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright(c) 2019 Thomas Hogarth 4 | 5 | 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: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | 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. 10 | 11 | */ 12 | 13 | #include "SharedTexture.h" 14 | 15 | #include "GLMemoryExtensions.h" 16 | 17 | #include 18 | 19 | using namespace osg; 20 | 21 | #define DEPRECATED_OPENSCENEGRAPH_3_7_0 (OPENSCENEGRAPH_MAJOR_VERSION == 3 && OPENSCENEGRAPH_MINOR_VERSION == 7 && OPENSCENEGRAPH_PATCH_VERSION == 0) 22 | 23 | SharedTexture::SharedTexture() : 24 | Texture(), 25 | _byteSize(0), 26 | _textureWidth(0), 27 | _textureHeight(0), 28 | _handle(0), 29 | _tiling(0), 30 | _isDedicated(false) 31 | { 32 | setUseHardwareMipMapGeneration(false); 33 | setResizeNonPowerOfTwoHint(false); 34 | } 35 | 36 | SharedTexture::SharedTexture(HandleType handle, GLuint64 byteSize, int width, int height, GLenum internalFormat, GLuint tiling, bool isDedicated) : 37 | Texture(), 38 | _byteSize(byteSize), 39 | _textureWidth(width), 40 | _textureHeight(height), 41 | _handle(handle), 42 | _tiling(tiling), 43 | _isDedicated(isDedicated) 44 | { 45 | setInternalFormat(internalFormat); 46 | setUseHardwareMipMapGeneration(false); 47 | setResizeNonPowerOfTwoHint(false); 48 | } 49 | 50 | 51 | SharedTexture::~SharedTexture() 52 | { 53 | } 54 | 55 | void SharedTexture::apply(State& state) const 56 | { 57 | const unsigned int contextID = state.getContextID(); 58 | 59 | // get the texture object for the current contextID. 60 | TextureObject* textureObject = getTextureObject(contextID); 61 | 62 | if (textureObject) 63 | { 64 | #if DEPRECATED_OPENSCENEGRAPH_3_7_0 65 | textureObject->bind(state); 66 | #else 67 | textureObject->bind(); 68 | #endif 69 | } 70 | else 71 | { 72 | const osg::GLMemoryExtensions * extensions = GLMemoryExtensions::Get(state.getContextID(), true); 73 | if (!extensions->glCreateMemoryObjectsEXT) return; 74 | 75 | // compute the internal texture format, this set the _internalFormat to an appropriate value. 76 | computeInternalFormat(); 77 | 78 | GLenum texStorageSizedInternalFormat = (GLenum)_internalFormat; //selectSizedInternalFormat(NULL); 79 | 80 | // this could potentially return a recycled texture object which we don't want!!! 81 | textureObject = generateAndAssignTextureObject(contextID, GL_TEXTURE_2D, 1, 82 | texStorageSizedInternalFormat != 0 ? texStorageSizedInternalFormat : _internalFormat, 83 | _textureWidth, _textureHeight, 1, 0); 84 | 85 | #if DEPRECATED_OPENSCENEGRAPH_3_7_0 86 | textureObject->bind(state); 87 | #else 88 | textureObject->bind(); 89 | #endif 90 | 91 | applyTexParameters(GL_TEXTURE_2D, state); 92 | 93 | // create memory object 94 | GLuint memory = 0; 95 | extensions->glCreateMemoryObjectsEXT(1, &memory); 96 | if (_isDedicated) 97 | { 98 | static const GLint DEDICATED_FLAG = GL_TRUE; 99 | extensions->glMemoryObjectParameterivEXT(memory, GL_DEDICATED_MEMORY_OBJECT_EXT, &DEDICATED_FLAG); 100 | } 101 | 102 | #if WIN32 103 | extensions->glImportMemoryWin32HandleEXT(memory, _byteSize, GL_HANDLE_TYPE_OPAQUE_WIN32_EXT, _handle); 104 | #else 105 | extensions->glImportMemoryFdEXT(memory, _byteSize, GL_HANDLE_TYPE_OPAQUE_FD_EXT, _handle); 106 | #endif 107 | 108 | // create texture storage using the memory 109 | extensions->glTextureParameteri(textureObject->id(), GL_TEXTURE_TILING_EXT, _tiling); 110 | extensions->glTextureStorageMem2DEXT(textureObject->id(), 1, texStorageSizedInternalFormat, _textureWidth, _textureHeight, memory, 0); 111 | 112 | osg::ref_ptr image = _image; 113 | if(image.valid()) 114 | { 115 | unsigned char* dataPtr = (unsigned char*)image->data(); 116 | glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 117 | _textureWidth, _textureHeight, 118 | (GLenum)image->getPixelFormat(), 119 | (GLenum)image->getDataType(), 120 | dataPtr); 121 | } 122 | 123 | textureObject->setAllocated(true); 124 | } 125 | } 126 | 127 | std::vector SharedTexture::getSupportedTilingTypesForFormat(const osg::State& state, GLenum format) 128 | { 129 | std::vector results; 130 | 131 | const osg::GLMemoryExtensions* extensions = osg::GLMemoryExtensions::Get(state.getContextID(), true); 132 | 133 | GLint numTilingTypes = 0; 134 | extensions->glGetInternalformativ(GL_TEXTURE_2D, format, GL_NUM_TILING_TYPES_EXT, 1, &numTilingTypes); 135 | 136 | // Broken tiling detection on AMD 137 | if (numTilingTypes == 0) 138 | { 139 | results.push_back(GL_LINEAR_TILING_EXT); 140 | return results; 141 | } 142 | 143 | results.resize(numTilingTypes); 144 | extensions->glGetInternalformativ(GL_TEXTURE_2D, format, GL_TILING_TYPES_EXT, numTilingTypes, results.data()); 145 | 146 | return results; 147 | } 148 | -------------------------------------------------------------------------------- /src/osg2vsg/SceneAnalysis.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright(c) 2019 Thomas Hogarth and Robert Osfield 4 | 5 | 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: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | 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. 10 | 11 | */ 12 | 13 | #include "SceneAnalysis.h" 14 | 15 | using namespace osg2vsg; 16 | 17 | void SceneStats::print(std::ostream& out) 18 | { 19 | out << "SceneStats class count: " << typeFrequencyMap.size() << "\n"; 20 | size_t longestClassName = 0; 21 | for (auto& entry : typeFrequencyMap) 22 | { 23 | longestClassName = std::max(strlen(entry.first), longestClassName); 24 | } 25 | 26 | out << "\nUnique objects:\n"; 27 | out << " className"; 28 | for (size_t i = strlen("className"); i < longestClassName; ++i) out << " "; 29 | out << "\tObjects\n"; 30 | 31 | for (auto& [className, objectFrequencyMap] : typeFrequencyMap) 32 | { 33 | uint32_t totalInstances = 0; 34 | for (auto& entry : objectFrequencyMap) 35 | { 36 | totalInstances += entry.second; 37 | } 38 | 39 | if (objectFrequencyMap.size() == totalInstances) 40 | { 41 | out << " " << className << ""; 42 | for (size_t i = strlen(className); i < longestClassName; ++i) out << " "; 43 | out << "\t" << objectFrequencyMap.size() << "\n"; 44 | } 45 | } 46 | 47 | out << "\nShared objects:\n"; 48 | out << " className"; 49 | for (size_t i = strlen("className"); i < longestClassName; ++i) out << " "; 50 | out << "\tObjects\tInstances\n"; 51 | 52 | for (auto& [className, objectFrequencyMap] : typeFrequencyMap) 53 | { 54 | uint32_t totalInstances = 0; 55 | for (auto& entry : objectFrequencyMap) 56 | { 57 | totalInstances += entry.second; 58 | } 59 | 60 | if (objectFrequencyMap.size() != totalInstances) 61 | { 62 | out << " " << className << ""; 63 | for (size_t i = strlen(className); i < longestClassName; ++i) out << " "; 64 | out << "\t" << objectFrequencyMap.size() << "\t" << totalInstances << "\n"; 65 | } 66 | } 67 | out << std::endl; 68 | } 69 | 70 | /////////////////////////////////////////////////////////////////////////////////// 71 | // 72 | // OsgSceneAnalysis 73 | // 74 | OsgSceneAnalysis::OsgSceneAnalysis() : 75 | osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN), 76 | _sceneStats(new SceneStats) 77 | { 78 | } 79 | 80 | OsgSceneAnalysis::OsgSceneAnalysis(SceneStats* sceneStats) : 81 | osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN), 82 | _sceneStats(sceneStats) 83 | { 84 | } 85 | 86 | void OsgSceneAnalysis::apply(osg::Node& node) 87 | { 88 | if (node.getStateSet()) apply(*node.getStateSet()); 89 | 90 | _sceneStats->insert(&node); 91 | 92 | node.traverse(*this); 93 | } 94 | 95 | void OsgSceneAnalysis::apply(osg::Geometry& geometry) 96 | { 97 | if (geometry.getStateSet()) apply(*geometry.getStateSet()); 98 | 99 | _sceneStats->insert(&geometry); 100 | 101 | osg::Geometry::ArrayList arrayList; 102 | geometry.getArrayList(arrayList); 103 | for (auto& array : arrayList) 104 | { 105 | _sceneStats->insert(array.get()); 106 | } 107 | 108 | for (auto& primitiveSet : geometry.getPrimitiveSetList()) 109 | { 110 | _sceneStats->insert(primitiveSet.get()); 111 | } 112 | } 113 | 114 | void OsgSceneAnalysis::apply(osg::StateSet& stateset) 115 | { 116 | _sceneStats->insert(&stateset); 117 | 118 | for (auto& attribute : stateset.getAttributeList()) 119 | { 120 | _sceneStats->insert(attribute.second.first.get()); 121 | } 122 | 123 | for (auto& textureList : stateset.getTextureAttributeList()) 124 | { 125 | for (auto& attribute : textureList) 126 | { 127 | _sceneStats->insert(attribute.second.first.get()); 128 | } 129 | } 130 | 131 | for (auto& uniform : stateset.getUniformList()) 132 | { 133 | _sceneStats->insert(uniform.second.first.get()); 134 | } 135 | } 136 | 137 | /////////////////////////////////////////////////////////////////////////////////// 138 | // 139 | // VsgSceneAnalysis 140 | // 141 | VsgSceneAnalysis::VsgSceneAnalysis() : 142 | _sceneStats(new SceneStats) 143 | { 144 | } 145 | 146 | VsgSceneAnalysis::VsgSceneAnalysis(SceneStats* sceneStats) : 147 | _sceneStats(sceneStats) 148 | { 149 | } 150 | 151 | void VsgSceneAnalysis::apply(const vsg::Object& object) 152 | { 153 | _sceneStats->insert(&object); 154 | 155 | object.traverse(*this); 156 | } 157 | 158 | void VsgSceneAnalysis::apply(const vsg::Geometry& geometry) 159 | { 160 | _sceneStats->insert(&geometry); 161 | 162 | for (auto& array : geometry.arrays) 163 | { 164 | _sceneStats->insert(array.get()); 165 | } 166 | 167 | if (geometry.indices) 168 | { 169 | _sceneStats->insert(geometry.indices.get()); 170 | } 171 | 172 | for (auto& command : geometry.commands) 173 | { 174 | command->accept(*this); 175 | } 176 | } 177 | 178 | void VsgSceneAnalysis::apply(const vsg::StateGroup& stategroup) 179 | { 180 | _sceneStats->insert(&stategroup); 181 | 182 | for (auto& command : stategroup.stateCommands) 183 | { 184 | command->accept(*this); 185 | } 186 | 187 | stategroup.traverse(*this); 188 | } 189 | 190 | #if 0 191 | void VsgSceneAnalysis::apply(const vsg::Commands& commands) override 192 | { 193 | _sceneStats->insert(&commands); 194 | for(auto& command : stategroup.getChildren()) 195 | { 196 | _sceneStats->insert(command.get()); 197 | } 198 | } 199 | #endif 200 | -------------------------------------------------------------------------------- /src/osg2vsg/Optimize.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright(c) 2019 Thomas Hogarth and Robert Osfield 4 | 5 | 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: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | 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. 10 | 11 | */ 12 | 13 | #include "Optimize.h" 14 | 15 | #include "GeometryUtils.h" 16 | #include "ImageUtils.h" 17 | #include "ShaderUtils.h" 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | #include 24 | 25 | using namespace osg2vsg; 26 | 27 | OptimizeOsgBillboards::OptimizeOsgBillboards() : 28 | osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN) 29 | { 30 | } 31 | 32 | void OptimizeOsgBillboards::apply(osg::Node& node) 33 | { 34 | osg::Transform* topTransform = transformStack.empty() ? nullptr : transformStack.top(); 35 | transformSubgraph[topTransform].insert(&node); 36 | 37 | traverse(node); 38 | } 39 | 40 | void OptimizeOsgBillboards::apply(osg::Group& group) 41 | { 42 | // osg::Transform* topTransform = transformStack.empty() ? nullptr : transformStack.top(); 43 | // transformSubgraph[topTransform].insert(&group); 44 | 45 | traverse(group); 46 | } 47 | 48 | void OptimizeOsgBillboards::apply(osg::Transform& transform) 49 | { 50 | osg::Transform* topTransform = transformStack.empty() ? nullptr : transformStack.top(); 51 | 52 | transformStack.push(&transform); 53 | 54 | transformSubgraph[topTransform].insert(&transform); 55 | 56 | traverse(transform); 57 | 58 | transformStack.pop(); 59 | } 60 | 61 | void OptimizeOsgBillboards::apply(osg::Billboard& billboard) 62 | { 63 | //std::cout<<"OptimizeOsgBillboards::apply(osg::Billboard& "<<&billboard<<") \n"; 64 | 65 | osg::Transform* topTransform = transformStack.empty() ? nullptr : transformStack.top(); 66 | 67 | transformSubgraph[topTransform].insert(&billboard); 68 | } 69 | 70 | void OptimizeOsgBillboards::apply(osg::Geometry& geometry) 71 | { 72 | osg::Transform* topTransform = transformStack.empty() ? nullptr : transformStack.top(); 73 | 74 | transformSubgraph[topTransform].insert(&geometry); 75 | 76 | traverse(geometry); 77 | } 78 | 79 | void OptimizeOsgBillboards::optimize() 80 | { 81 | using Billboards = std::set; 82 | using Transforms = std::set; 83 | using TransformBillboardMap = std::map; 84 | using BillboardTransformMap = std::map; 85 | 86 | TransformBillboardMap transformBillboardMap; 87 | BillboardTransformMap billboardTransformMap; 88 | 89 | for (auto [transform, nodes] : transformSubgraph) 90 | { 91 | size_t numBillboards = 0; 92 | for (auto& node : nodes) 93 | { 94 | osg::Billboard* billboard = dynamic_cast(node); 95 | if (billboard) ++numBillboards; 96 | } 97 | if (numBillboards > 0 && numBillboards == nodes.size()) 98 | { 99 | for (auto& node : nodes) 100 | { 101 | osg::Billboard* billboard = dynamic_cast(node); 102 | transformBillboardMap[transform].insert(billboard); 103 | billboardTransformMap[billboard].insert(transform); 104 | } 105 | } 106 | } 107 | 108 | using ReplacementMap = std::map, osg::ref_ptr>; 109 | ReplacementMap replacementMap; 110 | 111 | for (auto [billboard, transforms] : billboardTransformMap) 112 | { 113 | bool transformsUniqueMapToBillboard = true; 114 | 115 | for (auto& transform : transforms) 116 | { 117 | if (transformBillboardMap[transform].size() > 1) 118 | { 119 | transformsUniqueMapToBillboard = false; 120 | } 121 | } 122 | if (transformsUniqueMapToBillboard) 123 | { 124 | osg::ref_ptr new_billboard = new osg::Billboard; 125 | 126 | new_billboard->setStateSet(billboard->getStateSet()); 127 | 128 | for (auto& transform : transforms) 129 | { 130 | if (transform) 131 | { 132 | osg::Matrix matrix; 133 | transform->computeLocalToWorldMatrix(matrix, nullptr); 134 | 135 | unsigned int numPositions = std::min(static_cast(billboard->getPositionList().size()), billboard->getNumDrawables()); 136 | for (unsigned int i = 0; i < numPositions; ++i) 137 | { 138 | auto position = billboard->getPosition(i); 139 | new_billboard->addDrawable(billboard->getDrawable(i), position * matrix); 140 | } 141 | } 142 | else 143 | { 144 | unsigned int numPositions = std::min(static_cast(billboard->getPositionList().size()), billboard->getNumDrawables()); 145 | for (unsigned int i = 0; i < numPositions; ++i) 146 | { 147 | auto position = billboard->getPosition(i); 148 | new_billboard->addDrawable(billboard->getDrawable(i), position); 149 | } 150 | } 151 | 152 | replacementMap[transform] = nullptr; 153 | } 154 | replacementMap[*transforms.begin()] = new_billboard; 155 | } 156 | } 157 | 158 | for (auto [nodeToReplace, replacementNode] : replacementMap) 159 | { 160 | if (nodeToReplace) 161 | { 162 | if (replacementNode) 163 | { 164 | for (auto parent : nodeToReplace->getParents()) 165 | { 166 | parent->replaceChild(nodeToReplace.get(), replacementNode.get()); 167 | } 168 | } 169 | else 170 | { 171 | for (auto parent : nodeToReplace->getParents()) 172 | { 173 | parent->removeChild(nodeToReplace.get()); 174 | } 175 | } 176 | } 177 | } 178 | } 179 | -------------------------------------------------------------------------------- /src/osg2vsg/convert.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright(c) 2022 Robert Osfield 4 | 5 | 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: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | 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. 10 | 11 | */ 12 | 13 | #include 14 | #include 15 | 16 | #include "ConvertToVsg.h" 17 | #include "ImageUtils.h" 18 | 19 | using namespace osg2vsg; 20 | 21 | vsg::ref_ptr osg2vsg::convert(const osg::Image& image, vsg::ref_ptr options) 22 | { 23 | bool mapRGBtoRGBAHint = !options || options->mapRGBtoRGBAHint; 24 | return convertToVsg(&image, mapRGBtoRGBAHint); 25 | } 26 | 27 | vsg::ref_ptr osg2vsg::convert(const osg::Array& src_array, vsg::ref_ptr /*options*/) 28 | { 29 | switch (src_array.getType()) 30 | { 31 | case (osg::Array::ByteArrayType): return {}; 32 | case (osg::Array::ShortArrayType): return {}; 33 | case (osg::Array::IntArrayType): return {}; 34 | 35 | case (osg::Array::UByteArrayType): return convert(src_array); 36 | case (osg::Array::UShortArrayType): return convert(src_array); 37 | case (osg::Array::UIntArrayType): return convert(src_array); 38 | 39 | case (osg::Array::FloatArrayType): return convert(src_array); 40 | case (osg::Array::DoubleArrayType): return convert(src_array); 41 | 42 | case (osg::Array::Vec2bArrayType): return {}; 43 | case (osg::Array::Vec3bArrayType): return {}; 44 | case (osg::Array::Vec4bArrayType): return {}; 45 | 46 | case (osg::Array::Vec2sArrayType): return {}; 47 | case (osg::Array::Vec3sArrayType): return {}; 48 | case (osg::Array::Vec4sArrayType): return {}; 49 | 50 | case (osg::Array::Vec2iArrayType): return {}; 51 | case (osg::Array::Vec3iArrayType): return {}; 52 | case (osg::Array::Vec4iArrayType): return {}; 53 | 54 | case (osg::Array::Vec2ubArrayType): return convert(src_array); 55 | case (osg::Array::Vec3ubArrayType): return convert(src_array); 56 | case (osg::Array::Vec4ubArrayType): return convert(src_array); 57 | 58 | case (osg::Array::Vec2usArrayType): return convert(src_array); 59 | case (osg::Array::Vec3usArrayType): return convert(src_array); 60 | case (osg::Array::Vec4usArrayType): return convert(src_array); 61 | 62 | case (osg::Array::Vec2uiArrayType): return convert(src_array); 63 | case (osg::Array::Vec3uiArrayType): return convert(src_array); 64 | case (osg::Array::Vec4uiArrayType): return convert(src_array); 65 | 66 | case (osg::Array::Vec2ArrayType): return convert(src_array); 67 | case (osg::Array::Vec3ArrayType): return convert(src_array); 68 | case (osg::Array::Vec4ArrayType): return convert(src_array); 69 | 70 | case (osg::Array::Vec2dArrayType): return convert(src_array); 71 | case (osg::Array::Vec3dArrayType): return convert(src_array); 72 | case (osg::Array::Vec4dArrayType): return convert(src_array); 73 | 74 | case (osg::Array::MatrixArrayType): return convert(src_array); 75 | case (osg::Array::MatrixdArrayType): return convert(src_array); 76 | 77 | #if OSG_MIN_VERSION_REQUIRED(3, 5, 7) 78 | case (osg::Array::QuatArrayType): return {}; 79 | 80 | case (osg::Array::UInt64ArrayType): return {}; 81 | case (osg::Array::Int64ArrayType): return {}; 82 | #endif 83 | default: return {}; 84 | } 85 | } 86 | 87 | vsg::ref_ptr osg2vsg::convert(const osg::Node& node, vsg::ref_ptr options) 88 | { 89 | bool mapRGBtoRGBAHint = !options || options->mapRGBtoRGBAHint; 90 | vsg::Paths searchPaths = options ? options->paths : vsg::getEnvPaths("VSG_FILE_PATH"); 91 | 92 | vsg::ref_ptr buildOptions; 93 | auto pipelineCache = osg2vsg::PipelineCache::create(); 94 | 95 | std::string build_options_filename; 96 | if (options->getValue(OSG::read_build_options, build_options_filename)) 97 | { 98 | buildOptions = vsg::read_cast(build_options_filename, options); 99 | } 100 | 101 | if (!buildOptions) 102 | { 103 | buildOptions = osg2vsg::BuildOptions::create(); 104 | buildOptions->mapRGBtoRGBAHint = mapRGBtoRGBAHint; 105 | } 106 | 107 | if (options->getValue(OSG::write_build_options, build_options_filename)) 108 | { 109 | vsg::write(buildOptions, build_options_filename, options); 110 | } 111 | 112 | buildOptions->options = options; 113 | buildOptions->pipelineCache = pipelineCache; 114 | 115 | auto osg_scene = const_cast(&node); 116 | 117 | if (vsg::value(false, OSG::original_converter, options)) 118 | { 119 | osg2vsg::SceneBuilder sceneBuilder(buildOptions); 120 | auto vsg_scene = sceneBuilder.optimizeAndConvertToVsg(osg_scene, searchPaths); 121 | return vsg_scene; 122 | } 123 | else 124 | { 125 | vsg::ref_ptr inheritedStateGroup; 126 | 127 | osg2vsg::ConvertToVsg sceneBuilder(buildOptions, inheritedStateGroup); 128 | 129 | sceneBuilder.optimize(osg_scene); 130 | auto vsg_scene = sceneBuilder.convert(osg_scene); 131 | 132 | if (sceneBuilder.numOfPagedLOD > 0) 133 | { 134 | uint32_t maxLevel = 20; 135 | uint32_t estimatedNumOfTilesBelow = 0; 136 | uint32_t maxNumTilesBelow = 1024; 137 | 138 | uint32_t level = 0; 139 | for (uint32_t i = level; i < maxLevel; ++i) 140 | { 141 | estimatedNumOfTilesBelow += std::pow(4, i - level); 142 | } 143 | 144 | uint32_t tileMultiplier = std::min(estimatedNumOfTilesBelow, maxNumTilesBelow) + 1; 145 | 146 | vsg::CollectResourceRequirements collectResourceRequirements; 147 | vsg_scene->accept(collectResourceRequirements); 148 | vsg_scene->setObject("ResourceHints", collectResourceRequirements.createResourceHints(tileMultiplier)); 149 | } 150 | return vsg_scene; 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /applications/osgmaths/osgmaths.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | template 17 | typename T::value_type difference(const T& lhs, const T& rhs) 18 | { 19 | typename T::value_type delta = 0.0; 20 | for(std::size_t c=0; c<4; ++c) 21 | { 22 | for(std::size_t r=0; r<4; ++r) 23 | { 24 | delta += std::abs(lhs(c,r) - rhs(c,r)); 25 | } 26 | } 27 | return delta; 28 | } 29 | 30 | inline vsg::dmat4 convert(const osg::Matrixd& m) 31 | { 32 | return vsg::dmat4(m(0, 0), m(0, 1), m(0, 2), m(0, 3), 33 | m(1, 0), m(1, 1), m(1, 2), m(1, 3), 34 | m(2, 0), m(2, 1), m(2, 2), m(2, 3), 35 | m(3, 0), m(3, 1), m(3, 2), m(3, 3)); 36 | } 37 | 38 | inline osg::Matrixd convert(const vsg::dmat4& m) 39 | { 40 | return osg::Matrixd(m(0, 0), m(0, 1), m(0, 2), m(0, 3), 41 | m(1, 0), m(1, 1), m(1, 2), m(1, 3), 42 | m(2, 0), m(2, 1), m(2, 2), m(2, 3), 43 | m(3, 0), m(3, 1), m(3, 2), m(3, 3)); 44 | } 45 | 46 | int main(int argc, char** argv) 47 | { 48 | vsg::CommandLine arguments(&argc, argv); 49 | 50 | uint32_t numTests = arguments.value(1000000, "-n"); 51 | auto vsg_test = arguments.value(1, "--vsg"); 52 | auto osg_test = arguments.value(1, "--osg"); 53 | bool print_test = arguments.read("--print"); 54 | 55 | std::vector vsg_dmatrices; 56 | std::vector vsg_transposed_dmatrices; 57 | std::vector osg_dmatrices; 58 | std::vector osg_transposed_dmatrices; 59 | 60 | vsg::dvec3 axis = vsg::normalize(vsg::dvec3(0.2, 0.4, 0.8)); 61 | vsg::dvec3 direction(10000.0, 20000.0, 30000.0); 62 | 63 | for(uint32_t i = 0; i(mid_osg - before_osg).count()<<"ms delta = "<(after_osg - mid_osg).count()<<"ms delta = "<(mid_vsg - before_vsg).count()<<"ms delta = "<(after_vsg - mid_vsg).count()<<"ms delta = "< 2 | 3 | Copyright(c) 2019 Thomas Hogarth and Robert Osfield 4 | 5 | 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: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | 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. 10 | 11 | */ 12 | 13 | #include 14 | #include 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include "ConvertToVsg.h" 26 | #include "ImageUtils.h" 27 | #include "Optimize.h" 28 | #include "SceneBuilder.h" 29 | 30 | using namespace osg2vsg; 31 | 32 | OSG::OSG() 33 | { 34 | pipelineCache = osg2vsg::PipelineCache::create(); 35 | } 36 | 37 | OSG::~OSG() 38 | { 39 | }; 40 | 41 | bool OSG::getFeatures(Features& features) const 42 | { 43 | std::cout<<"OSG::getFeatures(Features& features)"<extensions) 69 | { 70 | features.extensionFeatureMap[dotPrefix + ext_description.first] = vsg::ReaderWriter::READ_FILENAME; 71 | } 72 | } 73 | 74 | // enumerate the supported vsg::Options::setValue(str, value) options 75 | features.optionNameTypeMap[OSG::original_converter] = vsg::type_name(); 76 | features.optionNameTypeMap[OSG::read_build_options] = vsg::type_name(); 77 | features.optionNameTypeMap[OSG::write_build_options] = vsg::type_name(); 78 | 79 | return true; 80 | } 81 | 82 | 83 | bool OSG::readOptions(vsg::Options& options, vsg::CommandLine& arguments) const 84 | { 85 | bool result = arguments.readAndAssign(OSG::original_converter, &options); 86 | result = arguments.readAndAssign(OSG::read_build_options, &options) || result; 87 | result = arguments.readAndAssign(OSG::write_build_options, &options) || result; 88 | return result; 89 | } 90 | 91 | vsg::ref_ptr OSG::read(const vsg::Path& filename, vsg::ref_ptr options) const 92 | { 93 | osg::ref_ptr osg_options; 94 | 95 | if (options) 96 | { 97 | if (osgDB::Registry::instance()->getOptions()) 98 | osg_options = osgDB::Registry::instance()->getOptions()->cloneOptions(); 99 | else 100 | osg_options = new osgDB::Options(); 101 | for (auto itr = options->paths.begin(); itr != options->paths.end(); ++itr) 102 | osg_options->getDatabasePathList().insert(osg_options->getDatabasePathList().end(), (*itr).string()); 103 | } 104 | 105 | auto ext = vsg::lowerCaseFileExtension(filename); 106 | if (ext == ".path") 107 | { 108 | auto foundPath = vsg::findFile(filename, options); 109 | if (foundPath) 110 | { 111 | std::ifstream fin(foundPath); 112 | if (!fin) return {}; 113 | 114 | osg::ref_ptr osg_animationPath = new osg::AnimationPath; 115 | osg_animationPath->read(fin); 116 | 117 | auto vsg_animation = vsg::Animation::create(); 118 | auto cameraSampler = vsg::CameraSampler::create(); 119 | auto keyframes = cameraSampler->keyframes = vsg::CameraKeyframes::create(); 120 | vsg_animation->samplers.push_back(cameraSampler); 121 | 122 | switch (osg_animationPath->getLoopMode()) 123 | { 124 | case (osg::AnimationPath::SWING): 125 | vsg_animation->mode = vsg::Animation::FORWARD_AND_BACK; 126 | break; 127 | case (osg::AnimationPath::LOOP): 128 | vsg_animation->mode = vsg::Animation::REPEAT; 129 | break; 130 | case (osg::AnimationPath::NO_LOOPING): 131 | vsg_animation->mode = vsg::Animation::ONCE; 132 | break; 133 | } 134 | 135 | for (auto& [time, cp] : osg_animationPath->getTimeControlPointMap()) 136 | { 137 | const auto& position = cp.getPosition(); 138 | const auto& rotation = cp.getRotation(); 139 | 140 | keyframes->add(time, vsg::dvec3(position.x(), position.y(), position.z()), 141 | vsg::dquat(rotation.x(), rotation.y(), rotation.z(), rotation.w())); 142 | } 143 | 144 | return vsg_animation; 145 | } 146 | return {}; 147 | } 148 | 149 | osgDB::ReaderWriter::ReadResult rr = osgDB::Registry::instance()->readObject(filename.string(), osg_options.get()); 150 | // if (!rr.success()) OSG_WARN << "Error reading file " << filename << ": " << rr.statusMessage() << std::endl; 151 | if (!rr.validObject()) return {}; 152 | 153 | bool mapRGBtoRGBAHint = !options || options->mapRGBtoRGBAHint; 154 | 155 | osg::ref_ptr object = rr.takeObject(); 156 | if (osg::Node* osg_scene = object->asNode(); osg_scene != nullptr) 157 | { 158 | return osg2vsg::convert(*osg_scene, options); 159 | } 160 | else if (osg::Image* osg_image = dynamic_cast(object.get()); osg_image != nullptr) 161 | { 162 | return osg2vsg::convertToVsg(osg_image, mapRGBtoRGBAHint); 163 | } 164 | else if (osg::TransferFunction1D* tf = dynamic_cast(object.get()); tf != nullptr) 165 | { 166 | auto tf_image = tf->getImage(); 167 | auto vsg_image = osg2vsg::convertToVsg(tf_image, mapRGBtoRGBAHint); 168 | vsg_image->setValue("Minimum", tf->getMinimum()); 169 | vsg_image->setValue("Maximum", tf->getMaximum()); 170 | 171 | return vsg_image; 172 | } 173 | else 174 | { 175 | vsg::warn("OSG::read(", filename, ") cannot convert object type ", object->className(), ")"); 176 | } 177 | 178 | return {}; 179 | } 180 | -------------------------------------------------------------------------------- /src/osg2vsg/BuildOptions.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright(c) 2019 Thomas Hogarth and Robert Osfield 4 | 5 | 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: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | 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. 10 | 11 | */ 12 | 13 | #include "BuildOptions.h" 14 | #include "ShaderUtils.h" 15 | 16 | #include "shaders/fbxshader_vert.cpp" 17 | #include "shaders/fbxshader_frag.cpp" 18 | 19 | using namespace osg2vsg; 20 | 21 | vsg::RegisterWithObjectFactoryProxy s_Register_BuildOptions; 22 | 23 | void BuildOptions::read(vsg::Input& input) 24 | { 25 | input.read("insertCullGroups", insertCullGroups); 26 | input.read("insertCullNodes", insertCullNodes); 27 | input.read("useBindDescriptorSet", useBindDescriptorSet); 28 | input.read("billboardTransform", billboardTransform); 29 | input.readValue("geometryTarget", geometryTarget); 30 | input.read("supportedGeometryAttributes", supportedGeometryAttributes); 31 | input.read("supportedShaderModeMask", supportedShaderModeMask); 32 | input.read("overrideGeomAttributes", overrideGeomAttributes); 33 | input.read("overrideShaderModeMask", overrideShaderModeMask); 34 | input.read("useDepthSorted", useDepthSorted); 35 | if (input.version_greater_equal(0, 2, 0)) 36 | { 37 | input.read("mapRGBtoRGBAHint", mapRGBtoRGBAHint); 38 | input.read("copyNames", copyNames); 39 | } 40 | input.read("vertexShaderPath", vertexShaderPath); 41 | input.read("fragmentShaderPath", fragmentShaderPath); 42 | input.read("extension", extension); 43 | } 44 | 45 | void BuildOptions::write(vsg::Output& output) const 46 | { 47 | output.write("insertCullGroups", insertCullGroups); 48 | output.write("insertCullNodes", insertCullNodes); 49 | output.write("useBindDescriptorSet", useBindDescriptorSet); 50 | output.write("billboardTransform", billboardTransform); 51 | output.writeValue("geometryTarget", geometryTarget); 52 | output.write("supportedGeometryAttributes", supportedGeometryAttributes); 53 | output.write("supportedShaderModeMask", supportedShaderModeMask); 54 | output.write("overrideGeomAttributes", overrideGeomAttributes); 55 | output.write("overrideShaderModeMask", overrideShaderModeMask); 56 | output.write("useDepthSorted", useDepthSorted); 57 | if (output.version_greater_equal(0, 2, 0)) 58 | { 59 | output.write("mapRGBtoRGBAHint", mapRGBtoRGBAHint); 60 | output.write("copyNames", copyNames); 61 | } 62 | output.write("vertexShaderPath", vertexShaderPath); 63 | output.write("fragmentShaderPath", fragmentShaderPath); 64 | output.write("extension", extension); 65 | } 66 | 67 | vsg::ref_ptr PipelineCache::getOrCreateBindGraphicsPipeline(uint32_t shaderModeMask, uint32_t geometryAttributesMask, const vsg::Path& vertShaderPath, const vsg::Path& fragShaderPath, vsg::ref_ptr options) 68 | { 69 | Key key(shaderModeMask, geometryAttributesMask, vertShaderPath, fragShaderPath); 70 | 71 | // check to see if pipeline has already been created 72 | { 73 | std::lock_guard guard(mutex); 74 | if (auto itr = pipelineMap.find(key); itr != pipelineMap.end()) return itr->second; 75 | } 76 | 77 | auto scs = vsg::ShaderCompileSettings::create(); 78 | scs->defines = createPSCDefineStrings(shaderModeMask, geometryAttributesMask); 79 | 80 | vsg::ref_ptr vertexShader; 81 | if (vertShaderPath) vertexShader = vsg::read_cast(vertShaderPath, options); 82 | if (!vertexShader) vertexShader = fbxshader_vert(); // fallback to shaders/fbxshader_vert.cpp 83 | vertexShader->module->hints = scs; 84 | 85 | vsg::ref_ptr fragmentShader; 86 | if (fragShaderPath) fragmentShader = vsg::read_cast(fragShaderPath, options); 87 | if (!fragmentShader) fragmentShader = fbxshader_frag(); // fallback to shaders/fbxshader_frag.cpp 88 | fragmentShader->module->hints = scs; 89 | 90 | vsg::ShaderStages shaders{vertexShader, fragmentShader}; 91 | 92 | // std::cout<<"createBindGraphicsPipeline("< graphicsPipeline = vsg::GraphicsPipeline::create(pipelineLayout, shaders, pipelineStates); 197 | auto bindGraphicsPipeline = vsg::BindGraphicsPipeline::create(graphicsPipeline); 198 | 199 | // assign the pipeline to cache. 200 | std::lock_guard guard(mutex); 201 | pipelineMap[key] = bindGraphicsPipeline; 202 | 203 | return bindGraphicsPipeline; 204 | } 205 | -------------------------------------------------------------------------------- /applications/vsgwithosg/vsgwithosg.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | vsg::ref_ptr createTextureQuad(vsg::ref_ptr sourceData) 18 | { 19 | struct ConvertToRGBA : public vsg::Visitor 20 | { 21 | vsg::ref_ptr textureData; 22 | 23 | void apply(vsg::Data& data) override 24 | { 25 | textureData = &data; 26 | } 27 | 28 | void apply(vsg::uintArray2D& fa) override 29 | { 30 | // treat as a 24bit depth buffer 31 | float div = 1.0f / static_cast(1<<24); 32 | 33 | auto rgba = vsg::vec4Array2D::create(fa.width(), fa.height(), vsg::Data::Properties{VK_FORMAT_R32G32B32A32_SFLOAT}); 34 | auto dest_itr = rgba->begin(); 35 | for(auto& v : fa) 36 | { 37 | float m = static_cast(v) * div; 38 | (*dest_itr++).set(m, m, m, 1.0); 39 | } 40 | textureData = rgba; 41 | } 42 | 43 | void apply(vsg::floatArray2D& fa) override 44 | { 45 | auto rgba = vsg::vec4Array2D::create(fa.width(), fa.height(), vsg::Data::Properties{VK_FORMAT_R32G32B32A32_SFLOAT}); 46 | auto dest_itr = rgba->begin(); 47 | for(auto& v : fa) 48 | { 49 | (*dest_itr++).set(v, v, v, 1.0); 50 | } 51 | textureData = rgba; 52 | } 53 | 54 | vsg::ref_ptr convert(vsg::ref_ptr data) 55 | { 56 | data->accept(*this); 57 | return textureData; 58 | } 59 | 60 | 61 | } convertToRGBA; 62 | 63 | auto textureData = convertToRGBA.convert(sourceData); 64 | if (!textureData) return {}; 65 | 66 | 67 | // set up search paths to SPIRV shaders and textures 68 | vsg::Paths searchPaths = vsg::getEnvPaths("VSG_FILE_PATH"); 69 | 70 | // load shaders 71 | vsg::ref_ptr vertexShader = vsg::ShaderStage::read(VK_SHADER_STAGE_VERTEX_BIT, "main", vsg::findFile("shaders/vert_PushConstants.spv", searchPaths)); 72 | vsg::ref_ptr fragmentShader = vsg::ShaderStage::read(VK_SHADER_STAGE_FRAGMENT_BIT, "main", vsg::findFile("shaders/frag_PushConstants.spv", searchPaths)); 73 | if (!vertexShader || !fragmentShader) 74 | { 75 | std::cout<<"Could not create shaders."<layout, 0, vsg::DescriptorSets{descriptorSet}); 125 | 126 | // create StateGroup as the root of the scene/command graph to hold the GraphicsPipeline, and binding of Descriptors to decorate the whole graph 127 | auto scenegraph = vsg::StateGroup::create(); 128 | scenegraph->add(bindGraphicsPipeline); 129 | scenegraph->add(bindDescriptorSets); 130 | 131 | // set up model transformation node 132 | auto transform = vsg::MatrixTransform::create(); // VK_SHADER_STAGE_VERTEX_BIT 133 | 134 | // add transform to root of the scene graph 135 | scenegraph->addChild(transform); 136 | 137 | // set up vertex and index arrays 138 | auto vertices = vsg::vec3Array::create( 139 | { 140 | {0.0f, 0.0f, 0.0f}, 141 | {static_cast(textureData->width()), 0.0f, 0.0f}, 142 | {static_cast(textureData->width()), 0.0f, static_cast(textureData->height())}, 143 | {0.0f, 0.0f, static_cast(textureData->height())} 144 | }); // VK_FORMAT_R32G32B32_SFLOAT, VK_VERTEX_INPUT_RATE_INSTANCE, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_SHARING_MODE_EXCLUSIVE 145 | 146 | auto colors = vsg::vec3Array::create( 147 | { 148 | {1.0f, 1.0f, 1.0f}, 149 | {1.0f, 1.0f, 1.0f}, 150 | {1.0f, 1.0f, 1.0f}, 151 | {1.0f, 1.0f, 1.0f} 152 | }); // VK_FORMAT_R32G32B32_SFLOAT, VK_VERTEX_INPUT_RATE_VERTEX, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_SHARING_MODE_EXCLUSIVE 153 | 154 | uint8_t origin = textureData->properties.origin; // in Vulkan the origin is in the top left corner by default. 155 | float left = 0.0f; 156 | float right = 1.0f; 157 | float top = (origin == vsg::TOP_LEFT) ? 0.0f : 1.0f; 158 | float bottom = (origin == vsg::TOP_LEFT) ? 1.0f : 0.0f; 159 | auto texcoords = vsg::vec2Array::create( 160 | { 161 | {left, bottom}, 162 | {right, bottom}, 163 | {right, top}, 164 | {left, top} 165 | }); // VK_FORMAT_R32G32_SFLOAT, VK_VERTEX_INPUT_RATE_VERTEX, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_SHARING_MODE_EXCLUSIVE 166 | 167 | auto indices = vsg::ushortArray::create( 168 | { 169 | 0, 1, 2, 170 | 2, 3, 0 171 | }); // VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_SHARING_MODE_EXCLUSIVE 172 | 173 | // setup geometry 174 | auto drawCommands = vsg::Commands::create(); 175 | drawCommands->addChild(vsg::BindVertexBuffers::create(0, vsg::DataList{vertices, colors, texcoords})); 176 | drawCommands->addChild(vsg::BindIndexBuffer::create(indices)); 177 | drawCommands->addChild(vsg::DrawIndexed::create(6, 1, 0, 0, 0)); 178 | 179 | // add drawCommands to transform 180 | transform->addChild(drawCommands); 181 | 182 | return scenegraph; 183 | } 184 | int main(int argc, char** argv) 185 | { 186 | // set up vsg::Options to pass in filepaths, ReaderWriters and other IO related options to use when reading and writing files. 187 | auto options = vsg::Options::create(); 188 | options->fileCache = vsg::getEnv("VSG_FILE_CACHE"); 189 | options->paths = vsg::getEnvPaths("VSG_FILE_PATH"); 190 | 191 | // add OpenSceneGraph's support for reading and writing 3rd party file formats 192 | options->add(vsg::VSG::create()); 193 | options->add(vsg::spirv::create()); 194 | options->add(osg2vsg::OSG::create()); 195 | 196 | auto windowTraits = vsg::WindowTraits::create(); 197 | windowTraits->windowTitle = "VulkanSceneGraph Window"; 198 | windowTraits->width = 800; 199 | windowTraits->height = 600; 200 | 201 | // set up defaults and read command line arguments to override them 202 | vsg::CommandLine arguments(&argc, argv); 203 | arguments.read(options); 204 | windowTraits->debugLayer = arguments.read({"--debug","-d"}); 205 | windowTraits->apiDumpLayer = arguments.read({"--api","-a"}); 206 | if (arguments.read({"--window", "-w"}, windowTraits->width, windowTraits->height)) { windowTraits->fullscreen = false; } 207 | arguments.read("--screen", windowTraits->screenNum); 208 | arguments.read("--display", windowTraits->display); 209 | auto pathFilename = arguments.value("","-p"); 210 | auto horizonMountainHeight = arguments.value(0.0, "--hmh"); 211 | 212 | if (arguments.errors()) return arguments.writeErrorMessages(std::cerr); 213 | 214 | if (argc <= 1) 215 | { 216 | std::cout<<"Please specify a model to load on command line."<(filename, options); 223 | 224 | if (!vsg_scene) 225 | { 226 | std::cout<<"vsg::read() could not read : "< vsg_window(vsg::Window::create(windowTraits)); 243 | if (!vsg_window) 244 | { 245 | std::cout<<"Could not create window."<addWindow(vsg_window); 250 | 251 | // compute the bounds of the scene graph to help position camera 252 | vsg::ComputeBounds computeBounds; 253 | vsg_scene->accept(computeBounds); 254 | vsg::dvec3 centre = (computeBounds.bounds.min+computeBounds.bounds.max)*0.5; 255 | double radius = vsg::length(computeBounds.bounds.max-computeBounds.bounds.min)*0.6; 256 | double nearFarRatio = 0.001; 257 | 258 | // set up the camera 259 | auto lookAt = vsg::LookAt::create(centre+vsg::dvec3(0.0, -radius*3.5, 0.0), centre, vsg::dvec3(0.0, 0.0, 1.0)); 260 | vsg::ref_ptr perspective; 261 | if (vsg::ref_ptr ellipsoidModel(vsg_scene->getObject("EllipsoidModel")); ellipsoidModel) 262 | { 263 | perspective = vsg::EllipsoidPerspective::create(lookAt, ellipsoidModel, 30.0, static_cast(vsg_window->extent2D().width) / static_cast(vsg_window->extent2D().height), nearFarRatio, horizonMountainHeight); 264 | } 265 | else 266 | { 267 | perspective = vsg::Perspective::create(30.0, static_cast(vsg_window->extent2D().width) / static_cast(vsg_window->extent2D().height), nearFarRatio*radius, radius * 4.5); 268 | } 269 | auto vsg_camera = vsg::Camera::create(perspective, lookAt, vsg::ViewportState::create(vsg_window->extent2D())); 270 | 271 | // add close handler to respond to the close window button and pressing escape 272 | vsg_viewer->addEventHandler(vsg::CloseHandler::create(vsg_viewer)); 273 | 274 | if (pathFilename) 275 | { 276 | auto animation = vsg::read_cast(pathFilename, options); 277 | if (!animation) 278 | { 279 | std::cout<<"Warning: unable to read animation path : "<addEventHandler(cameraAnimation); 285 | } 286 | else vsg_viewer->addEventHandler(vsg::Trackball::create(vsg_camera)); 287 | 288 | auto commandGraph = vsg::createCommandGraphForView(vsg_window, vsg_camera, vsg_scene); 289 | vsg_viewer->assignRecordAndSubmitTaskAndPresentation({commandGraph}); 290 | 291 | vsg_viewer->compile(); 292 | } 293 | 294 | // set up OpenSceneGraph viewer 295 | osgViewer::Viewer osg_viewer; 296 | { 297 | osg_viewer.setSceneData(osg_scene); 298 | 299 | osg::ref_ptr traits = new osg::GraphicsContext::Traits; 300 | traits->x = windowTraits->width; 301 | traits->y = 0; 302 | traits->width = windowTraits->width; 303 | traits->height = windowTraits->height; 304 | traits->windowDecoration = true; 305 | traits->doubleBuffer = true; 306 | traits->pbuffer = false; 307 | 308 | osg::ref_ptr gc = osg::GraphicsContext::createGraphicsContext(traits.get()); 309 | if (!gc || !gc->valid()) 310 | { 311 | osg::notify(osg::NOTICE)<<"Error: unable to create graphics window"<setGraphicsContext(gc); 316 | osg_viewer.getCamera()->setViewport(new osg::Viewport(0, 0, windowTraits->width, windowTraits->height)); 317 | 318 | osg_viewer.addEventHandler(new osgGA::StateSetManipulator(osg_viewer.getCamera()->getOrCreateStateSet())); 319 | osg_viewer.addEventHandler(new osgViewer::StatsHandler); 320 | 321 | if (pathFilename.empty()) osg_viewer.setCameraManipulator(new osgGA::TrackballManipulator()); 322 | else osg_viewer.setCameraManipulator(new osgGA::AnimationPathManipulator(pathFilename.string())); 323 | 324 | osg_viewer.realize(); 325 | 326 | auto osg_window = dynamic_cast(osg_viewer.getCamera()->getGraphicsContext()); 327 | if (osg_window) osg_window->setWindowName("OpenSceneGraph Window"); 328 | } 329 | 330 | // rendering main loop 331 | while (vsg_viewer->advanceToNextFrame() && !osg_viewer.done()) 332 | { 333 | // render VulkanSceneGraph frame 334 | { 335 | vsg_viewer->handleEvents(); 336 | vsg_viewer->update(); 337 | vsg_viewer->recordAndSubmit(); 338 | vsg_viewer->present(); 339 | } 340 | 341 | // render OpenSceneGraph frame 342 | { 343 | osg_viewer.advance(); 344 | osg_viewer.updateTraversal(); 345 | osg_viewer.eventTraversal(); 346 | osg_viewer.renderingTraversals(); 347 | } 348 | } 349 | 350 | // clean up done automatically thanks to ref_ptr<> 351 | return 0; 352 | } 353 | -------------------------------------------------------------------------------- /src/osg2vsg/ImageUtils.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright(c) 2018 Robert Osfield 4 | 5 | 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: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | 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. 10 | 11 | */ 12 | 13 | #include "ImageUtils.h" 14 | 15 | #include 16 | 17 | #include 18 | #include 19 | 20 | namespace osg2vsg 21 | { 22 | 23 | VkFormat convertGLImageFormatToVulkan(GLenum dataType, GLenum pixelFormat) 24 | { 25 | using GLtoVkFormatMap = std::map, VkFormat>; 26 | static GLtoVkFormatMap s_GLtoVkFormatMap = { 27 | {{GL_UNSIGNED_BYTE, GL_ALPHA}, VK_FORMAT_R8_UNORM}, 28 | {{GL_UNSIGNED_BYTE, GL_LUMINANCE}, VK_FORMAT_R8_UNORM}, 29 | {{GL_UNSIGNED_BYTE, GL_LUMINANCE_ALPHA}, VK_FORMAT_R8G8_UNORM}, 30 | {{GL_UNSIGNED_BYTE, GL_RGB}, VK_FORMAT_R8G8B8_UNORM}, 31 | {{GL_UNSIGNED_BYTE, GL_RGBA}, VK_FORMAT_R8G8B8A8_UNORM}}; 32 | 33 | auto itr = s_GLtoVkFormatMap.find({dataType, pixelFormat}); 34 | if (itr != s_GLtoVkFormatMap.end()) 35 | { 36 | std::cout << "convertGLImageFormatToVulkan(" << dataType << ", " << pixelFormat << ") VkFormat=" << itr->second << std::endl; 37 | return itr->second; 38 | } 39 | else 40 | { 41 | std::cout << "convertGLImageFormatToVulkan(" << dataType << ", " << pixelFormat << ") no match found." << std::endl; 42 | return VK_FORMAT_UNDEFINED; 43 | } 44 | } 45 | 46 | osg::ref_ptr formatImage(const osg::Image* image, GLenum targetPixelFormat = GL_RGBA) 47 | { 48 | if (targetPixelFormat == image->getPixelFormat()) 49 | { 50 | return const_cast(image); 51 | } 52 | 53 | osg::ref_ptr new_image(new osg::Image); 54 | 55 | new_image->allocateImage(image->s(), image->t(), image->r(), targetPixelFormat, image->getDataType()); 56 | 57 | int numBytesPerComponent = 1; 58 | unsigned char component_default[8] = {255, 0, 0, 0, 0, 0, 0, 0}; 59 | switch (image->getDataType()) 60 | { 61 | case (GL_BYTE): 62 | numBytesPerComponent = 1; 63 | *reinterpret_cast(component_default) = 127; 64 | break; 65 | case (GL_UNSIGNED_BYTE): 66 | numBytesPerComponent = 1; 67 | *reinterpret_cast(component_default) = 255; 68 | break; 69 | case (GL_SHORT): 70 | numBytesPerComponent = 2; 71 | *reinterpret_cast(component_default) = 32767; 72 | break; 73 | case (GL_UNSIGNED_SHORT): 74 | numBytesPerComponent = 2; 75 | *reinterpret_cast(component_default) = 65535; 76 | break; 77 | case (GL_INT): 78 | numBytesPerComponent = 4; 79 | *reinterpret_cast(component_default) = 2147483647; 80 | break; 81 | case (GL_UNSIGNED_INT): 82 | numBytesPerComponent = 4; 83 | *reinterpret_cast(component_default) = 4294967295; 84 | break; 85 | case (GL_FLOAT): 86 | numBytesPerComponent = 4; 87 | *reinterpret_cast(component_default) = 1.0f; 88 | break; 89 | case (GL_DOUBLE): 90 | numBytesPerComponent = 8; 91 | break; 92 | numBytesPerComponent = 8; 93 | *reinterpret_cast(component_default) = 1.0; 94 | break; 95 | default: { 96 | std::cout << "Warning: formatImage() DataType " << image->getDataType() << " not supported." << std::endl; 97 | return {}; 98 | } 99 | } 100 | 101 | int numComponents = 4; 102 | switch (targetPixelFormat) 103 | { 104 | case (GL_RED): numComponents = 1; break; 105 | case (GL_ALPHA): numComponents = 1; break; 106 | case (GL_LUMINANCE): numComponents = 1; break; 107 | case (GL_LUMINANCE_ALPHA): numComponents = 2; break; 108 | case (GL_RGB): numComponents = 3; break; 109 | case (GL_BGR): numComponents = 3; break; 110 | case (GL_RGBA): numComponents = 4; break; 111 | case (GL_BGRA): numComponents = 4; break; 112 | default: { 113 | std::cout << "Warning: formatImage() targetPixelFormat " << targetPixelFormat << " not supported." << std::endl; 114 | return {}; 115 | } 116 | } 117 | 118 | std::vector componentOffset = {0, 1 * numBytesPerComponent, 2 * numBytesPerComponent, 3 * numBytesPerComponent}; 119 | switch (image->getPixelFormat()) 120 | { 121 | case (GL_RED): 122 | componentOffset = {0, -1, -1, -1}; 123 | break; 124 | case (GL_ALPHA): 125 | componentOffset = {-1, -1, -1, 0}; 126 | break; 127 | case (GL_LUMINANCE): 128 | componentOffset = {0, 0, 0, -1}; 129 | break; 130 | case (GL_LUMINANCE_ALPHA): 131 | componentOffset = {0, 0, 0, numBytesPerComponent}; 132 | break; 133 | case (GL_RGB): 134 | componentOffset = {0, numBytesPerComponent, numBytesPerComponent * 2, -1}; 135 | break; 136 | case (GL_BGR): 137 | componentOffset = {numBytesPerComponent * 2, numBytesPerComponent, 0, -1}; 138 | break; 139 | case (GL_RGBA): 140 | componentOffset = {0, numBytesPerComponent, numBytesPerComponent * 2, numBytesPerComponent * 3}; 141 | break; 142 | case (GL_BGRA): 143 | componentOffset = {numBytesPerComponent * 2, numBytesPerComponent, 0, numBytesPerComponent * 3}; 144 | break; 145 | default: { 146 | std::cout << "Warning: formatImage() source PixelFormat " << image->getPixelFormat() << " not supported." << std::endl; 147 | return {}; 148 | } 149 | } 150 | 151 | for (int r = 0; r < image->r(); ++r) 152 | { 153 | for (int t = 0; t < image->t(); ++t) 154 | { 155 | for (int s = 0; s < image->s(); ++s) 156 | { 157 | const unsigned char* src = image->data(s, t, r); 158 | unsigned char* dst = new_image->data(s, t, r); 159 | 160 | for (int c = 0; c < numComponents; ++c) 161 | { 162 | int offset = componentOffset[c]; 163 | const unsigned char* component_src = (offset >= 0) ? (src + offset) : component_default; 164 | for (int b = 0; b < numBytesPerComponent; ++b) 165 | { 166 | *(dst++) = *(component_src + b); 167 | } 168 | } 169 | } 170 | } 171 | } 172 | 173 | return new_image; 174 | } 175 | 176 | vsg::ref_ptr createWhiteTexture() 177 | { 178 | auto vsg_data = vsg::vec4Array2D::create(1, 1, vsg::Data::Properties{VK_FORMAT_R32G32B32A32_SFLOAT}); 179 | for (auto& color : *vsg_data) 180 | { 181 | color = vsg::vec4(1.0f, 1.0f, 1.0f, 1.0f); 182 | } 183 | return vsg_data; 184 | } 185 | 186 | vsg::ref_ptr convertCompressedImageToVsg(const osg::Image* image) 187 | { 188 | uint32_t blockSize = 0; 189 | vsg::Data::Properties layout; 190 | switch (image->getPixelFormat()) 191 | { 192 | case (GL_COMPRESSED_ALPHA_ARB): 193 | case (GL_COMPRESSED_INTENSITY_ARB): 194 | case (GL_COMPRESSED_LUMINANCE_ALPHA_ARB): 195 | case (GL_COMPRESSED_LUMINANCE_ARB): 196 | case (GL_COMPRESSED_RGBA_ARB): 197 | case (GL_COMPRESSED_RGB_ARB): 198 | break; 199 | case (GL_COMPRESSED_RGB_S3TC_DXT1_EXT): 200 | blockSize = 64; 201 | layout.blockWidth = 4; 202 | layout.blockHeight = 4; 203 | layout.format = VK_FORMAT_BC1_RGB_UNORM_BLOCK; 204 | break; 205 | case (GL_COMPRESSED_RGBA_S3TC_DXT1_EXT): 206 | blockSize = 64; 207 | layout.blockWidth = 4; 208 | layout.blockHeight = 4; 209 | layout.format = VK_FORMAT_BC1_RGBA_UNORM_BLOCK; 210 | break; 211 | case (GL_COMPRESSED_RGBA_S3TC_DXT3_EXT): 212 | blockSize = 128; 213 | layout.blockWidth = 4; 214 | layout.blockHeight = 4; 215 | layout.format = VK_FORMAT_BC2_UNORM_BLOCK; 216 | break; 217 | case (GL_COMPRESSED_RGBA_S3TC_DXT5_EXT): 218 | blockSize = 128; 219 | layout.blockWidth = 4; 220 | layout.blockHeight = 4; 221 | layout.format = VK_FORMAT_BC3_UNORM_BLOCK; 222 | break; 223 | case (GL_COMPRESSED_SIGNED_RED_RGTC1_EXT): 224 | case (GL_COMPRESSED_RED_RGTC1_EXT): 225 | case (GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT): 226 | case (GL_COMPRESSED_RED_GREEN_RGTC2_EXT): 227 | case (GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG): 228 | case (GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG): 229 | case (GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG): 230 | case (GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG): 231 | case (GL_ETC1_RGB8_OES): 232 | case (GL_COMPRESSED_RGB8_ETC2): 233 | case (GL_COMPRESSED_SRGB8_ETC2): 234 | case (GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2): 235 | case (GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2): 236 | case (GL_COMPRESSED_RGBA8_ETC2_EAC): 237 | case (GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC): 238 | case (GL_COMPRESSED_R11_EAC): 239 | case (GL_COMPRESSED_SIGNED_R11_EAC): 240 | case (GL_COMPRESSED_RG11_EAC): 241 | case (GL_COMPRESSED_SIGNED_RG11_EAC): 242 | #if OSG_MIN_VERSION_REQUIRED(3, 5, 8) 243 | case (GL_COMPRESSED_RGBA_ASTC_4x4_KHR): 244 | case (GL_COMPRESSED_RGBA_ASTC_5x4_KHR): 245 | case (GL_COMPRESSED_RGBA_ASTC_5x5_KHR): 246 | case (GL_COMPRESSED_RGBA_ASTC_6x5_KHR): 247 | case (GL_COMPRESSED_RGBA_ASTC_6x6_KHR): 248 | case (GL_COMPRESSED_RGBA_ASTC_8x5_KHR): 249 | case (GL_COMPRESSED_RGBA_ASTC_8x6_KHR): 250 | case (GL_COMPRESSED_RGBA_ASTC_8x8_KHR): 251 | case (GL_COMPRESSED_RGBA_ASTC_10x5_KHR): 252 | case (GL_COMPRESSED_RGBA_ASTC_10x6_KHR): 253 | case (GL_COMPRESSED_RGBA_ASTC_10x8_KHR): 254 | case (GL_COMPRESSED_RGBA_ASTC_10x10_KHR): 255 | case (GL_COMPRESSED_RGBA_ASTC_12x10_KHR): 256 | case (GL_COMPRESSED_RGBA_ASTC_12x12_KHR): 257 | case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR): 258 | case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR): 259 | case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR): 260 | case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR): 261 | case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR): 262 | case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR): 263 | case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR): 264 | case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR): 265 | case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR): 266 | case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR): 267 | case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR): 268 | case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR): 269 | case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR): 270 | case (GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR): 271 | #endif 272 | break; 273 | default: 274 | break; 275 | } 276 | 277 | if (blockSize == 0) 278 | { 279 | std::cout << "Compressed format not supported, falling back to white texture." << std::endl; 280 | return createWhiteTexture(); 281 | } 282 | 283 | // stop the OSG image from deleting the image data as we are passing this on to the vsg Data object 284 | auto size = image->getTotalSizeInBytesIncludingMipmaps(); 285 | void* data = vsg::allocate(size, vsg::ALLOCATOR_AFFINITY_DATA); 286 | memcpy(data, image->data(), size); 287 | 288 | layout.mipLevels = image->getNumMipmapLevels(); 289 | 290 | uint32_t width = image->s() / layout.blockWidth; 291 | uint32_t height = image->t() / layout.blockHeight; 292 | uint32_t depth = image->r() / layout.blockDepth; 293 | 294 | layout.origin = (image->getOrigin() == osg::Image::BOTTOM_LEFT) ? vsg::BOTTOM_LEFT : vsg::TOP_LEFT; 295 | 296 | if (blockSize == 64) 297 | { 298 | if (image->r() == 1) 299 | { 300 | return vsg::block64Array2D::create(width, height, reinterpret_cast(data), layout); 301 | } 302 | else 303 | { 304 | return vsg::block64Array3D::create(width, height, depth, reinterpret_cast(data), layout); 305 | } 306 | } 307 | else 308 | { 309 | if (image->r() == 1) 310 | { 311 | return vsg::block128Array2D::create(width, height, reinterpret_cast(data), layout); 312 | } 313 | else 314 | { 315 | return vsg::block128Array3D::create(width, height, depth, reinterpret_cast(data), layout); 316 | } 317 | } 318 | 319 | return {}; 320 | } 321 | 322 | template 323 | vsg::ref_ptr create(osg::ref_ptr image, VkFormat format) 324 | { 325 | vsg::ref_ptr vsg_data; 326 | if (image->r() == 1) 327 | { 328 | vsg_data = vsg::Array2D::create(image->s(), image->t(), reinterpret_cast(image->data()), vsg::Data::Properties{format}); 329 | } 330 | else 331 | { 332 | vsg_data = vsg::Array3D::create(image->s(), image->t(), image->r(), reinterpret_cast(image->data()), vsg::Data::Properties{format}); 333 | } 334 | 335 | return vsg_data; 336 | } 337 | 338 | vsg::ref_ptr convertToVsg(const osg::Image* image, bool mapRGBtoRGBAHint) 339 | { 340 | if (!image) 341 | { 342 | return createWhiteTexture(); 343 | } 344 | 345 | if (image->isCompressed()) 346 | { 347 | return convertCompressedImageToVsg(image); 348 | } 349 | 350 | int numComponents = 4; 351 | osg::ref_ptr new_image; 352 | 353 | switch (image->getPixelFormat()) 354 | { 355 | case (GL_RED): 356 | case (GL_LUMINANCE): 357 | case (GL_ALPHA): 358 | numComponents = 1; 359 | new_image = const_cast(image); 360 | break; 361 | 362 | case (GL_LUMINANCE_ALPHA): 363 | numComponents = 2; 364 | new_image = const_cast(image); 365 | break; 366 | 367 | case (GL_RGB): 368 | if (mapRGBtoRGBAHint) 369 | { 370 | numComponents = 4; 371 | new_image = formatImage(image, GL_RGBA); 372 | } 373 | else 374 | { 375 | numComponents = 3; 376 | new_image = const_cast(image); 377 | } 378 | break; 379 | 380 | case (GL_BGR): 381 | if (mapRGBtoRGBAHint) 382 | { 383 | numComponents = 4; 384 | new_image = formatImage(image, GL_RGBA); 385 | } 386 | else 387 | { 388 | numComponents = 3; 389 | new_image = formatImage(image, GL_RGB); 390 | } 391 | break; 392 | 393 | case (GL_RGBA): 394 | numComponents = 4; 395 | new_image = const_cast(image); 396 | break; 397 | 398 | case (GL_BGRA): 399 | numComponents = 4; 400 | new_image = formatImage(image, GL_RGBA); 401 | break; 402 | 403 | default: 404 | std::cout << "Warning: convertToVsg(osg::Image*) does not support image->getPixelFormat() == " << std::hex << image->getPixelFormat() << std::endl; 405 | return {}; 406 | } 407 | 408 | if (!new_image) 409 | { 410 | std::cout << "Warning: convertToVsg(osg::Image*) unable to create vsg::Data." << std::endl; 411 | return {}; 412 | } 413 | 414 | // we want to pass ownership of the new_image data on to the vsg_image so reset the allocation mode on the image to prevent deletion. 415 | new_image->setAllocationMode(osg::Image::NO_DELETE); 416 | 417 | vsg::ref_ptr vsg_data; 418 | 419 | switch (numComponents) 420 | { 421 | case (1): 422 | if (image->getDataType() == GL_UNSIGNED_BYTE) 423 | vsg_data = create(new_image, VK_FORMAT_R8_UNORM); 424 | else if (image->getDataType() == GL_UNSIGNED_SHORT) 425 | vsg_data = create(new_image, VK_FORMAT_R16_UNORM); 426 | else if (image->getDataType() == GL_UNSIGNED_INT) 427 | vsg_data = create(new_image, VK_FORMAT_R32_UINT); 428 | else if (image->getDataType() == GL_FLOAT) 429 | vsg_data = create(new_image, VK_FORMAT_R32_SFLOAT); 430 | else if (image->getDataType() == GL_DOUBLE) 431 | vsg_data = create(new_image, VK_FORMAT_R64_SFLOAT); 432 | break; 433 | case (2): 434 | if (image->getDataType() == GL_UNSIGNED_BYTE) 435 | vsg_data = create(new_image, VK_FORMAT_R8G8_UNORM); 436 | else if (image->getDataType() == GL_UNSIGNED_SHORT) 437 | vsg_data = create(new_image, VK_FORMAT_R16G16_UNORM); 438 | else if (image->getDataType() == GL_UNSIGNED_INT) 439 | vsg_data = create(new_image, VK_FORMAT_R32G32_UINT); 440 | else if (image->getDataType() == GL_FLOAT) 441 | vsg_data = create(new_image, VK_FORMAT_R32G32_SFLOAT); 442 | else if (image->getDataType() == GL_DOUBLE) 443 | vsg_data = create(new_image, VK_FORMAT_R64G64_SFLOAT); 444 | break; 445 | case (3): 446 | if (image->getDataType() == GL_UNSIGNED_BYTE) 447 | vsg_data = create(new_image, VK_FORMAT_R8G8B8_UNORM); 448 | else if (image->getDataType() == GL_UNSIGNED_SHORT) 449 | vsg_data = create(new_image, VK_FORMAT_R16G16B16_UNORM); 450 | else if (image->getDataType() == GL_UNSIGNED_INT) 451 | vsg_data = create(new_image, VK_FORMAT_R32G32B32_UINT); 452 | else if (image->getDataType() == GL_FLOAT) 453 | vsg_data = create(new_image, VK_FORMAT_R32G32B32_SFLOAT); 454 | else if (image->getDataType() == GL_DOUBLE) 455 | vsg_data = create(new_image, VK_FORMAT_R64G64B64_SFLOAT); 456 | break; 457 | case (4): 458 | if (image->getDataType() == GL_UNSIGNED_BYTE) 459 | vsg_data = create(new_image, VK_FORMAT_R8G8B8A8_UNORM); 460 | else if (image->getDataType() == GL_UNSIGNED_SHORT) 461 | vsg_data = create(new_image, VK_FORMAT_R16G16B16A16_UNORM); 462 | else if (image->getDataType() == GL_UNSIGNED_INT) 463 | vsg_data = create(new_image, VK_FORMAT_R32G32B32A32_UINT); 464 | else if (image->getDataType() == GL_FLOAT) 465 | vsg_data = create(new_image, VK_FORMAT_R32G32B32A32_SFLOAT); 466 | else if (image->getDataType() == GL_DOUBLE) 467 | vsg_data = create(new_image, VK_FORMAT_R64G64B64A64_SFLOAT); 468 | break; 469 | } 470 | 471 | vsg::Data::Properties& layout = vsg_data->properties; 472 | layout.mipLevels = image->getNumMipmapLevels(); 473 | layout.origin = (image->getOrigin() == osg::Image::BOTTOM_LEFT) ? vsg::BOTTOM_LEFT : vsg::TOP_LEFT; 474 | 475 | return vsg_data; 476 | } 477 | 478 | } // namespace osg2vsg 479 | -------------------------------------------------------------------------------- /src/osg2vsg/GeometryUtils.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright(c) 2019 Thomas Hogarth and Robert Osfield 4 | 5 | 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: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | 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. 10 | 11 | */ 12 | 13 | #include "GeometryUtils.h" 14 | #include "ImageUtils.h" 15 | #include "ShaderUtils.h" 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | namespace osg2vsg 22 | { 23 | 24 | vsg::ref_ptr convertToVsg(const osg::Vec2Array* inarray, uint32_t bindOverallPaddingCount) 25 | { 26 | if (!inarray) return vsg::ref_ptr(); 27 | 28 | uint32_t count = inarray->size(); 29 | uint32_t targetSize = std::max(count, bindOverallPaddingCount); 30 | 31 | vsg::ref_ptr outarray(new vsg::vec2Array(targetSize)); 32 | uint32_t i = 0; 33 | for (; i < count; ++i) 34 | { 35 | const osg::Vec2& in_value = inarray->at(i); 36 | outarray->at(i) = vsg::vec2(in_value.x(), in_value.y()); 37 | } 38 | 39 | if (i < bindOverallPaddingCount) 40 | { 41 | auto last = outarray->at(count - 1); 42 | for (; i < bindOverallPaddingCount; ++i) 43 | { 44 | outarray->at(i) = last; 45 | } 46 | } 47 | 48 | return outarray; 49 | } 50 | 51 | vsg::ref_ptr convertToVsg(const osg::Vec3Array* inarray, uint32_t bindOverallPaddingCount) 52 | { 53 | if (!inarray || inarray->size() == 0) return vsg::ref_ptr(); 54 | 55 | uint32_t count = inarray->size(); 56 | uint32_t targetSize = std::max(count, bindOverallPaddingCount); 57 | 58 | vsg::ref_ptr outarray(new vsg::vec3Array(targetSize)); 59 | uint32_t i = 0; 60 | for (; i < count; ++i) 61 | { 62 | const osg::Vec3& in_value = inarray->at(i); 63 | outarray->at(i) = vsg::vec3(in_value.x(), in_value.y(), in_value.z()); 64 | } 65 | 66 | if (i < bindOverallPaddingCount) 67 | { 68 | auto last = outarray->at(count - 1); 69 | for (; i < bindOverallPaddingCount; ++i) 70 | { 71 | outarray->at(i) = last; 72 | } 73 | } 74 | 75 | return outarray; 76 | } 77 | 78 | vsg::ref_ptr convertToVsg(const osg::Vec4Array* inarray, uint32_t bindOverallPaddingCount) 79 | { 80 | if (!inarray) return vsg::ref_ptr(); 81 | 82 | uint32_t count = inarray->size(); 83 | uint32_t targetSize = std::max(count, bindOverallPaddingCount); 84 | 85 | vsg::ref_ptr outarray(new vsg::vec4Array(targetSize)); 86 | uint32_t i = 0; 87 | for (; i < count; ++i) 88 | { 89 | const osg::Vec4& in_value = inarray->at(i); 90 | outarray->at(i) = vsg::vec4(in_value.x(), in_value.y(), in_value.z(), in_value.w()); 91 | } 92 | 93 | if (i < bindOverallPaddingCount) 94 | { 95 | auto last = outarray->at(count - 1); 96 | for (; i < bindOverallPaddingCount; ++i) 97 | { 98 | outarray->at(i) = last; 99 | } 100 | } 101 | 102 | return outarray; 103 | } 104 | 105 | vsg::ref_ptr convertToVsg(const osg::Array* inarray, uint32_t bindOverallPaddingCount) 106 | { 107 | if (!inarray) return vsg::ref_ptr(); 108 | 109 | switch (inarray->getType()) 110 | { 111 | case osg::Array::Type::Vec2ArrayType: return convertToVsg(dynamic_cast(inarray), bindOverallPaddingCount); 112 | case osg::Array::Type::Vec3ArrayType: return convertToVsg(dynamic_cast(inarray), bindOverallPaddingCount); 113 | case osg::Array::Type::Vec4ArrayType: return convertToVsg(dynamic_cast(inarray), bindOverallPaddingCount); 114 | default: return vsg::ref_ptr(); 115 | } 116 | } 117 | 118 | uint32_t calculateAttributesMask(const osg::Geometry* geometry) 119 | { 120 | uint32_t mask = 0; 121 | if (!geometry) return mask; 122 | 123 | if (geometry->getVertexArray() != nullptr) mask |= VERTEX; 124 | 125 | if (geometry->getNormalArray() != nullptr) 126 | { 127 | mask |= NORMAL; 128 | if (geometry->getNormalBinding() == osg::Geometry::AttributeBinding::BIND_OVERALL) mask |= NORMAL_OVERALL; 129 | } 130 | 131 | if (geometry->getColorArray() != nullptr) 132 | { 133 | mask |= COLOR; 134 | if (geometry->getColorBinding() == osg::Geometry::AttributeBinding::BIND_OVERALL) mask |= COLOR_OVERALL; 135 | } 136 | 137 | if (geometry->getVertexAttribArray(6) != nullptr) 138 | { 139 | mask |= TANGENT; 140 | if (geometry->getVertexAttribBinding(6) == osg::Geometry::AttributeBinding::BIND_OVERALL) mask |= TANGENT_OVERALL; 141 | } 142 | 143 | if (geometry->getVertexAttribArray(7) != nullptr) 144 | { 145 | mask |= TRANSLATE; 146 | if (geometry->getVertexAttribBinding(7) == osg::Geometry::AttributeBinding::BIND_OVERALL) mask |= TRANSLATE_OVERALL; 147 | } 148 | 149 | if (geometry->getTexCoordArray(0) != nullptr) mask |= TEXCOORD0; 150 | if (geometry->getTexCoordArray(1) != nullptr) mask |= TEXCOORD1; 151 | if (geometry->getTexCoordArray(2) != nullptr) mask |= TEXCOORD2; 152 | return mask; 153 | } 154 | 155 | VkSamplerAddressMode convertToSamplerAddressMode(osg::Texture::WrapMode wrapmode) 156 | { 157 | switch (wrapmode) 158 | { 159 | case osg::Texture::WrapMode::CLAMP: return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; 160 | case osg::Texture::WrapMode::CLAMP_TO_EDGE: return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; 161 | case osg::Texture::WrapMode::CLAMP_TO_BORDER: return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER; 162 | case osg::Texture::WrapMode::REPEAT: return VK_SAMPLER_ADDRESS_MODE_REPEAT; 163 | case osg::Texture::WrapMode::MIRROR: 164 | return VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT; 165 | //VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE no osg equivalent for this 166 | default: return VK_SAMPLER_ADDRESS_MODE_MAX_ENUM; // unknown 167 | } 168 | } 169 | 170 | std::pair convertToFilterAndMipmapMode(osg::Texture::FilterMode filtermode) 171 | { 172 | switch (filtermode) 173 | { 174 | case osg::Texture::FilterMode::LINEAR: return {VK_FILTER_LINEAR, VK_SAMPLER_MIPMAP_MODE_NEAREST}; 175 | case osg::Texture::FilterMode::LINEAR_MIPMAP_LINEAR: return {VK_FILTER_LINEAR, VK_SAMPLER_MIPMAP_MODE_LINEAR}; 176 | case osg::Texture::FilterMode::LINEAR_MIPMAP_NEAREST: return {VK_FILTER_LINEAR, VK_SAMPLER_MIPMAP_MODE_NEAREST}; 177 | case osg::Texture::FilterMode::NEAREST: return {VK_FILTER_NEAREST, VK_SAMPLER_MIPMAP_MODE_NEAREST}; 178 | case osg::Texture::FilterMode::NEAREST_MIPMAP_LINEAR: return {VK_FILTER_NEAREST, VK_SAMPLER_MIPMAP_MODE_LINEAR}; 179 | case osg::Texture::FilterMode::NEAREST_MIPMAP_NEAREST: return {VK_FILTER_NEAREST, VK_SAMPLER_MIPMAP_MODE_NEAREST}; 180 | default: return {VK_FILTER_MAX_ENUM, VK_SAMPLER_MIPMAP_MODE_MAX_ENUM}; // unknown 181 | } 182 | } 183 | 184 | vsg::ref_ptr convertToSampler(const osg::Texture* texture) 185 | { 186 | auto minFilter = texture->getFilter(osg::Texture::MIN_FILTER); 187 | auto magFilter = texture->getFilter(osg::Texture::MAG_FILTER); 188 | auto minFilterMipmapMode = convertToFilterAndMipmapMode(minFilter); 189 | auto magFilterMipmapMode = convertToFilterAndMipmapMode(magFilter); 190 | bool mipmappingRequired = (minFilter != osg::Texture::NEAREST) && (minFilter != osg::Texture::LINEAR); 191 | 192 | auto sampler = vsg::Sampler::create(); 193 | 194 | sampler->minFilter = minFilterMipmapMode.first; 195 | sampler->magFilter = magFilterMipmapMode.first; 196 | sampler->mipmapMode = minFilterMipmapMode.second; 197 | sampler->addressModeU = convertToSamplerAddressMode(texture->getWrap(osg::Texture::WrapParameter::WRAP_S)); 198 | sampler->addressModeV = convertToSamplerAddressMode(texture->getWrap(osg::Texture::WrapParameter::WRAP_T)); 199 | sampler->addressModeW = convertToSamplerAddressMode(texture->getWrap(osg::Texture::WrapParameter::WRAP_R)); 200 | 201 | // requires Logical device to have deviceFeatures.samplerAnisotropy = VK_TRUE; set when creating the vsg::Device 202 | sampler->anisotropyEnable = texture->getMaxAnisotropy() > 1.0f ? VK_TRUE : VK_FALSE; 203 | sampler->maxAnisotropy = texture->getMaxAnisotropy(); 204 | 205 | if (mipmappingRequired) 206 | { 207 | const osg::Image* image = (texture->getNumImages() > 0) ? texture->getImage(0) : nullptr; 208 | 209 | auto maxDimension = std::max({image->s(), image->t(), image->r()}); 210 | auto numMipMapLevels = static_cast(std::floor(std::log2(maxDimension))) + 1; 211 | 212 | sampler->minLod = 0; 213 | sampler->maxLod = static_cast(numMipMapLevels); 214 | sampler->mipLodBias = 0; 215 | } 216 | else 217 | { 218 | sampler->minLod = 0; 219 | sampler->maxLod = 0; 220 | sampler->mipLodBias = 0; 221 | } 222 | 223 | // Vulkan doesn't support a vec4 border colour so have to map across to the enum's based on a best fit. 224 | osg::Vec4 borderColor = texture->getBorderColor(); 225 | if (borderColor.a() < 0.5f) 226 | { 227 | sampler->borderColor = VK_BORDER_COLOR_INT_TRANSPARENT_BLACK; 228 | } 229 | else 230 | { 231 | bool nearerWhite = (borderColor.r() + borderColor.g() + borderColor.b()) >= 1.5f; 232 | sampler->borderColor = nearerWhite ? VK_BORDER_COLOR_INT_OPAQUE_WHITE : VK_BORDER_COLOR_INT_OPAQUE_BLACK; 233 | } 234 | 235 | sampler->unnormalizedCoordinates = VK_FALSE; 236 | sampler->compareEnable = VK_FALSE; 237 | 238 | return sampler; 239 | } 240 | 241 | vsg::ref_ptr convertToMaterialValue(const osg::Material* material) 242 | { 243 | auto matvalue = vsg::materialValue::create(); 244 | 245 | osg::Vec4 ambient = material->getAmbient(osg::Material::Face::FRONT); 246 | if (ambient.x() == 1.0f && ambient.y() == 1.0f && ambient.z() == 1.0f) ambient.set(0.1f, 0.1f, 0.1f, 1.0f); // ambient sanity check (shouldn't be needed but models seem to have bad material values) 247 | matvalue->value().ambientColor = vsg::vec4(ambient.x(), ambient.y(), ambient.z(), ambient.w()); 248 | 249 | osg::Vec4 diffuse = material->getDiffuse(osg::Material::Face::FRONT); 250 | if (diffuse.x() == 0.0f && diffuse.y() == 0.0f && diffuse.z() == 0.0f) diffuse.set(1.0f, 1.0f, 1.0f, 1.0f); // diffuse sanity check (shouldn't be needed but models seem to have bad material values) 251 | matvalue->value().diffuseColor = vsg::vec4(diffuse.x(), diffuse.y(), diffuse.z(), diffuse.w()); 252 | 253 | osg::Vec4 specular = material->getSpecular(osg::Material::Face::FRONT); 254 | matvalue->value().specularColor = vsg::vec4(specular.x(), specular.y(), specular.z(), specular.w()); 255 | 256 | float shininess = material->getShininess(osg::Material::Face::FRONT); 257 | matvalue->value().shininess = shininess; 258 | 259 | return matvalue; 260 | } 261 | 262 | struct ConvertPrimitives 263 | { 264 | std::vector points; 265 | std::vector lines; 266 | std::vector triangles; 267 | std::vector quads; 268 | 269 | void operator()(unsigned int i0) 270 | { 271 | points.push_back(i0); 272 | } 273 | void operator()(unsigned int i0, unsigned int i1) 274 | { 275 | lines.push_back(i0); 276 | lines.push_back(i1); 277 | } 278 | void operator()(unsigned int i0, unsigned int i1, unsigned int i2) 279 | { 280 | triangles.push_back(i0); 281 | triangles.push_back(i1); 282 | triangles.push_back(i2); 283 | } 284 | void operator()(unsigned int i0, unsigned int i1, unsigned int i2, unsigned int i3) 285 | { 286 | quads.push_back(i0); 287 | quads.push_back(i1); 288 | quads.push_back(i2); 289 | quads.push_back(i3); 290 | } 291 | }; 292 | 293 | vsg::ref_ptr convertToVsg(osg::Geometry* ingeometry, uint32_t requiredAttributesMask, GeometryTarget geometryTarget) 294 | { 295 | uint32_t instanceCount = 1; 296 | 297 | // work out if we need to enable instancing by looking at BIND_OVERALL entries 298 | // to see if any have more than one element which we'll interpret as requesting instancing, such as for our custom osg::Billboard handling. 299 | { 300 | osg::Geometry::ArrayList arrays; 301 | if (ingeometry->getArrayList(arrays)) 302 | { 303 | for (auto& array : arrays) 304 | { 305 | if (array->getBinding() == osg::Array::BIND_OVERALL) 306 | { 307 | if (instanceCount < array->getNumElements()) instanceCount = array->getNumElements(); 308 | } 309 | } 310 | } 311 | } 312 | 313 | uint32_t bindOverallPaddingCount = instanceCount; 314 | 315 | // convert attribute arrays, create defaults for any requested attributes that don't exist for now to ensure pipeline gets required data 316 | vsg::ref_ptr vertices(osg2vsg::convertToVsg(ingeometry->getVertexArray(), bindOverallPaddingCount)); 317 | if (!vertices.valid() || vertices->valueCount() == 0) return {}; 318 | 319 | // normals 320 | vsg::ref_ptr normals(osg2vsg::convertToVsg(ingeometry->getNormalArray(), bindOverallPaddingCount)); 321 | 322 | // tangents 323 | vsg::ref_ptr tangents(osg2vsg::convertToVsg(ingeometry->getVertexAttribArray(6), bindOverallPaddingCount)); 324 | if ((!tangents.valid() || tangents->valueCount() == 0) && (requiredAttributesMask & TANGENT)) 325 | { 326 | osg::ref_ptr tangentSpaceGenerator = new osgUtil::TangentSpaceGenerator(); 327 | tangentSpaceGenerator->generate(ingeometry, 0); 328 | 329 | osg::Vec4Array* tangentArray = tangentSpaceGenerator->getTangentArray(); 330 | //osg::Vec4Array* biNormalArray = tangGen->getBinormalArray(); 331 | 332 | if (tangentArray && tangentArray->size() > 0) 333 | { 334 | tangents = osg2vsg::convertToVsg(tangentArray, bindOverallPaddingCount); 335 | // bind them to the osg geometry too?? 336 | ingeometry->setVertexAttribArray(6, tangentArray); 337 | ingeometry->setVertexAttribBinding(6, osg::Geometry::BIND_PER_VERTEX); 338 | } 339 | } 340 | 341 | // colors 342 | vsg::ref_ptr colors(osg2vsg::convertToVsg(ingeometry->getColorArray(), bindOverallPaddingCount)); 343 | 344 | // tex0 345 | vsg::ref_ptr texcoord0(osg2vsg::convertToVsg(ingeometry->getTexCoordArray(0), bindOverallPaddingCount)); 346 | 347 | vsg::ref_ptr translations(osg2vsg::convertToVsg(ingeometry->getVertexAttribArray(7), bindOverallPaddingCount)); 348 | 349 | // fill arrays data list THE ORDER HERE IS IMPORTANT 350 | auto attributeArrays = vsg::DataList{vertices}; // always have vertices 351 | if (normals.valid() && normals->valueCount() > 0) attributeArrays.push_back(normals); 352 | if (tangents.valid() && tangents->valueCount() > 0) attributeArrays.push_back(tangents); 353 | if (colors.valid() && colors->valueCount() > 0) attributeArrays.push_back(colors); 354 | if (texcoord0.valid() && texcoord0->valueCount() > 0) attributeArrays.push_back(texcoord0); 355 | if (translations.valid() && translations->valueCount() > 0) attributeArrays.push_back(translations); 356 | 357 | // convert indices 358 | 359 | // assume all the draw elements use the same primitive mode, copy all drawelements indices into one index array and use a single drawindexed command 360 | // create a draw command per drawarrays primitive set 361 | 362 | vsg::Geometry::DrawCommands drawCommands; 363 | 364 | osg::TemplatePrimitiveIndexFunctor collectPrimitives; 365 | ingeometry->accept(collectPrimitives); 366 | #if 0 367 | // TODO : need to add support for points and lines. 368 | if (collectPrimitives.points.size()>0) 369 | { 370 | std::cout<<"Warning: points not yet supported by vsgXchange/OSG loader."<0) 374 | { 375 | std::cout<<"Warning: lines not yet supported by vsgXchange/OSG loader."< 393 | if (triangles.empty()) return {}; 394 | 395 | vsg::ref_ptr vsgindices; 396 | if (vertices->valueCount() > 16384) 397 | { 398 | auto indices = vsg::uintArray::create(triangles.size()); 399 | for (size_t i = 0; i < triangles.size(); ++i) 400 | { 401 | indices->set(i, triangles[i]); 402 | } 403 | vsgindices = indices; 404 | } 405 | else 406 | { 407 | auto indices = vsg::ushortArray::create(triangles.size()); 408 | for (size_t i = 0; i < triangles.size(); ++i) 409 | { 410 | indices->set(i, triangles[i]); 411 | } 412 | vsgindices = indices; 413 | } 414 | 415 | if (geometryTarget == VSG_COMMANDS) 416 | { 417 | vsg::ref_ptr commands(new vsg::Commands); 418 | 419 | commands->addChild(vsg::BindVertexBuffers::create(0, attributeArrays)); 420 | 421 | for (auto& draw : drawCommands) 422 | { 423 | commands->addChild(draw); 424 | } 425 | 426 | if (vsgindices) 427 | { 428 | commands->addChild(vsg::BindIndexBuffer::create(vsgindices)); 429 | commands->addChild(vsg::DrawIndexed::create(vsgindices->valueCount(), instanceCount, 0, 0, 0)); 430 | } 431 | 432 | return commands; 433 | } 434 | else if (geometryTarget == VSG_VERTEXINDEXDRAW && vsgindices && drawCommands.empty()) 435 | { 436 | vsg::ref_ptr vid(new vsg::VertexIndexDraw()); 437 | 438 | vid->assignArrays(attributeArrays); 439 | vid->assignIndices(vsgindices); 440 | vid->indexCount = vsgindices->valueCount(); 441 | vid->instanceCount = instanceCount; 442 | vid->firstIndex = 0; 443 | vid->vertexOffset = 0; 444 | vid->firstInstance = 0; 445 | 446 | return vid; 447 | } 448 | 449 | // fallback to create the vsg geometry 450 | auto geometry = vsg::Geometry::create(); 451 | 452 | geometry->assignArrays(attributeArrays); 453 | 454 | // copy into ushortArray 455 | if (vsgindices) 456 | { 457 | geometry->assignIndices(vsgindices); 458 | 459 | drawCommands.push_back(vsg::DrawIndexed::create(vsgindices->valueCount(), instanceCount, 0, 0, 0)); 460 | } 461 | 462 | geometry->commands = drawCommands; 463 | 464 | return geometry; 465 | } 466 | 467 | } // namespace osg2vsg 468 | --------------------------------------------------------------------------------