SFML 2.X GLSL - Shader wody resetuje się co 512px

SFML 2.X GLSL - Shader wody resetuje się co 512px

Wątek przeniesiony 2024-10-24 19:08 z Inne języki programowania przez flowCRANE.

tBane
Tester Beta
  • Rejestracja:ponad rok
  • Ostatnio:około 10 godzin
  • Lokalizacja:Poznań
  • Postów:288
0

Witam. Znalazłem pewien Shader, który planuję użyć w swoim programie.
link
Problem polega na tym, że shader resetuje się co 512 px w pionie jak i poziomie.
Dlaczego tak się dzieje ?

RPG2D 143.png

Kod w SFML 2.X GLSL:

Kopiuj
uniform vec2 resolution;
uniform float time;

float random(float x) {
 
    return fract(sin(x) * 10000.);
          
}

float noise(vec2 p) {

    return random(p.x + p.y * 10000.);
            
}

vec2 sw(vec2 p) { return vec2(floor(p.x), floor(p.y)); }
vec2 se(vec2 p) { return vec2(ceil(p.x), floor(p.y)); }
vec2 nw(vec2 p) { return vec2(floor(p.x), ceil(p.y)); }
vec2 ne(vec2 p) { return vec2(ceil(p.x), ceil(p.y)); }

float smoothNoise(vec2 p) {

    vec2 interp = smoothstep(0., 1., fract(p));
    float s = mix(noise(sw(p)), noise(se(p)), interp.x);
    float n = mix(noise(nw(p)), noise(ne(p)), interp.x);
    return mix(s, n, interp.y);
        
}

float fractalNoise(vec2 p) {

    float x = 0.;
    x += smoothNoise(p      );
    x += smoothNoise(p * 2. ) / 2.;
    x += smoothNoise(p * 4. ) / 4.;
    x += smoothNoise(p * 8. ) / 8.;
    x += smoothNoise(p * 16.) / 16.;
    x /= 1. + 1./2. + 1./4. + 1./8. + 1./16.;
    return x;
            
}

float movingNoise(vec2 p) {
 
    float x = fractalNoise(p + time);
    float y = fractalNoise(p - time);
    return fractalNoise(p + vec2(x, y));   
    
}

float nestedNoise(vec2 p) {
    
    float x = movingNoise(p);
    float y = movingNoise(p + 100.);
    return movingNoise(p + vec2(x, y));
    
}
void main()
{
    vec2 uv = gl_TexCoord[0].xy / resolution.xy;
    float n = nestedNoise(uv * 25600.);
    gl_FragColor = vec4(mix(vec3(.4, .6, 1.), vec3(.1, .2, 1.), n), 1.);
}

W wolnych chwilach od codzienności programuję hobbystycznie Edytor gier RPG 2D.
Technologie, z których korzystam to C++ oraz SFML 2.X.
edytowany 6x, ostatnio: tBane
Spine
Fajnie jakbyś jeszcze jakiś screenshot dodał.
tBane
@Spine: ok. Już dodałem.
Spine
  • Rejestracja:prawie 22 lata
  • Ostatnio:około godziny
  • Postów:6628
2

Woda jest jednokolorowa i shader nakłada na nią szum, prawda?
Każdy sprite wody to duży prostokąt, tak?

Tak na szybko, wydaje m się, że stosujesz shader na każdym prostokącie w jego lokalnej przestrzeni.

Gdyby shader korzystał z przestrzeni globalnej, to by generował szum bezszwowo, o ile jest w ten sposób napisany.


🕹️⌨️🖥️🖱️🎮
tBane
Tester Beta
  • Rejestracja:ponad rok
  • Ostatnio:około 10 godzin
  • Lokalizacja:Poznań
  • Postów:288
1

@Spine eksperymentowałem z teksturami o różnym rozmiarze i zawsze jest taki sam efekt. Czyli to gdzieś po stronie shadera jest problem. A ja go niestety nie rozumiem, dlatego na forum się odezwałem.

No ale w Map Edytorze tego nie widać xD
screenshot-20241024151913.png


