diff --git a/README.md b/README.md new file mode 100644 index 0000000..c04df22 --- /dev/null +++ b/README.md @@ -0,0 +1,66 @@ +# GLSL Explorer + +Simple OpenGL based GLSL shader visualizer. + +## What does it do? + +GLSL Explorer simply allows you to import any GLSL fragment shader from a file, +and visualize it on a 2D plane. It supports viewport navigation with panning and zooming, +custom uniforms, multiple render passes and framebuffer export. + +## How do I build it? + +The project is self contained, all dependencies (glew, glfw, ImGui and stb_image) are directly integrated into it. Clone this repo anywhere you like, then open the folder in your favorite terminal and do: +``` +cmake -S . -B build +cmake --build ./build +``` + +## How do I use it? + +### Writing a shader + +All you technically need is to write the main function for your fragment shader, like this: +```glsl +void main(){ + frag0 = vec4(1); +} +``` + +The fragment shader has 8 outputs, frag0 to frag7. It also provides you with the following inputs: +```glsl +in vec4 pos; // the fragment position +in vec2 uv; // normalized screen space coordinates +uniform float scale; // the viewport scale parameter +uniform vec4 offset; // the viewport position parameter +uniform float time; // runtime +uniform vec2 res; // dimensions of the screen, in pixels +uniform sampler2D texNoise; // a white noise texture +``` + +To add your own inputs, simply add a uniform in your shader file, it will automatically appear in the UI, +in the "Shader parameters" section. +Only the following data types are supported: float, vec2, vec3, vec4, int, ivec2, ivec3, ivec4, bool, +bvec2, bvec3, bvec4. + +### General settings + +In this section your can find the general setup of the program: +- **Shader file**: the path to the GLSL file to load +- **Scale**: The global viewport scale level (decreasing the value "zooms in") +- **Position**: 4D offset to pan around +- **Mouse sensitivity**: Scale and position adjustment sensitivity +- **Slider sensitivity**: How sensitive should the sliders be for the custom shader parameters +- **Render pass**: Selects the output texture currently being displayed on screen + +### Navigation + +To pan the view, simply click and drag. To zoom in and out, hold shift and click and drag to the right/left. + +### Screenshots + +The "Save screenshot" button exports the contents of the current frame to file named "out.png" in the current working directory. + +## Going further + +The [examples](examples) folder contains a few premade shaders. \ No newline at end of file diff --git a/examples/blank.glsl b/examples/blank.glsl index acb8ed0..5e99214 100644 --- a/examples/blank.glsl +++ b/examples/blank.glsl @@ -6,5 +6,5 @@ void main(){ frag4 = vec4(1, 0, 0, 1); frag5 = vec4(1, 0, 1, 1); frag6 = vec4(1, 1, 0, 1); - frag7 = vec4(1, 1, 1, 1); + frag7 = vec4(1); } \ No newline at end of file diff --git a/examples/mandelbrot.glsl b/examples/mandelbrot.glsl index 7a57f76..35561ac 100644 --- a/examples/mandelbrot.glsl +++ b/examples/mandelbrot.glsl @@ -21,8 +21,9 @@ vec4 palette[16] = { }; void main(){ - vec2 C = pos.xy; + vec2 C = pos.xy * scale; C.x *= res.x/res.y; + C += offset.xy; vec2 Z = vec2(0); int i = 0; while(i++ < maxIter && dot(Z, Z) <= 4){ diff --git a/examples/palette.py b/examples/palette.py deleted file mode 100644 index c4234bd..0000000 --- a/examples/palette.py +++ /dev/null @@ -1,7 +0,0 @@ - -u = .5 -s = 0 -for _ in range(1000): - s += u - u /=2 -print(s) \ No newline at end of file diff --git a/main.cpp b/main.cpp index 98be692..2000242 100644 --- a/main.cpp +++ b/main.cpp @@ -27,7 +27,6 @@ class GLExplorer: public GLBase::Application GLBase::Texture _textures[8]; GLBase::Texture _noise; - int _selectedRenderPass = 0; static constexpr const char *_renderPasses[] = { "Pass 0", @@ -40,6 +39,7 @@ class GLExplorer: public GLBase::Application "Pass 7", }; + bool _showInspector = true; bool _vsync = 0; std::chrono::steady_clock::time_point _start; float _scale = 1.0f; @@ -229,7 +229,26 @@ class GLExplorer: public GLBase::Application ImGui::Text("Couldn't save frame: %s", strerror(errno)); ImGui::End(); } + if(ImGui::BeginMainMenuBar()){ + if(ImGui::BeginMenu("View")){ + ImGui::MenuItem("Show inspector", "Ctrl+1", &_showInspector); + ImGui::EndMenu(); + } + ImGui::EndMainMenuBar(); + } + if(_glslStatus.errStatus){ + ImGui::Begin("GLSL Error"); + ImGui::TextColored(ImVec4{1, 0, 0, 1}, "%s", _glslStatus.message.c_str()); + ImGui::End(); + } + if(_fileErrorPopup){ + ImGui::Begin("Error", &_fileErrorPopup); + ImGui::TextColored(ImVec4{1, 0, 0, 1}, "Couldn't load %s: %s", + _filePath.c_str(), strerror(errno)); + ImGui::End(); + } + if(!_showInspector) return; ImGui::Begin("Inspector"); ImGui::Text("%f FPS", ImGui::GetIO().Framerate); if(ImGui::TreeNode("General settings")){ @@ -264,17 +283,6 @@ class GLExplorer: public GLBase::Application _saveFrame = ImGui::Button("Save screenshot"); ImGui::End(); - if(_glslStatus.errStatus){ - ImGui::Begin("GLSL Error"); - ImGui::TextColored(ImVec4{1, 0, 0, 1}, "%s", _glslStatus.message.c_str()); - ImGui::End(); - } - if(_fileErrorPopup){ - ImGui::Begin("Error", &_fileErrorPopup); - ImGui::TextColored(ImVec4{1, 0, 0, 1}, "Couldn't load %s: %s", - _filePath.c_str(), strerror(errno)); - ImGui::End(); - } } bool loadFragmentShaderFromFile(const std::string& path) { std::ifstream f(path, std::ios_base::binary); diff --git a/out.png b/out.png new file mode 100644 index 0000000..4934148 Binary files /dev/null and b/out.png differ