Skip to content

Commit

Permalink
Made a few performance improvementsa
Browse files Browse the repository at this point in the history
  • Loading branch information
softwareantics committed Jan 17, 2024
1 parent 8ee6bed commit 9d14efc
Show file tree
Hide file tree
Showing 8 changed files with 91 additions and 76 deletions.
6 changes: 3 additions & 3 deletions FinalEngine.Examples.Sponza/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ private static void Main()

var watch = new Stopwatch();
var watchInvoker = new StopwatchInvoker(watch);
var gameTime = new GameTime(watchInvoker, 120.0f);
var gameTime = new GameTime(watchInvoker, 10000.0f);

float fieldDepth = 10.0f;
float fieldWidth = 10.0f;
Expand Down Expand Up @@ -223,9 +223,9 @@ private static void Main()

geometryRenderer.Enqueue(model);

for (var i = 0; i < 2; i++)
for (var i = 0; i < 5; i++)
{
for (var j = 0; j < 2; j++)
for (var j = 0; j < 5; j++)
{
lightRenderer.Enqueue(new Light()
{
Expand Down
21 changes: 1 addition & 20 deletions FinalEngine.Rendering.OpenGL/OpenGLPipeline.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,10 @@ namespace FinalEngine.Rendering.OpenGL;

public class OpenGLPipeline : IPipeline
{
private const int InitialSizeCapacity = 50;

private readonly IOpenGLInvoker invoker;

private readonly Dictionary<string, string> nameToHeaderMap;

private readonly Dictionary<string, int> uniformLocations;

private IOpenGLFrameBuffer? boundFrameBuffer;

private IOpenGLShaderProgram? boundProgram;
Expand All @@ -35,7 +31,6 @@ public class OpenGLPipeline : IPipeline
public OpenGLPipeline(IOpenGLInvoker invoker)
{
this.invoker = invoker ?? throw new ArgumentNullException(nameof(invoker));
this.uniformLocations = new Dictionary<string, int>(InitialSizeCapacity);
this.nameToHeaderMap = [];
}

Expand Down Expand Up @@ -106,8 +101,6 @@ public void SetShaderProgram(IShaderProgram program)
throw new ArgumentException($"The specified {nameof(program)} parameter is not of type {nameof(IOpenGLShaderProgram)}.", nameof(program));
}

this.uniformLocations.Clear();

this.boundProgram = glProgram;
this.boundProgram.Bind();
}
Expand Down Expand Up @@ -254,18 +247,6 @@ private bool TryGetUniformLocation(string name, out int location)
return false;
}

if (!this.uniformLocations.TryGetValue(name, out location))
{
location = this.boundProgram.GetUniformLocation(name);

if (location == -1)
{
return false;
}

this.uniformLocations.Add(name, location);
}

return true;
return this.boundProgram.TryGetUniformLocation(name, out location);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@ public interface IOpenGLShaderProgram : IShaderProgram
{
void Bind();

int GetUniformLocation(string name);
bool TryGetUniformLocation(string name, out int location);
}
20 changes: 16 additions & 4 deletions FinalEngine.Rendering.OpenGL/Pipeline/OpenGLShaderProgram.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,16 @@ public class OpenGLShaderProgram : IOpenGLShaderProgram, IDisposable
{
private readonly IOpenGLInvoker invoker;

private readonly Dictionary<string, int> uniformNameToLocationMap;

private int rendererID;

public OpenGLShaderProgram(IOpenGLInvoker invoker, IReadOnlyCollection<IOpenGLShader> shaders)
{
ArgumentNullException.ThrowIfNull(shaders, nameof(shaders));

this.invoker = invoker ?? throw new ArgumentNullException(nameof(invoker));
this.uniformNameToLocationMap = [];

this.rendererID = this.invoker.CreateProgram();

Expand Down Expand Up @@ -63,12 +66,21 @@ public void Dispose()
GC.SuppressFinalize(this);
}

public int GetUniformLocation(string name)
public bool TryGetUniformLocation(string name, out int location)
{
ObjectDisposedException.ThrowIf(this.IsDisposed, this);
ArgumentException.ThrowIfNullOrWhiteSpace(name, nameof(name));
if (!this.uniformNameToLocationMap.TryGetValue(name, out location))
{
location = this.invoker.GetUniformLocation(this.rendererID, name);

if (location == -1)
{
return false;
}

this.uniformNameToLocationMap.Add(name, location);
}

return this.invoker.GetUniformLocation(this.rendererID, name);
return true;
}

protected virtual void Dispose(bool disposing)
Expand Down
30 changes: 30 additions & 0 deletions FinalEngine.Rendering/Geometry/Material.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,34 @@ public void Bind(IPipeline pipeline)
pipeline.SetTexture(this.NormalTexture, 2);
pipeline.SetTexture(this.EmissionTexture, 3);
}

public bool Equals(Material? other)
{
if (other == null)
{
return false;
}

return ReferenceEquals(this.DiffuseTexture, other.DiffuseTexture) &&
ReferenceEquals(this.SpecularTexture, other.SpecularTexture) &&
ReferenceEquals(this.NormalTexture, other.NormalTexture) &&
ReferenceEquals(this.EmissionTexture, other.EmissionTexture) &&
this.Shininess == other.Shininess;
}

public override bool Equals(object? obj)
{
return obj is Material material && this.Equals(material);
}

public override int GetHashCode()
{
const int accumulator = 17;

return (this.DiffuseTexture.GetHashCode() * accumulator) +
(this.SpecularTexture.GetHashCode() * accumulator) +
(this.NormalTexture.GetHashCode() * accumulator) +
(this.EmissionTexture.GetHashCode() * accumulator) +
(this.Shininess.GetHashCode() * accumulator);
}
}
7 changes: 6 additions & 1 deletion FinalEngine.Rendering/Loaders/Models/ModelResourceLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,12 @@ public override Model LoadResource(string filePath)
var flags = PostProcessSteps.Triangulate |
PostProcessSteps.FlipUVs |
PostProcessSteps.GenerateNormals |
PostProcessSteps.CalculateTangentSpace;
PostProcessSteps.CalculateTangentSpace |
PostProcessSteps.OptimizeGraph |
PostProcessSteps.OptimizeMeshes |
PostProcessSteps.JoinIdenticalVertices |
PostProcessSteps.RemoveRedundantMaterials |
PostProcessSteps.SplitLargeMeshes;

var scene = context.ImportFile(filePath, flags);

Expand Down
50 changes: 15 additions & 35 deletions FinalEngine.Rendering/Renderers/GeometryRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,37 +11,37 @@ namespace FinalEngine.Rendering.Renderers;

public sealed class GeometryRenderer : IRenderQueue<RenderModel>, IRenderQueue<Model>, IGeometryRenderer
{
private readonly Dictionary<RenderModel, IEnumerable<Transform>> modelToTransformMap;
private readonly Dictionary<IMaterial, IList<RenderModel>> materialToRenderModelMap;

private readonly IRenderDevice renderDevice;

public GeometryRenderer(IRenderDevice renderDevice)
{
this.renderDevice = renderDevice ?? throw new ArgumentNullException(nameof(renderDevice));
this.modelToTransformMap = [];
this.materialToRenderModelMap = [];
}

public bool CanRender
{
get { return this.modelToTransformMap.Count != 0; }
get { return this.materialToRenderModelMap.Count != 0; }
}

public void Clear()
{
this.modelToTransformMap.Clear();
this.materialToRenderModelMap.Clear();
}

public void Enqueue(RenderModel renderable)
{
ArgumentNullException.ThrowIfNull(renderable, nameof(renderable));

if (!this.modelToTransformMap.TryGetValue(renderable, out var batch))
if (!this.materialToRenderModelMap.TryGetValue(renderable.Material, out var batch))
{
batch = new List<Transform>();
this.modelToTransformMap.Add(renderable, batch);
batch = new List<RenderModel>();
this.materialToRenderModelMap.Add(renderable.Material, batch);
}

((IList<Transform>)batch).Add(renderable.Transform);
batch.Add(renderable);
}

public void Enqueue(Model renderable)
Expand All @@ -61,20 +61,17 @@ public void Enqueue(Model renderable)

public void Render()
{
foreach (var kvp in this.modelToTransformMap)
foreach (var kvp in this.materialToRenderModelMap)
{
var model = kvp.Key;
var material = kvp.Key;
var batch = kvp.Value;

if (!this.TryPrepareModel(model))
{
continue;
}
material.Bind(this.renderDevice.Pipeline);

foreach (var transform in batch)
foreach (var renderModel in batch)
{
this.UpdateUniforms(transform);
this.RenderBatchInstance(model.Mesh);
this.UpdateUniforms(renderModel.Transform);
this.RenderBatchInstance(renderModel.Mesh);
}
}
}
Expand All @@ -86,25 +83,8 @@ private void RenderBatchInstance(IMesh? mesh)
return;
}

mesh.Draw(this.renderDevice);
}

