From 22f69204ca84af2ec8be40bef862dd39865dcd87 Mon Sep 17 00:00:00 2001
From: miku-666 <74728189+NessieHax@users.noreply.github.com>
Date: Wed, 7 Feb 2024 12:06:23 +0100
Subject: [PATCH] Separated ShaderObjects to its own class
---
PCK-Studio/PckStudio.csproj | 5 +-
PCK-Studio/Rendering/Renderer.cs | 3 +-
PCK-Studio/Rendering/Shader/ShaderObject.cs | 62 +++++++++++++
.../{Shader.cs => Shader/ShaderProgram.cs} | 49 +++++-----
.../Rendering/{ => Shader}/ShaderSource.cs | 4 +-
PCK-Studio/Rendering/SkinRenderer.cs | 89 +++++++++++++------
.../shader/skyboxFragmentShader.glsl | 3 +-
7 files changed, 161 insertions(+), 54 deletions(-)
create mode 100644 PCK-Studio/Rendering/Shader/ShaderObject.cs
rename PCK-Studio/Rendering/{Shader.cs => Shader/ShaderProgram.cs} (79%)
rename PCK-Studio/Rendering/{ => Shader}/ShaderSource.cs (83%)
diff --git a/PCK-Studio/PckStudio.csproj b/PCK-Studio/PckStudio.csproj
index 61ec8eee..5f2ab09c 100644
--- a/PCK-Studio/PckStudio.csproj
+++ b/PCK-Studio/PckStudio.csproj
@@ -159,8 +159,9 @@
-
-
+
+
+
UserControl
diff --git a/PCK-Studio/Rendering/Renderer.cs b/PCK-Studio/Rendering/Renderer.cs
index 85dd789a..84cad74d 100644
--- a/PCK-Studio/Rendering/Renderer.cs
+++ b/PCK-Studio/Rendering/Renderer.cs
@@ -16,12 +16,13 @@
* 3. This notice may not be removed or altered from any source distribution.
**/
using OpenTK.Graphics.OpenGL;
+using PckStudio.Rendering.Shader;
namespace PckStudio.Rendering
{
internal static class Renderer
{
- public static void Draw(Shader shader, RenderBuffer renderBuffer)
+ public static void Draw(ShaderProgram shader, RenderBuffer renderBuffer)
{
shader.Bind();
renderBuffer.VertexArray.Bind();
diff --git a/PCK-Studio/Rendering/Shader/ShaderObject.cs b/PCK-Studio/Rendering/Shader/ShaderObject.cs
new file mode 100644
index 00000000..1d594f3f
--- /dev/null
+++ b/PCK-Studio/Rendering/Shader/ShaderObject.cs
@@ -0,0 +1,62 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using OpenTK.Graphics.OpenGL;
+
+namespace PckStudio.Rendering.Shader
+{
+ internal class ShaderObject
+ {
+ private int _shaderId;
+ private ShaderSource _source;
+ private int _compileStatus;
+
+ internal bool CompileStatusOK => _compileStatus != 0;
+
+ private ShaderObject(ShaderSource source)
+ {
+ _shaderId = GL.CreateShader(source.Type);
+ _source = source;
+ _compileStatus = 0;
+ }
+
+ internal static ShaderObject CreateNew(ShaderSource shaderSource)
+ {
+ var shaderObject = new ShaderObject(shaderSource);
+ shaderObject.Compile();
+ if (!shaderObject.CompileStatusOK)
+ {
+ shaderObject.Delete();
+ return null;
+ }
+ return shaderObject;
+ }
+
+ internal void Delete()
+ {
+ GL.DeleteShader(_shaderId);
+ }
+
+ private void Compile()
+ {
+ GL.ShaderSource(_shaderId, _source.Source);
+ GL.CompileShader(_shaderId);
+
+ GL.GetShader(_shaderId, ShaderParameter.CompileStatus, out _compileStatus);
+
+ if (!CompileStatusOK)
+ {
+ string infoLog = GL.GetShaderInfoLog(_shaderId);
+ Debug.Fail(infoLog);
+ }
+ }
+
+ internal void AttachToProgram(int programId)
+ {
+ GL.AttachShader(programId, _shaderId);
+ }
+ }
+}
diff --git a/PCK-Studio/Rendering/Shader.cs b/PCK-Studio/Rendering/Shader/ShaderProgram.cs
similarity index 79%
rename from PCK-Studio/Rendering/Shader.cs
rename to PCK-Studio/Rendering/Shader/ShaderProgram.cs
index 67f2f613..df029499 100644
--- a/PCK-Studio/Rendering/Shader.cs
+++ b/PCK-Studio/Rendering/Shader/ShaderProgram.cs
@@ -8,14 +8,14 @@ using System.Threading.Tasks;
using OpenTK;
using OpenTK.Graphics.OpenGL;
-namespace PckStudio.Rendering
+namespace PckStudio.Rendering.Shader
{
- internal class Shader : IDisposable
+ internal class ShaderProgram : IDisposable
{
private int _programId;
private Dictionary locationCache = new Dictionary();
- private Shader(int programId)
+ private ShaderProgram(int programId)
{
_programId = programId;
}
@@ -25,7 +25,6 @@ namespace PckStudio.Rendering
GL.UseProgram(_programId);
}
- [Conditional("DEBUG")]
public void Unbind()
{
GL.UseProgram(0);
@@ -43,6 +42,12 @@ namespace PckStudio.Rendering
GL.Uniform1(location, value);
}
+ public void SetUniform1(string name, float value)
+ {
+ int location = GetUniformLocation(name);
+ GL.Uniform1(location, value);
+ }
+
public void SetUniform2(string name, Vector2 value)
{
int location = GetUniformLocation(name);
@@ -94,21 +99,13 @@ namespace PckStudio.Rendering
return shaderId;
}
- public static Shader Create(string vertexSource, string fragmentSource)
- {
- return Create(
- new ShaderSource(ShaderType.VertexShader, vertexSource),
- new ShaderSource(ShaderType.FragmentShader, fragmentSource)
- );
- }
-
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(Shader));
+ Debug.WriteLine(GL.GetProgramInfoLog(_programId), category: nameof(ShaderProgram));
return success;
}
@@ -119,33 +116,41 @@ namespace PckStudio.Rendering
GL.GetProgram(_programId, GetProgramParameterName.ValidateStatus, out int status);
bool success = status != 0;
if (!success)
- Debug.WriteLine(GL.GetProgramInfoLog(_programId), category: nameof(Shader));
+ Debug.WriteLine(GL.GetProgramInfoLog(_programId), category: nameof(ShaderProgram));
return success;
#else
return true;
#endif
}
- public static Shader Create(params ShaderSource[] shaderSources)
+ 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 shaderIds = new List(shaderSources.Length);
+ var shaderObjects = new List(shaderSources.Length);
foreach (var shaderSource in shaderSources)
{
- int shaderId = CompileShader(shaderSource.Type, shaderSource.Source);
- GL.AttachShader(programId, shaderId);
- shaderIds.Add(shaderId);
+ ShaderObject shaderObject = ShaderObject.CreateNew(shaderSource);
+ shaderObject.AttachToProgram(programId);
+ shaderObjects.Add(shaderObject);
}
- var shader = new Shader(programId);
+ var shader = new ShaderProgram(programId);
bool success = shader.Link();
Debug.Assert(success, "Shader Program linking failed.");
- foreach (var shaderId in shaderIds)
+ foreach (var shaderObject in shaderObjects)
{
- GL.DeleteShader(shaderId);
+ shaderObject.Delete();
}
return shader;
}
diff --git a/PCK-Studio/Rendering/ShaderSource.cs b/PCK-Studio/Rendering/Shader/ShaderSource.cs
similarity index 83%
rename from PCK-Studio/Rendering/ShaderSource.cs
rename to PCK-Studio/Rendering/Shader/ShaderSource.cs
index d7b9007a..f923949a 100644
--- a/PCK-Studio/Rendering/ShaderSource.cs
+++ b/PCK-Studio/Rendering/Shader/ShaderSource.cs
@@ -5,9 +5,9 @@ using System.Text;
using System.Threading.Tasks;
using OpenTK.Graphics.OpenGL;
-namespace PckStudio.Rendering
+namespace PckStudio.Rendering.Shader
{
- internal readonly struct ShaderSource
+ public readonly struct ShaderSource
{
public readonly ShaderType Type;
public readonly string Source;
diff --git a/PCK-Studio/Rendering/SkinRenderer.cs b/PCK-Studio/Rendering/SkinRenderer.cs
index 7ee43723..990f2792 100644
--- a/PCK-Studio/Rendering/SkinRenderer.cs
+++ b/PCK-Studio/Rendering/SkinRenderer.cs
@@ -33,6 +33,7 @@ using System.Drawing.Imaging;
using System.IO;
using PckStudio.Rendering.Camera;
using PckStudio.Rendering.Texture;
+using PckStudio.Rendering.Shader;
namespace PckStudio.Rendering
{
@@ -158,11 +159,12 @@ namespace PckStudio.Rendering
private Point PreviousMouseLocation;
private Point CurrentMouseLocation;
- private Shader _skinShader;
+ private ShaderProgram _skinShader;
private SkinANIM _anim;
private Image _texture;
private Shader _skyboxShader;
+ private ShaderProgram _skyboxShader;
private RenderBuffer _skyboxRenderBuffer;
private CubeTexture _skyboxTexture;
private float skyboxRotation = 0f;
@@ -198,12 +200,27 @@ namespace PckStudio.Rendering
private Matrix4 RightLegMatrix { get; set; } = Matrix4.Identity;
private Matrix4 LeftLegMatrix { get; set; } = Matrix4.Identity;
+ private static Vector3[] cubeVertices = new Vector3[]
+ {
+ // front
+ new Vector3(-1.0f, -1.0f, 1.0f),
+ new Vector3( 1.0f, -1.0f, 1.0f),
+ new Vector3( 1.0f, 1.0f, 1.0f),
+ new Vector3(-1.0f, 1.0f, 1.0f),
+ // back
+ new Vector3(-1.0f, -1.0f, -1.0f),
+ new Vector3( 1.0f, -1.0f, -1.0f),
+ new Vector3( 1.0f, 1.0f, -1.0f),
+ new Vector3(-1.0f, 1.0f, -1.0f)
+ };
public SkinRenderer() : base()
{
- InitializeComponent();
InitializeCamera();
InitializeSkinData();
- ANIM ??= SkinANIM.Empty;
+ InitializeShaders();
+ InitializeComponent();
+
+ ANIM ??= new SkinANIM(SkinAnimMask.RESOLUTION_64x64);
OnTimerTick = AnimationTick;
ModelData = new ObservableCollection();
ModelData.CollectionChanged += ModelData_CollectionChanged;
@@ -321,9 +338,8 @@ namespace PckStudio.Rendering
leftLegOverlay.Submit();
}
- protected override void OnLoad(EventArgs e)
+ private void InitializeShaders()
{
- base.OnLoad(e);
if (DesignMode)
return;
@@ -331,22 +347,34 @@ namespace PckStudio.Rendering
Trace.TraceInformation(GL.GetString(StringName.Version));
- // Initialize skybox shader
+ // Skin shader
{
- Vector3[] cubeVertices = new Vector3[]
- {
- // front
- new Vector3(-1.0f, -1.0f, 1.0f),
- new Vector3( 1.0f, -1.0f, 1.0f),
- new Vector3( 1.0f, 1.0f, 1.0f),
- new Vector3(-1.0f, 1.0f, 1.0f),
- // back
- new Vector3(-1.0f, -1.0f, -1.0f),
- new Vector3( 1.0f, -1.0f, -1.0f),
- new Vector3( 1.0f, 1.0f, -1.0f),
- new Vector3(-1.0f, 1.0f, -1.0f)
- };
+ _skinShader = ShaderProgram.Create(
+ new ShaderSource(ShaderType.VertexShader, Resources.skinVertexShader),
+ new ShaderSource(ShaderType.FragmentShader, Resources.skinFragmentShader),
+ new ShaderSource(ShaderType.GeometryShader, Resources.skinGeometryShader)
+ );
+ _skinShader.Bind();
+ _skinShader.SetUniform1("u_Texture", 0);
+ _skinShader.Validate();
+ GLErrorCheck();
+ skinTexture = new Texture2D(0);
+ skinTexture.PixelFormat = OpenTK.Graphics.OpenGL.PixelFormat.Bgra;
+ skinTexture.InternalPixelFormat = PixelInternalFormat.Rgba8;
+ skinTexture.MinFilter = TextureMinFilter.Nearest;
+ skinTexture.MagFilter = TextureMagFilter.Nearest;
+ skinTexture.WrapS = TextureWrapMode.Repeat;
+ skinTexture.WrapT = TextureWrapMode.Repeat;
+
+ Texture ??= Resources.classic_template;
+
+ _skinShader.Unbind();
+ GLErrorCheck();
+ }
+
+ // Skybox shader
+ {
var skyboxVAO = new VertexArray();
var skyboxVBO = new VertexBuffer(cubeVertices, cubeVertices.Length * Vector3.SizeInBytes);
var vboLayout = new VertexBufferLayout();
@@ -377,6 +405,12 @@ namespace PckStudio.Rendering
skyboxVAO.Unbind();
skybocIBO.Unbind();
+ _skyboxShader = ShaderProgram.Create(Resources.skyboxVertexShader, Resources.skyboxFragmentShader);
+ _skyboxShader.Bind();
+ _skyboxShader.SetUniform1("skybox", 1);
+ _skyboxShader.SetUniform1("brightness", 1f);
+ _skyboxShader.Validate();
+
string customSkyboxFilepath = Path.Combine(Program.AppData, "cubemap.png");
Image skyboxImage = File.Exists(customSkyboxFilepath)
? Image.FromFile(customSkyboxFilepath)
@@ -553,21 +587,23 @@ namespace PckStudio.Rendering
MakeCurrent();
- Camera.Update(AspectRatio);
+ GL.Viewport(Size);
+ GL.ClearColor(BackColor);
+ GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
+ GL.Enable(EnableCap.DepthTest); // Enable correct Z Drawings
+
+ // Render (custom) skin
+ {
var viewProjection = Camera.GetViewProjection();
_skinShader.Bind();
_skinShader.SetUniformMat4("u_ViewProjection", ref viewProjection);
_skinShader.SetUniform2("u_TexSize", new Vector2(TextureSize.Width, TextureSize.Height));
- GL.Viewport(Size);
-
- GL.ClearColor(BackColor);
- GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
+ skinTexture.Bind();
GL.Enable(EnableCap.Texture2D); // Enable textures
- GL.Enable(EnableCap.DepthTest); // Enable correct Z Drawings
GL.DepthFunc(DepthFunction.Lequal); // Enable correct Z Drawings
GL.DepthMask(true);
@@ -620,7 +656,8 @@ namespace PckStudio.Rendering
RenderBodyPart(new Vector3( 4f, 2f, 0f), new Vector3(slimModel ? -4f : -5f, -2f, 0f), RightArmMatrix * armRightMatrix, modelMatrix, "ARM0", "SLEEVE0");
RenderBodyPart(new Vector3(-4f, 2f, 0f), new Vector3( 5f, -2f, 0f), LeftArmMatrix * armLeftMatrix , modelMatrix, "ARM1", "SLEEVE1");
RenderBodyPart(new Vector3(0f, 12f, 0f), new Vector3(-2f, -12f, 0f), RightLegMatrix * legRightMatrix, modelMatrix, "LEG0", "PANTS0");
- RenderBodyPart(new Vector3(0f, 12f, 0f), new Vector3( 2f, -12f, 0f), LeftLegMatrix * legLeftMatrix , modelMatrix, "LEG1", "PANTS1");
+ RenderBodyPart(new Vector3(0f, 12f, 0f), new Vector3(2f, -12f, 0f), LeftLegMatrix * legLeftMatrix, modelMatrix, "LEG1", "PANTS1");
+ }
// Render Skybox
{
diff --git a/PCK-Studio/Resources/shader/skyboxFragmentShader.glsl b/PCK-Studio/Resources/shader/skyboxFragmentShader.glsl
index b242f456..f356fd63 100644
--- a/PCK-Studio/Resources/shader/skyboxFragmentShader.glsl
+++ b/PCK-Studio/Resources/shader/skyboxFragmentShader.glsl
@@ -3,10 +3,11 @@
layout(location = 0) out vec4 color;
uniform samplerCube skybox;
+uniform float brightness;
in vec3 texCoords;
void main()
{
- color = texture(skybox, texCoords);
+ color = texture(skybox, texCoords) * vec4(vec3(clamp(brightness, 0.0, 1.0)), 1.0);
}
\ No newline at end of file