Optische täuschung oder falsche berechnung? (kubischer.. gradient?)

heyo.

also. ich habe ein quadrat, und will es gradient-mäßig füllen, also die farbe soll von innen nach außen
interpoliert werden.
dazu habe ich im shader folgende zeile stehen:

finalColor = vec4(color, max(abs(pos.x), abs(fragmentPosition.y)));

idee: jenachdem ob x oder y größer ist, wird alpha zu dem wert der quadrat-„schale“ des punktes.
also im prinzip wie bei einem zirculärem gradienten, nur dass man da den satz des pythagoras benutzt.

das ergebnis:

  1. ich bin zu blöd den fehler zu entdecken?
  2. das ist eine optische täuschung
  3. da braucht meinen einen anderen ansatz?..

reingezoomt sieht es so aus:

also umsetzung von dem was ich wollte funktioniert ja, die schalen sind alle gleichfarbig und werden je nach innen / außen
dunkler / heller…

also, wie bekomme ich das weg, dass man dieses „X“ sieht?

danke euch :slight_smile:

[quote=mymaksimus]also, wie bekomme ich das weg, dass man dieses “X” sieht?[/quote]Keine Chanche, dass ist wirklich eine optische Täuschung: das Gehirn will die Ecken den Korridors sehen…

bye
TT

warum nicht zumindest noch etwas versuchen, abgerundete Ecken vielleicht,
oder zu Ecken hin leicht heller werden

okya, danke…
jemand ne idee, wie man so ne abrundung im shader umsetzen könnte? (mir will das gerade nicht gelingen…
außerdem bekomme ich es auf keinen fall ohne if abfragen hin…)

Mit (x²+y²)^(1/2) bekommst du Kreise (um den Ursprung, muss bei dir also noch verschoben werden). Wenn du für die Formel höhere gerade Potenzen nimmst, z.B. (x^4+y^4)^(1/4), werden die Ringe immer “eckiger”

[spoiler]

(linke Seite mit 4, rechte mit 5 als Potenz)

Oder zum selbst-mit-herumspielen: x’^‘4’+‘y’^‘4’='1 - Wolfram|Alpha
[/spoiler]

Dabei ist ein Viereck/Quadrat keine natürlich Form, btw…

Aber es stimmt, betrachtet man nur einen dünnen Innenrahmen, ist die Farbe an den Ecken gleich.

Ob optische Täuschung oder nicht (kann schon sein), aber das Bild hat einige viele Farbfragmente die sich insbesondere an den Ecken manifestieren.
Das ist kein linearer Gradient, oder liegt es viel eher an dem Bildformat dass dort Informationen verloren gingen?

Ich hab natürlich nix mit Wahrnehmungspsychologie zu tun, aber spitze Ecken sind Formen, die das Gehirn “weiterführen” möchte… Deswegen entsteht der visuelloptische Eindruck einer Linie (an den Diagonalen).

ich habe ein wenig versucht, mit Swing-Zeichnen,
links in etwa wie vorgegeben in Grau, in der Mitte runde Ecken ohne viel Fortschritt,
rechts mit etwas Aufhellung zu den Ecken hin, bisher nur für die Kante oben links (+ unten rechts),

immerhin einige Abschwächung des Effekts, finde ich,
vielleicht mit manch Parameteränderung noch besser zu machen,
wobei auch Gefahr dass es zu hell wird so dass unnatürliche helle Linie im Bild

Code dazu, der nun wirklich nicht zu empfehlen ist, nur bei starken Interesse an Weiterarbeit

