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