.
This commit is contained in:
@@ -117,7 +117,7 @@ public sealed class Engine
|
|||||||
|
|
||||||
Renderer.EndFrame();
|
Renderer.EndFrame();
|
||||||
|
|
||||||
Presenter!.Present(Renderer.TextureInternal);
|
Presenter!.Present(Renderer.RenderTexture);
|
||||||
Presenter!.Render();
|
Presenter!.Render();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,8 @@ namespace Engine.Graphics;
|
|||||||
|
|
||||||
public class Renderer
|
public class Renderer
|
||||||
{
|
{
|
||||||
internal Texture.Texture TextureInternal => _framebuffer.TextureInternal!;
|
internal Framebuffer.Framebuffer RenderFramebuffer => _framebuffer;
|
||||||
|
internal Texture.Texture RenderTexture => _framebuffer.TextureInternal!;
|
||||||
|
|
||||||
public QuadRenderer QuadRenderer { get; }
|
public QuadRenderer QuadRenderer { get; }
|
||||||
public GlobalMeshRenderer GlobalMeshRenderer { get; }
|
public GlobalMeshRenderer GlobalMeshRenderer { get; }
|
||||||
@@ -55,12 +56,10 @@ public class Renderer
|
|||||||
public void EnsureRenderThread()
|
public void EnsureRenderThread()
|
||||||
{
|
{
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
if (Thread.CurrentThread == _renderThread)
|
if (Thread.CurrentThread != _renderThread)
|
||||||
{
|
{
|
||||||
return;
|
throw new InvalidOperationException("Not on render thread");
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new InvalidOperationException("Not on render thread");
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -58,21 +58,21 @@ public class Hierarchy<T>
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddChild(T parEnt, T parChild)
|
public void AddChild(T parParent, T parChild)
|
||||||
{
|
{
|
||||||
SetParent(parChild, parEnt);
|
SetParent(parChild, parParent);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetParent(T parChild, T? parEnt)
|
private void SetParent(T parChild, T? parParent)
|
||||||
{
|
{
|
||||||
if (parChild.Equals(parEnt))
|
if (parChild.Equals(parParent))
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Child cannot be parent");
|
throw new InvalidOperationException("Child cannot be parent");
|
||||||
}
|
}
|
||||||
|
|
||||||
_hierarchyActions.Enqueue(() =>
|
_hierarchyActions.Enqueue(() =>
|
||||||
{
|
{
|
||||||
if (IsInHierarchy(parChild, parEnt))
|
if (IsInHierarchy(parChild, parParent))
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("Parent is a child of child");
|
throw new InvalidOperationException("Parent is a child of child");
|
||||||
}
|
}
|
||||||
@@ -80,8 +80,8 @@ public class Hierarchy<T>
|
|||||||
var oldParent = GetParent(parChild);
|
var oldParent = GetParent(parChild);
|
||||||
_childrenLookup[oldParent].Remove(parChild);
|
_childrenLookup[oldParent].Remove(parChild);
|
||||||
|
|
||||||
_childrenLookup[parEnt].Add(parChild);
|
_childrenLookup[parParent].Add(parChild);
|
||||||
_parentLookup[parChild] = parEnt;
|
_parentLookup[parChild] = parParent;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -87,6 +87,12 @@ public class Scene : IUpdate, IRender
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void AddChild(GameObject parParent, GameObject parGameObject)
|
||||||
|
{
|
||||||
|
Add(parGameObject);
|
||||||
|
Hierarchy.AddChild(parParent, parGameObject);
|
||||||
|
}
|
||||||
|
|
||||||
public void Remove(GameObject parGameObject)
|
public void Remove(GameObject parGameObject)
|
||||||
{
|
{
|
||||||
Hierarchy.Remove(parGameObject);
|
Hierarchy.Remove(parGameObject);
|
||||||
|
|||||||
@@ -63,13 +63,12 @@ public class Window : IPresenter
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
GL.ClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
GL.BlitNamedFramebuffer(_engine.Renderer.RenderFramebuffer.Handle, 0,
|
||||||
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
|
0, parTexture.Height, parTexture.Width, 0,
|
||||||
|
0, 0, Width, Height,
|
||||||
var texture = (Texture)parTexture;
|
ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit,
|
||||||
_engine.Renderer.QuadRenderer.Commit(Matrix4.CreateScale(2f), Vector4.One, texture);
|
BlitFramebufferFilter.Nearest
|
||||||
_engine.Renderer.QuadRenderer.Render(Matrix4.Identity, Matrix4.Identity);
|
);
|
||||||
_engine.Renderer.QuadRenderer.Reset();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,34 +37,50 @@ const vec3 ConsoleColorVec3[16] = vec3[](
|
|||||||
vec3(1.0, 1.0, 1.0) // White
|
vec3(1.0, 1.0, 1.0) // White
|
||||||
);
|
);
|
||||||
|
|
||||||
// RGB to LAB conversion (simplified approximation)
|
vec3 srgbToLinear(vec3 color) {
|
||||||
vec3 rgb2lab(vec3 x) {
|
return mix(color / 12.92, pow((color + 0.055) / 1.055, vec3(2.4)), step(0.04045, color));
|
||||||
const float epsilon = 0.008856;
|
}
|
||||||
const float k = 903.3;
|
|
||||||
vec3 fx;
|
vec3 rgbToXyz(vec3 color) {
|
||||||
fx.x = x.x > epsilon ? pow(x.x, 1.0 / 3.0) : (k * x.x + 16.0) / 116.0;
|
const mat3 rgbToXyzMatrix = mat3(
|
||||||
fx.y = x.y > epsilon ? pow(x.y, 1.0 / 3.0) : (k * x.y + 16.0) / 116.0;
|
0.4124564, 0.3575761, 0.1804375,
|
||||||
fx.z = x.z > epsilon ? pow(x.z, 1.0 / 3.0) : (k * x.z + 16.0) / 116.0;
|
0.2126729, 0.7151522, 0.0721750,
|
||||||
return fx;
|
0.0193339, 0.1191920, 0.9503041
|
||||||
|
);
|
||||||
|
return rgbToXyzMatrix * color;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 xyzToLab(vec3 xyz) {
|
||||||
|
const vec3 whitePoint = vec3(0.95047, 1.0, 1.08883); // D65 white point
|
||||||
|
xyz = xyz / whitePoint;
|
||||||
|
|
||||||
|
vec3 f = mix(pow(xyz, vec3(1.0 / 3.0)), 7.787 * xyz + 16.0 / 116.0, step(0.008856, xyz));
|
||||||
|
return vec3(
|
||||||
|
(116.0 * f.y) - 16.0,
|
||||||
|
500.0 * (f.x - f.y),
|
||||||
|
200.0 * (f.y - f.z)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 rgb2hsv(vec3 c)
|
||||||
|
{
|
||||||
|
vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
|
||||||
|
vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
|
||||||
|
vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
|
||||||
|
|
||||||
|
float d = q.x - min(q.w, q.y);
|
||||||
|
float e = 1.0e-10;
|
||||||
|
return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Perceptually weighted color difference (CIEDE2000-inspired)
|
|
||||||
float perceptualColorDistance(vec3 color1, vec3 color2) {
|
float perceptualColorDistance(vec3 color1, vec3 color2) {
|
||||||
vec3 lab1 = rgb2lab(color1);
|
vec3 lab1 = xyzToLab(rgbToXyz(srgbToLinear(color1)));
|
||||||
vec3 lab2 = rgb2lab(color2);
|
vec3 lab2 = xyzToLab(rgbToXyz(srgbToLinear(color2)));
|
||||||
|
vec3 delta = lab1 - lab2;
|
||||||
|
|
||||||
// Compute LAB-like color difference with perceptual weighting
|
return dot(delta, delta);
|
||||||
float deltaL = lab1.x - lab2.x;
|
|
||||||
float deltaA = lab1.y - lab2.y;
|
|
||||||
float deltaB = lab1.z - lab2.z;
|
|
||||||
|
|
||||||
// Perceptual weighting
|
|
||||||
return deltaL * deltaL * 1.0 + // Lightness difference
|
|
||||||
deltaA * deltaA * 1.5 + // Green-Red difference
|
|
||||||
deltaB * deltaB * 1.5; // Blue-Yellow difference
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Advanced color matching considering multiple color attributes
|
|
||||||
int findMostPerceptuallyAccurateColor(vec3 color) {
|
int findMostPerceptuallyAccurateColor(vec3 color) {
|
||||||
int bestMatchIndex = 0;
|
int bestMatchIndex = 0;
|
||||||
float minDistance = perceptualColorDistance(color, ConsoleColorVec3[0]);
|
float minDistance = perceptualColorDistance(color, ConsoleColorVec3[0]);
|
||||||
|
|||||||
Reference in New Issue
Block a user