mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/PCK-Studio.git
synced 2026-06-23 21:15:35 +00:00
Move Common functionality to Core project & rendering and Model support as well
This commit is contained in:
176
PckStudio.Rendering/Shader/ShaderProgram.cs
Normal file
176
PckStudio.Rendering/Shader/ShaderProgram.cs
Normal file
@@ -0,0 +1,176 @@
|
||||
/* Copyright (c) 2024-present miku-666
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1.The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
**/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics.OpenGL;
|
||||
|
||||
namespace PckStudio.Rendering.Shader
|
||||
{
|
||||
public sealed class ShaderProgram : IDisposable
|
||||
{
|
||||
private int _programId;
|
||||
private Dictionary<string, int> locationCache = new Dictionary<string, int>();
|
||||
|
||||
private ShaderProgram(int programId)
|
||||
{
|
||||
_programId = programId;
|
||||
}
|
||||
|
||||
public void Bind()
|
||||
{
|
||||
GL.UseProgram(_programId);
|
||||
}
|
||||
|
||||
public void Unbind()
|
||||
{
|
||||
GL.UseProgram(0);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Unbind();
|
||||
GL.DeleteProgram(_programId);
|
||||
}
|
||||
|
||||
public void SetUniform1(string name, int value)
|
||||
{
|
||||
int location = GetUniformLocation(name);
|
||||
GL.Uniform1(location, value);
|
||||
}
|
||||
|
||||
public void SetUniform1(string name, float value)
|
||||
{
|
||||
int location = GetUniformLocation(name);
|
||||
GL.Uniform1(location, value);
|
||||
}
|
||||
|
||||
public void SetUniform2(string name, Size value) => SetUniform2(name, new Vector2(value.Width, value.Height));
|
||||
|
||||
public void SetUniform2(string name, Vector2 value)
|
||||
{
|
||||
int location = GetUniformLocation(name);
|
||||
GL.Uniform2(location, value);
|
||||
}
|
||||
|
||||
public void SetUniform4(string name, Vector4 value)
|
||||
{
|
||||
int location = GetUniformLocation(name);
|
||||
GL.Uniform4(location, value);
|
||||
}
|
||||
|
||||
public void SetUniform4(string name, Color color)
|
||||
{
|
||||
int location = GetUniformLocation(name);
|
||||
GL.Uniform4(location, color);
|
||||
}
|
||||
|
||||
public void SetUniformMat4(string name, ref Matrix4 matrix)
|
||||
{
|
||||
int location = GetUniformLocation(name);
|
||||
GL.UniformMatrix4(location, false, ref matrix);
|
||||
}
|
||||
|
||||
private int GetUniformLocation(string name)
|
||||
{
|
||||
if (locationCache.ContainsKey(name))
|
||||
return locationCache[name];
|
||||
Debug.Assert(false, $"Uniform location '{name}' not found");
|
||||
return -1;
|
||||
}
|
||||
|
||||
private bool Link()
|
||||
{
|
||||
GL.LinkProgram(_programId);
|
||||
GL.GetProgram(_programId, GetProgramParameterName.LinkStatus, out int status);
|
||||
bool success = status != 0;
|
||||
if (!success)
|
||||
Debug.WriteLine(GL.GetProgramInfoLog(_programId), category: nameof(ShaderProgram));
|
||||
GetActiveUniformLocations();
|
||||
return success;
|
||||
}
|
||||
|
||||
private void GetActiveUniformLocations()
|
||||
{
|
||||
GL.GetProgram(_programId, GetProgramParameterName.ActiveUniforms, out int count);
|
||||
Debug.WriteLine("Active Uniforms: {0}", count);
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
GL.GetActiveUniform(_programId, i, 256, out int length, out int size, out ActiveUniformType type, out string name);
|
||||
int id = GL.GetUniformLocation(_programId, name);
|
||||
Debug.Assert(id != -1);
|
||||
RegisterUniform(name, id, type);
|
||||
Debug.WriteLine("Uniform {0}(id:{1}) Type: {2} Name: {3}", i, id, type, name);
|
||||
}
|
||||
}
|
||||
|
||||
private void RegisterUniform(string name, int id, ActiveUniformType type) => locationCache.Add(name, id);
|
||||
|
||||
public bool Validate()
|
||||
{
|
||||
#if DEBUG
|
||||
GL.ValidateProgram(_programId);
|
||||
GL.GetProgram(_programId, GetProgramParameterName.ValidateStatus, out int status);
|
||||
bool success = status != 0;
|
||||
if (!success)
|
||||
Debug.WriteLine(GL.GetProgramInfoLog(_programId), category: nameof(ShaderProgram));
|
||||
return success;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static ShaderProgram Create(string vertexSource, string fragmentSource)
|
||||
{
|
||||
return Create(
|
||||
new ShaderSource(ShaderType.VertexShader, vertexSource),
|
||||
new ShaderSource(ShaderType.FragmentShader, fragmentSource)
|
||||
);
|
||||
}
|
||||
|
||||
public static ShaderProgram Create(params ShaderSource[] shaderSources)
|
||||
{
|
||||
int programId = GL.CreateProgram();
|
||||
|
||||
var shaderObjects = new List<ShaderObject>(shaderSources.Length);
|
||||
|
||||
foreach (ShaderSource shaderSource in shaderSources)
|
||||
{
|
||||
ShaderObject shaderObject = ShaderObject.Create(shaderSource);
|
||||
shaderObject.AttachToProgram(programId);
|
||||
shaderObjects.Add(shaderObject);
|
||||
}
|
||||
|
||||
var shader = new ShaderProgram(programId);
|
||||
bool success = shader.Link();
|
||||
Debug.Assert(success, "Shader Program linking failed.");
|
||||
|
||||
foreach (ShaderObject shaderObject in shaderObjects)
|
||||
{
|
||||
shaderObject.Delete();
|
||||
}
|
||||
return shader;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user