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