- Implemented basic light source rendering

This commit is contained in:
Andreas Schneider 2009-12-20 22:05:15 +01:00
parent ee9a44219f
commit 7b46795bc1
6 changed files with 494 additions and 258 deletions

View File

@ -55,7 +55,7 @@
<MinVersion Major="4" Minor="5" Release="1" Valid="True"/> <MinVersion Major="4" Minor="5" Release="1" Valid="True"/>
</Item5> </Item5>
</RequiredPackages> </RequiredPackages>
<Units Count="42"> <Units Count="43">
<Unit0> <Unit0>
<Filename Value="CentrED.lpr"/> <Filename Value="CentrED.lpr"/>
<IsPartOfProject Value="True"/> <IsPartOfProject Value="True"/>
@ -304,6 +304,11 @@
<Filename Value="../version.inc"/> <Filename Value="../version.inc"/>
<IsPartOfProject Value="True"/> <IsPartOfProject Value="True"/>
</Unit41> </Unit41>
<Unit42>
<Filename Value="ULightManager.pas"/>
<IsPartOfProject Value="True"/>
<UnitName Value="ULightManager"/>
</Unit42>
</Units> </Units>
</ProjectOptions> </ProjectOptions>
<CompilerOptions> <CompilerOptions>
@ -332,7 +337,6 @@
<Linking> <Linking>
<Debugging> <Debugging>
<GenerateDebugInfo Value="True"/> <GenerateDebugInfo Value="True"/>
<UseExternalDbgSyms Value="True"/>
</Debugging> </Debugging>
<LinkSmart Value="True"/> <LinkSmart Value="True"/>
<Options> <Options>

View File

@ -42,7 +42,8 @@ uses
UGUIPlatformUtils, UPlatformTypes, UfrmRegionControl, UPackets, UGUIPlatformUtils, UPlatformTypes, UfrmRegionControl, UPackets,
UPacketHandlers, UAdminHandling, UGameResources, ULandscape, UfrmToolWindow, UPacketHandlers, UAdminHandling, UGameResources, ULandscape, UfrmToolWindow,
Logging, UTileDataProvider, UMap, UWorldItem, UStatics, UTiledata, UAnimData, Logging, UTileDataProvider, UMap, UWorldItem, UStatics, UTiledata, UAnimData,
UGLFont, UAnimDataProvider, UMulManager, UArtProvider, UTexmapProvider; UGLFont, UAnimDataProvider, UMulManager, UArtProvider, UTexmapProvider,
ULightManager;
{$IFDEF WINDOWS}{$R CentrED.rc}{$ENDIF} {$IFDEF WINDOWS}{$R CentrED.rc}{$ENDIF}

221
Client/ULightManager.pas Normal file
View File

