DYT/Tool/OpenSceneGraph-3.6.5/include/osgEarthImGui/ShaderGUI

190 lines
6.9 KiB
Plaintext
Raw Normal View History

2024-12-24 23:49:36 +00:00
/* -*-c++-*- */
/* osgEarth - Geospatial SDK for OpenSceneGraph
* Copyright 2018 Pelican Mapping
* http://osgearth.org
*
* osgEarth is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#pragma once
#include <osgEarthImGui/ImGuiPanel>
#include <osgEarth/Registry>
#include <osgEarth/VirtualProgram>
#include <osg/Uniform>
#include <osg/StateSet>
#include <chrono>
#include <list>
#include <vector>
namespace osgEarth
{
using namespace osgEarth::Threading;
using namespace osgEarth::Util;
class ShaderGUI : public ImGuiPanel
{
private:
struct UniformSpec {
std::string _name;
float _minval, _maxval, _value;
osg::ref_ptr<osg::Uniform> _u;
};
std::vector<UniformSpec> _uniforms;
struct DefineSpec {
std::string _name;
bool _checked;
};
std::vector<DefineSpec> _defines;
ProgramRepo::ProgramMap _db;
public:
ShaderGUI(osg::ArgumentParser* args = nullptr) : ImGuiPanel("Shaders")
{
if (args)
{
while (args->find("--uniform") >= 0)
{
UniformSpec spec;
if (args->read("--uniform", spec._name, spec._minval, spec._maxval))
{
spec._value = clamp(0.0f, spec._minval, spec._maxval);
spec._u = new osg::Uniform(spec._name.c_str(), spec._value);
_uniforms.emplace_back(spec);
}
}
while (args->find("--define") >= 0)
{
DefineSpec spec;
if (args->read("--define", spec._name))
{
spec._checked = false;
_defines.push_back(spec);
}
}
}
}
void load(const Config& conf) override
{
}
void save(Config& conf) override
{
}
void draw(osg::RenderInfo& ri) override
{
if (!isVisible())
return;
ImGui::Begin(name(), visible());
{
if (!_uniforms.empty())
ImGui::Text("Uniforms:");
for (auto& def : _uniforms)
{
if (ImGui::SliderFloat(def._name.c_str(), &def._value, def._minval, def._maxval))
{
def._u->set(def._value);
ri.getCurrentCamera()->getOrCreateStateSet()->addUniform(def._u.get(), osg::StateAttribute::OVERRIDE);
}
}
if (!_defines.empty())
ImGui::Text("Defines:");
for (auto& def : _defines)
{
if (ImGui::Checkbox(def._name.c_str(), &def._checked))
{
if (def._checked)
ri.getCurrentCamera()->getOrCreateStateSet()->setDefine(def._name, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
else
ri.getCurrentCamera()->getOrCreateStateSet()->setDefine(def._name, osg::StateAttribute::OFF | osg::StateAttribute::OVERRIDE);
}
}
ImGui::Separator();
ImGui::TextColored(ImVec4(1, 1, 0, 1), "Active Programs:");
if (_db.empty() || ImGui::Button("Refresh"))
{
_db = Registry::programRepo().copy();
}
static void* open_shader = nullptr;
int count = 0;
int frame = ri.getState()->getFrameStamp()->getFrameNumber();
for (auto& entry : _db)
{
if (entry.second->_users.size() > 0 && (frame - entry.second->_frameLastUsed < 60))
{
auto program = entry.second->_program;
auto name = program->getName();
if (name.empty()) name = "[no name]";
std::string tag = name + "##" + std::to_string(count++);
if (ImGui::TreeNode(tag.c_str())) //name.c_str()))
{
auto num = program->getNumShaders();
for (unsigned i = 0; i < num; ++i)
{
auto shader = program->getShader(i);
auto shader_name = shader->getName();
if (shader_name.empty()) shader_name = "[no name]";
ImGui::PushID(count++);
std::string shader_tag = shader_name + "##" + std::to_string(count++);
if (ImGui::Button(shader_tag.c_str()))
{
open_shader = shader;
}
if (open_shader == shader)
{
ImGui::SetNextWindowSize(ImVec2(800, 600), ImGuiCond_FirstUseEver);
ImGui::Begin(shader_name.c_str());
if (ImGui::Button("Compile"))
program->releaseGLObjects(nullptr);
ImGui::SameLine();
if (ImGui::Button("Close"))
open_shader = nullptr;
auto text = shader->getShaderSource();
if (ImGuiEx::InputTextMultiline("##shader_source", &text, ImVec2(-1, -1)))
{
shader->setShaderSource(text);
program->releaseGLObjects(nullptr);
}
ImGui::End();
}
ImGui::PopID();
}
ImGui::TreePop();
}
}
}
}
ImGui::End();
}
};
}