tBane Temat założony przez niniejszego użytkownika |
RGB i HSV - operacje na palecie kolorów » 2025-11-10 18:46:26 Witam. Posiadam kod na generowanie palety kolorów, który zamieszczam poniżej. Moje pytanie brzmi jak wyznaczyć funkcję odwrotną do RGB->HUE w taki sposób, by zwrócić koordynaty danego piksela. chodzi o to że jak podamy wartość np. 255, 0, 0 to zwróci nam 0,0.  Czy da się to obliczyć czy lepiej zastosować spradzenie dla każdego piksela ? kod:std::string palette_colors_shader_source = R"(
uniform sampler2D texture; // SFML podstawi teksturę sprite'a
uniform vec4 texRectUV; // (u0, v0, u1, v1) – NORMALIZOWANE granice wycinka
// --- HSV -> RGB (oficjalne) ---
vec3 hsv2rgb(in vec3 c) {
vec3 rgb = clamp(abs(mod(c.x*6.0 + vec3(0.0,4.0,2.0), 6.0) - 3.0) - 1.0, 0.0, 1.0);
return c.z * mix(vec3(1.0), rgb, c.y);
}
// --- HSV -> RGB (wygładzone) ---
vec3 hsv2rgb_smooth(in vec3 c) {
vec3 rgb = clamp(abs(mod(c.x*6.0 + vec3(0.0,4.0,2.0), 6.0) - 3.0) - 1.0, 0.0, 1.0);
rgb = rgb * rgb * (3.0 - 2.0 * rgb);
return c.z * mix(vec3(1.0), rgb, c.y);
}
void main() {
vec2 uvAtlas = gl_TexCoord[0].xy;
vec2 uv = (uvAtlas - texRectUV.xy) / (texRectUV.zw - texRectUV.xy);
float hue = fract(uv.x);
vec3 hsv = vec3(hue, 1.2 - uv.y, 1.3);
vec3 hsvRgb = hsv2rgb_smooth(hsv);
gl_FragColor = vec4(hsvRgb, 1.0);
}
)";
#include "Dialogs/Palette.hpp" #include "Filters.hpp" #include "Time.hpp" #include "Window.hpp" #include "Cursor.hpp" #include "Tools/Toolbar.hpp" #include "SFML/Graphics.hpp" #include "Theme.hpp"
PaletteValues::PaletteValues( sf::Vector2i position, sf::Vector2i size, std::string shader, sf::Color color ) { _shader = sf::Shader(); _shader.loadFromMemory( shader, sf::Shader::Type::Fragment ); _rect = sf::IntRect( position, size ); loadTexture( color ); _state = PaletteState::None; }
PaletteValues::~PaletteValues() { }
void PaletteValues::loadTexture( sf::Color color ) { sf::Image img; img.resize( sf::Vector2u( _rect.size ), color ); sf::Texture tex; tex.loadFromImage( img ); sf::IntRect r = sf::IntRect( sf::Vector2i( 0, 0 ), sf::Vector2i( tex.getSize().x, tex.getSize().y ) ); sf::Vector2u ts = tex.getSize(); sf::Glsl::Vec4 texRectUV( float( r.position.x ) / ts.x, float( r.position.y ) / ts.y, float( r.position.x + r.size.x ) / ts.x, float( r.position.y + r.size.y ) / ts.y ); _shader.setUniform( "texRectUV", texRectUV ); _renderTexture.resize( tex.getSize() ); sf::Sprite spr( tex ); _renderTexture.clear( sf::Color::White ); _renderTexture.draw( spr, & _shader ); _renderTexture.display(); }
void PaletteValues::setPosition( sf::Vector2i position ) { _rect.position = position; }
void PaletteValues::cursorHover() { if( _rect.contains( cursor->_worldMousePosition ) ) { ElementGUI_hovered = this->shared_from_this(); } }
void PaletteValues::handleEvent( const sf::Event & event ) { if( const auto * mbr = event.getIf < sf::Event::MouseButtonReleased >(); mbr && mbr->button == sf::Mouse::Button::Left ) { _state = PaletteState::None; ElementGUI_pressed = nullptr; } if( _rect.contains( cursor->_worldMousePosition ) ) { if( const auto * mbp = event.getIf < sf::Event::MouseButtonPressed >(); mbp && mbp->button == sf::Mouse::Button::Left ) { _state = PaletteState::Selecting; ElementGUI_pressed = this->shared_from_this(); } if( const auto * mbp = event.getIf < sf::Event::MouseMoved >(); mbp && sf::Mouse::isButtonPressed( sf::Mouse::Button::Left ) ) { _state = PaletteState::Selecting; ElementGUI_pressed = this->shared_from_this(); } } }
void PaletteValues::update() { if( _state == PaletteState::Selecting ) { _state = PaletteState::Selecting; sf::Image pixels = _renderTexture.getTexture().copyToImage(); sf::Vector2i pixelPos; pixelPos.x = std::clamp( cursor->_worldMousePosition.x - _rect.position.x, 0, _rect.size.x - 1 ); pixelPos.y = std::clamp( cursor->_worldMousePosition.y - _rect.position.y, 0, _rect.size.y - 1 ); sf::Color color = pixels.getPixel( sf::Vector2u( pixelPos ) ); toolbar->_selectedColorButton->setColor( color ); } }
void PaletteValues::draw() { sf::Sprite sprite( _renderTexture.getTexture() ); sprite.setPosition( sf::Vector2f( _rect.position ) ); window->draw( sprite ); }
Palette::Palette() : Dialog( L"Palette", sf::Vector2i( 192 + 24 + 8, dialog_title_rect_height + 192 + basic_text_rect_height + 8 ) ) { sf::Vector2i size = sf::Vector2i( sf::Vector2u( sf::Vector2i( 192 - 16, 192 - 16 ) ) ); sf::Vector2i position = getContentPosition() + sf::Vector2i( 8, 8 ); _hues = std::make_shared < PaletteValues >( position, size, palette_colors_shader_source, sf::Color::White ); position = sf::Vector2i( _hues->_rect.position + sf::Vector2i( _hues->_rect.size.x + 8, 0 ) ); size.x = 24; _values = std::make_shared < PaletteValues >( position, size, palette_values_shader_source, sf::Color::White ); _r = std::make_unique < sf::Text >( basicFont, L"R", basic_text_size ); _g = std::make_unique < sf::Text >( basicFont, L"G", basic_text_size ); _b = std::make_unique < sf::Text >( basicFont, L"B", basic_text_size ); _r->setFillColor( basic_text_color ); _g->setFillColor( basic_text_color ); _b->setFillColor( basic_text_color ); _red = std::make_shared < TextInput >( sf::Vector2i( 32, basic_text_rect_height ), 3, basic_text_size ); _green = std::make_shared < TextInput >( sf::Vector2i( 32, basic_text_rect_height ), 3, basic_text_size ); _blue = std::make_shared < TextInput >( sf::Vector2i( 32, basic_text_rect_height ), 3, basic_text_size ); setPosition( _position ); }
Palette::~Palette() { }
void Palette::setPosition( sf::Vector2i position ) { Dialog::setPosition( position ); _hues->setPosition( getContentPosition() + sf::Vector2i( 8, 8 ) ); _values->setPosition( sf::Vector2i( _hues->_rect.position + sf::Vector2i( _hues->_rect.size.x + 8, 0 ) ) ); sf::Vector2i textInputsPosistion; textInputsPosistion.x = position.x + 32; textInputsPosistion.y = _values->_rect.position.y + _values->_rect.size.y + 8; _red->setPosition( textInputsPosistion ); _green->setPosition( textInputsPosistion + sf::Vector2i( 32 * 2, 0 ) ); _blue->setPosition( textInputsPosistion + sf::Vector2i( 32 * 4, 0 ) ); _r->setPosition( sf::Vector2f( _red->getPosition() ) - sf::Vector2f( 16, 0 ) ); _g->setPosition( sf::Vector2f( _green->getPosition() ) - sf::Vector2f( 16, 0 ) ); _b->setPosition( sf::Vector2f( _blue->getPosition() ) - sf::Vector2f( 16, 0 ) ); }
void Palette::cursorHover() { Dialog::cursorHover(); _hues->cursorHover(); _values->cursorHover(); _red->cursorHover(); _green->cursorHover(); _blue->cursorHover(); }
void Palette::handleEvent( const sf::Event & event ) { Dialog::handleEvent( event ); _hues->handleEvent( event ); _values->handleEvent( event ); _red->handleEvent( event ); _green->handleEvent( event ); _blue->handleEvent( event ); }
void Palette::update() { Dialog::update(); _hues->update(); if( _hues->_state == PaletteState::Selecting ) { _values->loadTexture( toolbar->_selectedColorButton->_color ); } _values->update(); _red->update(); _green->update(); _blue->update(); }
void Palette::draw() { Dialog::draw(); _hues->draw(); _values->draw(); _red->draw(); _green->draw(); _blue->draw(); window->draw( * _r ); window->draw( * _g ); window->draw( * _b ); }
std::shared_ptr < Palette > palette;
|
|
pekfos |
» 2025-11-10 18:56:52 |
|
tBane Temat założony przez niniejszego użytkownika |
» 2025-11-10 20:08:05 Ok. dzięki, zobacze może się przyda :-) Bo ChatGPT jakoś zaczął działać, a szczerze mówiąc jestem na etapie na którym nie rozumiem już kodu ... |
|
tBane Temat założony przez niniejszego użytkownika |
» 2025-11-10 21:00:59 struct HSV { float h, s, v; }; HSV rgbToHsv( sf::Color c ) { float r = c.r / 255.f, g = c.g / 255.f, b = c.b / 255.f; float mx = std::max( { r, g, b } ), mn = std::min( { r, g, b } ); float d = mx - mn; float h = 0.f; if( d > 0.f ) { if( mx == r ) h = fmodf(( g - b ) / d, 6.f ); else if( mx == g ) h =( b - r ) / d + 2.f; else h =( r - g ) / d + 4.f; h /= 6.f; if( h < 0.f ) h += 1.f; } float s =( mx == 0.f ) ? 0.f :( d / mx ); float v = mx; return { h, s, v }; }
sf::Vector2i cursorOnHues( const sf::IntRect & rectHues, sf::Color rgb ) { HSV hsv = rgbToHsv( rgb ); float x = std::clamp( hsv.h, 0.f, 1.f ); float y = std::clamp( 1.0f - hsv.s, 0.f, 1.f ); return sf::Vector2i( rectHues.position.x + x * rectHues.size.x, rectHues.position.y + y * rectHues.size.y ); }
|
|
tBane Temat założony przez niniejszego użytkownika |
» 2025-11-10 21:27:24 Ten shader nie generuje poprawnie palety kolorów. Nie działają wartości skrajne takie jak: 255,0,0 255,255,255 0,0,0 Jak myślicie poprawić to czy zostawić tak jak jest? std::string palette_colors_shader_source = R"(
uniform sampler2D texture; // SFML podstawi teksturę sprite'a
uniform vec4 texRectUV; // (u0, v0, u1, v1) – NORMALIZOWANE granice wycinka
// --- HSV -> RGB (oficjalne) ---
vec3 hsv2rgb(in vec3 c) {
vec3 rgb = clamp(abs(mod(c.x*6.0 + vec3(0.0,4.0,2.0), 6.0) - 3.0) - 1.0, 0.0, 1.0);
return c.z * mix(vec3(1.0), rgb, c.y);
}
// --- HSV -> RGB (wygładzone) ---
vec3 hsv2rgb_smooth(in vec3 c) {
vec3 rgb = clamp(abs(mod(c.x*6.0 + vec3(0.0,4.0,2.0), 6.0) - 3.0) - 1.0, 0.0, 1.0);
rgb = rgb * rgb * (3.0 - 2.0 * rgb);
return c.z * mix(vec3(1.0), rgb, c.y);
}
void main() {
vec2 uvAtlas = gl_TexCoord[0].xy;
vec2 uv = (uvAtlas - texRectUV.xy) / (texRectUV.zw - texRectUV.xy);
float hue = fract(uv.x);
vec3 hsv = vec3(hue, 1.0 - uv.y, 1.0);
vec3 hsvRgb = hsv2rgb_smooth(hsv);
gl_FragColor = vec4(hsvRgb, 1.0);
}
)"; |
|
skovv |
» 2025-11-10 21:29:42 A nie łatwiej Ci zamiast shadera to wygenerować sobie samemu palete na texturze? A jak chcesz wtedy znaleźć pozycje danego koloru to szukasz na texturze i od razu masz pozycje |
|
tBane Temat założony przez niniejszego użytkownika |
» 2025-11-10 22:26:52 No właśnie generuje teksturę ale z użyciem shadera. A obliczanie koloru jest po to, bo nie każdy kolor jest na palecie. Paleta nie przechowuje wszystkich kolorów tylko te które widać, dlatego stosuje obliczanie. |
|
pekfos |
» 2025-11-11 12:14:57 Co znaczy że nie działają te wartości? Nie wyświetlają się piksele w tych kolorach? No właśnie generuje teksturę ale z użyciem shadera. A obliczanie koloru jest po to, bo nie każdy kolor jest na palecie. Paleta nie przechowuje wszystkich kolorów tylko te które widać, dlatego stosuje obliczanie. Przekaż brakującą współrzędną HSV jako uniform do shadera, wtedy paleta będzie miała wszystkie kolory. Widzę po screenie że masz już picker dla wartości V. |
|
| « 1 » 2 3 |