@ -0,0 +1,221 @@
(*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at
* http://www.opensource.org/licenses/cddl1.php.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at
* http://www.opensource.org/licenses/cddl1.php. If applicable,
* add the following below this CDDL HEADER, with the fields enclosed
* by brackets "[]" replaced with your own identifying * information:
* Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*
*
* Portions Copyright 2009 Andreas Schneider
*)
unit ULightManager;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, Imaging, ImagingTypes, ImagingClasses, ImagingCanvases,
ImagingOpenGL, GL, fgl, ULandscape, UWorldItem;
type
TCalculateOffset = procedure(ARelativeX, ARelativeY: Integer; out DrawX,
DrawY: Integer) of object;
{ TLightSource }
TLightSource = class
constructor Create(AWorldItem: TWorldItem);
protected
FX: Integer;
FY: Integer;
FZ: smallint;
public
property X: Integer read FX;
property Y: Integer read FY;
property Z: smallint read FZ;
end;
TLightSources = specialize TFPGObjectList<TLightSource>;
{ TLightManager }
TLightManager = class
constructor Create(ACalculateOffset: TCalculateOffset);
destructor Destroy; override;
protected
FLightSources: TLightSources;
FOverlay: TSingleImage;
FOverlayTexture: GLuint;
FLightLevel: byte;
FValid: Boolean;
FCalculateOffset: TCalculateOffset;
procedure UpdateOverlay(AScreenRect: TRect; FX, FY: Integer);
public
procedure UpdateLightMap(ALeft, AWidth, ATop, AHeight: Integer;
AScreenBuffer: TScreenBuffer);
procedure Draw(AScreenRect: TRect; FX, FY: Integer);
end;
implementation
uses
UGameResources, UTiledata, UStatics, Logging;
{ TLightManager }
constructor TLightManager.Create(ACalculateOffset: TCalculateOffset);
begin
FCalculateOffset := ACalculateOffset;
FLightSources := TLightSources.Create(True);
FLightLevel := 15; //TODO : 0 ...
end;
destructor TLightManager.Destroy;
begin
FreeAndNil(FLightSources);
FreeAndNil(FOverlay);
glDeleteTextures(1, @FOverlayTexture);
inherited Destroy;
end;
procedure TLightManager.UpdateOverlay(AScreenRect: TRect; FX, FY: Integer);
var
canvas: TFastARGB32Canvas;
color: TColor32Rec;
i, drawX, drawY, drawZ: Integer;
begin
FOverlay.Free;
glDeleteTextures(1, @FOverlayTexture);
color.A := $FF;
color.R := ((32 - FLightLevel) * 255) div 32;
color.G := color.R;
color.B := color.R;
FOverlay := TSingleImage.CreateFromParams(AScreenRect.Right, AScreenRect.Bottom,
ifA8R8G8B8);
canvas := TFastARGB32Canvas.CreateForImage(FOverlay);
try
canvas.FillColor32 := color.Color;
canvas.FillRect(AScreenRect);
finally
canvas.Free;
end;
for i := 0 to FLightSources.Count - 1 do
begin
FCalculateOffset(FLightSources[i].X - FX, FLightSources[i].Y - FY,
drawX, drawY);
drawZ := FLightSources[i].Z * 4;
color.A := $20;
color.R := 220;
color.G := 0;
color.B := 0;
canvas.FillColor32 := color.Color;
canvas.FillRectBlend(Rect(drawX - 22, drawY - drawZ, drawX + 22,
drawY + 44 - drawZ), bfOne, bfOne);
end;
//TODO : PowerOfTwo!!!
FOverlayTexture := CreateGLTextureFromImage(FOverlay.ImageDataPointer^);
FValid := True;
end;
procedure TLightManager.UpdateLightMap(ALeft, AWidth, ATop, AHeight: Integer;
AScreenBuffer: TScreenBuffer);
var
blockInfo: PBlockInfo;
itemMap, lightMap: array of array of TWorldItem;
x, y: Integer;
begin
//Logger.EnterMethod([lcClient, lcDebug], 'UpdateLightMap');
FLightSources.Clear;
{Logger.Send([lcClient, lcDebug], 'AWidth', AWidth);
Logger.Send([lcClient, lcDebug], 'AHeight', AHeight);}
SetLength(itemMap, AWidth, AHeight);
SetLength(lightMap, AWidth, AHeight);
for x := 0 to AWidth - 1 do
for y := 0 to AHeight - 1 do
begin
itemMap[x, y] := nil;
lightMap[x, y] := nil;
end;
blockInfo := nil;
while AScreenBuffer.Iterate(blockInfo) do
begin
if blockInfo^.State = ssNormal then
begin
x := blockInfo^.Item.X - ALeft;
y := blockInfo^.Item.Y - ATop;
itemMap[x, y] := blockInfo^.Item;
if (blockInfo^.Item is TStaticItem) and (tdfLightSource in
ResMan.Tiledata.StaticTiles[blockInfo^.Item.TileID].Flags) then
lightMap[x, y] := blockInfo^.Item;
end;
end;
for x := 0 to AWidth - 2 do
for y := 0 to AHeight - 2 do
if lightMap[x, y] <> nil then
begin
if ((itemMap[x, y] = nil) or (itemMap[x, y].Z < lightMap[x, y].Z + 3)) or
((itemMap[x + 1, y] = nil) or (itemMap[x + 1, y].Z < lightMap[x, y].Z + 3)) or
((itemMap[x + 1, y + 1] = nil) or (itemMap[x + 1, y + 1].Z < lightMap[x, y].Z + 3)) or
((itemMap[x, y + 1] = nil) or (itemMap[x, y + 1].Z < lightMap[x, y].Z + 3)) then
begin
FLightSources.Add(TLightSource.Create(lightMap[x, y]));
end;
end;
FValid := False;
//Logger.ExitMethod([lcClient, lcDebug], 'UpdateLightMap');
end;
procedure TLightManager.Draw(AScreenRect: TRect; FX, FY: Integer);
begin
if not FValid then
UpdateOverlay(AScreenRect, FX, FY);
glBindTexture(GL_TEXTURE_2D, FOverlayTexture);
glBlendFunc(GL_ZERO, GL_SRC_COLOR);
glBegin(GL_QUADS);
glTexCoord2i(0, 0);
glVertex2i(AScreenRect.Left, AScreenRect.Top);
glTexCoord2i(0, 1);
glVertex2i(AScreenRect.Left, AScreenRect.Bottom);
glTexCoord2i(1, 1);
glVertex2i(AScreenRect.Right, AScreenRect.Bottom);
glTexCoord2i(1, 0);
glVertex2i(AScreenRect.Right, AScreenRect.Top);
glEnd;
end;
{ TLightSource }
constructor TLightSource.Create(AWorldItem: TWorldItem);
begin
FX := AWorldItem.X;
FY := AWorldItem.Y;
FZ := AWorldItem.Z;
end;
end.

