├── .gitignore ├── OE_PBR.sln ├── OE_PBR ├── AdvancedMaterial.cpp ├── AdvancedMaterial.h ├── CreateHelper.h ├── CubeToQuad.h ├── EnvLight.cpp ├── EnvLight.h ├── Export.h ├── GLTFV2Reader.h ├── IBLBaker.cpp ├── IBLBaker.h ├── OE_PBR.vcxproj ├── OE_PBR.vcxproj.filters ├── OE_PBR.vcxproj.user ├── PbrLightEffect.cpp ├── PbrLightEffect.h ├── PbrMaterial.cpp ├── PbrMaterial.h ├── RayPicker.h ├── ReflectionProbe.cpp ├── ReflectionProbe.h ├── Shader │ ├── BRDF.glsl │ ├── IBLFunc.glsl │ ├── IBLIrridianceMap.glsl │ ├── IBLPrefilterMap.glsl │ ├── IBLSphericalSample.glsl │ ├── IBLbrdfLUT.glsl │ ├── cube_to_quad.glsl │ ├── ibl_irradiance_quad.glsl │ ├── ibl_radiance_quad.glsl │ ├── light_functions.glsl │ ├── materials │ │ ├── advanced.glsl │ │ ├── mat_gold.glsl │ │ ├── metalroughness.glsl │ │ ├── standard.glsl │ │ └── water_ocean.glsl │ ├── normal.glsl │ ├── normal_functions.glsl │ ├── pbr.glsl │ ├── pbrSpecularGlossiness.glsl │ ├── readme.md │ ├── struct.glsl │ └── transmission.glsl ├── SkyBox.h ├── SnapImage.h ├── TestUI.h ├── ddsNew.h └── main.cpp ├── README.md └── screenshot ├── II66YW(H$T@UR9OP5J[T)GS.png ├── custom_material.png ├── gltfPBR.png ├── metalRoughness.png ├── sheen.png ├── split_sum.png ├── thickGlass.png └── thinTranslucent.png /.gitignore: -------------------------------------------------------------------------------- 1 | Debug 2 | .vs 3 | Asset 4 | x64 5 | -------------------------------------------------------------------------------- /OE_PBR.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.33130.400 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OE_PBR", "OE_PBR\OE_PBR.vcxproj", "{0D5253E2-056B-4FBC-B719-1F6B593693D6}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {0D5253E2-056B-4FBC-B719-1F6B593693D6}.Debug|x64.ActiveCfg = Debug|x64 17 | {0D5253E2-056B-4FBC-B719-1F6B593693D6}.Debug|x64.Build.0 = Debug|x64 18 | {0D5253E2-056B-4FBC-B719-1F6B593693D6}.Debug|x86.ActiveCfg = Debug|Win32 19 | {0D5253E2-056B-4FBC-B719-1F6B593693D6}.Debug|x86.Build.0 = Debug|Win32 20 | {0D5253E2-056B-4FBC-B719-1F6B593693D6}.Release|x64.ActiveCfg = Release|x64 21 | {0D5253E2-056B-4FBC-B719-1F6B593693D6}.Release|x64.Build.0 = Release|x64 22 | {0D5253E2-056B-4FBC-B719-1F6B593693D6}.Release|x86.ActiveCfg = Release|Win32 23 | {0D5253E2-056B-4FBC-B719-1F6B593693D6}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {B66A0C3A-BCC2-4138-98D8-D80D5CC8851A} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /OE_PBR/AdvancedMaterial.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include"AdvancedMaterial.h" 3 | namespace osgEarth 4 | { 5 | const std::string AdvancedMaterial::USE_IOR = std::string("USE_IOR"); 6 | const std::string AdvancedMaterial::USE_SHEEN = std::string("USE_SHEEN"); 7 | const std::string AdvancedMaterial::USE_CLEARCOAT = std::string("USE_CLEARCOAT"); 8 | const std::string AdvancedMaterial::USE_IRIDESCENCE = std::string("USE_IRIDESCENCE"); 9 | const std::string AdvancedMaterial::USE_TRANSMISSION = std::string("USE_TRANSMISSION"); 10 | 11 | void AdvancedMaterial::initTechniqueCallback() 12 | { 13 | auto sheenCB = [](osg::StateAttribute* attr, osg::NodeVisitor* nv) 14 | { 15 | osgEarth::AdvancedMaterial* material = static_cast(attr); 16 | for (unsigned int i = 0; i < attr->getNumParents(); i++) 17 | { 18 | osg::StateSet* stateSet = attr->getParent(i); 19 | auto on = material->getUseSheen() ? osg::StateAttribute::ON : osg::StateAttribute::OFF; 20 | stateSet->setDefine(USE_SHEEN, "1", on); 21 | if (!material->getUseSheen()) 22 | { 23 | return; 24 | } 25 | 26 | static const std::string SHEENCOLOR = UPREFIX "sheenColor"; 27 | static const std::string SHEENROUGHNESS = UPREFIX "sheenRoughness"; 28 | stateSet->getOrCreateUniform(SHEENCOLOR, osg::Uniform::FLOAT_VEC3)->set(material->getSheenColor()); 29 | stateSet->getOrCreateUniform(SHEENROUGHNESS, osg::Uniform::FLOAT)->set(material->getSheenRoughness()); 30 | 31 | auto sheenColorMap = material->getSheenColorMap(); 32 | auto sheenRoughnessMap = material->getSheenRoughnessMap(); 33 | if (sheenColorMap.valid()) 34 | { 35 | //auto defineKey = textureDefines[TextureEnum::SHEENCOLORMAP]; 36 | stateSet->setTextureAttributeAndModes(material->texUnitCnt(), material->getSheenColorMap(), osg::StateAttribute::ON); 37 | stateSet->getOrCreateUniform("SheenColorMap", osg::Uniform::SAMPLER_2D)->set(material->texUnitCnt()); 38 | material->incementTexUnit(); 39 | 40 | } 41 | if (sheenRoughnessMap.valid()) 42 | { 43 | stateSet->setTextureAttributeAndModes(material->texUnitCnt(), material->getSheenRoughnessMap(), osg::StateAttribute::ON); 44 | stateSet->getOrCreateUniform("SheenRoughnessMap", osg::Uniform::SAMPLER_2D)->set(material->texUnitCnt()); 45 | material->incementTexUnit(); 46 | } 47 | } 48 | 49 | }; 50 | 51 | auto clearCoatCB = [](osg::StateAttribute* attr, osg::NodeVisitor* nv) 52 | { 53 | osgEarth::AdvancedMaterial* material = static_cast(attr); 54 | for (unsigned int i = 0; i < attr->getNumParents(); i++) 55 | { 56 | osg::StateSet* stateSet = attr->getParent(i); 57 | auto on = material->getUseClearcoat() ? osg::StateAttribute::ON : osg::StateAttribute::OFF; 58 | stateSet->setDefine(USE_CLEARCOAT, "1", on); 59 | if (!material->getUseClearcoat()) 60 | { 61 | return; 62 | } 63 | 64 | stateSet->getOrCreateUniform(UPREFIX "clearcoat", osg::Uniform::FLOAT)->set(material->getClearcoat()); 65 | stateSet->getOrCreateUniform(UPREFIX "clearcoatRoughness", osg::Uniform::FLOAT)->set(material->getClearcoatRoughness()); 66 | 67 | } 68 | 69 | }; 70 | 71 | auto transmissionCB = [](osg::StateAttribute* attr, osg::NodeVisitor* nv) 72 | { 73 | osgEarth::AdvancedMaterial* material = static_cast(attr); 74 | for (unsigned int i = 0; i < attr->getNumParents(); i++) 75 | { 76 | 77 | osg::StateSet* stateSet = attr->getParent(i); 78 | auto on = material->getUseTransmission() ? osg::StateAttribute::ON : osg::StateAttribute::OFF; 79 | stateSet->setDefine(USE_TRANSMISSION, "1", on); 80 | if (!material->getUseTransmission()) 81 | { 82 | return; 83 | } 84 | 85 | //stateSet->setMode(GL_BLEND, 1); 86 | stateSet->getOrCreateUniform(UPREFIX "transmission", osg::Uniform::FLOAT)->set(material->getTransmission()); 87 | stateSet->getOrCreateUniform(UPREFIX "ior", osg::Uniform::FLOAT)->set(material->getIOR()); 88 | stateSet->getOrCreateUniform(UPREFIX "transmissionAlpha", osg::Uniform::FLOAT)->set(material->getTransmissionAlpha()); 89 | stateSet->getOrCreateUniform(UPREFIX "thickness", osg::Uniform::FLOAT)->set(material->getThickness()); 90 | stateSet->getOrCreateUniform(UPREFIX "attenuationDistance", osg::Uniform::FLOAT)->set(material->getAttenuationDistance()); 91 | stateSet->getOrCreateUniform(UPREFIX "attenuationColor", osg::Uniform::FLOAT_VEC3)->set(material->getAttenuationColor()); 92 | 93 | } 94 | 95 | }; 96 | 97 | _techniqueCallbacks = new SAttrCallback(); 98 | _techniqueCallbacks->addUpdateCallback("pbr", new ExtensionedMaterialCallback()); 99 | _techniqueCallbacks->addUpdateCallback("sheen", sheenCB); 100 | _techniqueCallbacks->addUpdateCallback("clearcoat", clearCoatCB); 101 | _techniqueCallbacks->addUpdateCallback("transmission", transmissionCB); 102 | setUpdateCallback(_techniqueCallbacks); 103 | } 104 | 105 | void AdvancedMaterial::setMaterialImage(AdvancedMaterial::TextureEnum mapEnum, osg::Image* image) 106 | { 107 | 108 | } 109 | void AdvancedMaterial::setMaterialImage(StandardPBRMaterial::TextureEnum mapEnum, osg::Image* image) 110 | { 111 | StandardPBRMaterial::setMaterialImage(mapEnum, image); 112 | } 113 | void AdvancedMaterial::setMaterialImage(StandardPBRMaterial::TextureEnum mapEnum, const std::string& imageUrl) 114 | { 115 | StandardPBRMaterial::setMaterialImage(mapEnum, imageUrl); 116 | } 117 | AdvancedMaterial::AdvancedMaterial():ExtensionedMaterial() 118 | { 119 | initTechniqueCallback(); 120 | setMaterialFile("materials/advanced.glsl"); 121 | } 122 | 123 | void AdvancedMaterial::addUpdateCallback(const std::string& key, osg::StateAttributeCallback* f) 124 | { 125 | _techniqueCallbacks->addUpdateCallback(key, f); 126 | } 127 | void AdvancedMaterial::addUpdateCallback(const std::string& key, F&& f) 128 | { 129 | _techniqueCallbacks->addUpdateCallback(key, std::move(f)); 130 | } 131 | } -------------------------------------------------------------------------------- /OE_PBR/AdvancedMaterial.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "PbrMaterial.h" 3 | #include 4 | #include 5 | 6 | 7 | namespace osgEarth 8 | { 9 | using F = std::function; 10 | struct SAttrCallback : public osg::StateAttributeCallback 11 | { 12 | SAttrCallback() {} 13 | void operator()(osg::StateAttribute* attr, osg::NodeVisitor* nv) 14 | { 15 | for (auto& f : _funList) 16 | { 17 | f(attr, nv); 18 | } 19 | for (auto& cb : _subCallbacks) 20 | { 21 | cb->operator()(attr, nv); 22 | } 23 | } 24 | std::vector _funList; 25 | std::vector > _subCallbacks; 26 | std::vector _techniqueKeys; 27 | 28 | public: 29 | bool exist(const std::string& key) 30 | { 31 | for (const auto& _key : _techniqueKeys) 32 | { 33 | if (_key == key) 34 | { 35 | return true; 36 | } 37 | } 38 | return false; 39 | } 40 | void addUpdateCallback(const std::string& key, F&& f) 41 | { 42 | if (exist(key)) 43 | return; 44 | printf("<<<<<<<<<<<<<<<<<<<<<<<< textureDefines = { 80 | {CLEARCOATMAP, "USE_CLEARCOATMAP"}, 81 | {CLEARCOAT_ROUGHNESSMAP, "USE_CLEARCOAT_ROUGHNESSMAP"}, 82 | {IRIDESCENCEMAP, "USE_IRIDESCENCEMAP"}, 83 | {IRIDESCENCE_THICKNESSMAP, "USE_IRIDESCENCE_THICKNESSMAP"}, 84 | {SHEENCOLORMAP, "USE_SHEENCOLORMAP"}, 85 | {SHEENROUGHNESSMAP, "USE_SHEENROUGHNESSMAP"}, 86 | {TRANSMISSIONMAP, "USE_TRANSMISSIONMAP"}, 87 | {THICKNESSMAP, "USE_THICKNESSMAP"}, 88 | }; 89 | PROPERTY_DEFAULT(float, IOR, 1.2f) 90 | 91 | PROPERTY_DEFAULT(bool, UseClearcoat, false) 92 | PROPERTY_DEFAULT(float, Clearcoat, 0.5f) 93 | PROPERTY_DEFAULT(float, ClearcoatRoughness, 0.5f) 94 | PROPERTY_DEFAULT(osg::ref_ptr, ClearcoatRoughnessMap, 0) 95 | PROPERTY_DEFAULT(osg::ref_ptr, ClearcoatNormalMap, 0) 96 | PROPERTY_DEFAULT(Vec2f, ClearcoatNormalScale, osg::Vec2f(0.1f, 0.1f)) 97 | /*PROPERTY_DEFAULT(Vec3f, ClearcoatF0, Vec3(0.04f, 0.04f, 0.04f)) 98 | PROPERTY_DEFAULT(float, ClearcoatF90, 1.0f)*/ 99 | 100 | PROPERTY_DEFAULT(float, Iridescence, 0.1f) 101 | PROPERTY_DEFAULT(float, IridescenceIOR, 0.1f) 102 | PROPERTY_DEFAULT(float, IridescenceThickness, 0.1f) 103 | PROPERTY_DEFAULT(Vec3f, IridescenceFresnel, Vec3(0.0f, 0.0f, 0.0f)) 104 | PROPERTY_DEFAULT(float, IridescenceF0, 0.1f) 105 | 106 | PROPERTY_DEFAULT(bool, UseSheen, false) 107 | PROPERTY_DEFAULT(Vec3f, SheenColor, Vec3(0.0f, 0.5f, 0.0f)) 108 | PROPERTY_DEFAULT(float, SheenRoughness, 0.1f) 109 | PROPERTY_DEFAULT(osg::ref_ptr, SheenColorMap, 0) 110 | PROPERTY_DEFAULT(osg::ref_ptr, SheenRoughnessMap, 0) 111 | 112 | PROPERTY_DEFAULT(bool, UseTransmission, false) 113 | PROPERTY_DEFAULT(float, Transmission, 0.1f) 114 | PROPERTY_DEFAULT(float, TransmissionAlpha, 0.1f) 115 | PROPERTY_DEFAULT(float, Thickness, 0.1f) 116 | PROPERTY_DEFAULT(float, AttenuationDistance, 0.1f) 117 | PROPERTY_DEFAULT(Vec3f, AttenuationColor, Vec3(0.5f, 0.5f, 0.5f)) 118 | PROPERTY_DEFAULT(osg::ref_ptr, ThicknessMap, 0) 119 | public: 120 | void setMaterialImage(AdvancedMaterial::TextureEnum mapEnum, osg::Image* image); 121 | void setMaterialImage(StandardPBRMaterial::TextureEnum mapEnum, osg::Image* image); 122 | void setMaterialImage(StandardPBRMaterial::TextureEnum mapEnum, const std::string& imageUrl); 123 | 124 | protected: 125 | void initTechniqueCallback(); 126 | 127 | osg::ref_ptr _techniqueCallbacks; 128 | static constexpr const char* IOR = "IOR"; 129 | static constexpr const char* CLEARCOAT = "CLEARCOAT"; 130 | static constexpr const char* IRIDESCENCE = "IRIDESCENCE"; 131 | static constexpr const char* SHEEN = "SHEEN"; 132 | static constexpr const char* TRANSMISSION = "TRANSMISSION"; 133 | 134 | static constexpr const char* SHADER_MODEL = "PRINCIPLE_BSDF"; 135 | 136 | static const std::string USE_IOR; 137 | static const std::string USE_CLEARCOAT; 138 | static const std::string USE_IRIDESCENCE; 139 | static const std::string USE_SHEEN; 140 | static const std::string USE_TRANSMISSION; 141 | }; 142 | } // namespace osgEarth -------------------------------------------------------------------------------- /OE_PBR/CreateHelper.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | #include 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | #include "AdvancedMaterial.h" 21 | #include "CubeToQuad.h" 22 | #include "EnvLight.h" 23 | #include "GLTFV2Reader.h" 24 | #include "IBLBaker.h" 25 | #include "PbrLightEffect.h" 26 | #include "PbrMaterial.h" 27 | #include "RayPicker.h" 28 | #include "ReflectionProbe.h" 29 | #include "SkyBox.h" 30 | 31 | struct DrawCallback : public osg::Drawable::DrawCallback 32 | { 33 | 34 | DrawCallback() 35 | : _firstTime(true) 36 | { 37 | } 38 | 39 | virtual void drawImplementation(osg::RenderInfo& renderInfo, const osg::Drawable* drawable) const 40 | { 41 | osg::State& state = *renderInfo.getState(); 42 | 43 | // ZoneNamedN(___tracy_scoped_zone, "CustomDrawCallback", true); 44 | // OE_PROFILING_ZONE_NAMED("CustomDrawCallback"); 45 | 46 | drawable->drawImplementation(renderInfo); 47 | } 48 | 49 | mutable bool _firstTime; 50 | }; 51 | 52 | osg::ref_ptr CreatePbrSphere() 53 | { 54 | osg::ref_ptr geode = new osg::Geode(); 55 | 56 | osg::ShapeDrawable* sd = new osg::ShapeDrawable(new osg::Sphere(osg::Vec3f(0.0f, 0.0f, 0.0f), 2.0f)); 57 | 58 | geode->addDrawable(sd); 59 | 60 | bool usePhong = false; 61 | bool usePBR = true; 62 | if (usePhong) 63 | { 64 | auto* phong = new PhongLightingEffect(); 65 | phong->attach(geode->getOrCreateStateSet()); 66 | 67 | osg::ref_ptr m = new osgEarth::MaterialGL3(); 68 | m->setAmbient(m->FRONT_AND_BACK, osg::Vec4(.5, .5, .5, 1)); 69 | m->setDiffuse(m->FRONT_AND_BACK, osg::Vec4(1, 1, 1, 1)); 70 | m->setSpecular(m->FRONT_AND_BACK, osg::Vec4(0.2, 0.2, 0.2, 1)); 71 | m->setEmission(m->FRONT_AND_BACK, osg::Vec4(0, 0, 0, 1)); 72 | m->setShininess(m->FRONT_AND_BACK, 40.0); 73 | geode->getOrCreateStateSet()->setAttributeAndModes(m, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); 74 | MaterialCallback().operator()(m, 0L); 75 | } 76 | else if (usePBR) 77 | { 78 | } 79 | 80 | return geode; 81 | } 82 | 83 | osg::ref_ptr CreateExtensionedMaterialSphere() 84 | { 85 | osg::ref_ptr geode = new osg::Geode(); 86 | 87 | osg::ShapeDrawable* sd = new osg::ShapeDrawable(new osg::Sphere(osg::Vec3f(0.0f, 0.0f, 0.0f), 2.0f)); 88 | 89 | geode->addDrawable(sd); 90 | osg::ref_ptr m = new osgEarth::ExtensionedMaterial(); 91 | m->setName("PBR_MATERIAL"); 92 | 93 | m->setBaseColorFactor(osg::Vec4f(1.0f, 1.0f, 1.0f, 1.0f)); 94 | m->setEmissiveFactor(osg::Vec3f(0.0f, 0.0f, 0.0f)); 95 | m->setMetallicFactor(1.00f); 96 | m->setRoughnessFactor(0.88f); 97 | m->setAoStrength(0.15f); 98 | 99 | std::string dir = "C:/Users/10677/source/repos/OE_PBR/OE_PBR/Asset/Material/metal/", format = ".png"; 100 | m->extTextureAttribute("metalMap", dir + "metal" + format, "OE_ENABLE_Metal_MAP"); 101 | m->extTextureAttribute("roughnessMap", dir + "rough" + format, "OE_ENABLE_Roughness_MAP"); 102 | 103 | m->setMaterialImage(osgEarth::StandardPBRMaterial::TextureEnum::NormalMap, dir + "normal" + format); 104 | 105 | m->setMaterialFile("materials/metalroughness.glsl"); 106 | 107 | geode->getOrCreateStateSet()->setAttributeAndModes(m, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); 108 | 109 | m->setReceiveEnvLight(false); 110 | 111 | ExtensionedMaterialCallback().operator()(m, 0L); 112 | 113 | auto* pbr = new PbrLightEffect(); 114 | pbr->attach(geode->getOrCreateStateSet()); 115 | 116 | auto* vp = osgEarth::VirtualProgram::get(geode->getOrCreateStateSet()); 117 | vp->setShaderLogging(true); 118 | 119 | return geode; 120 | } 121 | osg::Node* CreateLight(osg::Light* myLight1, osg::Node* node) 122 | { 123 | osg::Group* lightGroup = new osg::Group; 124 | 125 | float modelSize = 5.0f; 126 | 127 | myLight1->setLightNum(0); 128 | myLight1->setPosition(osg::Vec4(1.0f, 1.0f, 0.0f, 0.0f)); 129 | myLight1->setAmbient(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f)); 130 | myLight1->setDiffuse(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f)); 131 | myLight1->setSpotCutoff(20.0f); 132 | myLight1->setSpotExponent(0.5f); 133 | myLight1->setDirection(osg::Vec3(-0.382353f, -0.254902f, -0.382353f)); 134 | 135 | osg::LightSource* lightS1 = new osg::LightSource; 136 | lightS1->setLight(myLight1); 137 | lightS1->setLocalStateSetModes(osg::StateAttribute::ON); 138 | 139 | /* lightS1->setStateSetModes(*rootStateSet, osg::StateAttribute::ON);*/ 140 | lightGroup->addChild(lightS1); 141 | #ifdef NDEBUG 142 | auto cb = new LightSourceGL3UniformGenerator(); 143 | lightS1->addCullCallback(cb); 144 | #endif 145 | 146 | /* EnvLightSource* els = new EnvLightSource; 147 | els->addCullCallback(new EnvLightGL3UniformGenerator()); 148 | lightGroup->addChild(els);*/ 149 | return lightGroup; 150 | } 151 | 152 | std::vector > createNoTexMaterials() 153 | { 154 | std::vector > result; 155 | 156 | for (int i = 0; i < 9; i++) 157 | { 158 | for (int j = 0; j < 9; j++) 159 | { 160 | osg::ref_ptr m = new osgEarth::StandardPBRMaterial(); 161 | 162 | m->setBaseColorFactor(osg::Vec4f(1.0f, 1.0f, 1.0f, 1.0f)); 163 | m->setEmissiveFactor(osg::Vec3f(0.0f, 0.0f, 0.0f)); 164 | m->setMetallicFactor(0.11f * i + 0.01); 165 | m->setRoughnessFactor(0.11f * j + 0.01); 166 | m->setReceiveEnvLight(true); 167 | result.push_back(m); 168 | } 169 | } 170 | 171 | return result; 172 | } 173 | std::vector > createMaterials() 174 | { 175 | std::vector > result; 176 | 177 | auto absolutePath = osgEarth::Util::getAbsolutePath("Asset/Material"); 178 | osg::ref_ptr dbo = new osgDB::Options(); 179 | if (osgDB::fileExists(absolutePath)) 180 | { 181 | dbo->setDatabasePath(absolutePath); 182 | } 183 | 184 | osg::ref_ptr grass = new osgEarth::ExtensionedMaterial(); 185 | grass->setName("grass"); 186 | grass->setDataBaseOption(dbo); 187 | 188 | grass->setBaseColorFactor(osg::Vec4f(0.5f, 0.5f, 0.5f, 0.5f)); 189 | grass->setEmissiveFactor(osg::Vec3f(0.0f, 0.0f, 0.0f)); 190 | grass->setMetallicFactor(1.0f); 191 | grass->setRoughnessFactor(1.0f); 192 | 193 | grass->setMaterialImage(osgEarth::StandardPBRMaterial::TextureEnum::MetalRoughenssMap, "grass/metalRoughness.png"); 194 | grass->setMaterialImage(osgEarth::StandardPBRMaterial::TextureEnum::EmissiveMap, "grass/emissive.png"); 195 | grass->setMaterialImage(osgEarth::StandardPBRMaterial::TextureEnum::NormalMap, "grass/normal.png"); 196 | grass->setMaterialImage(osgEarth::StandardPBRMaterial::TextureEnum::OcclusionMap, "grass/ao.png"); 197 | grass->setMaterialImage(osgEarth::StandardPBRMaterial::TextureEnum::BaseColorMap, "grass/albedo.png"); 198 | grass->setReceiveEnvLight(true); 199 | 200 | grass->extTextureAttribute("metalMap", "grass/metallic.png", "OE_ENABLE_Metal_MAP"); 201 | grass->extTextureAttribute("roughnessMap", "grass/roughness.png", "OE_ENABLE_Roughness_MAP"); 202 | grass->setMaterialFile("materials/metalroughness.glsl"); 203 | result.push_back(grass); 204 | 205 | osg::ref_ptr m = new osgEarth::ExtensionedMaterial(); 206 | m->setName("metal"); 207 | m->setDataBaseOption(dbo); 208 | 209 | m->setBaseColorFactor(osg::Vec4f(1.0f, 1.0f, 1.0f, 1.0f)); 210 | m->setEmissiveFactor(osg::Vec3f(0.0f, 0.0f, 0.0f)); 211 | m->setMetallicFactor(1.00f); 212 | m->setRoughnessFactor(1.0f); 213 | m->setMaterialImage(osgEarth::StandardPBRMaterial::TextureEnum::BaseColorMap, "metal/albedo.png"); 214 | m->setReceiveEnvLight(true); 215 | 216 | m->extTextureAttribute("metalMap", "metal/metal.png", "OE_ENABLE_Metal_MAP"); 217 | m->extTextureAttribute("roughnessMap", "metal/rough.png", "OE_ENABLE_Roughness_MAP"); 218 | m->setMaterialFile("materials/metalroughness.glsl"); 219 | result.push_back(m); 220 | 221 | osg::ref_ptr marber = new osgEarth::ExtensionedMaterial(); 222 | marber->setName("dalishi"); 223 | marber->setDataBaseOption(dbo); 224 | marber->setBaseColorFactor(osg::Vec4f(1.0f, 1.0f, 1.0f, 1.0f)); 225 | marber->setEmissiveFactor(osg::Vec3f(0.0f, 0.0f, 0.0f)); 226 | marber->setMetallicFactor(0.08f); 227 | marber->setRoughnessFactor(0.176f); 228 | 229 | marber->setMaterialImage(osgEarth::StandardPBRMaterial::TextureEnum::NormalMap, "gray/normal.png"); 230 | marber->setMaterialImage(osgEarth::StandardPBRMaterial::TextureEnum::OcclusionMap, "gray/ao.png"); 231 | marber->setMaterialImage(osgEarth::StandardPBRMaterial::TextureEnum::BaseColorMap, "gray/albedo.png"); 232 | marber->setReceiveEnvLight(true); 233 | 234 | marber->extTextureAttribute("metalMap", "gray/metallic.png", "OE_ENABLE_Metal_MAP"); 235 | marber->extTextureAttribute("roughnessMap", "gray/roughness.png", "OE_ENABLE_Roughness_MAP"); 236 | marber->setMaterialFile("materials/metalroughness.glsl"); 237 | result.push_back(marber); 238 | 239 | osg::ref_ptr rock = new osgEarth::ExtensionedMaterial(); 240 | rock->setName("rock"); 241 | rock->setDataBaseOption(dbo); 242 | 243 | rock->setBaseColorFactor(osg::Vec4f(1.0f, 1.0f, 1.0f, 1.0f)); 244 | rock->setEmissiveFactor(osg::Vec3f(0.0f, 0.0f, 0.0f)); 245 | rock->setMetallicFactor(0.5f); 246 | rock->setRoughnessFactor(0.668f); 247 | rock->setMaterialImage(osgEarth::StandardPBRMaterial::TextureEnum::NormalMap, "rock/normal.png"); 248 | rock->setMaterialImage(osgEarth::StandardPBRMaterial::TextureEnum::OcclusionMap, "rock/ao.png"); 249 | rock->setMaterialImage(osgEarth::StandardPBRMaterial::TextureEnum::BaseColorMap, "rock/albedo.png"); 250 | rock->setReceiveEnvLight(true); 251 | 252 | rock->extTextureAttribute("metalMap", "rock/metallic.png", "OE_ENABLE_Metal_MAP"); 253 | rock->extTextureAttribute("roughnessMap", "rock/roughness.png", "OE_ENABLE_Roughness_MAP"); 254 | rock->setMaterialFile("materials/metalroughness.glsl"); 255 | result.push_back(rock); 256 | 257 | osg::ref_ptr water = new osgEarth::ExtensionedMaterial(); 258 | water->setName("water"); 259 | water->setDataBaseOption(dbo); 260 | 261 | water->setBaseColorFactor(osg::Vec4f(1.0f, 1.0f, 1.0f, 1.0f)); 262 | water->setEmissiveFactor(osg::Vec3f(0.0f, 0.0f, 0.0f)); 263 | water->setMetallicFactor(0.04f); 264 | water->setRoughnessFactor(0.668f); 265 | water->setReceiveEnvLight(true); 266 | 267 | water->extTextureAttribute("water_M", "unreal/Textures/T_Water_M.tga", "water_M"); 268 | water->extTextureAttribute("water_N", "unreal/Textures/T_Water_N.tga", "water_N"); 269 | water->extTextureAttribute("perlin_Noise", "unreal/Textures/T_Perlin_Noise_M.tga", "perlin_Noise"); 270 | water->setMaterialFile("materials/water_ocean.glsl"); 271 | result.push_back(water); 272 | 273 | osg::ref_ptr gold = new osgEarth::ExtensionedMaterial(); 274 | gold->setName("gold"); 275 | gold->setDataBaseOption(dbo); 276 | 277 | gold->setBaseColorFactor(osg::Vec4f(1.0f, 1.0f, 1.0f, 1.0f)); 278 | gold->setEmissiveFactor(osg::Vec3f(0.0f, 0.0f, 0.0f)); 279 | gold->setMetallicFactor(0.8f); 280 | gold->setRoughnessFactor(0.168f); 281 | gold->setReceiveEnvLight(true); 282 | 283 | gold->extTextureAttribute("T_MacroVariation", "gold/T_MacroVariation.tga", "T_MacroVariation"); 284 | gold->extTextureAttribute("T_Metal_Gold_D", "gold/T_Metal_Gold_D.tga", "T_Metal_Gold_D"); 285 | gold->setMaterialImage(osgEarth::StandardPBRMaterial::TextureEnum::NormalMap, "gold/T_Metal_Gold_N.tga"); 286 | gold->setMaterialFile("materials/mat_gold.glsl"); 287 | result.push_back(gold); 288 | 289 | return result; 290 | } 291 | 292 | std::vector > createAdvancedMaterials() 293 | { 294 | auto absolutePath = osgEarth::Util::getAbsolutePath("Asset/Material"); 295 | osg::ref_ptr dbo = new osgDB::Options(); 296 | if (osgDB::fileExists(absolutePath)) 297 | { 298 | dbo->setDatabasePath(absolutePath); 299 | } 300 | 301 | std::vector > result; 302 | { 303 | osg::ref_ptr m = new osgEarth::AdvancedMaterial(); 304 | m->setName("sheen"); 305 | m->setDataBaseOption(dbo); 306 | m->setUseSheen(true); 307 | m->setSheenColor(osg::Vec3f(1.0f, 0.0f, 1.0f)); 308 | m->setSheenRoughness(0.5f); 309 | result.push_back(m); 310 | } 311 | { 312 | osg::ref_ptr m1 = new osgEarth::AdvancedMaterial(); 313 | m1->setDataBaseOption(dbo); 314 | m1->setName("Clearcoat"); 315 | m1->setUseClearcoat(true); 316 | m1->setMetallicFactor(0.1); 317 | m1->setClearcoat(1.0f); 318 | m1->setClearcoatRoughness(0.1f); 319 | 320 | m1->setMaterialImage(StandardPBRMaterial::NormalMap, "brick/T_Brick_Clay_New_N.tga"); 321 | m1->setMaterialImage(StandardPBRMaterial::BaseColorMap, "brick/T_Brick_Clay_New_D.tga"); 322 | m1->extTextureAttribute("clearcoatRoughnessMap", "brick/T_Brick_Clay_New_D.tga", "USE_CLEARCOAT_ROUGHNESSMAP"); 323 | result.push_back(m1); 324 | 325 | { 326 | osg::ref_ptr m2 = new osgEarth::AdvancedMaterial(); 327 | m2->setName("Transmission"); 328 | m2->setDataBaseOption(dbo); 329 | m2->setUseTransmission(true); 330 | m2->setTransmission(1.0); 331 | m2->setThickness(0.1f); 332 | m2->setMetallicFactor(0.1); 333 | m2->setRoughnessFactor(0.1f); 334 | result.push_back(m2); 335 | } 336 | } 337 | return result; 338 | } 339 | osg::ref_ptr createMaterialSpheres(int matType = 1) 340 | { 341 | osg::ref_ptr gp = new osg::Group(); 342 | 343 | if (matType == 1) 344 | { 345 | std::vector > materials = std::move(createNoTexMaterials()); 346 | int row, col; 347 | row = col = 9; 348 | 349 | for (size_t i = 0; i < row; i++) 350 | { 351 | for (size_t j = 0; j < col; j++) 352 | { 353 | osg::ref_ptr geode = new osg::Geode(); 354 | osg::ShapeDrawable* sd = new osg::ShapeDrawable(new osg::Sphere(osg::Vec3f(0.0f, 0.0f, 0.0f), 2.0f)); 355 | geode->addDrawable(sd); 356 | sd->setDrawCallback(new DrawCallback()); 357 | geode->getOrCreateStateSet()->setAttributeAndModes(materials[i * col + j], osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); 358 | geode->getOrCreateStateSet()->setName("110"); 359 | // geode->getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); 360 | osg::ref_ptr matrixT = new osg::MatrixTransform(); 361 | 362 | matrixT->setMatrix(osg::Matrix::translate((double)i * 5.0, (double)j * 5.0, 0.0)); 363 | matrixT->addChild(geode); 364 | matrixT->setName(materials[i * col + j]->getName()); 365 | 366 | PBRMaterialCallback().operator()(materials[i * col + j], 0L); 367 | auto* pbr = new PbrLightEffect(); 368 | pbr->attach(geode->getOrCreateStateSet()); 369 | gp->addChild(matrixT); 370 | } 371 | } 372 | } 373 | else if (matType == 2) 374 | { 375 | auto materials = std::move(createMaterials()); 376 | for (size_t i = 0; i < materials.size(); i++) 377 | { 378 | std::cout << " gsfdg " << i << std::endl; 379 | osg::ref_ptr geode = new osg::Geode(); 380 | osg::ShapeDrawable* sd = new osg::ShapeDrawable(new osg::Sphere(osg::Vec3f(0.0f, 0.0f, 0.0f), 2.0f)); 381 | geode->addDrawable(sd); 382 | geode->getOrCreateStateSet()->setAttributeAndModes(materials[i], osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); 383 | 384 | osg::ref_ptr matrixT = new osg::MatrixTransform(); 385 | 386 | matrixT->setMatrix(osg::Matrix::translate((double)i * 5.0, 0.0, 0.0)); 387 | matrixT->addChild(geode); 388 | matrixT->setName(materials[i]->getName()); 389 | // materials[i]->setUpdateCallback(new ExtensionedMaterialCallback()); 390 | ExtensionedMaterialCallback().operator()(materials[i], 0L); 391 | auto* pbr = new PbrLightEffect(); 392 | pbr->attach(geode->getOrCreateStateSet()); 393 | gp->addChild(matrixT); 394 | } 395 | } 396 | else 397 | { 398 | auto materials = std::move(createAdvancedMaterials()); 399 | for (size_t i = 0; i < materials.size(); i++) 400 | { 401 | std::cout << " gsfdg " << i << std::endl; 402 | osg::ref_ptr geode = new osg::Geode(); 403 | osg::ShapeDrawable* sd = new osg::ShapeDrawable(new osg::Sphere(osg::Vec3f(0.0f, 0.0f, 0.0f), 2.0f)); 404 | geode->addDrawable(sd); 405 | geode->getOrCreateStateSet()->setAttributeAndModes(materials[i], osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); 406 | 407 | osg::ref_ptr matrixT = new osg::MatrixTransform(); 408 | 409 | matrixT->setMatrix(osg::Matrix::translate((double)i * 5.0, 0.0, 0.0)); 410 | matrixT->addChild(geode); 411 | matrixT->setName(materials[i]->getName()); 412 | if (materials[i]->getUseTransmission()) 413 | { 414 | geode->setNodeMask(TRANSLUCENT_MASK); 415 | } 416 | 417 | auto* pbr = new PbrLightEffect(); 418 | pbr->attach(geode->getOrCreateStateSet()); 419 | gp->addChild(matrixT); 420 | } 421 | } 422 | 423 | return gp; 424 | } 425 | osg::Camera* createHUDCamera(osg::Texture* _texture, osgDB::Options* shaderDB) 426 | { 427 | osg::Camera* camera = new osg::Camera; 428 | 429 | // set the projection matrix 430 | camera->setProjectionMatrix(osg::Matrix::ortho2D(0, 200, 0, 200)); 431 | 432 | // set the view matrix 433 | camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF); 434 | camera->setViewMatrix(osg::Matrix::identity()); 435 | 436 | // only clear the depth buffer 437 | camera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); 438 | 439 | // draw subgraph after main camera view. 440 | camera->setRenderOrder(osg::Camera::POST_RENDER); 441 | 442 | // we don't want the camera to grab event focus from the viewers main camera(s). 443 | camera->setAllowEventFocus(false); 444 | 445 | { // Add geode and drawable with BaseClass display 446 | // create geode to contain hud drawables 447 | osg::Geode* geode = new osg::Geode; 448 | camera->addChild(geode); 449 | auto _hudOrigin = osg::Vec2(-100, -100); 450 | auto _hudSize = osg::Vec2(200, 200); 451 | // finally create and attach hud geometry 452 | osg::Geometry* geometry = osg::createTexturedQuadGeometry(osg::Vec3(_hudOrigin[0], _hudOrigin[1], 0), 453 | osg::Vec3(_hudSize[0], 0, 0), 454 | osg::Vec3(0, _hudSize[1], 0)); 455 | 456 | osg::StateSet* stateset = geometry->getOrCreateStateSet(); 457 | stateset->setTextureAttribute(0, _texture, osg::StateAttribute::ON); 458 | stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF); 459 | osgEarth::VirtualProgram* vp = osgEarth::VirtualProgram::getOrCreate(stateset); 460 | osgEarth::ShaderPackage shaders; 461 | shaders.load(vp, "cube_to_quad.glsl", shaderDB); 462 | 463 | // ss->setTextureAttributeAndModes(0, inputMap, osg::StateAttribute::ON); 464 | stateset->getOrCreateUniform("IrradianceMap", osg::Uniform::SAMPLER_CUBE)->set(0); 465 | stateset->getOrCreateUniform("mipLevel", osg::Uniform::FLOAT)->set(0 * 1.0f); 466 | 467 | geode->addDrawable(geometry); 468 | } 469 | return camera; 470 | } 471 | osg::Group* setupCamera(osg::Node* reflectedSubgraph, osg::Texture* texture) 472 | { 473 | auto clearColor = osg::Vec4(0, 0, 0, 0); 474 | 475 | unsigned int tex_width, tex_height; 476 | tex_width = tex_height = 256; 477 | typedef std::pair ImageData; 478 | const ImageData id[] = 479 | { 480 | ImageData(osg::Vec3(1, 0, 0), osg::Vec3(0, -1, 0)), // +X 481 | ImageData(osg::Vec3(-1, 0, 0), osg::Vec3(0, -1, 0)), // -X 482 | ImageData(osg::Vec3(0, 1, 0), osg::Vec3(0, 0, 1)), // +Y 483 | ImageData(osg::Vec3(0, -1, 0), osg::Vec3(0, 0, -1)), // -Y 484 | ImageData(osg::Vec3(0, 0, 1), osg::Vec3(0, -1, 0)), // +Z 485 | ImageData(osg::Vec3(0, 0, -1), osg::Vec3(0, -1, 0)) // -Z 486 | }; 487 | osg::Group* cameras = new osg::Group(); 488 | for (unsigned int i = 0; i < 6; ++i) 489 | { 490 | // create the camera 491 | osg::Camera* camera = new osg::Camera; 492 | 493 | camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 494 | camera->setClearColor(clearColor); 495 | 496 | // set viewport 497 | camera->setViewport(0, 0, tex_width, tex_height); 498 | 499 | // set the camera to render before the main camera. 500 | camera->setRenderOrder(osg::Camera::PRE_RENDER); 501 | camera->setComputeNearFarMode(osg::CullSettings::COMPUTE_NEAR_FAR_USING_PRIMITIVES); 502 | 503 | // tell the camera to use OpenGL frame buffer object where supported. 504 | camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT); 505 | camera->setImplicitBufferAttachmentMask(0, 0); 506 | camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF); 507 | // attach the texture and use it as the color buffer. 508 | camera->attach(osg::Camera::COLOR_BUFFER, texture, 0, i); 509 | 510 | osg::Matrix viewMat; 511 | osg::Vec3d position(1.0, 6.0, 0.0); 512 | viewMat.makeLookAt(position, position + id[i].first, id[i].second); 513 | 514 | // add subgraph to render 515 | camera->addChild(reflectedSubgraph); 516 | double size = 5.0; 517 | // camera->setProjectionMatrixAsOrtho2D(-size, size, -size, size); 518 | camera->setProjectionMatrixAsFrustum(-1.0, 1.0, -1.0, 1.0, 1.0, 10.0); 519 | camera->setViewMatrix(viewMat); 520 | 521 | if (i == 0) 522 | { 523 | osg::Matrix debug_mvp = camera->getViewMatrix() * camera->getProjectionMatrix(); 524 | osgShadow::ConvexPolyhedron frustum; 525 | frustum.setToUnitFrustum(); 526 | frustum.transform(osg::Matrix::inverse(debug_mvp), debug_mvp); 527 | osg::Geometry* geom = frustum.buildGeometry(osg::Vec4(0.0, 1.0, 0.0, 1.0), osg::Vec4(0.0, 0.0, 1.0, 0.0)); 528 | osg::Geode* geode = new osg::Geode(); 529 | geode->addDrawable(geom); 530 | cameras->addChild(geode); 531 | } 532 | 533 | cameras->addChild(camera); 534 | } 535 | return cameras; 536 | } 537 | -------------------------------------------------------------------------------- /OE_PBR/CubeToQuad.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fang1067720863/osgPBR/dba01b6cbc42c0ccb2e0611fcad1c04e27288f15/OE_PBR/CubeToQuad.h -------------------------------------------------------------------------------- /OE_PBR/EnvLight.cpp: -------------------------------------------------------------------------------- 1 | #include "EnvLight.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #include"PbrMaterial.h" 13 | #include"AdvancedMaterial.h" 14 | 15 | 16 | 17 | osg::ref_ptr& EnvLightEffect::instance() 18 | { 19 | static osg::ref_ptr s_registry = new EnvLightEffect(); 20 | /* if (erase) 21 | { 22 | s_registry->destruct(); 23 | s_registry = 0; 24 | }*/ 25 | return s_registry; // will return NULL on erase 26 | } 27 | 28 | EnvLightEffect::EnvLightEffect() 29 | { 30 | 31 | } 32 | 33 | EnvLightEffect::EnvLightEffect(const std::string& envCubeFile) : _enable(false), _texturesReady(false) 34 | { 35 | 36 | } 37 | 38 | void EnvLightEffect::setEnable(bool enable) 39 | { 40 | _enable = enable; 41 | if (enable && !_texturesReady) _ResetEnvMapAtlas(); 42 | _lightIntensity = 0.5; 43 | } 44 | 45 | void EnvLightEffect::setEnvMapAtlas(const EnvMapConfig& config, osgDB::Options* opts) 46 | { 47 | _config = config; 48 | if (opts != nullptr) 49 | { 50 | _options = opts; 51 | } 52 | 53 | _ResetEnvMapAtlas(); 54 | } 55 | 56 | void EnvLightEffect::_ResetEnvMapAtlas() 57 | { 58 | 59 | auto readOption = _options; 60 | 61 | auto prefilterMapPath = _config._specularMap; 62 | prefilterMap = new osg::Texture2D(); 63 | auto prefilterMapImage = osgDB::readRefImageFile(prefilterMapPath, readOption); 64 | if (!prefilterMapImage.valid()) 65 | { 66 | return; 67 | } 68 | osg::Texture2D* prefilterMap2D = dynamic_cast(prefilterMap.get()); 69 | 70 | std::cout << "miplevel" << prefilterMapImage->getNumMipmapLevels() << std::endl; 71 | _maxReflectionLOD = prefilterMapImage->getNumMipmapLevels(); 72 | 73 | prefilterMap2D->setNumMipmapLevels(_maxReflectionLOD); 74 | prefilterMap2D->setImage(0,prefilterMapImage.get()); 75 | prefilterMap2D->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE); 76 | prefilterMap2D->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE); 77 | prefilterMap2D->setFilter(osg::Texture::MIN_FILTER, osg::Texture::NEAREST_MIPMAP_LINEAR); 78 | prefilterMap2D->setFilter(osg::Texture::MAG_FILTER, osg::Texture::NEAREST_MIPMAP_LINEAR); 79 | prefilterMap2D->setMaxAnisotropy(4.0); 80 | prefilterMap2D->allocateMipmapLevels(); 81 | prefilterMap2D->setUseHardwareMipMapGeneration(false); 82 | prefilterMap = prefilterMap2D; 83 | 84 | 85 | auto envCubeMapPath = _config._envMap; 86 | envCubeMap = new osg::Texture2D(); 87 | auto envCubeMapImage = osgDB::readRefImageFile(envCubeMapPath, readOption); 88 | osg::Texture2D* envCubeMap2D = dynamic_cast(envCubeMap.get()); 89 | envCubeMap2D->setImage(0, prefilterMapImage.get()); 90 | envCubeMap2D->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE); 91 | envCubeMap2D->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE); 92 | envCubeMap2D->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR); 93 | envCubeMap2D->setFilter(osg::Texture::MAG_FILTER, osg::Texture::NEAREST_MIPMAP_LINEAR); 94 | envCubeMap2D->setMaxAnisotropy(4.0); 95 | envCubeMap2D->allocateMipmapLevels(); 96 | envCubeMap2D->setUseHardwareMipMapGeneration(true); 97 | envCubeMap = envCubeMap2D; 98 | 99 | auto irridianceMapPath = _config._diffuseMap; 100 | irridianceMap = new osg::Texture2D(); 101 | auto irridianceMapImage = osgDB::readRefImageFile(irridianceMapPath, readOption); 102 | osg::Texture2D* irridianceMap2D = dynamic_cast(irridianceMap.get()); 103 | irridianceMap2D->setImage(irridianceMapImage.get()); 104 | irridianceMap2D->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE); 105 | irridianceMap2D->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE); 106 | irridianceMap2D->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR); 107 | irridianceMap2D->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); 108 | irridianceMap = irridianceMap2D; 109 | 110 | auto brdfLUTPath = "brdfLUT.png"; 111 | auto brdfImage = osgDB::readRefImageFile(brdfLUTPath, readOption); 112 | 113 | brdfLUTMap = new osg::Texture2D(); 114 | brdfLUTMap->setImage(brdfImage.get()); 115 | brdfLUTMap->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE); 116 | brdfLUTMap->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE); 117 | 118 | brdfLUTMap->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR); 119 | brdfLUTMap->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); 120 | brdfLUTMap->setNumMipmapLevels(1); 121 | 122 | if (!replaceCallbacks.empty()) 123 | { 124 | for (auto& cb : replaceCallbacks) 125 | { 126 | cb(); 127 | } 128 | } 129 | 130 | } 131 | 132 | EnvLightGL3UniformGenerator::EnvLightGL3UniformGenerator(): 133 | _statesetsMutex("EnvLightGL3UniformGenerator(OE)") 134 | { 135 | } 136 | 137 | bool EnvLightGL3UniformGenerator::run(osg::Object* obj, osg::Object* data) 138 | { 139 | EnvLightSource* lightSource = dynamic_cast(obj); 140 | osgUtil::CullVisitor* cv = dynamic_cast(data); 141 | 142 | if (cv && lightSource ) 143 | { 144 | auto envLight = lightSource->getEnvLightEffect()->instance(); 145 | 146 | osg::StateSet* ss = cv->getCurrentRenderStage()->getStateSet(); 147 | if (ss == 0L) 148 | { 149 | cv->getCurrentRenderStage()->setStateSet(ss = new osg::StateSet()); 150 | 151 | Threading::ScopedMutexLock lock(_statesetsMutex); 152 | _statesets.push_back(ss); 153 | } 154 | auto material = ss->getAttribute(osg::StateAttribute::MATERIAL); 155 | if (dynamic_cast(material)) 156 | { 157 | auto useCubeUV = envLight->useCubeUV() ? osg::StateAttribute::ON : osg::StateAttribute::OFF; 158 | ss->setDefine("USE_ENV_MAP"); 159 | 160 | auto uniformType = envLight->useCubeUV() ? osg::Uniform::SAMPLER_CUBE : osg::Uniform::SAMPLER_2D; 161 | ss->setDefine("USE_ENV_CUBE_UV", useCubeUV); 162 | 163 | ss->getOrCreateUniform("envLightIntensity", osg::Uniform::FLOAT)->set(envLight->lightIntensity()); 164 | ss->getOrCreateUniform("MAX_REFLECTION_LOD", osg::Uniform::FLOAT)->set(envLight->maxReflectionLOD()); 165 | 166 | 167 | 168 | int unit = 5; 169 | osg::Texture* diffuseEnvMap = envLight->getIrridianceMap(); 170 | ss->setTextureAttributeAndModes(unit, diffuseEnvMap, osg::StateAttribute::ON); 171 | ss->getOrCreateUniform("irradianceMap", uniformType)->set(unit++); 172 | 173 | osg::Texture* specularEnvMap = envLight->getPrefilterMap(); 174 | ss->setTextureAttributeAndModes(unit, specularEnvMap, osg::StateAttribute::ON); 175 | ss->getOrCreateUniform("prefilterMap", osg::Uniform::SAMPLER_2D)->set(unit++); 176 | 177 | 178 | osg::Texture* brdfLUTMap = envLight->getBrdfLUTMap(); 179 | ss->setTextureAttributeAndModes(unit, brdfLUTMap, osg::StateAttribute::ON); 180 | ss->getOrCreateUniform("brdfLUT", osg::Uniform::SAMPLER_2D)->set(unit++); 181 | } 182 | 183 | 184 | 185 | } 186 | return traverse(obj, data); 187 | 188 | } 189 | 190 | void EnvLightGL3UniformGenerator::resizeGLBufferObjects(unsigned maxSize) 191 | { 192 | Threading::ScopedMutexLock lock(_statesetsMutex); 193 | for (unsigned i = 0; i < _statesets.size(); ++i) 194 | _statesets[i]->resizeGLObjectBuffers(maxSize); 195 | } 196 | 197 | void EnvLightGL3UniformGenerator::releaseGLObjects(osg::State* state) const 198 | { 199 | Threading::ScopedMutexLock lock(_statesetsMutex); 200 | for (unsigned i = 0; i < _statesets.size(); ++i) 201 | _statesets[i]->releaseGLObjects(state); 202 | _statesets.clear(); 203 | } 204 | 205 | osg::ref_ptr& EnvLightSource::getEnvLightEffect() 206 | { 207 | 208 | static osg::ref_ptr s_registry = new EnvLightEffect(); 209 | /* if (erase) 210 | { 211 | s_registry->destruct(); 212 | s_registry = 0; 213 | }*/ 214 | return s_registry; // will return NULL on erase 215 | 216 | } 217 | 218 | EnvLightSource::~EnvLightSource() 219 | { 220 | } 221 | 222 | GenerateEnvLightUniforms::GenerateEnvLightUniforms():osg::NodeVisitor(TRAVERSE_ALL_CHILDREN) 223 | { 224 | setNodeMaskOverride(~0); 225 | } 226 | 227 | void GenerateEnvLightUniforms::apply(osg::Node& node) 228 | { 229 | osg::StateSet* ss = node.getStateSet(); 230 | if (ss) 231 | { 232 | if (_statesets.find(ss) == _statesets.end()) 233 | { 234 | const osg::StateSet::RefAttributePair* rap = ss->getAttributePair(osg::StateAttribute::MATERIAL); 235 | if (rap) 236 | { 237 | osgEarth::StandardPBRMaterial* material = dynamic_cast(rap->first.get()); 238 | auto envCB = new EnvLightGL3UniformCallback(); 239 | if (material) 240 | { 241 | if (material->getUpdateCallback()) 242 | { 243 | if (auto aMat = dynamic_cast(material)) 244 | { 245 | aMat->addUpdateCallback("env", envCB); 246 | } 247 | else { 248 | 249 | } 250 | 251 | } 252 | else { 253 | material->setUpdateCallback(envCB); 254 | } 255 | 256 | } 257 | 258 | // mark this stateset as visited. 259 | _statesets.insert(ss); 260 | } 261 | } 262 | } 263 | traverse(node); 264 | } 265 | 266 | void EnvLightGL3UniformCallback::operator()(osg::StateAttribute* attr, osg::NodeVisitor* nv) 267 | { 268 | for (unsigned int i = 0; i < attr->getNumParents(); i++) 269 | { 270 | osg::StateSet* ss = attr->getParent(i); 271 | 272 | auto envLight = EnvLightEffect::instance(); 273 | 274 | 275 | auto useCubeUV = envLight->useCubeUV() ? osg::StateAttribute::ON : osg::StateAttribute::OFF; 276 | ss->setDefine("USE_ENV_MAP"); 277 | 278 | auto uniformType = envLight->useCubeUV() ? osg::Uniform::SAMPLER_CUBE : osg::Uniform::SAMPLER_2D; 279 | ss->setDefine("USE_ENV_CUBE_UV", useCubeUV); 280 | 281 | ss->getOrCreateUniform("envLightIntensity", osg::Uniform::FLOAT)->set(envLight->lightIntensity()); 282 | ss->getOrCreateUniform("MAX_REFLECTION_LOD", osg::Uniform::FLOAT)->set(envLight->maxReflectionLOD()); 283 | 284 | 285 | 286 | int unit = 5; 287 | osg::Texture* diffuseEnvMap = envLight->getIrridianceMap(); 288 | ss->setTextureAttributeAndModes(unit, diffuseEnvMap, osg::StateAttribute::ON); 289 | ss->getOrCreateUniform("irradianceMap", uniformType)->set(unit++); 290 | 291 | osg::Texture* specularEnvMap = envLight->getPrefilterMap(); 292 | ss->setTextureAttributeAndModes(unit, specularEnvMap, osg::StateAttribute::ON); 293 | ss->getOrCreateUniform("prefilterMap", osg::Uniform::SAMPLER_2D)->set(unit++); 294 | 295 | 296 | osg::Texture* brdfLUTMap = envLight->getBrdfLUTMap(); 297 | ss->setTextureAttributeAndModes(unit, brdfLUTMap, osg::StateAttribute::ON); 298 | ss->getOrCreateUniform("brdfLUT", osg::Uniform::SAMPLER_2D)->set(unit++); 299 | } 300 | 301 | } 302 | -------------------------------------------------------------------------------- /OE_PBR/EnvLight.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // author:1067720863@qq.com 4 | // create date:2023/04 5 | // decription: Cook_BRDF Light 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "Export.h" 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include 33 | #include 34 | 35 | using namespace osgEarth; 36 | 37 | class EnvLightEffect; 38 | class EnvLightSource : public osg::Group 39 | { 40 | public: 41 | EnvLightSource() {} 42 | 43 | /** Copy constructor using CopyOp to manage deep vs shallow copy. */ 44 | EnvLightSource(const EnvLightSource& ls, 45 | const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY) 46 | : Group(ls, copyop) 47 | { 48 | } 49 | 50 | META_Node(osg, EnvLightSource); 51 | 52 | static osg::ref_ptr& getEnvLightEffect(); 53 | enum ReferenceFrame 54 | { 55 | RELATIVE_RF, 56 | ABSOLUTE_RF 57 | }; 58 | 59 | protected: 60 | virtual ~EnvLightSource(); 61 | }; 62 | class GenerateEnvLightUniforms : public osg::NodeVisitor 63 | { 64 | public: 65 | GenerateEnvLightUniforms(); 66 | 67 | public: // osg::NodeVisitor 68 | virtual void apply(osg::Node& node); 69 | /*virtual void apply(osg::LightSource& node);*/ 70 | 71 | protected: 72 | std::set _statesets; 73 | 74 | template bool alreadyInstalled(osg::Callback* cb) const { 75 | return !cb ? false : dynamic_cast(cb) != 0L ? true : alreadyInstalled(cb->getNestedCallback()); 76 | } 77 | }; 78 | class EnvLightGL3UniformGenerator : public osg::NodeCallback 79 | { 80 | public: 81 | EnvLightGL3UniformGenerator(); 82 | 83 | public: 84 | bool run(osg::Object* obj, osg::Object* data); 85 | 86 | public: // osg::Object 87 | void resizeGLBufferObjects(unsigned maxSize); 88 | void releaseGLObjects(osg::State* state) const; 89 | 90 | mutable std::vector > _statesets; 91 | mutable Threading::Mutex _statesetsMutex; 92 | }; 93 | 94 | class EnvLightEffect : public osg::Object 95 | { 96 | friend class EnvLightSource; 97 | friend class EnvLightGL3UniformGenerator; 98 | friend class EnvLightGL3UniformCallback; 99 | 100 | struct EnvMapConfig 101 | { 102 | std::string _diffuseMap; 103 | std::string _specularMap; 104 | std::string _envMap; 105 | }; 106 | using Functor = std::function; 107 | 108 | public: 109 | META_Object(osgEarth, EnvLightEffect) 110 | 111 | static osg::ref_ptr& instance(); 112 | osg::Texture* getEnvCubeMap() { return _enable ? envCubeMap.get() : nullptr; } 113 | 114 | bool enabled() const { return _enable; } 115 | bool useCubeUV() const { return _useCubeUV; } 116 | float lightIntensity() const { return _lightIntensity; } 117 | float maxReflectionLOD() const { return _maxReflectionLOD; } 118 | void setEnable(bool enable); 119 | void setLightIntensity(float i) { _lightIntensity = i; } 120 | void setEnvMapAtlas(const EnvMapConfig& config, osgDB::Options* opts = nullptr); 121 | void addReplaceCallback(Functor&& f) { replaceCallbacks.push_back(std::move(f)); } 122 | 123 | protected: 124 | EnvLightEffect(); 125 | EnvLightEffect(const std::string& envCubeFile); 126 | void _ResetEnvMapAtlas(); 127 | 128 | osg::Texture* getIrridianceMap() { return _enable ? irridianceMap.get() : nullptr; } 129 | osg::Texture* getPrefilterMap() { return _enable ? prefilterMap.get() : nullptr; } 130 | osg::Texture* getBrdfLUTMap() { return _enable ? brdfLUTMap.get() : nullptr; } 131 | 132 | private: 133 | EnvLightEffect(const EnvLightEffect& rhs, const osg::CopyOp& copyop = osg::CopyOp::DEEP_COPY_ALL) {} 134 | bool _enable; 135 | bool _texturesReady; 136 | bool _useCubeUV{false}; 137 | osg::ref_ptr envCubeMap; 138 | osg::ref_ptr irridianceMap; 139 | osg::ref_ptr prefilterMap; 140 | osg::ref_ptr brdfLUTMap; 141 | osg::ref_ptr _options{0}; 142 | 143 | EnvMapConfig _config; 144 | float _lightIntensity{0.0f}; 145 | float _maxReflectionLOD{1.0f}; 146 | std::vector replaceCallbacks; 147 | }; 148 | 149 | class OE_MATERIAL_PULGIN EnvLightGL3UniformCallback : public osg::StateAttributeCallback 150 | { 151 | public: 152 | virtual void operator()(osg::StateAttribute* attr, osg::NodeVisitor* nv); 153 | }; -------------------------------------------------------------------------------- /OE_PBR/Export.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | 4 | #if defined(_MSC_VER) || defined(__CYGWIN__) || defined(__MINGW32__) || defined( __BCPLUSPLUS__) || defined( __MWERKS__) 5 | # if defined( OE_MATERIAL_STATIC ) 6 | # define OSG_EXPORT 7 | # elif defined( OE_MATERIAL_LIBRARY ) 8 | # define OE_MATERIAL_PULGIN __declspec(dllexport) 9 | # else 10 | # define OE_MATERIAL_PULGIN __declspec(dllimport) 11 | # endif 12 | #else 13 | # define OSG_EXPORT 14 | #endif 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /OE_PBR/IBLBaker.cpp: -------------------------------------------------------------------------------- 1 | #include"IBLBaker.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | //#include"SnapImage.h" 13 | //#include"ddsNew.h" 14 | 15 | using namespace osgEarth; 16 | 17 | // 18 | 19 | void IBLTechnique::startUp() 20 | { 21 | createTextures(); 22 | 23 | 24 | auto shaderPath = "..//..//OE_PBR//Shader"; 25 | auto shaderPath2 = "..//OE_PBR//Shader"; 26 | 27 | _dbo = new osgDB::Options(); 28 | if (osgDB::fileExists(osgEarth::getAbsolutePath(shaderPath))) 29 | { 30 | _dbo->setDatabasePath(osgEarth::getAbsolutePath(shaderPath)); 31 | } 32 | else { 33 | _dbo->setDatabasePath(osgEarth::getAbsolutePath(shaderPath2)); 34 | } 35 | 36 | //createHDRCubePass(); 37 | /* createIrridiancePass();*/ 38 | // createRadianceQuadPass(); 39 | // createBrdfLUTPass(); 40 | //createIrridianceQuadPass(); 41 | 42 | IrridianceBoxToQuad(); 43 | //createLightPass(); 44 | } 45 | 46 | void IBLTechnique::createLightPass() 47 | { 48 | //osg::ref_ptr box = createHDRBox(); 49 | 50 | 51 | 52 | 53 | //const char* pick_preview = R"( 54 | // 55 | 56 | // #pragma vp_function vs, vertex_model 57 | // out vec3 WorldPos; 58 | // void vs(inout vec4 vertex) { 59 | // WorldPos = normalize(vertex.xyz); 60 | // } 61 | // [break] 62 | 63 | // #pragma vp_function fs, fragment_output 64 | // in vec3 WorldPos; 65 | // out vec4 frag; 66 | // uniform samplerCube tex; 67 | // void fs(inout vec4 c) { 68 | // c = texture(tex, normalize(WorldPos)); 69 | // frag = c; 70 | // } 71 | //)"; 72 | //VirtualProgram* vp = VirtualProgram::getOrCreate(box->getOrCreateStateSet()); 73 | //ShaderLoader::load(vp, pick_preview); 74 | 75 | //box->getOrCreateStateSet()->setTextureAttributeAndModes(0, prefilterMap.get(), osg::StateAttribute::ON); 76 | //box->getOrCreateStateSet()->getOrCreateUniform("environmentMap", osg::Uniform::SAMPLER_CUBE)->set(0); 77 | 78 | //root->addChild(box); 79 | 80 | // root->addChild(createQuadGeom().get()); 81 | 82 | } 83 | void IBLTechnique::createIrridiancePass() 84 | { 85 | 86 | // input: env_cubeMap output:irridianceCubeMap 87 | osg::ref_ptr box = createHDRBox(); 88 | VirtualProgram* vp = VirtualProgram::getOrCreate(box->getOrCreateStateSet()); 89 | box->getOrCreateStateSet()->setTextureAttributeAndModes(0, envCubeMap.get(), osg::StateAttribute::ON); 90 | box->getOrCreateStateSet()->getOrCreateUniform("environmentMap", osg::Uniform::SAMPLER_2D)->set(0); 91 | const char* pick_preview = R"( 92 | 93 | 94 | #pragma vp_function vs, vertex_model 95 | out vec3 WorldPos; 96 | void vs(inout vec4 vertex) { 97 | WorldPos = normalize(vertex.xyz); 98 | } 99 | [break] 100 | 101 | #pragma vp_function fs, fragment_output 102 | in vec3 WorldPos; 103 | out vec4 FragColor; 104 | #define PI 3.14159265359f 105 | uniform samplerCube environmentMap; 106 | void fs(inout vec4 c) { 107 | vec3 N = normalize(WorldPos); 108 | 109 | vec3 irradiance = vec3(0.0); 110 | 111 | // tangent space calculation from origin point 112 | vec3 up = vec3(0.0, 1.0, 0.0); 113 | vec3 right = normalize(cross(up, N)); 114 | up = normalize(cross(N, right)); 115 | 116 | float sampleDelta = 0.025; 117 | float nrSamples = 0.0f; 118 | for(float phi = 0.0; phi < 2.0 * PI; phi += sampleDelta) 119 | { 120 | for(float theta = 0.0; theta < 0.5 * PI; theta += sampleDelta) 121 | { 122 | // spherical to cartesian (in tangent space) 123 | vec3 tangentSample = vec3(sin(theta) * cos(phi), sin(theta) * sin(phi), cos(theta)); 124 | // tangent space to world 125 | vec3 sampleVec = tangentSample.x * right + tangentSample.y * up + tangentSample.z * N; 126 | 127 | irradiance += texture(environmentMap, sampleVec).rgb * cos(theta) * sin(theta); 128 | nrSamples++; 129 | } 130 | } 131 | irradiance = PI * irradiance * (1.0 / float(nrSamples)); 132 | 133 | FragColor = vec4(irradiance, 1.0); 134 | } 135 | )"; 136 | 137 | ShaderLoader::load(vp, pick_preview); 138 | osg::Node* cameras = createSlaveCameras(box.get(), irridianceMap.get()); 139 | root->addChild(cameras); 140 | } 141 | 142 | 143 | std::string read_raw_source(osgDB::Options* dbOptions, const std::string& filename) 144 | { 145 | URIContext context(dbOptions); 146 | URI uri(filename, context); 147 | 148 | // searches OSG_FILE_PATH 149 | std::string path = osgDB::findDataFile(uri.full(), dbOptions); 150 | if (!path.empty()) 151 | { 152 | std::string externalSource = URI(path, context).getString(dbOptions); 153 | return externalSource; 154 | /* if (!externalSource.empty()) 155 | { 156 | OE_DEBUG << LC << "Loaded external shader " << filename << " from " << path << "\n"; 157 | output = externalSource; 158 | }*/ 159 | } 160 | } 161 | void IBLTechnique::createPrefilterPass() 162 | { 163 | 164 | // input: env_cubeMap output:PrefilterCubeMap 165 | osg::ref_ptr box = createHDRBox(); 166 | VirtualProgram* vp = VirtualProgram::getOrCreate(box->getOrCreateStateSet()); 167 | box->getOrCreateStateSet()->setTextureAttributeAndModes(0, envCubeMap.get(), osg::StateAttribute::ON); 168 | box->getOrCreateStateSet()->getOrCreateUniform("environmentMap", osg::Uniform::SAMPLER_CUBE)->set(0); 169 | 170 | auto shaderPath = "..//..//OE_PBR//Shader"; 171 | auto shaderPath2 = "..//OE_PBR//Shader"; 172 | 173 | osg::ref_ptr dbo = new osgDB::Options(); 174 | 175 | 176 | if (osgDB::fileExists(osgEarth::getAbsolutePath(shaderPath))) 177 | { 178 | dbo->setDatabasePath(osgEarth::getAbsolutePath(shaderPath)); 179 | } 180 | else { 181 | dbo->setDatabasePath(osgEarth::getAbsolutePath(shaderPath2)); 182 | } 183 | 184 | ShaderPackage shaders; 185 | shaders.load(vp, "IBLPrefilterMap.glsl", dbo); 186 | 187 | 188 | uint32_t maxMipLevels = 3; 189 | for (unsigned int mip = 0; mip < maxMipLevels; ++mip) 190 | { 191 | 192 | unsigned int mipWidth = 128 * std::pow(0.5, mip); 193 | unsigned int mipHeight = 128 * std::pow(0.5, mip); 194 | float roughness = (float)mip / (float)(maxMipLevels - 1); 195 | 196 | box->getOrCreateStateSet()->getOrCreateUniform("roughness", osg::Uniform::FLOAT)->set(roughness); 197 | osg::Node* cameras = createSlaveCameras(box.get(), prefilterMap.get(), mip, mipWidth, mipHeight, true); 198 | root->addChild(cameras); 199 | } 200 | } 201 | osg::ref_ptr createQuad() 202 | { 203 | osg::ref_ptr geode = new osg::Geode(); 204 | 205 | osg::ShapeDrawable* sd = new osg::ShapeDrawable(new osg::Box(osg::Vec3(0.0, 0.0, 0.0), 512.0)); 206 | 207 | geode->addDrawable(sd); 208 | return geode; 209 | } 210 | void IBLTechnique::createBrdfLUTPass() 211 | { 212 | 213 | osg::ref_ptr box = createQuad(); 214 | VirtualProgram* vp = VirtualProgram::getOrCreate(box->getOrCreateStateSet()); 215 | 216 | auto shaderPath = "..//..//OE_PBR//Shader"; 217 | auto shaderPath2 = "..//OE_PBR//Shader"; 218 | 219 | osg::ref_ptr dbo = new osgDB::Options(); 220 | 221 | 222 | if (osgDB::fileExists(osgEarth::getAbsolutePath(shaderPath))) 223 | { 224 | dbo->setDatabasePath(osgEarth::getAbsolutePath(shaderPath)); 225 | } 226 | else { 227 | dbo->setDatabasePath(osgEarth::getAbsolutePath(shaderPath2)); 228 | } 229 | 230 | 231 | 232 | 233 | 234 | ShaderPackage shaders; 235 | shaders.load(vp, "IBLbrdfLUT.glsl", dbo); 236 | int w, h; 237 | w = h = 512; 238 | osg::ref_ptr cam = new osg::Camera(); 239 | cam->addChild(box); 240 | cam->setReferenceFrame(osg::Camera::ABSOLUTE_RF); 241 | cam->setClearColor(osg::Vec4(0, 0, 1, 1)); 242 | cam->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 243 | cam->setViewport(0, 0, w, h); 244 | cam->setRenderOrder(osg::Camera::PRE_RENDER); 245 | cam->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT); 246 | cam->setImplicitBufferAttachmentMask(0, 0); 247 | 248 | //osg::Image* image = new osg::Image; 249 | //image->allocateImage(w, h, 1, GL_RGBA, GL_FLOAT); 250 | 251 | 252 | cam->attach(osg::Camera::COLOR_BUFFER, brdfLUTMap.get(), 0); 253 | cam->setProjectionMatrixAsOrtho2D(-1.0 * w / 2, (-1.0 * w / 2) + w * 1.0, -1.0 * h / 2, (-1.0 * h / 2) + h * 1.0); 254 | //cam->setViewMatrixAsLookAt(osg::Vec3(0.0, 0.0, 0.0), osg::Vec3(1.0, 0.0, 0.0), osg::Vec3(0.0, -1.0, 0.0)); 255 | cam->setViewMatrix( 256 | osg::Matrixd::identity()); 257 | 258 | 259 | 260 | //{ 261 | // osg::Image* image = new osg::Image; 262 | // //image->allocateImage(tex_width, tex_height, 1, GL_RGBA, GL_UNSIGNED_BYTE); 263 | // image->allocateImage(w, h, 1, GL_RGBA, GL_UNSIGNED_SHORT); 264 | 265 | // // attach the image so its copied on each frame. 266 | // cam->attach(osg::Camera::COLOR_BUFFER, image, 0); 267 | 268 | // // Rather than attach the texture directly to illustrate the texture's ability to 269 | // // detect an image update and to subload the image onto the texture. You needn't 270 | // // do this when using an Image for copying to, as a separate camera->attach(..) 271 | // // would suffice as well, but we'll do it the long way round here just for demonstration 272 | // // purposes (long way round meaning we'll need to copy image to main memory, then 273 | // // copy it back to the graphics card to the texture in one frame). 274 | // // The long way round allows us to manually modify the copied image via the callback 275 | // // and then let this modified image by reloaded back. 276 | // brdfLUTMap->setImage(0, image); 277 | // auto snap = new SnapImage("brdfLUT.png", image, brdfLUTMap); 278 | // cam->setPostDrawCallback(snap); 279 | // viewer->addEventHandler(new SnapeImageHandler('p', snap)); 280 | //} 281 | 282 | 283 | root->addChild(cam); 284 | 285 | } 286 | 287 | void IBLTechnique::createHDRCubePass(osg::Texture* envCubeMap) 288 | { 289 | 290 | 291 | osg::ref_ptr box = createHDRBox(); 292 | VirtualProgram* vp = VirtualProgram::getOrCreate(box->getOrCreateStateSet()); 293 | box->getOrCreateStateSet()->setTextureAttributeAndModes(0, hdrMap.get(), osg::StateAttribute::ON); 294 | const char* pick_preview = R"( 295 | 296 | 297 | #pragma vp_function SampleSphericalMap, vertex_model 298 | const vec2 invAtan = vec2(0.1591, 0.3183); 299 | out vec2 spherical_uv; 300 | void SampleSphericalMap(inout vec4 vertex) { 301 | vec3 tmp = normalize(vertex.xyz); 302 | 303 | vec2 uv = vec2(atan(tmp.z, tmp.x), asin(tmp.y)); 304 | uv *= invAtan; 305 | uv += 0.5; 306 | spherical_uv = uv; 307 | } 308 | 309 | [break] 310 | 311 | #pragma vp_function fs, fragment_output 312 | in vec2 spherical_uv; 313 | out vec4 frag; 314 | uniform sampler2D tex; 315 | void fs(inout vec4 c) { 316 | c = texture(tex, spherical_uv); 317 | frag = c; 318 | } 319 | )"; 320 | 321 | ShaderLoader::load(vp, pick_preview); 322 | osg::Node* cameras = createSlaveCameras(box.get(), envCubeMap); 323 | root->addChild(cameras); 324 | } 325 | 326 | osg::Node* IBLTechnique::createSlaveCameras(osg::Node* box, osg::Texture* tex, unsigned int level, unsigned int w, unsigned int h, bool generateMipmap) 327 | { 328 | osg::Group* cameras = new osg::Group(); 329 | 330 | { 331 | osg::ref_ptr cam = new osg::Camera(); 332 | cam->addChild(box); 333 | cam->setReferenceFrame(osg::Camera::ABSOLUTE_RF); 334 | cam->setClearColor(osg::Vec4(0, 0, 1, 1)); 335 | cam->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 336 | cam->setViewport(0, 0, w, h); 337 | cam->setRenderOrder(osg::Camera::PRE_RENDER); 338 | cam->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT); 339 | cam->setImplicitBufferAttachmentMask(0, 0); 340 | cam->attach(osg::Camera::COLOR_BUFFER, tex, level, osg::TextureCubeMap::POSITIVE_X, generateMipmap); 341 | cam->setProjectionMatrixAsOrtho2D(-1.0 * w / 2, (-1.0 * w / 2) + w * 1.0, -1.0 * h / 2, (-1.0 * h / 2) + h * 1.0); 342 | //cam->setViewMatrixAsLookAt(osg::Vec3(0.0, 0.0, 0.0), osg::Vec3(1.0, 0.0, 0.0), osg::Vec3(0.0, -1.0, 0.0)); 343 | cam->setViewMatrix( 344 | osg::Matrixd::rotate(osg::inDegrees(90.0f), 0.0, 1.0, 0.0) * osg::Matrixd::rotate(osg::inDegrees(90.0f), 0.0, 0.0, 1.0)); 345 | 346 | cameras->addChild(cam); 347 | } 348 | 349 | 350 | { 351 | osg::ref_ptr cam = new osg::Camera(); 352 | cam->addChild(box); 353 | cam->setReferenceFrame(osg::Camera::ABSOLUTE_RF); 354 | cam->setClearColor(osg::Vec4(0, 0, 1, 1)); 355 | cam->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 356 | cam->setViewport(0, 0, w, h); 357 | cam->setRenderOrder(osg::Camera::PRE_RENDER); 358 | cam->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT); 359 | cam->setImplicitBufferAttachmentMask(0, 0); 360 | cam->attach(osg::Camera::COLOR_BUFFER, tex, level, osg::TextureCubeMap::NEGATIVE_X, generateMipmap); 361 | cam->setProjectionMatrixAsOrtho2D(-1.0 * w / 2, (-1.0 * w / 2) + w * 1.0, -1.0 * h / 2, (-1.0 * h / 2) + h * 1.0); 362 | //cam->setViewMatrixAsLookAt(osg::Vec3(0.0, 0.0, 0.0), osg::Vec3(-1.0, 0.0, 0.0), osg::Vec3(0.0, -1.0, 0.0)); 363 | cam->setViewMatrix(osg::Matrixd::rotate(osg::inDegrees(-90.0f), 0.0, 1.0, 0.0) * osg::Matrixd::rotate(osg::inDegrees(-90.0f), 0.0, 0.0, 1.0)); 364 | 365 | cameras->addChild(cam); 366 | } 367 | { 368 | osg::ref_ptr cam = new osg::Camera(); 369 | cam->addChild(box); 370 | cam->setReferenceFrame(osg::Camera::ABSOLUTE_RF); 371 | cam->setClearColor(osg::Vec4(0, 0, 1, 1)); 372 | cam->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 373 | cam->setViewport(0, 0, w, h); 374 | cam->setRenderOrder(osg::Camera::PRE_RENDER); 375 | cam->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT); 376 | cam->setImplicitBufferAttachmentMask(0, 0); 377 | cam->attach(osg::Camera::COLOR_BUFFER, tex, level, osg::TextureCubeMap::POSITIVE_Y, generateMipmap); 378 | cam->setProjectionMatrixAsOrtho2D(-1.0 * w / 2, (-1.0 * w / 2) + w * 1.0, -1.0 * h / 2, (-1.0 * h / 2) + h * 1.0); 379 | //cam->setViewMatrixAsLookAt(osg::Vec3(0.0, 0.0, 0.0), osg::Vec3(0.0, 1.0, 0.0), osg::Vec3(0.0, 0.0, 1.0)); 380 | cam->setViewMatrix(osg::Matrixd()); 381 | cameras->addChild(cam); 382 | } 383 | { 384 | osg::ref_ptr cam = new osg::Camera(); 385 | cam->addChild(box); 386 | cam->setReferenceFrame(osg::Camera::ABSOLUTE_RF); 387 | cam->setClearColor(osg::Vec4(0, 0, 1, 1)); 388 | cam->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 389 | cam->setViewport(0, 0, w, h); 390 | cam->setRenderOrder(osg::Camera::PRE_RENDER); 391 | cam->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT); 392 | cam->setImplicitBufferAttachmentMask(0, 0); 393 | cam->attach(osg::Camera::COLOR_BUFFER, tex, level, osg::TextureCubeMap::NEGATIVE_Y, generateMipmap); 394 | cam->setProjectionMatrixAsOrtho2D(-1.0 * w / 2, (-1.0 * w / 2) + w * 1.0, -1.0 * h / 2, (-1.0 * h / 2) + h * 1.0); 395 | cam->setViewMatrixAsLookAt(osg::Vec3(0.0, 0.0, 0.0), osg::Vec3(0.0, -1.0, 0.0), osg::Vec3(0.0, -1.0, 0.0)); 396 | cam->setViewMatrix(osg::Matrixd::rotate(osg::inDegrees(180.0f), 1.0, 0.0, 0.0)); 397 | cameras->addChild(cam); 398 | } 399 | { 400 | osg::ref_ptr cam = new osg::Camera(); 401 | cam->addChild(box); 402 | cam->setReferenceFrame(osg::Camera::ABSOLUTE_RF); 403 | cam->setClearColor(osg::Vec4(0, 0, 1, 1)); 404 | cam->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 405 | cam->setViewport(0, 0, w, h); 406 | cam->setRenderOrder(osg::Camera::PRE_RENDER); 407 | cam->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT); 408 | cam->setImplicitBufferAttachmentMask(0, 0); 409 | cam->attach(osg::Camera::COLOR_BUFFER, tex, level, osg::TextureCubeMap::POSITIVE_Z, generateMipmap); 410 | cam->setProjectionMatrixAsOrtho2D(-1.0 * w / 2, (-1.0 * w / 2) + w * 1.0, -1.0 * h / 2, (-1.0 * h / 2) + h * 1.0); 411 | cam->setViewMatrix(osg::Matrixd::rotate(osg::inDegrees(-90.0f), 1.0, 0.0, 0.0)); 412 | //cam->setViewMatrixAsLookAt(osg::Vec3(0.0, 0.0, 0.0), osg::Vec3(0.0, 0.0, 1.0), osg::Vec3(0.0, -1.0, 0.0)); 413 | cameras->addChild(cam); 414 | } 415 | { 416 | osg::ref_ptr cam = new osg::Camera(); 417 | cam->addChild(box); 418 | cam->setReferenceFrame(osg::Camera::ABSOLUTE_RF); 419 | cam->setClearColor(osg::Vec4(0, 0, 1, 1)); 420 | cam->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 421 | cam->setViewport(0, 0, w, h); 422 | cam->setRenderOrder(osg::Camera::PRE_RENDER); 423 | cam->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT); 424 | cam->setImplicitBufferAttachmentMask(0, 0); 425 | cam->attach(osg::Camera::COLOR_BUFFER, tex, level, osg::TextureCubeMap::NEGATIVE_Z, generateMipmap); 426 | cam->setProjectionMatrixAsOrtho2D(-1.0 * w / 2, (-1.0 * w / 2) + w * 1.0, -1.0 * h / 2, (-1.0 * h / 2) + h * 1.0); 427 | //cam->setViewMatrixAsLookAt(osg::Vec3(0.0, 0.0, 0.0), osg::Vec3(0.0, 0.0, -1.0), osg::Vec3(0.0, -1.0, 0.0)); 428 | cam->setViewMatrix(osg::Matrixd::rotate(osg::inDegrees(90.0f), 1.0, 0.0, 0.0) * osg::Matrixd::rotate(osg::inDegrees(180.0f), 0.0, 0.0, 1.0)); 429 | cameras->addChild(cam); 430 | } 431 | return cameras; 432 | 433 | } 434 | osg::ref_ptr IBLTechnique::createHDRBox(int w) 435 | { 436 | osg::ref_ptr geode = new osg::Geode(); 437 | osg::ShapeDrawable* sd = new osg::ShapeDrawable(new osg::Box(osg::Vec3(0.0, 0.0, 0.0), 1.0)); 438 | 439 | geode->addDrawable(sd); 440 | osg::ref_ptr trans = new osg::MatrixTransform(); 441 | trans->setMatrix(osg::Matrix::scale(w, w, w)); 442 | trans->addChild(geode); 443 | return trans; 444 | } 445 | osg::ref_ptr createTextureQuad(float width,float height) 446 | { 447 | bool xyPlane, flip; 448 | xyPlane = flip = true; 449 | osg::ref_ptr geode = new osg::Geode; 450 | auto geom = osg::createTexturedQuadGeometry(osg::Vec3(0.0, 0.0, 0.0), 451 | osg::Vec3(width, 0.0f, 0.0f), 452 | xyPlane ? osg::Vec3(0.0f, height, 0.0f) : osg::Vec3(0.0f, 0.0f, height), 453 | 0.0f, flip ? 1.0f : 0.0f, 1.0f, flip ? 0.0f : 1.0f); 454 | geode->addDrawable(geom); 455 | return geode; 456 | 457 | } 458 | 459 | 460 | void IBLTechnique::createIrridianceQuadPass() 461 | { 462 | 463 | 464 | osg::ref_ptr box = createHDRBox(); 465 | VirtualProgram* vp = VirtualProgram::getOrCreate(box->getOrCreateStateSet()); 466 | box->getOrCreateStateSet()->setTextureAttributeAndModes(0, envQuadMap.get(), osg::StateAttribute::ON); 467 | box->getOrCreateStateSet()->getOrCreateUniform("environmentMap", osg::Uniform::SAMPLER_2D)->set(0); 468 | 469 | ShaderPackage shaders; 470 | shaders.load(vp, "ibl_irradiance_quad.glsl", _dbo); 471 | 472 | osg::Node* cameras = createSlaveCameras(box.get(), irridianceMap.get()); 473 | root->addChild(cameras); 474 | 475 | 476 | } 477 | 478 | void IBLTechnique::IrridianceBoxToQuad() 479 | { 480 | 481 | /* int w = 2048; 482 | int h = 1024; 483 | 484 | osg::ref_ptr node = createQuadGeom(w * 1.0f, h * 1.0f); 485 | 486 | auto irridianceMapPath = "Cerberus_NSpecularHDR.dds"; 487 | std::string path = "C:\\Users\\10677\\source\\repos\\OE_PBR\\OE_PBR\\Asset\\IBL"; 488 | osg::ref_ptr readOption = new osgDB::Options("IBL"); 489 | readOption->setDatabasePath(path); 490 | auto irridianceImages = readCubeImages(irridianceMapPath, readOption.get()); 491 | auto irridianceBoxMap = new osg::TextureCubeMap(); 492 | irridianceBoxMap->setNumMipmapLevels(5); 493 | 494 | for (uint32_t i = 0; i < 6; i++) 495 | { 496 | irridianceBoxMap->setImage(i, irridianceImages[i]); 497 | } 498 | irridianceBoxMap->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE); 499 | irridianceBoxMap->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE); 500 | irridianceBoxMap->setWrap(osg::Texture::WRAP_R, osg::Texture::CLAMP_TO_EDGE); 501 | 502 | irridianceBoxMap->setFilter(osg::Texture::MIN_FILTER, osg::Texture::NEAREST_MIPMAP_LINEAR); 503 | irridianceBoxMap->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); 504 | 505 | 506 | osgEarth::VirtualProgram* vp = osgEarth::VirtualProgram::getOrCreate(node->getOrCreateStateSet()); 507 | osgEarth::ShaderPackage shaders; 508 | shaders.load(vp, "cube_to_quad.glsl", _dbo.get()); 509 | node->getOrCreateStateSet()->setTextureAttributeAndModes(0, irridianceBoxMap, osg::StateAttribute::ON); 510 | node->getOrCreateStateSet()->getOrCreateUniform("IrradianceMap", osg::Uniform::SAMPLER_CUBE)->set(0); 511 | 512 | 513 | osg::ref_ptr target = new osg::Texture2D(); 514 | target->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE); 515 | target->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE); 516 | target->setWrap(osg::Texture::WRAP_R, osg::Texture::CLAMP_TO_EDGE); 517 | target->setTextureSize(256, 128); 518 | target->setInternalFormat(GL_RGBA); 519 | target->setNumMipmapLevels(1); 520 | 521 | target->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR); 522 | target->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); 523 | 524 | root->addChild(node);*/ 525 | 526 | 527 | } 528 | 529 | 530 | void IBLTechnique::createRadianceQuadPass() 531 | { 532 | 533 | 534 | uint32_t maxMipLevels = 3; 535 | for (unsigned int mip = 2; mip < maxMipLevels; ++mip) 536 | { 537 | 538 | unsigned int mipWidth = 512 * std::pow(0.5, mip); 539 | unsigned int mipHeight = 512 * std::pow(0.5, mip); 540 | float roughness = (float)mip / (float)(maxMipLevels - 1); 541 | std::cout << roughness << "roughness" << std::endl; 542 | 543 | osg::ref_ptr box = createHDRBox(mipWidth); 544 | 545 | VirtualProgram* vp = VirtualProgram::getOrCreate(box->getOrCreateStateSet()); 546 | ShaderPackage shaders; 547 | shaders.load(vp, "ibl_radiance_quad.glsl", _dbo); 548 | box->getOrCreateStateSet()->setTextureAttributeAndModes(0, envQuadMap.get(), osg::StateAttribute::ON); 549 | box->getOrCreateStateSet()->getOrCreateUniform("environmentMap", osg::Uniform::SAMPLER_2D)->set(0); 550 | auto uniform = new osg::Uniform("roughness", 1.0f); 551 | box->getOrCreateStateSet()->getOrCreateUniform("ngt", osg::Uniform::INT)->set(5); 552 | osg::Node* cameras = createSlaveCameras(box.get(), prefilterMap.get(), 0, mipWidth, mipHeight, true); 553 | root->addChild(cameras); 554 | } 555 | 556 | 557 | } 558 | 559 | 560 | void IBLTechnique::createTextures() 561 | { 562 | int w, h; 563 | w = h = 256; 564 | // hdr 565 | osg::ref_ptr image = osgDB::readRefImageFile("C:\\Users\\10677\\source\\repos\\OE_PBR\\OE_PBR\\Asset\\abandoned_bakery_4k.hdr"); 566 | hdrMap = new osg::Texture2D(image.get()); 567 | 568 | 569 | envCubeMap = new osg::TextureCubeMap(); 570 | envCubeMap->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE); 571 | envCubeMap->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE); 572 | envCubeMap->setWrap(osg::Texture::WRAP_R, osg::Texture::CLAMP_TO_EDGE); 573 | envCubeMap->setTextureSize(w, h); 574 | envCubeMap->setInternalFormat(GL_RGBA); 575 | envCubeMap->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_LINEAR); 576 | envCubeMap->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); 577 | envCubeMap->setNumMipmapLevels(5); 578 | //envCubeMap->setUseHardwareMipMapGeneration(true); 579 | 580 | envQuadMap = new osg::Texture2D(); 581 | envQuadMap->setImage(image.get()); 582 | envQuadMap->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE); 583 | envQuadMap->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE); 584 | envQuadMap->setWrap(osg::Texture::WRAP_R, osg::Texture::CLAMP_TO_EDGE); 585 | 586 | envQuadMap->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_LINEAR); 587 | envQuadMap->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); 588 | //envQuadMap->setNumMipmapLevels(5); 589 | //envQuadMap->setTextureSize(w, h); 590 | //envQuadMap->setInternalFormat(GL_RGB); 591 | 592 | 593 | 594 | w = h = 128; 595 | irridianceMap = new osg::TextureCubeMap(); 596 | irridianceMap->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE); 597 | irridianceMap->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE); 598 | irridianceMap->setWrap(osg::Texture::WRAP_R, osg::Texture::CLAMP_TO_EDGE); 599 | irridianceMap->setTextureSize(w, h); 600 | irridianceMap->setInternalFormat(GL_RGBA); 601 | irridianceMap->setNumMipmapLevels(1); 602 | 603 | irridianceMap->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR); 604 | irridianceMap->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); 605 | 606 | 607 | w = h = 128; 608 | prefilterMap = new osg::TextureCubeMap(); 609 | prefilterMap->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE); 610 | prefilterMap->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE); 611 | prefilterMap->setWrap(osg::Texture::WRAP_R, osg::Texture::CLAMP_TO_EDGE); 612 | prefilterMap->setTextureSize(w, h); 613 | prefilterMap->setInternalFormat(GL_RGBA); 614 | 615 | prefilterMap->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_LINEAR); 616 | prefilterMap->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); 617 | //prefilterMap->setUseHardwareMipMapGeneration(true); 618 | prefilterMap->setNumMipmapLevels(3); 619 | prefilterMap->setUseHardwareMipMapGeneration(false); 620 | 621 | w = h = 512; 622 | brdfLUTMap = new osg::Texture2D(); 623 | brdfLUTMap->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE); 624 | brdfLUTMap->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE); 625 | brdfLUTMap->setTextureSize(w, h); 626 | brdfLUTMap->setInternalFormat(GL_RGBA); 627 | brdfLUTMap->setSourceType(GL_FLOAT); 628 | 629 | brdfLUTMap->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR); 630 | brdfLUTMap->setFilter(osg::Texture2D::MAG_FILTER, osg::Texture2D::LINEAR); 631 | //prefilterMap->setUseHardwareMipMapGeneration(true); 632 | 633 | } 634 | -------------------------------------------------------------------------------- /OE_PBR/IBLBaker.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // author:1067720863@qq.com 4 | // create date:2023/04 5 | // decription: Cook_BRDF Light 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "Export.h" 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | class IBLTechnique : public osg::Object 34 | { 35 | 36 | public: 37 | IBLTechnique() {} 38 | IBLTechnique(osg::Group* _root, osgViewer::Viewer* _viewer) 39 | : root(_root) 40 | , viewer(_viewer) 41 | { 42 | } 43 | virtual ~IBLTechnique() {} 44 | 45 | virtual osg::Object* cloneType() const override { return new IBLTechnique(); } 46 | virtual osg::Object* clone(const osg::CopyOp& copyop) const override { return new IBLTechnique(*this, copyop); } 47 | 48 | IBLTechnique(const IBLTechnique& es, const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY) {} 49 | virtual bool isSameKindAs(const osg::Object* obj) const { return dynamic_cast(obj) != NULL; } 50 | virtual const char* libraryName() const { return "osgShadow"; } 51 | virtual const char* className() const { return "ShadowTechnique"; } 52 | struct Config 53 | { 54 | bool baked{false}; 55 | }; 56 | void startUp(); 57 | 58 | void createIrridiancePass(); 59 | 60 | void createPrefilterPass(); 61 | 62 | void createBrdfLUTPass(); 63 | 64 | void createHDRCubePass(osg::Texture* envCubeMap); 65 | void createRadianceQuadPass(); 66 | 67 | void createTextures(); 68 | void createLightPass(); 69 | 70 | osg::Node* createSlaveCameras(osg::Node* box, osg::Texture* tex, unsigned int level = 0, unsigned int w = 256, unsigned int h = 256, bool generateMipmap = false); 71 | 72 | osg::ref_ptr createHDRBox(int w = 128); 73 | 74 | void createIrridianceQuadPass(); 75 | 76 | void IrridianceBoxToQuad(); 77 | 78 | private: 79 | osg::ref_ptr envCubeMap; 80 | osg::ref_ptr irridianceMap; 81 | osg::ref_ptr prefilterMap; 82 | osg::ref_ptr brdfLUTMap; 83 | osg::ref_ptr hdrMap; 84 | 85 | osg::ref_ptr _dbo; 86 | 87 | osg::ref_ptr envQuadMap; 88 | 89 | osg::Group* root; 90 | osgViewer::Viewer* viewer; 91 | }; 92 | -------------------------------------------------------------------------------- /OE_PBR/OE_PBR.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 16.0 23 | Win32Proj 24 | {0d5253e2-056b-4fbc-b719-1f6b593693d6} 25 | OEPBR 26 | 10.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v143 33 | Unicode 34 | 35 | 36 | Application 37 | false 38 | v143 39 | true 40 | Unicode 41 | 42 | 43 | Application 44 | true 45 | v143 46 | Unicode 47 | 48 | 49 | Application 50 | false 51 | v143 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | true 76 | 77 | 78 | false 79 | 80 | 81 | true 82 | D:\LocalSDK\osgEarthSDK\include\third_party\tinygltf;D:\GitProject\osgEarth\osgearth\src\third_party\tinygltf\glew210\include;D:\LocalSDK\osgEarthSDK\include\third_party\imgui;$(IncludePath) 83 | D:\GitProject\osgEarth\osgearth\src\third_party\tinygltf\glew210\lib;$(LibraryPath) 84 | osgEarthPBRd 85 | 86 | 87 | false 88 | D:\LocalSDK\osgEarthSDK\include\third_party\tinygltf;D:\LocalSDK\vcpkg\packages\glew_x64-windows\include;D:\GitProject\osgEarth\osgearth\src\third_party\tinygltf\glew210\include;D:\LocalSDK\osgearth\src\third_party\imgui;D:\LocalSDK\osgearth\src\third_party\imgui\examples;D:\LocalSDK\osgEarthSDK\include;$(IncludePath) 89 | D:\LocalSDK\osgearth\src\osgEarth\ImGui;$(SourcePath) 90 | D:\GitProject\osgEarth\osgearth\src\third_party\tinygltf\glew210\lib;D:\LocalSDK\osgEarthSDK\lib;$(LibraryPath) 91 | osgEarthPBR 92 | 93 | 94 | 95 | Level3 96 | true 97 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 98 | true 99 | 100 | 101 | Console 102 | true 103 | 104 | 105 | 106 | 107 | Level3 108 | true 109 | true 110 | true 111 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 112 | true 113 | 114 | 115 | Console 116 | true 117 | true 118 | true 119 | 120 | 121 | 122 | 123 | Level3 124 | true 125 | _DEBUG;_CONSOLE;OE_MATERIAL_LIBRARY;%(PreprocessorDefinitions) 126 | true 127 | $(IntDir)%(RelativeDir) 128 | /bigobj %(AdditionalOptions) 129 | 130 | 131 | Console 132 | true 133 | D:\GitProject\osgEarth\osgearth\src\third_party\tinygltf\glew210\lib\glew32d.lib;%(AdditionalDependencies) 134 | 135 | 136 | 137 | 138 | Level3 139 | true 140 | true 141 | true 142 | NDEBUG;_CONSOLE;OE_MATERIAL_LIBRARY;OSGEARTH_PROFILING;%(PreprocessorDefinitions) 143 | true 144 | $(IntDir)%(RelativeDir) 145 | stdcpp17 146 | 147 | 148 | Console 149 | true 150 | true 151 | true 152 | D:\GitProject\osgEarth\osgearth\src\third_party\tinygltf\glew210\lib\glew32.lib;D:\LocalSDK\osgEarthSDK\lib\osgEarth.lib;%(AdditionalDependencies) 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | -------------------------------------------------------------------------------- /OE_PBR/OE_PBR.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | 源文件 20 | 21 | 22 | 源文件 23 | 24 | 25 | 源文件 26 | 27 | 28 | 源文件 29 | 30 | 31 | 源文件 32 | 33 | 34 | 源文件 35 | 36 | 37 | 源文件 38 | 39 | 40 | 源文件 41 | 42 | 43 | 源文件 44 | 45 | 46 | 源文件 47 | 48 | 49 | 源文件 50 | 51 | 52 | 源文件 53 | 54 | 55 | 源文件 56 | 57 | 58 | 源文件 59 | 60 | 61 | 62 | 63 | 头文件 64 | 65 | 66 | 头文件 67 | 68 | 69 | 头文件 70 | 71 | 72 | 头文件 73 | 74 | 75 | 头文件 76 | 77 | 78 | 头文件 79 | 80 | 81 | 头文件 82 | 83 | 84 | 头文件 85 | 86 | 87 | 头文件 88 | 89 | 90 | 头文件 91 | 92 | 93 | 头文件 94 | 95 | 96 | 头文件 97 | 98 | 99 | 头文件 100 | 101 | 102 | 头文件 103 | 104 | 105 | 头文件 106 | 107 | 108 | 头文件 109 | 110 | 111 | 头文件 112 | 113 | 114 | -------------------------------------------------------------------------------- /OE_PBR/OE_PBR.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | false 5 | 6 | -------------------------------------------------------------------------------- /OE_PBR/PbrLightEffect.cpp: -------------------------------------------------------------------------------- 1 | 2 | //author:1067720863@qq.com 3 | //create date:2023/04 4 | //decription: PBR Material 5 | 6 | #include "PbrLightEffect.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | //#include 15 | #include 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | using namespace osgEarth; 25 | using namespace osgEarth::Util; 26 | 27 | 28 | 29 | class ExtensionedMaterial; 30 | 31 | 32 | osgEarth::Util::PbrLightEffect::PbrLightEffect() 33 | { 34 | init(); 35 | } 36 | 37 | osgEarth::Util::PbrLightEffect::PbrLightEffect(osg::StateSet* stateset) 38 | { 39 | init(); 40 | attach(stateset); 41 | } 42 | 43 | 44 | void osgEarth::Util::PbrLightEffect::attach(osg::StateSet* stateset) 45 | { 46 | 47 | if (stateset && _supported) 48 | { 49 | _statesets.push_back(stateset); 50 | 51 | // set light 52 | stateset->setDefine(OE_LIGHTING_DEFINE, "1", osg::StateAttribute::ON); 53 | stateset->setDefine("OE_NUM_LIGHTS", "1"); 54 | stateset->setDefine("OE_USE_PBR", "1"); 55 | stateset->setDefine("cascade", "1"); 56 | 57 | 58 | ShaderPackage shaders; 59 | VirtualProgram* pbrVP = VirtualProgram::getOrCreate(stateset); 60 | 61 | 62 | osg::ref_ptr dbo = new osgDB::Options(); 63 | 64 | auto shaderPath = "..//..//OE_PBR//Shader"; 65 | auto shaderPath2 = "..//OE_PBR//Shader"; 66 | 67 | if (osgDB::fileExists(osgEarth::getAbsolutePath(shaderPath))) 68 | { 69 | dbo->setDatabasePath(osgEarth::getAbsolutePath(shaderPath)); 70 | } 71 | else { 72 | dbo->setDatabasePath(osgEarth::getAbsolutePath(shaderPath2)); 73 | } 74 | 75 | 76 | 77 | 78 | auto material = stateset->getAttribute(osg::StateAttribute::MATERIAL); 79 | 80 | std::string materialSnippet = ""; 81 | std::string material_defines(""), material_body, material_uniforms(""); 82 | 83 | URIContext context(dbo.get()); 84 | URI standard("materials/standard.glsl", context); 85 | std::string basic = osgDB::findDataFile(standard.full(), dbo); 86 | material_body = URI(basic, context).getString(dbo); 87 | 88 | if (osgEarth::ExtensionedMaterial* mat = dynamic_cast(material)) 89 | { 90 | const std::string fileName = mat->materialFile(); 91 | if (!fileName.empty()) 92 | { 93 | URI uri(fileName, context); 94 | std::string path = osgDB::findDataFile(uri.full(), dbo); 95 | if (!path.empty()) 96 | { 97 | materialSnippet = URI(path, context).getString(dbo); 98 | if (!materialSnippet.empty()) 99 | { 100 | OE_DEBUG << "Loaded materail shader " << fileName << " from " << path << "\n"; 101 | } 102 | } 103 | } 104 | } 105 | if (!materialSnippet.empty()) 106 | { 107 | // parse custom material 108 | std::string::size_type pragmaPos = 0; 109 | while (pragmaPos != std::string::npos) 110 | { 111 | const std::string token("#pragma import_defines"); 112 | std::string::size_type statementPos = materialSnippet.find(token, pragmaPos); 113 | if (statementPos == std::string::npos) 114 | { 115 | break; 116 | } 117 | std::string::size_type bracketLeft = materialSnippet.find_first_not_of("(", statementPos + token.length()); 118 | std::string::size_type bracketRight = materialSnippet.find_first_of(")", bracketLeft); 119 | if (!material_defines.empty()) 120 | { 121 | material_defines.push_back(','); 122 | } 123 | material_defines.append(materialSnippet.substr(bracketLeft, bracketRight - bracketLeft)); 124 | pragmaPos = bracketRight + 1; 125 | } 126 | pragmaPos = 0; 127 | while (pragmaPos != std::string::npos) 128 | { 129 | const std::string token("uniform"); 130 | std::string::size_type statementPos = materialSnippet.find(token, pragmaPos); 131 | if (statementPos == std::string::npos) 132 | { 133 | break; 134 | } 135 | std::string::size_type uniformEnd = materialSnippet.find_first_of("\n", statementPos); 136 | material_uniforms.append(materialSnippet.substr(statementPos, uniformEnd - statementPos)); 137 | pragmaPos = uniformEnd; 138 | } 139 | material_body.append(materialSnippet.substr(pragmaPos)); 140 | 141 | std::cout << " material_defines " << material_defines << std::endl << "material_define_end" << std::endl; 142 | std::cout << " material_uniform" << material_uniforms << std::endl << "material_uniform_end" << std::endl; 143 | std::cout << " material_body" << material_body << std::endl << "material_body_end" << std::endl; 144 | } 145 | 146 | 147 | // insert into basic shader 148 | osgEarth::Registry::instance()->getShaderFactory()->addPreProcessorCallback( 149 | "MaterialReplace", 150 | [this, material_body, material_defines, material_uniforms](std::string& output) 151 | { 152 | auto replaceFunc = [](const std::string& token, const std::string& source, std::string& output) 153 | { 154 | std::string::size_type statementPos = output.find(token); 155 | if (statementPos == std::string::npos) 156 | return; 157 | 158 | std::string::size_type startPos = output.find_first_not_of(" \t", statementPos + token.length()); 159 | if (startPos == std::string::npos) 160 | return; 161 | 162 | std::string::size_type endPos = output.find('\n', startPos); 163 | if (endPos == std::string::npos) 164 | return; 165 | 166 | std::string statement(output.substr(statementPos, endPos - statementPos)); 167 | 168 | Strings::replaceIn(output, statement, source); 169 | }; 170 | 171 | replaceFunc("MATERIAL_DEFINES", material_defines, output); 172 | replaceFunc("# MATERIAL_UNIFORMS", material_uniforms, output); 173 | replaceFunc("# MATERIAL_BODY", material_body, output); 174 | 175 | } 176 | ); 177 | 178 | shaders.load(pbrVP, "pbr.glsl", dbo.get()); 179 | 180 | } 181 | } 182 | 183 | 184 | void osgEarth::Util::PbrLightEffect::detach() 185 | { 186 | if (_supported) 187 | { 188 | for (StateSetList::iterator it = _statesets.begin(); it != _statesets.end(); ++it) 189 | { 190 | osg::ref_ptr stateset; 191 | if ((*it).lock(stateset)) 192 | { 193 | detach(stateset.get()); 194 | (*it) = 0L; 195 | } 196 | } 197 | 198 | _statesets.clear(); 199 | } 200 | } 201 | 202 | void osgEarth::Util::PbrLightEffect::detach(osg::StateSet* stateset) 203 | { 204 | if (stateset && _supported) 205 | { 206 | stateset->removeDefine(OE_LIGHTING_DEFINE); 207 | 208 | VirtualProgram* vp = VirtualProgram::get(stateset); 209 | if (vp) 210 | { 211 | Shaders shaders; 212 | shaders.unload(vp, shaders.PhongLighting); 213 | } 214 | } 215 | } 216 | 217 | osgEarth::Util::PbrLightEffect::~PbrLightEffect() 218 | { 219 | detach(); 220 | } 221 | 222 | void osgEarth::Util::PbrLightEffect::init() 223 | { 224 | _supported = Registry::capabilities().supportsGLSL(); 225 | _supported = true; 226 | } 227 | -------------------------------------------------------------------------------- /OE_PBR/PbrLightEffect.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | //author:1067720863@qq.com 3 | //create date:2023/04 4 | //decription: Cook_BRDF Light 5 | #ifndef OSGEARTH_PBR_LIGHTING_EFFECT_H 6 | #define OSGEARTH_PBR_LIGHTING_EFFECT_H 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include"Export.h" 20 | #include"PbrMaterial.h" 21 | 22 | 23 | 24 | 25 | #define OE_ENABLE_BASECOLOR_MAP "OE_ENABLE_BASECOLOR_MAP" 26 | #define OE_ENABLE_NORMAL_MAP "OE_ENABLE_NORMAL_MAP" 27 | #define OE_ENABLE_MR_MAP "OE_ENABLE_MR_MAP" 28 | #define OE_ENABLE_AO_MAP "OE_ENABLE_AO_MAP" 29 | #define OE_ENABLE_EMISSIVE_MAP "OE_ENABLE_EMISSIVE_MAP" 30 | 31 | #define oe_basecolor_map "oe_basecolor_map" 32 | #define oe_normal_map "oe_normal_map" 33 | #define oe_mr_map "oe_mr_map" 34 | #define oe_ao_map "oe_ao_map" 35 | #define oe_emissive_map "oe_emissive_map" 36 | 37 | 38 | 39 | namespace osgEarth { 40 | 41 | namespace Util 42 | { 43 | /** 44 | * Shader effect that performs simple Cook_Torrence BRDF lighting. 45 | */ 46 | class OE_MATERIAL_PULGIN PbrLightEffect : public osg::Referenced 47 | { 48 | public: 49 | /** constructs a new effect */ 50 | PbrLightEffect(); 51 | 52 | /** contructs a new effect and attaches it to a stateset. */ 53 | PbrLightEffect(osg::StateSet* stateset); 54 | 55 | /** is it supported by the h/w? */ 56 | bool supported() const { return _supported; } 57 | 58 | public: 59 | /** attach this effect to a stateset. */ 60 | void attach(osg::StateSet* stateset); 61 | 62 | /** detach this effect from any attached statesets. */ 63 | void detach(); 64 | 65 | /** detach this effect from a stateset. */ 66 | void detach(osg::StateSet* stateset); 67 | 68 | protected: 69 | virtual ~PbrLightEffect(); 70 | 71 | 72 | typedef std::list< osg::observer_ptr > StateSetList; 73 | 74 | 75 | bool _supported; 76 | StateSetList _statesets; 77 | 78 | void init(); 79 | 80 | using TextureCache = osgEarth::Mutexed< 81 | std::unordered_map> >; 82 | 83 | mutable TextureCache* _texCache; 84 | 85 | }; 86 | 87 | } 88 | } // namespace osgEarth::Util 89 | 90 | #endif -------------------------------------------------------------------------------- /OE_PBR/PbrMaterial.cpp: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | //author:1067720863@qq.com 5 | //create date:2023/04 6 | //decription: PBR Material 7 | #include 8 | #include "PbrMaterial.h" 9 | 10 | 11 | #include 12 | #include 13 | #include 14 | #include"EnvLight.h" 15 | #include 16 | 17 | osgEarth::StandardPBRMaterial::StandardPBRMaterial() 18 | { 19 | mTextureAtlas = new osg::Texture2DArray(); 20 | mTextureAtlas->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR); 21 | mTextureAtlas->setFilter(osg::Texture2D::MAG_FILTER, osg::Texture2D::LINEAR); 22 | mTextureAtlas->setWrap(osg::Texture2D::WRAP_S, osg::Texture2D::REPEAT); 23 | mTextureAtlas->setWrap(osg::Texture2D:: WRAP_T, osg::Texture2D::REPEAT); 24 | mTextureAtlas->setUnRefImageDataAfterApply(true); 25 | mTextureAtlas->setResizeNonPowerOfTwoHint(false); 26 | } 27 | 28 | osgEarth::StandardPBRMaterial::StandardPBRMaterial(const Config& conf) 29 | { 30 | /* conf.get("baseColor", mBaseColorFactor); 31 | conf.get("emissive", mEmissiveFactor); 32 | conf.get("roughness", mRoughnessFactor); 33 | conf.get("metallic", mMetallicFactor); 34 | conf.get("aoStrength", mAoStrength); 35 | conf.get("alphaMask", mAlphaMask); 36 | conf.get("alphaMaskCutoff", mAlphaMaskCutoff);*/ 37 | 38 | } 39 | 40 | std::string osgEarth::StandardPBRMaterial::getDefaultDefineName(TextureEnum mapEnum) 41 | { 42 | if (textureDefines.find(mapEnum) == textureDefines.end()) 43 | { 44 | return ""; 45 | } 46 | return textureDefines.at(mapEnum); 47 | } 48 | 49 | 50 | void osgEarth::StandardPBRMaterial::apply(State& state) const 51 | { 52 | OSG_NOTICE << "Warning: Material::apply(State&) - not supported." << std::endl; 53 | 54 | state.Color(mBaseColorFactor.r(), mBaseColorFactor.g(), mBaseColorFactor.b(), mBaseColorFactor.a()); 55 | } 56 | 57 | void osgEarth::StandardPBRMaterial::setMaterialImage(TextureEnum mapEnum, osg::Image* image) 58 | { 59 | int layer = _maps.size(); 60 | if (_maps.find(mapEnum) != _maps.end()) 61 | { 62 | layer = _maps[mapEnum].layer; 63 | } 64 | osg::ref_ptr temp; 65 | if (texWidth < 0 && texHeight < 0) 66 | { 67 | texWidth = image->s(); 68 | texHeight = image->t(); 69 | temp = image; 70 | } 71 | else { 72 | if (texWidth != image->s() || texHeight != image->t()) 73 | { 74 | ImageUtils::resizeImage(image, texWidth, texHeight, temp); 75 | } 76 | else { 77 | temp = image; 78 | } 79 | } 80 | 81 | std::cout << "dff" << temp->s() << " " << temp->t() << " " << temp->r()<<" " << layer << std::endl; 82 | mTextureAtlas->setImage(layer, temp.get()); 83 | _maps[mapEnum] = TextureInfo{ layer }; 84 | } 85 | 86 | void osgEarth::StandardPBRMaterial::setMaterialImage(TextureEnum mapEnum, const std::string& imageUrl) 87 | { 88 | osg::ref_ptr image = osgDB::readRefImageFile(imageUrl, _options.get()); 89 | 90 | if (image.valid() == false) 91 | { 92 | return; 93 | } 94 | setMaterialImage(mapEnum, image.get()); 95 | } 96 | 97 | osg::Texture* osgEarth::StandardPBRMaterial::createTexture(const std::string& imagePath) 98 | { 99 | float s = -1.0f, t = -1.0f; 100 | 101 | osg::ref_ptr image = osgDB::readRefImageFile(imagePath, _options.get()); 102 | 103 | if (image.valid() == false) 104 | { 105 | return nullptr; 106 | } 107 | osg::Texture2D* tex = new osg::Texture2D(); 108 | 109 | tex->setFilter(tex->MIN_FILTER, tex->NEAREST_MIPMAP_LINEAR); 110 | tex->setFilter(tex->MAG_FILTER, tex->NEAREST_MIPMAP_LINEAR); 111 | tex->setWrap(tex->WRAP_S, tex->REPEAT); 112 | tex->setWrap(tex->WRAP_T, tex->REPEAT); 113 | tex->setUnRefImageDataAfterApply(osgEarth::Registry::instance()->unRefImageDataAfterApply().get()); 114 | tex->setMaxAnisotropy(4.0); 115 | tex->setImage(image.get()); 116 | // Let the GPU do it since we only download this at startup 117 | tex->setUseHardwareMipMapGeneration(true); 118 | 119 | return tex; 120 | } 121 | 122 | void osgEarth::PBRMaterialCallback::operator()(osg::StateAttribute* attr, osg::NodeVisitor* nv) 123 | { 124 | 125 | static const std::string BASECOLOR = UPREFIX "baseColorFactor"; 126 | static const std::string EMISSIVE = UPREFIX "emissiveFactor"; 127 | static const std::string METALLIC = UPREFIX "metallicFactor"; 128 | static const std::string ROUGHNESS = UPREFIX "roughnessFactor"; 129 | static const std::string ALPHAMASK = UPREFIX "alphaMask"; 130 | static const std::string ALPHAMASKCUTOFF = UPREFIX "alphaMaskCutoff"; 131 | static const std::string AMBIENTOCCLUSION = UPREFIX "aoStrength"; 132 | static const std::string RECEIVEENVLIGHT = UPREFIX "aoStrength"; 133 | 134 | osgEarth::StandardPBRMaterial* material = static_cast(attr); 135 | for (unsigned int i = 0; i < attr->getNumParents(); i++) 136 | { 137 | osg::StateSet* stateSet = attr->getParent(i); 138 | 139 | stateSet->getOrCreateUniform(BASECOLOR, osg::Uniform::FLOAT_VEC4)->set(material->getBaseColorFactor()); 140 | stateSet->getOrCreateUniform(EMISSIVE, osg::Uniform::FLOAT_VEC3)->set(material->getEmissiveFactor()); 141 | stateSet->getOrCreateUniform(METALLIC, osg::Uniform::FLOAT)->set(material->getMetallicFactor()); 142 | stateSet->getOrCreateUniform(ROUGHNESS, osg::Uniform::FLOAT)->set(material->getRoughnessFactor()); 143 | stateSet->getOrCreateUniform(ALPHAMASK, osg::Uniform::FLOAT)->set(material->getAlphaMask()); 144 | stateSet->getOrCreateUniform(ALPHAMASKCUTOFF, osg::Uniform::FLOAT)->set(material->getAlphaMaskCutoff()); 145 | stateSet->getOrCreateUniform(AMBIENTOCCLUSION, osg::Uniform::FLOAT)->set(material->getAoStrength()); 146 | 147 | osg::Texture* tex = material->getTextureAtlas(); 148 | int unit = material->getOrCreateTexUnit("pbrMaps"); 149 | stateSet->setTextureAttributeAndModes(unit, tex, osg::StateAttribute::ON); 150 | stateSet->getOrCreateUniform("pbrMaps", osg::Uniform::SAMPLER_2D_ARRAY)->set(unit); 151 | 152 | 153 | for (const auto iter : material->_maps) 154 | { 155 | auto define = material->getDefaultDefineName(iter.first); 156 | float layer = iter.second.layer * 1.0f; 157 | stateSet->setDefine(define, std::to_string(layer), osg::StateAttribute::ON); 158 | 159 | } 160 | 161 | 162 | } 163 | } 164 | 165 | void osgEarth::ExtensionedMaterialCallback::operator()(osg::StateAttribute* attr, osg::NodeVisitor* nv) 166 | { 167 | PBRMaterialCallback::operator()(attr, nv); 168 | osgEarth::ExtensionedMaterial* material = static_cast(attr); 169 | for (unsigned int i = 0; i < attr->getNumParents(); i++) 170 | { 171 | const auto& maps = material->_customMaps; 172 | auto iter = maps.begin(); 173 | osg::StateSet* stateSet = attr->getParent(i); 174 | for (; iter != maps.end(); iter++) 175 | { 176 | auto uniformKey = iter->first; 177 | int unit = material->getOrCreateTexUnit(uniformKey); 178 | stateSet->setTextureAttributeAndModes(unit, iter->second, osg::StateAttribute::ON); 179 | stateSet->getOrCreateUniform(uniformKey, osg::Uniform::SAMPLER_2D)->set(unit); 180 | 181 | } 182 | for (const auto& define : material->customDefines()) 183 | { 184 | stateSet->setDefine(define, "1", osg::StateAttribute::ON); 185 | } 186 | } 187 | } 188 | 189 | void osgEarth::ExtensionedMaterial::extTextureAttribute(const std::string name, const std::string& fileName, const std::string& defineName, unsigned int uvChannel, StateAttribute::OverrideValue value) 190 | { 191 | _customMaps[name] = createTexture(fileName); 192 | _customDefines.push_back(defineName); 193 | 194 | } 195 | -------------------------------------------------------------------------------- /OE_PBR/PbrMaterial.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fang1067720863/osgPBR/dba01b6cbc42c0ccb2e0611fcad1c04e27288f15/OE_PBR/PbrMaterial.h -------------------------------------------------------------------------------- /OE_PBR/RayPicker.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | class RayPicker:public osgGA::GUIEventHandler 12 | { 13 | 14 | public: 15 | using FindCallback = std::function; 16 | RayPicker(osgViewer::Viewer *viewer, FindCallback cb):_viewer(viewer),_cb(cb){} 17 | virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) 18 | { 19 | switch (ea.getEventType()) 20 | { 21 | case osgGA::GUIEventAdapter::PUSH: 22 | if (ea.getButton() == osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON) 23 | { 24 | Pick(ea.getX(), ea.getY()); 25 | } 26 | return true; 27 | default: 28 | return false; 29 | } 30 | return false; 31 | } 32 | protected: 33 | void Pick(float x, float y) 34 | { 35 | osgUtil::LineSegmentIntersector::Intersections intersections; 36 | if (_viewer->computeIntersections(x,y,intersections)) 37 | { 38 | auto hiter = intersections.begin(); 39 | if (!hiter->nodePath.empty()) 40 | { 41 | const auto& nodePath = hiter->nodePath; 42 | for (const auto& node : nodePath) 43 | { 44 | 45 | std::cout << node->getCompoundClassName()<<" " << node->getName() << std::endl; 46 | auto maT = node->asTransform() ? node->asTransform()->asMatrixTransform() : NULL; 47 | if (maT) 48 | { 49 | _cb(maT); 50 | } 51 | } 52 | } 53 | } 54 | } 55 | private: 56 | 57 | FindCallback _cb; 58 | osgViewer::Viewer* _viewer; 59 | 60 | }; -------------------------------------------------------------------------------- /OE_PBR/ReflectionProbe.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fang1067720863/osgPBR/dba01b6cbc42c0ccb2e0611fcad1c04e27288f15/OE_PBR/ReflectionProbe.cpp -------------------------------------------------------------------------------- /OE_PBR/ReflectionProbe.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | //author:1067720863@qq.com 3 | //create date:2023/04 4 | //decription: Cook_BRDF Light 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include"Export.h" 33 | #include 34 | 35 | class ReflectionProbe:public osg::Object 36 | { 37 | public: 38 | ReflectionProbe(float near = 1.f, float far = 10.f, uint32_t resolution = 128); 39 | ReflectionProbe(const ReflectionProbe& teapot, const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY) {} 40 | META_Object(osgIBLApp, ReflectionProbe); 41 | 42 | void createCubeCameras(float near=1.f, float far=100.f, uint32_t resolution = 128); 43 | void setPosition(osg::Vec3d pos); 44 | osg::ref_ptr getCubeMap() { return _texture; } 45 | osg::Vec3d getPos() { return _pos; } 46 | osg::Node* getNode(); 47 | osg::Camera* createDebugHUDCamera(); 48 | osg::Node* getCubeCameras() { return _camGp.get(); } 49 | void addReflectedGraph(osg::Node* graph); 50 | void setCullMask(osg::Node::NodeMask mask); 51 | void installProbeCallback(); 52 | 53 | 54 | osg::ref_ptr _camGp; 55 | osg::Vec3d _pos; 56 | osg::ref_ptr _texture; 57 | osg::ref_ptr _probe; 58 | osg::ref_ptr _debugGeom; 59 | 60 | }; 61 | 62 | 63 | class ProbeManager :public osg::Object 64 | { 65 | public: 66 | META_Object(osgEarth, ProbeManager) 67 | static osg::ref_ptr& instance(); 68 | void addProbe(osg::ref_ptr probe); 69 | osg::ref_ptr createProbe(); 70 | osg::ref_ptr getProbe(int index) const; 71 | 72 | void setTransmissionMap(osg::Texture2D* tex) { transmissionMap = tex; } 73 | osg::Texture2D* getTransmissionMap() { return transmissionMap.get(); } 74 | bool empty() const; 75 | protected: 76 | ProbeManager(){} 77 | ProbeManager(const ProbeManager& rhs, const osg::CopyOp& copyop = osg::CopyOp::DEEP_COPY_ALL) {} 78 | std::vector< osg::ref_ptr> _probes; 79 | osg::ref_ptr< osg::Texture2D> transmissionMap; 80 | 81 | }; 82 | class GenerateProbeUniforms : public osg::NodeVisitor 83 | { 84 | public: 85 | GenerateProbeUniforms(); 86 | 87 | public: // osg::NodeVisitor 88 | virtual void apply(osg::Node& node); 89 | 90 | protected: 91 | std::set _statesets; 92 | 93 | std::function _probeCallback; 94 | 95 | template bool alreadyInstalled(osg::Callback* cb) const { 96 | return !cb ? false : dynamic_cast(cb) != 0L ? true : alreadyInstalled(cb->getNestedCallback()); 97 | } 98 | }; 99 | 100 | class TransparentCamera : public osg::Node 101 | { 102 | 103 | public: 104 | using Ptr = osg::ref_ptr; 105 | //! Construct a new picker 106 | TransparentCamera(); 107 | 108 | //! View within which to pick 109 | void setView(osgViewer::View* view); 110 | osgViewer::View* getView() const { return _view.get(); } 111 | 112 | //! Scene graph from which to pick 113 | void setGraph(osg::Node*); 114 | osg::Node* getGraph() const { return _graph.get(); } 115 | 116 | public: // for debugging 117 | 118 | /** For debugging only - creates (if nec.) and returns a texture that captures 119 | the RTT image so you can display it. */ 120 | osg::Texture2D* getOrCreateTexture(); 121 | 122 | public: // osg::Node 123 | void traverse(osg::NodeVisitor&) override; 124 | 125 | protected: 126 | 127 | /** dtor */ 128 | virtual ~TransparentCamera(); 129 | 130 | osg::observer_ptr _view; 131 | osg::ref_ptr _pickImage; 132 | osg::ref_ptr _rtt; 133 | osg::ref_ptr _graph; 134 | osg::ref_ptr _debugTex; 135 | 136 | 137 | void setupRTT(osgViewer::View*); 138 | 139 | int _rttSize; // size of the RTT image (pixels per side) 140 | int _buffer; // buffer around pick point to check (pixels) 141 | 142 | }; -------------------------------------------------------------------------------- /OE_PBR/Shader/BRDF.glsl: -------------------------------------------------------------------------------- 1 | float saturate(float v) 2 | { 3 | return max(v,0.0f); 4 | } 5 | 6 | float pow2(float v) 7 | { 8 | return v * v; 9 | } 10 | 11 | vec4 SRGBtoLINEAR(vec4 srgbIn) 12 | { 13 | vec3 linOut = pow(srgbIn.xyz, vec3(2.2f)); 14 | return vec4(linOut, srgbIn.w); 15 | } 16 | 17 | vec4 LINEARtoSRGB(vec4 srgbIn) 18 | { 19 | vec3 linOut = pow(srgbIn.xyz, vec3(1.0 / 2.2f)); 20 | return vec4(linOut, srgbIn.w); 21 | } 22 | 23 | 24 | vec3 fresnel_GGX(float VdotH, vec3 f0) 25 | { 26 | return f0 + (1.0 - f0) * pow(1.0 - VdotH, 5); 27 | } 28 | 29 | vec3 fresnel_Epic(float VdotH, vec3 f0) 30 | { 31 | return f0 + (1 - f0) * exp2((-5.55473 * VdotH - 6.98316) * VdotH); 32 | } 33 | 34 | vec3 fresnelSchlickRoughness(float cosTheta, vec3 F0, float roughness) 35 | { 36 | return F0 + (max(vec3(1.0 - roughness), F0) - F0) * pow(clamp(1.0 - cosTheta, 0.0, 1.0), 5.0); 37 | } 38 | 39 | 40 | float microfacetDistribution(float NdotH, float roughness) 41 | { 42 | float roughness2 = roughness * roughness; 43 | float f = NdotH * NdotH * (roughness2 - 1) + 1.0; 44 | return roughness2 / (PI * f * f); 45 | } 46 | 47 | float geometricOcclusion(float NdotL, float NdotV, float roughness) 48 | { 49 | // End result of remapping: 50 | float k = pow(roughness + 1, 2) / 8.0f; 51 | float attenuationV = NdotV / (NdotV * (1 - k) + k); 52 | float attenuationL = NdotL / (NdotL * (1 - k) + k); 53 | return attenuationL * attenuationV; 54 | } 55 | 56 | 57 | 58 | vec3 CookTorranceSpecular(float VdotH, float NdotH, float NdotL, float NdotV, 59 | float roughness, float metalness, vec3 f0, out vec3 kS) 60 | { 61 | 62 | float D = microfacetDistribution(NdotH, roughness); 63 | vec3 F = fresnel_Epic(VdotH, f0); 64 | float G = geometricOcclusion(NdotL, NdotV, roughness); 65 | return (D * F * G) / (4 * max(NdotV * NdotL, 0.01f)); 66 | } 67 | 68 | 69 | 70 | vec2 DFGApprox( const in vec3 normal, const in vec3 viewDir, const in float roughness ) { 71 | 72 | float dotNV = saturate( dot( normal, viewDir ) ); 73 | const vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 ); 74 | const vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 ); 75 | vec4 r = roughness * c0 + c1; 76 | float a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y; 77 | vec2 fab = vec2( - 1.04, 1.04 ) * a004 + r.zw; 78 | return fab; 79 | 80 | } 81 | 82 | vec3 EnvironmentBRDF( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness ) 83 | { 84 | vec2 fab = DFGApprox( normal, viewDir, roughness ); 85 | return specularColor * fab.x + specularF90 * fab.y; 86 | } 87 | 88 | vec3 BRDF_Diffuse_Lambert(vec3 albedo) 89 | { 90 | return albedo / PI; 91 | } 92 | 93 | vec3 BRDF_Diffuse_Disney(float VdotH, float NdotL, float NdotV, 94 | float roughness, vec3 diffuseColor) 95 | { 96 | float Fd90 = 0.5 + 2.0 * roughness * VdotH * VdotH; 97 | vec3 f0 = vec3(0.1f, 0.1f, 0.1f); 98 | vec3 invF0 = vec3(1.0, 1.0, 1.0) - f0; 99 | float dim = min(invF0.r, min(invF0.g, invF0.b)); 100 | float result = ((1.0 + (Fd90 - 1.0) * pow(1.0 - NdotL, 5.0)) * (1.0 + (Fd90 - 1.0) * pow(1.0 - NdotV, 5.0))) * dim; 101 | return diffuseColor * result; 102 | } 103 | 104 | vec3 BRDF_Diffuse_Burley(float VdotH, float NdotL, float NdotV, 105 | float roughness, vec3 diffuseColor) 106 | { 107 | float energyBias = mix(roughness, 0.0, 0.5); // 0.5 108 | float energyFactor = mix(roughness, 1.0, 1.0 / 1.51); // 1/3.1415 109 | float fd90 = energyBias + 2.0 * VdotH * VdotH * roughness; 110 | float f0 = 1.0; 111 | float lightScatter = f0 + (fd90 - f0) * pow(1.0 - NdotL, 5.0); 112 | float viewScatter = f0 + (fd90 - f0) * pow(1.0 - NdotV, 5.0); 113 | float result = lightScatter * viewScatter * energyFactor; 114 | return diffuseColor * result; 115 | } 116 | 117 | vec3 BRDF_GGX( 118 | vec3 direction, 119 | vec3 viewDir, 120 | vec3 normal, 121 | float roughness, 122 | float metalness, 123 | vec3 f0 124 | ) 125 | { 126 | vec3 h = normalize(direction + viewDir); 127 | 128 | float NdotL = max(dot(normal, direction), 0.0f); 129 | float VdotH = max(dot(h, viewDir), 0.0f); 130 | float NdotH = max(dot(normal, h), 0.0f); 131 | float NdotV = max(dot(normal, viewDir), 0.0f); 132 | 133 | float D = microfacetDistribution(NdotH, roughness); 134 | vec3 F = fresnel_Epic(VdotH, f0); 135 | float G = geometricOcclusion(NdotL, NdotV, roughness); 136 | 137 | vec3 numerator = D * G * F; 138 | float denominator = 4.0 * NdotV * NdotL; 139 | vec3 specContrib = numerator / max(denominator, 0.001); 140 | return specContrib; 141 | } 142 | 143 | #ifdef USE_SHEEN 144 | 145 | 146 | float D_Charlie( float roughness, float dotNH ) { 147 | 148 | float alpha = roughness * roughness; 149 | 150 | // Estevez and Kulla 2017, "Production Friendly Microfacet Sheen BRDF" 151 | float invAlpha = 1.0 / alpha; 152 | float cos2h = dotNH * dotNH; 153 | float sin2h = max( 1.0 - cos2h, 0.0078125 ); // 2^(-14/2), so sin2h^2 > 0 in fp16 154 | 155 | return ( 2.0 + invAlpha ) * pow( sin2h, invAlpha * 0.5 ) / ( 2.0 * PI ); 156 | 157 | } 158 | 159 | float V_Neubelt( float dotNV, float dotNL ) 160 | { 161 | // Neubelt and Pettineo 2013, "Crafting a Next-gen Material Pipeline for The Order: 1886" 162 | return saturate( 1.0 / ( 4.0 * ( dotNL + dotNV - dotNL * dotNV ) ) ); 163 | 164 | } 165 | 166 | vec3 BRDF_Sheen( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, vec3 sheenColor, const in float sheenRoughness ) 167 | { 168 | vec3 halfDir = normalize( lightDir + viewDir ); 169 | 170 | float dotNL = saturate( dot( normal, lightDir ) ); 171 | float dotNV = saturate( dot( normal, viewDir ) ); 172 | float dotNH = saturate( dot( normal, halfDir ) ); 173 | 174 | float D = D_Charlie( sheenRoughness, dotNH ); 175 | float V = V_Neubelt( dotNV, dotNL ); 176 | 177 | return sheenColor * ( D * V ); 178 | } 179 | 180 | float IBLSheenBRDF( const in vec3 normal, const in vec3 viewDir, const in float roughness ) 181 | { 182 | 183 | float dotNV = saturate( dot( normal, viewDir ) ); 184 | float r2 = roughness * roughness; 185 | float a = roughness < 0.25 ? -339.2 * r2 + 161.4 * roughness - 25.9 : -8.48 * r2 + 14.3 * roughness - 9.95; 186 | float b = roughness < 0.25 ? 44.0 * r2 - 23.7 * roughness + 3.26 : 1.97 * r2 - 3.27 * roughness + 0.72; 187 | float DG = exp( a * dotNV + b ) + ( roughness < 0.25 ? 0.0 : 0.1 * ( roughness - 0.25 ) ); 188 | return saturate( DG * RECIPROCAL_PI ); 189 | 190 | } 191 | 192 | #endif -------------------------------------------------------------------------------- /OE_PBR/Shader/IBLFunc.glsl: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | float DistributionGGX(vec3 N, vec3 H, float roughness) 3 | { 4 | float a = roughness*roughness; 5 | float a2 = a*a; 6 | float NdotH = max(dot(N, H), 0.0); 7 | float NdotH2 = NdotH*NdotH; 8 | 9 | float nom = a2; 10 | float denom = (NdotH2 * (a2 - 1.0) + 1.0); 11 | denom = PI * denom * denom; 12 | 13 | return nom / denom; 14 | } 15 | 16 | float specularD(float roughness, float NoH) 17 | { 18 | float r2 = roughness * roughness; 19 | float NoH2 = NoH * NoH; 20 | // float a = 1.0/(3.14159*r2*pow(NoH, 4)); 21 | // float b = exp((NoH2 - 1) / r2 * NoH2); 22 | // return a * b; 23 | 24 | return r2 / pow(NoH2 * (r2 - 1.0) + 1.0, 2.0); 25 | } 26 | 27 | // ---------------------------------------------------------------------------- 28 | // http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html 29 | // efficient VanDerCorpus calculation. 30 | float RadicalInverse_VdC(uint bits) 31 | { 32 | bits = (bits << 16u) | (bits >> 16u); 33 | bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); 34 | bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); 35 | bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); 36 | bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); 37 | return float(bits) * 2.3283064365386963e-10; // / 0x100000000 38 | } 39 | // ---------------------------------------------------------------------------- 40 | vec2 Hammersley(uint i, uint N) 41 | { 42 | return vec2(float(i)/float(N), RadicalInverse_VdC(i)); 43 | } 44 | // ---------------------------------------------------------------------------- 45 | vec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness) 46 | { 47 | float a = roughness*roughness; 48 | 49 | float phi = 2.0 * PI * Xi.x; 50 | float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a*a - 1.0) * Xi.y)); 51 | float sinTheta = sqrt(1.0 - cosTheta*cosTheta); 52 | 53 | // from spherical coordinates to cartesian coordinates - halfway vector 54 | vec3 H; 55 | H.x = cos(phi) * sinTheta; 56 | H.y = sin(phi) * sinTheta; 57 | H.z = cosTheta; 58 | 59 | // from tangent-space H vector to world-space sample vector 60 | vec3 up = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0); 61 | vec3 tangent = normalize(cross(up, N)); 62 | vec3 bitangent = cross(N, tangent); 63 | 64 | vec3 sampleVec = tangent * H.x + bitangent * H.y + N * H.z; 65 | return normalize(sampleVec); 66 | } 67 | 68 | 69 | 70 | float GeometrySchlickGGX(float NdotV, float roughness) 71 | { 72 | // note that we use a different k for IBL 73 | float a = roughness; 74 | float k = (a * a) / 2.0; 75 | 76 | float nom = NdotV; 77 | float denom = NdotV * (1.0 - k) + k; 78 | 79 | return nom / denom; 80 | } 81 | float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness) 82 | { 83 | float NdotV = max(dot(N, V), 0.0); 84 | float NdotL = max(dot(N, L), 0.0); 85 | float ggx2 = GeometrySchlickGGX(NdotV, roughness); 86 | float ggx1 = GeometrySchlickGGX(NdotL, roughness); 87 | 88 | return ggx1 * ggx2; 89 | } 90 | -------------------------------------------------------------------------------- /OE_PBR/Shader/IBLIrridianceMap.glsl: -------------------------------------------------------------------------------- 1 | #pragma vp_function vs, vertex_model 2 | out vec3 WorldPos; 3 | void vs(inout vec4 vertex) { 4 | WorldPos = normalize(vertex.xyz); 5 | } 6 | [break] 7 | 8 | #pragma vp_function fs, fragment_output 9 | in vec3 WorldPos; 10 | out vec4 FragColor; 11 | #define PI 3.14159265359f 12 | uniform samplerCube environmentMap; 13 | void fs(inout vec4 c) { 14 | vec3 N = normalize(WorldPos); 15 | 16 | vec3 irradiance = vec3(0.0); 17 | 18 | // tangent space calculation from origin point 19 | vec3 up = vec3(0.0, 1.0, 0.0); 20 | vec3 right = normalize(cross(up, N)); 21 | up = normalize(cross(N, right)); 22 | 23 | float sampleDelta = 0.025; 24 | float nrSamples = 0.0f; 25 | for(float phi = 0.0; phi < 2.0 * PI; phi += sampleDelta) 26 | { 27 | for(float theta = 0.0; theta < 0.5 * PI; theta += sampleDelta) 28 | { 29 | // spherical to cartesian (in tangent space) 30 | vec3 tangentSample = vec3(sin(theta) * cos(phi), sin(theta) * sin(phi), cos(theta)); 31 | // tangent space to world 32 | vec3 sampleVec = tangentSample.x * right + tangentSample.y * up + tangentSample.z * N; 33 | 34 | irradiance += texture(environmentMap, sampleVec).rgb * cos(theta) * sin(theta); 35 | nrSamples++; 36 | } 37 | } 38 | irradiance = PI * irradiance * (1.0 / float(nrSamples)); 39 | 40 | FragColor = vec4(irradiance, 1.0); 41 | } -------------------------------------------------------------------------------- /OE_PBR/Shader/IBLPrefilterMap.glsl: -------------------------------------------------------------------------------- 1 | 2 | 3 | #pragma vp_function vs, vertex_model 4 | out vec3 WorldPos; 5 | void vs(inout vec4 vertex) { 6 | WorldPos = normalize(vertex.xyz); 7 | } 8 | [break] 9 | 10 | 11 | 12 | #pragma vp_function fs, fragment_output 13 | 14 | out vec4 FragColor; 15 | in vec3 WorldPos; 16 | #define PI 3.14159265359f 17 | uniform samplerCube environmentMap; 18 | uniform float roughness; 19 | #pragma include IBLFunc.glsl 20 | 21 | 22 | 23 | void fs(inout vec4 c) { 24 | vec3 N = normalize(WorldPos.xyz); 25 | 26 | // make the simplifying assumption that V equals R equals the normal 27 | vec3 R = N; 28 | vec3 V = R; 29 | 30 | const uint SAMPLE_COUNT = 1024u; 31 | vec3 prefilteredColor = vec3(0.0); 32 | float totalWeight = 0.0; 33 | 34 | for(uint i = 0u; i < SAMPLE_COUNT; ++i) 35 | { 36 | // generates a sample vector that's biased towards the preferred alignment direction (importance sampling). 37 | vec2 Xi = Hammersley(i, SAMPLE_COUNT); 38 | vec3 H = ImportanceSampleGGX(Xi, N, roughness); 39 | vec3 L = normalize(2.0 * dot(V, H) * H - V); 40 | 41 | float NdotL = max(dot(N, L), 0.0); 42 | if(NdotL > 0.0) 43 | { 44 | // sample from the environment's mip level based on roughness/pdf 45 | float D = DistributionGGX(N, H, roughness); 46 | float NdotH = max(dot(N, H), 0.0); 47 | float HdotV = max(dot(H, V), 0.0); 48 | float pdf = D * NdotH / (4.0 * HdotV) + 0.0001; 49 | 50 | float resolution = 512.0; // resolution of source cubemap (per face) 51 | float saTexel = 4.0 * PI / (6.0 * resolution * resolution); 52 | float saSample = 1.0 / (float(SAMPLE_COUNT) * pdf + 0.0001); 53 | 54 | float mipLevel = roughness == 0.0 ? 0.0 : 0.5 * log2(saSample / saTexel); 55 | 56 | prefilteredColor += textureLod(environmentMap, L, mipLevel).rgb * NdotL; 57 | totalWeight += NdotL; 58 | } 59 | } 60 | 61 | prefilteredColor = prefilteredColor / totalWeight; 62 | 63 | FragColor = vec4(prefilteredColor, 1.0); 64 | } -------------------------------------------------------------------------------- /OE_PBR/Shader/IBLSphericalSample.glsl: -------------------------------------------------------------------------------- 1 | 2 | 3 | #pragma vp_function SampleSphericalMap, vertex_model 4 | const vec2 invAtan = vec2(0.1591, 0.3183); 5 | out vec2 spherical_uv; 6 | void SampleSphericalMap(inout vec4 vertex) { 7 | vec3 tmp = normalize(vertex.xyz); 8 | 9 | vec2 uv = vec2(atan(tmp.z, tmp.x), asin(tmp.y)); 10 | uv *= invAtan; 11 | uv += 0.5; 12 | spherical_uv = uv; 13 | } 14 | 15 | [break] 16 | 17 | #pragma vp_function fs, fragment_output 18 | in vec2 spherical_uv; 19 | out vec4 frag; 20 | uniform sampler2D tex; 21 | void fs(inout vec4 c) { 22 | c = texture(tex, spherical_uv); 23 | frag = c; 24 | } -------------------------------------------------------------------------------- /OE_PBR/Shader/IBLbrdfLUT.glsl: -------------------------------------------------------------------------------- 1 | #pragma vp_function vs, vertex_model 2 | out vec2 TexCoords; 3 | void vs(inout vec4 vertex) { 4 | TexCoords = gl_MultiTexCoord0.xy; 5 | } 6 | [break] 7 | 8 | #pragma vp_function fs, fragment_output 9 | out vec4 FragColor; 10 | in vec2 TexCoords; 11 | #define PI 3.14159265359f 12 | #pragma include IBLFunc.glsl 13 | 14 | 15 | 16 | vec2 IntegrateBRDF(float NdotV, float roughness) 17 | { 18 | vec3 V; 19 | V.x = sqrt(1.0 - NdotV*NdotV); 20 | V.y = 0.0; 21 | V.z = NdotV; 22 | 23 | float A = 0.0; 24 | float B = 0.0; 25 | 26 | vec3 N = vec3(0.0, 0.0, 1.0); 27 | 28 | const uint SAMPLE_COUNT = 1024u; 29 | for(uint i = 0u; i < SAMPLE_COUNT; ++i) 30 | { 31 | // generates a sample vector that's biased towards the 32 | // preferred alignment direction (importance sampling). 33 | vec2 Xi = Hammersley(i, SAMPLE_COUNT); 34 | vec3 H = ImportanceSampleGGX(Xi, N, roughness); 35 | vec3 L = normalize(2.0 * dot(V, H) * H - V); 36 | 37 | float NdotL = max(L.z, 0.0); 38 | float NdotH = max(H.z, 0.0); 39 | float VdotH = max(dot(V, H), 0.0); 40 | 41 | if(NdotL > 0.0) 42 | { 43 | float G = GeometrySmith(N, V, L, roughness); 44 | float G_Vis = (G * VdotH) / (NdotH * NdotV); 45 | float Fc = pow(1.0 - VdotH, 5.0); 46 | 47 | A += (1.0 - Fc) * G_Vis; 48 | B += Fc * G_Vis; 49 | } 50 | } 51 | A /= float(SAMPLE_COUNT); 52 | B /= float(SAMPLE_COUNT); 53 | return vec2(A, B); 54 | } 55 | 56 | void fs(inout vec4 c) { 57 | vec2 integratedBRDF = IntegrateBRDF(TexCoords.x, TexCoords.y); 58 | FragColor = vec4(integratedBRDF,0.0,1.0); 59 | } 60 | -------------------------------------------------------------------------------- /OE_PBR/Shader/cube_to_quad.glsl: -------------------------------------------------------------------------------- 1 | #pragma vp_function vs, vertex_model 2 | out vec3 WorldPos; 3 | out vec2 TexCoords; 4 | void vs(inout vec4 vertex) { 5 | WorldPos = normalize(vertex.xyz); 6 | TexCoords = gl_MultiTexCoord0.xy; 7 | } 8 | [break] 9 | 10 | #pragma vp_function fs, fragment_output 11 | out vec4 frag; 12 | in vec3 WorldPos; 13 | in vec2 TexCoords; 14 | uniform samplerCube IrradianceMap; 15 | 16 | uniform float mipLevel; 17 | uniform int colorMap; 18 | 19 | const vec2 Atan = vec2(6.28318, 3.14159); 20 | vec3 invSphericalUV(vec2 v) 21 | { 22 | vec2 uv = (v - vec2(0.5)) * Atan; float cosT = cos(uv.y); 23 | return vec3(cosT * cos(uv.x), sin(uv.y), cosT * sin(uv.x)); 24 | } 25 | 26 | void fs(inout vec4 c) { 27 | 28 | vec3 N = normalize(invSphericalUV(TexCoords.xy)); 29 | // vec3 N = invSphericalUV(TexCoords.xy); 30 | // N = normalize(vec3(-N.x,N.y,N.z)); 31 | // vec3 up = vec3(0.0, 1.0, 0.0); 32 | // vec3 right = cross(up, N); up = cross(N, right); // tangent space calculation 33 | 34 | // vec3 sampleVec = tangentVec.x * right + tangentVec.y * up + tangentVec.z * N; 35 | vec3 irradiance = textureLod(IrradianceMap, N, mipLevel).rgb; 36 | c = vec4(irradiance, 1.0f); 37 | frag = c; 38 | } 39 | -------------------------------------------------------------------------------- /OE_PBR/Shader/ibl_irradiance_quad.glsl: -------------------------------------------------------------------------------- 1 | #pragma vp_function vs, vertex_model 2 | out vec3 WorldPos; 3 | out vec2 TexCoords; 4 | out vec3 Normal; 5 | void vs(inout vec4 vertex) { 6 | WorldPos = normalize(vertex.xyz); 7 | TexCoords = gl_MultiTexCoord0.xy; 8 | Normal = normalize(gl_Normal); 9 | } 10 | [break] 11 | 12 | #pragma vp_function fs, fragment_output 13 | in vec3 WorldPos; 14 | in vec2 TexCoords; 15 | in vec3 Normal; 16 | out vec4 FragColor; 17 | #define PI 3.14159265359f 18 | uniform sampler2D environmentMap; 19 | 20 | 21 | const vec2 invAtan = vec2(0.1591, 0.3183); 22 | vec2 sphericalUV(vec3 v) 23 | { 24 | vec2 uv = vec2(atan(v.z, v.x), asin(v.y)); 25 | uv *= invAtan; uv += vec2(0.5); return uv; 26 | } 27 | 28 | const vec2 Atan = vec2(6.28318, 3.14159); 29 | vec3 invSphericalUV(vec2 v) 30 | { 31 | vec2 uv = (v - vec2(0.5)) * Atan; float cosT = cos(uv.y); 32 | return vec3(cosT * cos(uv.x), sin(uv.y), cosT * sin(uv.x)); 33 | } 34 | 35 | vec3 ImportanceSampleGGX 36 | void fs(inout vec4 c) { 37 | vec3 N = normalize(WorldPos.xyz); 38 | 39 | vec3 irradiance = vec3(0.0); 40 | 41 | // tangent space calculation from origin point 42 | vec3 up = vec3(0.0, 1.0, 0.0); 43 | vec3 right = normalize(cross(up, N)); 44 | up = normalize(cross(N, right)); 45 | 46 | float sampleDelta = 0.025; 47 | float nrSamples = 0.0f; 48 | for(float phi = 0.0; phi < 2.0 * PI; phi += sampleDelta) 49 | { 50 | // for(float theta = 0.0; theta < 0.5 * PI; theta += sampleDelta) 51 | // { 52 | float theta = 0.25*PI; 53 | // spherical to cartesian (in tangent space) 54 | vec3 tangentSample = vec3(sin(theta) * cos(phi), sin(theta) * sin(phi), cos(theta)); 55 | // tangent space to world 56 | vec3 sampleVec = tangentSample.x * right + tangentSample.y * up + tangentSample.z * N; 57 | 58 | irradiance += texture(environmentMap, sphericalUV(sampleVec)).rgb * cos(theta) * sin(theta); 59 | nrSamples++; 60 | //} 61 | } 62 | irradiance = PI * irradiance * (1.0 / float(nrSamples)); 63 | // float phi = PI; 64 | // float theta = 0.25 * PI; 65 | // vec3 tangentSample = vec3(sin(theta) * cos(phi), sin(theta) * sin(phi), cos(theta)); 66 | // // tangent space to world 67 | // vec3 sampleVec = tangentSample.x * right + tangentSample.y * up + tangentSample.z * N; 68 | 69 | // irradiance += texture(environmentMap, sphericalUV(sampleVec)).rgb * cos(theta) * sin(theta); 70 | 71 | 72 | FragColor = vec4(irradiance, 1.0); 73 | } -------------------------------------------------------------------------------- /OE_PBR/Shader/ibl_radiance_quad.glsl: -------------------------------------------------------------------------------- 1 | 2 | 3 | #pragma vp_function vs, vertex_model 4 | out vec3 WorldPos; 5 | void vs(inout vec4 vertex) { 6 | WorldPos = normalize(vertex.xyz); 7 | } 8 | [break] 9 | 10 | 11 | 12 | #pragma vp_function fs, fragment_output 13 | 14 | out vec4 FragColor; 15 | in vec3 WorldPos; 16 | #define PI 3.14159265359f 17 | uniform sampler2D environmentMap; 18 | // uniform float roughness; 19 | // uniform int ngt; 20 | #pragma include IBLFunc.glsl 21 | 22 | const vec2 invAtan = vec2(0.1591, 0.3183); 23 | 24 | const uint ConvolutionSampleCount = 1024u; 25 | const uint ConvolutionMaxSamples = 1024u; 26 | 27 | vec2 sphericalUV(vec3 v) 28 | { 29 | vec2 uv = vec2(atan(v.z, v.x), asin(v.y)); 30 | uv *= invAtan; uv += vec2(0.5); return uv; 31 | } 32 | 33 | const vec2 Atan = vec2(6.28318, 3.14159); 34 | vec3 invSphericalUV(vec2 v) 35 | { 36 | vec2 uv = (v - vec2(0.5)) * Atan; float cosT = cos(uv.y); 37 | return vec3(cosT * cos(uv.x), sin(uv.y), cosT * sin(uv.x)); 38 | } 39 | 40 | 41 | 42 | 43 | void 44 | sumSpecular (vec3 hdrPixel, float NoL, inout vec4 result) 45 | { 46 | result.xyz += (hdrPixel * NoL); 47 | result.w += NoL; 48 | } 49 | 50 | 51 | vec3 ImportanceSample (vec3 R ) 52 | { 53 | vec3 N = R; 54 | vec3 V = R; 55 | vec4 result = vec4(0,0,0,0); 56 | 57 | 58 | float ConvolutionRoughness = 5.5; 59 | float ConvolutionSamplesOffset = 0.0; 60 | 61 | uint SampleStep = uint(ConvolutionMaxSamples / ConvolutionSampleCount); 62 | uint sampleId = uint(ConvolutionSamplesOffset); 63 | 64 | const uint cubeWidth = 512u; 65 | 66 | 67 | for(uint i = 0; i < ConvolutionSampleCount; i++ ) 68 | { 69 | vec2 Xi = Hammersley(sampleId, ConvolutionMaxSamples); 70 | 71 | vec3 H = ImportanceSampleGGX( Xi, N, ConvolutionRoughness); 72 | vec3 L = 2 * dot( V, H ) * H - V; 73 | float NoL = max(dot( N, L ), 0.0); 74 | float VoL = max (dot(V, L), 0.0); 75 | float NoH = max(dot( N, H ), 0.0); 76 | float VoH = max(dot( V, H ), 0.0); 77 | if( NoL > 0.0 ) 78 | { 79 | // 80 | // Compute pdf of BRDF 81 | // Taken from Epic's Siggraph 2013 Lecture: 82 | // http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf 83 | // 84 | float Dh = specularD(ConvolutionRoughness, NoH); 85 | float pdf = Dh * NoH / (4*VoH); 86 | float solidAngleTexel = 4 * PI / (6 * cubeWidth * cubeWidth); 87 | float solidAngleSample = 1.0 / (ConvolutionSampleCount * pdf); 88 | float lod = ConvolutionRoughness == 0.0 ? 0.0 : 0.5 * log2(float(solidAngleSample/solidAngleTexel)); 89 | 90 | //vec3 hdrPixel = rescaleHDR(ConvolutionSrc.SampleLevel(EnvMapSampler, L, lod).rgb); 91 | vec3 hdrPixel = textureLod(environmentMap, sphericalUV(L), 4.0).rgb; 92 | 93 | sumSpecular(hdrPixel, 0.5, result); 94 | } 95 | sampleId += SampleStep; 96 | } 97 | 98 | if (result.w == 0.0) 99 | return result.xyz; 100 | else 101 | return (result.xyz / result.w); 102 | } 103 | 104 | void fs(inout vec4 c) { 105 | 106 | vec3 N = normalize(WorldPos.xyz); 107 | vec3 prefilteredColor = ImportanceSample(N); 108 | 109 | FragColor = vec4(prefilteredColor, 1.0); 110 | } 111 | 112 | // void fs(inout vec4 c) { 113 | // vec3 N = normalize(WorldPos.xyz); 114 | // float roughness = 0.0f; 115 | 116 | 117 | // // make the simplifying assumption that V equals R equals the normal 118 | // vec3 R = N; 119 | // vec3 V = R; 120 | 121 | // const uint SAMPLE_COUNT = 1024u; 122 | // vec3 prefilteredColor = vec3(0.0); 123 | // float totalWeight = 0.0; 124 | 125 | // for(uint i = 0u; i < SAMPLE_COUNT; ++i) 126 | // { 127 | // // generates a sample vector that's biased towards the preferred alignment direction (importance sampling). 128 | // vec2 Xi = Hammersley(i, SAMPLE_COUNT); 129 | // vec3 H = ImportanceSampleGGX(Xi, N, roughness); 130 | // vec3 L = normalize(2.0 * dot(V, H) * H - V); 131 | 132 | // float NdotL = max(dot(N, L), 0.0); 133 | // if(NdotL > 0.0) 134 | // { 135 | // // sample from the environment's mip level based on roughness/pdf 136 | // float D = DistributionGGX(N, H, roughness); 137 | // float NdotH = max(dot(N, H), 0.0); 138 | // float HdotV = max(dot(H, V), 0.0); 139 | // float pdf = D * NdotH / (4.0 * HdotV) + 0.0001; 140 | 141 | // float resolution = 512.0; // resolution of source cubemap (per face) 142 | // float saTexel = 4.0 * PI / (6.0 * resolution * resolution); 143 | // float saSample = 1.0 / (float(SAMPLE_COUNT) * pdf + 0.0001); 144 | 145 | // float mipLevel = roughness == 0.0 ? 0.0 : 0.5 * log2(saSample / saTexel); 146 | 147 | // prefilteredColor += textureLod(environmentMap, sphericalUV(L), 0.5).rgb * NdotL; 148 | // totalWeight += NdotL; 149 | // } 150 | // } 151 | 152 | // prefilteredColor = prefilteredColor / totalWeight; 153 | 154 | // FragColor = vec4(prefilteredColor, 1.0); 155 | // } 156 | 157 | 158 | 159 | 160 | 161 | -------------------------------------------------------------------------------- /OE_PBR/Shader/light_functions.glsl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | #pragma include struct.glsl 5 | // https://www.unrealengine.com/blog/physically-based-shading-on-mobile 6 | 7 | 8 | vec3 F_Schlick( const in vec3 f0, const in float f90, const in float dotVH ) { 9 | 10 | float fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH ); 11 | return f0 * ( 1.0 - fresnel ) + ( f90 * fresnel ); 12 | 13 | } // validated 14 | 15 | void computeMultiscattering( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, \ 16 | const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) { 17 | 18 | vec2 fab = DFGApprox( normal, viewDir, roughness ); 19 | 20 | vec3 Fr = specularColor; 21 | 22 | vec3 FssEss = Fr * fab.x + specularF90 * fab.y; 23 | 24 | float Ess = fab.x + fab.y; 25 | float Ems = 1.0 - Ess; 26 | 27 | vec3 Favg = Fr + ( 1.0 - Fr ) * 0.047619; // 1/21 28 | vec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg ); 29 | 30 | singleScatter += FssEss; 31 | multiScatter += Fms * Ems; 32 | 33 | } 34 | 35 | const vec2 invAtan = vec2(0.1591, 0.3183); 36 | vec2 sphericalUV(vec3 v) 37 | { 38 | vec2 uv = vec2(atan(v.z, v.x), asin(v.y)); 39 | uv *= invAtan; uv += vec2(0.5); return uv; 40 | } 41 | 42 | #ifdef USE_ENV_MAP 43 | 44 | 45 | #ifdef USE_ENV_CUBE_UV 46 | uniform samplerCube irradianceMap; 47 | uniform samplerCube prefilterMap; 48 | #else 49 | uniform sampler2D irradianceMap; 50 | uniform sampler2D prefilterMap; 51 | #endif 52 | 53 | uniform mat4 osg_ViewMatrixInverse; 54 | vec3 getIBLIrradiance(vec3 normal) 55 | { 56 | // world space 57 | vec3 normalWC = (osg_ViewMatrixInverse * vec4(normal, 0.0)).rgb; 58 | normalWC = normalize(normalWC); 59 | float envMapIntensity = 1.0; 60 | #ifdef USE_ENV_CUBE_UV 61 | vec3 irradiance = texture(irradianceMap, normalWC).rgb; 62 | #else 63 | vec3 irradiance = texture(irradianceMap, sphericalUV(normalWC)).rgb; 64 | #endif 65 | return PI * irradiance * envMapIntensity; 66 | } 67 | 68 | float roughToMip(float _uroughness, float mipLevel) 69 | { 70 | float _umip = 0.0; 71 | if ((_uroughness >= 0.80000001)) 72 | { 73 | (_umip = ((((1.0 - _uroughness) * 1.0) / 0.19999999) + -2.0)); 74 | } 75 | else 76 | { 77 | if ((_uroughness >= 0.40000001)) 78 | { 79 | (_umip = ((((0.80000001 - _uroughness) * 3.0) / 0.40000001) + -1.0)); 80 | } 81 | else 82 | { 83 | if ((_uroughness >= 0.30500001)) 84 | { 85 | (_umip = ((((0.40000001 - _uroughness) * 1.0) / 0.094999999) + 2.0)); 86 | } 87 | else 88 | { 89 | if ((_uroughness >= 0.20999999)) 90 | { 91 | (_umip = ((((0.30500001 - _uroughness) * 1.0) / 0.095000014) + 3.0)); 92 | } 93 | else 94 | { 95 | (_umip = (-2.0 * log2((1.16 * _uroughness)))); 96 | } 97 | } 98 | } 99 | } 100 | return mipLevel -1 - (_umip+2) * mipLevel/11; 101 | 102 | } 103 | 104 | uniform float MAX_REFLECTION_LOD; 105 | vec3 getIBLRadiance(vec3 normal, float roughnessFactor, vec3 viewDir) 106 | { 107 | //const float MAX_REFLECTION_LOD = 9.0; 108 | float envMapIntensity = 1.0; 109 | 110 | vec3 r = reflect(-viewDir, normal); 111 | float lod = MAX_REFLECTION_LOD; 112 | vec3 reflectWC = (osg_ViewMatrixInverse * vec4(r, 0.0)).rgb; 113 | reflectWC = normalize(reflectWC); 114 | float mip = roughToMip(roughnessFactor, MAX_REFLECTION_LOD); 115 | //return vec3(mip/lod); 116 | #ifdef USE_ENV_CUBE_UV 117 | vec3 prefilteredColor = textureLod(prefilterMap, reflectWC, mip).rgb; 118 | #else 119 | vec3 prefilteredColor = textureLod(prefilterMap, sphericalUV(reflectWC), mip).rgb; 120 | #endif 121 | //vec3 F = fresnelSchlickRoughness(max(dot(normal,viewDir), 0.0), vec3(0.04), roughnessFactor); 122 | // vec2 brdf = texture(brdfLUT, vec2(max(dot(normal,viewDir), 0.0), roughnessFactor)).rg; 123 | vec3 radiance = prefilteredColor; 124 | // * (F * brdf.x + brdf.y); 125 | return radiance * envMapIntensity; 126 | } 127 | #endif 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | void RE_Direct_Physical( const in osg_LightSourceParameters directLight, const in GeometricContext geometry, const in vec3 f0, const in pbr_Material material, inout ReflectedLight reflectedLight) { 138 | 139 | vec3 lightDir = normalize(-directLight.spotDirection.xyz); 140 | float dotNL = max(dot(geometry.normal, lightDir),0.0f); 141 | vec3 irradiance = dotNL * vec3(directLight.diffuse); 142 | irradiance *= directLight.spotExponent; 143 | 144 | #ifdef USE_SHEEN 145 | vec3 sheenSpecular = irradiance * BRDF_Sheen( lightDir, geometry.viewDir, geometry.normal, material.sheenColor, material.sheenRoughness ); 146 | reflectedLight.sheenSpecular += sheenSpecular; 147 | #endif 148 | 149 | #ifdef USE_CLEARCOAT 150 | vec3 clearcoatNormal = vec3(1.0,0.0,0.0); 151 | float dotNLcc = saturate( dot( clearcoatNormal, lightDir ) ); 152 | vec3 ccIrradiance = dotNLcc * directLight.diffuse.rgb; 153 | 154 | reflectedLight.clearcoatSpecular += ccIrradiance * BRDF_GGX( lightDir, geometry.viewDir, clearcoatNormal,material.clearcoatRoughness, material.clearcoatF90,material.clearcoatF0 ); 155 | #endif 156 | 157 | 158 | reflectedLight.directSpecular += irradiance * BRDF_GGX(lightDir, geometry.viewDir, geometry.normal, material.roughnessFactor, material.metallicFactor, f0 ); 159 | reflectedLight.directDiffuse += irradiance * BRDF_Diffuse_Lambert( material.baseColorFactor.rgb ); 160 | } 161 | 162 | uniform sampler2D brdfLUT; 163 | void RE_IndirectSpecular_Physical(const in vec3 radiance, const in vec3 irradiance, const in vec3 clearcoatRadiance,const in vec3 f0, 164 | const in GeometricContext geometry, const in pbr_Material material, inout ReflectedLight reflectedLight) 165 | { 166 | 167 | #ifdef USE_SHEEN 168 | 169 | //reflectedLight.sheenSpecular += irradiance * material.sheenColor * IBLSheenBRDF( geometry.normal, geometry.viewDir, material.sheenRoughness ); 170 | 171 | #endif 172 | 173 | #ifdef USE_CLEARCOAT 174 | reflectedLight.clearcoatSpecular += clearcoatRadiance * EnvironmentBRDF(geometry.clearcoatNormal, geometry.viewDir, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness); 175 | #endif 176 | 177 | vec3 singleScattering = vec3( 0.0 ); 178 | vec3 multiScattering = vec3( 0.0 ); 179 | vec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI; 180 | 181 | computeMultiscattering(geometry.normal, geometry.viewDir, material.specularF0, 1.0f, material.roughnessFactor, singleScattering, multiScattering); 182 | 183 | // float NdotV = max(dot( geometry.normal, geometry.viewDir), 0.0); 184 | // vec3 F = fresnelSchlickRoughness(NdotV, material.specularF0, material.roughnessFactor); 185 | // vec2 brdf = texture(brdfLUT, vec2(NdotV, material.roughnessFactor)).rg; 186 | // // mark 0929 187 | // singleScattering = (F * brdf.x + brdf.y); 188 | 189 | 190 | vec3 scattering = singleScattering + multiScattering; 191 | vec3 diffuse = material.baseColorFactor.rgb * ( 1.0 - max( max( scattering.r, scattering.g ), scattering.b ) ); 192 | 193 | reflectedLight.indirectSpecular += singleScattering * radiance; 194 | 195 | reflectedLight.indirectDiffuse += diffuse * cosineWeightedIrradiance; 196 | return; 197 | 198 | } 199 | 200 | void RE_IndirectDiffuse_Physical(vec3 irradiance, vec3 diffuseColor, inout ReflectedLight reflectedLight) 201 | { 202 | //reflectedLight.indirectDiffuse += irradiance * RECIPROCAL_PI * diffuseColor; 203 | return; 204 | } -------------------------------------------------------------------------------- /OE_PBR/Shader/materials/advanced.glsl: -------------------------------------------------------------------------------- 1 | uniform sampler2D sheenColorMap; 2 | uniform sampler2D sheenRoughnessMap; 3 | uniform sampler2D clearcoatMap; 4 | uniform sampler2D clearcoatRoughnessMap; 5 | uniform mat4 osg_ViewMatrix; 6 | uniform mat4 osg_ModelViewMatrix; 7 | uniform mat4 osg_ProjectionMatrix; 8 | 9 | #ifdef USE_SHEEN 10 | 11 | material.sheenColor = oe_pbr.sheenColor; 12 | material.sheenRoughness = oe_pbr.sheenRoughness; 13 | #ifdef USE_SHEENCOLORMAP 14 | material.sheenColor *= texture( sheenColorMap, oe_texcoord ).rgb; 15 | #endif 16 | 17 | material.sheenRoughness = clamp(material.sheenRoughness, 0.07, 1.0 ); 18 | #ifdef USE_SHEENROUGHNESSMAP 19 | material.sheenRoughness *= texture( sheenRoughnessMap, oe_texcoord ).a; 20 | #endif 21 | 22 | #endif 23 | 24 | 25 | 26 | // vec3 dxy = max( abs( dFdx( geometryNormal ) ), abs( dFdy( geometryNormal ) ) ); 27 | // float geometryRoughness = max( max( dxy.x, dxy.y ), dxy.z ); 28 | // 0.0525 corresponds to the base mip of a 256 cubemap. 29 | 30 | #ifdef USE_CLEARCOAT 31 | 32 | material.clearcoat = oe_pbr.clearcoat; 33 | material.clearcoatF0 = vec3( 0.04 ); 34 | material.clearcoatF90 = 1.0; 35 | material.clearcoat = saturate( material.clearcoat ); 36 | float clearcoatRoughness = oe_pbr.clearcoatRoughness; 37 | material.clearcoatRoughness = max( clearcoatRoughness, 0.0525 ); 38 | material.clearcoatRoughness = min( material.clearcoatRoughness, 1.0 ); 39 | geometry.clearcoatNormal = geometry.normal; 40 | 41 | #ifdef USE_CLEARCOATMAP 42 | material.clearcoat *= texture( clearcoatMap, oe_texcoord ).x; 43 | #endif 44 | 45 | #ifdef USE_CLEARCOAT_ROUGHNESSMAP 46 | material.clearcoatRoughness *= texture( clearcoatRoughnessMap, oe_texcoord ).y; 47 | #endif 48 | 49 | material.clearcoat = saturate( material.clearcoat ); // Burley clearcoat model 50 | material.clearcoatRoughness = max( material.clearcoatRoughness, 0.0525 ); 51 | //material.clearcoatRoughness += geometryRoughness; 52 | material.clearcoatRoughness = min( material.clearcoatRoughness, 1.0 ); 53 | 54 | #endif 55 | 56 | 57 | #ifdef USE_TRANSMISSION 58 | 59 | material.transmission = oe_pbr.transmission; 60 | material.transmissionAlpha = oe_pbr.transmissionAlpha; 61 | material.thickness = oe_pbr.thickness; 62 | material.attenuationDistance = oe_pbr.attenuationDistance; 63 | material.attenuationColor = oe_pbr.attenuationColor; 64 | material.ior = max(1.0, oe_pbr.ior); 65 | material.baseColorFactor = vec4(1.0); 66 | 67 | float specularIntensityFactor = 1.0f; 68 | vec3 specularColorFactor = vec3( 1.0 ); 69 | float specularF90 = 1.0; 70 | // override 71 | f0 = mix( min( pow2( ( material.ior - 1.0 ) / ( material.ior + 1.0 ) ) * specularColorFactor, vec3( 1.0 ) ) * specularIntensityFactor, diffuseColor.rgb, vec3(metallic) ); 72 | material.specularF0 = f0; 73 | 74 | #ifdef USE_TRANSMISSIONMAP 75 | 76 | material.transmission *= texture( transmissionMap, oe_texcoord ).r; 77 | 78 | #endif 79 | 80 | #ifdef USE_THICKNESSMAP 81 | 82 | material.thickness *= texture( thicknessMap, oe_texcoord ).g; 83 | 84 | #endif 85 | 86 | mat4 modelMatrix = osg_ViewMatrixInverse * osg_ModelViewMatrix; 87 | 88 | vec4 tmp = modelMatrix * vec4(oe_pos,1.0f); 89 | vec3 pos = tmp.xyz; 90 | vec3 cameraPosition = osg_ViewMatrixInverse[3].xyz; 91 | vec3 viewInWC = normalize( cameraPosition - pos); 92 | vec3 normalInWC = (osg_ViewMatrixInverse * vec4(oe_normal,1.0)).xyz; 93 | 94 | 95 | 96 | vec4 transmission = getIBLVolumeRefraction( 97 | normalInWC, viewInWC, material.roughnessFactor, material.baseColorFactor.xyz, f0, specularF90, 98 | pos.xyz, modelMatrix, osg_ViewMatrix, osg_ProjectionMatrix, material.ior, material.thickness, 99 | material.attenuationColor, material.attenuationDistance, translucentMap); 100 | 101 | material.transmissionAlpha = mix( material.transmissionAlpha, transmission.a, material.transmission ); 102 | 103 | reflectedLight.backLight = transmission.rgb; 104 | 105 | #endif -------------------------------------------------------------------------------- /OE_PBR/Shader/materials/mat_gold.glsl: -------------------------------------------------------------------------------- 1 | 2 | uniform sampler2D T_Metal_Gold_N; 3 | uniform sampler2D T_Metal_Gold_D; 4 | uniform sampler2D T_MacroVariation; 5 | 6 | vec2 uv_1 = oe_texcoord * vec2(0.2134); 7 | vec2 uv_2 = oe_texcoord * vec2(0.05341); 8 | vec2 uv_3 = oe_texcoord * vec2(0.002); 9 | 10 | float color1 = texture(T_MacroVariation, uv_1).r + 0.5; 11 | float color2 = texture(T_MacroVariation, uv_2).r + 0.5; 12 | float color3 = texture(T_MacroVariation, uv_3).r + 0.5; 13 | 14 | float color_r = color1 * color2 * color3; 15 | 16 | vec3 color_m = mix(vec3(0.5),vec3(1.0),color_r); 17 | 18 | vec4 color_d = texture(T_Metal_Gold_D, oe_texcoord).rgba; 19 | color_d = SRGBtoLINEAR(color_d); 20 | 21 | diffuseColor = color_d.rgb * color_m; 22 | metallic *= 1.0; 23 | roughness *= mix(0.3,0.5, color_d.a*color_r); 24 | 25 | -------------------------------------------------------------------------------- /OE_PBR/Shader/materials/metalroughness.glsl: -------------------------------------------------------------------------------- 1 | #pragma import_defines(OE_ENABLE_Metal_MAP) 2 | #pragma import_defines(OE_ENABLE_Roughness_MAP) 3 | #pragma import_defines(OE_ENABLE_Roughness_MAP) 4 | 5 | uniform sampler2D roughnessMap; 6 | uniform sampler2D metalMap; 7 | 8 | 9 | 10 | #ifdef OE_ENABLE_Metal_MAP 11 | vec3 metal = texture(metalMap, oe_texcoord).rgb; 12 | metallic *= metal.x; 13 | #endif 14 | 15 | #ifdef OE_ENABLE_Roughness_MAP 16 | vec3 rough = texture(roughnessMap, oe_texcoord).rgb; 17 | roughness *= rough.x; 18 | #endif 19 | 20 | // f0 = mix(f0, diffuseColor, vec3(metallic)); 21 | // material.metallicFactor=metallic; 22 | // material.roughnessFactor=min(roughness,0.04f); 23 | // material.specularF0 = f0; -------------------------------------------------------------------------------- /OE_PBR/Shader/materials/standard.glsl: -------------------------------------------------------------------------------- 1 | 2 | 3 | #ifdef cascade 4 | #ifdef OE_ENABLE_MR_MAP 5 | vec3 tmp = texture(pbrMaps, vec3(oe_texcoord,OE_ENABLE_MR_MAP)).rgb; 6 | metallic = tmp.b; 7 | roughness = tmp.g; 8 | #endif 9 | 10 | #ifdef OE_ENABLE_BASECOLOR_MAP 11 | diffuseColor = texture(pbrMaps, vec3(oe_texcoord,OE_ENABLE_BASECOLOR_MAP)).rgb; 12 | #endif 13 | 14 | #ifdef OE_ENABLE_NORMAL_MAP 15 | 16 | vec3 tangent = vec3(1.0,0.0,0.0) * gl_NormalMatrix; 17 | vec3 mapN = texture(pbrMaps, vec3(oe_texcoord,OE_ENABLE_NORMAL_MAP)).rgb; // normal in tangent space 18 | //vec3 normal = geometry.normal; 19 | normal = getNormal(normal, mapN); 20 | 21 | #endif 22 | 23 | #ifdef OE_ENABLE_AO_MAP 24 | vec3 aoFromMap = texture(pbrMaps, vec3(oe_texcoord,OE_ENABLE_AO_MAP)).rgb; 25 | 26 | #endif 27 | 28 | #ifdef OE_ENABLE_EMISSIVE_MAP 29 | vec3 emissiveFromMap = texture(pbrMaps, vec3(oe_texcoord,OE_ENABLE_EMISSIVE_MAP)).rgb; 30 | emissive *= emissiveFromMap; 31 | #endif 32 | #endif 33 | 34 | 35 | -------------------------------------------------------------------------------- /OE_PBR/Shader/materials/water_ocean.glsl: -------------------------------------------------------------------------------- 1 | uniform float osg_FrameTime; 2 | uniform sampler2D water_N; 3 | uniform sampler2D water_M; 4 | uniform sampler2D perlin_Noise; 5 | 6 | 7 | // calc normal 8 | 9 | //vec3 normal = geometry.normal; 10 | const float noiseSpeed = 0.4; 11 | // large wave 12 | float time = sin(oe_pos.x/150.f + osg_FrameTime * noiseSpeed); 13 | 14 | vec2 uv_sin = vec2(0.18f,0.15f) + time * vec2(-0.06f, -0.04f); 15 | vec2 uv_color = vec2(0.75f) + osg_FrameTime *vec2(-0.07f); 16 | vec2 uv_normal = vec2(0.05f, 0.08f) + osg_FrameTime *vec2(-0.03f, -0.02f); 17 | uv_sin = fract(oe_texcoord + uv_sin); 18 | uv_color = fract(oe_texcoord + uv_color); 19 | uv_normal = fract(oe_texcoord + uv_normal); 20 | 21 | vec3 baseNormal = texture(water_N, uv_normal).rgb; 22 | vec3 additionalNormal = texture(water_N, uv_sin).rgb * vec3(-1,1,-1); 23 | baseNormal = getNormal(normal, baseNormal); 24 | additionalNormal = getNormal(normal, additionalNormal); 25 | 26 | vec3 pixelNomal = vec3(1.0f,0.0f,0.0f); 27 | vec3 worldNormal = oe_normal; 28 | vec3 largeNormal = normalize(mix(baseNormal, additionalNormal, pow(1 - dot(pixelNomal, worldNormal), 2))); 29 | 30 | // small wave 31 | vec2 uv_large_scale_tiling = vec2(1.0f) * 0.05f; 32 | float noise = texture(perlin_Noise, uv_large_scale_tiling).r; 33 | float pixelDepthWithNoise = mix(-2000.f, 2000.f, noise); 34 | 35 | // 36 | float pixelDepth = length(oe_posView); 37 | float gradient = clamp((pixelDepth + pixelDepthWithNoise - 1000.0f)/2000.0f,0.0,1.0f); 38 | 39 | vec3 smallNormal = mix(texture(water_N, uv_color).rgb, vec3(0,0,1), gradient); 40 | smallNormal = getNormal(normal, smallNormal); 41 | //BlendAngleCorrectedNormals 42 | vec3 finalNormal = normalize(mix(largeNormal, smallNormal, pow(1 - dot(pixelNomal, worldNormal), 2))); 43 | normal = finalNormal; 44 | // calc diffuseColor 45 | 46 | float mask = texture(water_M, uv_normal).r * texture(water_M, uv_color).r; 47 | mask = clamp(mask, 0.0f, 1.0f); 48 | 49 | vec4 waterBaseColor = vec4(0.0336f, 0.055f, 0.0545f, 1.0f); 50 | vec4 waveCrestColor = vec4(0.433f, 0.61f,0.601f, 1.0f); 51 | vec4 waterCrestColor = mix(mix(waterBaseColor, waveCrestColor, mask),waterBaseColor, gradient); 52 | diffuseColor = waterCrestColor.rgb; 53 | 54 | // calc roughness 55 | roughness = 0.1f; 56 | 57 | #ifdef debug_texture 58 | color.rgb = normal; 59 | #endif 60 | 61 | -------------------------------------------------------------------------------- /OE_PBR/Shader/normal.glsl: -------------------------------------------------------------------------------- 1 | // export default /* glsl */` 2 | 3 | // #ifdef OBJECTSPACE_NORMALMAP 4 | 5 | // normal = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0; // overrides both flatShading and attribute normals 6 | 7 | // #ifdef FLIP_SIDED 8 | 9 | // normal = - normal; 10 | 11 | // #endif 12 | 13 | // #ifdef DOUBLE_SIDED 14 | 15 | // normal = normal * faceDirection; 16 | 17 | // #endif 18 | 19 | // normal = normalize( normalMatrix * normal ); 20 | 21 | // #elif defined( TANGENTSPACE_NORMALMAP ) 22 | 23 | // vec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0; 24 | // mapN.xy *= normalScale; 25 | 26 | // #ifdef USE_TANGENT 27 | 28 | // normal = normalize( vTBN * mapN ); 29 | 30 | // #else 31 | 32 | // normal = perturbNormal2Arb( - vViewPosition, normal, mapN, faceDirection ); 33 | 34 | // #endif 35 | 36 | // #elif defined( USE_BUMPMAP ) 37 | 38 | // normal = perturbNormalArb( - vViewPosition, normal, dHdxy_fwd(), faceDirection ); 39 | 40 | // #endif 41 | // `; 42 | -------------------------------------------------------------------------------- /OE_PBR/Shader/normal_functions.glsl: -------------------------------------------------------------------------------- 1 | 2 | 3 | vec3 normalInWorldWithoutTangent(vec3 normal, vec3 eyePos,vec2 uv, vec3 normalFromTexture) 4 | { 5 | // Perturb normal, see http://www.thetenthplanet.de/archives/1180 6 | vec3 unpackedNormal = normalFromTexture * 2.0f - 1.0f; 7 | 8 | // vec3 q1 = ddx(eyePos); 9 | // vec3 q2 = ddy(eyePos); 10 | // vec2 st1 = ddx(uv); 11 | // vec2 st2 = ddy(uv); 12 | 13 | // vec3 N = normalize(normal); 14 | // vec3 T = normalize(q1 * st2.y - q2 * st1.y); 15 | // vec3 B = normalize(cross(N, T)); 16 | 17 | // mat3 TBN = mat3(T, B, N); 18 | // return normalize(TBN*unpackedNormal); 19 | return normal; 20 | 21 | } 22 | 23 | vec3 getNormal(vec3 N, vec3 normalFromTexture) 24 | { 25 | 26 | vec3 unpackedNormal = normalFromTexture*2.0 -1.0; // normal in tangent space 27 | // vec3 tangent = gl_NormalMatrix * vec3(1.0,0.0,0.0); 28 | 29 | // vec3 N = normalize(normal); 30 | // vec3 T = normalize(tangent - N * dot(tangent, N)); 31 | // vec3 B = cross(N, T); 32 | // mat3 TBN = mat3(T, B, N); 33 | // return normalize(TBN * unpackedNormal); 34 | 35 | vec3 B = normalize(gl_NormalMatrix * vec3(0,1,0)); 36 | 37 | vec3 T = normalize(cross(B, N)); 38 | 39 | return normalize(mat3(T, B, N) * unpackedNormal); 40 | 41 | 42 | } 43 | 44 | mat3 makeTBN(vec3 N, vec3 p, vec2 uv) 45 | { 46 | // get edge vectors of the pixel triangle 47 | vec3 dp1 = dFdx(p); 48 | vec3 dp2 = dFdy(p); 49 | vec2 duv1 = dFdx(uv); 50 | vec2 duv2 = dFdy(uv); 51 | 52 | // solve the linear system 53 | vec3 dp2perp = cross(dp2, N); 54 | vec3 dp1perp = cross(N, dp1); 55 | vec3 T = dp2perp * duv1.x + dp1perp * duv2.x; 56 | vec3 B = dp2perp * duv1.y + dp1perp * duv2.y; 57 | 58 | // construct a scale-invariant frame 59 | float invmax = inversesqrt(max(dot(T, T), dot(B, B))); 60 | return mat3(T * invmax, B * invmax, N); 61 | } -------------------------------------------------------------------------------- /OE_PBR/Shader/pbr.glsl: -------------------------------------------------------------------------------- 1 | #pragma vp_name Phong Lighting Vertex Stage 2 | #pragma vp_entryPoint vertex_main_pbr 3 | #pragma vp_location vertex_view 4 | 5 | #pragma import_defines(OE_LIGHTING, OE_NUM_LIGHTS) 6 | 7 | vec3 vp_Normal; //same as gl_Normal 8 | 9 | out vec3 oe_posView; 10 | out vec2 oe_texcoord; 11 | out vec3 oe_normal; 12 | out vec3 oe_pos; 13 | /*vs define attribute binding and how todefine 14 | */ 15 | void vertex_main_pbr(inout vec4 VertexVIEW) 16 | { 17 | #ifndef OE_LIGHTING 18 | return; 19 | #endif 20 | 21 | oe_posView = VertexVIEW.xyz / VertexVIEW.w; 22 | oe_texcoord = gl_MultiTexCoord0.xy; 23 | oe_normal = vp_Normal; 24 | oe_pos = gl_Vertex.xyz; 25 | } 26 | 27 | [break] 28 | 29 | 30 | 31 | #pragma vp_name Pbr Lighting Fragment Stage 32 | #pragma vp_entryPoint fragment_main_pbr 33 | #pragma vp_location fragment_lighting 34 | 35 | #define PI 3.14159265359f 36 | #define RECIPROCAL_PI 0.318309886142228 37 | // #define debug_texture 1 38 | #pragma import_defines(MATERIAL_DEFINES) 39 | #pragma import_defines(OE_LIGHTING, OE_USE_PBR, USE_ENV_MAP, USE_ENV_CUBE_UV) 40 | #pragma import_defines(OE_NUM_LIGHTS) 41 | #pragma import_defines(cascade, OE_ENABLE_BASECOLOR_MAP,OE_ENABLE_NORMAL_MAP, OE_ENABLE_MR_MAP, OE_ENABLE_AO_MAP, OE_ENABLE_EMISSIVE_MAP) 42 | #pragma import_defines(USE_SHEEN,USE_CLEARCOAT,USE_TRANSMISSION) 43 | #pragma import_defines(USE_CLEARCOATMAP,USE_CLEARCOAT_ROUGHNESSMAP, USE_SHEENCOLORMAP, USE_SHEENROUGHNESSMAP) 44 | #pragma include normal_functions.glsl 45 | #pragma include BRDF.glsl 46 | #pragma include light_functions.glsl 47 | #pragma include transmission.glsl 48 | #pragma include struct.glsl 49 | 50 | 51 | in vec3 oe_posView; // view space 52 | in vec2 oe_texcoord; 53 | in vec3 oe_normal; // view space 54 | in vec3 oe_pos; 55 | // stage global 56 | in vec3 vp_Normal; 57 | 58 | 59 | // varying decorated with flat, the data will not change when pass from vs to ps, and not introplote ,every fragment share same data 60 | 61 | 62 | uniform osg_LightSourceParameters osg_LightSource[OE_NUM_LIGHTS]; 63 | 64 | uniform pbr_Material oe_pbr; 65 | #ifdef cascade 66 | uniform sampler2DArray pbrMaps; 67 | #endif 68 | #ifdef USE_ENV_MAP 69 | uniform float envLightIntensity; 70 | #endif 71 | 72 | #ifdef USE_TRANSMISSION 73 | uniform sampler2D translucentMap; 74 | #endif 75 | 76 | # MATERIAL_UNIFORMS 77 | 78 | 79 | vec4 linearTosRGB(in vec4 value) 80 | { 81 | return vec4(mix(((pow(value.xyz, vec3(0.41666001, 0.41666001, 0.41666001)) * 1.0549999) - vec3(0.055, 0.055, 0.055)), \ 82 | (value.xyz * 12.92), vec3(lessThanEqual(value.xyz, vec3(0.0031308001, 0.0031308001, 0.0031308001)))), value.w); 83 | } 84 | #ifdef OE_USE_PBR 85 | void fragment_main_pbr(inout vec4 color) 86 | { 87 | #ifndef OE_LIGHTING 88 | return; 89 | #endif 90 | vec3 baseColor = oe_pbr.baseColorFactor.rgb; 91 | float lightIntensity = 5.0; 92 | vec3 f0 = vec3(0.04); 93 | 94 | vec3 normal = oe_normal; 95 | vec3 normalEC = normal; 96 | 97 | float roughness = oe_pbr.roughnessFactor; 98 | float metallic = oe_pbr.metallicFactor; 99 | float ao = oe_pbr.aoStrength; 100 | vec3 emissive = oe_pbr.emissiveFactor; 101 | vec3 diffuseColor =vec3(1.0); 102 | 103 | pbr_Material material; 104 | GeometricContext geometry; 105 | ReflectedLight reflectedLight; 106 | 107 | # MATERIAL_BODY 108 | #ifdef debug_texture 109 | return; 110 | #endif 111 | 112 | f0 = mix(f0, diffuseColor, vec3(metallic)); 113 | diffuseColor *= (1.0 - metallic); 114 | 115 | material.baseColorFactor=vec4(diffuseColor,1.0); 116 | material.metallicFactor=metallic; 117 | material.roughnessFactor=max(roughness, 0.04f); 118 | material.aoStrength=ao; 119 | material.specularF0 = f0; 120 | 121 | geometry.normal = normalize(normal); 122 | 123 | vec3 n = normalize(geometry.normal); 124 | vec3 v = normalize(-oe_posView); 125 | float NdotV = max(dot(n, v), 0.0f); 126 | vec3 r = reflect(-v, n); 127 | 128 | vec3 Lo = vec3(0.0); 129 | 130 | 131 | geometry.viewDir = v; 132 | geometry.normal = n; 133 | 134 | 135 | reflectedLight.indirectDiffuse = vec3(0.0); 136 | reflectedLight.indirectSpecular = vec3(0.0); 137 | reflectedLight.directDiffuse = vec3(0.0); 138 | reflectedLight.directSpecular = vec3(0.0); 139 | 140 | 141 | for (int i = 0; i < OE_NUM_LIGHTS; ++i) 142 | { 143 | RE_Direct_Physical( osg_LightSource[i], geometry, f0, material, reflectedLight); 144 | } 145 | 146 | // indirect light accumulate 147 | vec3 ambient =vec3(0.0); 148 | vec3 irradiance = vec3(0.0); 149 | vec3 radiance = vec3(0.0); 150 | 151 | irradiance += osg_LightSource[0].ambient.rgb; 152 | // irradiance += getLightProbeIrradiance(); 153 | // irradiance += getLightMapIrradiance(); 154 | vec3 irradianceIBL = vec3(0.0); 155 | vec3 radianceIBL = vec3(0.0); 156 | 157 | 158 | vec3 clearcoatRadiance = vec3(0.0); 159 | #ifdef USE_ENV_MAP 160 | radianceIBL = getIBLRadiance(n, roughness,v); 161 | irradianceIBL = getIBLIrradiance(n); 162 | RE_IndirectDiffuse_Physical(irradiance, diffuseColor, reflectedLight); 163 | 164 | #ifdef USE_CLEARCOAT 165 | clearcoatRadiance = getIBLRadiance(geometry.clearcoatNormal, material.clearcoatRoughness, v); 166 | #endif 167 | RE_IndirectSpecular_Physical(radianceIBL, irradianceIBL,clearcoatRadiance,f0,geometry, material, reflectedLight); 168 | 169 | #endif 170 | 171 | vec3 totalDiffuse = reflectedLight.directDiffuse; 172 | vec3 totalSpecular = reflectedLight.directSpecular; 173 | 174 | 175 | #ifdef USE_ENV_MAP 176 | totalDiffuse += reflectedLight.indirectDiffuse * envLightIntensity; 177 | totalSpecular += reflectedLight.indirectSpecular* ao * envLightIntensity; 178 | 179 | 180 | #endif 181 | #ifdef USE_TRANSMISSION 182 | //SRGBtoLINEAR 183 | totalDiffuse = mix( totalDiffuse, vec4(reflectedLight.backLight,1.0f).rgb, material.transmission ); 184 | float exposure = 2.2f; 185 | totalSpecular.rgb *= exposure; 186 | //color.rgb = color.rgb / (color.rgb + vec3(1.0)); 187 | 188 | totalSpecular = linearTosRGB(vec4(totalSpecular,1.0f)).rgb; 189 | color.rgb = (totalDiffuse + totalSpecular); 190 | #else 191 | color.rgb = (totalDiffuse + totalSpecular); 192 | #endif 193 | #ifdef OE_ENABLE_EMISSIVE_MAP 194 | color.rgb += emissive; 195 | #endif 196 | 197 | 198 | #ifdef USE_SHEEN 199 | 200 | // Sheen energy compensation approximation calculation can be found at the end of 201 | // https://drive.google.com/file/d/1T0D1VSyR4AllqIJTQAraEIzjlb5h4FKH/view?usp=sharing 202 | float sheenEnergyComp = 1.0 - 0.157 * material.sheenColor.r; 203 | 204 | color.rgb = color.rgb * sheenEnergyComp + reflectedLight.sheenSpecular; 205 | #endif 206 | 207 | #ifdef USE_CLEARCOAT 208 | 209 | float dotNVcc = saturate( dot( geometry.clearcoatNormal, geometry.viewDir ) ); 210 | 211 | vec3 Fcc = F_Schlick( material.clearcoatF0, material.clearcoatF90, dotNVcc ); 212 | 213 | color.rgb = color.rgb * ( 1.0 - material.clearcoat * Fcc ) + reflectedLight.clearcoatSpecular; 214 | 215 | #endif 216 | 217 | 218 | 219 | 220 | // tonemap: 221 | 222 | #ifdef USE_TRANSMISSION 223 | 224 | color.a = 0.1 + 0.1; 225 | #else 226 | float exposure = 2.2f; 227 | color.rgb *= exposure; 228 | //color.rgb = color.rgb / (color.rgb + vec3(1.0)); 229 | 230 | color = linearTosRGB(color); 231 | #endif 232 | 233 | color.a = oe_pbr.alphaMask; 234 | 235 | 236 | // add in the haze 237 | //color.rgb += atmos_color; 238 | 239 | // exposure: 240 | //color.rgb = 1.0 - exp(-oe_sky_exposure * color.rgb); 241 | //color.rgb = 1.0 - exp(-oe_sky_exposure * 0.33 * color.rgb); 242 | 243 | // brightness and contrast 244 | //color.rgb = ((color.rgb - 0.5)*oe_pbr.contrast + 0.5) * oe_pbr.brightness; 245 | } 246 | #else 247 | void fragment_main_pbr(inout vec4 color) 248 | { 249 | // debug 250 | //color = color * vec4(1.0,0.0,0.0,1.0); 251 | color = texture(pbrMaps, vec3(oe_texcoord,4)); 252 | } 253 | #endif -------------------------------------------------------------------------------- /OE_PBR/Shader/pbrSpecularGlossiness.glsl: -------------------------------------------------------------------------------- 1 | 2 | #define OE_ENABLE_NORMAL_MAP OE_ENABLE_AO_MAP OE_ENABLE_DIFFUSE_MAP OE_ENABLE_SPECGLOSSY_MAP OE_ENABLE_EMISSIVE_MAP 3 | 4 | struct pbr_material_input{ 5 | vec3 diffuseFactor; 6 | vec3 specularFactor; 7 | float ao; 8 | vec3 emissive; 9 | } 10 | #ifdef OE_ENABLE_DIFFUSE_MAP 11 | diffuseColor = texture(pbrMaps, vec3(oe_texcoord,OE_ENABLE_DIFFUSE_MAP)).rgb; 12 | diffuseColor = diffuseFactor * diffuseColor; 13 | #endif 14 | 15 | #ifdef OE_ENABLE_SPECGLOSSY_MAP 16 | vec3 specularColor = texture(pbrMaps, vec3(oe_texcoord,OE_ENABLE_SPECGLOSSY_MAP)).rgb; 17 | specularColor = specularFactor * specularColor; 18 | #endif 19 | 20 | #ifdef OE_ENABLE_NORMAL_MAP 21 | 22 | vec3 tangent = vec3(1.0,0.0,0.0); 23 | vec3 tangentNormal = texture(pbrMaps, vec3(oe_texcoord,OE_ENABLE_NORMAL_MAP)).rgb; // normal in tangent space 24 | normal = tangentNormal; 25 | #endif 26 | 27 | #ifdef OE_ENABLE_AO_MAP 28 | float aoFromMap = texture(pbrMaps, vec3(oe_texcoord,OE_ENABLE_AO_MAP)).r; // normal in tangent space 29 | ao = mix(aoFromMap, 1, ao); 30 | #endif 31 | 32 | #ifdef OE_ENABLE_EMISSIVE_MAP 33 | vec3 emissiveFromMap = texture(pbrMaps, vec3(oe_texcoord,OE_ENABLE_EMISSIVE_MAP)).rgb; // normal in tangent space 34 | emissive *= emissiveFromMap; 35 | #endif 36 | -------------------------------------------------------------------------------- /OE_PBR/Shader/readme.md: -------------------------------------------------------------------------------- 1 | # OSGEARTH PBR MATERIAL LIB 2 | 3 | Tutorial:https://zhuanlan.zhihu.com/p/653871547 4 | ## V1.0 5 | - 提供osgEarth::StandardPBRMaterial 6 | - GLTFReaderV2读取gltf2.0模型 7 | - PbrLightEffect实现Cook_BRDF光照 8 | 9 | ## V1.1 10 | - 新增透明材质 11 | - 新增IBL环境光照 12 | - 扩展了dds插件对CubeMap的读取 和 GL_RGBA_ARB扩展压缩格式的支持 13 | - 【Tool】 cubemap -> quadMap 14 | 15 | ## V1.2 16 | - 提供osgEarth::ExtensionedMaterial 可自定义材质 17 | - 实现了waterial example from ue 18 | - 可以切换 HDR specularHDR 可设置mipmap 19 | - OPAQUE 20 | 21 | ## V1.3 22 | - 提供osgEarth::AdvancedMaterial 23 | - 支持sheen和clearcloat特性 24 | - gtlf插件增加对khr_extenison的支持 25 | - 完成relection probe cubeCamera以支持transmission 26 | 27 | # TODO 28 | - 透明材质 29 | - 后处理 30 | - 提供osg自己的材质资产格式 .omat 31 | - gltf插件和dds插件编译好 32 | 33 | - sheen tranmission ior anisotropy variants iridescence 34 | - exposure -------------------------------------------------------------------------------- /OE_PBR/Shader/struct.glsl: -------------------------------------------------------------------------------- 1 | 2 | struct pbr_Material 3 | { 4 | vec4 baseColorFactor; 5 | vec3 emissiveFactor; 6 | float metallicFactor; 7 | float roughnessFactor; 8 | float alphaMask; 9 | float alphaMaskCutoff; 10 | float aoStrength; 11 | vec3 specularF0; 12 | float specularF90; 13 | #ifdef USE_SHEEN 14 | vec3 sheenColor; 15 | float sheenRoughness; 16 | #endif 17 | #ifdef USE_CLEARCOAT 18 | float clearcoat; 19 | float clearcoatRoughness; 20 | vec3 clearcoatF0; 21 | float clearcoatF90; 22 | #endif 23 | #ifdef USE_TRANSMISSION 24 | float transmission; 25 | float transmissionAlpha; 26 | float thickness; 27 | float attenuationDistance; 28 | float ior; 29 | vec3 attenuationColor; 30 | 31 | #endif 32 | }; 33 | 34 | struct ReflectedLight 35 | { 36 | vec3 indirectDiffuse; 37 | vec3 indirectSpecular; 38 | vec3 directDiffuse; 39 | vec3 directSpecular; 40 | #ifdef USE_SHEEN 41 | vec3 sheenSpecular; 42 | #endif 43 | #ifdef USE_CLEARCOAT 44 | vec3 clearcoatSpecular; 45 | #endif 46 | #ifdef USE_TRANSMISSION 47 | vec3 backLight; 48 | #endif 49 | }; 50 | struct GeometricContext 51 | { 52 | vec3 normal; 53 | vec3 viewDir; 54 | #ifdef USE_CLEARCOAT 55 | vec3 clearcoatNormal; 56 | #endif 57 | }; 58 | struct osg_LightSourceParameters 59 | { 60 | vec4 ambient; 61 | vec4 diffuse; 62 | vec4 specular; 63 | vec4 position; 64 | vec3 spotDirection; 65 | float spotExponent; 66 | float spotCutoff; 67 | float spotCosCutoff; 68 | float constantAttenuation; 69 | float linearAttenuation; 70 | float quadraticAttenuation; 71 | 72 | bool enabled; 73 | }; 74 | 75 | struct ProbeData 76 | { 77 | vec3 pos; 78 | float boxWidth; 79 | }; -------------------------------------------------------------------------------- /OE_PBR/Shader/transmission.glsl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | vec3 getVolumeTransmissionRay( const in vec3 n, const in vec3 v, const in float thickness, const in float ior, const in mat4 modelMatrix ) 5 | { 6 | 7 | // Direction of refracted light. 8 | vec3 refractionVector = refract(v, normalize( n ), 1.0 / 1.0 ); 9 | 10 | // Compute rotation-independant scaling of the model matrix. 11 | vec3 modelScale; 12 | modelScale.x = length( vec3( modelMatrix[ 0 ].xyz ) ); 13 | modelScale.y = length( vec3( modelMatrix[ 1 ].xyz ) ); 14 | modelScale.z = length( vec3( modelMatrix[ 2 ].xyz ) ); 15 | 16 | // The thickness is specified in local space. 17 | return normalize( refractionVector ) * thickness; 18 | 19 | } 20 | 21 | float applyIorToRoughness( const in float roughness, const in float ior ) 22 | { 23 | 24 | // Scale roughness with IOR so that an IOR of 1.0 results in no microfacet refraction and 25 | // an IOR of 1.5 results in the default amount of microfacet refraction. 26 | return roughness * clamp( ior * 2.0 - 2.0, 0.0, 1.0 ); 27 | 28 | } 29 | 30 | vec4 getTransmissionSample( const in vec3 probeSampleVec, const in float roughness, const in float ior ) 31 | { 32 | 33 | //float framebufferLod = log2( transmissionSamplerSize.x ) * applyIorToRoughness( roughness, ior ); 34 | 35 | // #ifdef texture2DLodEXT 36 | 37 | // return texture2DLodEXT( transmissionSamplerMap, fragCoord.xy, framebufferLod ); 38 | 39 | // #else 40 | 41 | 42 | return vec4(1.0f); 43 | 44 | } 45 | 46 | vec3 applyVolumeAttenuation( const in vec3 radiance, const in float transmissionDistance, const in vec3 attenuationColor, const in float attenuationDistance ) 47 | { 48 | 49 | if ( attenuationDistance>1000.0f ) { 50 | return radiance; 51 | 52 | } else { 53 | 54 | vec3 attenuationCoefficient = -log( attenuationColor ) / attenuationDistance; 55 | vec3 transmittance = exp( - attenuationCoefficient * transmissionDistance ); // Beer's law 56 | return transmittance * radiance; 57 | 58 | } 59 | 60 | } 61 | 62 | vec4 getIBLVolumeRefraction( const in vec3 n, const in vec3 v, const in float roughness, const in vec3 diffuseColor, 63 | const in vec3 specularColor, const in float specularF90, const in vec3 position, const in mat4 modelMatrix, 64 | const in mat4 viewMatrix, const in mat4 projMatrix, const in float ior, const in float thickness, 65 | const in vec3 attenuationColor, const in float attenuationDistance, sampler2D translucentMap) 66 | { 67 | 68 | vec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix ); 69 | vec3 refractedRayExit = position + transmissionRay; 70 | 71 | vec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 ); 72 | vec2 refractionCoords = ndcPos.xy / ndcPos.w; 73 | refractionCoords += 1.0; 74 | refractionCoords /= 2.0; 75 | 76 | // vec3 dirToProbe = probePos - position; 77 | // vec3 probeSampleVec = refractedRayExit - dirToProbe; 78 | 79 | // probeSampleVec = vec3(1.0,0.0,0.0); 80 | // vec3 off = sin(refractedRayExit.x) * vec3(1.0,1.0,0.0); 81 | 82 | vec4 transmittedLight = texture( translucentMap, refractionCoords, 0 ); 83 | //getTransmissionSample( probeSampleVec, roughness, ior ); 84 | 85 | //return transmittedLight; 86 | 87 | vec3 attenuatedColor = applyVolumeAttenuation( transmittedLight.rgb, length( transmissionRay ), attenuationColor, attenuationDistance ); 88 | vec3 F = EnvironmentBRDF( n, v, specularColor, specularF90, roughness ); 89 | // 90 | return vec4(( 1.0 - F ) * attenuatedColor.rgb * diffuseColor, transmittedLight.a ); 91 | 92 | } 93 | 94 | -------------------------------------------------------------------------------- /OE_PBR/SkyBox.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #include"EnvLight.h" 35 | 36 | //osg::TextureCubeMap* readCubeMap() 37 | //{ 38 | // osg::TextureCubeMap* cubemap = new osg::TextureCubeMap; 39 | // //#define CUBEMAP_FILENAME(face) "nvlobby_" #face ".png" 40 | // //#define CUBEMAP_FILENAME(face) "Cubemap_axis/" #face ".png" 41 | //#define CUBEMAP_FILENAME(face) "Cubemap_snow/" #face ".jpg" 42 | // 43 | // osg::ref_ptrimagePosX = osgDB::readRefImageFile(CUBEMAP_FILENAME(posx)); 44 | // osg::ref_ptrimageNegX = osgDB::readRefImageFile(CUBEMAP_FILENAME(negx)); 45 | // osg::ref_ptrimagePosY = osgDB::readRefImageFile(CUBEMAP_FILENAME(posy)); 46 | // osg::ref_ptrimageNegY = osgDB::readRefImageFile(CUBEMAP_FILENAME(negy)); 47 | // osg::ref_ptrimagePosZ = osgDB::readRefImageFile(CUBEMAP_FILENAME(posz)); 48 | // osg::ref_ptrimageNegZ = osgDB::readRefImageFile(CUBEMAP_FILENAME(negz)); 49 | // 50 | // if (imagePosX && imageNegX && imagePosY && imageNegY && imagePosZ && imageNegZ) 51 | // { 52 | // cubemap->setImage(osg::TextureCubeMap::POSITIVE_X, imagePosX); 53 | // cubemap->setImage(osg::TextureCubeMap::NEGATIVE_X, imageNegX); 54 | // cubemap->setImage(osg::TextureCubeMap::POSITIVE_Y, imagePosY); 55 | // cubemap->setImage(osg::TextureCubeMap::NEGATIVE_Y, imageNegY); 56 | // cubemap->setImage(osg::TextureCubeMap::POSITIVE_Z, imagePosZ); 57 | // cubemap->setImage(osg::TextureCubeMap::NEGATIVE_Z, imageNegZ); 58 | // 59 | // cubemap->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE); 60 | // cubemap->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE); 61 | // cubemap->setWrap(osg::Texture::WRAP_R, osg::Texture::CLAMP_TO_EDGE); 62 | // 63 | // cubemap->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_LINEAR); 64 | // cubemap->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); 65 | // } 66 | // 67 | // return cubemap; 68 | //} 69 | 70 | 71 | // Update texture matrix for cubemaps 72 | struct TexMatCallback : public osg::NodeCallback 73 | { 74 | public: 75 | 76 | TexMatCallback(osg::TexMat& tm) : 77 | _texMat(tm) 78 | { 79 | } 80 | 81 | virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) 82 | { 83 | osgUtil::CullVisitor* cv = dynamic_cast(nv); 84 | if (cv) 85 | { 86 | const osg::Matrix& MV = *(cv->getModelViewMatrix()); 87 | const osg::Matrix R = osg::Matrix::rotate(osg::DegreesToRadians(112.0f), 0.0f, 0.0f, 1.0f) * 88 | osg::Matrix::rotate(osg::DegreesToRadians(90.0f), 1.0f, 0.0f, 0.0f); 89 | 90 | osg::Quat q = MV.getRotate(); 91 | const osg::Matrix C = osg::Matrix::rotate(q.inverse()); 92 | 93 | _texMat.setMatrix(C * R); 94 | } 95 | 96 | traverse(node, nv); 97 | } 98 | 99 | osg::TexMat& _texMat; 100 | }; 101 | 102 | 103 | class MoveEarthySkyWithEyePointTransform : public osg::Transform 104 | { 105 | public: 106 | /** Get the transformation matrix which moves from local coords to world coords.*/ 107 | virtual bool computeLocalToWorldMatrix(osg::Matrix& matrix, osg::NodeVisitor* nv) const 108 | { 109 | osgUtil::CullVisitor* cv = dynamic_cast(nv); 110 | if (cv) 111 | { 112 | osg::Vec3 eyePointLocal = cv->getEyeLocal(); 113 | matrix.preMultTranslate(eyePointLocal); 114 | } 115 | return true; 116 | } 117 | 118 | /** Get the transformation matrix which moves from world coords to local coords.*/ 119 | virtual bool computeWorldToLocalMatrix(osg::Matrix& matrix, osg::NodeVisitor* nv) const 120 | { 121 | osgUtil::CullVisitor* cv = dynamic_cast(nv); 122 | if (cv) 123 | { 124 | osg::Vec3 eyePointLocal = cv->getEyeLocal(); 125 | matrix.postMultTranslate(-eyePointLocal); 126 | } 127 | return true; 128 | } 129 | }; 130 | 131 | 132 | extern osg::Node* createSkyBox() 133 | { 134 | 135 | osg::StateSet* stateset = new osg::StateSet(); 136 | 137 | osg::TexEnv* te = new osg::TexEnv; 138 | te->setMode(osg::TexEnv::REPLACE); 139 | stateset->setTextureAttributeAndModes(0, te, osg::StateAttribute::ON); 140 | 141 | osg::TexGen* tg = new osg::TexGen; 142 | tg->setMode(osg::TexGen::NORMAL_MAP); 143 | stateset->setTextureAttributeAndModes(0, tg, osg::StateAttribute::ON); 144 | 145 | osg::TexMat* tm = new osg::TexMat; 146 | stateset->setTextureAttribute(0, tm); 147 | 148 | auto setEnvMap = [stateset]() 149 | { 150 | osg::Texture* skymap = EnvLightEffect::instance()->getEnvCubeMap(); 151 | stateset->setTextureAttributeAndModes(0, skymap, osg::StateAttribute::ON); 152 | }; 153 | setEnvMap(); 154 | EnvLightEffect::instance()->addReplaceCallback(setEnvMap); 155 | 156 | 157 | stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF); 158 | stateset->setMode(GL_CULL_FACE, osg::StateAttribute::OFF); 159 | 160 | // clear the depth to the far plane. 161 | osg::Depth* depth = new osg::Depth; 162 | depth->setFunction(osg::Depth::ALWAYS); 163 | depth->setRange(1.0, 1.0); 164 | stateset->setAttributeAndModes(depth, osg::StateAttribute::ON); 165 | 166 | stateset->setRenderBinDetails(-1, "RenderBin"); 167 | 168 | osg::Drawable* drawable = new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(0.0f, 0.0f, 0.0f), 1)); 169 | 170 | osg::Geode* geode = new osg::Geode; 171 | geode->setCullingActive(false); 172 | geode->setStateSet(stateset); 173 | geode->addDrawable(drawable); 174 | 175 | 176 | osg::Transform* transform = new MoveEarthySkyWithEyePointTransform; 177 | transform->setCullingActive(false); 178 | transform->addChild(geode); 179 | 180 | osg::ClearNode* clearNode = new osg::ClearNode; 181 | // clearNode->setRequiresClear(false); 182 | clearNode->setCullCallback(new TexMatCallback(*tm)); 183 | clearNode->addChild(transform); 184 | 185 | clearNode->setNodeMask(TRANSLUCENT_MASK); 186 | return clearNode; 187 | } -------------------------------------------------------------------------------- /OE_PBR/SnapImage.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | #include 12 | #include 13 | 14 | #include "ddsNew.h" 15 | #include 16 | 17 | class SwitchOption 18 | { 19 | public: 20 | SwitchOption() 21 | : once(false) 22 | { 23 | } 24 | 25 | mutable bool once; 26 | }; 27 | 28 | struct SnapImage : public SwitchOption, public osg::Camera::DrawCallback 29 | { 30 | SnapImage(const std::string& filename, osg::Image* image) 31 | : _filename(filename) 32 | , _image(image) 33 | , _tex(nullptr) 34 | { 35 | // _image = new osg::Image; 36 | } 37 | SnapImage(const std::string& filename, osg::Image* image, osg::Texture2D* tex) 38 | : _filename(filename) 39 | , _image(image) 40 | , _tex(tex) 41 | { 42 | // _image = new osg::Image; 43 | } 44 | virtual void operator()(osg::RenderInfo& renderInfo) const 45 | { 46 | 47 | if (!once) 48 | return; 49 | osg::ref_ptr state = new osg::State; 50 | state->initializeExtensionProcs(); 51 | osg::notify(osg::NOTICE) << "Camera callback" << std::endl; 52 | 53 | osg::Camera* camera = renderInfo.getCurrentCamera(); 54 | osg::Viewport* viewport = camera ? camera->getViewport() : 0; 55 | 56 | GLboolean binding1D = GL_FALSE, binding2D = GL_FALSE, bindingRect = GL_FALSE, binding3D = GL_FALSE, binding2DArray = GL_FALSE, bindingCubeMap = GL_FALSE; 57 | 58 | glGetBooleanv(GL_TEXTURE_BINDING_1D, &binding1D); 59 | glGetBooleanv(GL_TEXTURE_BINDING_2D, &binding2D); 60 | glGetBooleanv(GL_TEXTURE_BINDING_RECTANGLE, &bindingRect); 61 | glGetBooleanv(GL_TEXTURE_BINDING_3D, &binding3D); 62 | glGetBooleanv(GL_TEXTURE_BINDING_CUBE_MAP, &bindingCubeMap); 63 | 64 | if (binding1D) 65 | { 66 | std::cout << "1D" << std::endl; 67 | } 68 | if (binding2D) 69 | { 70 | unsigned contextID = renderInfo.getContextID(); 71 | std::cout << "contextID" << contextID << std::endl; 72 | _tex->getImage()->readImageFromCurrentTexture(contextID, true); 73 | osgDB::writeImageFile(*_tex->getImage(), _filename); 74 | once = false; 75 | } 76 | if (bindingRect) 77 | { 78 | std::cout << "RecD" << std::endl; 79 | } 80 | if (binding3D) 81 | { 82 | std::cout << "3D" << std::endl; 83 | } 84 | if (bindingCubeMap) 85 | { 86 | std::cout << "CubeD" << std::endl; 87 | } 88 | 89 | // if (true) 90 | //{ 91 | // _tex->setUnRefImageDataAfterApply(false); 92 | 93 | // 94 | // unsigned contextID = renderInfo.getContextID(); 95 | // std::cout<<"contextID"<getImage()->readImageFromCurrentTexture(contextID, true); 97 | // osgDB::writeImageFile(*_tex->getImage(), _filename); 98 | //} 99 | // else { 100 | // // _image->readImageFromCurrentTexture(0, true); 101 | // osgDB::writeImageFile(*_image, _filename); 102 | //} 103 | 104 | // 105 | /* osg::Camera* cam = nullptr;*/ 106 | 107 | //_image->readPixels(0, 0, _tex->getTextureWidth(), _tex->getTextureHeight(), _image->getPixelFormat(), _image->getDataType()); 108 | // osgDB::writeImageFile(*_image, _filename); 109 | // float* data = (float*)_image->data(0, 0); 110 | // fprintf(stderr, "Float pixel data: r %e g %e b %e\n", data[0], data[1], data[2]); 111 | 112 | // osg::notify(osg::NOTICE) << "Taken screenshot, and written to '" << _filename << "'" << std::endl; 113 | 114 | /* float* data = (float*)_image->data(0, 0); 115 | fprintf(stderr, "Float pixel data: r %e g %e b %e\n", data[0], data[1], data[2]);*/ 116 | 117 | // osg::notify(osg::NOTICE) << "Taken screenshot, and written to '" << _filename << "'" << std::endl; 118 | 119 | /* if (viewport && _image.valid()) 120 | { 121 | _image->readPixels(int(viewport->x()), int(viewport->y()), int(viewport->width()), int(viewport->height()), 122 | GL_RGBA, 123 | GL_UNSIGNED_BYTE); 124 | 125 | }*/ 126 | } 127 | 128 | std::string _filename; 129 | osg::Image* _image; 130 | osg::Texture2D* _tex; 131 | }; 132 | 133 | struct SnapMipmap : public SwitchOption, public osg::Camera::DrawCallback 134 | { 135 | 136 | SnapMipmap(const std::string& filename, std::vector images) 137 | : _images(images) 138 | , _filename(filename) 139 | { 140 | // _image = new osg::Image; 141 | } 142 | 143 | virtual void operator()(osg::RenderInfo& renderInfo) const 144 | { 145 | if (!once) 146 | return; 147 | once = false; 148 | size_t miplevel = _images.size(); 149 | 150 | osg::ref_ptr image = new osg::Image; 151 | osg::Image::MipmapDataType mipmapData; 152 | unsigned int width = _images[0]->s(); 153 | unsigned int height = _images[0]->t(); 154 | 155 | unsigned int totalSize = 0; 156 | unsigned i; 157 | unsigned int pixelSize = 16; // rgba * GL_FLOAT 158 | for (i = 0; width > 0 && i < miplevel; width >>= 1, height >>= 1, ++i) 159 | { 160 | if (i > 0) 161 | mipmapData.push_back(totalSize); 162 | totalSize += width * height * pixelSize; 163 | } 164 | 165 | unsigned char* ptr = new unsigned char[totalSize]; 166 | image->setImage(_images[0]->s(), _images[0]->t(), 1, GL_RGBA32F_ARB, GL_RGBA, GL_FLOAT, ptr, osg::Image::USE_NEW_DELETE, 1); 167 | image->setMipmapLevels(mipmapData); 168 | 169 | unsigned int size = width * height; 170 | for (i = 0; size > 0, i < miplevel; size >>= 2, ++i) 171 | { 172 | for (osg::Image::DataIterator itr(_images[i]); itr.valid(); ++itr) 173 | { 174 | 175 | memcpy(ptr, itr.data(), itr.size()); 176 | ptr += itr.size(); 177 | 178 | /* auto top = itr.data(); 179 | width >>= 2;*/ 180 | } 181 | } 182 | image->flipVertical(); 183 | writeDDSNew(*image, _filename); 184 | } 185 | 186 | std::vector _images; 187 | std::string _filename; 188 | }; 189 | 190 | void flipImageVertical(unsigned char* top, unsigned char* bottom, unsigned int rowSize, unsigned int rowStep) 191 | { 192 | while (top < bottom) 193 | { 194 | unsigned char* t = top; 195 | unsigned char* b = bottom; 196 | for (unsigned int i = 0; i < rowSize; ++i, ++t, ++b) 197 | { 198 | unsigned char temp = *t; 199 | *t = *b; 200 | *b = temp; 201 | } 202 | top += rowStep; 203 | bottom -= rowStep; 204 | } 205 | } 206 | 207 | class SnapImageV2 : public SwitchOption, public osg::Drawable::DrawCallback 208 | { 209 | public: 210 | SnapImageV2() {} 211 | 212 | virtual void drawImplementation(osg::RenderInfo& renderInfo, const osg::Drawable* drawable) const 213 | { 214 | unsigned int contextId = renderInfo.getContextID(); 215 | drawable->drawImplementation(renderInfo); 216 | if (!once) 217 | { 218 | return; 219 | } 220 | GLboolean binding1D = GL_FALSE, binding2D = GL_FALSE, bindingRect = GL_FALSE, binding3D = GL_FALSE, binding2DArray = GL_FALSE, bindingCubeMap = GL_FALSE; 221 | 222 | glGetBooleanv(GL_TEXTURE_BINDING_1D, &binding1D); 223 | glGetBooleanv(GL_TEXTURE_BINDING_2D, &binding2D); 224 | glGetBooleanv(GL_TEXTURE_BINDING_RECTANGLE, &bindingRect); 225 | glGetBooleanv(GL_TEXTURE_BINDING_3D, &binding3D); 226 | glGetBooleanv(GL_TEXTURE_BINDING_CUBE_MAP, &bindingCubeMap); 227 | 228 | if (binding1D) 229 | { 230 | std::cout << "1D" << std::endl; 231 | } 232 | if (binding2D) 233 | { 234 | std::cout << "2D" << std::endl; 235 | } 236 | if (bindingRect) 237 | { 238 | std::cout << "RecD" << std::endl; 239 | } 240 | if (binding3D) 241 | { 242 | std::cout << "3D" << std::endl; 243 | } 244 | if (bindingCubeMap) 245 | { 246 | std::cout << "CubeD" << std::endl; 247 | } 248 | /* osg::GLBufferObject* glbo = _dyn->getBufferObject()->getOrCreateGLBufferObject(contextId); 249 | glbo->bindBuffer(); 250 | GLfloat* data = (GLfloat*)glbo->_persistentDMA + glbo->getOffset(_dyn->getBufferIndex()); 251 | if (data) 252 | { 253 | _rate += 0.01; 254 | float value = sinf(_rate) * _scale + _offset; 255 | for (int i = 0; i < 4; i++) { 256 | data[i * 4 + 0] = float(i) * 0.25 * value; 257 | } 258 | glbo->commitDMA(_dyn->getBufferIndex()); 259 | }*/ 260 | } 261 | }; 262 | 263 | struct SnapeImageHandler : public osgGA::GUIEventHandler 264 | { 265 | 266 | SnapeImageHandler(int key, SwitchOption* si) 267 | : _key(key) 268 | , _switch(si) 269 | { 270 | } 271 | 272 | bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) 273 | { 274 | if (ea.getHandled()) 275 | return false; 276 | 277 | switch (ea.getEventType()) 278 | { 279 | case (osgGA::GUIEventAdapter::KEYUP): 280 | { 281 | 282 | if (ea.getKey() == _key) 283 | { 284 | osg::notify(osg::NOTICE) << "event handler" << std::endl; 285 | _switch->once = true; 286 | return true; 287 | } 288 | 289 | break; 290 | } 291 | default: 292 | break; 293 | } 294 | 295 | return false; 296 | } 297 | 298 | int _key; 299 | SwitchOption* _switch; 300 | /* osg::ref_ptr _snapImage;*/ 301 | }; 302 | -------------------------------------------------------------------------------- /OE_PBR/TestUI.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include"EnvLight.h" 4 | #include"AdvancedMaterial.h" 5 | #include 6 | 7 | 8 | class MaterialGUI :public osgEarth::GUI::BaseGUI 9 | { 10 | public: 11 | float metal = 1.0; 12 | float roughness = 0.0; 13 | struct UniformSpec { 14 | std::string _name; 15 | float _minval, _maxval, _value; 16 | //osg::ref_ptr _u; 17 | }; 18 | 19 | 20 | struct DefineSpec { 21 | std::string _name; 22 | std::string _val; 23 | bool _checked; 24 | }; 25 | std::vector _defines; 26 | std::vector _uniforms; 27 | char material[256] = "Original text"; 28 | osg::Node* _node; 29 | public: 30 | MaterialGUI() :GUI::BaseGUI("PBR Material") 31 | { 32 | _node = nullptr; 33 | 34 | UniformSpec metallic{ "oe_pbr.metallicFactor" ,0.0f,1.0f,0.5f }; 35 | UniformSpec roughness{ "oe_pbr.roughnessFactor" ,0.0f,1.0f,0.5f }; 36 | UniformSpec aoStrength{ "oe_pbr.aoStrength" ,0.0f,1.0f,0.5f }; 37 | UniformSpec alphaMask{ "oe_pbr.alphaMask" ,0.0f,1.0f,0.99f }; 38 | DefineSpec normal{ "OE_ENABLE_NORMAL_MAP" , "3",true }; 39 | 40 | UniformSpec sheenRoughness{ "oe_pbr.sheenRoughness" ,0.0f,1.0f,0.5f }; 41 | UniformSpec clearcoat{ "oe_pbr.clearcoat" ,0.0f,1.0f,0.5f }; 42 | UniformSpec clearcoatRoughness{ "oe_pbr.clearcoatRoughness" ,0.0f,1.0f,0.5f }; 43 | 44 | UniformSpec transmission{ "oe_pbr.transmission" ,0.0f,1.0f,0.5f }; 45 | UniformSpec transmissionAlpha{ "oe_pbr.transmissionAlpha" ,0.0f,1.0f,0.5f }; 46 | UniformSpec thickness{ "oe_pbr.thickness" ,0.0f,5.0f,0.5f }; 47 | UniformSpec attenuationDistance{ "oe_pbr.attenuationDistance" ,0.0f,1.0f,0.5f }; 48 | UniformSpec ior{ "oe_pbr.ior" ,1.0f,2.0f,1.5f }; 49 | 50 | 51 | DefineSpec mr{ "OE_ENABLE_MR_MAP" ,"4", true }; 52 | DefineSpec ao{ "OE_ENABLE_AO_MAP" ,"2", true }; 53 | DefineSpec emssive{ "OE_ENABLE_EMISSIVE_MAP" ,"1", true }; 54 | DefineSpec baseColor{ "OE_ENABLE_BASECOLOR_MAP" ,"0", true }; 55 | 56 | 57 | _uniforms.emplace_back(metallic); 58 | _uniforms.emplace_back(roughness); 59 | _uniforms.emplace_back(aoStrength); 60 | _uniforms.emplace_back(alphaMask); 61 | 62 | _uniforms.emplace_back(sheenRoughness); 63 | _uniforms.emplace_back(clearcoat); 64 | _uniforms.emplace_back(clearcoatRoughness); 65 | _uniforms.emplace_back(transmission); 66 | _uniforms.emplace_back(transmissionAlpha); 67 | _uniforms.emplace_back(thickness); 68 | _uniforms.emplace_back(attenuationDistance); 69 | _uniforms.emplace_back(ior); 70 | 71 | 72 | 73 | _defines.emplace_back(normal); 74 | _defines.emplace_back(mr); 75 | _defines.emplace_back(ao); 76 | _defines.emplace_back(emssive); 77 | _defines.emplace_back(baseColor); 78 | 79 | } 80 | bool setNode(osg::MatrixTransform* node) 81 | { 82 | if (!node->asMatrixTransform()) 83 | { 84 | return false; 85 | } 86 | osg::Node* child; 87 | if (node->getNumChildren() >= 2) 88 | { 89 | child = node->getChild(1); 90 | } 91 | else { 92 | child = node->getChild(0); 93 | } 94 | 95 | 96 | strcpy(material, node->getName().c_str()); 97 | _node = child; 98 | if (auto mat = dynamic_cast(child)) 99 | { 100 | _node = mat->getChild(0); 101 | } 102 | // std::vector uList = { "oe_pbr.metallicFactor","oe_pbr.roughnessFactor" ,"oe_pbr.aoStrength" ,"oe_pbr.alphaMask","oe_pbr.sheenRoughness" ,"oe_pbr.clearcoat","oe_pbr.clearcoatRoughness" }; 103 | for (auto& def : _uniforms) 104 | { 105 | float value; 106 | auto u = _node->getOrCreateStateSet()->getUniform(def._name); 107 | if (u) 108 | { 109 | u->get(value); 110 | def._value = value; 111 | } 112 | 113 | 114 | } 115 | 116 | return true; 117 | } 118 | 119 | void draw(osg::RenderInfo& ri)override { 120 | if (!isVisible()) { 121 | return; 122 | } 123 | ImGui::Begin(name(), visible()); 124 | { 125 | if (!_uniforms.empty()) 126 | { 127 | ImGui::Text(material); 128 | } 129 | } 130 | for (auto& def : _uniforms) 131 | { 132 | if (ImGui::SliderFloat(def._name.c_str(), &def._value, def._minval, def._maxval)) 133 | { 134 | auto material = _node->getOrCreateStateSet()->getAttribute(osg::StateAttribute::MATERIAL); 135 | if (osgEarth::AdvancedMaterial* mat = dynamic_cast(material)) 136 | { 137 | 138 | if (def._name == "oe_pbr.clearcoat") 139 | { 140 | mat->setClearcoat(def._value); 141 | } 142 | if (def._name == "oe_pbr.clearcoatRoughness") 143 | { 144 | mat->setClearcoatRoughness(def._value); 145 | } 146 | if (def._name == "oe_pbr.sheenRoughness") 147 | { 148 | mat->setSheenRoughness(def._value); 149 | } 150 | if (def._name == "oe_pbr.metallicFactor") 151 | { 152 | mat->setMetallicFactor(def._value); 153 | } 154 | if (def._name == "oe_pbr.roughnessFactor") 155 | { 156 | mat->setRoughnessFactor(def._value); 157 | } 158 | if (def._name == "oe_pbr.transmission") 159 | { 160 | mat->setTransmission(def._value); 161 | } 162 | if (def._name == "oe_pbr.transmissionAlpha") 163 | { 164 | mat->setTransmissionAlpha(def._value); 165 | } 166 | if (def._name == "oe_pbr.thickness") 167 | { 168 | mat->setThickness(def._value); 169 | } 170 | if (def._name == "oe_pbr.attenuationDistance") 171 | { 172 | mat->setAttenuationDistance(def._value); 173 | } 174 | if (def._name == "oe_pbr.ior") 175 | { 176 | mat->setIOR(def._value); 177 | } 178 | 179 | } 180 | 181 | if (_node) 182 | { 183 | _node->getOrCreateStateSet()->getOrCreateUniform(def._name, osg::Uniform::FLOAT)->set(def._value); 184 | _node->getOrCreateStateSet()->addUniform(new osg::Uniform(def._name.c_str(), def._value), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); 185 | } 186 | 187 | 188 | 189 | /* if (def._name == "oe_pbr.alphaMask") 190 | { 191 | ImGui::Spacing(); 192 | }*/ 193 | } 194 | } 195 | 196 | 197 | const char* items[] = { "opaque", "blend" }; 198 | static int item_current = 0; 199 | if (ImGui::Combo("AlphaMode", &item_current, items, IM_ARRAYSIZE(items))) 200 | { 201 | if (item_current == 0) 202 | { 203 | _node->getOrCreateStateSet()->setMode(GL_BLEND, 0); 204 | } 205 | else { 206 | 207 | _node->getOrCreateStateSet()->setMode(GL_BLEND, 1); 208 | } 209 | 210 | } 211 | 212 | for (auto& def : _defines) 213 | { 214 | if (ImGui::Checkbox(def._name.c_str(), &def._checked)) 215 | { 216 | if (_node) 217 | { 218 | if (def._checked) 219 | { 220 | _node->getOrCreateStateSet()->setDefine(def._name, def._val, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); 221 | } 222 | else { 223 | _node->getOrCreateStateSet()->setDefine(def._name, osg::StateAttribute::OFF | osg::StateAttribute::OVERRIDE); 224 | } 225 | } 226 | 227 | } 228 | } 229 | 230 | 231 | ImGui::End(); 232 | } 233 | }; 234 | 235 | 236 | class LightGUI :public osgEarth::GUI::BaseGUI 237 | { 238 | public: 239 | 240 | osg::Light* _light; 241 | public: 242 | LightGUI(osg::Light* light) :GUI::BaseGUI("Light"), _light(light) 243 | { 244 | 245 | 246 | } 247 | 248 | void draw(osg::RenderInfo& ri)override { 249 | if (!isVisible()) { 250 | return; 251 | } 252 | ImGui::Begin(name(), visible()); 253 | 254 | 255 | ImGui::Separator(); 256 | { 257 | //IMGUI_DEMO_MARKER("Widgets/Basic/ColorEdit3, ColorEdit4"); 258 | auto ambient = _light->getAmbient(); 259 | auto diffuse = _light->getDiffuse(); 260 | auto direction = _light->getDirection(); 261 | static float col1[4] = { ambient[0],ambient[1], ambient[2], ambient[3] }; 262 | static float col2[4] = { diffuse[0],diffuse[1], diffuse[2], diffuse[3] }; 263 | static float col3[4] = { 0.4f, 0.7f, 0.0f, 0.5f }; 264 | static float col4[3] = { direction[0],direction[1], direction[2] }; 265 | static float itensity = 0.5f; 266 | static bool lightenable = true; 267 | if (ImGui::Checkbox("on/off", &lightenable)) 268 | { 269 | if (lightenable) 270 | { 271 | _light->setAmbient(osg::Vec4(col1[0], col1[1], col1[2], col1[3])); 272 | _light->setDiffuse(osg::Vec4(col2[0], col2[1], col2[2], col2[3])); 273 | _light->setDirection(osg::Vec3(col4[0], col4[1], col4[2])); 274 | } 275 | else { 276 | _light->setAmbient(osg::Vec4(0.0, 0.0, 0.0, 0.0)); 277 | _light->setDiffuse(osg::Vec4(0.0, 0.0, 0.0, 0.0)); 278 | _light->setDirection(osg::Vec3(0.0, 0.0, 0.0)); 279 | } 280 | } 281 | if (ImGui::ColorEdit4("ambient", col1)) 282 | { 283 | _light->setAmbient(osg::Vec4(col1[0], col1[1], col1[2], col1[3])); 284 | } 285 | if (ImGui::ColorEdit4("diffuse", col2)) 286 | { 287 | _light->setDiffuse(osg::Vec4(col2[0], col2[1], col2[2], col2[3])); 288 | } 289 | if (ImGui::ColorEdit4("direction", col4)) 290 | { 291 | _light->setDirection(osg::Vec3(col4[0], col4[1], col4[2])); 292 | std::cout << "setDirection" << col4[0] << " " << col4[1] << " " << col4[2] << std::endl; 293 | } 294 | if (ImGui::SliderFloat("intensity", &itensity, 0.0f, 1.0f)) 295 | { 296 | _light->setSpotExponent(itensity); 297 | 298 | } 299 | 300 | 301 | } 302 | ImGui::End(); 303 | } 304 | }; 305 | 306 | class IndirectLightGUI :public osgEarth::GUI::BaseGUI 307 | { 308 | 309 | public: 310 | IndirectLightGUI() :GUI::BaseGUI("IndirectLightGUI") 311 | { 312 | 313 | 314 | } 315 | 316 | void draw(osg::RenderInfo& ri)override { 317 | if (!isVisible()) { 318 | return; 319 | } 320 | ImGui::Begin(name(), visible()); 321 | 322 | 323 | ImGui::Separator(); 324 | { 325 | 326 | static float itensity = 0.5f; 327 | static bool lightenable = true; 328 | if (ImGui::Checkbox("on/off", &lightenable)) 329 | { 330 | EnvLightEffect::instance()->setEnable(lightenable); 331 | } 332 | if (ImGui::SliderFloat("intensity", &itensity, 0.0f, 1.0f)) 333 | { 334 | std::cout << "itensity" << itensity << std::endl; 335 | EnvLightEffect::instance()->setLightIntensity(itensity); 336 | 337 | } 338 | 339 | const char* items[] = { "pisaHDR", "abandoned_bakery_4k" }; 340 | static int item_current = 0; 341 | if (ImGui::Combo("EnvMap", &item_current, items, IM_ARRAYSIZE(items))) 342 | { 343 | if (item_current == 0) 344 | { 345 | EnvLightEffect::instance()->setEnvMapAtlas({ "pisaHDR\\diffuse.png", "pisaHDR\\specular.dds", "pisaHDR\\env.dds" }); 346 | } 347 | else { 348 | 349 | EnvLightEffect::instance()->setEnvMapAtlas({ "bakery\\diffuse_quad.png", "bakery\\specular_quad.dds", "bakery\\abandoned_bakery_4k.hdr" }); 350 | } 351 | 352 | } 353 | 354 | 355 | 356 | 357 | } 358 | ImGui::End(); 359 | } 360 | }; 361 | -------------------------------------------------------------------------------- /OE_PBR/main.cpp: -------------------------------------------------------------------------------- 1 | 2 | #define NOMINMAX 3 | //#define EARTH_GUI 4 | 5 | #include 6 | 7 | #ifdef EARTH_GUI 8 | #include "TestUI.h" 9 | #endif // EARTH_GUI 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | 41 | #include "GLTFV2Reader.h" 42 | #include "CreateHelper.h" 43 | #include "FlyCameraManipulator.h" 44 | 45 | // #define LC "[viewer] " 46 | 47 | const std::string PROJECT_PATH = "..//OE_PBR//"; 48 | 49 | template 50 | struct CB : public osg::NodeCallback 51 | { 52 | using F = std::function; 53 | F _func; 54 | CB(F func) 55 | : _func(func) 56 | { 57 | } 58 | void operator()(osg::Node* node, osg::NodeVisitor* nv) 59 | { 60 | _func(static_cast(node), nv); 61 | } 62 | }; 63 | 64 | using namespace osgEarth; 65 | using namespace osgEarth::Util; 66 | using NodePtr = osg::ref_ptr; 67 | 68 | int usage(const char* name) 69 | { 70 | OE_NOTICE 71 | << "\nUsage: " << name << " file.earth" << std::endl 72 | << MapNodeHelper().usage() << std::endl; 73 | 74 | return 0; 75 | } 76 | 77 | class CullCallback : public osg::NodeCallback 78 | { 79 | virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) 80 | { 81 | std::cout << "cull callback - pre traverse" << node << std::endl; 82 | traverse(node, nv); 83 | std::cout << "cull callback - post traverse" << node << std::endl; 84 | } 85 | }; 86 | 87 | 88 | void SetupSceneGraph(osgViewer::Viewer& viewer) 89 | { 90 | osg::ref_ptr modelDB = new osgDB::Options("model"); 91 | modelDB->setDatabasePath(PROJECT_PATH + "Asset"); 92 | 93 | auto iblDB = new osgDB::Options("IBL"); 94 | iblDB->setDatabasePath(PROJECT_PATH + "Asset//IBL"); 95 | 96 | osg::ref_ptr shaderDB = new osgDB::Options(); 97 | shaderDB->setName("osgEarthShader"); 98 | shaderDB->setDatabasePath(PROJECT_PATH + "Asset//Shader"); 99 | osgDB::Registry::instance()->getObjectWrapperManager()->findWrapper("osg::Image"); 100 | 101 | 102 | auto baseGraph = new osg::Group(); 103 | 104 | // init env light 105 | EnvLightEffect::instance()->setEnvMapAtlas({ "pisaHDR\\diffuse.dds", "pisaHDR\\specular.dds", "pisaHDR\\env.dds" }, iblDB); 106 | EnvLightEffect::instance()->setEnable(true); 107 | 108 | // init models 109 | GLTFReaderV2 reader; 110 | auto gltfModel = reader.read("Dragon\\DragonAttenuation.gltf", false, modelDB); 111 | // Helmet\\DamagedHelmet BoomBox\\BoomBox Sponza\\Sponza Sheen\\SheenChair.glb Dragon\\DragonAttenuation 112 | auto gltfNode = gltfModel.getNode(); 113 | 114 | // init material spheres 115 | auto materialSpheres = createMaterialSpheres(2); 116 | baseGraph->addChild(materialSpheres); 117 | 118 | // init skybox 119 | baseGraph->addChild(createSkyBox()); 120 | 121 | //init lights 122 | osg::Light* lightState = new osg::Light; 123 | auto light = CreateLight(lightState, baseGraph); 124 | baseGraph->addChild(light); 125 | 126 | auto func = [&](osg::MatrixTransform* node, osg::NodeVisitor* nv) 127 | { 128 | auto matrix = node->getMatrix(); 129 | 130 | node->setMatrix(matrix * osg::Matrix(osg::Quat(0.01, osg::Vec3(0.0, 0.0, 1.0)))); 131 | }; 132 | 133 | osg::Group* sceneData = new osg::Group; 134 | sceneData->addChild(baseGraph); 135 | 136 | auto nv = new GenerateEnvLightUniforms(); 137 | baseGraph->accept(*nv); 138 | auto gpNV = new GenerateProbeUniforms(); 139 | baseGraph->accept(*gpNV); 140 | 141 | // init transparent pass 142 | TransparentCamera::Ptr tCam = new TransparentCamera(); 143 | tCam->setView(&viewer); 144 | tCam->setGraph(baseGraph); 145 | 146 | sceneData->addChild(tCam); 147 | viewer.setSceneData(sceneData); 148 | 149 | #ifdef EARTH_GUI 150 | // init gui 151 | GUI::ApplicationGUI* gui = new GUI::ApplicationGUI(true); 152 | auto materialPanel = new MaterialGUI(); 153 | gui->add("Demo", materialPanel); 154 | gui->add("Demo2", new LightGUI(lightState)); 155 | gui->add("Demo3", new IndirectLightGUI()); 156 | viewer.getEventHandlers().push_front(gui); 157 | 158 | auto findCallback = [materialPanel](osg::MatrixTransform* node) 159 | { 160 | node->getName(); 161 | materialPanel->setNode(node); 162 | return true; 163 | }; 164 | viewer.addEventHandler(new RayPicker(&viewer, findCallback)); 165 | #endif // EARTH_GUI 166 | 167 | } 168 | 169 | 170 | int main(int argc, char** argv) 171 | { 172 | 173 | osg::ArgumentParser arguments(&argc, argv); 174 | int versio = osg::getGLVersionNumber(); 175 | arguments.getApplicationUsage()->setApplicationName("osgEarth PBR Material"); 176 | osgViewer::Viewer viewer(arguments); 177 | viewer.setReleaseContextAtEndOfFrameHint(false); 178 | viewer.getDatabasePager()->setUnrefImageDataAfterApplyPolicy(true, false); 179 | auto name = arguments.getApplicationUsage()->getApplicationName(); 180 | 181 | const int width(800), height(450); 182 | const std::string version("3.0"); 183 | osg::ref_ptr traits = new osg::GraphicsContext::Traits(); 184 | traits->x = 20; 185 | traits->y = 30; 186 | traits->width = width; 187 | traits->height = height; 188 | traits->windowDecoration = true; 189 | traits->glContextProfileMask = 0X1; 190 | traits->doubleBuffer = true; 191 | traits->readDISPLAY(); 192 | traits->setUndefinedScreenDetailsToDefaultScreen(); 193 | osg::ref_ptr gc = osg::GraphicsContext::createGraphicsContext(traits.get()); 194 | osg::setNotifyLevel(osg::NotifySeverity::ALWAYS); 195 | if (!gc.valid()) 196 | { 197 | osg::notify(osg::FATAL) << "Unable to create OpenGL v" << version << " context." << std::endl; 198 | return (1); 199 | } 200 | 201 | viewer.setReleaseContextAtEndOfFrameHint(false); 202 | 203 | #ifdef EARTH_GUI 204 | viewer.setRealizeOperation(new GUI::ApplicationGUI::RealizeOperation); 205 | #endif 206 | 207 | SetupSceneGraph(viewer); 208 | 209 | viewer.setCameraManipulator(new osgGA::UnityCameraManipulator); 210 | viewer.setUpViewInWindow(100, 100, 800, 600); 211 | osgViewer::Viewer::Windows windows; 212 | viewer.getWindows(windows); 213 | //windows.front()->setCursor(osgViewer::GraphicsWindow::MouseCursor::HandCursor); 214 | viewer.realize(); 215 | 216 | Metrics::setEnabled(true); 217 | Metrics::setGPUProfilingEnabled(true); 218 | return Metrics::run(viewer); 219 | /* viewer.run();*/ 220 | /*return 0;*/ 221 | } 222 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OSGEARTH PBR MATERIAL LIB 2 | 3 | Tutorial:https://zhuanlan.zhihu.com/p/653871547 4 | Video: https://www.bilibili.com/video/BV14b41197DL?p=9&vd_source=7bfbfedb02b03e995d21f8ad506f2b86 5 | 6 | ## V1.0 7 | - 提供osgEarth::StandardPBRMaterial 8 | - GLTFReaderV2读取gltf2.0模型 9 | - PbrLightEffect实现Cook_BRDF光照 10 | 11 | ## V1.1 12 | - 新增透明材质 13 | - 新增IBL环境光照 14 | - 扩展了dds插件对CubeMap的读取 和 GL_RGBA_ARB扩展压缩格式的支持 15 | - 【Tool】 cubemap -> quadMap 16 | 17 | ## V1.2 18 | - 提供osgEarth::ExtensionedMaterial 可自定义材质 19 | - 实现了waterial example from ue 20 | - 可以切换 HDR specularHDR 可设置mipmap 21 | - OPAQUE 22 | 23 | ## V1.3 24 | - 提供osgEarth::AdvancedMaterial 25 | - 支持sheen和clearcloat特性 26 | - gtlf插件增加对khr_extenison的支持 27 | - 完成relection probe cubeCamera以支持transmission 28 | 29 | # TODO 30 | - 透明材质 31 | - 后处理 32 | - 提供osg自己的材质资产格式 .omat 33 | - gltf插件和dds插件编译好 34 | 35 | - sheen tranmission ior anisotropy variants iridescence 36 | - exposure -------------------------------------------------------------------------------- /screenshot/II66YW(H$T@UR9OP5J[T)GS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fang1067720863/osgPBR/dba01b6cbc42c0ccb2e0611fcad1c04e27288f15/screenshot/II66YW(H$T@UR9OP5J[T)GS.png -------------------------------------------------------------------------------- /screenshot/custom_material.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fang1067720863/osgPBR/dba01b6cbc42c0ccb2e0611fcad1c04e27288f15/screenshot/custom_material.png -------------------------------------------------------------------------------- /screenshot/gltfPBR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fang1067720863/osgPBR/dba01b6cbc42c0ccb2e0611fcad1c04e27288f15/screenshot/gltfPBR.png -------------------------------------------------------------------------------- /screenshot/metalRoughness.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fang1067720863/osgPBR/dba01b6cbc42c0ccb2e0611fcad1c04e27288f15/screenshot/metalRoughness.png -------------------------------------------------------------------------------- /screenshot/sheen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fang1067720863/osgPBR/dba01b6cbc42c0ccb2e0611fcad1c04e27288f15/screenshot/sheen.png -------------------------------------------------------------------------------- /screenshot/split_sum.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fang1067720863/osgPBR/dba01b6cbc42c0ccb2e0611fcad1c04e27288f15/screenshot/split_sum.png -------------------------------------------------------------------------------- /screenshot/thickGlass.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fang1067720863/osgPBR/dba01b6cbc42c0ccb2e0611fcad1c04e27288f15/screenshot/thickGlass.png -------------------------------------------------------------------------------- /screenshot/thinTranslucent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fang1067720863/osgPBR/dba01b6cbc42c0ccb2e0611fcad1c04e27288f15/screenshot/thinTranslucent.png --------------------------------------------------------------------------------