mirror of
https://github.com/brunoherbelin/vimix.git
synced 2025-12-11 10:19:59 +01:00
Mask Paint!! New MaskShader for mouse paiting of masks and associated changes.
UI for pain mask, load & save of FrameBuffer Image.
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -16,3 +16,5 @@ rules.ninja
|
||||
/vmix
|
||||
/vimix_*.snap
|
||||
/CMakeLists.txt.user.*
|
||||
|
||||
rsc/shaders/paint.fs
|
||||
|
||||
@@ -298,8 +298,9 @@ set(VMIX_RSC_FILES
|
||||
./rsc/shaders/mask_elipse.fs
|
||||
./rsc/shaders/mask_box.fs
|
||||
./rsc/shaders/mask_round.fs
|
||||
./rsc/shaders/mask_lowleftcorner.fs
|
||||
./rsc/shaders/mask_uprightcorner.fs
|
||||
./rsc/shaders/mask_horizontal.fs
|
||||
./rsc/shaders/mask_vertical.fs
|
||||
./rsc/shaders/mask_draw.fs
|
||||
./rsc/shaders/image.vs
|
||||
./rsc/shaders/imageprocessing.fs
|
||||
./rsc/fonts/Hack-Regular.ttf
|
||||
@@ -373,6 +374,7 @@ set(VMIX_RSC_FILES
|
||||
./rsc/mesh/icon_clock_hand.ply
|
||||
./rsc/mesh/icon_grid.ply
|
||||
./rsc/mesh/icon_rightarrow.ply
|
||||
./rsc/mesh/icon_crop.ply
|
||||
./rsc/mesh/h_line.ply
|
||||
./rsc/mesh/h_mark.ply
|
||||
)
|
||||
|
||||
115
FrameBuffer.cpp
115
FrameBuffer.cpp
@@ -9,6 +9,8 @@
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
|
||||
#include <glad/glad.h>
|
||||
#include <stb_image.h>
|
||||
#include <stb_image_write.h>
|
||||
|
||||
const char* FrameBuffer::aspect_ratio_name[5] = { "4:3", "3:2", "16:10", "16:9", "21:9" };
|
||||
glm::vec2 FrameBuffer::aspect_ratio_size[5] = { glm::vec2(4.f,3.f), glm::vec2(3.f,2.f), glm::vec2(16.f,10.f), glm::vec2(16.f,9.f) , glm::vec2(21.f,9.f) };
|
||||
@@ -129,6 +131,12 @@ FrameBuffer::~FrameBuffer()
|
||||
{
|
||||
if (framebufferid_)
|
||||
glDeleteFramebuffers(1, &framebufferid_);
|
||||
if (intermediate_framebufferid_)
|
||||
glDeleteFramebuffers(1, &intermediate_framebufferid_);
|
||||
if (textureid_)
|
||||
glDeleteTextures(1, &textureid_);
|
||||
if (intermediate_textureid_)
|
||||
glDeleteTextures(1, &intermediate_textureid_);
|
||||
}
|
||||
|
||||
|
||||
@@ -163,7 +171,7 @@ glm::vec3 FrameBuffer::resolution() const
|
||||
return glm::vec3(attrib_.viewport.x, attrib_.viewport.y, 0.f);
|
||||
}
|
||||
|
||||
void FrameBuffer::begin()
|
||||
void FrameBuffer::begin(bool clear)
|
||||
{
|
||||
if (!framebufferid_)
|
||||
init();
|
||||
@@ -172,7 +180,8 @@ void FrameBuffer::begin()
|
||||
|
||||
Rendering::manager().pushAttrib(attrib_);
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
if (clear)
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
}
|
||||
|
||||
void FrameBuffer::end()
|
||||
@@ -197,7 +206,7 @@ void FrameBuffer::release()
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
void FrameBuffer::readPixels()
|
||||
void FrameBuffer::readPixels(uint8_t *target_data)
|
||||
{
|
||||
if (!framebufferid_)
|
||||
return;
|
||||
@@ -212,21 +221,24 @@ void FrameBuffer::readPixels()
|
||||
else
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
||||
|
||||
glReadPixels(0, 0, attrib_.viewport.x, attrib_.viewport.y, (use_alpha_? GL_RGBA : GL_RGB), GL_UNSIGNED_BYTE, 0);
|
||||
glReadPixels(0, 0, attrib_.viewport.x, attrib_.viewport.y, (use_alpha_? GL_RGBA : GL_RGB), GL_UNSIGNED_BYTE, target_data);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
bool FrameBuffer::blit(FrameBuffer *other)
|
||||
bool FrameBuffer::blit(FrameBuffer *destination)
|
||||
{
|
||||
if (!framebufferid_ || !other || !other->framebufferid_)
|
||||
if (!framebufferid_ || !destination)
|
||||
return false;
|
||||
|
||||
if (!destination->framebufferid_)
|
||||
destination->init();
|
||||
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, framebufferid_);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, other->framebufferid_);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, destination->framebufferid_);
|
||||
// blit to the frame buffer object
|
||||
glBlitFramebuffer(0, 0, attrib_.viewport.x, attrib_.viewport.y,
|
||||
0, 0, other->width(), other->height(), GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
0, 0, destination->width(), destination->height(), GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -285,3 +297,88 @@ void FrameBuffer::setProjectionArea(glm::vec2 c)
|
||||
projection_ = glm::ortho(-projection_area_.x, projection_area_.x, projection_area_.y, -projection_area_.y, -1.f, 1.f);
|
||||
}
|
||||
|
||||
|
||||
FrameBufferImage::FrameBufferImage(int w, int h) :
|
||||
rgb(nullptr), width(w), height(h)
|
||||
{
|
||||
if (width>0 && height>0)
|
||||
rgb = new uint8_t[width*height*3];
|
||||
}
|
||||
|
||||
FrameBufferImage::FrameBufferImage(jpegBuffer jpgimg) :
|
||||
rgb(nullptr), width(0), height(0)
|
||||
{
|
||||
int c = 0;
|
||||
if (jpgimg.buffer != nullptr && jpgimg.len >0)
|
||||
rgb = stbi_load_from_memory(jpgimg.buffer, jpgimg.len, &width, &height, &c, 3);
|
||||
}
|
||||
|
||||
FrameBufferImage::~FrameBufferImage() {
|
||||
if (rgb!=nullptr)
|
||||
delete rgb;
|
||||
}
|
||||
|
||||
FrameBufferImage::jpegBuffer FrameBufferImage::getJpeg()
|
||||
{
|
||||
jpegBuffer jpgimg;
|
||||
|
||||
// if we hold a valid image
|
||||
if (rgb!=nullptr && width>0 && height>0) {
|
||||
|
||||
// allocate JPEG buffer
|
||||
// (NB: JPEG will need less than this but we can't know before...)
|
||||
jpgimg.buffer = (unsigned char *) malloc( width * height * 3 * sizeof(unsigned char));
|
||||
|
||||
stbi_write_jpg_to_func( [](void *context, void *data, int size)
|
||||
{
|
||||
memcpy(((FrameBufferImage::jpegBuffer*)context)->buffer + ((FrameBufferImage::jpegBuffer*)context)->len, data, size);
|
||||
((FrameBufferImage::jpegBuffer*)context)->len += size;
|
||||
}
|
||||
,&jpgimg, width, height, 3, rgb, FBI_JPEG_QUALITY);
|
||||
}
|
||||
|
||||
return jpgimg;
|
||||
}
|
||||
|
||||
FrameBufferImage *FrameBuffer::image(){
|
||||
|
||||
FrameBufferImage *img = nullptr;
|
||||
|
||||
// not ready
|
||||
if (!framebufferid_)
|
||||
return img;
|
||||
|
||||
// allocate image
|
||||
img = new FrameBufferImage(attrib_.viewport.x, attrib_.viewport.y);
|
||||
|
||||
// get pixels into image
|
||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); // set buffer target readpixel
|
||||
readPixels(img->rgb);
|
||||
|
||||
return img;
|
||||
}
|
||||
|
||||
bool FrameBuffer::fill(FrameBufferImage *image)
|
||||
{
|
||||
if (!framebufferid_)
|
||||
init();
|
||||
|
||||
// not compatible for RGB
|
||||
if (use_alpha_ || use_multi_sampling_)
|
||||
return false;
|
||||
|
||||
// invalid image
|
||||
if ( image == nullptr ||
|
||||
image->rgb==nullptr ||
|
||||
image->width !=attrib_.viewport.x ||
|
||||
image->height!=attrib_.viewport.y )
|
||||
return false;
|
||||
|
||||
// fill texture with image
|
||||
glBindTexture(GL_TEXTURE_2D, textureid_);
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, image->width, image->height,
|
||||
GL_RGB, GL_UNSIGNED_BYTE, image->rgb);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,9 +1,35 @@
|
||||
#ifndef FRAMEBUFFER_H
|
||||
#define FRAMEBUFFER_H
|
||||
|
||||
#include "Scene.h"
|
||||
#include "RenderingManager.h"
|
||||
|
||||
#define FBI_JPEG_QUALITY 90
|
||||
|
||||
/**
|
||||
* @brief The FrameBufferImage class stores an RGB image in RAM
|
||||
* Direct access to rgb array, and exchange format to JPEG in RAM
|
||||
*/
|
||||
class FrameBufferImage
|
||||
{
|
||||
public:
|
||||
uint8_t *rgb = nullptr;
|
||||
int width;
|
||||
int height;
|
||||
|
||||
struct jpegBuffer {
|
||||
unsigned char *buffer = nullptr;
|
||||
uint len = 0;
|
||||
};
|
||||
jpegBuffer getJpeg();
|
||||
|
||||
FrameBufferImage(int w, int h);
|
||||
FrameBufferImage(jpegBuffer jpgimg);
|
||||
~FrameBufferImage();
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The FrameBuffer class holds an OpenGL Frame Buffer Object.
|
||||
*/
|
||||
class FrameBuffer {
|
||||
|
||||
public:
|
||||
@@ -22,14 +48,14 @@ public:
|
||||
~FrameBuffer();
|
||||
|
||||
// Bind & push attribs to prepare draw
|
||||
void begin();
|
||||
void begin(bool clear = true);
|
||||
// pop attrib and unbind to end draw
|
||||
void end();
|
||||
// blit copy to another, returns true on success
|
||||
bool blit(FrameBuffer *other);
|
||||
bool blit(FrameBuffer *destination);
|
||||
// bind the FrameBuffer in READ and perform glReadPixels
|
||||
// return the size of the buffer
|
||||
void readPixels();
|
||||
// (to be used after preparing a target PBO)
|
||||
void readPixels(uint8_t* target_data = 0);
|
||||
|
||||
// clear color
|
||||
inline void setClearColor(glm::vec4 color) { attrib_.clear_color = color; }
|
||||
@@ -54,6 +80,10 @@ public:
|
||||
// index for texturing
|
||||
uint texture() const;
|
||||
|
||||
// get and fill image
|
||||
FrameBufferImage *image();
|
||||
bool fill(FrameBufferImage *image);
|
||||
|
||||
private:
|
||||
void init();
|
||||
void checkFramebufferStatus();
|
||||
@@ -64,6 +94,7 @@ private:
|
||||
uint textureid_, intermediate_textureid_;
|
||||
uint framebufferid_, intermediate_framebufferid_;
|
||||
bool use_alpha_, use_multi_sampling_;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -9,12 +9,8 @@
|
||||
|
||||
static ShadingProgram imageShadingProgram("shaders/image.vs", "shaders/image.fs");
|
||||
|
||||
const char* MaskShader::mask_names[6] = { ICON_FA_EXPAND,
|
||||
ICON_FA_CIRCLE,
|
||||
ICON_FA_MINUS_CIRCLE,
|
||||
ICON_FA_SQUARE,
|
||||
ICON_FA_CARET_SQUARE_RIGHT,
|
||||
ICON_FA_CARET_SQUARE_LEFT };
|
||||
const char* MaskShader::mask_names[3] = { ICON_FA_EXPAND, ICON_FA_EDIT, ICON_FA_SHAPES };
|
||||
const char* MaskShader::mask_shapes[5] = { "Elipse", "Oblong", "Rectangle", "Horizontal", "Vertical" };
|
||||
std::vector< ShadingProgram* > MaskShader::mask_programs;
|
||||
|
||||
ImageShader::ImageShader(): Shader(), stipple(0.0)
|
||||
@@ -72,11 +68,12 @@ MaskShader::MaskShader(): Shader(), mode(0)
|
||||
// first initialization
|
||||
if ( mask_programs.empty() ) {
|
||||
mask_programs.push_back(new ShadingProgram("shaders/simple.vs", "shaders/simple.fs"));
|
||||
mask_programs.push_back(new ShadingProgram("shaders/image.vs", "shaders/mask_draw.fs"));
|
||||
mask_programs.push_back(new ShadingProgram("shaders/simple.vs", "shaders/mask_elipse.fs"));
|
||||
mask_programs.push_back(new ShadingProgram("shaders/simple.vs", "shaders/mask_round.fs"));
|
||||
mask_programs.push_back(new ShadingProgram("shaders/simple.vs", "shaders/mask_box.fs"));
|
||||
mask_programs.push_back(new ShadingProgram("shaders/simple.vs", "shaders/mask_lowleftcorner.fs"));
|
||||
mask_programs.push_back(new ShadingProgram("shaders/simple.vs", "shaders/mask_uprightcorner.fs"));
|
||||
mask_programs.push_back(new ShadingProgram("shaders/simple.vs", "shaders/mask_horizontal.fs"));
|
||||
mask_programs.push_back(new ShadingProgram("shaders/simple.vs", "shaders/mask_vertical.fs"));
|
||||
}
|
||||
// reset instance
|
||||
reset();
|
||||
@@ -87,15 +84,22 @@ MaskShader::MaskShader(): Shader(), mode(0)
|
||||
void MaskShader::use()
|
||||
{
|
||||
// select program to use
|
||||
mode = CLAMP(mode, 0, mask_programs.size()-1);
|
||||
program_ = mask_programs[mode];
|
||||
mode = CLAMP(mode, 0, 2);
|
||||
shape = CLAMP(shape, 0, 4);
|
||||
program_ = mode < 2 ? mask_programs[mode] : mask_programs[shape+2] ;
|
||||
|
||||
// actual use of shader program
|
||||
Shader::use();
|
||||
|
||||
// set parameters
|
||||
program_->setUniform("blur", blur);
|
||||
// shape parameters
|
||||
size = shape < HORIZONTAL ? glm::max(glm::abs(size), glm::vec2(0.2)) : size;
|
||||
program_->setUniform("size", size);
|
||||
program_->setUniform("blur", blur);
|
||||
|
||||
// brush parameters
|
||||
program_->setUniform("cursor", cursor);
|
||||
program_->setUniform("brush", brush);
|
||||
program_->setUniform("option", option);
|
||||
}
|
||||
|
||||
void MaskShader::reset()
|
||||
@@ -104,8 +108,16 @@ void MaskShader::reset()
|
||||
|
||||
// default mask
|
||||
mode = 0;
|
||||
|
||||
// default shape
|
||||
shape = 0;
|
||||
blur = 0.5f;
|
||||
size = glm::vec2(1.f, 1.f);
|
||||
|
||||
// default brush
|
||||
cursor = glm::vec4(-10.f, -10.f, 1.f, 1.f);
|
||||
brush = glm::vec3(0.5f, 0.1f, 0.f);
|
||||
option = 0;
|
||||
}
|
||||
|
||||
void MaskShader::operator = (const MaskShader &S)
|
||||
@@ -113,6 +125,7 @@ void MaskShader::operator = (const MaskShader &S)
|
||||
Shader::operator =(S);
|
||||
|
||||
mode = S.mode;
|
||||
shape = S.shape;
|
||||
blur = S.blur;
|
||||
size = S.size;
|
||||
}
|
||||
@@ -122,3 +135,5 @@ void MaskShader::accept(Visitor& v) {
|
||||
Shader::accept(v);
|
||||
v.visit(*this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@ class ImageShader : public Shader
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
ImageShader();
|
||||
|
||||
void use() override;
|
||||
@@ -33,7 +32,6 @@ class MaskShader : public Shader
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
MaskShader();
|
||||
|
||||
void use() override;
|
||||
@@ -41,13 +39,32 @@ public:
|
||||
void accept(Visitor& v) override;
|
||||
void operator = (const MaskShader &S);
|
||||
|
||||
enum Modes {
|
||||
NONE = 0,
|
||||
PAINT = 1,
|
||||
SHAPE = 2
|
||||
};
|
||||
uint mode;
|
||||
|
||||
// uniforms
|
||||
float blur;
|
||||
glm::vec2 size;
|
||||
enum Shapes {
|
||||
ELIPSE = 0,
|
||||
OBLONG = 1,
|
||||
RECTANGLE = 2,
|
||||
HORIZONTAL = 3,
|
||||
VERTICAL = 4
|
||||
};
|
||||
uint shape;
|
||||
|
||||
static const char* mask_names[6];
|
||||
// uniforms
|
||||
glm::vec2 size;
|
||||
float blur;
|
||||
|
||||
int option;
|
||||
glm::vec4 cursor;
|
||||
glm::vec3 brush;
|
||||
|
||||
static const char* mask_names[3];
|
||||
static const char* mask_shapes[5];
|
||||
static std::vector< ShadingProgram* > mask_programs;
|
||||
};
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@ void SessionCreator::load(const std::string& filename)
|
||||
header->QueryIntAttribute("major", &version_major);
|
||||
header->QueryIntAttribute("minor", &version_minor);
|
||||
if (version_major != XML_VERSION_MAJOR || version_minor != XML_VERSION_MINOR){
|
||||
Log::Warning("%s is in a different versions of session file. Loading might fail.", filename.c_str());
|
||||
Log::Warning("%s is in an older versions of session file.\nLoading might fail or be incomplete.", filename.c_str());
|
||||
// return;
|
||||
}
|
||||
|
||||
@@ -100,6 +100,7 @@ void SessionCreator::loadConfig(XMLElement *viewsNode)
|
||||
SessionLoader::XMLToNode( viewsNode->FirstChildElement("Mixing"), *session_->config(View::MIXING));
|
||||
SessionLoader::XMLToNode( viewsNode->FirstChildElement("Geometry"), *session_->config(View::GEOMETRY));
|
||||
SessionLoader::XMLToNode( viewsNode->FirstChildElement("Layer"), *session_->config(View::LAYER));
|
||||
SessionLoader::XMLToNode( viewsNode->FirstChildElement("Appearance"), *session_->config(View::APPEARANCE));
|
||||
SessionLoader::XMLToNode( viewsNode->FirstChildElement("Rendering"), *session_->config(View::RENDERING));
|
||||
}
|
||||
}
|
||||
@@ -395,10 +396,12 @@ void SessionLoader::visit(MaskShader &n)
|
||||
return;
|
||||
|
||||
xmlCurrent_->QueryUnsignedAttribute("mode", &n.mode);
|
||||
xmlCurrent_->QueryUnsignedAttribute("shape", &n.shape);
|
||||
|
||||
XMLElement* uniforms = xmlCurrent_->FirstChildElement("uniforms");
|
||||
if (uniforms) {
|
||||
uniforms->QueryFloatAttribute("blur", &n.blur);
|
||||
uniforms->QueryIntAttribute("option", &n.option);
|
||||
XMLElement* size = uniforms->FirstChildElement("size");
|
||||
if (size)
|
||||
tinyxml2::XMLElementToGLM( size->FirstChildElement("vec2"), n.size);
|
||||
@@ -458,7 +461,33 @@ void SessionLoader::visit (Source& s)
|
||||
if (xmlCurrent_) s.blendingShader()->accept(*this);
|
||||
|
||||
xmlCurrent_ = sourceNode->FirstChildElement("Mask");
|
||||
if (xmlCurrent_) s.maskShader()->accept(*this);
|
||||
if (xmlCurrent_) {
|
||||
// read the mask shader attributes
|
||||
s.maskShader()->accept(*this);
|
||||
// if there is an Image mask stored
|
||||
XMLElement* imageNode = xmlCurrent_->FirstChildElement("Image");
|
||||
if (imageNode) {
|
||||
// if there is an internal array of data
|
||||
XMLElement* array = imageNode->FirstChildElement("array");
|
||||
if (array) {
|
||||
// create a temporary jpeg with size of the array
|
||||
FrameBufferImage::jpegBuffer jpgimg;
|
||||
array->QueryUnsignedAttribute("len", &jpgimg.len);
|
||||
// ok, we got a size of data to load
|
||||
if (jpgimg.len>0) {
|
||||
// allocate jpeg buffer
|
||||
jpgimg.buffer = (unsigned char*) malloc(jpgimg.len);
|
||||
// actual decoding of array
|
||||
if (XMLElementDecodeArray(array, jpgimg.buffer, jpgimg.len) )
|
||||
// create and set the image from jpeg
|
||||
s.setMask(new FrameBufferImage(jpgimg));
|
||||
// free temporary buffer
|
||||
if (jpgimg.buffer)
|
||||
free(jpgimg.buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
xmlCurrent_ = sourceNode->FirstChildElement("ImageProcessing");
|
||||
if (xmlCurrent_) {
|
||||
|
||||
@@ -208,17 +208,18 @@ void SessionVisitor::visit(ImageShader &n)
|
||||
|
||||
void SessionVisitor::visit(MaskShader &n)
|
||||
{
|
||||
// Shader of a textured type
|
||||
// Shader of a mask type
|
||||
xmlCurrent_->SetAttribute("type", "MaskShader");
|
||||
xmlCurrent_->SetAttribute("id", n.id());
|
||||
xmlCurrent_->SetAttribute("mode", n.mode);
|
||||
xmlCurrent_->SetAttribute("shape", n.shape);
|
||||
|
||||
XMLElement *uniforms = xmlDoc_->NewElement("uniforms");
|
||||
uniforms->SetAttribute("blur", n.blur);
|
||||
uniforms->SetAttribute("option", n.option);
|
||||
XMLElement *size = xmlDoc_->NewElement("size");
|
||||
size->InsertEndChild( XMLElementFromGLM(xmlDoc_, n.size) );
|
||||
uniforms->InsertEndChild(size);
|
||||
|
||||
xmlCurrent_->InsertEndChild(uniforms);
|
||||
}
|
||||
|
||||
@@ -368,6 +369,28 @@ void SessionVisitor::visit (Source& s)
|
||||
xmlCurrent_ = xmlDoc_->NewElement( "Mask" );
|
||||
sourceNode->InsertEndChild(xmlCurrent_);
|
||||
s.maskShader()->accept(*this);
|
||||
// if we are saving a pain mask
|
||||
if (s.maskShader()->mode == MaskShader::PAINT) {
|
||||
// get the mask previously stored
|
||||
FrameBufferImage *img = s.getMask();
|
||||
if (img != nullptr) {
|
||||
// get the jpeg encoded buffer
|
||||
FrameBufferImage::jpegBuffer jpgimg = img->getJpeg();
|
||||
if (jpgimg.buffer != nullptr) {
|
||||
// fill the xml array with jpeg buffer
|
||||
XMLElement *array = XMLElementEncodeArray(xmlDoc_, jpgimg.buffer, jpgimg.len);
|
||||
// free the buffer
|
||||
free(jpgimg.buffer);
|
||||
// if we could create the array
|
||||
if (array) {
|
||||
// create an Image node to store the mask image
|
||||
XMLElement *imageelement = xmlDoc_->NewElement("Image");
|
||||
imageelement->InsertEndChild(array);
|
||||
xmlCurrent_->InsertEndChild(imageelement);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
xmlCurrent_ = xmlDoc_->NewElement( "ImageProcessing" );
|
||||
xmlCurrent_->SetAttribute("enabled", s.imageProcessingEnabled());
|
||||
|
||||
77
Source.cpp
77
Source.cpp
@@ -206,7 +206,8 @@ Source::Source() : initialized_(false), active_(true), need_update_(true), symbo
|
||||
rendersurface_ = nullptr;
|
||||
mixingsurface_ = nullptr;
|
||||
maskbuffer_ = nullptr;
|
||||
|
||||
maskimage_ = nullptr;
|
||||
mask_need_update_ = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -223,6 +224,8 @@ Source::~Source()
|
||||
delete renderbuffer_;
|
||||
if (maskbuffer_)
|
||||
delete maskbuffer_;
|
||||
if (maskimage_)
|
||||
delete maskimage_;
|
||||
|
||||
// all groups and their children are deleted in the scene
|
||||
// this includes rendersurface_, overlays, blendingshader_ and rendershader_
|
||||
@@ -381,7 +384,7 @@ void Source::attach(FrameBuffer *renderbuffer)
|
||||
// (re) create the masking buffer
|
||||
if (maskbuffer_)
|
||||
delete maskbuffer_;
|
||||
maskbuffer_ = new FrameBuffer( renderbuffer->resolution() );
|
||||
maskbuffer_ = new FrameBuffer( glm::vec3(0.5) * renderbuffer->resolution() );
|
||||
|
||||
// make the source visible
|
||||
if ( mode_ == UNINITIALIZED )
|
||||
@@ -433,8 +436,8 @@ void Source::update(float dt)
|
||||
// read position of the mixing node and interpret this as transparency of render output
|
||||
glm::vec2 dist = glm::vec2(groups_[View::MIXING]->translation_);
|
||||
// use the prefered transfer function
|
||||
blendingshader_->color.a = sin_quad( dist.x, dist.y );
|
||||
mixingshader_->color.a = blendingshader_->color.a;
|
||||
blendingshader_->color = glm::vec4(1.0, 1.0, 1.0, sin_quad( dist.x, dist.y ));
|
||||
mixingshader_->color = blendingshader_->color;
|
||||
|
||||
// CHANGE update status based on limbo
|
||||
bool a = glm::length(dist) < 1.3f;
|
||||
@@ -454,6 +457,7 @@ void Source::update(float dt)
|
||||
|
||||
// MODIFY CROP projection based on GEOMETRY crop
|
||||
renderbuffer_->setProjectionArea( glm::vec2(groups_[View::GEOMETRY]->crop_) );
|
||||
|
||||
// Mixing and layer icons scaled based on GEOMETRY crop
|
||||
mixingsurface_->scale_ = groups_[View::GEOMETRY]->crop_;
|
||||
mixingsurface_->scale_.x *= renderbuffer_->aspectRatio();
|
||||
@@ -487,10 +491,24 @@ void Source::update(float dt)
|
||||
// 7. switch back to UV coordinate system
|
||||
texturesurface_->shader()->iTransform = glm::inverse(UVtoScene) * glm::inverse(Sca) * glm::inverse(Ar) * Rot * Tra * Ar * UVtoScene;
|
||||
|
||||
// draw nask in mask frame buffer
|
||||
maskbuffer_->begin();
|
||||
masksurface_->draw(glm::identity<glm::mat4>(), maskbuffer_->projection());
|
||||
maskbuffer_->end();
|
||||
// if a mask image was given to be updated
|
||||
if (mask_need_update_) {
|
||||
// fill the mask buffer (once)
|
||||
if (maskbuffer_->fill(maskimage_) )
|
||||
mask_need_update_ = false;
|
||||
}
|
||||
// otherwise, render the mask buffer
|
||||
else
|
||||
{
|
||||
// draw mask in mask frame buffer
|
||||
maskbuffer_->begin(false);
|
||||
// loopback maskbuffer texture for painting
|
||||
masksurface_->setTextureIndex(maskbuffer_->texture());
|
||||
// fill surface with mask texture
|
||||
masksurface_->draw(glm::identity<glm::mat4>(), maskbuffer_->projection());
|
||||
maskbuffer_->end();
|
||||
}
|
||||
|
||||
// set the rendered mask as mask for blending
|
||||
blendingshader_->mask_texture = maskbuffer_->texture();
|
||||
|
||||
@@ -522,6 +540,49 @@ bool Source::contains(Node *node) const
|
||||
}
|
||||
|
||||
|
||||
void Source::storeMask(FrameBufferImage *img)
|
||||
{
|
||||
// free the output mask storage
|
||||
if (maskimage_ != nullptr) {
|
||||
delete maskimage_;
|
||||
maskimage_ = nullptr;
|
||||
}
|
||||
|
||||
// if no image is provided
|
||||
if (img == nullptr) {
|
||||
// if ready
|
||||
if (maskbuffer_!=nullptr) {
|
||||
// get & store image from mask buffer
|
||||
maskimage_ = maskbuffer_->image();
|
||||
}
|
||||
}
|
||||
else
|
||||
// store the given image
|
||||
maskimage_ = img;
|
||||
|
||||
// maskimage_ can now be accessed with Source::getStoredMask
|
||||
}
|
||||
|
||||
void Source::setMask(FrameBufferImage *img)
|
||||
{
|
||||
// if a valid image is given
|
||||
if (img != nullptr && img->width>0 && img->height>0) {
|
||||
|
||||
// remember this new image as the current mask
|
||||
// NB: will be freed when replaced
|
||||
storeMask(img);
|
||||
|
||||
// ask Source::update to use it at next update for filling mask buffer
|
||||
mask_need_update_ = true;
|
||||
|
||||
// ask to update the source
|
||||
touch();
|
||||
}
|
||||
else
|
||||
mask_need_update_ = false;
|
||||
}
|
||||
|
||||
|
||||
bool Source::hasNode::operator()(const Source* elem) const
|
||||
{
|
||||
if (_n && elem)
|
||||
|
||||
14
Source.h
14
Source.h
@@ -77,16 +77,15 @@ public:
|
||||
|
||||
// a Source has a shader to control mixing effects
|
||||
inline ImageShader *blendingShader () const { return blendingshader_; }
|
||||
|
||||
// a Source has a shader used to render mask
|
||||
inline MaskShader *maskShader () const { return maskshader_; }
|
||||
|
||||
// a Source has a shader used to render in fbo
|
||||
inline Shader *renderingShader () const { return renderingshader_; }
|
||||
|
||||
// every Source has a frame buffer from the renderbuffer
|
||||
virtual FrameBuffer *frame () const;
|
||||
|
||||
// a Source has a shader used to render mask
|
||||
inline MaskShader *maskShader () const { return maskshader_; }
|
||||
|
||||
// touch to request update
|
||||
inline void touch () { need_update_ = true; }
|
||||
|
||||
@@ -112,6 +111,11 @@ public:
|
||||
// accept all kind of visitors
|
||||
virtual void accept (Visitor& v);
|
||||
|
||||
// operations on mask
|
||||
void storeMask(FrameBufferImage *img = nullptr);
|
||||
FrameBufferImage *getMask() const { return maskimage_; }
|
||||
void setMask(FrameBufferImage *img);
|
||||
|
||||
struct hasNode: public std::unary_function<Source*, bool>
|
||||
{
|
||||
bool operator()(const Source* elem) const;
|
||||
@@ -179,6 +183,8 @@ protected:
|
||||
MaskShader *maskshader_;
|
||||
FrameBuffer *maskbuffer_;
|
||||
Surface *masksurface_;
|
||||
bool mask_need_update_;
|
||||
FrameBufferImage *maskimage_;
|
||||
|
||||
// surface to draw on
|
||||
Surface *texturesurface_;
|
||||
|
||||
@@ -179,7 +179,6 @@ bool UserInterface::Init()
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGui::CreateContext();
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
|
||||
io.FontGlobalScale = Settings::application.scale;
|
||||
|
||||
// Setup Platform/Renderer bindings
|
||||
@@ -447,10 +446,18 @@ void UserInterface::handleMouse()
|
||||
if (ImGui::IsMouseClicked(ImGuiMouseButton_Right) /*|| ImGui::IsMouseClicked(ImGuiMouseButton_Middle)*/)
|
||||
ImGui::FocusWindow(NULL);
|
||||
|
||||
//
|
||||
// Mouse over
|
||||
//
|
||||
{
|
||||
View::Cursor c = Mixer::manager().view()->over(mousepos);
|
||||
if (c.type > 0)
|
||||
setMouseCursor(io.MousePos, c);
|
||||
}
|
||||
|
||||
// if not on any window
|
||||
if ( !ImGui::IsAnyWindowHovered() && !ImGui::IsAnyWindowFocused() )
|
||||
{
|
||||
|
||||
//
|
||||
// Mouse wheel over background
|
||||
//
|
||||
|
||||
433
View.cpp
433
View.cpp
@@ -1681,14 +1681,14 @@ void TransitionView::draw()
|
||||
scene.accept(dv2);
|
||||
|
||||
// display interface duration
|
||||
glm::vec2 P = Rendering::manager().project(glm::vec3(-0.11f, -0.14f, 0.f), scene.root()->transform_, false);
|
||||
glm::vec2 P = Rendering::manager().project(glm::vec3(-0.15f, -0.14f, 0.f), scene.root()->transform_, false);
|
||||
ImGui::SetNextWindowPos(ImVec2(P.x, P.y), ImGuiCond_Always);
|
||||
if (ImGui::Begin("##Transition", NULL, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoBackground
|
||||
| ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings
|
||||
| ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav))
|
||||
| ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoBringToFrontOnFocus))
|
||||
{
|
||||
ImGuiToolkit::PushFont(ImGuiToolkit::FONT_LARGE);
|
||||
ImGui::SetNextItemWidth(100.f);
|
||||
ImGui::SetNextItemWidth(160.f);
|
||||
ImGui::DragFloat("##transitionduration", &Settings::application.transition.duration,
|
||||
0.1f, TRANSITION_MIN_DURATION, TRANSITION_MAX_DURATION, "%.1f s");
|
||||
ImGui::SameLine();
|
||||
@@ -1912,21 +1912,43 @@ AppearanceView::AppearanceView() : View(APPEARANCE), edit_source_(nullptr), need
|
||||
// Mask manipulation
|
||||
mask_node_ = new Group;
|
||||
mask_square_ = new Frame(Frame::SHARP, Frame::LARGE, Frame::NONE);
|
||||
mask_square_->color = glm::vec4( COLOR_APPEARANCE_MASK, 1.0f ); //BLUE
|
||||
mask_square_->color = glm::vec4( COLOR_APPEARANCE_MASK, 1.f );
|
||||
mask_node_->attach(mask_square_);
|
||||
mask_handle_ = new Handles(Handles::CROP);
|
||||
mask_handle_->color = glm::vec4( COLOR_APPEARANCE_MASK, 1.0f ); //BLUE
|
||||
mask_node_->attach(mask_handle_);
|
||||
mask_circle_ = new Mesh("mesh/circle.ply");
|
||||
mask_circle_->shader()->color = glm::vec4( COLOR_APPEARANCE_MASK, 1.0f );
|
||||
mask_circle_->shader()->color = glm::vec4( COLOR_APPEARANCE_MASK, 1.f );
|
||||
mask_node_->attach(mask_circle_);
|
||||
mask_corner_ = new Mesh("mesh/corner.ply");
|
||||
mask_corner_->shader()->color = glm::vec4( COLOR_APPEARANCE_MASK, 0.9f );
|
||||
mask_corner_->translation_ = glm::vec3(-1.f, -1.0f, 0.0f);
|
||||
mask_corner_->scale_ = glm::vec3(0.5f, 0.5f, 1.f);
|
||||
mask_node_->attach(mask_corner_);
|
||||
mask_horizontal_ = new Mesh("mesh/h_line.ply");
|
||||
mask_horizontal_->shader()->color = glm::vec4( COLOR_APPEARANCE_MASK, 1.f );
|
||||
mask_horizontal_->scale_.x = 1.0f;
|
||||
mask_horizontal_->scale_.y = 3.0f;
|
||||
mask_node_->attach(mask_horizontal_);
|
||||
mask_vertical_ = new Group;
|
||||
Mesh *line = new Mesh("mesh/h_line.ply");
|
||||
line->shader()->color = glm::vec4( COLOR_APPEARANCE_MASK, 1.f );
|
||||
line->scale_.x = 1.0f;
|
||||
line->scale_.y = 3.0f;
|
||||
line->rotation_.z = M_PI_2;
|
||||
mask_vertical_->attach(line);
|
||||
mask_node_->attach(mask_vertical_);
|
||||
scene.fg()->attach(mask_node_);
|
||||
|
||||
// horizontal_mark_ = new Mesh("mesh/h_mark.ply");
|
||||
// horizontal_mark_->translation_ = glm::vec3(0.f, 1.12f, 0.0f);
|
||||
// horizontal_mark_->scale_ = glm::vec3(2.5f, -2.5f, 0.0f);
|
||||
// horizontal_mark_->shader()->color = glm::vec4( COLOR_TRANSITION_LINES, 0.9f );
|
||||
//// scene.bg()->attach(horizontal_mark_);
|
||||
// // vertical axis
|
||||
// vertical_line_ = new Group;
|
||||
// Mesh *line = new Mesh("mesh/h_line.ply");
|
||||
// line->shader()->color = glm::vec4( COLOR_TRANSITION_LINES, 0.9f );
|
||||
// line->translation_ = glm::vec3(-0.12f, 0.0f, 0.0f);
|
||||
// line->scale_.x = 1.0f;
|
||||
// line->scale_.y = 3.0f;
|
||||
// line->rotation_.z = M_PI_2;
|
||||
//// vertical_line_->attach(line);
|
||||
|
||||
|
||||
|
||||
// Source manipulation (texture coordinates)
|
||||
//
|
||||
// point to show POSITION
|
||||
@@ -2001,17 +2023,25 @@ AppearanceView::AppearanceView() : View(APPEARANCE), edit_source_(nullptr), need
|
||||
scene.fg()->attach(overlay_rotation_);
|
||||
overlay_rotation_->visible_ = false;
|
||||
|
||||
|
||||
/// Tests
|
||||
// test_buffer = new FrameBuffer(800, 450);
|
||||
// Log::Info("test_buffer %s", test_buffer->info().c_str());
|
||||
// test_shader = new MaskShader;
|
||||
// test_shader->type = 0;
|
||||
// test_shader->blur = 0.0;
|
||||
// test_surface = new Surface(test_shader);
|
||||
// preview_mask_ = new FrameBufferSurface(test_buffer); // to attach source preview
|
||||
// preview_mask_->translation_.z = 0.002f;
|
||||
//// scene.bg()->attach(preview_mask_);
|
||||
// Mask draw
|
||||
mask_cursor_paint_ = 0;
|
||||
mask_cursor_shape_ = 0;
|
||||
stored_mask_size_ = glm::vec3(0.f);
|
||||
mask_cursor_circle_ = new Mesh("mesh/icon_circle.ply");
|
||||
mask_cursor_circle_->scale_ = glm::vec3(0.2f, 0.2f, 1.f);
|
||||
mask_cursor_circle_->shader()->color = glm::vec4( COLOR_APPEARANCE_MASK, 0.8f );
|
||||
mask_cursor_circle_->visible_ = false;
|
||||
scene.fg()->attach(mask_cursor_circle_);
|
||||
mask_cursor_square_ = new Mesh("mesh/icon_square.ply");
|
||||
mask_cursor_square_->scale_ = glm::vec3(0.2f, 0.2f, 1.f);
|
||||
mask_cursor_square_->shader()->color = glm::vec4( COLOR_APPEARANCE_MASK, 0.8f );
|
||||
mask_cursor_square_->visible_ = false;
|
||||
scene.fg()->attach(mask_cursor_square_);
|
||||
mask_cursor_crop_ = new Mesh("mesh/icon_crop.ply");
|
||||
mask_cursor_crop_->scale_ = glm::vec3(1.2f, 1.2f, 1.f);
|
||||
mask_cursor_crop_->shader()->color = glm::vec4( COLOR_APPEARANCE_MASK, 0.8f );
|
||||
mask_cursor_crop_->visible_ = false;
|
||||
scene.fg()->attach(mask_cursor_crop_);
|
||||
|
||||
}
|
||||
|
||||
@@ -2078,6 +2108,48 @@ void AppearanceView::select(glm::vec2 A, glm::vec2 B)
|
||||
}
|
||||
|
||||
|
||||
View::Cursor AppearanceView::over (glm::vec2 pos)
|
||||
{
|
||||
if (edit_source_ != nullptr)
|
||||
{
|
||||
glm::vec3 scene_pos = Rendering::manager().unProject(pos, scene.root()->transform_);
|
||||
glm::vec2 P(scene_pos);
|
||||
glm::vec2 S(preview_surface_->scale_);
|
||||
mask_cursor_circle_->translation_ = glm::vec3(P, 0.f);
|
||||
mask_cursor_square_->translation_ = glm::vec3(P, 0.f);
|
||||
mask_cursor_crop_->translation_ = glm::vec3(P, 0.f);
|
||||
mask_cursor_circle_->visible_ = false;
|
||||
mask_cursor_square_->visible_ = false;
|
||||
mask_cursor_crop_->visible_ = false;
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
if (!io.WantCaptureMouse) {
|
||||
|
||||
// show paint brush cursor
|
||||
if (edit_source_->maskShader()->mode == MaskShader::PAINT) {
|
||||
if (mask_cursor_paint_ > 0) {
|
||||
if ( ABS(P.x) < S.x && ABS(P.y) < S.y ) {
|
||||
mask_cursor_circle_->visible_ = edit_source_->maskShader()->brush.z < 1.0;
|
||||
mask_cursor_square_->visible_ = edit_source_->maskShader()->brush.z > 0.0;
|
||||
edit_source_->maskShader()->option = mask_cursor_paint_;
|
||||
}
|
||||
else {
|
||||
edit_source_->maskShader()->option = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
// show crup cursor
|
||||
else if (edit_source_->maskShader()->mode == MaskShader::SHAPE) {
|
||||
if (mask_cursor_shape_ > 0) {
|
||||
mask_cursor_crop_->visible_ = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Cursor();
|
||||
}
|
||||
|
||||
std::pair<Node *, glm::vec2> AppearanceView::pick(glm::vec2 P)
|
||||
{
|
||||
// prepare empty return value
|
||||
@@ -2093,9 +2165,21 @@ std::pair<Node *, glm::vec2> AppearanceView::pick(glm::vec2 P)
|
||||
// picking visitor found nodes?
|
||||
if ( !pv.empty()) {
|
||||
// keep edit source active if it is clicked
|
||||
// AND if the cursor is not for drawing
|
||||
Source *s = edit_source_;
|
||||
if (s != nullptr) {
|
||||
|
||||
// special case for drawing in the mask
|
||||
if ( s->maskShader()->mode == MaskShader::PAINT && mask_cursor_paint_ > 0) {
|
||||
pick = { mask_cursor_circle_, P };
|
||||
return pick;
|
||||
}
|
||||
// special case for cropping the mask shape
|
||||
else if ( s->maskShader()->mode == MaskShader::SHAPE && mask_cursor_shape_ > 0) {
|
||||
pick = { mask_cursor_crop_, P };
|
||||
return pick;
|
||||
}
|
||||
|
||||
// find if the edit source was picked
|
||||
auto itp = pv.rbegin();
|
||||
for (; itp != pv.rend(); itp++){
|
||||
@@ -2106,10 +2190,6 @@ std::pair<Node *, glm::vec2> AppearanceView::pick(glm::vec2 P)
|
||||
pick = *itp;
|
||||
break;
|
||||
}
|
||||
else if ( (*itp).first == mask_handle_ ) {
|
||||
pick = *itp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// not found: the edit source was not clicked
|
||||
if ( itp == pv.rend() )
|
||||
@@ -2149,18 +2229,29 @@ void AppearanceView::adjustBackground()
|
||||
preview_shader_->mask_texture = edit_source_->blendingShader()->mask_texture;
|
||||
preview_surface_->scale_ = scale;
|
||||
// mask appearance
|
||||
mask_node_->visible_ = edit_source_->maskShader()->mode > 0;
|
||||
mask_circle_->visible_ = edit_source_->maskShader()->mode == 1;
|
||||
mask_square_->visible_ = edit_source_->maskShader()->mode >= 2;
|
||||
if (edit_source_->maskShader()->mode >= 4) {
|
||||
mask_node_->scale_ = scale;
|
||||
mask_node_->translation_ = scale - glm::vec3(edit_source_->maskShader()->size, 0.f) * scale ;
|
||||
mask_node_->translation_.z = 0.f;
|
||||
} else {
|
||||
mask_node_->visible_ = edit_source_->maskShader()->mode > MaskShader::PAINT && mask_cursor_shape_ > 0;
|
||||
|
||||
int shape = edit_source_->maskShader()->shape;
|
||||
mask_circle_->visible_ = shape == MaskShader::ELIPSE;
|
||||
mask_square_->visible_ = shape == MaskShader::OBLONG || shape == MaskShader::RECTANGLE;
|
||||
mask_horizontal_->visible_ = shape == MaskShader::HORIZONTAL;
|
||||
mask_vertical_->visible_ = shape == MaskShader::VERTICAL;
|
||||
|
||||
// symetrical shapes
|
||||
if ( shape < MaskShader::HORIZONTAL){
|
||||
mask_node_->scale_ = scale * glm::vec3(edit_source_->maskShader()->size, 1.f);
|
||||
mask_node_->translation_ = glm::vec3(0.f);
|
||||
}
|
||||
mask_corner_->scale_.y = mask_corner_->scale_.x * mask_node_->scale_.x / mask_node_->scale_.y;
|
||||
// vertical
|
||||
else if ( shape > MaskShader::HORIZONTAL ) {
|
||||
mask_node_->scale_ = glm::vec3(1.f, scale.y, 1.f);
|
||||
mask_node_->translation_ = glm::vec3(edit_source_->maskShader()->size.x * scale.x, 0.f, 0.f);
|
||||
}
|
||||
// horizontal
|
||||
else {
|
||||
mask_node_->scale_ = glm::vec3(scale.x, 1.f, 1.f);
|
||||
mask_node_->translation_ = glm::vec3(0.f, edit_source_->maskShader()->size.y * scale.y, 0.f);
|
||||
}
|
||||
}
|
||||
|
||||
// background scene
|
||||
@@ -2174,11 +2265,6 @@ void AppearanceView::adjustBackground()
|
||||
static glm::mat4 Tra = glm::scale(glm::translate(glm::identity<glm::mat4>(), glm::vec3( -32.f, -32.f, 0.f)), glm::vec3( 64.f, 64.f, 1.f));
|
||||
preview_checker_->shader()->iTransform = Ar * Tra;
|
||||
|
||||
// /// Tests
|
||||
// // update mask
|
||||
// test_buffer->begin();
|
||||
// test_surface->draw(glm::identity<glm::mat4>(), test_buffer->projection());
|
||||
// test_buffer->end();
|
||||
}
|
||||
|
||||
Source *AppearanceView::getEditOrCurrentSource()
|
||||
@@ -2226,17 +2312,25 @@ void AppearanceView::draw()
|
||||
|
||||
// draw marks in axis
|
||||
if (edit_source_ != nullptr && show_scale_){
|
||||
{
|
||||
if (edit_source_->maskShader()->shape != MaskShader::HORIZONTAL){
|
||||
DrawVisitor dv(horizontal_mark_, Rendering::manager().Projection());
|
||||
glm::vec3 dT = glm::vec3( -0.2f * edit_source_->mixingsurface_->scale_.x, 0.f, 0.f);
|
||||
glm::mat4 T = glm::translate(glm::identity<glm::mat4>(), dT);
|
||||
DrawVisitor dv(horizontal_mark_, Rendering::manager().Projection());
|
||||
dv.loop(6, T);
|
||||
scene.accept(dv);
|
||||
dT = glm::vec3( +0.2f * edit_source_->mixingsurface_->scale_.x, 0.f, 0.f);
|
||||
T = glm::translate(glm::identity<glm::mat4>(), dT);
|
||||
dv.loop(6, T);
|
||||
scene.accept(dv);
|
||||
}
|
||||
{
|
||||
if (edit_source_->maskShader()->shape != MaskShader::VERTICAL){
|
||||
DrawVisitor dv(vertical_mark_, Rendering::manager().Projection());
|
||||
glm::vec3 dT = glm::vec3( 0.f, -0.2f * edit_source_->mixingsurface_->scale_.y, 0.f);
|
||||
glm::mat4 T = glm::translate(glm::identity<glm::mat4>(), dT);
|
||||
DrawVisitor dv(vertical_mark_, Rendering::manager().Projection());
|
||||
dv.loop(6, T);
|
||||
scene.accept(dv);
|
||||
dT = glm::vec3( 0.f, +0.2f * edit_source_->mixingsurface_->scale_.y, 0.f);
|
||||
T = glm::translate(glm::identity<glm::mat4>(), dT);
|
||||
dv.loop(6, T);
|
||||
scene.accept(dv);
|
||||
}
|
||||
@@ -2260,40 +2354,181 @@ void AppearanceView::draw()
|
||||
ImGui::SetNextWindowPos(ImVec2(P.x, P.y - 70.f ), ImGuiCond_Always);
|
||||
if (ImGui::Begin("##AppearanceMaskOptions", NULL, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoBackground
|
||||
| ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings
|
||||
| ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav))
|
||||
| ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoBringToFrontOnFocus ))
|
||||
{
|
||||
ImGuiToolkit::PushFont(ImGuiToolkit::FONT_LARGE);
|
||||
|
||||
int type = edit_source_->maskShader()->mode;
|
||||
int mode = edit_source_->maskShader()->mode;
|
||||
ImGui::SetNextItemWidth(100.f);
|
||||
if ( ImGui::Combo("Mask ", &type, MaskShader::mask_names, IM_ARRAYSIZE(MaskShader::mask_names) ) ) {
|
||||
edit_source_->maskShader()->mode = type;
|
||||
if ( ImGui::Combo("Mask ", &mode, MaskShader::mask_names, IM_ARRAYSIZE(MaskShader::mask_names) ) ) {
|
||||
edit_source_->maskShader()->mode = mode;
|
||||
if (mode == MaskShader::NONE)
|
||||
Mixer::manager().setCurrentSource(edit_source_);
|
||||
else if (mode == MaskShader::PAINT)
|
||||
edit_source_->storeMask();
|
||||
edit_source_->touch();
|
||||
need_edit_update_ = true;
|
||||
// store action history
|
||||
std::ostringstream oss;
|
||||
oss << edit_source_->name() << ": Texture Mask " << type;
|
||||
oss << edit_source_->name() << ": Texture Mask " << mode;
|
||||
Action::manager().store(oss.str(), edit_source_->id());
|
||||
}
|
||||
|
||||
if (edit_source_->maskShader()->mode > 0) {
|
||||
int val = int(edit_source_->maskShader()->blur * 100.f);
|
||||
static bool smoothchanged = false;
|
||||
// GUI for drawing mask
|
||||
if (edit_source_->maskShader()->mode == MaskShader::PAINT) {
|
||||
|
||||
// select cursor
|
||||
static bool on = true;
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(190.f);
|
||||
if (ImGui::DragInt("Smooth", &val, 1, 0, 100, "%d%%") ) {
|
||||
edit_source_->maskShader()->blur = float(val) / 100.f;
|
||||
edit_source_->touch();
|
||||
on = mask_cursor_paint_ == 0;
|
||||
if (ImGuiToolkit::ButtonToggle(ICON_FA_MOUSE_POINTER, &on)) {
|
||||
Mixer::manager().setCurrentSource(edit_source_);
|
||||
mask_cursor_paint_ = 0;
|
||||
}
|
||||
if (ImGui::IsItemHovered())
|
||||
{
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::Text("Cursor");
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
on = mask_cursor_paint_ == 1;
|
||||
if (ImGuiToolkit::ButtonToggle(ICON_FA_PAINT_BRUSH, &on)) {
|
||||
Mixer::manager().unsetCurrentSource();
|
||||
mask_cursor_paint_ = 1;
|
||||
}
|
||||
if (ImGui::IsItemHovered())
|
||||
{
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::Text("Paint");
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
on = mask_cursor_paint_ == 2;
|
||||
if (ImGuiToolkit::ButtonToggle(ICON_FA_ERASER, &on)) {
|
||||
Mixer::manager().unsetCurrentSource();
|
||||
mask_cursor_paint_ = 2;
|
||||
}
|
||||
if (ImGui::IsItemHovered())
|
||||
{
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::Text("Erase");
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
|
||||
if (mask_cursor_paint_ > 0) {
|
||||
|
||||
ImGui::SameLine(0, 50);
|
||||
ImGui::SetNextItemWidth(100.f);
|
||||
const char* items[] = { ICON_FA_CIRCLE, ICON_FA_SQUARE };
|
||||
static int item = 0;
|
||||
item = (int) round(edit_source_->maskShader()->brush.z);
|
||||
if(ImGui::Combo("##BrushShape", &item, items, IM_ARRAYSIZE(items))) {
|
||||
edit_source_->maskShader()->brush.z = float(item);
|
||||
}
|
||||
ImGui::SameLine(0, 20);
|
||||
ImGui::SetNextItemWidth(180.f);
|
||||
|
||||
int pixel_size_min = int(0.05 * edit_source_->frame()->height() );
|
||||
int pixel_size_max = int(2.0 * edit_source_->frame()->height() );
|
||||
int pixel_size = int(edit_source_->maskShader()->brush.x *
|
||||
edit_source_->frame()->height() );
|
||||
if (ImGui::SliderInt("##BrushSize", &pixel_size, pixel_size_min, pixel_size_max, "%dpx") )
|
||||
edit_source_->maskShader()->brush.x = CLAMP(float(pixel_size) / edit_source_->frame()->height(), 0.05, 2.0);
|
||||
// ImGui::SliderFloat("Size", &edit_source_->maskShader()->brush.x, 0.1, 2.0, "%.1f");
|
||||
|
||||
glm::vec2 s = glm::vec2(edit_source_->maskShader()->brush.x);
|
||||
mask_cursor_circle_->scale_ = glm::vec3(s * 1.16f, 1.f);
|
||||
mask_cursor_square_->scale_ = glm::vec3(s * 1.72f, 1.f);
|
||||
ImGui::SameLine(0, 20);
|
||||
ImGui::SetNextItemWidth(150.f);
|
||||
ImGui::SliderFloat("Strength", &edit_source_->maskShader()->brush.y, 0.01, 1.0, "%.2f", 3.f);
|
||||
}
|
||||
|
||||
}
|
||||
// GUI for all other masks
|
||||
else if (edit_source_->maskShader()->mode == MaskShader::SHAPE) {
|
||||
|
||||
// select cursor
|
||||
static bool on = true;
|
||||
ImGui::SameLine();
|
||||
on = mask_cursor_shape_ == 0;
|
||||
if (ImGuiToolkit::ButtonToggle(ICON_FA_MOUSE_POINTER, &on)) {
|
||||
Mixer::manager().setCurrentSource(edit_source_);
|
||||
need_edit_update_ = true;
|
||||
smoothchanged = true;
|
||||
mask_cursor_shape_ = 0;
|
||||
}
|
||||
else if (smoothchanged && ImGui::IsMouseReleased(ImGuiMouseButton_Left)){
|
||||
// store action history
|
||||
std::ostringstream oss;
|
||||
oss << edit_source_->name() << ": Texture Smooth " << edit_source_->maskShader()->blur;
|
||||
Action::manager().store(oss.str(), edit_source_->id());
|
||||
smoothchanged = false;
|
||||
if (ImGui::IsItemHovered())
|
||||
{
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::Text("Cursor");
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
on = mask_cursor_shape_ == 1;
|
||||
if (ImGuiToolkit::ButtonToggle(ICON_FA_CROP_ALT, &on)) {
|
||||
Mixer::manager().unsetCurrentSource();
|
||||
need_edit_update_ = true;
|
||||
mask_cursor_shape_ = 1;
|
||||
}
|
||||
if (ImGui::IsItemHovered())
|
||||
{
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::Text("Crop");
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
|
||||
int shape = edit_source_->maskShader()->shape;
|
||||
int val = int(edit_source_->maskShader()->blur * 100.f);
|
||||
|
||||
if (mask_cursor_shape_ > 0) {
|
||||
|
||||
ImGui::SameLine(0, 50);
|
||||
ImGui::SetNextItemWidth(220.f);
|
||||
if ( ImGui::Combo("##MaskShape", &shape, MaskShader::mask_shapes, IM_ARRAYSIZE(MaskShader::mask_shapes) ) ) {
|
||||
edit_source_->maskShader()->shape = shape;
|
||||
edit_source_->touch();
|
||||
need_edit_update_ = true;
|
||||
// store action history
|
||||
std::ostringstream oss;
|
||||
oss << edit_source_->name() << ": Texture Shape " << shape;
|
||||
Action::manager().store(oss.str(), edit_source_->id());
|
||||
}
|
||||
|
||||
static bool smoothchanged = false;
|
||||
|
||||
ImGui::SameLine(0, 20);
|
||||
ImGui::SetNextItemWidth(190.f);
|
||||
if (ImGui::DragInt("Smooth ", &val, 1, 0, 100, "%d%%") ) {
|
||||
edit_source_->maskShader()->blur = float(val) / 100.f;
|
||||
edit_source_->touch();
|
||||
need_edit_update_ = true;
|
||||
smoothchanged = true;
|
||||
}
|
||||
else if (smoothchanged && ImGui::IsMouseReleased(ImGuiMouseButton_Left)){
|
||||
// store action history
|
||||
std::ostringstream oss;
|
||||
oss << edit_source_->name() << ": Texture Smooth " << edit_source_->maskShader()->blur;
|
||||
Action::manager().store(oss.str(), edit_source_->id());
|
||||
smoothchanged = false;
|
||||
}
|
||||
}
|
||||
// disabled info
|
||||
else {
|
||||
ImGui::SameLine(0, 60);
|
||||
ImGui::TextDisabled( MaskShader::mask_shapes[shape] );
|
||||
ImGui::SameLine(0, 180);
|
||||
ImGui::TextDisabled( "%d%%", val );
|
||||
ImGui::SameLine(0, 60);
|
||||
ImGui::TextDisabled( "Smooth" );
|
||||
}
|
||||
}
|
||||
else {// mode == MaskShader::NONE
|
||||
// always active mouse pointer
|
||||
bool on = true;
|
||||
ImGui::SameLine();
|
||||
ImGuiToolkit::ButtonToggle(ICON_FA_MOUSE_POINTER, &on);
|
||||
|
||||
}
|
||||
|
||||
ImGui::PopFont();
|
||||
@@ -2312,6 +2547,8 @@ void AppearanceView::draw()
|
||||
show_scale_ = false;
|
||||
}
|
||||
|
||||
#define MASK_PAINT_ACTION_LABEL "Texture Paint"
|
||||
|
||||
View::Cursor AppearanceView::grab (Source *s, glm::vec2 from, glm::vec2 to, std::pair<Node *, glm::vec2> pick)
|
||||
{
|
||||
std::ostringstream info;
|
||||
@@ -2327,38 +2564,57 @@ View::Cursor AppearanceView::grab (Source *s, glm::vec2 from, glm::vec2 to, std:
|
||||
// work on the edited source
|
||||
if ( edit_source_ != nullptr ) {
|
||||
|
||||
// match edit source AR
|
||||
glm::vec3 scale = edit_source_->mixingsurface_->scale_;
|
||||
glm::vec3 delta = glm::vec3(0.1) / glm::vec3(scene.root()->scale_.x, scene.root()->scale_.y, 1.0);
|
||||
if ( pick.first == mask_cursor_circle_ ) {
|
||||
|
||||
if ( pick.first == mask_handle_ ) {
|
||||
// compute scaling of mask
|
||||
glm::vec3 val = -scene_to + delta;
|
||||
val /= scale;
|
||||
// discretized scaling with ALT
|
||||
// inform shader of a cursor action : coordinates and crop scaling
|
||||
edit_source_->maskShader()->cursor = glm::vec4(scene_to.x, scene_to.y,
|
||||
edit_source_->mixingsurface_->scale_.x, edit_source_->mixingsurface_->scale_.y);
|
||||
edit_source_->touch();
|
||||
// action label
|
||||
info << MASK_PAINT_ACTION_LABEL;
|
||||
// cursor indication - no info, just cursor
|
||||
ret.type = Cursor_Hand;
|
||||
}
|
||||
else if ( pick.first == mask_cursor_crop_ ) {
|
||||
|
||||
// special case for horizontal and vertical Shapes
|
||||
bool hv = edit_source_->maskShader()->shape > MaskShader::RECTANGLE;
|
||||
// match edit source AR
|
||||
glm::vec3 val = edit_source_->mixingsurface_->scale_;
|
||||
// use cursor translation to scale by quadrant
|
||||
val = glm::sign( hv ? glm::vec3(1.f) : scene_from) * glm::vec3(scene_translation / val);
|
||||
// relative change of stored mask size
|
||||
val += stored_mask_size_;
|
||||
// apply discrete scale with ALT modifier
|
||||
if (UserInterface::manager().altModifier()) {
|
||||
val.x = ROUND(val.x, 5.f);
|
||||
val.y = ROUND(val.y, 5.f);
|
||||
show_scale_ = true;
|
||||
}
|
||||
// crop mask horizontally
|
||||
edit_source_->maskShader()->size.x = CLAMP(val.x, 0.2f, 2.f);
|
||||
edit_source_->maskShader()->size.y = CLAMP(val.y, 0.2f, 2.f);
|
||||
// Clamp | val | < 2.0
|
||||
val = glm::sign(val) * glm::min( glm::abs(val), glm::vec3(2.f));
|
||||
// clamp values for correct effect
|
||||
if (edit_source_->maskShader()->shape == MaskShader::HORIZONTAL)
|
||||
edit_source_->maskShader()->size.y = val.y;
|
||||
else if (edit_source_->maskShader()->shape == MaskShader::VERTICAL)
|
||||
edit_source_->maskShader()->size.x = val.x;
|
||||
else
|
||||
edit_source_->maskShader()->size = glm::max(glm::abs(glm::vec2(val)), glm::vec2(0.2));
|
||||
// edit_source_->maskShader()->size = glm::max( glm::min( glm::vec2(val), glm::vec2(2.f)), glm::vec2(hv?-2.f:0.2f));
|
||||
edit_source_->touch();
|
||||
// update
|
||||
need_edit_update_ = true;
|
||||
// cursor indication
|
||||
// action label
|
||||
info << "Texture Mask " << std::fixed << std::setprecision(3) << edit_source_->maskShader()->size.x;
|
||||
info << " x " << edit_source_->maskShader()->size.y;
|
||||
ret.type = Cursor_ResizeNESW;
|
||||
// cursor indication - no info, just cursor
|
||||
ret.type = Cursor_Hand;
|
||||
}
|
||||
|
||||
// store action in history
|
||||
current_action_ = edit_source_->name() + ": " + info.str();
|
||||
current_id_ = edit_source_->id();
|
||||
|
||||
// update cursor
|
||||
ret.info = info.str();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -2684,8 +2940,25 @@ View::Cursor AppearanceView::grab (Source *s, glm::vec2 from, glm::vec2 to, std:
|
||||
}
|
||||
|
||||
|
||||
void AppearanceView::initiate()
|
||||
{
|
||||
// View default initiation of action
|
||||
View::initiate();
|
||||
|
||||
if ( edit_source_ != nullptr )
|
||||
stored_mask_size_ = glm::vec3(edit_source_->maskShader()->size, 0.0);
|
||||
else
|
||||
stored_mask_size_ = glm::vec3(0.f);
|
||||
}
|
||||
|
||||
void AppearanceView::terminate()
|
||||
{
|
||||
// special case for texture paint: store image on mouse release (end of action PAINT)
|
||||
if ( edit_source_ != nullptr && current_action_.find(MASK_PAINT_ACTION_LABEL) != std::string::npos ) {
|
||||
edit_source_->storeMask();
|
||||
}
|
||||
|
||||
// View default termination of action
|
||||
View::terminate();
|
||||
|
||||
// hide all overlays
|
||||
|
||||
27
View.h
27
View.h
@@ -71,10 +71,10 @@ public:
|
||||
return Cursor();
|
||||
}
|
||||
|
||||
// // test mouse over provided a point in screen coordinates and the picking point
|
||||
// virtual Cursor over (Source*, glm::vec2, std::pair<Node *, glm::vec2>) {
|
||||
// return Cursor();
|
||||
// }
|
||||
// test mouse over provided a point in screen coordinates
|
||||
virtual Cursor over (glm::vec2) {
|
||||
return Cursor();
|
||||
}
|
||||
|
||||
// accessible scene
|
||||
Scene scene;
|
||||
@@ -240,6 +240,9 @@ public:
|
||||
std::pair<Node *, glm::vec2> pick(glm::vec2 P) override;
|
||||
Cursor grab (Source *s, glm::vec2 from, glm::vec2 to, std::pair<Node *, glm::vec2> pick) override;
|
||||
Cursor drag (glm::vec2, glm::vec2) override;
|
||||
Cursor over (glm::vec2) override;
|
||||
|
||||
void initiate() override;
|
||||
void terminate() override;
|
||||
|
||||
private:
|
||||
@@ -261,8 +264,8 @@ private:
|
||||
Group *mask_node_;
|
||||
Frame *mask_square_;
|
||||
Mesh *mask_circle_;
|
||||
Mesh *mask_corner_;
|
||||
class Handles *mask_handle_;
|
||||
Mesh *mask_horizontal_;
|
||||
Group *mask_vertical_;
|
||||
|
||||
Symbol *overlay_position_;
|
||||
Symbol *overlay_position_cross_;
|
||||
@@ -275,12 +278,14 @@ private:
|
||||
Symbol *overlay_rotation_clock_hand_;
|
||||
bool show_context_menu_;
|
||||
|
||||
// for mask shader draw: 0=cursor, 1=brush, 2=eraser, 3=crop_shape
|
||||
int mask_cursor_paint_;
|
||||
int mask_cursor_shape_;
|
||||
Mesh *mask_cursor_circle_;
|
||||
Mesh *mask_cursor_square_;
|
||||
Mesh *mask_cursor_crop_;
|
||||
glm::vec3 stored_mask_size_;
|
||||
|
||||
// /// tests
|
||||
// Surface *preview_mask_;
|
||||
// Surface *test_surface;
|
||||
// class MaskShader *test_shader;
|
||||
// FrameBuffer *test_buffer;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#define APP_VERSION_MAJOR 0
|
||||
#define APP_VERSION_MINOR 4
|
||||
#define XML_VERSION_MAJOR 0
|
||||
#define XML_VERSION_MINOR 1
|
||||
#define XML_VERSION_MINOR 2
|
||||
#define MAX_RECENT_HISTORY 20
|
||||
|
||||
#define MINI(a, b) (((a) < (b)) ? (a) : (b))
|
||||
|
||||
506
rsc/mesh/icon_crop.ply
Normal file
506
rsc/mesh/icon_crop.ply
Normal file
@@ -0,0 +1,506 @@
|
||||
ply
|
||||
format ascii 1.0
|
||||
comment Created by Blender 2.91.0 - www.blender.org
|
||||
element vertex 250
|
||||
property float x
|
||||
property float y
|
||||
property float z
|
||||
element face 246
|
||||
property list uchar uint vertex_indices
|
||||
end_header
|
||||
-0.042157 0.063218 0.000000
|
||||
-0.041120 0.063272 0.000000
|
||||
-0.041354 0.063272 0.000000
|
||||
-0.040476 0.063272 0.000000
|
||||
-0.039503 0.063272 0.000000
|
||||
-0.038283 0.063272 0.000000
|
||||
-0.036898 0.063272 0.000000
|
||||
-0.035432 0.063272 0.000000
|
||||
-0.033965 0.063272 0.000000
|
||||
-0.032581 0.063272 0.000000
|
||||
-0.031361 0.063272 0.000000
|
||||
-0.030387 0.063272 0.000000
|
||||
-0.029743 0.063272 0.000000
|
||||
-0.029510 0.063272 0.000000
|
||||
-0.028707 0.063218 0.000000
|
||||
-0.042927 0.063061 0.000000
|
||||
-0.027936 0.063061 0.000000
|
||||
-0.043658 0.062807 0.000000
|
||||
-0.027206 0.062807 0.000000
|
||||
-0.044342 0.062464 0.000000
|
||||
-0.026522 0.062464 0.000000
|
||||
-0.044972 0.062039 0.000000
|
||||
-0.025892 0.062039 0.000000
|
||||
-0.045540 0.061539 0.000000
|
||||
-0.025323 0.061539 0.000000
|
||||
-0.046041 0.060970 0.000000
|
||||
-0.024823 0.060970 0.000000
|
||||
-0.046467 0.060341 0.000000
|
||||
-0.024397 0.060341 0.000000
|
||||
-0.046810 0.059657 0.000000
|
||||
-0.024054 0.059657 0.000000
|
||||
-0.047064 0.058926 0.000000
|
||||
-0.023800 0.058926 0.000000
|
||||
-0.047221 0.058155 0.000000
|
||||
-0.023642 0.058155 0.000000
|
||||
-0.047275 0.057352 0.000000
|
||||
-0.023588 0.057352 0.000000
|
||||
-0.047275 0.057158 0.000000
|
||||
-0.023588 0.055760 0.000000
|
||||
-0.047275 0.056621 0.000000
|
||||
-0.047275 0.055810 0.000000
|
||||
-0.047275 0.054794 0.000000
|
||||
-0.023588 0.051358 0.000000
|
||||
-0.047275 0.053640 0.000000
|
||||
-0.047275 0.052418 0.000000
|
||||
-0.047275 0.051196 0.000000
|
||||
-0.023588 0.044709 0.000000
|
||||
-0.047275 0.050043 0.000000
|
||||
-0.047275 0.049026 0.000000
|
||||
-0.047275 0.048215 0.000000
|
||||
-0.047275 0.047678 0.000000
|
||||
-0.047275 0.047484 0.000000
|
||||
-0.057948 0.047430 0.000000
|
||||
-0.057145 0.047484 0.000000
|
||||
-0.015693 0.023802 0.000000
|
||||
-0.014605 0.047484 0.000000
|
||||
-0.015693 0.047484 0.000000
|
||||
-0.011599 0.047484 0.000000
|
||||
-0.007057 0.047484 0.000000
|
||||
-0.001363 0.047484 0.000000
|
||||
0.005097 0.047484 0.000000
|
||||
0.011942 0.047484 0.000000
|
||||
0.018787 0.047484 0.000000
|
||||
0.025248 0.047484 0.000000
|
||||
0.030941 0.047484 0.000000
|
||||
0.035483 0.047484 0.000000
|
||||
0.038490 0.047484 0.000000
|
||||
0.039577 0.047484 0.000000
|
||||
0.040648 0.047412 0.000000
|
||||
-0.058719 0.047273 0.000000
|
||||
0.041676 0.047202 0.000000
|
||||
-0.059449 0.047019 0.000000
|
||||
0.042650 0.046864 0.000000
|
||||
-0.060133 0.046676 0.000000
|
||||
0.043562 0.046406 0.000000
|
||||
-0.060763 0.046251 0.000000
|
||||
0.044402 0.045839 0.000000
|
||||
-0.061332 0.045751 0.000000
|
||||
0.045160 0.045172 0.000000
|
||||
-0.061832 0.045182 0.000000
|
||||
-0.062258 0.044553 0.000000
|
||||
0.045827 0.044414 0.000000
|
||||
-0.023588 0.036374 0.000000
|
||||
-0.062601 0.043869 0.000000
|
||||
0.046395 0.043574 0.000000
|
||||
-0.062855 0.043138 0.000000
|
||||
0.046852 0.042663 0.000000
|
||||
-0.063013 0.042367 0.000000
|
||||
0.047191 0.041689 0.000000
|
||||
-0.063067 0.041564 0.000000
|
||||
0.047401 0.040661 0.000000
|
||||
-0.063067 0.041331 0.000000
|
||||
-0.063067 0.040687 0.000000
|
||||
-0.063067 0.039714 0.000000
|
||||
0.047473 0.039590 0.000000
|
||||
-0.063067 0.038494 0.000000
|
||||
0.023786 0.023802 0.000000
|
||||
0.047473 -0.023562 0.000000
|
||||
-0.063067 0.037110 0.000000
|
||||
-0.063067 0.035643 0.000000
|
||||
-0.023588 0.026916 0.000000
|
||||
-0.063067 0.034177 0.000000
|
||||
-0.063067 0.032793 0.000000
|
||||
-0.063067 0.031573 0.000000
|
||||
-0.063067 0.030600 0.000000
|
||||
-0.063067 0.029956 0.000000
|
||||
-0.063067 0.029723 0.000000
|
||||
-0.063013 0.028920 0.000000
|
||||
-0.062855 0.028149 0.000000
|
||||
-0.062601 0.027419 0.000000
|
||||
-0.062258 0.026735 0.000000
|
||||
-0.047275 0.023802 0.000000
|
||||
-0.023588 0.016895 0.000000
|
||||
-0.061832 0.026105 0.000000
|
||||
-0.061332 0.025537 0.000000
|
||||
-0.060763 0.025036 0.000000
|
||||
-0.060133 0.024611 0.000000
|
||||
-0.059449 0.024268 0.000000
|
||||
-0.058719 0.024014 0.000000
|
||||
-0.057948 0.023856 0.000000
|
||||
-0.057145 0.023802 0.000000
|
||||
-0.056951 0.023802 0.000000
|
||||
-0.056414 0.023802 0.000000
|
||||
-0.055603 0.023802 0.000000
|
||||
-0.054586 0.023802 0.000000
|
||||
-0.053432 0.023802 0.000000
|
||||
-0.052210 0.023802 0.000000
|
||||
-0.050988 0.023802 0.000000
|
||||
-0.049834 0.023802 0.000000
|
||||
-0.048817 0.023802 0.000000
|
||||
-0.048006 0.023802 0.000000
|
||||
-0.047469 0.023802 0.000000
|
||||
-0.047275 -0.039350 0.000000
|
||||
0.023786 -0.057111 0.000000
|
||||
-0.023588 0.006875 0.000000
|
||||
-0.023588 -0.002584 0.000000
|
||||
-0.023588 -0.010919 0.000000
|
||||
-0.023588 -0.017568 0.000000
|
||||
-0.023588 -0.021970 0.000000
|
||||
-0.023588 -0.023562 0.000000
|
||||
0.015890 -0.023562 0.000000
|
||||
0.015890 -0.047244 0.000000
|
||||
0.057342 -0.023562 0.000000
|
||||
0.058146 -0.023616 0.000000
|
||||
0.058916 -0.023773 0.000000
|
||||
0.059647 -0.024027 0.000000
|
||||
0.060331 -0.024370 0.000000
|
||||
0.060960 -0.024795 0.000000
|
||||
0.061529 -0.025295 0.000000
|
||||
0.062030 -0.025864 0.000000
|
||||
0.062455 -0.026493 0.000000
|
||||
0.062798 -0.027177 0.000000
|
||||
0.063052 -0.027908 0.000000
|
||||
0.063210 -0.028679 0.000000
|
||||
0.063264 -0.029482 0.000000
|
||||
0.063264 -0.029715 0.000000
|
||||
0.063264 -0.030359 0.000000
|
||||
0.063264 -0.031332 0.000000
|
||||
0.063264 -0.032552 0.000000
|
||||
0.063264 -0.033936 0.000000
|
||||
0.063264 -0.035403 0.000000
|
||||
0.063264 -0.036869 0.000000
|
||||
0.063264 -0.038253 0.000000
|
||||
0.063264 -0.039473 0.000000
|
||||
-0.047203 -0.040421 0.000000
|
||||
0.063264 -0.040446 0.000000
|
||||
-0.046993 -0.041448 0.000000
|
||||
0.047473 -0.047244 0.000000
|
||||
0.063264 -0.041090 0.000000
|
||||
0.063264 -0.041323 0.000000
|
||||
0.063210 -0.042126 0.000000
|
||||
-0.046655 -0.042422 0.000000
|
||||
0.063052 -0.042897 0.000000
|
||||
-0.046197 -0.043334 0.000000
|
||||
0.062798 -0.043627 0.000000
|
||||
-0.045630 -0.044173 0.000000
|
||||
0.062455 -0.044311 0.000000
|
||||
-0.044962 -0.044931 0.000000
|
||||
0.062030 -0.044940 0.000000
|
||||
-0.044204 -0.045599 0.000000
|
||||
0.061529 -0.045509 0.000000
|
||||
0.060960 -0.046010 0.000000
|
||||
-0.043364 -0.046166 0.000000
|
||||
0.060331 -0.046435 0.000000
|
||||
-0.042453 -0.046623 0.000000
|
||||
0.059647 -0.046778 0.000000
|
||||
-0.041478 -0.046962 0.000000
|
||||
0.058916 -0.047032 0.000000
|
||||
-0.040451 -0.047172 0.000000
|
||||
0.058146 -0.047190 0.000000
|
||||
-0.039380 -0.047244 0.000000
|
||||
0.057342 -0.047244 0.000000
|
||||
-0.038292 -0.047244 0.000000
|
||||
-0.035286 -0.047244 0.000000
|
||||
-0.030744 -0.047244 0.000000
|
||||
-0.025050 -0.047244 0.000000
|
||||
-0.018590 -0.047244 0.000000
|
||||
-0.011745 -0.047244 0.000000
|
||||
-0.004900 -0.047244 0.000000
|
||||
0.001561 -0.047244 0.000000
|
||||
0.007254 -0.047244 0.000000
|
||||
0.011796 -0.047244 0.000000
|
||||
0.014803 -0.047244 0.000000
|
||||
0.047473 -0.047438 0.000000
|
||||
0.047473 -0.047975 0.000000
|
||||
0.047473 -0.048785 0.000000
|
||||
0.047473 -0.049802 0.000000
|
||||
0.047473 -0.050955 0.000000
|
||||
0.047473 -0.052177 0.000000
|
||||
0.047473 -0.053399 0.000000
|
||||
0.047473 -0.054553 0.000000
|
||||
0.047473 -0.055569 0.000000
|
||||
0.047473 -0.056380 0.000000
|
||||
0.047473 -0.056917 0.000000
|
||||
0.047473 -0.057111 0.000000
|
||||
0.023840 -0.057914 0.000000
|
||||
0.047419 -0.057914 0.000000
|
||||
0.023997 -0.058685 0.000000
|
||||
0.047261 -0.058685 0.000000
|
||||
0.024251 -0.059415 0.000000
|
||||
0.047007 -0.059415 0.000000
|
||||
0.024594 -0.060099 0.000000
|
||||
0.046664 -0.060099 0.000000
|
||||
0.025020 -0.060728 0.000000
|
||||
0.046238 -0.060728 0.000000
|
||||
0.025521 -0.061297 0.000000
|
||||
0.045738 -0.061297 0.000000
|
||||
0.026089 -0.061798 0.000000
|
||||
0.045169 -0.061798 0.000000
|
||||
0.026719 -0.062223 0.000000
|
||||
0.044539 -0.062223 0.000000
|
||||
0.027403 -0.062566 0.000000
|
||||
0.043855 -0.062566 0.000000
|
||||
0.028134 -0.062820 0.000000
|
||||
0.043125 -0.062820 0.000000
|
||||
0.028904 -0.062978 0.000000
|
||||
0.042354 -0.062978 0.000000
|
||||
0.029707 -0.063032 0.000000
|
||||
0.041551 -0.063032 0.000000
|
||||
0.029940 -0.063032 0.000000
|
||||
0.030585 -0.063032 0.000000
|
||||
0.031558 -0.063032 0.000000
|
||||
0.032778 -0.063032 0.000000
|
||||
0.034162 -0.063032 0.000000
|
||||
0.035629 -0.063032 0.000000
|
||||
0.037096 -0.063032 0.000000
|
||||
0.038480 -0.063032 0.000000
|
||||
0.039700 -0.063032 0.000000
|
||||
0.040674 -0.063032 0.000000
|
||||
0.041318 -0.063032 0.000000
|
||||
3 0 1 2
|
||||
3 0 3 1
|
||||
3 0 4 3
|
||||
3 0 5 4
|
||||
3 0 6 5
|
||||
3 0 7 6
|
||||
3 0 8 7
|
||||
3 0 9 8
|
||||
3 0 10 9
|
||||
3 0 11 10
|
||||
3 0 12 11
|
||||
3 0 13 12
|
||||
3 0 14 13
|
||||
3 15 14 0
|
||||
3 15 16 14
|
||||
3 17 16 15
|
||||
3 17 18 16
|
||||
3 19 18 17
|
||||
3 19 20 18
|
||||
3 21 20 19
|
||||
3 21 22 20
|
||||
3 23 22 21
|
||||
3 23 24 22
|
||||
3 25 24 23
|
||||
3 25 26 24
|
||||
3 27 26 25
|
||||
3 27 28 26
|
||||
3 29 28 27
|
||||
3 29 30 28
|
||||
3 31 30 29
|
||||
3 31 32 30
|
||||
3 33 32 31
|
||||
3 33 34 32
|
||||
3 35 34 33
|
||||
3 35 36 34
|
||||
3 37 36 35
|
||||
3 37 38 36
|
||||
3 39 38 37
|
||||
3 40 38 39
|
||||
3 41 38 40
|
||||
3 41 42 38
|
||||
3 43 42 41
|
||||
3 44 42 43
|
||||
3 45 42 44
|
||||
3 45 46 42
|
||||
3 47 46 45
|
||||
3 48 46 47
|
||||
3 49 46 48
|
||||
3 50 46 49
|
||||
3 51 46 50
|
||||
3 52 51 53
|
||||
3 52 46 51
|
||||
3 54 55 56
|
||||
3 54 57 55
|
||||
3 54 58 57
|
||||
3 54 59 58
|
||||
3 54 60 59
|
||||
3 54 61 60
|
||||
3 54 62 61
|
||||
3 54 63 62
|
||||
3 54 64 63
|
||||
3 54 65 64
|
||||
3 54 66 65
|
||||
3 54 67 66
|
||||
3 54 68 67
|
||||
3 69 46 52
|
||||
3 54 70 68
|
||||
3 71 46 69
|
||||
3 54 72 70
|
||||
3 73 46 71
|
||||
3 54 74 72
|
||||
3 75 46 73
|
||||
3 54 76 74
|
||||
3 77 46 75
|
||||
3 54 78 76
|
||||
3 79 46 77
|
||||
3 80 46 79
|
||||
3 54 81 78
|
||||
3 80 82 46
|
||||
3 83 82 80
|
||||
3 54 84 81
|
||||
3 85 82 83
|
||||
3 54 86 84
|
||||
3 87 82 85
|
||||
3 54 88 86
|
||||
3 89 82 87
|
||||
3 54 90 88
|
||||
3 91 82 89
|
||||
3 92 82 91
|
||||
3 93 82 92
|
||||
3 54 94 90
|
||||
3 95 82 93
|
||||
3 54 96 94
|
||||
3 96 97 94
|
||||
3 98 82 95
|
||||
3 99 82 98
|
||||
3 99 100 82
|
||||
3 101 100 99
|
||||
3 102 100 101
|
||||
3 103 100 102
|
||||
3 104 100 103
|
||||
3 105 100 104
|
||||
3 106 100 105
|
||||
3 107 100 106
|
||||
3 108 100 107
|
||||
3 109 100 108
|
||||
3 110 100 109
|
||||
3 110 111 100
|
||||
3 111 112 100
|
||||
3 113 111 110
|
||||
3 114 111 113
|
||||
3 115 111 114
|
||||
3 116 111 115
|
||||
3 117 111 116
|
||||
3 118 111 117
|
||||
3 119 111 118
|
||||
3 120 111 119
|
||||
3 121 111 120
|
||||
3 122 111 121
|
||||
3 123 111 122
|
||||
3 124 111 123
|
||||
3 125 111 124
|
||||
3 126 111 125
|
||||
3 127 111 126
|
||||
3 128 111 127
|
||||
3 129 111 128
|
||||
3 130 111 129
|
||||
3 131 111 130
|
||||
3 132 112 111
|
||||
3 133 97 96
|
||||
3 132 134 112
|
||||
3 132 135 134
|
||||
3 132 136 135
|
||||
3 132 137 136
|
||||
3 132 138 137
|
||||
3 132 139 138
|
||||
3 132 140 139
|
||||
3 132 141 140
|
||||
3 133 142 97
|
||||
3 133 143 142
|
||||
3 133 144 143
|
||||
3 133 145 144
|
||||
3 133 146 145
|
||||
3 133 147 146
|
||||
3 133 148 147
|
||||
3 133 149 148
|
||||
3 133 150 149
|
||||
3 133 151 150
|
||||
3 133 152 151
|
||||
3 133 153 152
|
||||
3 133 154 153
|
||||
3 133 155 154
|
||||
3 133 156 155
|
||||
3 133 157 156
|
||||
3 133 158 157
|
||||
3 133 159 158
|
||||
3 133 160 159
|
||||
3 133 161 160
|
||||
3 133 162 161
|
||||
3 133 163 162
|
||||
3 164 141 132
|
||||
3 133 165 163
|
||||
3 166 141 164
|
||||
3 133 167 165
|
||||
3 167 168 165
|
||||
3 167 169 168
|
||||
3 167 170 169
|
||||
3 171 141 166
|
||||
3 167 172 170
|
||||
3 173 141 171
|
||||
3 167 174 172
|
||||
3 175 141 173
|
||||
3 167 176 174
|
||||
3 177 141 175
|
||||
3 167 178 176
|
||||
3 179 141 177
|
||||
3 167 180 178
|
||||
3 167 181 180
|
||||
3 182 141 179
|
||||
3 167 183 181
|
||||
3 184 141 182
|
||||
3 167 185 183
|
||||
3 186 141 184
|
||||
3 167 187 185
|
||||
3 188 141 186
|
||||
3 167 189 187
|
||||
3 190 141 188
|
||||
3 167 191 189
|
||||
3 192 141 190
|
||||
3 193 141 192
|
||||
3 194 141 193
|
||||
3 195 141 194
|
||||
3 196 141 195
|
||||
3 197 141 196
|
||||
3 198 141 197
|
||||
3 199 141 198
|
||||
3 200 141 199
|
||||
3 201 141 200
|
||||
3 202 141 201
|
||||
3 133 203 167
|
||||
3 133 204 203
|
||||
3 133 205 204
|
||||
3 133 206 205
|
||||
3 133 207 206
|
||||
3 133 208 207
|
||||
3 133 209 208
|
||||
3 133 210 209
|
||||
3 133 211 210
|
||||
3 133 212 211
|
||||
3 133 213 212
|
||||
3 133 214 213
|
||||
3 215 214 133
|
||||
3 215 216 214
|
||||
3 217 216 215
|
||||
3 217 218 216
|
||||
3 219 218 217
|
||||
3 219 220 218
|
||||
3 221 220 219
|
||||
3 221 222 220
|
||||
3 223 222 221
|
||||
3 223 224 222
|
||||
3 225 224 223
|
||||
3 225 226 224
|
||||
3 227 226 225
|
||||
3 227 228 226
|
||||
3 229 228 227
|
||||
3 229 230 228
|
||||
3 231 230 229
|
||||
3 231 232 230
|
||||
3 233 232 231
|
||||
3 233 234 232
|
||||
3 235 234 233
|
||||
3 235 236 234
|
||||
3 237 236 235
|
||||
3 237 238 236
|
||||
3 239 238 237
|
||||
3 240 238 239
|
||||
3 241 238 240
|
||||
3 242 238 241
|
||||
3 243 238 242
|
||||
3 244 238 243
|
||||
3 245 238 244
|
||||
3 246 238 245
|
||||
3 247 238 246
|
||||
3 248 238 247
|
||||
3 249 238 248
|
||||
@@ -25,13 +25,14 @@ void main()
|
||||
vec4 textureColor = texture(iChannel0, texcoord.xy);
|
||||
vec3 RGB = textureColor.rgb * vertexColor.rgb * color.rgb;
|
||||
|
||||
// alpha is a mix of texture alpha, vertex alpha, and uniform alpha affected by stippling
|
||||
vec4 maskColor = texture(iChannel1, vertexUV);
|
||||
float maskIntensity = (maskColor.r + maskColor.g + maskColor.b) / 3.0;
|
||||
// read mask intensity as average of RGB
|
||||
float maskIntensity = dot(texture(iChannel1, vertexUV).rgb, vec3(1.0/3.0));
|
||||
|
||||
// alpha is a mix of texture alpha, vertex alpha, and uniform alpha affected by stippling
|
||||
float A = textureColor.a * vertexColor.a * color.a * maskIntensity;
|
||||
A += stipple * ( int(gl_FragCoord.x + gl_FragCoord.y) % 2 );
|
||||
|
||||
// output RGBA
|
||||
FragColor = vec4(RGB, clamp(A, 0.0, 1.0) );
|
||||
// FragColor = texture(iChannel1, vertexUV);
|
||||
}
|
||||
|
||||
@@ -25,8 +25,7 @@ void main()
|
||||
vec3 RGB = textureColor.rgb * vertexColor.rgb * color.rgb;
|
||||
|
||||
// alpha is a mix of texture alpha, vertex alpha, and uniform alpha affected by stippling
|
||||
vec4 maskColor = texture(iChannel1, vertexUV);
|
||||
float maskIntensity = (maskColor.r + maskColor.g + maskColor.b) / 3.0;
|
||||
float maskIntensity = dot(texture(iChannel1, vertexUV).rgb, vec3(1.0/3.0));
|
||||
|
||||
float A = textureColor.a * vertexColor.a * color.a * maskIntensity;
|
||||
A -= stipple * ( int(gl_FragCoord.x + gl_FragCoord.y) % 2 > 0 ? 0.05 : 0.95 );
|
||||
|
||||
@@ -12,8 +12,8 @@ uniform vec4 color; // drawing color
|
||||
uniform vec4 uv;
|
||||
|
||||
// Mask Shader
|
||||
uniform vec2 size;
|
||||
uniform float blur;
|
||||
uniform vec2 size; // size of the mask area
|
||||
uniform float blur; // percent of blur
|
||||
|
||||
float sdRoundBox( in vec2 p, in vec2 b, in float r )
|
||||
{
|
||||
@@ -29,7 +29,7 @@ void main()
|
||||
float d = sdRoundBox( uv, vec2(size.x * iResolution.x/iResolution.y, size.y), blur * 0.5 );
|
||||
|
||||
vec3 col = vec3(1.0 - sign(d));
|
||||
col *= 1.0 - exp( -60.0/ (blur * 100.f + 1.0) * abs(d));
|
||||
col *= 1.0 - exp( -600.0/ (blur * 1000.f + 1.0) * abs(d));
|
||||
|
||||
FragColor = vec4( col, 1.0 );
|
||||
}
|
||||
|
||||
100
rsc/shaders/mask_draw.fs
Normal file
100
rsc/shaders/mask_draw.fs
Normal file
@@ -0,0 +1,100 @@
|
||||
#version 330 core
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
in vec4 vertexColor;
|
||||
in vec2 vertexUV;
|
||||
|
||||
// from General Shader
|
||||
uniform vec3 iResolution; // viewport resolution (in pixels)
|
||||
uniform mat4 iTransform; // image transformation
|
||||
uniform vec4 color; // drawing color
|
||||
uniform vec4 uv;
|
||||
|
||||
// Mask Shader
|
||||
uniform sampler2D iChannel0; // base texture
|
||||
uniform vec2 size; // size of the mask area
|
||||
uniform float blur; // percent of blur
|
||||
|
||||
uniform vec4 cursor;
|
||||
uniform vec3 brush;
|
||||
uniform int option;
|
||||
|
||||
float sdBox( in vec2 p, in float b)
|
||||
{
|
||||
vec2 q = abs(p) - vec2(b);
|
||||
float d = min( max(q.x, q.y), 0.0) + length(max(q,0.0));
|
||||
return 1.0 - abs(d) * step(d, 0.0);
|
||||
}
|
||||
|
||||
float sdCircle( in vec2 p, in float b)
|
||||
{
|
||||
return ( length( p ) / b );
|
||||
}
|
||||
|
||||
const mat3 KERNEL = mat3( 0.0625, 0.125, 0.0625,
|
||||
0.125, 0.25, 0.125,
|
||||
0.0625, 0.125, 0.0625);
|
||||
|
||||
vec3 gaussian()
|
||||
{
|
||||
vec2 filter_step = 1.f / textureSize(iChannel0, 0);
|
||||
int i = 0, j = 0;
|
||||
vec3 sum = vec3(0.0);
|
||||
|
||||
for (i = 0; i<3; ++i)
|
||||
for (j = 0; j<3; ++j)
|
||||
sum += texture(iChannel0, vertexUV.xy + filter_step * vec2 (i-1, j-1) ).rgb * KERNEL[i][j];
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
// blur the image incrementally each step
|
||||
vec3 color = gaussian();
|
||||
// vec3 color = texture(iChannel0, vertexUV).rgb; // raw color
|
||||
|
||||
if ( option > 0 ) {
|
||||
// fragment coordinates
|
||||
vec2 uv = -1.0 + 2.0 * gl_FragCoord.xy / iResolution.xy;
|
||||
// adjust coordinates to match scaling area
|
||||
uv.x *= cursor.z ;
|
||||
uv.y *= cursor.w ;
|
||||
// cursor coordinates
|
||||
vec2 cursor = vec2(cursor.x, - cursor.y);
|
||||
// use distance function relative to length brush.x (size), depending on brush.z (shape):
|
||||
// - brush.z = 0 : circle shape
|
||||
// - brush.z = 1 : square shape
|
||||
float d = (1.0 -brush.z) * sdCircle(cursor-uv, brush.x) + brush.z * sdBox(uv-cursor, brush.x);
|
||||
|
||||
// modify only the pixels inside the brush
|
||||
if( d < 1.0 )
|
||||
{
|
||||
// mask intensity
|
||||
float c = dot(color, vec3(1.0/3.0));
|
||||
|
||||
// depending on option:
|
||||
// - option 1 : paint (add color)
|
||||
// - option 2 : erase (substract color)
|
||||
float p = c + (option > 1 ? d - 1.0 : 1.0 - d );
|
||||
|
||||
// new intensity is a mix betwen current intensity and painted intensity
|
||||
c = (1.0 - brush.y) * c + (brush.y) * p;
|
||||
|
||||
// distribute value in RGB (will be averaged in image.fs)
|
||||
// NB : this encodes the mask intensity over 3*8 bits
|
||||
c *= 3.0;
|
||||
color.r = clamp(c, 0.0, 1.0);
|
||||
color.g = step(1.0, c) * (clamp(c, 1.0, 2.0) - 1.0);
|
||||
color.b = step(2.0, c) * (clamp(c, 2.0, 3.0) - 2.0);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
FragColor = vec4( clamp(color, 0.0, 1.0), 1.0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -12,8 +12,8 @@ uniform vec4 color; // drawing color
|
||||
uniform vec4 uv;
|
||||
|
||||
// Mask Shader
|
||||
uniform vec2 size;
|
||||
uniform float blur;
|
||||
uniform vec2 size; // size of the mask area
|
||||
uniform float blur; // percent of blur
|
||||
|
||||
// See: http://www.iquilezles.org/www/articles/ellipsoids/ellipsoids.htm
|
||||
float sdEllipsoid( in vec2 p, in vec2 r )
|
||||
@@ -57,7 +57,7 @@ void main()
|
||||
float d = sdEllipse( uv, vec2(size.x * iResolution.x/iResolution.y, size.y) );
|
||||
|
||||
vec3 col = vec3(1.0- sign(d));
|
||||
col *= 1.0 - exp( -60.0/ (blur * 100.f + 1.0) * abs(d));
|
||||
col *= 1.0 - exp( -600.0/ (blur * 1000.f + 1.0) * abs(d));
|
||||
|
||||
FragColor = vec4( col, 1.0 );
|
||||
}
|
||||
|
||||
32
rsc/shaders/mask_horizontal.fs
Normal file
32
rsc/shaders/mask_horizontal.fs
Normal file
@@ -0,0 +1,32 @@
|
||||
#version 330 core
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
in vec4 vertexColor;
|
||||
in vec2 vertexUV;
|
||||
|
||||
// from General Shader
|
||||
uniform vec3 iResolution; // viewport resolution (in pixels)
|
||||
uniform mat4 iTransform; // image transformation
|
||||
uniform vec4 color; // drawing color
|
||||
uniform vec4 uv;
|
||||
|
||||
// Mask Shader
|
||||
uniform vec2 size; // size of the mask area
|
||||
uniform float blur; // percent of blur
|
||||
|
||||
float sdHorizontal( in vec2 p, in float y )
|
||||
{
|
||||
float d = step(0.0, y);
|
||||
d = d * smoothstep(0.0, 2.0 * blur, y + p.y) + (1.0-d)*smoothstep(-2.0 * blur, 0.0, (-2.0 * blur) - (y + p.y));
|
||||
return d;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 uv = -1.0 + 2.0 * gl_FragCoord.xy / iResolution.xy;
|
||||
|
||||
float d = sdHorizontal( uv, size.y);
|
||||
|
||||
FragColor = vec4( vec3(d), 1.0 );
|
||||
}
|
||||
@@ -12,8 +12,8 @@ uniform vec4 color; // drawing color
|
||||
uniform vec4 uv;
|
||||
|
||||
// Mask Shader
|
||||
uniform vec2 size;
|
||||
uniform float blur;
|
||||
uniform vec2 size; // size of the mask area
|
||||
uniform float blur; // percent of blur
|
||||
|
||||
float sdRoundSide( in vec2 p, in vec2 b, in float r )
|
||||
{
|
||||
@@ -21,16 +21,47 @@ float sdRoundSide( in vec2 p, in vec2 b, in float r )
|
||||
return min(max(q.x,q.y),0.0) + length(max(q,0.0)) - r;
|
||||
}
|
||||
|
||||
float sdHorizontal( in vec2 p, in float y )
|
||||
{
|
||||
float d = 0.0;
|
||||
|
||||
// if (y < 0.0) {
|
||||
|
||||
// d = smoothstep(-2.0 * blur, 0.0, (-2.0 * blur) - (y + p.y));
|
||||
//// d = smoothstep(-2.0 * blur, 0.0, -y -blur -p.y); // centered blur
|
||||
|
||||
|
||||
// }
|
||||
// else {
|
||||
|
||||
// d = smoothstep(0.0, 2.0 * blur, y + p.y);
|
||||
|
||||
//// d = smoothstep(0.0, 2.0 * blur, y +blur +p.y); // centered blur
|
||||
|
||||
// }
|
||||
d = step(0.0, y);
|
||||
d = d * smoothstep(0.0, 2.0 * blur, y + p.y) + (1.0-d)*smoothstep(-2.0 * blur, 0.0, (-2.0 * blur) - (y + p.y));
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 uv = -1.0 + 2.0 * gl_FragCoord.xy / iResolution.xy;
|
||||
uv.x *= iResolution.x / iResolution.y;
|
||||
|
||||
float d = sdRoundSide( uv, vec2(size.x * iResolution.x/iResolution.y, size.y), blur );
|
||||
float d = sdHorizontal( uv, size.y);
|
||||
|
||||
vec3 col = vec3(1.0 - sign(d));
|
||||
float delta = 0.5 * length(min(size,1.0));
|
||||
col *= 1.0 - exp( -30.0/ (blur * 100.0 * delta + 1.0) * abs(d));
|
||||
vec3 col = vec3(d);
|
||||
|
||||
|
||||
// col = vec3(sign(d));
|
||||
// col *= 1.0 - exp( -600.0/ (blur * 1000.0 + 1.0) * abs(d));
|
||||
|
||||
// float d = sdRoundSide( uv, vec2(size.x * iResolution.x/iResolution.y, size.y), blur );
|
||||
// vec3 col = vec3(1.0 - sign(d));
|
||||
// float delta = 0.5 * length(min(size,1.0));
|
||||
// col *= 1.0 - exp( -300.0/ (blur * 1000.0 * delta + 1.0) * abs(d));
|
||||
|
||||
FragColor = vec4( col, 1.0 );
|
||||
}
|
||||
|
||||
@@ -12,9 +12,8 @@ uniform vec4 color; // drawing color
|
||||
uniform vec4 uv;
|
||||
|
||||
// Mask Shader
|
||||
uniform vec2 size;
|
||||
uniform float blur;
|
||||
uniform float invert;
|
||||
uniform vec2 size; // size of the mask area
|
||||
uniform float blur; // percent of blur
|
||||
|
||||
float udSegment( in vec2 p, in vec2 a, in vec2 b )
|
||||
{
|
||||
@@ -49,7 +48,7 @@ void main()
|
||||
float d = udSegment( uv, v1, v2 )- th;
|
||||
|
||||
vec3 col = vec3(1.0- sign(d));
|
||||
col *= 1.0 - exp( -60.0/ (blur * 100.0 + 1.0) * abs(d));
|
||||
col *= 1.0 - exp( -600.0/ (blur * 1000.0 + 1.0) * abs(d));
|
||||
|
||||
FragColor = vec4( col, 1.0 );
|
||||
}
|
||||
|
||||
@@ -12,9 +12,8 @@ uniform vec4 color; // drawing color
|
||||
uniform vec4 uv;
|
||||
|
||||
// Mask Shader
|
||||
uniform vec2 size;
|
||||
uniform float blur;
|
||||
|
||||
uniform vec2 size; // size of the mask area
|
||||
uniform float blur; // percent of blur
|
||||
|
||||
float sdRoundSide( in vec2 p, in vec2 b, in float r )
|
||||
{
|
||||
@@ -31,8 +30,8 @@ void main()
|
||||
float d = sdRoundSide( uv, vec2(s.x * iResolution.x/iResolution.y, s.y), blur );
|
||||
|
||||
vec3 col = vec3(1.0 - sign(d));
|
||||
float delta = 0.5 * length(min(size,1.0));
|
||||
col *= 1.0 - exp( -20.0/ (blur * 100.0 * delta + 1.0) * abs(d) );
|
||||
float delta = 0.5 * length(min(size, 1.0));
|
||||
col *= 1.0 - exp( -200.0/ (blur * 1000.0 * delta + 1.0) * abs(d) );
|
||||
|
||||
FragColor = vec4( col, 1.0 );
|
||||
}
|
||||
|
||||
32
rsc/shaders/mask_vertical.fs
Normal file
32
rsc/shaders/mask_vertical.fs
Normal file
@@ -0,0 +1,32 @@
|
||||
#version 330 core
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
in vec4 vertexColor;
|
||||
in vec2 vertexUV;
|
||||
|
||||
// from General Shader
|
||||
uniform vec3 iResolution; // viewport resolution (in pixels)
|
||||
uniform mat4 iTransform; // image transformation
|
||||
uniform vec4 color; // drawing color
|
||||
uniform vec4 uv;
|
||||
|
||||
// Mask Shader
|
||||
uniform vec2 size; // size of the mask area
|
||||
uniform float blur; // percent of blur
|
||||
|
||||
float sdVertical( in vec2 p, in float x )
|
||||
{
|
||||
float d = step(0.0, x);
|
||||
d = d * smoothstep(0.0, 2.0 * blur, x + p.x) + (1.0-d)*smoothstep(-2.0 * blur, 0.0, (-2.0 * blur) - (x + p.x));
|
||||
return d;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 uv = -1.0 + 2.0 * gl_FragCoord.xy / iResolution.xy;
|
||||
|
||||
float d = sdVertical( uv, -size.x);
|
||||
|
||||
FragColor = vec4( vec3(d), 1.0 );
|
||||
}
|
||||
Reference in New Issue
Block a user