W wolnych chwilach od codzienności programuję hobbystycznie Edytor gier RPG 2D.
Technologie, z których korzystam to C++ oraz SFML 2.X.
edytowany 2x, ostatnio: tBane
Spine
  • Rejestracja:prawie 22 lata
  • Ostatnio:około godziny
  • Postów:6628
0
tBane napisał(a):

No ale w Map Edytorze tego nie widać xD

Ale chyba wiesz dlaczego :) ?
Szwy są zakrywane liniami.
Nie ma różnicy między 0x0 i 2x0, 0x1 i 2x1, itd...


🕹️⌨️🖥️🖱️🎮
DD
  • Rejestracja:5 miesięcy
  • Ostatnio:około 2 miesiące
  • Postów:18
0

Lepiej finalizuj to i przejdz do kolejnego kroku, bo przed toba jeszcze 1000 takich problemow. Lepiej nie zawieszaj sie na tym, lepiej wroc do tego typu problemow jak juz gra bedzie gotowa i potraktuj to jako szlifowanie efektu. Kazdy ci to powie

Spine
  • Rejestracja:prawie 22 lata
  • Ostatnio:około godziny
  • Postów:6628
0

@Donsacz Donośny: Masz rację, ale nie do końca.

Może przy którymś problemie przejrzy na oczy, zobaczy z jaką prymitywną technologią ma do czynienia i przejdzie na coś współczesnego, co lepiej wspiera tworzenie gier, pracę nad shaderami itd...

Im szybciej, tym lepiej. Przesiadka z łopaty na koparkę naprawdę przyspieszy pracę.


🕹️⌨️🖥️🖱️🎮
edytowany 3x, ostatnio: Spine
DD
99xmarcin
  • Rejestracja:prawie 5 lat
  • Ostatnio:4 miesiące
  • Postów:2420
0

A ta twoja textura to jakie ma wymiary?


Holy sh*t, with every month serenityos.org gets better & better...
tBane
Tester Beta
  • Rejestracja:ponad rok
  • Ostatnio:około 10 godzin
  • Lokalizacja:Poznań
  • Postów:288
0

@99xmarcin 256x256


W wolnych chwilach od codzienności programuję hobbystycznie Edytor gier RPG 2D.
Technologie, z których korzystam to C++ oraz SFML 2.X.
99xmarcin
  • Rejestracja:prawie 5 lat
  • Ostatnio:4 miesiące
  • Postów:2420
0

Szukał bym bug'a w linijce:

Kopiuj
vec2 uv = gl_TexCoord[0].xy / resolution.xy;

być może resolution źle ustawiasz i się "zawija"


Holy sh*t, with every month serenityos.org gets better & better...
Spine
  • Rejestracja:prawie 22 lata
  • Ostatnio:około godziny
  • Postów:6628
0

@99xmarcin: A ta linijka nie konwertuje po prostu uv z pikselowych wymiarów na zakres (0.0, 1.0)?

i potem float n = nestedNoise(uv * 25600.); mnoży jednostkowe uv przez 25600, bo np. viewport SFML jest ustawiony na bardzo duże liczby i w ten sposób zagęszczane są piksele szumu.

@tBane: Spróbuj rozwinąć linijkę vec2 uv = gl_TexCoord[0].xy / resolution.xy; w

Kopiuj
vec2 uv = abs((gl_TexCoord[0].xy / resolution.xy) + vec2(-0.5, -0.5));

Powinno to zmienić pattern w bardziej powtarzalny, ale za to będzie tileable.


🕹️⌨️🖥️🖱️🎮
edytowany 2x, ostatnio: Spine
99xmarcin
Tak ale w zależności od tego jakie coords textury są na obiekcie to textura może się zawijać więc będzie 0 - 1.0 - 0.0 - 1.0 - 0.0 - 0.3
tBane
Wtedy psuje się shader. Staje się jednolitym kolorem.
Spine
  • Rejestracja:prawie 22 lata
  • Ostatnio:około godziny
  • Postów:6628
0

@tBane: Przerobiłem Twój shader, żeby działał w shadertoy.

1. Wklej ten kod zamiast shadera ze strony https://www.shadertoy.com/view/XdXBRH :

