- Added FBO based light source rendering
- Fixed memory leak in TLightManager.UpdateLightMap
This commit is contained in:
parent
a19e23a82e
commit
841061abbb
|
@ -350,14 +350,14 @@
|
|||
<CodeGeneration>
|
||||
<SmartLinkUnit Value="True"/>
|
||||
<Optimizations>
|
||||
<OptimizationLevel Value="3"/>
|
||||
<OptimizationLevel Value="0"/>
|
||||
</Optimizations>
|
||||
</CodeGeneration>
|
||||
<Linking>
|
||||
<Debugging>
|
||||
<GenerateDebugInfo Value="True"/>
|
||||
<UseHeaptrc Value="True"/>
|
||||
</Debugging>
|
||||
<LinkSmart Value="True"/>
|
||||
<Options>
|
||||
<Win32>
|
||||
<GraphicApplication Value="True"/>
|
||||
|
|
|
@ -56,7 +56,7 @@ type
|
|||
FRealWidth: Integer;
|
||||
FRealHeight: Integer;
|
||||
FGraphic: TMultiImage;
|
||||
procedure CalculateTextureDimensions(ACaps: TGLTextureCaps; ARealWidth,
|
||||
class procedure CalculateTextureDimensions(ACaps: TGLTextureCaps; ARealWidth,
|
||||
ARealHeight: Integer; out AWidth, AHeight: Integer);
|
||||
function GenerateTexture(AImage: TBaseImage): TGLuint;
|
||||
function GetTexture: GLuint; virtual; abstract;
|
||||
|
@ -1283,7 +1283,7 @@ begin
|
|||
inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure TMaterial.CalculateTextureDimensions(ACaps: TGLTextureCaps;
|
||||
class procedure TMaterial.CalculateTextureDimensions(ACaps: TGLTextureCaps;
|
||||
ARealWidth, ARealHeight: Integer; out AWidth, AHeight: Integer);
|
||||
begin
|
||||
if ACaps.NonPowerOfTwo then
|
||||
|
|
|
@ -31,8 +31,7 @@ interface
|
|||
|
||||
uses
|
||||
Classes, SysUtils, Imaging, ImagingTypes, ImagingClasses, ImagingCanvases,
|
||||
ImagingOpenGL, GL, fgl, ULandscape, UWorldItem, UCacheManager,
|
||||
ImagingUtility;
|
||||
ImagingOpenGL, GL, GLu, GLext, fgl, ULandscape, UWorldItem, UCacheManager;
|
||||
|
||||
type
|
||||
|
||||
|
@ -40,22 +39,13 @@ type
|
|||
|
||||
{ TLightMaterial }
|
||||
|
||||
TLightMaterial = class(ICacheable)
|
||||
TLightMaterial = class(TSimpleMaterial)
|
||||
constructor Create(AGraphic: TBaseImage);
|
||||
destructor Destroy; override;
|
||||
protected
|
||||
FRefCount: Integer;
|
||||
FGraphic: TSingleImage;
|
||||
FCanvas: TFastARGB32Canvas;
|
||||
public
|
||||
property Graphic: TSingleImage read FGraphic;
|
||||
property Canvas: TFastARGB32Canvas read FCanvas;
|
||||
procedure AddRef;
|
||||
procedure DelRef;
|
||||
|
||||
{ICacheable}
|
||||
function CanBeRemoved: Boolean;
|
||||
procedure RemoveFromCache;
|
||||
end;
|
||||
|
||||
TLightCache = specialize TCacheManager<TLightMaterial>;
|
||||
|
@ -94,11 +84,14 @@ type
|
|||
FValid: Boolean;
|
||||
FCalculateOffset: TCalculateOffset;
|
||||
FLightCache: TLightCache;
|
||||
FUseFBO: Boolean;
|
||||
FInitialized: Boolean;
|
||||
function GetLight(AID: Integer): TLightMaterial;
|
||||
procedure SetLightLevel(AValue: Byte);
|
||||
procedure UpdateOverlay(AScreenRect: TRect);
|
||||
public
|
||||
property LightLevel: Byte read FLightLevel write SetLightLevel;
|
||||
procedure InitGL;
|
||||
procedure UpdateLightMap(ALeft, AWidth, ATop, AHeight: Integer;
|
||||
AScreenBuffer: TScreenBuffer);
|
||||
procedure Draw(AScreenRect: TRect);
|
||||
|
@ -117,6 +110,7 @@ begin
|
|||
FLightSources := TLightSources.Create(True);
|
||||
FLightLevel := 0;
|
||||
FLightCache := TLightCache.Create(32);
|
||||
FInitialized := False;
|
||||
end;
|
||||
|
||||
destructor TLightManager.Destroy;
|
||||
|
@ -157,42 +151,101 @@ var
|
|||
color: TColor32Rec;
|
||||
i: Integer;
|
||||
lightMaterial: TLightMaterial;
|
||||
colorGL: GLclampf;
|
||||
fbo: GLuint;
|
||||
begin
|
||||
FOverlay.Free;
|
||||
glDeleteTextures(1, @FOverlayTexture);
|
||||
if FUseFBO then
|
||||
begin
|
||||
glGenTextures(1, @FOverlayTexture);
|
||||
glBindTexture(GL_TEXTURE_2D, FOverlayTexture);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, AScreenRect.Right,
|
||||
AScreenRect.Bottom, 0, GL_RGBA, GL_UNSIGNED_BYTE, nil);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
color.A := $FF;
|
||||
color.R := ((32 - FLightLevel) * 255) div 32;
|
||||
color.G := color.R;
|
||||
color.B := color.R;
|
||||
glGenFramebuffersEXT(1, @fbo);
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
|
||||
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
|
||||
GL_TEXTURE_2D, FOverlayTexture, 0);
|
||||
|
||||
FOverlay := TSingleImage.CreateFromParams(AScreenRect.Right,
|
||||
AScreenRect.Bottom, ifA8R8G8B8);
|
||||
canvas := TFastARGB32Canvas.CreateForImage(FOverlay);
|
||||
try
|
||||
canvas.FillColor32 := color.Color;
|
||||
canvas.FillRect(AScreenRect);
|
||||
colorGL :=(32 - lightLevel) / 32;
|
||||
glClearColor(colorGL, colorGL, colorGL, 1);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
glBlendFunc(GL_ONE, GL_ONE);
|
||||
for i := 0 to FLightSources.Count - 1 do
|
||||
begin
|
||||
lightMaterial := FLightSources[i].Material;
|
||||
if lightMaterial <> nil then
|
||||
begin
|
||||
lightMaterial.Canvas.DrawAdd(lightMaterial.Canvas.ClipRect, canvas,
|
||||
FLightSources[i].FX - lightMaterial.Graphic.Width div 2,
|
||||
FLightSources[i].FY - lightMaterial.Graphic.Height div 2);
|
||||
lightMaterial := FLightSources[i].Material;
|
||||
if lightMaterial <> nil then
|
||||
begin
|
||||
glBindTexture(GL_TEXTURE_2D, lightMaterial.Texture);
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2i(0, 0);
|
||||
glVertex2i(FLightSources[i].FX - lightMaterial.RealWidth div 2,
|
||||
FLightSources[i].FY - lightMaterial.RealHeight div 2);
|
||||
glTexCoord2i(0, 1);
|
||||
glVertex2i(FLightSources[i].FX - lightMaterial.RealWidth div 2,
|
||||
FLightSources[i].FY - lightMaterial.RealHeight div 2 +
|
||||
lightMaterial.Height);
|
||||
glTexCoord2i(1, 1);
|
||||
glVertex2i(FLightSources[i].FX - lightMaterial.RealWidth div 2 +
|
||||
lightMaterial.Width, FLightSources[i].FY -
|
||||
lightMaterial.RealHeight div 2 + lightMaterial.Height);
|
||||
glTexCoord2i(1, 0);
|
||||
glVertex2i(FLightSources[i].FX - lightMaterial.RealWidth div 2 +
|
||||
lightMaterial.Width,
|
||||
FLightSources[i].FY - lightMaterial.RealHeight div 2);
|
||||
glEnd;
|
||||
end;
|
||||
end;
|
||||
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||
glDeleteFramebuffersEXT(1, @fbo);
|
||||
end else
|
||||
begin
|
||||
FOverlay.Free;
|
||||
|
||||
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);
|
||||
|
||||
for i := 0 to FLightSources.Count - 1 do
|
||||
begin
|
||||
lightMaterial := FLightSources[i].Material;
|
||||
if lightMaterial <> nil then
|
||||
begin
|
||||
lightMaterial.Canvas.DrawAdd(lightMaterial.Canvas.ClipRect, canvas,
|
||||
FLightSources[i].FX - lightMaterial.RealWidth div 2,
|
||||
FLightSources[i].FY - lightMaterial.RealHeight div 2);
|
||||
end;
|
||||
end;
|
||||
finally
|
||||
canvas.Free;
|
||||
end;
|
||||
finally
|
||||
canvas.Free;
|
||||
|
||||
FOverlayTexture := CreateGLTextureFromImage(FOverlay.ImageDataPointer^);
|
||||
end;
|
||||
|
||||
//TODO : PowerOfTwo!!!
|
||||
FOverlayTexture := CreateGLTextureFromImage(FOverlay.ImageDataPointer^);
|
||||
|
||||
FValid := True;
|
||||
end;
|
||||
|
||||
procedure TLightManager.InitGL;
|
||||
begin
|
||||
FUseFBO := Load_GL_EXT_framebuffer_object;
|
||||
end;
|
||||
|
||||
procedure TLightManager.UpdateLightMap(ALeft, AWidth, ATop, AHeight: Integer;
|
||||
AScreenBuffer: TScreenBuffer);
|
||||
var
|
||||
|
@ -249,18 +302,35 @@ begin
|
|||
for i := 0 to lights.Count - 1 do
|
||||
FLightSources.Add(TLightSource.Create(Self, lights[i]));
|
||||
|
||||
lights.Free;
|
||||
|
||||
FValid := False;
|
||||
//Logger.ExitMethod([lcClient, lcDebug], 'UpdateLightMap');
|
||||
end;
|
||||
|
||||
procedure TLightManager.Draw(AScreenRect: TRect);
|
||||
begin
|
||||
if not FInitialized then
|
||||
InitGL;
|
||||
|
||||
if not FValid then
|
||||
UpdateOverlay(AScreenRect);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, FOverlayTexture);
|
||||
glBlendFunc(GL_ZERO, GL_SRC_COLOR);
|
||||
glBegin(GL_QUADS);
|
||||
if FUseFBO then
|
||||
begin
|
||||
glTexCoord2i(0, 1);
|
||||
glVertex2i(AScreenRect.Left, AScreenRect.Top);
|
||||
glTexCoord2i(0, 0);
|
||||
glVertex2i(AScreenRect.Left, AScreenRect.Bottom);
|
||||
glTexCoord2i(1, 0);
|
||||
glVertex2i(AScreenRect.Right, AScreenRect.Bottom);
|
||||
glTexCoord2i(1, 1);
|
||||
glVertex2i(AScreenRect.Right, AScreenRect.Top);
|
||||
end else
|
||||
begin
|
||||
glTexCoord2i(0, 0);
|
||||
glVertex2i(AScreenRect.Left, AScreenRect.Top);
|
||||
glTexCoord2i(0, 1);
|
||||
|
@ -269,6 +339,7 @@ begin
|
|||
glVertex2i(AScreenRect.Right, AScreenRect.Bottom);
|
||||
glTexCoord2i(1, 0);
|
||||
glVertex2i(AScreenRect.Right, AScreenRect.Top);
|
||||
end;
|
||||
glEnd;
|
||||
end;
|
||||
|
||||
|
@ -300,39 +371,15 @@ end;
|
|||
|
||||
constructor TLightMaterial.Create(AGraphic: TBaseImage);
|
||||
begin
|
||||
FRefCount := 1;
|
||||
FGraphic := TSingleImage.CreateFromImage(AGraphic);
|
||||
inherited Create(AGraphic);
|
||||
FCanvas := TFastARGB32Canvas.CreateForImage(FGraphic);
|
||||
end;
|
||||
|
||||
destructor TLightMaterial.Destroy;
|
||||
begin
|
||||
FreeAndNil(FCanvas);
|
||||
FreeAndNil(FGraphic);
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure TLightMaterial.AddRef;
|
||||
begin
|
||||
Inc(FRefCount);
|
||||
end;
|
||||
|
||||
procedure TLightMaterial.DelRef;
|
||||
begin
|
||||
Dec(FRefCount);
|
||||
if FRefCount < 1 then
|
||||
Free;
|
||||
end;
|
||||
|
||||
function TLightMaterial.CanBeRemoved: Boolean;
|
||||
begin
|
||||
Result := (FRefCount <= 1);
|
||||
end;
|
||||
|
||||
procedure TLightMaterial.RemoveFromCache;
|
||||
begin
|
||||
DelRef;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
|
|
Loading…
Reference in New Issue