mirror of
https://github.com/brunoherbelin/vimix.git
synced 2025-12-12 02:40:00 +01:00
Added WhiteBalance to RenderingWindow and Display View
Render output frame to output window using a Shader implementing white balance correction. Adjusting parameters of white balance from Display View with color picker (white) and slider (temperature). GLSL filter for white balance created from ShaderToy.
This commit is contained in:
@@ -613,6 +613,7 @@ set(VMIX_RSC_FILES
|
||||
./rsc/shaders/filters/resample_quarter.glsl
|
||||
./rsc/shaders/filters/earlybird.glsl
|
||||
./rsc/shaders/filters/logo.glsl
|
||||
./rsc/shaders/filters/whitebalance.glsl
|
||||
)
|
||||
|
||||
cmrc_add_resource_library(vmix-resources ALIAS vmix::rc NAMESPACE vmix WHENCE rsc ${VMIX_RSC_FILES})
|
||||
|
||||
Binary file not shown.
262
rsc/shaders/filters/whitebalance.glsl
Normal file
262
rsc/shaders/filters/whitebalance.glsl
Normal file
@@ -0,0 +1,262 @@
|
||||
// From https://www.shadertoy.com/view/Ml2BRD
|
||||
// and https://www.shadertoy.com/view/MtcfDr
|
||||
// By Tynach.
|
||||
// Adapted by Bruno Herbelin for vimix
|
||||
|
||||
precision highp float;
|
||||
|
||||
/*
|
||||
* Settings
|
||||
*/
|
||||
|
||||
// Minimum temperature in the range (defined in the standard as 4000)
|
||||
const float minTemp = 4000.0;
|
||||
|
||||
// Maximum temperature in the range (defined in the standard as 25000)
|
||||
const float maxTemp = 9000.0;
|
||||
|
||||
// [0 1] value slider between min and max Temp
|
||||
uniform float Temperature;
|
||||
|
||||
// Color for picked 'grey'
|
||||
uniform float Red;
|
||||
uniform float Green;
|
||||
uniform float Blue;
|
||||
|
||||
|
||||
// Parameters for transfer characteristics (gamma curves)
|
||||
struct transfer {
|
||||
// Exponent used to linearize the signal
|
||||
float power;
|
||||
|
||||
// Offset from 0.0 for the exponential curve
|
||||
float off;
|
||||
|
||||
// Slope of linear segment near 0
|
||||
float slope;
|
||||
|
||||
// Values below this are divided by slope during linearization
|
||||
float cutoffToLinear;
|
||||
|
||||
// Values below this are multiplied by slope during gamma correction
|
||||
float cutoffToGamma;
|
||||
};
|
||||
|
||||
// Parameters for a colorspace
|
||||
struct rgb_space {
|
||||
// Chromaticity coordinates (xyz) for Red, Green, and Blue primaries
|
||||
mat4 primaries;
|
||||
|
||||
// Chromaticity coordinates (xyz) for white point
|
||||
vec4 white;
|
||||
|
||||
// Linearization and gamma correction parameters
|
||||
transfer trc;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Preprocessor 'functions' that help build colorspaces as constants
|
||||
*/
|
||||
|
||||
// Turns 6 chromaticity coordinates into a 3x3 matrix
|
||||
#define Primaries(r1, r2, g1, g2, b1, b2)\
|
||||
mat4(\
|
||||
(r1), (r2), 1.0 - (r1) - (r2), 0,\
|
||||
(g1), (g2), 1.0 - (g1) - (g2), 0,\
|
||||
(b1), (b2), 1.0 - (b1) - (b2), 0,\
|
||||
0, 0, 0, 1)
|
||||
|
||||
// Creates a whitepoint's xyz chromaticity coordinates from the given xy coordinates
|
||||
#define White(x, y)\
|
||||
vec4(vec3((x), (y), 1.0 - (x) - (y))/(y), 1)
|
||||
|
||||
// Automatically calculate the slope and cutoffs for transfer characteristics
|
||||
#define Transfer(po, of)\
|
||||
transfer(\
|
||||
(po),\
|
||||
(of),\
|
||||
(pow((po)*(of)/((po) - 1.0), 1.0 - (po))*pow(1.0 + (of), (po)))/(po),\
|
||||
(of)/((po) - 1.0),\
|
||||
(of)/((po) - 1.0)*(po)/(pow((po)*(of)/((po) - 1.0), 1.0 - (po))*pow(1.0 + (of), (po)))\
|
||||
)
|
||||
|
||||
// Creates a scaling matrix using a vec4 to set the xyzw scalars
|
||||
#define diag(v)\
|
||||
mat4(\
|
||||
(v).x, 0, 0, 0,\
|
||||
0, (v).y, 0, 0,\
|
||||
0, 0, (v).z, 0,\
|
||||
0, 0, 0, (v).w)
|
||||
|
||||
// Creates a conversion matrix that turns RGB colors into XYZ colors
|
||||
#define rgbToXyz(space)\
|
||||
(space.primaries*diag(inverse((space).primaries)*(space).white))
|
||||
|
||||
// Creates a conversion matrix that turns XYZ colors into RGB colors
|
||||
#define xyzToRgb(space)\
|
||||
inverse(rgbToXyz(space))
|
||||
|
||||
|
||||
/*
|
||||
* Chromaticities for RGB primaries
|
||||
*/
|
||||
|
||||
|
||||
// Rec. 709 (HDTV) and sRGB primaries
|
||||
const mat4 primaries709 = Primaries(
|
||||
0.64, 0.33,
|
||||
0.3, 0.6,
|
||||
0.15, 0.06
|
||||
);
|
||||
|
||||
|
||||
// Same as above, but in fractional form
|
||||
const mat4 primariesLms = Primaries(
|
||||
194735469.0/263725741.0, 68990272.0/263725741.0,
|
||||
141445123.0/106612934.0, -34832189.0/106612934.0,
|
||||
36476327.0/229961670.0, 0.0
|
||||
);
|
||||
|
||||
|
||||
/*
|
||||
* Chromaticities for white points
|
||||
*/
|
||||
|
||||
// Standard illuminant E (also known as the 'equal energy' white point)
|
||||
const vec4 whiteE = White(1.0/3.0, 1.0/3.0);
|
||||
|
||||
// Standard Illuminant D65 according to the Rec. 709 and sRGB standards
|
||||
const vec4 whiteD65S = White(0.3127, 0.3290);
|
||||
|
||||
/*
|
||||
* Gamma curve parameters
|
||||
*/
|
||||
// Linear gamma
|
||||
const transfer gam10 = transfer(1.0, 0.0, 1.0, 0.0, 0.0);
|
||||
// Gamma for sRGB
|
||||
const transfer gamSrgb = transfer(2.4, 0.055, 12.92, 0.04045, 0.0031308);
|
||||
|
||||
/*
|
||||
* RGB Colorspaces
|
||||
*/
|
||||
// sRGB (mostly the same as Rec. 709, but different gamma and full range values)
|
||||
const rgb_space Srgb = rgb_space(primaries709, whiteD65S, gamSrgb);
|
||||
|
||||
// Lms primaries, balanced against equal energy white point
|
||||
const rgb_space LmsRgb = rgb_space(primariesLms, whiteE, gam10);
|
||||
|
||||
|
||||
/*
|
||||
* Colorspace conversion functions
|
||||
*/
|
||||
|
||||
// Converts RGB colors to a linear light scale
|
||||
vec4 toLinear(vec4 color, const transfer trc)
|
||||
{
|
||||
bvec4 cutoff = lessThan(color, vec4(trc.cutoffToLinear));
|
||||
bvec4 negCutoff = lessThanEqual(color, vec4(-1.0*trc.cutoffToLinear));
|
||||
vec4 higher = pow((color + trc.off)/(1.0 + trc.off), vec4(trc.power));
|
||||
vec4 lower = color/trc.slope;
|
||||
vec4 neg = -1.0*pow((color - trc.off)/(-1.0 - trc.off), vec4(trc.power));
|
||||
|
||||
vec4 result = mix(higher, lower, cutoff);
|
||||
return mix(result, neg, negCutoff);
|
||||
}
|
||||
|
||||
// Gamma-corrects RGB colors to be sent to a display
|
||||
vec4 toGamma(vec4 color, const transfer trc)
|
||||
{
|
||||
bvec4 cutoff = lessThan(color, vec4(trc.cutoffToGamma));
|
||||
bvec4 negCutoff = lessThanEqual(color, vec4(-1.0*trc.cutoffToGamma));
|
||||
vec4 higher = (1.0 + trc.off)*pow(color, vec4(1.0/trc.power)) - trc.off;
|
||||
vec4 lower = color*trc.slope;
|
||||
vec4 neg = (-1.0 - trc.off)*pow(-1.0*color, vec4(1.0/trc.power)) + trc.off;
|
||||
|
||||
vec4 result = mix(higher, lower, cutoff);
|
||||
return mix(result, neg, negCutoff);
|
||||
}
|
||||
|
||||
// Scales a color to the closest in-gamut representation of that color
|
||||
vec4 gamutScale(vec4 color, float luma)
|
||||
{
|
||||
float low = min(color.r, min(color.g, min(color.b, 0.0)));
|
||||
float high = max(color.r, max(color.g, max(color.b, 1.0)));
|
||||
|
||||
float lowScale = low/(low - luma);
|
||||
float highScale = max((high - 1.0)/(high - luma), 0.0);
|
||||
float scale = max(lowScale, highScale);
|
||||
color.rgb += scale*(luma - color.rgb);
|
||||
|
||||
return color;
|
||||
}
|
||||
// Calculate Standard Illuminant Series D light source XYZ values
|
||||
vec4 temperatureToXyz(float temperature)
|
||||
{
|
||||
// Calculate terms to be added up. Since only the coefficients aren't
|
||||
// known ahead of time, they're the only thing determined by mix()
|
||||
float x = dot(mix(
|
||||
vec4(0.244063, 99.11, 2967800.0, -4607000000.0),
|
||||
vec4(0.23704, 247.48, 1901800.0, -2006400000.0),
|
||||
bvec4(temperature > 7000.0)
|
||||
)/vec4(1, temperature, pow(temperature, 2.0), pow(temperature, 3.0)), vec4(1));
|
||||
|
||||
return White(x, -3.0*pow(x, 2.0) + 2.87*x - 0.275);
|
||||
}
|
||||
|
||||
|
||||
// XYZ conversion matrices for the display colorspace
|
||||
const mat4 toXyz = rgbToXyz(Srgb);
|
||||
const mat4 toRgb = xyzToRgb(Srgb);
|
||||
|
||||
// LMS conversion matrices for white point adaptation
|
||||
const mat4 toLms = xyzToRgb(LmsRgb);
|
||||
const mat4 frLms = rgbToXyz(LmsRgb);
|
||||
|
||||
|
||||
// Converts from one RGB colorspace to another, output as linear light
|
||||
vec4 convert(vec4 color, vec4 whiteNew)
|
||||
{
|
||||
color = toXyz*color;
|
||||
|
||||
color= toLms*color;
|
||||
color = diag(((toLms*Srgb.white)/(toLms*whiteNew)))*color;
|
||||
color = inverse(toLms)*color;
|
||||
float luma = color.y;
|
||||
|
||||
color = toRgb*color;
|
||||
color = gamutScale(color, luma);
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
// Main function
|
||||
void mainImage(out vec4 color, in vec2 coord)
|
||||
{
|
||||
vec2 uv = coord.xy / iResolution.xy;
|
||||
vec4 texColor = texture(iChannel0, uv);
|
||||
|
||||
texColor = toLinear(texColor, Srgb.trc);
|
||||
|
||||
// Calculate temperature conversion
|
||||
vec4 convWhite = temperatureToXyz(Temperature*(maxTemp - minTemp) + minTemp);
|
||||
mat4 adapt = toRgb*frLms*diag((toLms*convWhite)/(toLms*Srgb.white))*toLms*toXyz;
|
||||
texColor = adapt*texColor;
|
||||
|
||||
// Darken values to fit within gamut (for texture)
|
||||
vec4 newWhite = adapt*vec4(1);
|
||||
texColor.rgb /= max(newWhite.r, max(newWhite.g, newWhite.b));
|
||||
color = texColor;
|
||||
|
||||
// color balance by color picker
|
||||
vec4 whiteNew = vec4( Red, Green, Blue, 1.0);
|
||||
whiteNew = toXyz*whiteNew;
|
||||
whiteNew /= dot(whiteNew, vec4(1.0));
|
||||
whiteNew /= whiteNew.y;
|
||||
color = convert(color, whiteNew);
|
||||
|
||||
// Convert to display gamma curve
|
||||
color = toGamma(color, Srgb.trc);
|
||||
}
|
||||
|
||||
|
||||
@@ -119,8 +119,8 @@ DisplaysView::DisplaysView() : View(DISPLAYS)
|
||||
// initial behavior: no window selected, no menu
|
||||
show_window_menu_ = false;
|
||||
current_window_ = -1;
|
||||
current_window_status_ = new Group;
|
||||
|
||||
current_window_status_ = new Group;
|
||||
current_window_whitebalance = glm::vec4(1.f, 1.f, 1.f, 0.5f);
|
||||
draw_pending_ = false;
|
||||
|
||||
// display actions : 0 = move output, 1 paint, 2 erase
|
||||
@@ -377,15 +377,19 @@ void DisplaysView::draw()
|
||||
// Add / Remove windows
|
||||
ImGui::SameLine();
|
||||
if ( Settings::application.num_output_windows < MAX_OUTPUT_WINDOW) {
|
||||
if (ImGuiToolkit::IconButton(18, 4, "More windows"))
|
||||
if (ImGuiToolkit::IconButton(18, 4, "More windows")) {
|
||||
++Settings::application.num_output_windows;
|
||||
current_window_ = Settings::application.num_output_windows-1;
|
||||
}
|
||||
}
|
||||
else
|
||||
ImGuiToolkit::Icon(18, 4, false);
|
||||
ImGui::SameLine();
|
||||
if ( Settings::application.num_output_windows > 0 ) {
|
||||
if (ImGuiToolkit::IconButton(19, 4, "Less windows"))
|
||||
if (ImGuiToolkit::IconButton(19, 4, "Less windows")) {
|
||||
--Settings::application.num_output_windows;
|
||||
current_window_ = -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
ImGuiToolkit::Icon(19, 4, false);
|
||||
@@ -393,47 +397,73 @@ void DisplaysView::draw()
|
||||
// Modify current window
|
||||
if (current_window_ > -1) {
|
||||
|
||||
// Pattern output
|
||||
ImGui::SameLine(0, 50);
|
||||
ImGuiContext& g = *GImGui;
|
||||
|
||||
// title output
|
||||
ImGui::SameLine(0, 5.f * g.Style.FramePadding.x);
|
||||
ImGui::Text("Output %d", current_window_ + 1);
|
||||
|
||||
// Output options
|
||||
ImGui::SameLine(0, 2.f * g.Style.FramePadding.x);
|
||||
ImGuiToolkit::ButtonIconToggle(8,5,9,5, &Settings::application.windows[1+current_window_].scaled, "Scaled to window");
|
||||
|
||||
ImGui::SameLine(0, g.Style.FramePadding.x);
|
||||
ImGuiToolkit::ButtonIconToggle(10,1,11,1, &Settings::application.windows[1+current_window_].show_pattern, "Test pattern");
|
||||
|
||||
// // White ballance
|
||||
// static DialogToolkit::ColorPickerDialog whitedialog;
|
||||
// ImGui::SameLine(0, 30);
|
||||
// ImGuiToolkit::Icon(5, 4);
|
||||
// static ImVec4 white = ImVec4(1.f, 1.f, 1.f, 1.f);
|
||||
// ImGui::SameLine();
|
||||
// ImGuiToolkit::PushFont(ImGuiToolkit::FONT_DEFAULT);
|
||||
// if (ImGui::ColorButton("White", white, ImGuiColorEditFlags_NoAlpha)) {
|
||||
// whitedialog.setRGB( std::make_tuple(white.x, white.y, white.z) );
|
||||
// whitedialog.open();
|
||||
// }
|
||||
// ImGui::PopFont();
|
||||
// // get picked color if dialog finished
|
||||
// if (whitedialog.closed()){
|
||||
// std::tuple<float, float, float> c = whitedialog.RGB();
|
||||
// white.x = std::get<0>(c);
|
||||
// white.y = std::get<1>(c);
|
||||
// white.z = std::get<2>(c);
|
||||
// }
|
||||
// White ballance color
|
||||
static DialogToolkit::ColorPickerDialog whitebalancedialog;
|
||||
|
||||
// ImGui::SameLine();
|
||||
// ImGuiToolkit::Icon(3,4);
|
||||
// static ImVec4 grey = ImVec4(0.5f, 0.5f, 0.5f, 1.f);
|
||||
// ImGui::SameLine();
|
||||
// ImGuiToolkit::PushFont(ImGuiToolkit::FONT_DEFAULT);
|
||||
// ImGui::ColorButton("Grey", grey, ImGuiColorEditFlags_NoAlpha);
|
||||
// ImGui::PopFont();
|
||||
ImGui::SameLine(0, 1.5f * g.Style.FramePadding.x);
|
||||
ImGuiToolkit::PushFont(ImGuiToolkit::FONT_DEFAULT);
|
||||
|
||||
// ImGui::SameLine();
|
||||
// ImGuiToolkit::Icon(4,4);
|
||||
// static ImVec4 black = ImVec4(0.f, 0.f, 0.f, 1.f);
|
||||
// ImGui::SameLine();
|
||||
// ImGuiToolkit::PushFont(ImGuiToolkit::FONT_DEFAULT);
|
||||
// ImGui::ColorButton("Black", black, ImGuiColorEditFlags_NoAlpha);
|
||||
// ImGui::PopFont();
|
||||
// hack to re-align color button to text
|
||||
ImGuiWindow* window = ImGui::GetCurrentWindow();
|
||||
window->DC.CursorPos.y += g.Style.FramePadding.y;
|
||||
|
||||
if (ImGui::ColorButton("White balance", ImVec4(current_window_whitebalance.x,
|
||||
current_window_whitebalance.y,
|
||||
current_window_whitebalance.z, 1.f),
|
||||
ImGuiColorEditFlags_NoAlpha)) {
|
||||
whitebalancedialog.setRGB( std::make_tuple(current_window_whitebalance.x,
|
||||
current_window_whitebalance.y,
|
||||
current_window_whitebalance.z) );
|
||||
whitebalancedialog.open();
|
||||
}
|
||||
ImGui::PopFont();
|
||||
|
||||
// get picked color if dialog finished
|
||||
if (whitebalancedialog.closed()){
|
||||
std::tuple<float, float, float> c = whitebalancedialog.RGB();
|
||||
current_window_whitebalance.x = std::get<0>(c);
|
||||
current_window_whitebalance.y = std::get<1>(c);
|
||||
current_window_whitebalance.z = std::get<2>(c);
|
||||
|
||||
// set White Balance Color matrix to shader
|
||||
Rendering::manager().outputWindow(current_window_).setWhiteBalance( current_window_whitebalance );
|
||||
}
|
||||
|
||||
// White ballance temperature
|
||||
ImGui::SameLine();
|
||||
window->DC.CursorPos.y -= g.Style.FramePadding.y;
|
||||
if (ImGui::Button(ICON_FA_THERMOMETER_HALF ICON_FA_SORT_DOWN ))
|
||||
ImGui::OpenPopup("temperature_popup");
|
||||
if (ImGui::BeginPopup("temperature_popup", ImGuiWindowFlags_NoMove))
|
||||
{
|
||||
ImGuiToolkit::PushFont(ImGuiToolkit::FONT_DEFAULT);
|
||||
ImGuiToolkit::Indication("9000 K", " " ICON_FA_THERMOMETER_FULL);
|
||||
if ( ImGui::VSliderFloat("##Temperature", ImVec2(30,260), ¤t_window_whitebalance.w, 0.0, 1.0, "") ){
|
||||
|
||||
Rendering::manager().outputWindow(current_window_).setWhiteBalance( current_window_whitebalance );
|
||||
}
|
||||
if (ImGui::IsItemHovered() || ImGui::IsItemActive() ) {
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::Text("%d K", 4000 + (int) ceil(current_window_whitebalance.w * 5000.f));
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
ImGuiToolkit::Indication("4000 K", " " ICON_FA_THERMOMETER_EMPTY);
|
||||
ImGui::PopFont();
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -482,7 +512,7 @@ void DisplaysView::draw()
|
||||
Rendering::manager().outputWindow(current_window_).setDecoration(!_borderless);
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem( ICON_FA_EXPAND_ALT " Buffer aspect ratio" , nullptr, false, _windowed )){
|
||||
if (ImGui::MenuItem( ICON_FA_EXPAND_ALT " Reset aspect ratio" , nullptr, false, _windowed )){
|
||||
// reset aspect ratio
|
||||
glm::ivec4 rect = windowCoordinates(current_window_);
|
||||
float ar = Mixer::manager().session()->frame()->aspectRatio();
|
||||
@@ -493,7 +523,7 @@ void DisplaysView::draw()
|
||||
Rendering::manager().outputWindow(current_window_).setCoordinates( rect );
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem( ICON_FA_COMPRESS " Buffer size", nullptr, false, _windowed )){
|
||||
if (ImGui::MenuItem( ICON_FA_RULER_COMBINED " Reset to pixel size", nullptr, false, _windowed )){
|
||||
// reset resolution to 1:1
|
||||
glm::ivec4 rect = windowCoordinates(current_window_);
|
||||
rect.p = Mixer::manager().session()->frame()->width();
|
||||
@@ -517,7 +547,17 @@ void DisplaysView::draw()
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
ImGui::MenuItem( ICON_FA_EXPAND_ARROWS_ALT " Scaled content", nullptr, &Settings::application.windows[1].scaled );
|
||||
if ( ImGui::MenuItem( ICON_FA_REPLY " Reset") ) {
|
||||
glm::ivec4 rect (0, 0, 800, 600);
|
||||
rect.p = Mixer::manager().session()->frame()->width();
|
||||
rect.q = Mixer::manager().session()->frame()->height();
|
||||
Rendering::manager().outputWindow(current_window_).setDecoration(true);
|
||||
Rendering::manager().outputWindow(current_window_).setWhiteBalance( glm::vec4(1.f, 1.f, 1.f, 0.5f) );
|
||||
if (Settings::application.windows[current_window_+1].fullscreen)
|
||||
Rendering::manager().outputWindow(current_window_).exitFullscreen();
|
||||
else
|
||||
Rendering::manager().outputWindow(current_window_).setCoordinates( rect );
|
||||
}
|
||||
|
||||
ImGui::PopStyleColor(2);
|
||||
ImGui::EndPopup();
|
||||
@@ -538,6 +578,8 @@ std::pair<Node *, glm::vec2> DisplaysView::pick(glm::vec2 P)
|
||||
|
||||
// test all windows
|
||||
current_window_ = -1;
|
||||
current_window_whitebalance = glm::vec4(1.f, 1.f, 1.f, 0.5f);
|
||||
|
||||
for (int i = 0; i < Settings::application.num_output_windows; ++i) {
|
||||
|
||||
// ignore pick on render surface: it's the same as output surface
|
||||
@@ -555,6 +597,7 @@ std::pair<Node *, glm::vec2> DisplaysView::pick(glm::vec2 P)
|
||||
(pick.first == windows_[i].handles_) ||
|
||||
(pick.first == windows_[i].menu_) ) {
|
||||
current_window_ = i;
|
||||
current_window_whitebalance = Rendering::manager().outputWindow(current_window_).whiteBalance();
|
||||
windows_[i].overlays_->setActive(1);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -80,6 +80,7 @@ private:
|
||||
std::vector<WindowPreview> windows_;
|
||||
int current_window_;
|
||||
Group *current_window_status_;
|
||||
glm::vec4 current_window_whitebalance;
|
||||
bool show_window_menu_;
|
||||
|
||||
// Group *window_;
|
||||
|
||||
@@ -19,18 +19,14 @@
|
||||
#include <ctime>
|
||||
#include <algorithm>
|
||||
|
||||
#include <glib.h>
|
||||
#include <glm/gtc/matrix_access.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
|
||||
#include "defines.h"
|
||||
#include "Resource.h"
|
||||
#include "ImageShader.h"
|
||||
#include "Visitor.h"
|
||||
#include "FrameBuffer.h"
|
||||
#include "ImageShader.h"
|
||||
#include "Primitives.h"
|
||||
#include "Log.h"
|
||||
|
||||
#include "ImageFilter.h"
|
||||
|
||||
@@ -162,38 +158,6 @@ bool FilteringProgram::operator!= (const FilteringProgram& other) const
|
||||
/// ////
|
||||
////////////////////////////////////////
|
||||
|
||||
class ImageFilteringShader : public ImageShader
|
||||
{
|
||||
// GLSL Program
|
||||
ShadingProgram custom_shading_;
|
||||
|
||||
// fragment shader GLSL code
|
||||
std::string shader_code_;
|
||||
std::string code_;
|
||||
|
||||
public:
|
||||
// for iTimedelta
|
||||
GTimer *timer_;
|
||||
double iTime_;
|
||||
uint iFrame_;
|
||||
|
||||
// list of uniforms to control shader
|
||||
std::map< std::string, float > uniforms_;
|
||||
|
||||
ImageFilteringShader();
|
||||
~ImageFilteringShader();
|
||||
|
||||
void update(float dt);
|
||||
|
||||
void use() override;
|
||||
void reset() override;
|
||||
void copy(ImageFilteringShader const& S);
|
||||
|
||||
// set the code of the filter
|
||||
void setCode(const std::string &code, std::promise<std::string> *ret = nullptr);
|
||||
|
||||
};
|
||||
|
||||
|
||||
ImageFilteringShader::ImageFilteringShader(): ImageShader()
|
||||
{
|
||||
|
||||
@@ -7,8 +7,10 @@
|
||||
#include <string>
|
||||
#include <future>
|
||||
|
||||
#include <glib.h>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include "ImageShader.h"
|
||||
#include "FrameBufferFilter.h"
|
||||
|
||||
class FilteringProgram
|
||||
@@ -65,7 +67,39 @@ public:
|
||||
|
||||
class Surface;
|
||||
class FrameBuffer;
|
||||
class ImageFilteringShader;
|
||||
|
||||
class ImageFilteringShader : public ImageShader
|
||||
{
|
||||
// GLSL Program
|
||||
ShadingProgram custom_shading_;
|
||||
|
||||
// fragment shader GLSL code
|
||||
std::string shader_code_;
|
||||
std::string code_;
|
||||
|
||||
public:
|
||||
// for iTimedelta
|
||||
GTimer *timer_;
|
||||
double iTime_;
|
||||
uint iFrame_;
|
||||
|
||||
// list of uniforms to control shader
|
||||
std::map< std::string, float > uniforms_;
|
||||
|
||||
ImageFilteringShader();
|
||||
~ImageFilteringShader();
|
||||
|
||||
void update(float dt);
|
||||
|
||||
void use() override;
|
||||
void reset() override;
|
||||
void copy(ImageFilteringShader const& S);
|
||||
|
||||
// set the code of the filter
|
||||
void setCode(const std::string &code, std::promise<std::string> *ret = nullptr);
|
||||
|
||||
};
|
||||
|
||||
|
||||
class ImageFilter : public FrameBufferFilter
|
||||
{
|
||||
|
||||
@@ -69,6 +69,7 @@
|
||||
#include "GstToolkit.h"
|
||||
#include "UserInterfaceManager.h"
|
||||
#include "ControlManager.h"
|
||||
#include "ImageFilter.h"
|
||||
|
||||
#include "RenderingManager.h"
|
||||
|
||||
@@ -1042,6 +1043,7 @@ void RenderingWindow::terminate()
|
||||
|
||||
// invalidate
|
||||
window_ = NULL;
|
||||
shader_ = nullptr;
|
||||
surface_ = nullptr;
|
||||
fbo_ = 0;
|
||||
index_ = -1;
|
||||
@@ -1088,6 +1090,33 @@ void RenderingWindow::swap()
|
||||
|
||||
}
|
||||
|
||||
FilteringProgram whitebalance("Whitebalance", "shaders/filters/whitebalance.glsl", "", { { "Red", 1.0}, { "Green", 1.0}, { "Blue", 1.0}, { "Temperature", 0.5} });
|
||||
|
||||
|
||||
void RenderingWindow::setWhiteBalance(glm::vec4 colorcorrection)
|
||||
{
|
||||
if (shader_)
|
||||
shader_->uniforms_ = std::map< std::string, float >{
|
||||
{ "Red", colorcorrection.x},
|
||||
{ "Green", colorcorrection.y},
|
||||
{ "Blue", colorcorrection.z},
|
||||
{ "Temperature", colorcorrection.w}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
glm::vec4 RenderingWindow::whiteBalance() const
|
||||
{
|
||||
glm::vec4 ret(1.f, 1.f, 1.f, 0.5f);
|
||||
|
||||
ret.x = shader_->uniforms_["Red"];
|
||||
ret.y = shader_->uniforms_["Green"];
|
||||
ret.z = shader_->uniforms_["Blue"];
|
||||
ret.w = shader_->uniforms_["Temperature"];
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool RenderingWindow::draw(FrameBuffer *fb)
|
||||
{
|
||||
// cannot draw if there is no window or invalid framebuffer
|
||||
@@ -1119,8 +1148,15 @@ bool RenderingWindow::draw(FrameBuffer *fb)
|
||||
|
||||
// VAO is not shared between multiple contexts of different windows
|
||||
// so we have to create a new VAO for rendering the surface in this window
|
||||
if (surface_ == nullptr)
|
||||
surface_ = new WindowSurface;
|
||||
if (surface_ == nullptr) {
|
||||
|
||||
const std::pair<std::string, std::string> codes = whitebalance.code();
|
||||
shader_ = new ImageFilteringShader;
|
||||
shader_->setCode( codes.first );
|
||||
shader_->uniforms_ = whitebalance.parameters();
|
||||
|
||||
surface_ = new WindowSurface(shader_);
|
||||
}
|
||||
|
||||
// calculate scaling factor of frame buffer inside window
|
||||
const float windowAspectRatio = aspectRatio();
|
||||
|
||||
@@ -40,6 +40,7 @@ class RenderingWindow
|
||||
uint fbo_;
|
||||
Stream *pattern_;
|
||||
class WindowSurface *surface_;
|
||||
class ImageFilteringShader *shader_;
|
||||
|
||||
protected:
|
||||
void setTitle(const std::string &title = "");
|
||||
@@ -82,6 +83,10 @@ public:
|
||||
void setCoordinates(glm::ivec4 rect);
|
||||
void setDecoration (bool on);
|
||||
|
||||
// set color correction
|
||||
void setWhiteBalance(glm::vec4 colorcorrection);
|
||||
glm::vec4 whiteBalance() const;
|
||||
|
||||
// get width of rendering area
|
||||
int width();
|
||||
// get height of rendering area
|
||||
|
||||
@@ -916,7 +916,7 @@ void TextureView::draw()
|
||||
s->touch();
|
||||
Action::manager().store(s->name() + std::string(": Texture Reset rotation"));
|
||||
}
|
||||
if (ImGui::Selectable( ICON_FA_EXPAND_ALT " Reset aspect ratio" )){
|
||||
if (ImGui::Selectable( ICON_FA_EXPAND_ALT " Reset aspect ratio" )){
|
||||
s->group(mode_)->scale_.x = s->group(mode_)->scale_.y;
|
||||
s->group(mode_)->scale_.x *= s->group(mode_)->crop_.x / s->group(mode_)->crop_.y;
|
||||
s->touch();
|
||||
|
||||
Reference in New Issue
Block a user