Kopiuj
float random(float x) {
 
    return fract(sin(x) * 10000.);
          
}

float noise(vec2 p) {

    return random(p.x + p.y * 10000.);
            
}

vec2 sw(vec2 p) { return vec2(floor(p.x), floor(p.y)); }
vec2 se(vec2 p) { return vec2(ceil(p.x), floor(p.y)); }
vec2 nw(vec2 p) { return vec2(floor(p.x), ceil(p.y)); }
vec2 ne(vec2 p) { return vec2(ceil(p.x), ceil(p.y)); }

float smoothNoise(vec2 p) {

    vec2 interp = smoothstep(0., 1., fract(p));
    float s = mix(noise(sw(p)), noise(se(p)), interp.x);
    float n = mix(noise(nw(p)), noise(ne(p)), interp.x);
    return mix(s, n, interp.y);
        
}

float fractalNoise(vec2 p) {

    float x = 0.;
    x += smoothNoise(p      );
    x += smoothNoise(p * 2. ) / 2.;
    x += smoothNoise(p * 4. ) / 4.;
    x += smoothNoise(p * 8. ) / 8.;
    x += smoothNoise(p * 16.) / 16.;
    x /= 1. + 1./2. + 1./4. + 1./8. + 1./16.;
    return x;
            
}

float movingNoise(vec2 p) {
 
    float x = fractalNoise(p + iTime);
    float y = fractalNoise(p - iTime);
    return fractalNoise(p + vec2(x, y));   
    
}

float nestedNoise(vec2 p) {
    
    float x = movingNoise(p);
    float y = movingNoise(p + 100.);
    return movingNoise(p + vec2(x, y));
    
}

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    //vec2 uv = fragCoord / iResolution.xy;
    vec2 uv = abs((fragCoord / iResolution.xy) + vec2(-0.5, -0.5));
    float n = nestedNoise(uv * 25.61);
    fragColor = vec4(mix(vec3(.4, .6, 1.), vec3(.1, .2, 1.), n), 1.);
}

2. I daj play (lewy dolny róg pola tekstowego):

screenshot-20241024182955.png

3. Działa...

screenshot-20241024184241.png


🕹️⌨️🖥️🖱️🎮
edytowany 1x, ostatnio: Spine
Zobacz pozostałe 3 komentarze
tBane
nie wiadomo co było źle
obscurity
aha, no na tym playgroundzie jest tylko jeden tile tak? W każdym razie efekt tragiczny, wygląda jak fraktal albo obraz z kalejdoskopu. @tBane: może poszukaj po prostu innego shadera wody, ten i tak jest kiepski
Spine
Ten shader i tak nie pasuje do reszty grafiki ;)
tBane
Ale lepszego nie znalazłem :-/
Spine
Nowy shader najlepiej gdyby operował na world position. TexCoordy w ogóle można by pominąć. https://stackoverflow.com/questions/4899555/glsl-how-to-get-pixel-x-y-z-world-position
tBane
Tester Beta
  • Rejestracja:ponad rok
  • Ostatnio:około 10 godzin
  • Lokalizacja:Poznań
  • Postów:288
0

@Spine ale po konwersji na SFML GLSL już nie działa:

screenshot-20241024190654.png

Kopiuj
uniform vec2 resolution;
uniform float time;

float random(float x) {
 
    return fract(sin(x) * 10000.);
          
}

float noise(vec2 p) {

    return random(p.x + p.y * 10000.);
            
}

vec2 sw(vec2 p) { return vec2(floor(p.x), floor(p.y)); }
vec2 se(vec2 p) { return vec2(ceil(p.x), floor(p.y)); }
vec2 nw(vec2 p) { return vec2(floor(p.x), ceil(p.y)); }
vec2 ne(vec2 p) { return vec2(ceil(p.x), ceil(p.y)); }

float smoothNoise(vec2 p) {

    vec2 interp = smoothstep(0., 1., fract(p));
    float s = mix(noise(sw(p)), noise(se(p)), interp.x);
    float n = mix(noise(nw(p)), noise(ne(p)), interp.x);
    return mix(s, n, interp.y);
        
}

float fractalNoise(vec2 p) {

    float x = 0.;
    x += smoothNoise(p      );
    x += smoothNoise(p * 2. ) / 2.;
    x += smoothNoise(p * 4. ) / 4.;
    x += smoothNoise(p * 8. ) / 8.;
    x += smoothNoise(p * 16.) / 16.;

    x /= 1. + 1./2. + 1./4. + 1./8. + 1./16.;
    return x;
            
}

float movingNoise(vec2 p) {
 
    float x = fractalNoise(p + time);
    float y = fractalNoise(p - time);
    return fractalNoise(p + vec2(x, y));   
    
}

float nestedNoise(vec2 p) {
    
    float x = movingNoise(p);
    float y = movingNoise(p + 100.);
    return movingNoise(p + vec2(x, y));
    
}
void main()
{
    //vec2 uv = gl_TexCoord[0].xy / resolution.xy;
    vec2 uv = abs((gl_TexCoord[0].xy / resolution.xy) + vec2(-0.5, -0.5));
    float n = nestedNoise(uv * 25.61);
    gl_FragColor = vec4(mix(vec3(.4, .6, 1.), vec3(.1, .2, 1.), n), 1.);
}

Poza tym vec2 uv = abs((fragCoord / iResolution.xy) + vec2(-0.5, -0.5)); zmieniłbym na vec2 uv = abs((fragCoord / iResolution.xy);, bo wtedy nie ma lustrzanego poziomego odbicia


W wolnych chwilach od codzienności programuję hobbystycznie Edytor gier RPG 2D.
Technologie, z których korzystam to C++ oraz SFML 2.X.
edytowany 3x, ostatnio: tBane
Spine
  • Rejestracja:prawie 22 lata
  • Ostatnio:około godziny
  • Postów:6628
0
tBane napisał(a):

Poza tym vec2 uv = abs((fragCoord / iResolution.xy) + vec2(-0.5, -0.5)); zmieniłbym na vec2 uv = abs((fragCoord / iResolution.xy);, bo wtedy nie ma lustrzanego poziomego odbicia

Jak usuniesz + vec2(-0.5, -0.5), to abs() jest zbędny.

To pewnie niewiele zmieni, ale mnożnika uv nie zwiększyłeś. W shadertoy zmniejszyłem go, bo szum miał zbyt duże zagęszczenie.


🕹️⌨️🖥️🖱️🎮
edytowany 2x, ostatnio: Spine
LukeJL
  • Rejestracja:około 11 lat
  • Ostatnio:minuta
  • Postów:8403
0
tBane napisał(a):

@Spine eksperymentowałem z teksturami o różnym rozmiarze i zawsze jest taki sam efekt. Czyli to gdzieś po stronie shadera jest problem.

Nie czytałem całego wątku, ale jak tekstury się powtarzają, to może ustawić wrapping mode na MIRRORED_REPEAT?
Nazewnictwa tutaj używam WebGL (które może być inne w tym API, z którego korzystasz), ale chodzi mi o to, co się ma dziać, jak pobierzesz wartość piksela spoza tekstury. Teraz widzę, że się powtarza:
Chodzi mi o coś takiego:
https://webglfundamentals.org/webgl/webgl-3d-textures-repeat-clamp.html

Taka pierwsza myśl, jednak ty tam robisz coś więcej niż tylko ustawiasz teksturę, więc możliwe, że problem jest w głębi shadera.
Chociaż w sumie taki efekt można by uzyskać również ręcznie.


edytowany 2x, ostatnio: LukeJL
Spine
  • Rejestracja:prawie 22 lata
  • Ostatnio:około godziny
  • Postów:6628
0
LukeJL napisał(a):

Nie czytałem całego wątku, ale jak tekstury się powtarzają, to może ustawić wrapping mode na MIRRORED_REPEAT?

Wątpię aby to było cokolwiek innego niż CLAMP...
W końcu ma edytor, w którym można dodać wodę, więc każda woda to jest pojedynczy kafelek, czyli tutaj żaden REPEAT nie jest potrzebny, ani nie będzie wykorzystywany.


🕹️⌨️🖥️🖱️🎮
edytowany 2x, ostatnio: Spine
tBane
Tester Beta
  • Rejestracja:ponad rok
  • Ostatnio:około 10 godzin
  • Lokalizacja:Poznań
  • Postów:288
1

No więc problem polegał na tym, że odnosiłem się do współrzędnych tekstury a nie do współrzędnych globalnych. (Prawdopodobnie domyślnie tekstura ma rozmiary 512x512). Rozwiązaniem jest stworzenie vertex shadera, dzięki któremu można otrzymać informację o współrzędnych pixela.

screenshot-20241025110353.png

Kopiuj
// vertex.frag

varying vec2 worldPos;

void main()
{
	gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
	gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
	worldPos = gl_ModelViewMatrix * gl_Vertex;
	gl_FrontColor = gl_Color;
}
Kopiuj
// water2.frag

uniform vec2 resolution;
uniform float time;
varying vec2 worldPos;

float random(float x) {
 
    return fract(sin(x) * 10000.);
          
}

float noise(vec2 p) {

    return random(p.x + p.y * 10000.);
            
}

vec2 sw(vec2 p) { return vec2(floor(p.x), floor(p.y)); }
vec2 se(vec2 p) { return vec2(ceil(p.x), floor(p.y)); }
vec2 nw(vec2 p) { return vec2(floor(p.x), ceil(p.y)); }
vec2 ne(vec2 p) { return vec2(ceil(p.x), ceil(p.y)); }

float smoothNoise(vec2 p) {

    vec2 interp = smoothstep(0., 1., fract(p));
    float s = mix(noise(sw(p)), noise(se(p)), interp.x);
    float n = mix(noise(nw(p)), noise(ne(p)), interp.x);
    return mix(s, n, interp.y);
        
}

float fractalNoise(vec2 p) {

    float x = 0.;
    x += smoothNoise(p      );
    x += smoothNoise(p * 2. ) / 2.;
    x += smoothNoise(p * 4. ) / 4.;
    x += smoothNoise(p * 8. ) / 8.;
    x += smoothNoise(p * 16.) / 16.;

    x /= 1. + 1./2. + 1./4. + 1./8. + 1./16.;
    return x;
            
}

float movingNoise(vec2 p) {
 
    float x = fractalNoise(p + time);
    float y = fractalNoise(p - time);
    return fractalNoise(p + vec2(x, y));   
    
}

float nestedNoise(vec2 p) {
    
    float x = movingNoise(p);
    float y = movingNoise(p + 100.);
    return movingNoise(p + vec2(x, y));
    
}
void main()
{
    vec2 uv = worldPos.xy * 0.05;
    float n = nestedNoise(uv);
    gl_FragColor = vec4(mix(vec3(.4, .6, 1.), vec3(.1, .2, 1.), n), 1.);
}

W wolnych chwilach od codzienności programuję hobbystycznie Edytor gier RPG 2D.
Technologie, z których korzystam to C++ oraz SFML 2.X.
edytowany 1x, ostatnio: tBane
Spine
  • Rejestracja:prawie 22 lata
  • Ostatnio:około godziny
  • Postów:6628
2
tBane napisał(a):

No więc problem polegał na tym, że odnosiłem się do współrzędnych tekstury a nie do współrzędnych globalnych.

Właśnie to napisałem w pierwszej odpowiedzi => SFML 2.X GLSL - Shader wody resetuje się co 512px

Tak na szybko, wydaje m się, że stosujesz shader na każdym prostokącie w jego lokalnej przestrzeni.

Gdyby shader korzystał z przestrzeni globalnej, to by generował szum bezszwowo, o ile jest w ten sposób napisany.


🕹️⌨️🖥️🖱️🎮
edytowany 1x, ostatnio: Spine
tBane
Tester Beta
  • Rejestracja:ponad rok
  • Ostatnio:około 10 godzin
  • Lokalizacja:Poznań
  • Postów:288
2

@Spine po prostu nie zrozumiałem :-)


W wolnych chwilach od codzienności programuję hobbystycznie Edytor gier RPG 2D.
Technologie, z których korzystam to C++ oraz SFML 2.X.
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)