View File

@ -224,6 +224,9 @@ procedure TOverlayUI.Draw(AContext: TOpenGLControl);
begin begin
if FVisible then if FVisible then
begin begin
glColor4f(1.0, 1.0, 1.0, 1.0);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
FArrows[0].DrawGL(10, 10, FActiveArrow = 0); FArrows[0].DrawGL(10, 10, FActiveArrow = 0);
FArrows[1].DrawGL(AContext.Width div 2 - FArrows[1].Width div 2, 10, FArrows[1].DrawGL(AContext.Width div 2 - FArrows[1].Width div 2, 10,
FActiveArrow = 1); FActiveArrow = 1);

View File

@ -1,7 +1,7 @@
object frmMain: TfrmMain object frmMain: TfrmMain
Left = 257 Left = 257
Height = 579 Height = 579
Top = 135 Top = 141
Width = 755 Width = 755
ActiveControl = oglGameWindow ActiveControl = oglGameWindow
Caption = 'UO CentrED' Caption = 'UO CentrED'

View File

@ -35,7 +35,7 @@ uses
StdCtrls, Spin, UEnums, VirtualTrees, Buttons, UMulBlock, UWorldItem, math, StdCtrls, Spin, UEnums, VirtualTrees, Buttons, UMulBlock, UWorldItem, math,
LCLIntf, UOverlayUI, UStatics, UEnhancedMemoryStream, ActnList, LCLIntf, UOverlayUI, UStatics, UEnhancedMemoryStream, ActnList,
XMLPropStorage, fgl, ImagingClasses, dateutils, UPlatformTypes, UMap, UPacket, XMLPropStorage, fgl, ImagingClasses, dateutils, UPlatformTypes, UMap, UPacket,
UGLFont, DOM, XMLRead, XMLWrite, strutils; UGLFont, DOM, XMLRead, XMLWrite, strutils, ULightManager;
type type
TAccessChangedListener = procedure(AAccessLevel: TAccessLevel) of object; TAccessChangedListener = procedure(AAccessLevel: TAccessLevel) of object;
@ -323,6 +323,7 @@ type
FGLFont: TGLFont; FGLFont: TGLFont;
FSelectionListeners: TSelectionListeners; FSelectionListeners: TSelectionListeners;
FTileHint: TTileHintInfo; FTileHint: TTileHintInfo;
FLightManager: TLightManager;
{ Methods } { Methods }
procedure BuildTileList; procedure BuildTileList;
function ConfirmAction: Boolean; function ConfirmAction: Boolean;
@ -892,6 +893,7 @@ begin
edX.MaxValue := FLandscape.CellWidth; edX.MaxValue := FLandscape.CellWidth;
edY.MaxValue := FLandscape.CellHeight; edY.MaxValue := FLandscape.CellHeight;
FOverlayUI := TOverlayUI.Create; FOverlayUI := TOverlayUI.Create;
FLightManager := TLightManager.Create(@GetDrawOffset);
ProcessAccessLevel; ProcessAccessLevel;
@ -1258,6 +1260,7 @@ begin
FreeAndNil(FTextureManager); FreeAndNil(FTextureManager);
FreeAndNil(FScreenBuffer); FreeAndNil(FScreenBuffer);
FreeAndNil(FOverlayUI); FreeAndNil(FOverlayUI);
FreeAndNil(FLightManager);
FreeAndNil(FVLayerImage); FreeAndNil(FVLayerImage);
FreeAndNil(FVLayerMaterial); FreeAndNil(FVLayerMaterial);
FreeAndNil(FVirtualTiles); FreeAndNil(FVirtualTiles);
@ -2387,7 +2390,7 @@ begin
blockInfo^.Text.Render(blockInfo^.ScreenRect); blockInfo^.Text.Render(blockInfo^.ScreenRect);
end; end;
glColor4f(1.0, 1.0, 1.0, 1.0); FLightManager.Draw(oglGameWindow.ClientRect, FX, FY);
FOverlayUI.Draw(oglGameWindow); FOverlayUI.Draw(oglGameWindow);
end; end;
@ -2729,6 +2732,10 @@ begin
end; end;
end; end;
Include(FScreenBufferState, sbsFiltered); Include(FScreenBufferState, sbsFiltered);
//TODO : Check lightlevel first
FLightManager.UpdateLightMap(FX + FLowOffsetX, FRangeX + 1, FY + FLowOffsetY,
FRangeY + 1, FScreenBuffer);
end; end;
procedure TfrmMain.UpdateSelection; procedure TfrmMain.UpdateSelection;