private bool TryPrepareModel(RenderModel model)
{
ArgumentNullException.ThrowIfNull(model, nameof(model));

var mesh = model.Mesh;
var material = model.Material;

if (mesh == null)
{
return false;
}

material.Bind(this.renderDevice.Pipeline);
mesh.Bind(this.renderDevice.InputAssembler);

return true;
mesh.Draw(this.renderDevice);
}

private void UpdateUniforms(Transform transform)
Expand Down
31 changes: 19 additions & 12 deletions FinalEngine.Rendering/Resources/Shaders/Includes/lighting.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -44,34 +44,41 @@ struct SpotLight
float outerRadius;
};

uniform bool u_test;

vec3 CalculateLight(LightBase light, Material material, vec3 direction, vec3 normal, vec3 viewPosition, vec3 fragPosition, vec2 texCoord)
{
normal = normalize(normal);
direction = normalize(direction);

vec3 diffuseColor = vec3(0, 0, 0);
vec3 specularColor = vec3(0, 0, 0);

// As the angle widens, diffuse shading decreases.
float diffuseShading = max(dot(direction, normal), 0.0);
vec3 diffuseColor = diffuseShading * light.color * light.intensity * texture(material.diffuseTexture, texCoord).rgb;

// Now let's measure the angle between the normal and halfway point of the light and view direction.
vec3 viewDirection = normalize(viewPosition - fragPosition);
vec3 halfWayDirection = normalize(direction + viewDirection);
if (diffuseShading > 0)
{
diffuseColor = diffuseShading * light.color * light.intensity * texture(material.diffuseTexture, texCoord).rgb;

// Now let's measure the angle between the normal and halfway point of the light and view direction.
vec3 viewDirection = normalize(viewPosition - fragPosition);
vec3 halfWayDirection = normalize(direction + viewDirection);

// As the angle widens, specular shading decreases.
// This is why we raise to the power of shininess.
float specularShading = pow(max(dot(normal, halfWayDirection), 0.0), material.shininess);
vec3 specularColor = specularShading * light.color * light.intensity * texture(material.specularTexture, texCoord).rgb;
// As the angle widens, specular shading decreases.
// This is why we raise to the power of shininess.
float specularShading = pow(max(dot(normal, halfWayDirection), 0.0), material.shininess);

if (specularShading > 0)
{
specularColor = specularShading * light.color * light.intensity * texture(material.specularTexture, texCoord).rgb;
}
}

// Calculate emission map here as it's a lighting effect.
vec3 emissionColor = texture(material.emissionTexture, texCoord).rgb;

return diffuseColor + specularColor + emissionColor;
}



vec3 CalculateDirectionalLight(DirectionalLight light, Material material, vec3 normal, vec3 viewPosition, vec3 fragPosition, vec2 texCoord)
{
return CalculateLight(light.base, material, -light.direction, normal, viewPosition, fragPosition, texCoord);
Expand Down

0 comments on commit 9d14efc

Please sign in to comment.