📄 dxrender.pas
字号:
end;
DXR_BLEND_SRCALPHA1:
begin
Col1_1 := [chRed, chGreen, chBlue];
Col1_2 := [chAlpha];
Col2_1 := [];
Col2_2 := [];
end;
DXR_BLEND_SRCALPHA1_ADD_ONE2:
begin
Col1_1 := [chRed, chGreen, chBlue];
Col1_2 := [chAlpha];
Col2_1 := [chRed, chGreen, chBlue, chAlpha];
Col2_2 := [];
end;
DXR_BLEND_ONE2_SUB_SRCALPHA1:
begin
Col1_1 := [chRed, chGreen, chBlue];
Col1_2 := [chAlpha];
Col2_1 := [chRed, chGreen, chBlue, chAlpha];
Col2_2 := [];
end;
DXR_BLEND_SRCALPHA1_ADD_INVSRCALPHA2:
begin
Col1_1 := [chRed, chGreen, chBlue];
Col1_2 := [chAlpha];
Col2_1 := [chRed, chGreen, chBlue, chAlpha];
Col2_2 := [];
end;
DXR_BLEND_INVSRCALPHA1_ADD_SRCALPHA2:
begin
Col1_1 := [chRed, chGreen, chBlue];
Col1_2 := [chAlpha];
Col2_1 := [chRed, chGreen, chBlue, chAlpha];
Col2_2 := [];
end;
DXR_BLEND_DECAL:
begin
Col1_1 := [chRed, chGreen, chBlue, chAlpha];
Col1_2 := [];
Col2_1 := [];
Col2_2 := [];
end;
DXR_BLEND_DECALALPHA:
begin
Col1_1 := [chRed, chGreen, chBlue];
Col1_2 := [];
Col2_1 := [];
Col2_2 := [chAlpha];
end;
DXR_BLEND_MODULATE:
begin
Col1_1 := [chRed, chGreen, chBlue, chAlpha];
Col1_2 := [];
Col2_1 := [chRed, chGreen, chBlue, chAlpha];
Col2_2 := [];
end;
DXR_BLEND_MODULATEALPHA:
begin
Col1_1 := [chRed, chGreen, chBlue];
Col1_2 := [chAlpha];
Col2_1 := [chRed, chGreen, chBlue];
Col2_2 := [chAlpha];
end;
DXR_BLEND_ADD:
begin
Col1_1 := [chRed, chGreen, chBlue, chAlpha];
Col1_2 := [];
Col2_1 := [chRed, chGreen, chBlue, chAlpha];
Col2_2 := [];
end;
end;
end;
var
c: TDXRColorChannels;
Col1_1, Col1_2, Col2_1, Col2_2: TDXRColorChannels;
begin
case Tree.Typ of
DXR_TREETYPE_LOADBLACK:
begin
// Load black color
end;
DXR_TREETYPE_LOADCOLOR:
begin
// Load color
end;
DXR_TREETYPE_LOADTEXTURE:
begin
// Load texel
end;
DXR_TREETYPE_LOADBUMPTEXTURE:
begin
// Load texel with Bump mapping
end;
DXR_TREETYPE_LOADDESTPIXEL:
begin
// Load dest pixel
end;
DXR_TREETYPE_BLEND:
begin
// Blend color
GetBlendChannels(Tree.Blend, Col1_1, Col1_2, Col2_1, Col2_2);
Tree.BlendTree1.Channels := Tree.Channels*Col1_1+Col1_2;
Tree.BlendTree2.Channels := Tree.Channels*Col2_1+Col2_2;
OptimizeTree(Tree.BlendTree1);
OptimizeTree(Tree.BlendTree2);
if (Tree.Blend=DXR_BLEND_ZERO) then
begin
c := Tree.Channels; Tree^.Typ := DXR_TREETYPE_LOADBLACK; Tree.Channels := c;
end else
if (Tree.Blend in [DXR_BLEND_ONE1, DXR_BLEND_DECAL]) then
begin
c := Tree.Channels; Tree := Tree.BlendTree1; Tree.Channels := c;
end else
if (Tree.Blend=DXR_BLEND_ONE2) then
begin
c := Tree.Channels; Tree := Tree.BlendTree2; Tree.Channels := c;
end else
if (Tree.Blend in [DXR_BLEND_ONE1_ADD_ONE2, DXR_BLEND_ONE2_SUB_ONE1]) and
(Tree.BlendTree2.Typ=DXR_TREETYPE_LOADBLACK) then
begin
c := Tree.Channels; Tree := Tree.BlendTree1; Tree.Channels := c;
end else
if (Tree.Blend in [DXR_BLEND_ONE1_ADD_ONE2, DXR_BLEND_ONE2_SUB_ONE1]) and
(Tree.BlendTree1.Typ=DXR_TREETYPE_LOADBLACK) then
begin
c := Tree.Channels; Tree := Tree.BlendTree2; Tree.Channels := c;
end else
begin
if (Col1_1=[]) and (Col1_2=[]) then Tree.BlendTree1 := nil;
if (Col2_1=[]) and (Col2_2=[]) then Tree.BlendTree2 := nil;
end;
end;
end;
end;
procedure GetEnableChannels(Tree: PDXRMachine_Tree);
begin
case Tree.Typ of
DXR_TREETYPE_LOADBLACK:
begin
// Load black color
end;
DXR_TREETYPE_LOADCOLOR:
begin
// Load color
ColorList[Tree.Color].Channels := ColorList[Tree.Color].Channels + Tree.Channels;
ColorList[Tree.Color].Enable := ColorList[Tree.Color].Channels<>[];
end;
DXR_TREETYPE_LOADTEXTURE:
begin
// Load texel
TextureList[Tree.Texture].EnableChannels := TextureList[Tree.Texture].EnableChannels +
Tree.Channels*GetSurfaceChannels(TextureList[Tree.Texture].Surface^);
TextureList[Tree.Texture].Enable := TextureList[Tree.Texture].EnableChannels<>[];
end;
DXR_TREETYPE_LOADBUMPTEXTURE:
begin
// Load texel with Bump mapping
TextureList[Tree.Texture].EnableChannels := TextureList[Tree.Texture].EnableChannels +
Tree.Channels*GetSurfaceChannels(TextureList[Tree.Texture].Surface^);
TextureList[Tree.Texture].Enable := TextureList[Tree.Texture].EnableChannels<>[];
TextureList[Tree.BumpTexture].Enable := True;
end;
DXR_TREETYPE_LOADDESTPIXEL:
begin
// Load dest pixel
end;
DXR_TREETYPE_BLEND:
begin
// Blend color
if Tree.BlendTree1<>nil then GetEnableChannels(Tree.BlendTree1);
if Tree.BlendTree2<>nil then GetEnableChannels(Tree.BlendTree2);
end;
end;
end;
var
Code: Pointer;
i: Integer;
begin
{ Optimize tree }
Tree.Channels := GetSurfaceChannels(Dest^);
OptimizeTree(Tree);
{ Get enable channels }
GetEnableChannels(Tree);
for i:=Low(ColorList) to High(ColorList) do
if ColorList[i].Enable then
begin
ColorIndex[ColorIndexCount] := i;
Inc(ColorIndexCount);
end;
for i:=Low(TextureList) to High(TextureList) do
if TextureList[i].Enable then
begin
TextureIndex[TextureIndexCount] := i;
Inc(TextureIndexCount);
end;
ZBuffer.Enable := ZBuffer.Surface<>nil;
RHW.Enable := ZBuffer.Enable;
Axis.IncEnable := Dither.Enable;
{ Generate X86 code }
Code := FBuf; GenerateCode(Code, Tree);
FCompiled := True;
end;
const
Mask1: array[0..7] of DWORD= ($80, $40, $20, $10, $08, $04, $02, $01);
Mask2: array[0..3] of DWORD= ($C0, $30, $0C, $03);
Mask4: array[0..1] of DWORD= ($F0, $0F);
Shift1: array[0..7] of DWORD= (7, 6, 5, 4, 3, 2, 1, 0);
Shift2: array[0..3] of DWORD= (6, 4, 2, 0);
Shift4: array[0..1] of DWORD= (4, 0);
var
_null: Byte;
// Saturation addition table
// Result := Min(n+j, 255)
_AddTable: array[0..256*2-1] of Byte;
_SubTable: array[-255..255] of Byte;
// Byte to QWORD convert table
// Result := (n shl 56)+(n shl 48)+(n shl 32)+(n shl 24)+(n shl 16)+(n shl 8)+n
_ByteToQWORDTable: array[0..255, 0..3] of WORD;
_BlackColor: TDXRMachine_Color = (R: 0; G: 0; B: 0; A: 0);
procedure Init;
var
i: Integer;
begin
for i:=Low(_AddTable) to High(_AddTable) do
begin
if i>255 then
_AddTable[i] := 255
else
_AddTable[i] := i;
end;
for i:=Low(_SubTable) to High(_SubTable) do
begin
if i<0 then
_SubTable[i] := 0
else
_SubTable[i] := i;
end;
for i:=0 to 255 do
begin
_ByteToQWORDTable[i, 0] := i;
_ByteToQWORDTable[i, 1] := i;
_ByteToQWORDTable[i, 2] := i;
_ByteToQWORDTable[i, 3] := i;
end;
end;
procedure TDXRMachine.GenerateCode(var Code: Pointer; Tree: PDXRMachine_Tree);
var
SkipAddress: Pointer;
procedure genCmpFunc(var Code: Pointer; Func: TDXR_CmpFunc; JmpAdress: Pointer);
procedure genShortJmp(var Code: Pointer; JmpCode: Pointer; sC: Byte);
type
PShortJmp = ^TShortJmp;
TShortJmp = packed record
c: Byte;
A: ShortInt;
end;
begin
with PShortJmp(Code)^ do
begin
c := sC;
A := Integer(JmpCode)-(Integer(Code)+2);
end;
Inc(Integer(Code), 2);
end;
procedure genNearJmp(var Code: Pointer; JmpCode: Pointer; nC: Byte);
type
PNearJmp = ^TNearJmp;
TNearJmp = packed record
c: Byte;
A: Integer;
end;
begin
with PNearJmp(Code)^ do
begin
c := nC;
A := Integer(JmpCode)-(Integer(Code)+5);
end;
Inc(Integer(Code), 5);
end;
procedure genNearJmp2(var Code: Pointer; JmpCode: Pointer; nC1, nC2: Byte);
type
PNearJmp2 = ^TNearJmp2;
TNearJmp2 = packed record
c1, c2: Byte;
A: Integer;
end;
begin
with PNearJmp2(Code)^ do
begin
c1 := nC1;
c2 := nC2;
A := Integer(JmpCode)-(Integer(Code)+6);
end;
Inc(Integer(Code), 6);
end;
procedure genFlagJmp(var Code: Pointer; JmpCode: Pointer; sC, nC1, nC2: Byte);
var
i: Integer;
begin
i := Integer(JmpCode)-(Integer(Code)+2);
if abs(i)<128 then
genShortJmp(Code, JmpCode, sC)
else
genNearJmp2(Code, JmpCode, nC1, nC2);
end;
procedure genJmp(var Code: Pointer; JmpCode: Pointer);
var
i: Integer;
begin
i := Integer(JmpCode)-(Integer(Code)+2);
if abs(i)<128 then
genShortJmp(Code, JmpCode, $EB)
else
genNearJmp(Code, JmpCode, $E9);
end;
begin
case Func of
DXR_CMPFUNC_NEVER:
begin
{ if (False) then Jump }
end;
DXR_CMPFUNC_LESS:
begin
{ if (New<Old) then Jump }
genFlagJmp(Code, JmpAdress, $7C, $0F, $8C);
end;
DXR_CMPFUNC_EQUAL:
begin
{ if (New=Old) then Jump }
genFlagJmp(Code, JmpAdress, $74, $0F, $84);
end;
DXR_CMPFUNC_LESSEQUAL:
begin
{ if (New<=Old) then Jump }
genFlagJmp(Code, JmpAdress, $7E, $0F, $8E);
end;
DXR_CMPFUNC_GREATER:
begin
{ if (New>Old) then Jump }
genFlagJmp(Code, JmpAdress, $7F, $0F, $8F);
end;
DXR_CMPFUNC_NOTEQUAL:
begin
{ if (New<>Old) then Jump }
genFlagJmp(Code, JmpAdress, $75, $0F, $85);
end;
DXR_CMPFUNC_GREATEREQUAL:
begin
{ if (New>=Old) then Jump }
genFlagJmp(Code, JmpAdress, $7D, $0F, $8D);
end;
DXR_CMPFUNC_ALWAYS:
begin
{ if (True) then Break }
genJmp(Code, JmpAdress);
end;
end;
end;
procedure genInitDestAddress(var Code: Pointer);
var
_Axis: Pointer;
ByteCount, Pitch: DWORD;
Bits: Pointer;
begin
_Axis := @Axis.Axis;
ByteCount := Dest.BitCount shr 3;
Pitch := Dest.pitch;
Bits := Dest.Bits;
asm
jmp @@EndCode
@@StartCode:
mov eax,dword ptr [offset _null]{}@@AxisX:
imul eax,$11{} @@ByteCount: // Dest.BitCount div 8
mov edi,dword ptr [offset _null]{}@@AxisY:
imul edi,$11111111{} @@Pitch: // Dest.pitch
add edi,$11111111{} @@Bits: // Dest.Bits
add edi,eax
@@EndCode:
{$I DXRender.inc}
{ @@AxisX }
mov eax,_Axis; add eax,TDXRMachine_Axis.X
mov edx,offset @@AxisX-4
sub edx,offset @@StartCode
mov dword ptr [ecx+edx],eax
{ @@AxisY }
mov eax,_Axis; add eax,TDXRMachine_Axis.Y
mov edx,offset @@AxisY-4
sub edx,offset @@StartCode
mov dword ptr [ecx+edx],eax
{ @@ByteCount }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -