如何实现文字的3D效果?(200分)

  • 主题发起人 主题发起人 孔枫
  • 开始时间 开始时间
下面是Demo的源代码:至于具体窗体设计,你可以参照Demo样式。

Setup.pas (这是setup设置窗口的代码,即主窗体)

unit Setup;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;

type
TfrmSetup = class(TForm)
cmbRes: TComboBox;
Resolution: TLabel;
cbFullscreen: TCheckBox;
btnOK: TButton;
btnCancel: TButton;
rb16: TRadioButton;
rb32: TRadioButton;
procedure btnCancelClick(Sender: TObject);
procedure btnOKClick(Sender: TObject);
procedure cbFullscreenClick(Sender: TObject);
procedure cmbResChange(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure rb16Click(Sender: TObject);
procedure rb32Click(Sender: TObject);
private
{ Private declarations }
public
windowWidth : Integer;
windowHeight : Integer;
windowColorDepth : Integer;
fullscreen : Boolean;
closeProgram : Boolean;
end;

var
frmSetup: TfrmSetup;

implementation

{$R *.DFM}

procedure TfrmSetup.btnCancelClick(Sender: TObject);
begin
closeProgram := True;
Close;
end;

procedure TfrmSetup.btnOKClick(Sender: TObject);
begin
Close;
end;

procedure TfrmSetup.cbFullscreenClick(Sender: TObject);
begin
fullscreen := not fullscreen;
cmbRes.Enabled := fullscreen;
rb16.Enabled := fullscreen;
rb32.Enabled := fullscreen;
end;

procedure TfrmSetup.cmbResChange(Sender: TObject);
begin
case cmbRes.ItemIndex of
0 : // 640x480
begin
windowWidth := 640;
windowHeight := 480;
end;
1 : // 800x600
begin
windowWidth := 800;
windowHeight := 600;
end;
2 : //1024x768
begin
windowWidth := 1024;
windowHeight := 768;
end;
3 : // 1152x864
begin
windowWidth := 1152;
windowHeight := 864;
end;
4 : // 1280x960
begin
windowWidth := 1280;
windowHeight := 960;
end;
5 : // 1280x1024
begin
windowWidth := 1280;
windowHeight := 1024;
end;
end;
end;

procedure TfrmSetup.FormCreate(Sender: TObject);
begin
cmbRes.ItemIndex := 0;
windowWidth := 640;
windowHeight := 480;
windowColorDepth := 16;
fullscreen := False;
closeProgram := False;
end;

procedure TfrmSetup.rb16Click(Sender: TObject);
begin
windowColorDepth := 16;
end;

procedure TfrmSetup.rb32Click(Sender: TObject);
begin
windowColorDepth := 32;
end;

end.
 
运用下面的代码,稍稍扩展改进一下,就可以做出更多美妙的3D图象!
GlBMP.pas (这是BMP文件转换为3D效果的核心算法的代码)

unit glBMP;

interface

uses Windows, OpenGL, Sysutils;

const
BM = 19778;

type
TGLBMP = class
Width : Integer; // bitmap文件宽度
Height : Integer; // bitmap文件长度
ColorDepth : Integer; // bitmap文件色深
Bits : Pointer;
ColorsChanged : Boolean;
constructor Create();
destructor Destroy(); override;
function LoadBitmap(filename : String; ChangeColors : Boolean) : Boolean;
function SaveBitmap(filename : String) : Boolean;
function SaveScreen(filename : String) : Boolean;
function Invert() : Boolean;
private
function ConvertColors() : Boolean;
end;

implementation

{ TGLBMP }

constructor TGLBMP.Create;
begin
Width := 0;
Height := 0;
Bits := nil;
end;

function TGLBMP.LoadBitmap(filename : String; ChangeColors : Boolean) : Boolean;
var
fHeader : BITMAPFILEHEADER;
iHeader : BITMAPINFOHEADER;
bmpFile : File;
length : Integer;
bytesRead : Integer;
begin
if FileExists(filename) then begin
AssignFile(bmpFile, filename);
Reset(bmpFile, 1);
BlockRead(bmpFile, fHeader, SizeOf(fHeader));
if fHeader.bfType <> BM then begin
Result := False;
CloseFile(bmpFile);
Exit;
end;
BlockRead(bmpFile, iHeader, SizeOf(iHeader));
if iHeader.biCompression <> BI_RGB then begin
Result := False;
CloseFile(bmpFile);
Exit;
end;
Width := iHeader.biWidth;
Height := Abs(iHeader.biHeight);
ColorDepth := iHeader.biBitCount;
Seek(bmpFile, fHeader.bfOffBits);
length := Width * Height * (iHeader.biBitCount div 8);
GetMem(Bits, length);
BlockRead(bmpFile, Bits^, length, bytesRead);
if bytesRead <> length then begin
Result := False;
CloseFile(bmpFile);
Exit;
end;
if ChangeColors then
ConvertColors();
CloseFile(bmpFile);
Result := True;
end else
Result := False;
end;

function TGLBMP.SaveBitmap(filename : String) : Boolean;
var
fHeader : BITMAPFILEHEADER;
iHeader : BITMAPINFOHEADER;
bmpFile : File;
length : Integer;
bytesWritten : Integer;
begin
if Assigned(Bits) then begin
AssignFile(bmpFile, filename);
Rewrite(bmpFile, 1);
length := Width * Height * (ColorDepth div 8);
fHeader.bfType := BM;
fHeader.bfSize := SizeOf(BITMAPFILEHEADER) + SizeOf(iHeader) + length;
fHeader.bfReserved1 := 0;
fHeader.bfReserved2 := 0;
fHeader.bfOffBits := SizeOf(BITMAPFILEHEADER) + SizeOf(iHeader);
BlockWrite(bmpFile, fHeader, SizeOf(fHeader), bytesWritten);
if bytesWritten <> SizeOf(fHeader) then begin
Result := False;
CloseFile(bmpFile);
Exit;
end;
iHeader.biSize := SizeOf(BITMAPINFOHEADER);
iHeader.biWidth := Width;
iHeader.biHeight := Height;
iHeader.biPlanes := 1;
iHeader.biBitCount := ColorDepth;
iHeader.biCompression := BI_RGB;
iHeader.biSizeImage := length;
BlockWrite(bmpFile, iHeader, SizeOf(iHeader), bytesWritten);
if bytesWritten <> SizeOf(iHeader) then begin
Result := False;
CloseFile(bmpFile);
Exit;
end;
if ColorsChanged then
ConvertColors();
BlockWrite(bmpFile, Bits^, length, bytesWritten);
if bytesWritten <> length then begin
Result := False;
CloseFile(bmpFile);
Exit;
end;
CloseFile(bmpFile);

Result := True;
end else
Result := False;
end;

function TGLBMP.SaveScreen(filename : String) : Boolean;
var
viewport : Array[0..3] of GLint;
length : Integer;
tWidth : Integer;
begin
glGetIntegerv(GL_VIEWPORT, @viewport);
tWidth := viewport[2]*3;
tWidth := (tWidth + 3) and not 3;
length := tWidth * viewport[3];
FreeMem(Bits);
GetMem(Bits, length);
glFinish();
glPixelStorei(GL_PACK_ALIGNMENT, 4);
glPixelStorei(GL_PACK_ROW_LENGTH, 0);
glPixelStorei(GL_PACK_SKIP_ROWS, 0);
glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
glReadPixels(0, 0, viewport[2], viewport[3], GL_RGB, GL_UNSIGNED_BYTE, bits);
ColorsChanged := True;
Width := viewport[2];
Height := viewport[3];
ColorDepth := 24;
Result := SaveBitmap(filename);
if Result = False then
Exit;
Result := True;
end;

function TGLBMP.Invert() : Boolean;
var
Red : ^Byte;
Green : ^Byte;
Blue : ^Byte;
I : Integer;
begin
if Assigned(Bits) then begin
for I := 0 to Width * Height - 1 do begin
Red := Pointer(Integer(bits) + I*3);
Green := Pointer(Integer(bits) + I*3+1);
Blue := Pointer(Integer(bits) + I*3+2);
Red^ := 255 - Red^;
Green^ := 255 - Green^;
Blue^ := 255 - Blue^;
end;
end else begin
Result := False;
Exit;
end;
Result := True;
end;

function TGLBMP.ConvertColors() : Boolean;
var
Blue : ^Byte;
Red : ^Byte;
Temp: Byte;
I : Integer;
begin
if Assigned(Bits) then begin
for I := 0 to Width * Height - 1 do begin
Blue := Pointer(Integer(bits) + I*3);
Red := Pointer(Integer(bits) + I*3 + 2);
Temp := Blue^;
Blue^ := Red^;
Red^ := Temp;
end;
end else begin
Result := False;
Exit;
end;
ColorsChanged := not ColorsChanged;
Result := True;
end;

destructor TGLBMP.Destroy;
begin
inherited;
FreeMem(bits);
end;

end.
 
好了!全部代码都贴出来了!大家有什么好的建议和改进,希望能共同交流探讨!
还是那句话:现阶段,真3D还是离不开DirectX和OpenGl。我觉得如果你不是游戏开发者或者多媒体技术狂人
或者图象视频的深入研究的话,那么还是用2D平面尽量解决一切吧!
不过话说回来,3D技术的研究比2D的有趣许多,至少我是这么以为!
 
谢谢 人在边缘!谢谢大家!

这个帖子也够长了,我想好多人也打不开。现在关帖。如果有人要讨论也可继续,不过没
分了:)
如果有人想要 人在边缘 的demo,给我mail(chinaren又收不到dfw的邮件通知了),我发。
 
多人接受答案了。
 
后退
顶部