Beveled edges

0

Spróbujcie w Delphi wstawić na formę przycisk (któż tego nie robił!) - ma on efekt 3D, co nie? Chodzi o to że wygląda tak jakby miał grubość - tak jakby światło padało na niego z lewego górnego rogu.

Mój problem to napisanie algorytmu, który stosowałby ten efekt (zwany "beveled edges" z angielska) do bitmapy o dowolnym kształcie. Czyli żeby robił trójwymiarową elipsę, bądź kółko, bądź romb, bądź dowolny wielobok (o to głównie chodzi).

Wiem, że to zagadnienie to raczej wyższe studium graficzne; myślałem nawet nad zrobieniem bardzo prostego engine'a 3D który renderowałby graniastosłupy o dowolnym kształcie podstawy i o zadanym oświetleniu. Niestety zadanie mnie przerosło.

Ten efekt jest powszechnie stosowany, np. w Photoshopie i w wielu prostszych programach graficznych. Może źródła tego algorytmu są gdzieś dostępne? Czy ktoś wie coś na ten temat? Szukałem wszędzie i nic nie znalazłem.

Jeśli chcesz ZOBACZYĆ o co mi chodzi to wejdź na:

<url>jacekvool.w.interia.pl/bevel.jpg</url>
zielone koło, które posiada grubość, prawda ? :)

Jak widać zadanie sprowadza się do rozjaśniania i przyciemniania odpowiednich fragmentów obrazka.

Czy ktoś ma jakiś pomysł? HELP!

0

Na torry.net jest biblioteka Fastlib ,może to ci się przyda.

0

szukaj: Bump Mapping (banał).

0

Można też pokusić się o wykorzystanie tajemniej rzeczy zwanej emboss. Czyli filtr konwolucyjny np. z taką maską:

-1 -1   0
-1   0   1
&nbsp;0   1   1
0

Marooned:
próbowałem emboss - niestety do niczego, nie o to mi chodziło; emboss powoduje wyraźne zaznaczenie się konturów - fajny efekty ale w moim przypadku nie wiele daje (eksperymentowałem z nim głębiej i nijak nie da się go przystosować do moich potrzeb)

km:
dzięki, fastlib przydał mi się do zgłębienia "emboss-u"

AndRew:
bump mapping jest najbliższy moich oczekiwań. Jednak nie znam tej techniki kompletnie. Może ktoś siedzi w tym cały BUMP-ie i byłby mi w stanie pomóc z moim wielkim problemem ...?

Czekam na dalszą pomoc i wciąż nad tym pracuję!

0

Wlacz photoshopa, psp lub to co lubisz, wykonaj przycisk normalny i ten sam ale wcisniety i sobie podmieniaj w Image :-P

0

Nie o to mi zupełnie chodzi, Passage.

Zobaczcie jeszcze dokładniej o co mi chodzi:

<url>jacekvool.w.interia.pl/my.htm</url>

0

Bump Map: (solidny, światło z północnego zachodu)

0  1  1  0  0
1  1  0  0  0
1  0  <b>1</b>  0-1
0  0  0-1-1
0  0-1-1  0

i ewentualnie Gaussian Blur:

0  1  1  1  0
1  2  3  2  1
1  3  <b>4</b>  3  1
1  2  3  2  1
0  1  1  1  0

Dzielnik dla powyższych = 1.

Moja procedura aplikująca dany efekt z "matryca" na "płótnie" w "obszarze":
gdzie TMatryca to:

   
   TMatryca = record    // matryca 5x5 punktów oraz dzielnik
     waga     : array[0..4] of array[0..4] of shortint;
     dzielnik : shortint;
    end;
procedure naMatrycy(obszar : TRect; matryca: TMatryca; plotno : TCanvas);
type
   TKolor = record    
     R, G, B : byte;
    end;
   TBufor = record
     kolor  : array of array of TKolor;
    end;

var x, y, mx, my, width, height, l, t : integer;
    R, G, B                           : real;
    bitmap                            : TBitmap;  // bufor 1
    bufor                             : TBufor;
    linia                             : PByteArray;

begin
    if matryca.dzielnik <> 0 then
    try

      width  := abs(obszar.Right  - obszar.Left);
      height := abs(obszar.Bottom - obszar.Top);
      setLength(bufor.kolor, width, height);

      bitmap := TBitmap.Create;                 // na tym pracujemy
      bitmap.Width  := width;
      bitmap.Height := height;
      bitmap.Canvas.CopyRect(rect(0,0,bitmap.width,bitmap.height),plotno,obszar);  // załaduj bufor
      bitmap.PixelFormat:=pf24Bit;


      for y := 0 to height - 1 do
      begin
        linia := bitmap.ScanLine[y];
        x := 0;
        repeat
           bufor.kolor[x,y].B := linia[x*3];
           bufor.kolor[x,y].G := linia[x*3+1];
           bufor.kolor[x,y].R := linia[x*3+2];
           inc(x);
        until x > (width-1);
      end;

      t := obszar.Top;
      l := obszar.Left;

      for x := 2 to width-3 do begin
          for y := 2 to height-3 do begin

            R := 0;
            G := 0;
            B := 0;

            for mx := 0 to 4 do
             for my := 0 to 4 do begin
              R := R + bufor.kolor[x + l - my + 2, y + t - mx + 2].R * matryca.waga[mx, my] / matryca.dzielnik;
              G := G + bufor.kolor[x + l - my + 2, y + t - mx + 2].G * matryca.waga[mx, my] / matryca.dzielnik;
              B := B + bufor.kolor[x + l - my + 2, y + t - mx + 2].B * matryca.waga[mx, my] / matryca.dzielnik;
             end;

             if r > 255 then r := 255;  // + ogranicz wartości (0..255)
             if r <  0 then r := 0;     //
             if g > 255 then g := 255;  //
             if g <  0 then g := 0;     //
             if b > 255 then b := 255;  //
             if b <  0 then b := 0;     // -

             SetPixel(bitmap.canvas.Handle, x, y, rgb(round(R), round(G), round(B)));
         end;
      end;
0

Dobra Andrew, ale co właściwie twój kod robi? Próbowałem go użyć i efekty są raczej dalekie od zamierzonych. Może coś źle robię ...?

1 użytkowników online, w tym zalogowanych: 0, gości: 1