lieber nicht öffnen, Leser haften für ihre Augen
[spoiler]```public class Test2
{
static int height = 400;

public static void main(String[] args)
{
    JFrame f = new JFrame();
    f.add(new TestPanel());
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    f.setSize(height * 4, height + 100);
    f.setVisible(true);
}

}

class TestPanel
extends JPanel
{

@Override
protected void paintComponent(Graphics g)
{
    super.paintComponent(g);

    // Anzahl Stufen
    int n = 30;

    int k = 200 / n;
    int max = Test2.height;
    int p = max / n;
    int p2 = max / 2 / n;

    Color[] allC = new Color[255];
    for (int i = 0; i < 255; i++)
        allC** = new Color(i, i, i);

    // Stufen-Farben
    Color[] cc = new Color[n];
    int ccc = 230;
    for (int i = 0; i + 10 < n; i++)
    {
        cc** = new Color(ccc, ccc, ccc);
        ccc -= k;
    }
    for (int i = n - 10; i < n; i++)
        cc** = cc[n - 11];

    // linkes Quadrat
    int min = 0;
    int w = max;
    for (int i = 0; i + 10 < n; i++)
    {
        g.setColor(cc**);
        g.fillRect(min, min + 40, w, w);

        min += p2;
        w -= p;
    }

    // mittleres Quadrat
    min = 0;
    w = max;
    int shiftX = (int)(max * 1.1);
    int d2 = max / n;
    int r = max / 2 / n;
    int d = d2 * 2;
    for (int i = 0; i + 10 < n; i++)
    {
        g.setColor(cc**);
        int x = min + shiftX;
        int y = min + 40;
        // zwei Rechtecke, Ecken für Viertelkreise frei gelassen
        g.fillRect(x + r, y - p2, w - d2, w + p);
        g.fillRect(x - p2, y + r, w + p, w - d2);

        // 4 Viertelkreise
        int xArc = x - p2;
        int yArc = y - p2;
        int wArc = w - d2;
        g.fillArc(xArc, yArc, d, d, 90, 90);
        g.fillArc(xArc + wArc - 1, yArc, d, d, 90, -90);
        g.fillArc(xArc + wArc - 1, yArc + wArc - 1, d, d, 270, 90);
        g.fillArc(xArc, yArc + wArc - 1, d, d, 270, -90);

        min += p2;
        w -= p;
    }

    // drittes Quadrat
    min = 0;
    w = max;
    shiftX = (int)(max * 2.222);
    int intv = 1 + (max / 2 / n);

    // Breite des Bereichts in der Ecke der aufgehellt wird, variable
    int gr = 30;
    int tGr = gr * gr;
    for (int i = 0; i < max; i++)
    {
        for (int j = 0; j < max; j++)
        {
            int x = i + shiftX;
            int y = j + 40;

            // Grund-Stufe bestimmen
            int km = Math.min(i, j);
            km = Math.min(km, max - i);
            km = Math.min(km, max - j);
            int index = km / intv;
            Color c = cc[index];

            // falls i und j nahe beieinander, dann aufhellen,
            // nur eine der Diagonalen im Moment
            int ab = Math.abs(i - j);
            if (ab < gr && index > 0)
            {
                int maxC = cc[index - 1].getBlue();
                int minC = cc[index].getBlue();
                if (minC != maxC)
                {
                    // quadrieren, sehr nahe an Diagonale stärker aufhellen
                    int ab2 = 100 * ((gr - ab) * (gr - ab)) / tGr;
                    int nc = minC + ab2 * (maxC - minC) / 100;
                    c = allC[nc];
                }
            }

            g.setColor(c);
            g.drawLine(x, y, x, y);
        }
    }

}

}```[/spoiler]

und trotzdem sieht man die X’e, slater… ^^ auch wenn eettwas schwächer

So sieht es bei mir aus mit meiner Formel für den Exponenten 4

Und wenn man noch ein bisschen runtergeht auf 3 (dann mit abs)

Ich war zu faul, ordentlichen Code zu schreiben (habe direkt auf ein JPanel gemalt, was natürlich absolut ineffizient ist)

[spoiler]

    private static JPanel getPanel() {
        return new JPanel(){
            @Override
            protected void paintComponent(Graphics g) {
                Graphics2D g2 = (Graphics2D) g;
                for(int i = 0; i < getWidth(); i++) {
                    for (int j = 0; j < getHeight(); j++) {
                        double x = (i - getWidth()/2.0)/getWidth();
                        double y = (j - getHeight()/2.0)/getHeight();
                        double c = pow(pow(abs(x), POWER) + pow(abs(y), POWER), 1.0 / POWER);
                        g2.setColor(new Color((float)c, (float)(1-c), 0));
                        g2.fillRect(i, j, 1, 1);
                    }
                }
            }
        };
    }

[/spoiler]

Da finde ich das mit dem „x“ spannender. :smiley: