首页  编辑  

黑色浮雕化图形和光照效果

Tags: /超级猛料/Picture.图形图像编程/图片处理/   Date Created:

黑色浮雕化图形和光照效果

produce a simple bumpmapping

Autor: Sven Lorenz  

Homepage: http://www.Sven-of-Nine.de

unit Unit1;

interface

uses

 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

 Dialogs, ExtCtrls;

type

 TForm1 = class(TForm)

   Timer1: TTimer;

   Image1: TImage;

   procedure FormCreate(Sender: TObject);

   procedure FormClose(Sender: TObject; var Action: TCloseAction);

   procedure Timer1Timer(Sender: TObject);

 private

   { Private declarations }

 public

   { Public declarations }

 end;

var

 Form1: TForm1;

implementation

uses Unit2;

{$R *.dfm}

var

 XPos: Single = 0.1;

 YPos: Single = 0.3;

procedure TForm1.FormCreate(Sender: TObject);

begin

 Image1.Picture.LoadFromFile('C:\windows\acd wallpaper.bmp');

 //Init bumpmapping and set color to cyan (2*r,3*g,+4*b)

 Bump_Init(Image1.Picture.Bitmap, 2,3,4);

end;

// ----- animate bumpmapping -----

procedure TForm1.Timer1Timer(Sender: TObject);

begin

 //Timer1.Interval:=40;

 Image1.Stretch:=TRUE;

 //Position des Lichtpunktes ?ndern

 XPos := XPos + 0.02;

 YPos := YPos + 0.01;

 //Auf 2Pi begrenzen

 if (XPos > 2 * PI) then XPos := XPos - 2 * PI;

 if (YPos > 2 * PI) then YPos := YPos - 2 * PI;

 //Und ausgeben

 with Image1.Picture do

   Bump_Do(Bitmap,

     trunc(Sin(XPos) * (Bitmap.Width shr 1) + (Bitmap.Width shr 1)),

     trunc(Sin(YPos) * (Bitmap.Height shr 1) + (Bitmap.Height shr 1))

     )

end;

// ----- Close -----

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);

begin

 Bump_Flush();

end;

end.

---------------------------------------

unit Unit_Bumpmapping;

interface

uses Windows, Graphics;

// ----- Bumpmapping procedures -----

procedure Bump_Init(SourceBitMap: TBitmap; r: Single = 3; g: Single = 3.6;

 b: Single = 4);

procedure Bump_Flush();

procedure Bump_Do(Target: TBitmap; XLight, YLight: Integer);

procedure Bump_SetSource(SourceBitMap: TBitmap);

procedure Bump_SetColor(r, g, b: Single);

implementation

// ----- ein paar n ützliche Types definieren -----

type

 PBitmap = ^TBitmap;

 //Kleines Arry zum schnelleren Zugriff auf Bitmaps

 TLine = array[0..MaxInt div SizeOf(TRGBQUAD) - 1] of TRGBQUAD;

 PLine = ^TLine;

 // ----- Einige interne Variablen -----

var

 ColorArray: array of TRGBQuad;                //Array für die Farbtabelle beim Bumpmapping

 SourceArray: array of Byte;                    //Quell Muster

 TargetBMP: TBitmap;                          //ZielBitmap

 Black: TRGBQuad;                         //Schwart

 White: TRGBQuad;                         //Weiß

 // ----- Die Quelle für das Bumpmapping erzeugen            -----

 // ----- aus einem Bitmap wird ein Schwarzweißarray erzeugt -----

procedure Bump_SetSource(SourceBitMap: TBitmap);

var

 iX, iY: Integer;

 z: Integer;

 sLine: PLine;

 iDot: Integer;

begin

 //QuellArray erzeugen

 SourceBitmap.PixelFormat := pf32Bit;

 SetLength(SourceArray, SourceBitMap.Height * SourceBitMap.Width);

 for iY := 0 to SourceBitMap.Height - 1 do

 begin

   //Scanline holen

   sLine := SourceBitMap.ScanLine[iY];

   //Und durchwursten

   for iX := 0 to SourceBitMap.Width - 1 do

   begin

     //Koordinaten errechnene

     z := iY * SourceBitMap.Width + iX;

     //Grauwert bestimmen

     idot := sLine[iX].rgbRed;

     idot := idot + sLine[iX].rgbGreen;

     idot := idot + sLine[iX].rgbBlue;

     iDot := (iDot div 3);

     //Und eintragen

     SourceArray[z] := iDot;

   end;

 end;

