Create Tutorial 2.2 to demonstrate Camera basics (#221)
* start of tutorial2.2 * Rename Tutorial 1.6 to Tutorial 2.1 to align with planned documentation sections * Add Tutorial2.2 to demonstrate moving the viewport with WASD, looking around with Mouse movement, and Zooming in and out with the Scroll Wheel
This commit is contained in:
Родитель
d1385a9a5f
Коммит
f057c16d99
17
Silk.NET.sln
17
Silk.NET.sln
|
@ -293,7 +293,9 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Silk.NET.Windowing.Extensio
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FramebufferResized", "src\Lab\FramebufferResized\FramebufferResized.csproj", "{7AF3C6CA-64FE-43F3-BD7B-C57C83AFAB79}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tutorial 1.6 - Co-ordinate Systems", "examples\CSharp\Tutorial 1.6 - Co-ordinate Systems\Tutorial 1.6 - Co-ordinate Systems.csproj", "{7874B5F2-2428-4D4E-8FDB-8634573163B8}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tutorial 2.1 - Co-ordinate Systems", "examples\CSharp\Tutorial 2.1 - Co-ordinate Systems\Tutorial 2.1 - Co-ordinate Systems.csproj", "{7874B5F2-2428-4D4E-8FDB-8634573163B8}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tutorial 2.2 - Camera", "examples\CSharp\Tutorial 2.2 - Camera\Tutorial 2.2 - Camera.csproj", "{4FBE561E-7FF9-4D69-91D5-945DE9A20291}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
|
@ -1832,6 +1834,18 @@ Global
|
|||
{7874B5F2-2428-4D4E-8FDB-8634573163B8}.Release|x64.Build.0 = Release|Any CPU
|
||||
{7874B5F2-2428-4D4E-8FDB-8634573163B8}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{7874B5F2-2428-4D4E-8FDB-8634573163B8}.Release|x86.Build.0 = Release|Any CPU
|
||||
{4FBE561E-7FF9-4D69-91D5-945DE9A20291}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4FBE561E-7FF9-4D69-91D5-945DE9A20291}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4FBE561E-7FF9-4D69-91D5-945DE9A20291}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{4FBE561E-7FF9-4D69-91D5-945DE9A20291}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{4FBE561E-7FF9-4D69-91D5-945DE9A20291}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{4FBE561E-7FF9-4D69-91D5-945DE9A20291}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{4FBE561E-7FF9-4D69-91D5-945DE9A20291}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4FBE561E-7FF9-4D69-91D5-945DE9A20291}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4FBE561E-7FF9-4D69-91D5-945DE9A20291}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{4FBE561E-7FF9-4D69-91D5-945DE9A20291}.Release|x64.Build.0 = Release|Any CPU
|
||||
{4FBE561E-7FF9-4D69-91D5-945DE9A20291}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{4FBE561E-7FF9-4D69-91D5-945DE9A20291}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
|
@ -1969,6 +1983,7 @@ Global
|
|||
{F5D5B4B4-58B7-48D9-881B-DD6A4001793E} = {3501BAD6-406A-49BC-BE0E-5A49A3AAAE6A}
|
||||
{7AF3C6CA-64FE-43F3-BD7B-C57C83AFAB79} = {DFA0E841-33E5-4533-AF00-964E21A141B8}
|
||||
{7874B5F2-2428-4D4E-8FDB-8634573163B8} = {E1F91563-7277-4E9B-A3B7-8D5FD9802A4A}
|
||||
{4FBE561E-7FF9-4D69-91D5-945DE9A20291} = {E1F91563-7277-4E9B-A3B7-8D5FD9802A4A}
|
||||
EndGlobalSection
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
До Ширина: | Высота: | Размер: 11 KiB После Ширина: | Высота: | Размер: 11 KiB |
|
@ -0,0 +1,36 @@
|
|||
using Silk.NET.OpenGL;
|
||||
using System;
|
||||
|
||||
namespace Tutorial
|
||||
{
|
||||
public class BufferObject<TDataType> : IDisposable
|
||||
where TDataType : unmanaged
|
||||
{
|
||||
private uint _handle;
|
||||
private BufferTargetARB _bufferType;
|
||||
private GL _gl;
|
||||
|
||||
public unsafe BufferObject(GL gl, Span<TDataType> data, BufferTargetARB bufferType)
|
||||
{
|
||||
_gl = gl;
|
||||
_bufferType = bufferType;
|
||||
|
||||
_handle = _gl.GenBuffer();
|
||||
Bind();
|
||||
fixed (void* d = data)
|
||||
{
|
||||
_gl.BufferData(bufferType, (UIntPtr)(data.Length * sizeof(TDataType)), d, BufferUsageARB.StaticDraw);
|
||||
}
|
||||
}
|
||||
|
||||
public void Bind()
|
||||
{
|
||||
_gl.BindBuffer(_bufferType, _handle);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_gl.DeleteBuffer(_handle);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,242 @@
|
|||
using Silk.NET.Input;
|
||||
using Silk.NET.Input.Common;
|
||||
using Silk.NET.OpenGL;
|
||||
using Silk.NET.Windowing;
|
||||
using Silk.NET.Windowing.Common;
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Tutorial
|
||||
{
|
||||
class Program
|
||||
{
|
||||
private static IWindow window;
|
||||
private static GL Gl;
|
||||
private static IKeyboard primaryKeyboard;
|
||||
|
||||
private const int Width = 800;
|
||||
private const int Height = 700;
|
||||
|
||||
private static BufferObject<float> Vbo;
|
||||
private static BufferObject<uint> Ebo;
|
||||
private static VertexArrayObject<float, uint> Vao;
|
||||
private static Texture Texture;
|
||||
private static Shader Shader;
|
||||
|
||||
//Setup the cameras location, directions, and movement speed
|
||||
private static Vector3 CameraPosition = new Vector3(0.0f, 0.0f, 3.0f);
|
||||
private static Vector3 CameraFront = new Vector3(0.0f, 0.0f, -1.0f);
|
||||
private static Vector3 CameraUp = new Vector3(0.0f, 1.0f, 3.0f);
|
||||
private static Vector3 CameraDirection = Vector3.Zero;
|
||||
private static float CameraYaw = -90f;
|
||||
private static float CameraPitch = 0f;
|
||||
private static float CameraZoom = 45f;
|
||||
|
||||
//Used to track change in mouse movement to allow for moving of the Camera
|
||||
private static PointF LastMousePosition;
|
||||
|
||||
//Track when the window started so we can use the time elapsed to rotate the cube
|
||||
private static DateTime StartTime;
|
||||
|
||||
private static readonly float[] Vertices =
|
||||
{
|
||||
//X Y Z U V
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
|
||||
0.5f, -0.5f, -0.5f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
|
||||
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
|
||||
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
|
||||
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
|
||||
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f,
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
|
||||
|
||||
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
|
||||
-0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
|
||||
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
|
||||
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
|
||||
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
|
||||
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
|
||||
0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
|
||||
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
|
||||
0.5f, -0.5f, -0.5f, 1.0f, 1.0f,
|
||||
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
|
||||
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
|
||||
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
|
||||
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
|
||||
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
|
||||
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
|
||||
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
|
||||
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f,
|
||||
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f
|
||||
};
|
||||
|
||||
private static readonly uint[] Indices =
|
||||
{
|
||||
0, 1, 3,
|
||||
1, 2, 3
|
||||
};
|
||||
|
||||
private static void Main(string[] args)
|
||||
{
|
||||
var options = WindowOptions.Default;
|
||||
options.Size = new Size(800, 600);
|
||||
options.Title = "LearnOpenGL with Silk.NET";
|
||||
window = Window.Create(options);
|
||||
|
||||
window.Load += OnLoad;
|
||||
window.Update += OnUpdate;
|
||||
window.Render += OnRender;
|
||||
window.Closing += OnClose;
|
||||
|
||||
window.Run();
|
||||
}
|
||||
|
||||
private static void OnLoad()
|
||||
{
|
||||
StartTime = DateTime.UtcNow;
|
||||
IInputContext input = window.CreateInput();
|
||||
primaryKeyboard = input.Keyboards.FirstOrDefault();
|
||||
if (primaryKeyboard != null)
|
||||
{
|
||||
primaryKeyboard.KeyDown += KeyDown;
|
||||
}
|
||||
for (int i = 0; i < input.Mice.Count; i++)
|
||||
{
|
||||
input.Mice[i].MouseMove += OnMouseMove;
|
||||
input.Mice[i].Scroll += OnMouseWheel;
|
||||
}
|
||||
|
||||
Gl = GL.GetApi(window);
|
||||
|
||||
Ebo = new BufferObject<uint>(Gl, Indices, BufferTargetARB.ElementArrayBuffer);
|
||||
Vbo = new BufferObject<float>(Gl, Vertices, BufferTargetARB.ArrayBuffer);
|
||||
Vao = new VertexArrayObject<float, uint>(Gl, Vbo, Ebo);
|
||||
|
||||
Vao.VertexAttributePointer(0, 3, VertexAttribPointerType.Float, 5, 0);
|
||||
Vao.VertexAttributePointer(1, 2, VertexAttribPointerType.Float, 5, 3);
|
||||
|
||||
Shader = new Shader(Gl, "shader.vert", "shader.frag");
|
||||
|
||||
Texture = new Texture(Gl, "silk.png");
|
||||
}
|
||||
|
||||
private static unsafe void OnUpdate(double deltaTime)
|
||||
{
|
||||
var moveSpeed = 2.5f * (float)deltaTime;
|
||||
|
||||
if (primaryKeyboard.IsKeyPressed(Key.W))
|
||||
{
|
||||
//Move forwards
|
||||
CameraPosition += moveSpeed * CameraFront;
|
||||
}
|
||||
if (primaryKeyboard.IsKeyPressed(Key.S))
|
||||
{
|
||||
//Move backwards
|
||||
CameraPosition -= moveSpeed * CameraFront;
|
||||
}
|
||||
if (primaryKeyboard.IsKeyPressed(Key.A))
|
||||
{
|
||||
//Move left
|
||||
CameraPosition -= Vector3.Normalize(Vector3.Cross(CameraFront, CameraUp)) * moveSpeed;
|
||||
}
|
||||
if (primaryKeyboard.IsKeyPressed(Key.D))
|
||||
{
|
||||
//Move right
|
||||
CameraPosition += Vector3.Normalize(Vector3.Cross(CameraFront, CameraUp)) * moveSpeed;
|
||||
}
|
||||
}
|
||||
|
||||
private static unsafe void OnRender(double deltaTime)
|
||||
{
|
||||
Gl.Enable(EnableCap.DepthTest);
|
||||
Gl.Clear((uint)(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit));
|
||||
|
||||
Vao.Bind();
|
||||
Texture.Bind();
|
||||
Shader.Use();
|
||||
Shader.SetUniform("uTexture0", 0);
|
||||
|
||||
//Use elapsed time to convert to radians to allow our cube to rotate over time
|
||||
var difference = (DateTime.UtcNow - StartTime).TotalMilliseconds / 10;
|
||||
|
||||
var model = Matrix4x4.CreateRotationY((float)DegreesToRadians(difference)) * Matrix4x4.CreateRotationX((float)DegreesToRadians(difference));
|
||||
var view = Matrix4x4.CreateLookAt(CameraPosition, CameraPosition + CameraFront, CameraUp);
|
||||
var projection = Matrix4x4.CreatePerspectiveFieldOfView((float)DegreesToRadians(CameraZoom), Width / Height, 0.1f, 100.0f);
|
||||
|
||||
Shader.SetUniform("uModel", model);
|
||||
Shader.SetUniform("uView", view);
|
||||
Shader.SetUniform("uProjection", projection);
|
||||
|
||||
//We're drawing with just vertices and no indicies, and it takes 36 verticies to have a six-sided textured cube
|
||||
Gl.DrawArrays(PrimitiveType.Triangles, 0, 36);
|
||||
}
|
||||
|
||||
private static unsafe void OnMouseMove(IMouse mouse, PointF position)
|
||||
{
|
||||
var lookSensitivity = 0.02f;
|
||||
if (LastMousePosition == default) { LastMousePosition = position; }
|
||||
else
|
||||
{
|
||||
var xOffset = (position.X - LastMousePosition.X) * lookSensitivity;
|
||||
var yOffset = (position.Y - LastMousePosition.Y) * lookSensitivity;
|
||||
LastMousePosition = position;
|
||||
|
||||
CameraYaw += xOffset;
|
||||
CameraPitch += yOffset;
|
||||
|
||||
//We don't want to be able to look behind us by going over our head or under our feet so make sure it stays within these bounds
|
||||
if (CameraPitch > 89.0f) { CameraPitch = 89.0f; }
|
||||
if (CameraPitch < -89.0f) { CameraPitch = -89.0f; }
|
||||
|
||||
CameraDirection.X = MathF.Cos((float)DegreesToRadians(CameraYaw)) * MathF.Cos((float)DegreesToRadians(CameraPitch));
|
||||
CameraDirection.Y = MathF.Sin((float)DegreesToRadians(CameraPitch));
|
||||
CameraDirection.Z = MathF.Sin((float)DegreesToRadians(CameraYaw)) * MathF.Cos((float)DegreesToRadians(CameraPitch));
|
||||
CameraFront = Vector3.Normalize(CameraDirection);
|
||||
}
|
||||
}
|
||||
|
||||
private static unsafe void OnMouseWheel(IMouse mouse, ScrollWheel scrollWheel)
|
||||
{
|
||||
//We don't want to be able to zoom in too close or too far away so clamp to these values
|
||||
CameraZoom = Math.Clamp(CameraZoom - scrollWheel.Y, 1.0f, 45f);
|
||||
}
|
||||
|
||||
private static void OnClose()
|
||||
{
|
||||
Vbo.Dispose();
|
||||
Ebo.Dispose();
|
||||
Vao.Dispose();
|
||||
Shader.Dispose();
|
||||
Texture.Dispose();
|
||||
}
|
||||
|
||||
private static void KeyDown(IKeyboard keyboard, Key key, int arg3)
|
||||
{
|
||||
if (key == Key.Escape)
|
||||
{
|
||||
window.Close();
|
||||
}
|
||||
}
|
||||
|
||||
private static double DegreesToRadians(double degrees)
|
||||
{
|
||||
return (Math.PI / 180f) * degrees;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Numerics;
|
||||
using Silk.NET.OpenGL;
|
||||
|
||||
namespace Tutorial
|
||||
{
|
||||
public class Shader : IDisposable
|
||||
{
|
||||
private uint _handle;
|
||||
private GL _gl;
|
||||
|
||||
public Shader(GL gl, string vertexPath, string fragmentPath)
|
||||
{
|
||||
_gl = gl;
|
||||
|
||||
uint vertex = LoadShader(ShaderType.VertexShader, vertexPath);
|
||||
uint fragment = LoadShader(ShaderType.FragmentShader, fragmentPath);
|
||||
_handle = _gl.CreateProgram();
|
||||
_gl.AttachShader(_handle, vertex);
|
||||
_gl.AttachShader(_handle, fragment);
|
||||
_gl.LinkProgram(_handle);
|
||||
string infoLog = _gl.GetProgramInfoLog(_handle);
|
||||
if (!string.IsNullOrWhiteSpace(infoLog))
|
||||
{
|
||||
throw new Exception($"Program failed to link with error: {infoLog}");
|
||||
}
|
||||
_gl.DetachShader(_handle, vertex);
|
||||
_gl.DetachShader(_handle, fragment);
|
||||
_gl.DeleteShader(vertex);
|
||||
_gl.DeleteShader(fragment);
|
||||
}
|
||||
|
||||
public void Use()
|
||||
{
|
||||
_gl.UseProgram(_handle);
|
||||
}
|
||||
|
||||
public void SetUniform(string name, int value)
|
||||
{
|
||||
int location = _gl.GetUniformLocation(_handle, name);
|
||||
if (location == -1)
|
||||
{
|
||||
throw new Exception($"{name} uniform not found on shader.");
|
||||
}
|
||||
Use();
|
||||
_gl.Uniform1(location, value);
|
||||
}
|
||||
|
||||
public unsafe void SetUniform(string name, Matrix4x4 value)
|
||||
{
|
||||
//A new overload has been created for setting a uniform so we can use the transform in our shader.
|
||||
int location = _gl.GetUniformLocation(_handle, name);
|
||||
if (location == -1)
|
||||
{
|
||||
throw new Exception($"{name} uniform not found on shader.");
|
||||
}
|
||||
Use();
|
||||
_gl.UniformMatrix4(location, 1, false, (float*)&value);
|
||||
}
|
||||
|
||||
public void SetUniform(string name, float value)
|
||||
{
|
||||
int location = _gl.GetUniformLocation(_handle, name);
|
||||
if (location == -1)
|
||||
{
|
||||
throw new Exception($"{name} uniform not found on shader.");
|
||||
}
|
||||
Use();
|
||||
_gl.Uniform1(location, value);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_gl.DeleteProgram(_handle);
|
||||
}
|
||||
|
||||
private uint LoadShader(ShaderType type, string path)
|
||||
{
|
||||
string src = File.ReadAllText(path);
|
||||
uint handle = _gl.CreateShader(type);
|
||||
_gl.ShaderSource(handle, src);
|
||||
_gl.CompileShader(handle);
|
||||
string infoLog = _gl.GetShaderInfoLog(handle);
|
||||
if (!string.IsNullOrWhiteSpace(infoLog))
|
||||
{
|
||||
throw new Exception($"Error compiling shader of type {type}, failed with error {infoLog}");
|
||||
}
|
||||
|
||||
return handle;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
using Silk.NET.OpenGL;
|
||||
using SixLabors.ImageSharp;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
using SixLabors.ImageSharp.Processing;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Tutorial
|
||||
{
|
||||
public class Texture : IDisposable
|
||||
{
|
||||
private uint _handle;
|
||||
private GL _gl;
|
||||
|
||||
public unsafe Texture(GL gl, string path)
|
||||
{
|
||||
Image<Rgba32> img = (Image<Rgba32>)Image.Load(path);
|
||||
img.Mutate(x => x.Flip(FlipMode.Vertical));
|
||||
|
||||
fixed (void* data = &MemoryMarshal.GetReference(img.GetPixelRowSpan(0)))
|
||||
{
|
||||
Load(gl, data, (uint)img.Width, (uint)img.Height);
|
||||
}
|
||||
|
||||
img.Dispose();
|
||||
}
|
||||
|
||||
public unsafe Texture(GL gl, Span<byte> data, uint width, uint height)
|
||||
{
|
||||
fixed (void* d = &data[0])
|
||||
{
|
||||
Load(gl, d, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
private unsafe void Load(GL gl, void* data, uint width, uint height)
|
||||
{
|
||||
_gl = gl;
|
||||
|
||||
_handle = _gl.GenTexture();
|
||||
Bind();
|
||||
|
||||
_gl.TexImage2D(TextureTarget.Texture2D, 0, (int)InternalFormat.Rgba, width, height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, data);
|
||||
_gl.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)GLEnum.ClampToEdge);
|
||||
_gl.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)GLEnum.ClampToEdge);
|
||||
_gl.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)GLEnum.Linear);
|
||||
_gl.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)GLEnum.Linear);
|
||||
_gl.GenerateMipmap(TextureTarget.Texture2D);
|
||||
}
|
||||
|
||||
public void Bind(TextureUnit textureSlot = TextureUnit.Texture0)
|
||||
{
|
||||
_gl.ActiveTexture(textureSlot);
|
||||
_gl.BindTexture(TextureTarget.Texture2D, _handle);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_gl.DeleteTexture(_handle);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
using System.Numerics;
|
||||
|
||||
namespace Tutorial
|
||||
{
|
||||
public class Transform
|
||||
{
|
||||
//A transform abstraction.
|
||||
//For a transform we need to have a position a scale and a rotation,
|
||||
//depending on what application you are creating the type for these may vary.
|
||||
|
||||
//Here we have chosen a vec3 for position, float for scale and quaternion for rotation,
|
||||
//as that is the most normal to go with.
|
||||
//Another example could have been vec3, vec3, vec4, so the rotation is an axis angle instead of a quaternion
|
||||
|
||||
public Vector3 Position { get; set; } = new Vector3(0, 0, 0);
|
||||
|
||||
public float Scale { get; set; } = 1f;
|
||||
|
||||
public Quaternion Rotation { get; set; } = Quaternion.Identity;
|
||||
|
||||
//Note: The order here does matter.
|
||||
public Matrix4x4 ViewMatrix => Matrix4x4.Identity * Matrix4x4.CreateFromQuaternion(Rotation) * Matrix4x4.CreateScale(Scale) * Matrix4x4.CreateTranslation(Position);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
<RootNamespace>Tutorial</RootNamespace>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Silk.NET" Version="1.4.0" />
|
||||
<PackageReference Include="SixLabors.ImageSharp" Version="1.0.0-rc0003" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="Shader.frag">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="Shader.vert">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="silk.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,39 @@
|
|||
using Silk.NET.OpenGL;
|
||||
using System;
|
||||
|
||||
namespace Tutorial
|
||||
{
|
||||
public class VertexArrayObject<TVertexType, TIndexType> : IDisposable
|
||||
where TVertexType : unmanaged
|
||||
where TIndexType : unmanaged
|
||||
{
|
||||
private uint _handle;
|
||||
private GL _gl;
|
||||
|
||||
public VertexArrayObject(GL gl, BufferObject<TVertexType> vbo, BufferObject<TIndexType> ebo)
|
||||
{
|
||||
_gl = gl;
|
||||
|
||||
_handle = _gl.GenVertexArray();
|
||||
Bind();
|
||||
vbo.Bind();
|
||||
ebo.Bind();
|
||||
}
|
||||
|
||||
public unsafe void VertexAttributePointer(uint index, int count, VertexAttribPointerType type, uint vertexSize, int offSet)
|
||||
{
|
||||
_gl.VertexAttribPointer(index, count, type, false, vertexSize * (uint)sizeof(TVertexType), (void*)(offSet * sizeof(TVertexType)));
|
||||
_gl.EnableVertexAttribArray(index);
|
||||
}
|
||||
|
||||
public void Bind()
|
||||
{
|
||||
_gl.BindVertexArray(_handle);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_gl.DeleteVertexArray(_handle);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
#version 330 core
|
||||
in vec2 fUv;
|
||||
|
||||
uniform sampler2D uTexture0;
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
FragColor = texture(uTexture0, fUv);
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
#version 330 core
|
||||
layout (location = 0) in vec3 vPos;
|
||||
layout (location = 1) in vec2 vUv;
|
||||
|
||||
uniform mat4 uModel;
|
||||
uniform mat4 uView;
|
||||
uniform mat4 uProjection;
|
||||
|
||||
out vec2 fUv;
|
||||
|
||||
void main()
|
||||
{
|
||||
//Multiplying our uniform with the vertex position, the multiplication order here does matter.
|
||||
gl_Position = uProjection * uView * uModel * vec4(vPos, 1.0);
|
||||
fUv = vUv;
|
||||
}
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 11 KiB |
Загрузка…
Ссылка в новой задаче