mirror of
https://github.com/brunoherbelin/vimix.git
synced 2025-12-20 22:59:59 +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);
|
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'
|
/// e.g. '/vimix/current/filter sf blur 0.5'
|
||||||
else if (attribute.compare(OSC_SOURCE_FILTER) == 0) {
|
else if (attribute.compare(OSC_SOURCE_FILTER) == 0) {
|
||||||
std::string filter_name;
|
std::string filter_name;
|
||||||
|
|||||||
@@ -71,6 +71,7 @@
|
|||||||
#define OSC_SOURCE_TEXSIZE "/texture_size"
|
#define OSC_SOURCE_TEXSIZE "/texture_size"
|
||||||
#define OSC_SOURCE_TEXANGLE "/texture_angle"
|
#define OSC_SOURCE_TEXANGLE "/texture_angle"
|
||||||
#define OSC_SOURCE_FILTER "/filter"
|
#define OSC_SOURCE_FILTER "/filter"
|
||||||
|
#define OSC_SOURCE_UNIFORM "/uniform"
|
||||||
|
|
||||||
#define OSC_SESSION "/session"
|
#define OSC_SESSION "/session"
|
||||||
#define OSC_SESSION_VERSION "/version"
|
#define OSC_SESSION_VERSION "/version"
|
||||||
|
|||||||
@@ -1377,6 +1377,12 @@ void ImGuiVisitor::visit (ImageFilter& f)
|
|||||||
FilteringProgram target;
|
FilteringProgram target;
|
||||||
f.setProgram( target );
|
f.setProgram( target );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// List of parameters
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "Custom ";
|
||||||
|
list_parameters_(f, oss);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImGuiVisitor::visit (CloneSource& s)
|
void ImGuiVisitor::visit (CloneSource& s)
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
**/
|
**/
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <regex>
|
||||||
|
|
||||||
#include <glm/gtc/matrix_access.hpp>
|
#include <glm/gtc/matrix_access.hpp>
|
||||||
#include <glm/gtc/matrix_transform.hpp>
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
@@ -26,6 +27,7 @@
|
|||||||
#include "Visitor.h"
|
#include "Visitor.h"
|
||||||
#include "FrameBuffer.h"
|
#include "FrameBuffer.h"
|
||||||
#include "Primitives.h"
|
#include "Primitives.h"
|
||||||
|
#include "BaseToolkit.h"
|
||||||
|
|
||||||
#include "ImageFilter.h"
|
#include "ImageFilter.h"
|
||||||
|
|
||||||
@@ -150,6 +152,17 @@ bool FilteringProgram::operator!= (const FilteringProgram& other) const
|
|||||||
return false;
|
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 ();
|
timer_ = g_timer_new ();
|
||||||
iTime_ = 0.0;
|
iTime_ = 0.0;
|
||||||
iFrame_ = 0;
|
iFrame_ = 0;
|
||||||
|
uniforms_changed_ = true;
|
||||||
|
|
||||||
ImageShader::reset();
|
ImageShader::reset();
|
||||||
}
|
}
|
||||||
@@ -216,9 +230,17 @@ void ImageFilteringShader::use()
|
|||||||
//
|
//
|
||||||
// loop over uniforms
|
// 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
|
// 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()
|
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 is composed of a header, the given code and a footer
|
||||||
shader_code_ = fragmentHeader + code_ + fragmentFooter;
|
shader_code_ = fragmentHeader + code_ + fragmentFooter;
|
||||||
// shift line numbers by number of lines in header
|
// 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
|
// launch build
|
||||||
custom_shading_.setShaders("shaders/image.vs", shader_code_, (int)n, ret);
|
custom_shading_.setShaders("shaders/image.vs", shader_code_, (int)n, ret);
|
||||||
}
|
}
|
||||||
@@ -309,6 +331,19 @@ void ImageFilter::update (float dt)
|
|||||||
|
|
||||||
if ( program_.isTwoPass() )
|
if ( program_.isTwoPass() )
|
||||||
shaders_.second->update(dt);
|
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
|
uint ImageFilter::texture () const
|
||||||
@@ -392,6 +427,9 @@ FilteringProgram ImageFilter::program () const
|
|||||||
return program_;
|
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)
|
void ImageFilter::setProgram(const FilteringProgram &f, std::promise<std::string> *ret)
|
||||||
{
|
{
|
||||||
// always keep local copy
|
// 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
|
// set code to the shader for first-pass
|
||||||
shaders_.first->setCode( codes.first, ret );
|
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
|
// SECOND PASS
|
||||||
if ( program_.isTwoPass() )
|
if ( program_.isTwoPass() )
|
||||||
// set the code to the shader for second-pass
|
// set the code to the shader for second-pass
|
||||||
shaders_.second->setCode(codes.second);
|
shaders_.second->setCode(codes.second);
|
||||||
|
|
||||||
|
// UPDATE UNIFORMS
|
||||||
updateParameters();
|
updateParameters();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ public:
|
|||||||
std::pair< std::string, std::string > code();
|
std::pair< std::string, std::string > code();
|
||||||
|
|
||||||
// if has second pass
|
// if has second pass
|
||||||
bool isTwoPass() const { return two_pass_filter_; }
|
inline bool isTwoPass() const { return two_pass_filter_; }
|
||||||
|
|
||||||
// set the list of parameters
|
// set the list of parameters
|
||||||
inline void setParameters(const std::map< std::string, float > ¶meters) { parameters_ = parameters; }
|
inline void setParameters(const std::map< std::string, float > ¶meters) { parameters_ = parameters; }
|
||||||
@@ -57,6 +57,8 @@ public:
|
|||||||
|
|
||||||
// set the value of a parameter
|
// set the value of a parameter
|
||||||
inline void setParameter(const std::string &p, float value) { parameters_[p] = value; }
|
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
|
// globals
|
||||||
static std::string getFilterCodeInputs();
|
static std::string getFilterCodeInputs();
|
||||||
@@ -85,6 +87,7 @@ public:
|
|||||||
|
|
||||||
// list of uniforms to control shader
|
// list of uniforms to control shader
|
||||||
std::map< std::string, float > uniforms_;
|
std::map< std::string, float > uniforms_;
|
||||||
|
bool uniforms_changed_;
|
||||||
|
|
||||||
ImageFilteringShader();
|
ImageFilteringShader();
|
||||||
~ImageFilteringShader();
|
~ImageFilteringShader();
|
||||||
|
|||||||
@@ -232,52 +232,89 @@ void ShadingProgram::reset()
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
void ShadingProgram::setUniform<int>(const std::string& name, int val) {
|
bool ShadingProgram::setUniform<int>(const std::string &name, int val)
|
||||||
glUniform1i(glGetUniformLocation(id_, name.c_str()), val);
|
{
|
||||||
|
GLint uid = glGetUniformLocation(id_, name.c_str());
|
||||||
|
if (uid < 0)
|
||||||
|
return false;
|
||||||
|
glUniform1i(uid, val);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
void ShadingProgram::setUniform<bool>(const std::string& name, bool val) {
|
bool ShadingProgram::setUniform<bool>(const std::string& name, bool val) {
|
||||||
glUniform1i(glGetUniformLocation(id_, name.c_str()), val);
|
GLint uid = glGetUniformLocation(id_, name.c_str());
|
||||||
|
if (uid < 0)
|
||||||
|
return false;
|
||||||
|
glUniform1i(uid, val);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
void ShadingProgram::setUniform<float>(const std::string& name, float val) {
|
bool ShadingProgram::setUniform<float>(const std::string& name, float val) {
|
||||||
glUniform1f(glGetUniformLocation(id_, name.c_str()), val);
|
GLint uid = glGetUniformLocation(id_, name.c_str());
|
||||||
|
if (uid < 0)
|
||||||
|
return false;
|
||||||
|
glUniform1f(uid, val);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
void ShadingProgram::setUniform<float>(const std::string& name, float val1, float val2) {
|
bool ShadingProgram::setUniform<float>(const std::string& name, float val1, float val2) {
|
||||||
glUniform2f(glGetUniformLocation(id_, name.c_str()), val1, val2);
|
GLint uid = glGetUniformLocation(id_, name.c_str());
|
||||||
|
if (uid < 0)
|
||||||
|
return false;
|
||||||
|
glUniform2f(uid, val1, val2);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
void ShadingProgram::setUniform<float>(const std::string& name, float val1, float val2, float val3) {
|
bool ShadingProgram::setUniform<float>(const std::string& name, float val1, float val2, float val3) {
|
||||||
glUniform3f(glGetUniformLocation(id_, name.c_str()), val1, val2, val3);
|
GLint uid = glGetUniformLocation(id_, name.c_str());
|
||||||
|
if (uid < 0)
|
||||||
|
return false;
|
||||||
|
glUniform3f(uid, val1, val2, val3);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
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);
|
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<>
|
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);
|
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<>
|
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);
|
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<>
|
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);
|
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();
|
static void enduse();
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
template<typename T> void setUniform(const std::string& name, T val);
|
template<typename T> bool setUniform(const std::string& name, T val);
|
||||||
template<typename T> void setUniform(const std::string& name, T val1, T val2);
|
template<typename T> bool 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 val1, T val2, T val3);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
unsigned int id_;
|
unsigned int id_;
|
||||||
|
|||||||
Reference in New Issue
Block a user