Skip to content

Commit

Permalink
adds shader includes, configures publish build, fixes typos and other…
Browse files Browse the repository at this point in the history
… small stuff
  • Loading branch information
BoyBaykiller committed Oct 10, 2021
1 parent 614bd53 commit 1fa8e0f
Show file tree
Hide file tree
Showing 15 changed files with 231 additions and 195 deletions.
37 changes: 22 additions & 15 deletions OpenTK-PathTracer/Src/CSharp/Helper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ namespace OpenTK_PathTracer
{
static class Helper
{
public const string SHADER_DIRECTORY_PATH = "Res/Shaders/";
public static readonly int APIMajor = (int)char.GetNumericValue(GL.GetString(StringName.Version)[0]);
public static readonly int APIMinor = (int)char.GetNumericValue(GL.GetString(StringName.Version)[2]);

public static T[] AddArray<T>(this T[] arr0, T[] arr1) where T : struct
{
int oldLength = arr0.Length;
Expand Down Expand Up @@ -61,39 +65,42 @@ public static void ParallelLoadCubemapImages(Texture texture, string[] paths, Si
}
}


public static readonly int APIMajor = (int)char.GetNumericValue(GL.GetString(StringName.Version)[0]);
public static readonly int APIMinor = (int)char.GetNumericValue(GL.GetString(StringName.Version)[2]);

private static IEnumerable<string> GetExtensions()
{
for (int i = 0; i < GL.GetInteger(GetPName.NumExtensions); i++)
yield return GL.GetString(StringNameIndexed.Extensions, i);
}

private static readonly HashSet<string> extensions = new HashSet<string>(GetExtensions());
private static readonly HashSet<string> glExtensions = new HashSet<string>(GetExtensions());


/// <summary>
/// Checks if a extensions is available
/// Extensions are not guaranteed to be part of any OpenGL version. Some of them are widely implemented on any hardware, others are supported only on specific vendors like NVIDIA and newer hardware.
/// </summary>
/// <param name="extension">The extension to check against. Examples: GL_ARB_bindless_texture or WGL_EXT_swap_control</param>
/// <returns></returns>
/// <returns>True if the extension is available</returns>
public static bool IsExtensionsAvailable(string extension)
{
return extensions.Contains(extension);
return glExtensions.Contains(extension);
}

/// <summary>
/// Checks if a core extension is available
/// Core Extensions are those which are core in a specific version and are very likely to be supported in following releases as well. There functionality may also be available in lower GL versions.
/// See all core extensions <see href="https://www.khronos.org/opengl/wiki/History_of_OpenGL#Summary_of_version_changes">here</see>
/// </summary>
/// <param name="extension">The extension to check against. Examples: GL_ARB_direct_state_access or GL_ARB_seamless_cube_map</param>
/// <param name="major">The major API version the extension became part of the core profile</param>
/// <param name="minor">The minor API version the extension became part of the core profile</param>
/// <returns></returns>
public static bool IsCoreExtensionAvailable(string extension, int major, int minor)
/// <param name="extension">The extension to check against. Examples: GL_ARB_direct_state_access or GL_ARB_compute_shader</param>
/// <param name="firstMajor">The major API version the extension became part of the core profile</param>
/// <param name="firstMinor">The minor API version the extension became part of the core profile</param>
/// <param name="lastMajor">The last major API version the extension was part of the core profile</param>
/// <param name="lastMinor">The last minor API version the extension was part of the core profile</param>
/// <returns>True if this OpenGL version is in the specified range or the extension is otherwise available</returns>
public static bool IsCoreExtensionAvailable(string extension, int firstMajor, int firstMinor, int lastMajor = 4, int lastMinor = 6)
{
return (Convert.ToInt32($"{APIMajor}{APIMinor}") >= Convert.ToInt32($"{major}{minor}")) || extension.Contains(extension);
int firstVersion = Convert.ToInt32($"{firstMajor}{firstMinor}");
int lastVersion = Convert.ToInt32($"{lastMajor}{lastMinor}");
int thisVersion = Convert.ToInt32($"{APIMajor}{APIMinor}");

return (thisVersion >= firstVersion && thisVersion <= lastVersion) || IsExtensionsAvailable(extension);
}
}
}
6 changes: 3 additions & 3 deletions OpenTK-PathTracer/Src/CSharp/ImGui/ImGuiController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -166,9 +166,9 @@ private void UpdateImGuiInput(GameWindow wnd)
{
ImGuiIOPtr io = ImGui.GetIO();

io.MouseDown[0] = MouseManager.LeftButton == ButtonState.Pressed;
io.MouseDown[1] = MouseManager.RightButton == ButtonState.Pressed;
io.MouseDown[2] = MouseManager.MiddleButton == ButtonState.Pressed;
io.MouseDown[0] = MouseManager.IsButtonTouched(MouseButton.Left);
io.MouseDown[1] = MouseManager.IsButtonTouched(MouseButton.Right);
io.MouseDown[2] = MouseManager.IsButtonTouched(MouseButton.Middle);

System.Drawing.Point screenPoint = new System.Drawing.Point(MouseManager.WindowPositionX, MouseManager.WindowPositionY);
System.Drawing.Point point = wnd.PointToClient(screenPoint);
Expand Down
2 changes: 1 addition & 1 deletion OpenTK-PathTracer/Src/CSharp/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ static void Main()
try
{
MainWindow mainWindow = new MainWindow();
mainWindow.Run(144);
mainWindow.Run(Math.Min(OpenTK.DisplayDevice.Default.RefreshRate, 144));
}
catch (Exception ex)
{
Expand Down
2 changes: 1 addition & 1 deletion OpenTK-PathTracer/Src/CSharp/Ray.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public bool IntersectsAABB(AABB aabb, out float t1, out float t2)

public static Ray GetWorldSpaceRay(Matrix4 inverseProjection, Matrix4 inverseView, Vector3 worldPosition, Vector2 normalizedDeviceCoords)
{
Vector4 _rayEye = new Vector4(normalizedDeviceCoords.X, normalizedDeviceCoords.Y, -1.0f, 1.0f) * inverseProjection; _rayEye.Z = -1.0f; _rayEye.W = 0.0f; // vector * matrix, because OpenTK is stupid
Vector4 _rayEye = new Vector4(normalizedDeviceCoords.X, normalizedDeviceCoords.Y, -1.0f, 1.0f) * inverseProjection; _rayEye.Z = -1.0f; _rayEye.W = 0.0f; // vector * matrix, because OpenTK...
return new Ray(worldPosition, (_rayEye * inverseView).Xyz.Normalized());
}

Expand Down
14 changes: 7 additions & 7 deletions OpenTK-PathTracer/Src/CSharp/Render/AtmosphericScatterer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,15 @@ public float DensityFallOff
}


private float _atmossphereRadius;
public float AtmossphereRadius
private float _atmosphereRadius;
public float AtmosphereRadius
{
get => _atmossphereRadius;
get => _atmosphereRadius;

set
{
shaderProgram.Upload("atmossphereRad", value);
_atmossphereRadius = value;
shaderProgram.Upload("atmosphereRad", value);
_atmosphereRadius = value;
}
}

Expand Down Expand Up @@ -114,7 +114,7 @@ public Vector3 ViewPos
public readonly Texture Result;
private readonly ShaderProgram shaderProgram;
private readonly BufferObject bufferObject;
public AtmosphericScattering(int size, int inScatteringSamples, int densitySamples, float scatteringStrength, float densityFallOff, float atmossphereRadius, Vector3 waveLengths, Vector3 lightPos, Vector3 viewPos)
public AtmosphericScattering(int size, int inScatteringSamples, int densitySamples, float scatteringStrength, float densityFallOff, float atmosphereRadius, Vector3 waveLengths, Vector3 lightPos, Vector3 viewPos)
{
Query = new Query(600);

Expand Down Expand Up @@ -147,7 +147,7 @@ public AtmosphericScattering(int size, int inScatteringSamples, int densitySampl
DensitySamples = densitySamples;
ScatteringStrength = scatteringStrength;
DensityFallOff = densityFallOff;
AtmossphereRadius = atmossphereRadius;
AtmosphereRadius = atmosphereRadius;
WaveLengths = waveLengths;
LightPos = lightPos;
ViewPos = viewPos;
Expand Down
46 changes: 24 additions & 22 deletions OpenTK-PathTracer/Src/CSharp/Render/GUI/Final.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ struct Final
public static ImGuiController ImGuiController = new ImGuiController(0, 0, "Res/imgui.ini");
private static BaseGameObject pickedObject;

private static bool IsEnvironmentAtmossphere = false;
private static bool IsEnvironmentAtmosphere = false;

public static ImGuiIOPtr ImGuiIOPtr => ImGui.GetIO();

Expand All @@ -35,13 +35,13 @@ public static void Run(MainWindow mainWindow, float frameTime, out bool frameCha
if (ImGui.CollapsingHeader("PathTracing"))
{
ImGui.Text($"VSync: {mainWindow.VSync}");
ImGui.Text($"FPS: {mainWindow.FPS}"); ImGui.SameLine(); ImGui.Text($"UPS: {mainWindow.UPS}");
ImGui.Text($"FPS: {mainWindow.FPS}"); ImGui.SameLine(); ImGui.Text($"SPS: {mainWindow.FPS * mainWindow.PathTracer.SPP}"); ImGui.SameLine(); ImGui.Text($"UPS: {mainWindow.UPS}");
ImGui.Checkbox("RenderInBackground", ref mainWindow.IsRenderInBackground);
int temp = mainWindow.PathTracer.SSP;
if (ImGui.SliderInt("SSP", ref temp, 1, 10))
int temp = mainWindow.PathTracer.SPP;
if (ImGui.SliderInt("SPP", ref temp, 1, 10))
{
frameChanged = true;
mainWindow.PathTracer.SSP = temp;
mainWindow.PathTracer.SPP = temp;
}


Expand Down Expand Up @@ -77,10 +77,10 @@ public static void Run(MainWindow mainWindow, float frameTime, out bool frameCha
{
bool hadInput = false;

if (ImGui.Checkbox("Atmossphere", ref IsEnvironmentAtmossphere))
if (ImGui.Checkbox("Atmosphere", ref IsEnvironmentAtmosphere))
{
hadInput = true;
if (!IsEnvironmentAtmossphere)
if (!IsEnvironmentAtmosphere)
{
mainWindow.PathTracer.EnvironmentMap = mainWindow.SkyBox;
}
Expand All @@ -91,7 +91,7 @@ public static void Run(MainWindow mainWindow, float frameTime, out bool frameCha
}
}

if (IsEnvironmentAtmossphere)
if (IsEnvironmentAtmosphere)
{
ImGui.Text($"Computation Time: {MathF.Round(mainWindow.AtmosphericScatterer.Query.ElapsedMilliseconds, 2)} ms");

Expand Down Expand Up @@ -127,11 +127,11 @@ public static void Run(MainWindow mainWindow, float frameTime, out bool frameCha
mainWindow.AtmosphericScatterer.Run();
}

temp = mainWindow.AtmosphericScatterer.AtmossphereRadius;
if (ImGui.DragFloat("AtmossphereRadius", ref temp, 0.2f, 0.1f, 100))
temp = mainWindow.AtmosphericScatterer.AtmosphereRadius;
if (ImGui.DragFloat("AtmosphereRadius", ref temp, 0.2f, 0.1f, 100))
{
hadInput = true;
mainWindow.AtmosphericScatterer.AtmossphereRadius = temp;
mainWindow.AtmosphericScatterer.AtmosphereRadius = temp;
mainWindow.AtmosphericScatterer.Run();
}

Expand Down Expand Up @@ -228,29 +228,31 @@ public static void Update(MainWindow mainWindow)
if (MouseManager.IsButtonTouched(MouseButton.Left))
{
System.Drawing.Point windowSpaceCoords = mainWindow.PointToClient(new System.Drawing.Point(Mouse.GetCursorState().X, Mouse.GetCursorState().Y)); windowSpaceCoords.Y = mainWindow.Height - windowSpaceCoords.Y; // [0, Width][0, Height]
Vector2 normalizedDeviceCoords = Vector2.Divide(new Vector2(windowSpaceCoords.X, windowSpaceCoords.Y), new Vector2(mainWindow.Width, mainWindow.Height)) * 2.0f - new Vector2(1.0f);
Vector2 normalizedDeviceCoords = Vector2.Divide(new Vector2(windowSpaceCoords.X, windowSpaceCoords.Y), new Vector2(mainWindow.Width, mainWindow.Height)) * 2.0f - new Vector2(1.0f); // [-1.0, 1.0][-1.0, 1.0]
Ray rayWorld = Ray.GetWorldSpaceRay(mainWindow.inverseProjection, mainWindow.Camera.View.Inverted(), mainWindow.Camera.Position, normalizedDeviceCoords);

mainWindow.RayTrace(rayWorld, out pickedObject, out _, out _);

/// DEBUG
/// Comment out to test object deletion (Spheres in this case)
//if (pickedObject is Sphere sphere)
//{
// /// Procedure to properly delete objects

// /// Delete from GPU
// int start = pickedObject.BufferOffset + Sphere.GPU_INSTANCE_SIZE;
// int size = Sphere.GPU_INSTANCE_SIZE * mainWindow.PathTracer.NumSpheres - start;
// int bufferSpheresEnd = Sphere.GPU_INSTANCE_SIZE * mainWindow.PathTracer.NumSpheres - start;

// /// Copys data from GPU to CPU and then with tiny offset back to GPU
// mainWindow.GameObjectsUBO.GetSubData(start, size, out IntPtr followingSphereData);
// mainWindow.GameObjectsUBO.SubData(pickedObject.BufferOffset, size, followingSphereData); // override selected sphere
// /// Shift following Spheres backwards to override the picked one (just using the last sphere to overriding the picked sphere should work as well !?)
// mainWindow.GameObjectsUBO.GetSubData(start, bufferSpheresEnd, out IntPtr followingSphereData);
// mainWindow.GameObjectsUBO.SubData(pickedObject.BufferOffset, bufferSpheresEnd, followingSphereData); // override selected sphere
// System.Runtime.InteropServices.Marshal.FreeHGlobal(followingSphereData);

// /// Delete from CPU
// mainWindow.GameObjects.Remove(sphere);
// mainWindow.PathTracer.NumSpheres--;

// for (int i = 0; i < mainWindow.GameObjects.Count; i++)
// if (mainWindow.GameObjects[i] is Sphere temp && temp != null && temp.Instance > sphere.Instance)
// if (mainWindow.GameObjects[i] is Sphere temp && temp is not null && temp.Instance > sphere.Instance)
// temp.Instance--;

// mainWindow.PathTracer.ThisRenderNumFrame = 0;
Expand All @@ -260,11 +262,11 @@ public static void Update(MainWindow mainWindow)
}
}

private static OpenTK.Vector3 NVector3ToVector3(System.Numerics.Vector3 v) => new OpenTK.Vector3(v.X, v.Y, v.Z);
private static System.Numerics.Vector3 Vector3ToNVector3(OpenTK.Vector3 v) => new System.Numerics.Vector3(v.X, v.Y, v.Z);
private static Vector3 NVector3ToVector3(System.Numerics.Vector3 v) => new Vector3(v.X, v.Y, v.Z);
private static System.Numerics.Vector3 Vector3ToNVector3(Vector3 v) => new System.Numerics.Vector3(v.X, v.Y, v.Z);

private static OpenTK.Vector2 NVector2ToVector2(System.Numerics.Vector2 v) => new OpenTK.Vector2(v.X, v.Y);
private static System.Numerics.Vector2 Vector2ToNVector2(OpenTK.Vector2 v) => new System.Numerics.Vector2(v.X, v.Y);
private static Vector2 NVector2ToVector2(System.Numerics.Vector2 v) => new Vector2(v.X, v.Y);
private static System.Numerics.Vector2 Vector2ToNVector2(Vector2 v) => new System.Numerics.Vector2(v.X, v.Y);

public static void SetSize(int width, int height)
{
Expand Down
45 changes: 38 additions & 7 deletions OpenTK-PathTracer/Src/CSharp/Render/Objects/ShaderProgram.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using System;
using System.IO;
using System.Linq;
using System.Text;
using OpenTK;
using OpenTK.Graphics.OpenGL4;

Expand All @@ -15,6 +17,8 @@ public Shader(ShaderType shaderType, string sourceCode)
ShaderType = shaderType;

ID = GL.CreateShader(shaderType);

sourceCode = PreProcessIncludes(sourceCode);
GL.ShaderSource(ID, sourceCode);
GL.CompileShader(ID);

Expand All @@ -23,6 +27,33 @@ public Shader(ShaderType shaderType, string sourceCode)
Console.WriteLine(compileInfo);
}

/// <summary>
/// Searches the string for #include and includes the specified Path. Example: #include PathTracing/fragCompute
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
private static string PreProcessIncludes(string s)
{
StringBuilder includedContent = new StringBuilder(s.Length + 2000);
using StringReader stringReader = new StringReader(s);

string line;
while ((line = stringReader.ReadLine()) is not null) // dont use != because it could be overriden
{
string trimmed = line.Trim();
if (trimmed.Length > 9 && trimmed.Substring(0, 9) == "#include ")
{
string filePath = $"{Helper.SHADER_DIRECTORY_PATH}{trimmed.Substring(9, trimmed.Length - 9)}.glsl";
includedContent.Append(PreProcessIncludes(File.ReadAllText(filePath)));
}
else
{
includedContent.AppendLine(line);
}
}
return includedContent.ToString();
}

public void Dispose()
{
GL.DeleteShader(ID);
Expand All @@ -31,13 +62,13 @@ public void Dispose()

class ShaderProgram : IDisposable
{
public readonly int ID;

private static int lastBindedID = -1;

public readonly int ID;
public ShaderProgram(params Shader[] shaders)
{
if (shaders is null || shaders.Length == 0 || !shaders.All(s => s.ID != 0))
throw new IndexOutOfRangeException($"Shader array is empty or null. Or one shader has ID 0");
throw new IndexOutOfRangeException($"Shader array is empty or null. Or at least one shader has ID 0");

if(!shaders.All(s => shaders.All(s1 => s.ID == s1.ID || s1.ShaderType != s.ShaderType)))
throw new Exception($"A ShaderProgram can only hold one instance of every ShaderType. Validate the shader array.");
Expand All @@ -64,12 +95,12 @@ public void Use()
}
}

public static void Use(int ID)
public static void Use(int id)
{
if (lastBindedID != ID)
if (lastBindedID != id)
{
GL.UseProgram(ID);
lastBindedID = ID;
GL.UseProgram(id);
lastBindedID = id;
}
}

Expand Down
Loading

0 comments on commit 1fa8e0f

Please sign in to comment.