diff --git a/PCK-Studio/PckStudio.csproj b/PCK-Studio/PckStudio.csproj
index cd7f3d5e..358ea7a0 100644
--- a/PCK-Studio/PckStudio.csproj
+++ b/PCK-Studio/PckStudio.csproj
@@ -641,6 +641,9 @@
+
+
+
diff --git a/PCK-Studio/Properties/Resources.Designer.cs b/PCK-Studio/Properties/Resources.Designer.cs
index a5516225..98a02888 100644
--- a/PCK-Studio/Properties/Resources.Designer.cs
+++ b/PCK-Studio/Properties/Resources.Designer.cs
@@ -222,6 +222,16 @@ namespace PckStudio.Properties {
}
}
+ ///
+ /// Looks up a localized resource of type System.Drawing.Bitmap.
+ ///
+ public static System.Drawing.Bitmap DefaultSkyTexture {
+ get {
+ object obj = ResourceManager.GetObject("DefaultSkyTexture", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+
///
/// Looks up a localized resource of type System.Drawing.Bitmap.
///
@@ -590,6 +600,7 @@ namespace PckStudio.Properties {
///
///layout(location = 0) in vec4 vertexPosition;
///layout(location = 1) in vec2 texCoord;
+ ///layout(location = 2) in float scale;
///
///uniform mat4 u_ViewProjection;
///uniform mat4 u_Model;
@@ -599,7 +610,9 @@ namespace PckStudio.Properties {
///void main()
///{
/// v_TexCoord = texCoord;
- /// gl_Position = u_ViewProjection * u_Model * vertexPosition;
+ /// vec4 scaledVertex = scale * vertexPosition;
+ /// vec4 invertedVertex = vec4(scaledVertex.x, scaledVertex.y * -1.0, scaledVertex.z * -1.0, 1.0);
+ /// gl_Position = u_ViewProjection * u_Model * invertedVertex;
///};.
///
public static string skinVertexShader {
@@ -608,6 +621,48 @@ namespace PckStudio.Properties {
}
}
+ ///
+ /// Looks up a localized string similar to #version 330 core
+ ///
+ ///layout(location = 0) out vec4 color;
+ ///
+ ///uniform samplerCube skybox;
+ ///
+ ///in vec3 texCoords;
+ ///
+ ///void main()
+ ///{
+ /// color = texture(skybox, texCoords);
+ ///}.
+ ///
+ public static string skyboxFragmentShader {
+ get {
+ return ResourceManager.GetString("skyboxFragmentShader", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to #version 330 core
+ ///
+ ///layout(location = 0) in vec4 a_Pos;
+ ///
+ ///uniform mat4 viewProjection;
+ ///
+ ///out vec3 texCoords;
+ ///
+ ///void main()
+ ///{
+ /// vec4 pos = viewProjection * a_Pos;
+ /// gl_Position = vec4(pos.x, pos.y, pos.ww);
+ /// texCoords = vec3(a_Pos.x, a_Pos.y, -a_Pos.z);
+ ///};.
+ ///
+ public static string skyboxVertexShader {
+ get {
+ return ResourceManager.GetString("skyboxVertexShader", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized resource of type System.Drawing.Bitmap.
///
diff --git a/PCK-Studio/Properties/Resources.resx b/PCK-Studio/Properties/Resources.resx
index 6d7bce1d..962702fc 100644
--- a/PCK-Studio/Properties/Resources.resx
+++ b/PCK-Studio/Properties/Resources.resx
@@ -334,4 +334,13 @@
..\Resources\shader\skinFragmentShader.glsl;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252
+
+ ..\Resources\skybox_texture.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\Resources\shader\skyboxFragmentShader.glsl;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252
+
+
+ ..\Resources\shader\skyboxVertexShader.glsl;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252
+
\ No newline at end of file
diff --git a/PCK-Studio/Rendering/SkinRenderer.cs b/PCK-Studio/Rendering/SkinRenderer.cs
index e29ed60b..9a9a2df9 100644
--- a/PCK-Studio/Rendering/SkinRenderer.cs
+++ b/PCK-Studio/Rendering/SkinRenderer.cs
@@ -31,6 +31,7 @@ using PckStudio.Forms.Editor;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Drawing.Imaging;
+using System.IO;
using PckStudio.Rendering.Camera;
using PckStudio.Rendering.Texture;
@@ -99,7 +100,7 @@ namespace PckStudio.Rendering
set
{
_globalModelRotation.X = MathHelper.Clamp(value.X, -90f, 90f);
- _globalModelRotation.Y = MathHelper.Clamp(value.Y, -180f, 180f);
+ _globalModelRotation.Y = value.Y % 360f;
}
}
@@ -114,8 +115,9 @@ namespace PckStudio.Rendering
{
set
{
- if (HasValidContext && _skinShader is not null)
+ if (value is not null && HasValidContext && _skinShader is not null)
{
+ MakeCurrent();
TextureSize = value.Width == value.Height ? new Size(64, 64) : new Size(64, 32);
UvTranslation = value.Width == value.Height ? new Vector2(1f / 64) : new Vector2(1f / 64, 1f / 32);
var texture = new Texture2D(value);
@@ -146,6 +148,12 @@ namespace PckStudio.Rendering
private SkinANIM _anim;
private Image _texture;
+ private Shader _skyboxShader;
+ private RenderBuffer _skyboxRenderBuffer;
+ private CubeTexture _skyboxTexture;
+ private float skyboxRotation = 0f;
+ private float skyboxRotationStep = 0.5f;
+
private Dictionary additionalModelRenderGroups;
private Dictionary partOffset;
private CubeRenderGroup head;
@@ -328,15 +336,76 @@ namespace PckStudio.Rendering
Trace.TraceInformation(GL.GetString(StringName.Version));
+ // Initialize skybox shader
+ {
+ string customSkyboxFilepath = Path.Combine(Program.AppData, "cubemap.png");
+ Image skyboxImage = File.Exists(customSkyboxFilepath)
+ ? Image.FromFile(customSkyboxFilepath)
+ : Resources.DefaultSkyTexture;
+
+ _skyboxShader = Shader.Create(Resources.skyboxVertexShader, Resources.skyboxFragmentShader);
+ _skyboxTexture = new CubeTexture(skyboxImage);
+ _skyboxTexture.Bind(1);
+ _skyboxShader.Bind();
+ _skyboxShader.SetUniform1("skybox", 1);
+ _skyboxShader.Validate();
+
+ 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)
+ };
+
+ var skyboxVAO = new VertexArray();
+ var skyboxVBO = new VertexBuffer(cubeVertices, cubeVertices.Length * Vector3.SizeInBytes);
+ var vboLayout = new VertexBufferLayout();
+ vboLayout.Add(3);
+ skyboxVAO.AddBuffer(skyboxVBO, vboLayout);
+ var skybocIBO = IndexBuffer.Create(
+ // front
+ 0, 1, 2,
+ 2, 3, 0,
+ // right
+ 1, 5, 6,
+ 6, 2, 1,
+ // back
+ 7, 6, 5,
+ 5, 4, 7,
+ // left
+ 4, 0, 3,
+ 3, 7, 4,
+ // bottom
+ 4, 5, 1,
+ 1, 0, 4,
+ // top
+ 3, 2, 6,
+ 6, 7, 3);
+
+ _skyboxRenderBuffer = new RenderBuffer(skyboxVAO, skybocIBO, PrimitiveType.Triangles);
+ skyboxVAO.Unbind();
+ skybocIBO.Unbind();
+ }
+
+ // Initialize skin shader
+ {
_skinShader = Shader.Create(Resources.skinVertexShader, Resources.skinFragmentShader);
+ _skinShader.Validate();
_skinShader.Bind();
Texture ??= Resources.classic_template;
-
RenderTexture = Texture;
GLErrorCheck();
}
+ }
public void UpdateModelData()
{
@@ -472,9 +541,10 @@ namespace PckStudio.Rendering
MakeCurrent();
- camera.Update(ClientSize.Width / (float)ClientSize.Height);
+ camera.Update(AspectRatio);
var viewProjection = camera.GetViewProjection();
+ _skinShader.Bind();
_skinShader.SetUniformMat4("u_ViewProjection", ref viewProjection);
_skinShader.SetUniform2("u_TexScale", UvTranslation);
@@ -537,6 +607,20 @@ namespace PckStudio.Rendering
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");
+ if (true)
+ {
+ GL.DepthFunc(DepthFunction.Lequal);
+ _skyboxShader.Bind();
+
+ var view = new Matrix4(new Matrix3(Matrix4.LookAt(camera.WorldPosition, camera.WorldPosition + camera.Orientation, camera.Up)))
+ * Matrix4.CreateRotationY(MathHelper.DegreesToRadians(skyboxRotation));
+ var proj = Matrix4.CreatePerspectiveFieldOfView(MathHelper.DegreesToRadians(camera.Fov), AspectRatio, 1f, 1000f);
+ var viewproj = view * proj;
+ _skyboxShader.SetUniformMat4("viewProjection", ref viewproj);
+ Renderer.Draw(_skyboxShader, _skyboxRenderBuffer);
+ GL.DepthFunc(DepthFunction.Less);
+ }
+
SwapBuffers();
}
@@ -605,9 +689,8 @@ namespace PckStudio.Rendering
private void animationTimer_Tick(object sender, EventArgs e)
{
- if (!Focused)
- return;
-
+ skyboxRotation += skyboxRotationStep;
+ skyboxRotation %= 360f;
animationCurrentRotationAngle += animationRotationStep;
if (animationCurrentRotationAngle >= animationMaxAngleInDegrees || animationCurrentRotationAngle <= -animationMaxAngleInDegrees)
animationRotationStep = -animationRotationStep;
diff --git a/PCK-Studio/Resources/shader/skyboxFragmentShader.glsl b/PCK-Studio/Resources/shader/skyboxFragmentShader.glsl
new file mode 100644
index 00000000..b242f456
--- /dev/null
+++ b/PCK-Studio/Resources/shader/skyboxFragmentShader.glsl
@@ -0,0 +1,12 @@
+#version 330 core
+
+layout(location = 0) out vec4 color;
+
+uniform samplerCube skybox;
+
+in vec3 texCoords;
+
+void main()
+{
+ color = texture(skybox, texCoords);
+}
\ No newline at end of file
diff --git a/PCK-Studio/Resources/shader/skyboxVertexShader.glsl b/PCK-Studio/Resources/shader/skyboxVertexShader.glsl
new file mode 100644
index 00000000..7a955686
--- /dev/null
+++ b/PCK-Studio/Resources/shader/skyboxVertexShader.glsl
@@ -0,0 +1,14 @@
+#version 330 core
+
+layout(location = 0) in vec4 a_Pos;
+
+uniform mat4 viewProjection;
+
+out vec3 texCoords;
+
+void main()
+{
+ vec4 pos = viewProjection * a_Pos;
+ gl_Position = vec4(pos.x, pos.y, pos.ww);
+ texCoords = vec3(a_Pos.x, a_Pos.y, -a_Pos.z);
+};
\ No newline at end of file
diff --git a/PCK-Studio/Resources/skybox_texture.png b/PCK-Studio/Resources/skybox_texture.png
new file mode 100644
index 00000000..d0f91faa
Binary files /dev/null and b/PCK-Studio/Resources/skybox_texture.png differ