mirror of
https://github.com/brunoherbelin/vimix.git
synced 2025-12-21 15:20:00 +01:00
New User defined uniforms in Custom shaders
This commit is contained in:
@@ -967,6 +967,27 @@ bool Control::receiveSourceAttribute(Source *target, const std::string &attribut
|
||||
textsrc->contents()->setText(label);
|
||||
}
|
||||
}
|
||||
/// e.g. '/vimix/current/uniform sf var 0.5'
|
||||
else if (attribute.compare(OSC_SOURCE_UNIFORM) == 0) {
|
||||
std::string uniform_name;
|
||||
float uniform_value = NAN;
|
||||
|
||||
const char *str = nullptr;
|
||||
arguments >> str;
|
||||
uniform_name = std::string(str);
|
||||
|
||||
arguments >> uniform_value >> osc::EndMessage;
|
||||
|
||||
|
||||
CloneSource *clonesrc = dynamic_cast<CloneSource *>(target);
|
||||
if (clonesrc) {
|
||||
ImageFilter *f = dynamic_cast<ImageFilter *>(clonesrc->filter());
|
||||
if (f) {
|
||||
f->setProgramParameter(uniform_name, uniform_value);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/// e.g. '/vimix/current/filter sf blur 0.5'
|
||||
else if (attribute.compare(OSC_SOURCE_FILTER) == 0) {
|
||||
std::string filter_name;
|
||||
|
||||
@@ -71,6 +71,7 @@
|
||||
#define OSC_SOURCE_TEXSIZE "/texture_size"
|
||||
#define OSC_SOURCE_TEXANGLE "/texture_angle"
|
||||
#define OSC_SOURCE_FILTER "/filter"
|
||||
#define OSC_SOURCE_UNIFORM "/uniform"
|
||||
|
||||
#define OSC_SESSION "/session"
|
||||
#define OSC_SESSION_VERSION "/version"
|
||||
|
||||
@@ -1377,6 +1377,12 @@ void ImGuiVisitor::visit (ImageFilter& f)
|
||||
FilteringProgram target;
|
||||
f.setProgram( target );
|
||||
}
|
||||
|
||||
// List of parameters
|
||||
std::ostringstream oss;
|
||||
oss << "Custom ";
|
||||
list_parameters_(f, oss);
|
||||
|
||||
}
|
||||
|
||||
void ImGuiVisitor::visit (CloneSource& s)
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
**/
|
||||
#include <ctime>
|
||||
#include <algorithm>
|
||||
#include <regex>
|
||||
|
||||
#include <glm/gtc/matrix_access.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
@@ -26,6 +27,7 @@
|
||||
#include "Visitor.h"
|
||||
#include "FrameBuffer.h"
|
||||
#include "Primitives.h"
|
||||
#include "BaseToolkit.h"
|
||||
|
||||
#include "ImageFilter.h"
|
||||
|
||||
@@ -150,6 +152,17 @@ bool FilteringProgram::operator!= (const FilteringProgram& other) const
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FilteringProgram::hasParameter(const std::string &p)
|
||||
{
|
||||
return parameters_.find(p) != parameters_.end();
|
||||
}
|
||||
|
||||
void FilteringProgram::removeParameter(const std::string &p)
|
||||
{
|
||||
if (hasParameter(p))
|
||||
parameters_.erase(p);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////
|
||||
///// //
|
||||
@@ -168,6 +181,7 @@ ImageFilteringShader::ImageFilteringShader(): ImageShader()
|
||||
timer_ = g_timer_new ();
|
||||
iTime_ = 0.0;
|
||||
iFrame_ = 0;
|
||||
uniforms_changed_ = true;
|
||||
|
||||
ImageShader::reset();
|
||||
}
|
||||
@@ -216,9 +230,17 @@ void ImageFilteringShader::use()
|
||||
//
|
||||
// loop over uniforms
|
||||
//
|
||||
for (auto u = uniforms_.begin(); u != uniforms_.end(); ++u)
|
||||
for (auto u = uniforms_.begin(); u != uniforms_.end(); ) {
|
||||
// set uniform to current value
|
||||
program_->setUniform( u->first, u->second );
|
||||
if ( program_->setUniform(u->first, u->second) )
|
||||
// uniform variable could be set, keep it
|
||||
++u;
|
||||
else {
|
||||
// uniform variable does not exist in code, remove it
|
||||
u = uniforms_.erase(u);
|
||||
uniforms_changed_ = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ImageFilteringShader::reset()
|
||||
@@ -242,7 +264,7 @@ void ImageFilteringShader::setCode(const std::string &code, std::promise<std::st
|
||||
// shader is composed of a header, the given code and a footer
|
||||
shader_code_ = fragmentHeader + code_ + fragmentFooter;
|
||||
// shift line numbers by number of lines in header
|
||||
std::string::difference_type n = std::count(fragmentHeader.begin(), fragmentHeader.end(), '\n');
|
||||
static std::string::difference_type n = std::count(fragmentHeader.begin(), fragmentHeader.end(), '\n');
|
||||
// launch build
|
||||
custom_shading_.setShaders("shaders/image.vs", shader_code_, (int)n, ret);
|
||||
}
|
||||
@@ -309,6 +331,19 @@ void ImageFilter::update (float dt)
|
||||
|
||||
if ( program_.isTwoPass() )
|
||||
shaders_.second->update(dt);
|
||||
|
||||
// uniforms changed in main shader
|
||||
if ( shaders_.first->uniforms_changed_ ) {
|
||||
// loop over the parameters of the program...
|
||||
std::map<std::string, float> __P = program_.parameters();
|
||||
for (auto param = __P.begin(); param != __P.end(); ++param) {
|
||||
// .. and remove the parameters that are not valid uniforms
|
||||
if (shaders_.first->uniforms_.count(param->first) < 1)
|
||||
program_.removeParameter(param->first);
|
||||
}
|
||||
// done
|
||||
shaders_.first->uniforms_changed_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
uint ImageFilter::texture () const
|
||||
@@ -392,6 +427,9 @@ FilteringProgram ImageFilter::program () const
|
||||
return program_;
|
||||
}
|
||||
|
||||
#define REGEX_UNIFORM_DECLARATION "uniform\\s+float\\s+"
|
||||
#define REGEX_UNIFORM_VALUE "(\\s*=\\s*[[:digit:]](\\.[[:digit:]])?)?\\s*\\;"
|
||||
|
||||
void ImageFilter::setProgram(const FilteringProgram &f, std::promise<std::string> *ret)
|
||||
{
|
||||
// always keep local copy
|
||||
@@ -404,11 +442,42 @@ void ImageFilter::setProgram(const FilteringProgram &f, std::promise<std::string
|
||||
// set code to the shader for first-pass
|
||||
shaders_.first->setCode( codes.first, ret );
|
||||
|
||||
// Parse code to detect additional declaration of uniform variables
|
||||
// Search for "uniform float", a variable name, with possibly a '=' and float value
|
||||
std::string glslcode(codes.first);
|
||||
std::smatch found_uniform;
|
||||
std::regex is_a_uniform(REGEX_UNIFORM_DECLARATION "[[:alpha:]]+" REGEX_UNIFORM_VALUE);
|
||||
// loop over every uniform declarations in the GLSL code
|
||||
while (std::regex_search(glslcode, found_uniform, is_a_uniform)) {
|
||||
// found a complete declaration of uniform variable
|
||||
std::string declaration = found_uniform.str();
|
||||
// extract variable name by erasing everything else
|
||||
std::string varname =
|
||||
std::regex_replace(declaration,std::regex(REGEX_UNIFORM_DECLARATION),"");
|
||||
varname = std::regex_replace(varname, std::regex(REGEX_UNIFORM_VALUE), "");
|
||||
// add to list of parameters if was not already there, with default value
|
||||
if ( !program_.hasParameter(varname) )
|
||||
program_.setParameter(varname, 0.f);
|
||||
|
||||
// try to find a value in uniform declaration, and set parameter value if valid
|
||||
float val = 0.f;
|
||||
std::smatch found_value;
|
||||
std::regex is_a_float_value("[[:digit:]](\\.[[:digit:]])?");
|
||||
if (std::regex_search(declaration, found_value, is_a_float_value)) {
|
||||
// set value only if a value is given
|
||||
if ( BaseToolkit::is_a_value(found_value.str(), &val) )
|
||||
program_.setParameter(varname, val);
|
||||
}
|
||||
// keep parsing
|
||||
glslcode = found_uniform.suffix().str();
|
||||
}
|
||||
|
||||
// SECOND PASS
|
||||
if ( program_.isTwoPass() )
|
||||
// set the code to the shader for second-pass
|
||||
shaders_.second->setCode( codes.second );
|
||||
shaders_.second->setCode(codes.second);
|
||||
|
||||
// UPDATE UNIFORMS
|
||||
updateParameters();
|
||||
}
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ public:
|
||||
std::pair< std::string, std::string > code();
|
||||
|
||||
// if has second pass
|
||||
bool isTwoPass() const { return two_pass_filter_; }
|
||||
inline bool isTwoPass() const { return two_pass_filter_; }
|
||||
|
||||
// set the list of parameters
|
||||
inline void setParameters(const std::map< std::string, float > ¶meters) { parameters_ = parameters; }
|
||||
@@ -57,6 +57,8 @@ public:
|
||||
|
||||
// set the value of a parameter
|
||||
inline void setParameter(const std::string &p, float value) { parameters_[p] = value; }
|
||||
bool hasParameter(const std::string &p);
|
||||
void removeParameter(const std::string &p);
|
||||
|
||||
// globals
|
||||
static std::string getFilterCodeInputs();
|
||||
@@ -85,6 +87,7 @@ public:
|
||||
|
||||
// list of uniforms to control shader
|
||||
std::map< std::string, float > uniforms_;
|
||||
bool uniforms_changed_;
|
||||
|
||||
ImageFilteringShader();
|
||||
~ImageFilteringShader();
|
||||
|
||||
@@ -232,52 +232,89 @@ void ShadingProgram::reset()
|
||||
}
|
||||
|
||||
template<>
|
||||
void ShadingProgram::setUniform<int>(const std::string& name, int val) {
|
||||
glUniform1i(glGetUniformLocation(id_, name.c_str()), val);
|
||||
bool ShadingProgram::setUniform<int>(const std::string &name, int val)
|
||||
{
|
||||
GLint uid = glGetUniformLocation(id_, name.c_str());
|
||||
if (uid < 0)
|
||||
return false;
|
||||
glUniform1i(uid, val);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<>
|
||||
void ShadingProgram::setUniform<bool>(const std::string& name, bool val) {
|
||||
glUniform1i(glGetUniformLocation(id_, name.c_str()), val);
|
||||
bool ShadingProgram::setUniform<bool>(const std::string& name, bool val) {
|
||||
GLint uid = glGetUniformLocation(id_, name.c_str());
|
||||
if (uid < 0)
|
||||
return false;
|
||||
glUniform1i(uid, val);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<>
|
||||
void ShadingProgram::setUniform<float>(const std::string& name, float val) {
|
||||
glUniform1f(glGetUniformLocation(id_, name.c_str()), val);
|
||||
bool ShadingProgram::setUniform<float>(const std::string& name, float val) {
|
||||
GLint uid = glGetUniformLocation(id_, name.c_str());
|
||||
if (uid < 0)
|
||||
return false;
|
||||
glUniform1f(uid, val);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<>
|
||||
void ShadingProgram::setUniform<float>(const std::string& name, float val1, float val2) {
|
||||
glUniform2f(glGetUniformLocation(id_, name.c_str()), val1, val2);
|
||||
bool ShadingProgram::setUniform<float>(const std::string& name, float val1, float val2) {
|
||||
GLint uid = glGetUniformLocation(id_, name.c_str());
|
||||
if (uid < 0)
|
||||
return false;
|
||||
glUniform2f(uid, val1, val2);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<>
|
||||
void ShadingProgram::setUniform<float>(const std::string& name, float val1, float val2, float val3) {
|
||||
glUniform3f(glGetUniformLocation(id_, name.c_str()), val1, val2, val3);
|
||||
bool ShadingProgram::setUniform<float>(const std::string& name, float val1, float val2, float val3) {
|
||||
GLint uid = glGetUniformLocation(id_, name.c_str());
|
||||
if (uid < 0)
|
||||
return false;
|
||||
glUniform3f(uid, val1, val2, val3);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<>
|
||||
void ShadingProgram::setUniform<glm::vec2>(const std::string& name, glm::vec2 val) {
|
||||
bool ShadingProgram::setUniform<glm::vec2>(const std::string& name, glm::vec2 val) {
|
||||
glm::vec2 v(val);
|
||||
glUniform2fv(glGetUniformLocation(id_, name.c_str()), 1, glm::value_ptr(v));
|
||||
GLint uid = glGetUniformLocation(id_, name.c_str());
|
||||
if (uid < 0)
|
||||
return false;
|
||||
glUniform2fv(uid, 1, glm::value_ptr(v));
|
||||
return true;
|
||||
}
|
||||
|
||||
template<>
|
||||
void ShadingProgram::setUniform<glm::vec3>(const std::string& name, glm::vec3 val) {
|
||||
bool ShadingProgram::setUniform<glm::vec3>(const std::string& name, glm::vec3 val) {
|
||||
glm::vec3 v(val);
|
||||
glUniform3fv(glGetUniformLocation(id_, name.c_str()), 1, glm::value_ptr(v));
|
||||
GLint uid = glGetUniformLocation(id_, name.c_str());
|
||||
if (uid < 0)
|
||||
return false;
|
||||
glUniform3fv(uid, 1, glm::value_ptr(v));
|
||||
return true;
|
||||
}
|
||||
|
||||
template<>
|
||||
void ShadingProgram::setUniform<glm::vec4>(const std::string& name, glm::vec4 val) {
|
||||
bool ShadingProgram::setUniform<glm::vec4>(const std::string& name, glm::vec4 val) {
|
||||
glm::vec4 v(val);
|
||||
glUniform4fv(glGetUniformLocation(id_, name.c_str()), 1, glm::value_ptr(v));
|
||||
GLint uid = glGetUniformLocation(id_, name.c_str());
|
||||
if (uid < 0)
|
||||
return false;
|
||||
glUniform4fv(uid, 1, glm::value_ptr(v));
|
||||
return true;
|
||||
}
|
||||
|
||||
template<>
|
||||
void ShadingProgram::setUniform<glm::mat4>(const std::string& name, glm::mat4 val) {
|
||||
bool ShadingProgram::setUniform<glm::mat4>(const std::string& name, glm::mat4 val) {
|
||||
glm::mat4 m(val);
|
||||
glUniformMatrix4fv(glGetUniformLocation(id_, name.c_str()), 1, GL_FALSE, glm::value_ptr(m));
|
||||
GLint uid = glGetUniformLocation(id_, name.c_str());
|
||||
if (uid < 0)
|
||||
return false;
|
||||
glUniformMatrix4fv(uid, 1, GL_FALSE, glm::value_ptr(m));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -25,9 +25,9 @@ public:
|
||||
static void enduse();
|
||||
void reset();
|
||||
|
||||
template<typename T> void setUniform(const std::string& name, T val);
|
||||
template<typename T> void setUniform(const std::string& name, T val1, T val2);
|
||||
template<typename T> void setUniform(const std::string& name, T val1, T val2, T val3);
|
||||
template<typename T> bool setUniform(const std::string& name, T val);
|
||||
template<typename T> bool setUniform(const std::string& name, T val1, T val2);
|
||||
template<typename T> bool setUniform(const std::string& name, T val1, T val2, T val3);
|
||||
|
||||
private:
|
||||
unsigned int id_;
|
||||
@@ -54,7 +54,7 @@ public:
|
||||
virtual void use();
|
||||
virtual void reset();
|
||||
virtual void accept(Visitor& v);
|
||||
void copy(Shader const& S);
|
||||
void copy(Shader const &S);
|
||||
|
||||
glm::mat4 projection;
|
||||
glm::mat4 modelview;
|
||||
|
||||
Reference in New Issue
Block a user