end;

// ----- Farbtabelle erzeugen -----

procedure Bump_SetColor(r, g, b: Single);

var

 iIndex: Integer;

 c: Byte;

begin

 if (r > 4) then r := 4;

 if (r < 0) then r := 0;

 if (g > 4) then g := 4;

 if (g < 0) then g := 0;

 if (b > 4) then b := 4;

 if (b < 0) then b := 0;

 //Länge setzen

 SetLength(ColorArray, 255);

 //Und erstmalschwarz machen

 FillMemory(ColorArray, 255 * SizeOf(TRGBQuad), 0);

 //Schoener Blauverlauf

 for iIndex := 0 to 127 do

 begin

   c := 63 - iIndex div 2;

   //Hier kann die Farber eingestellt werden 0.0-4.0

   ColorArray[iIndex].rgbRed   := round(c * r);

   ColorArray[iIndex].rgbGreen := round(c * g);

   ColorArray[iIndex].rgbBlue  := round(c * b);

 end;

 //Schwarz und Weiß definieren

 Black.rgbRed   := 0;

 Black.rgbBlue  := 0;

 Black.rgbGreen := 0;

 White.rgbRed   := 255;

 White.rgbBlue  := 255;

 White.rgbGreen := 255;

end;

// ----- Eigentliches Bumpmapping ausführen -----

procedure Bump_Do(Target: TBitmap; XLight, YLight: Integer);

var

 iX, iY: Integer;

 sLine: PLine;

 iR1, iT1: Integer;

 iR, iT: Integer;

 z: Integer;

begin

 //Alle Zeile (bis auf oben und unten)

 for iY := 1 to TargetBMP.Height - 2 do

 begin

   //Scanline holen

   sLine := TargetBMP.ScanLine[iY];

   //Startposition im Quell-Array

   z := iY * TargetBMP.Width;

   //Vorberechnung zur Beleuchtung

   iT1 := (iY - YLight);

   //Und alle Pixel durchwursten

   for iX := 1 to TargetBMP.Width - 2 do

   begin

     //Position im Array aktualisieren

     Inc(z);

     //Steigung in unserem Punkt bestimmen

     iT := iT1 - (SourceArray[z + TargetBMP.Width] -

       SourceArray[z - TargetBMP.Width]);

     iR := (iX - XLight) - (SourceArray[z + 1] - SourceArray[z - 1]);

     //Absolut machen

     if (iR < 0) then iR := -iR;

     if (iT < 0) then iT := -iT;

     //Wie sieht die Steigung aus ?

     iR1 := iR + iT;

     if (iR1 < 129) then

     begin

       //Hohe steigung, Farbe holen

       sLine[iX] := ColorArray[iR1];

     end

     else

     begin

       //Ansonsten schwarz

       sLine[iX] := Black;

     end;

   end;

 end;

 //Ergebnis übergeben

 Target.Assign(TargetBMP);

end;

// ----- Bumpmapping initialisieren -----

procedure Bump_Init(SourceBitMap: TBitmap; r: Single = 3; g: Single = 3.6;

 b: Single = 4);

begin

 //Zielbitmap erzeugen

 TargetBMP := TBitmap.Create;

 with TargetBMP do

 begin

   Height      := SourceBitMap.Height;

   Width       := SourceBitMap.Width;

   PixelFormat := pf32Bit;

 end;

 //Farbtabellen initialisieren

 Bump_SetColor(r, g, b);

 //Und aus dem Quellbitmap ein Array machen

 Bump_SetSource(SourceBitmap);

end;

// ----- Bumpmapping beenden -----

procedure Bump_Flush();

begin

 //Speicher freimachen

 TargetBMP.Free;

 SetLength(ColorArray, 0);

end;

end.