mirror of
https://github.com/UOH-CS-Level5/551455-graphics-programming-2526-the-repo-Zyb3rWolfi.git
synced 2025-11-29 08:53:07 +00:00
Compare commits
No commits in common. "8d46d85df03193afd7a85132924e3e7899746505" and "82bc46fbb3129f5ac52b40271e899b28dfea3df3" have entirely different histories.
8d46d85df0
...
82bc46fbb3
@ -3,7 +3,6 @@
|
|||||||
<component name="UserContentModel">
|
<component name="UserContentModel">
|
||||||
<attachedFolders>
|
<attachedFolders>
|
||||||
<Path>../../551455-graphics-programming-2526-the-repo-Zyb3rWolfi</Path>
|
<Path>../../551455-graphics-programming-2526-the-repo-Zyb3rWolfi</Path>
|
||||||
<Path>TheLabs/Textures</Path>
|
|
||||||
</attachedFolders>
|
</attachedFolders>
|
||||||
<explicitIncludes />
|
<explicitIncludes />
|
||||||
<explicitExcludes />
|
<explicitExcludes />
|
||||||
|
|||||||
@ -9,7 +9,6 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="OpenTK" Version="4.8.2" />
|
<PackageReference Include="OpenTK" Version="4.8.2" />
|
||||||
<PackageReference Include="StbImageSharp" Version="2.30.15" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@ -1,132 +0,0 @@
|
|||||||
namespace TheLabs;
|
|
||||||
using LearnOpenTK.Common;
|
|
||||||
using OpenTK.Graphics.OpenGL4;
|
|
||||||
using OpenTK.Mathematics;
|
|
||||||
using OpenTK.Windowing.Desktop;
|
|
||||||
using StbImageSharp;
|
|
||||||
|
|
||||||
public class Mesh : IDisposable
|
|
||||||
{
|
|
||||||
private readonly int _vao;
|
|
||||||
private readonly int _vbo;
|
|
||||||
private readonly int _ebo;
|
|
||||||
private readonly int _vertexCount;
|
|
||||||
private readonly bool _useIndices;
|
|
||||||
|
|
||||||
// A flexible way to define vertex layout
|
|
||||||
// (Could be an enum or a struct)
|
|
||||||
public enum VertexLayout { PosColor, PosTex }
|
|
||||||
|
|
||||||
public Mesh(float[] vertices, uint[] indices, VertexLayout layout)
|
|
||||||
{
|
|
||||||
_vertexCount = indices.Length;
|
|
||||||
_useIndices = true;
|
|
||||||
|
|
||||||
_vao = GL.GenVertexArray();
|
|
||||||
GL.BindVertexArray(_vao);
|
|
||||||
|
|
||||||
_vbo = GL.GenBuffer();
|
|
||||||
GL.BindBuffer(BufferTarget.ArrayBuffer, _vbo);
|
|
||||||
GL.BufferData(BufferTarget.ArrayBuffer, vertices.Length * sizeof(float), vertices, BufferUsageHint.StaticDraw);
|
|
||||||
|
|
||||||
_ebo = GL.GenBuffer();
|
|
||||||
GL.BindBuffer(BufferTarget.ElementArrayBuffer, _ebo);
|
|
||||||
GL.BufferData(BufferTarget.ElementArrayBuffer, indices.Length * sizeof(uint), indices, BufferUsageHint.StaticDraw);
|
|
||||||
|
|
||||||
// --- Set up Vertex Attributes based on layout ---
|
|
||||||
if (layout == VertexLayout.PosColor)
|
|
||||||
{
|
|
||||||
// layout(location = 0) in shader: vec3 position
|
|
||||||
var stride = 7 * sizeof(float);
|
|
||||||
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, stride, 0);
|
|
||||||
GL.EnableVertexAttribArray(0);
|
|
||||||
|
|
||||||
// layout(location = 1) in shader: vec4 color
|
|
||||||
GL.VertexAttribPointer(1, 4, VertexAttribPointerType.Float, false, stride, 3 * sizeof(float));
|
|
||||||
GL.EnableVertexAttribArray(1);
|
|
||||||
}
|
|
||||||
else if (layout == VertexLayout.PosTex)
|
|
||||||
{
|
|
||||||
// layout(location = 0) in shader: vec3 position
|
|
||||||
var stride = 5 * sizeof(float);
|
|
||||||
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, stride, 0);
|
|
||||||
GL.EnableVertexAttribArray(0);
|
|
||||||
|
|
||||||
// layout(location = 1) in shader: vec2 texCoord
|
|
||||||
GL.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, stride, 3 * sizeof(float));
|
|
||||||
GL.EnableVertexAttribArray(1);
|
|
||||||
}
|
|
||||||
// ... (you could add more layouts)
|
|
||||||
|
|
||||||
GL.BindVertexArray(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Constructor for non-indexed drawing (like your Circle)
|
|
||||||
public Mesh(float[] vertices, VertexLayout layout)
|
|
||||||
{
|
|
||||||
// Calculate vertex count based on stride
|
|
||||||
if (layout == VertexLayout.PosColor)
|
|
||||||
_vertexCount = vertices.Length / 7;
|
|
||||||
else // PosTex
|
|
||||||
_vertexCount = vertices.Length / 5;
|
|
||||||
|
|
||||||
_useIndices = false;
|
|
||||||
_ebo = 0; // No EBO
|
|
||||||
|
|
||||||
_vao = GL.GenVertexArray();
|
|
||||||
GL.BindVertexArray(_vao);
|
|
||||||
|
|
||||||
_vbo = GL.GenBuffer();
|
|
||||||
GL.BindBuffer(BufferTarget.ArrayBuffer, _vbo);
|
|
||||||
GL.BufferData(BufferTarget.ArrayBuffer, vertices.Length * sizeof(float), vertices, BufferUsageHint.StaticDraw);
|
|
||||||
|
|
||||||
// --- Set up Vertex Attributes based on layout ---
|
|
||||||
if (layout == VertexLayout.PosColor)
|
|
||||||
{
|
|
||||||
// layout(location = 0) in shader: vec3 position
|
|
||||||
var stride = 7 * sizeof(float);
|
|
||||||
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, stride, 0);
|
|
||||||
GL.EnableVertexAttribArray(0);
|
|
||||||
|
|
||||||
// layout(location = 1) in shader: vec4 color
|
|
||||||
GL.VertexAttribPointer(1, 4, VertexAttribPointerType.Float, false, stride, 3 * sizeof(float));
|
|
||||||
GL.EnableVertexAttribArray(1);
|
|
||||||
}
|
|
||||||
else if (layout == VertexLayout.PosTex)
|
|
||||||
{
|
|
||||||
// layout(location = 0) in shader: vec3 position
|
|
||||||
var stride = 5 * sizeof(float);
|
|
||||||
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, stride, 0);
|
|
||||||
GL.EnableVertexAttribArray(0);
|
|
||||||
|
|
||||||
// layout(location = 1) in shader: vec2 texCoord
|
|
||||||
GL.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, stride, 3 * sizeof(float));
|
|
||||||
GL.EnableVertexAttribArray(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
GL.BindVertexArray(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Draw the mesh. Notice it doesn't know about shaders or matrices!
|
|
||||||
public void Draw()
|
|
||||||
{
|
|
||||||
GL.BindVertexArray(_vao);
|
|
||||||
|
|
||||||
if (_useIndices)
|
|
||||||
{
|
|
||||||
GL.DrawElements(PrimitiveType.Triangles, _vertexCount, DrawElementsType.UnsignedInt, 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// For your Circle (which used TriangleFan)
|
|
||||||
GL.DrawArrays(PrimitiveType.TriangleFan, 0, _vertexCount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
GL.DeleteBuffer(_vbo);
|
|
||||||
GL.DeleteBuffer(_ebo);
|
|
||||||
GL.DeleteVertexArray(_vao);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -15,17 +15,31 @@ namespace TheLabs
|
|||||||
// Negative X coordinates move to the left, positive X move to the right.
|
// Negative X coordinates move to the left, positive X move to the right.
|
||||||
// Negative Y coordinates move to the bottom, positive Y move to the top.
|
// Negative Y coordinates move to the bottom, positive Y move to the top.
|
||||||
// OpenGL only supports rendering in 3D, so to create a flat triangle, the Z coordinate will be kept as 0.
|
// OpenGL only supports rendering in 3D, so to create a flat triangle, the Z coordinate will be kept as 0.
|
||||||
|
private readonly float[] _vertices =
|
||||||
|
{
|
||||||
|
-0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, // Bottom-left vertex
|
||||||
|
0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, // Bottom-right vertex
|
||||||
|
0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, // Top vertex
|
||||||
|
};
|
||||||
|
|
||||||
|
private readonly float[] _quadvertices =
|
||||||
|
{
|
||||||
|
// x, y, z
|
||||||
|
-0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, // Bottom-left vertex
|
||||||
|
-0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, // Bottom-right vertex
|
||||||
|
0.0f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, // Top vertex
|
||||||
|
|
||||||
|
-0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, // Bottom-left vertex
|
||||||
|
0.0f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, // Bottom-right vertex
|
||||||
|
0.0f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, // Top vertex
|
||||||
|
};
|
||||||
|
|
||||||
|
private Cube _cube;
|
||||||
|
private Circle _circle;
|
||||||
|
private Cylinder _cylinder;
|
||||||
private Shader _shader;
|
private Shader _shader;
|
||||||
|
|
||||||
// - Resources that only need to be created once
|
|
||||||
private Mesh _cubeMesh;
|
|
||||||
private Texture _cubeTexture;
|
|
||||||
private float _rotation;
|
private float _rotation;
|
||||||
|
|
||||||
// -- Scene Objects
|
|
||||||
private RenderObject _cubeObject;
|
|
||||||
|
|
||||||
public MyExampleWindow(GameWindowSettings gameWindowSettings, NativeWindowSettings nativeWindowSettings)
|
public MyExampleWindow(GameWindowSettings gameWindowSettings, NativeWindowSettings nativeWindowSettings)
|
||||||
: base(gameWindowSettings, nativeWindowSettings)
|
: base(gameWindowSettings, nativeWindowSettings)
|
||||||
{
|
{
|
||||||
@ -36,28 +50,17 @@ namespace TheLabs
|
|||||||
{
|
{
|
||||||
// This is called when the window is created and is where we can set up OpenGL resources.
|
// This is called when the window is created and is where we can set up OpenGL resources.
|
||||||
base.OnLoad();
|
base.OnLoad();
|
||||||
string shaderVertPath = "Shaders/shader.vert";
|
|
||||||
string texturePath = "Textures/placeholder.png";
|
|
||||||
|
|
||||||
if (!File.Exists(shaderVertPath))
|
|
||||||
{
|
|
||||||
throw new FileNotFoundException($"The shader file was not found at: {Path.GetFullPath(shaderVertPath)}");
|
|
||||||
}
|
|
||||||
if (!File.Exists(texturePath))
|
|
||||||
{
|
|
||||||
throw new FileNotFoundException($"The texture file was not found at: {Path.GetFullPath(texturePath)}");
|
|
||||||
}
|
|
||||||
//GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line);
|
|
||||||
// Set The background color to a nice blue.
|
// Set The background color to a nice blue.
|
||||||
GL.ClearColor(0.2f, 0.3f, 0.3f, 1.0f);
|
GL.ClearColor(0.2f, 0.3f, 0.3f, 1.0f);
|
||||||
|
// Enable depth buffering.
|
||||||
GL.Enable(EnableCap.DepthTest);
|
GL.Enable(EnableCap.DepthTest);
|
||||||
|
// Create and compile our shader program from the shader source files
|
||||||
_shader = new Shader("Shaders/shader.vert", "Shaders/shader.frag");
|
_shader = new Shader("Shaders/shader.vert", "Shaders/shader.frag");
|
||||||
|
// Create a cube
|
||||||
_cubeMesh = ShapeFactory.CreateTexturedCube();
|
_circle = new Circle();
|
||||||
_cubeTexture = new Texture("Textures/placeholder.png");
|
_cylinder = new Cylinder();
|
||||||
|
// Use the shader program. This is similar to "activating" the shader program.
|
||||||
_cubeObject = new RenderObject(_cubeMesh, _shader, _cubeTexture);
|
_shader.Use();
|
||||||
_cubeObject.Position = new Vector3(-0.75f, 0.0f, 0.0f);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,9 +71,8 @@ namespace TheLabs
|
|||||||
base.OnRenderFrame(e);
|
base.OnRenderFrame(e);
|
||||||
// Clear the color buffer and the depth buffer
|
// Clear the color buffer and the depth buffer
|
||||||
GL.Clear(ClearBufferMask.DepthBufferBit | ClearBufferMask.ColorBufferBit);
|
GL.Clear(ClearBufferMask.DepthBufferBit | ClearBufferMask.ColorBufferBit);
|
||||||
_cubeObject.Rotation = Quaternion.FromEulerAngles(_rotation * 0.5f, _rotation, 0); //
|
// Create the model, view, and projection matrices
|
||||||
|
Matrix4 model = Matrix4.CreateRotationY(_rotation) * Matrix4.CreateRotationX(_rotation * 0.5f);
|
||||||
// --- Set up Camera ---
|
|
||||||
Matrix4 view = Matrix4.CreateTranslation(0.0f, 0.0f, -3.0f);
|
Matrix4 view = Matrix4.CreateTranslation(0.0f, 0.0f, -3.0f);
|
||||||
Matrix4 projection = Matrix4.CreatePerspectiveFieldOfView(
|
Matrix4 projection = Matrix4.CreatePerspectiveFieldOfView(
|
||||||
MathHelper.DegreesToRadians(45f),
|
MathHelper.DegreesToRadians(45f),
|
||||||
@ -79,22 +81,32 @@ namespace TheLabs
|
|||||||
100.0f
|
100.0f
|
||||||
);
|
);
|
||||||
|
|
||||||
_cubeObject.Draw(view, projection);
|
// Draw the cube
|
||||||
|
//_cube = new Cube();
|
||||||
|
//_cube.Draw(_shader, view, projection, _rotation);
|
||||||
|
//_circle.Draw(_shader, view, projection, model);
|
||||||
|
//_cylinder.Draw(_shader, model, view, projection);
|
||||||
SwapBuffers();
|
SwapBuffers();
|
||||||
|
GL.GetError();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnUpdateFrame(FrameEventArgs e)
|
protected override void OnUpdateFrame(FrameEventArgs e)
|
||||||
{
|
{
|
||||||
base.OnUpdateFrame(e);
|
base.OnUpdateFrame(e);
|
||||||
_rotation += (float)e.Time;
|
|
||||||
var input = KeyboardState;
|
var input = KeyboardState;
|
||||||
|
|
||||||
if (input.IsKeyDown(Keys.Escape))
|
if (input.IsKeyDown(Keys.Escape))
|
||||||
{
|
{
|
||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
|
if (input.IsKeyDown(Keys.R))
|
||||||
|
{
|
||||||
|
_rotation += 0.8f * (float)e.Time; // Update rotation only when the condition is met
|
||||||
|
} else if (input.IsKeyDown(Keys.T))
|
||||||
|
{
|
||||||
|
_rotation -= 0.8f * (float)e.Time; // Update rotation only when the condition is met
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnResize(ResizeEventArgs e)
|
protected override void OnResize(ResizeEventArgs e)
|
||||||
|
|||||||
@ -1,42 +0,0 @@
|
|||||||
using LearnOpenTK.Common;
|
|
||||||
using OpenTK.Graphics.OpenGL4;
|
|
||||||
using OpenTK.Mathematics;
|
|
||||||
|
|
||||||
namespace TheLabs;
|
|
||||||
|
|
||||||
public class RenderObject
|
|
||||||
{
|
|
||||||
public Mesh Mesh;
|
|
||||||
public Shader Shader;
|
|
||||||
public Texture Texture;
|
|
||||||
|
|
||||||
public Vector3 Position = Vector3.Zero;
|
|
||||||
public Quaternion Rotation = Quaternion.Identity;
|
|
||||||
public Vector3 Scale = Vector3.One;
|
|
||||||
|
|
||||||
public RenderObject(Mesh mesh, Shader shader, Texture texture)
|
|
||||||
{
|
|
||||||
Mesh = mesh;
|
|
||||||
Shader = shader;
|
|
||||||
Texture = texture;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Draw(Matrix4 view, Matrix4 projection)
|
|
||||||
{
|
|
||||||
// 1. Activate Shader
|
|
||||||
Shader.Use();
|
|
||||||
Shader.SetInt("uTexture", 0);
|
|
||||||
// 2. Bind Texture
|
|
||||||
Texture.Use(); // Assumes you have a Texture class
|
|
||||||
|
|
||||||
// 3. Calculate Model Matrix
|
|
||||||
Matrix4 model = Matrix4.CreateScale(Scale) * Matrix4.CreateFromQuaternion(Rotation) * Matrix4.CreateTranslation(Position);
|
|
||||||
// 4. Set Uniforms
|
|
||||||
Shader.SetMatrix4("model", model);
|
|
||||||
Shader.SetMatrix4("view", view);
|
|
||||||
Shader.SetMatrix4("projection", projection);
|
|
||||||
|
|
||||||
// 5. Tell the Mesh to draw itself
|
|
||||||
Mesh.Draw();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -2,10 +2,8 @@
|
|||||||
|
|
||||||
in vec4 outColour;
|
in vec4 outColour;
|
||||||
out vec4 outputColor;
|
out vec4 outputColor;
|
||||||
in vec2 TexCoord;
|
|
||||||
uniform sampler2D uTexture;
|
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
outputColor = texture(uTexture, TexCoord);
|
outputColor = outColour;
|
||||||
}
|
}
|
||||||
@ -26,14 +26,12 @@
|
|||||||
// Then, the keyword "vec3" means this is a vector with 3 floats inside.
|
// Then, the keyword "vec3" means this is a vector with 3 floats inside.
|
||||||
|
|
||||||
layout(location = 0) in vec3 aPosition;
|
layout(location = 0) in vec3 aPosition;
|
||||||
layout(location = 1)in vec2 aTexCoord;
|
layout(location = 1) in vec4 aColour;
|
||||||
out vec4 outColour;
|
out vec4 outColour;
|
||||||
uniform mat4 model;
|
uniform mat4 model;
|
||||||
uniform mat4 view;
|
uniform mat4 view;
|
||||||
uniform mat4 projection;
|
uniform mat4 projection;
|
||||||
|
|
||||||
out vec2 TexCoord;
|
|
||||||
|
|
||||||
// Like C, we have an entrypoint function. In this case, it takes void and returns void, and must be named main.
|
// Like C, we have an entrypoint function. In this case, it takes void and returns void, and must be named main.
|
||||||
// You can do all sorts of calculations here to modify your vertices, but right now, we don't need to do any of that.
|
// You can do all sorts of calculations here to modify your vertices, but right now, we don't need to do any of that.
|
||||||
// gl_Position is the final vertex position; pass a vec4 to it and you're done.
|
// gl_Position is the final vertex position; pass a vec4 to it and you're done.
|
||||||
@ -43,6 +41,6 @@ out vec2 TexCoord;
|
|||||||
|
|
||||||
void main(void)
|
void main(void)
|
||||||
{
|
{
|
||||||
|
outColour = aColour;
|
||||||
gl_Position = projection * view * model * vec4(aPosition, 1.0);
|
gl_Position = projection * view * model * vec4(aPosition, 1.0);
|
||||||
TexCoord = aTexCoord;
|
|
||||||
}
|
}
|
||||||
@ -1,118 +0,0 @@
|
|||||||
namespace TheLabs;
|
|
||||||
|
|
||||||
public static class ShapeFactory
|
|
||||||
{
|
|
||||||
public static Mesh CreateTexturedCube()
|
|
||||||
{
|
|
||||||
float[] vertices = {
|
|
||||||
// Front face (z = +0.5)
|
|
||||||
-0.5f, -0.5f, 0.5f, 0f, 0f, // Bottom-left
|
|
||||||
0.5f, -0.5f, 0.5f, 1f, 0f, // Bottom-right
|
|
||||||
0.5f, 0.5f, 0.5f, 1f, 1f, // Top-right
|
|
||||||
-0.5f, 0.5f, 0.5f, 0f, 1f, // Top-left
|
|
||||||
|
|
||||||
// Back face (z = -0.5)
|
|
||||||
-0.5f, -0.5f, -0.5f, 1f, 0f, // Bottom-left
|
|
||||||
0.5f, -0.5f, -0.5f, 0f, 0f, // Bottom-right
|
|
||||||
0.5f, 0.5f, -0.5f, 0f, 1f, // Top-right
|
|
||||||
-0.5f, 0.5f, -0.5f, 1f, 1f, // Top-left
|
|
||||||
|
|
||||||
// Left face (x = -0.5)
|
|
||||||
-0.5f, -0.5f, -0.5f, 0f, 0f, // Bottom-left
|
|
||||||
-0.5f, -0.5f, 0.5f, 1f, 0f, // Bottom-right
|
|
||||||
-0.5f, 0.5f, 0.5f, 1f, 1f, // Top-right
|
|
||||||
-0.5f, 0.5f, -0.5f, 0f, 1f, // Top-left
|
|
||||||
// Right face (x = +0.5)
|
|
||||||
0.5f, -0.5f, -0.5f, 1f, 0f, // Bottom-left
|
|
||||||
0.5f, -0.5f, 0.5f, 0f, 0f, // Bottom-right
|
|
||||||
0.5f, 0.5f, 0.5f, 0f, 1f, // Top-right
|
|
||||||
0.5f, 0.5f, -0.5f, 1f, 1f, // Top-left
|
|
||||||
|
|
||||||
// Top face (y = +0.5)
|
|
||||||
-0.5f, 0.5f, -0.5f, 0f, 1f, // Bottom-left
|
|
||||||
0.5f, 0.5f, -0.5f, 1f, 1f, // Bottom-right
|
|
||||||
0.5f, 0.5f, 0.5f, 1f, 0f, // Top-right
|
|
||||||
-0.5f, 0.5f, 0.5f, 0f, 0f, // Top-left
|
|
||||||
|
|
||||||
// Bottom face (y = -0.5)
|
|
||||||
-0.5f, -0.5f, -0.5f, 1f, 1f, // Bottom-left
|
|
||||||
0.5f, -0.5f, -0.5f, 0f, 1f, // Bottom-right
|
|
||||||
0.5f, -0.5f, 0.5f, 0f, 0f, // Top-right
|
|
||||||
-0.5f, -0.5f, 0.5f, 1f, 0f, // Top-left
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
uint[] indices = {
|
|
||||||
// Front face
|
|
||||||
0, 1, 2,
|
|
||||||
0, 2, 3,
|
|
||||||
// Back face
|
|
||||||
4, 5, 6,
|
|
||||||
4, 6, 7,
|
|
||||||
// Left face
|
|
||||||
8, 9, 10,
|
|
||||||
8, 10, 11,
|
|
||||||
// Right face
|
|
||||||
12, 13, 14,
|
|
||||||
12, 14, 15,
|
|
||||||
// Top face
|
|
||||||
16, 17, 18,
|
|
||||||
16, 18, 19,
|
|
||||||
// Bottom face
|
|
||||||
20, 21, 22,
|
|
||||||
20, 22, 23
|
|
||||||
};
|
|
||||||
|
|
||||||
return new Mesh(vertices, indices, Mesh.VertexLayout.PosTex);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Mesh CreateColorCube()
|
|
||||||
{
|
|
||||||
float[] vertices = {
|
|
||||||
// Front face (z = +0.5)
|
|
||||||
-0.5f, -0.5f, 0.5f, 1f, 0f, 0f, 1f, // Bottom-left
|
|
||||||
0.5f, -0.5f, 0.5f, 1f, 0f, 0f, 1f, // Bottom-right
|
|
||||||
0.5f, 0.5f, 0.5f, 0f, 0f, 0f, 1f, // Top-right
|
|
||||||
-0.5f, 0.5f, 0.5f, 1f, 0f, 0f, 1f, // Top-left
|
|
||||||
|
|
||||||
// Back face (z = -0.5)
|
|
||||||
-0.5f, -0.5f, -0.5f, 1f, 0f, 1f, 1f, // Bottom-left
|
|
||||||
0.5f, -0.5f, -0.5f, 0f, 1f, 1f, 1f, // Bottom-right
|
|
||||||
0.5f, 0.5f, -0.5f, 1f, 1f, 1f, 1f, // Top-right
|
|
||||||
-0.5f, 0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 1f // Top-left
|
|
||||||
};
|
|
||||||
|
|
||||||
uint[] indices = {
|
|
||||||
// Front face
|
|
||||||
0, 1, 2,
|
|
||||||
2, 3, 0,
|
|
||||||
|
|
||||||
// Back face
|
|
||||||
4, 5, 6,
|
|
||||||
6, 7, 4,
|
|
||||||
|
|
||||||
// Left face
|
|
||||||
4, 0, 3,
|
|
||||||
3, 7, 4,
|
|
||||||
|
|
||||||
// Right face
|
|
||||||
1, 5, 6,
|
|
||||||
6, 2, 1,
|
|
||||||
|
|
||||||
// Top face
|
|
||||||
3, 2, 6,
|
|
||||||
6, 7, 3,
|
|
||||||
|
|
||||||
// Bottom face
|
|
||||||
4, 5, 1,
|
|
||||||
1, 0, 4
|
|
||||||
};
|
|
||||||
|
|
||||||
return new Mesh(vertices, indices, Mesh.VertexLayout.PosColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
// You'd also add CreateCircle, CreateCylinder, etc.
|
|
||||||
// Your Cylinder should be ONE mesh, not 3 draw calls.
|
|
||||||
// Generate the top, bottom, and side vertices into one
|
|
||||||
// big array and use one EBO for all of it.
|
|
||||||
}
|
|
||||||
@ -29,9 +29,9 @@ public class Cylinder
|
|||||||
{
|
{
|
||||||
// The number of vertices to draw
|
// The number of vertices to draw
|
||||||
_vertexCount = _indices.Length;
|
_vertexCount = _indices.Length;
|
||||||
_topCircle = new Circle(0.5f, 10, new Vector4(1f, 1f, 0f, 1f));
|
_topCircle = new Circle(0.5f, 100, new Vector4(1f, 1f, 0f, 1f));
|
||||||
_bottomCircle = new Circle(-0.5f, 10, new Vector4(1f, 0f, 0f, 1f));
|
_bottomCircle = new Circle(-0.5f, 100, new Vector4(1f, 0f, 0f, 1f));
|
||||||
GenerateCylinder(10);
|
GenerateCylinder(100);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,163 +0,0 @@
|
|||||||
using LearnOpenTK.Common;
|
|
||||||
using OpenTK.Graphics.OpenGL4;
|
|
||||||
using OpenTK.Mathematics;
|
|
||||||
using OpenTK.Windowing.Desktop;
|
|
||||||
using StbImageSharp;
|
|
||||||
|
|
||||||
namespace TheLabs.Shapes;
|
|
||||||
|
|
||||||
public class TexturedCube
|
|
||||||
{
|
|
||||||
// Vertex Array Object, Vertex Buffer Object, Element Buffer Object
|
|
||||||
private int _vao;
|
|
||||||
private int _vbo;
|
|
||||||
private int _ebo;
|
|
||||||
private int _tb;
|
|
||||||
private int _vertexCount;
|
|
||||||
public Vector3 Position = Vector3.Zero;
|
|
||||||
|
|
||||||
private readonly float[] _cubevertices =
|
|
||||||
{
|
|
||||||
// Position // Color (RGBA)
|
|
||||||
// Front face (z = +0.5)
|
|
||||||
-0.5f, -0.5f, 0.5f, 0f, 0f, // Bottom-left
|
|
||||||
0.5f, -0.5f, 0.5f, 1f, 0f, // Bottom-right
|
|
||||||
0.5f, 0.5f, 0.5f, 1f, 1f, // Top-right
|
|
||||||
-0.5f, 0.5f, 0.5f, 0f, 1f, // Top-left
|
|
||||||
|
|
||||||
// Back face (z = -0.5)
|
|
||||||
-0.5f, -0.5f, -0.5f, 1f, 0f, // Bottom-left
|
|
||||||
0.5f, -0.5f, -0.5f, 0f, 0f, // Bottom-right
|
|
||||||
0.5f, 0.5f, -0.5f, 0f, 1f, // Top-right
|
|
||||||
-0.5f, 0.5f, -0.5f, 1f, 1f, // Top-left
|
|
||||||
|
|
||||||
// Left face (x = -0.5)
|
|
||||||
-0.5f, -0.5f, -0.5f, 0f, 0f, // Bottom-left
|
|
||||||
-0.5f, -0.5f, 0.5f, 1f, 0f, // Bottom-right
|
|
||||||
-0.5f, 0.5f, 0.5f, 1f, 1f, // Top-right
|
|
||||||
-0.5f, 0.5f, -0.5f, 0f, 1f, // Top-left
|
|
||||||
// Right face (x = +0.5)
|
|
||||||
0.5f, -0.5f, -0.5f, 1f, 0f, // Bottom-left
|
|
||||||
0.5f, -0.5f, 0.5f, 0f, 0f, // Bottom-right
|
|
||||||
0.5f, 0.5f, 0.5f, 0f, 1f, // Top-right
|
|
||||||
0.5f, 0.5f, -0.5f, 1f, 1f, // Top-left
|
|
||||||
|
|
||||||
// Top face (y = +0.5)
|
|
||||||
-0.5f, 0.5f, -0.5f, 0f, 1f, // Bottom-left
|
|
||||||
0.5f, 0.5f, -0.5f, 1f, 1f, // Bottom-right
|
|
||||||
0.5f, 0.5f, 0.5f, 1f, 0f, // Top-right
|
|
||||||
-0.5f, 0.5f, 0.5f, 0f, 0f, // Top-left
|
|
||||||
|
|
||||||
// Bottom face (y = -0.5)
|
|
||||||
-0.5f, -0.5f, -0.5f, 1f, 1f, // Bottom-left
|
|
||||||
0.5f, -0.5f, -0.5f, 0f, 1f, // Bottom-right
|
|
||||||
0.5f, -0.5f, 0.5f, 0f, 0f, // Top-right
|
|
||||||
-0.5f, -0.5f, 0.5f, 1f, 0f, // Top-left
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
private readonly uint[] _cubeIndices =
|
|
||||||
{
|
|
||||||
// Front face
|
|
||||||
0, 2, 1,
|
|
||||||
0, 2, 3,
|
|
||||||
// Back face
|
|
||||||
4, 5, 6,
|
|
||||||
4, 6, 7,
|
|
||||||
// Left face
|
|
||||||
8, 9, 10,
|
|
||||||
8, 10, 11,
|
|
||||||
// Right face
|
|
||||||
12, 14, 13,
|
|
||||||
12, 14, 15,
|
|
||||||
// Top face
|
|
||||||
16, 17, 18,
|
|
||||||
16, 18, 19,
|
|
||||||
// Bottom face
|
|
||||||
20, 22, 21,
|
|
||||||
20, 22, 23
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
public TexturedCube()
|
|
||||||
{
|
|
||||||
_tb = GL.GenTexture();
|
|
||||||
GL.BindTexture(TextureTarget.Texture2D, _tb);
|
|
||||||
StbImage.stbi_set_flip_vertically_on_load(1);
|
|
||||||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat);
|
|
||||||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat);
|
|
||||||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.LinearMipmapLinear);
|
|
||||||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
|
|
||||||
// Load the image
|
|
||||||
ImageResult image = ImageResult.FromStream(File.OpenRead("Textures/placeholder.png"), ColorComponents.RedGreenBlueAlpha);
|
|
||||||
GL.TexImage2D(TextureTarget.Texture2D,0, PixelInternalFormat.Rgba, image.Width, image.Height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, image.Data);
|
|
||||||
GL.GenerateMipmap(GenerateMipmapTarget.Texture2D);
|
|
||||||
// The number of vertices to draw
|
|
||||||
_vertexCount = _cubeIndices.Length;
|
|
||||||
// The Vertex Array Object
|
|
||||||
// This stores the confifuration of vertex atributes
|
|
||||||
_vao = GL.GenVertexArray();
|
|
||||||
// The Vertex Buffer Object
|
|
||||||
// This stores the actual vertex data e.g. positions, colors, normals, texture coordinates
|
|
||||||
_vbo = GL.GenBuffer();
|
|
||||||
// The Element Buffer Object, stores the indices for indexed drawing
|
|
||||||
_ebo = GL.GenBuffer();
|
|
||||||
|
|
||||||
// We bind the VAO
|
|
||||||
GL.BindVertexArray(_vao);
|
|
||||||
GL.BindBuffer(BufferTarget.ArrayBuffer, _vbo); // Specifying the type of buffer
|
|
||||||
// Uploading the vertex data to the GPU
|
|
||||||
GL.BufferData(BufferTarget.ArrayBuffer, _cubevertices.Length * sizeof(float), _cubevertices, BufferUsageHint.StaticDraw);
|
|
||||||
|
|
||||||
// Now we set up the EBO
|
|
||||||
GL.BindBuffer(BufferTarget.ElementArrayBuffer, _ebo);
|
|
||||||
// Uploading the index data to the GPU
|
|
||||||
GL.BufferData(BufferTarget.ElementArrayBuffer, _cubeIndices.Length * sizeof(uint), _cubeIndices, BufferUsageHint.StaticDraw);
|
|
||||||
|
|
||||||
// We tell opengl how to interpret the vertex data.
|
|
||||||
// The Location 0 corresponds to the layout(location = 0) in the vertex shader
|
|
||||||
// How many components (x, y, z) -> 3
|
|
||||||
// Data type -> float
|
|
||||||
// Not normalized
|
|
||||||
// The Stride -> The total size of a vertex (in bytes)
|
|
||||||
// The offset -> The position data starts at the beginning of the vertex data so 0
|
|
||||||
var stride = 5 * sizeof(float);
|
|
||||||
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, stride, 0);
|
|
||||||
GL.EnableVertexAttribArray(0);
|
|
||||||
|
|
||||||
GL.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, 5 * sizeof(float), 3 * sizeof(float));
|
|
||||||
GL.EnableVertexAttribArray(1);
|
|
||||||
GL.BindVertexArray(0);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void Draw(Shader shader, Matrix4 view, Matrix4 projection, float rotation)
|
|
||||||
{
|
|
||||||
// Create the model matrix with rotation and translation
|
|
||||||
Matrix4 model = Matrix4.CreateRotationY(rotation) * Matrix4.CreateRotationX(rotation * 0.5f) * Matrix4.CreateTranslation(Position);
|
|
||||||
|
|
||||||
shader.Use();
|
|
||||||
GL.Uniform1(GL.GetUniformLocation(shader.Handle, "uTexture"), 0);
|
|
||||||
GL.UniformMatrix4(GL.GetUniformLocation(shader.Handle, "model"), false, ref model);
|
|
||||||
GL.UniformMatrix4(GL.GetUniformLocation(shader.Handle, "view"), false, ref view);
|
|
||||||
GL.UniformMatrix4(GL.GetUniformLocation(shader.Handle, "projection"), false, ref projection);
|
|
||||||
int texLoc = GL.GetUniformLocation(shader.Handle, "uTexture");
|
|
||||||
GL.Uniform1(texLoc, 0);
|
|
||||||
|
|
||||||
GL.ActiveTexture(TextureUnit.Texture0);
|
|
||||||
GL.BindTexture(TextureTarget.Texture2D, _tb);
|
|
||||||
|
|
||||||
GL.BindVertexArray(_vao);
|
|
||||||
GL.DrawElements(PrimitiveType.Triangles, _vertexCount, DrawElementsType.UnsignedInt, 0);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
GL.DeleteBuffer(_vbo);
|
|
||||||
GL.DeleteBuffer(_ebo);
|
|
||||||
GL.DeleteVertexArray(_vao);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,61 +0,0 @@
|
|||||||
namespace TheLabs;
|
|
||||||
|
|
||||||
using OpenTK.Graphics.OpenGL4;
|
|
||||||
using StbImageSharp;
|
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
public class Texture : IDisposable
|
|
||||||
{
|
|
||||||
public readonly int Handle;
|
|
||||||
|
|
||||||
public Texture(string path)
|
|
||||||
{
|
|
||||||
// Generate the handle
|
|
||||||
Handle = GL.GenTexture();
|
|
||||||
|
|
||||||
// Bind the texture so we can configure it
|
|
||||||
GL.ActiveTexture(TextureUnit.Texture0);
|
|
||||||
GL.BindTexture(TextureTarget.Texture2D, Handle);
|
|
||||||
|
|
||||||
// --- Set texture parameters ---
|
|
||||||
// Repeat the texture if UVs go outside [0, 1]
|
|
||||||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat);
|
|
||||||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat);
|
|
||||||
|
|
||||||
// Set filter for shrinking (mipmap) and stretching (linear)
|
|
||||||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.LinearMipmapLinear);
|
|
||||||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
|
|
||||||
|
|
||||||
// --- Load and upload the image data ---
|
|
||||||
StbImage.stbi_set_flip_vertically_on_load(1);
|
|
||||||
|
|
||||||
// Load the image from disk
|
|
||||||
using (var stream = File.OpenRead(path))
|
|
||||||
{
|
|
||||||
ImageResult image = ImageResult.FromStream(stream, ColorComponents.RedGreenBlueAlpha);
|
|
||||||
|
|
||||||
// Upload data to the GPU
|
|
||||||
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba,
|
|
||||||
image.Width, image.Height, 0,
|
|
||||||
PixelFormat.Rgba, PixelType.UnsignedByte, image.Data);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate mipmaps for better quality shrinking
|
|
||||||
GL.GenerateMipmap(GenerateMipmapTarget.Texture2D);
|
|
||||||
|
|
||||||
// Unbind the texture
|
|
||||||
GL.BindTexture(TextureTarget.Texture2D, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// A simple method to bind the texture to a specific unit
|
|
||||||
public void Use(TextureUnit unit = TextureUnit.Texture0)
|
|
||||||
{
|
|
||||||
GL.ActiveTexture(unit);
|
|
||||||
GL.BindTexture(TextureTarget.Texture2D, Handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
GL.DeleteTexture(Handle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 6.6 KiB |
@ -9,7 +9,6 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="OpenTK" Version="4.8.2" />
|
<PackageReference Include="OpenTK" Version="4.8.2" />
|
||||||
<PackageReference Include="StbImageSharp" Version="2.30.15" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@ -15,7 +15,6 @@
|
|||||||
<PackageReference Include="MSTest.TestAdapter" Version="3.1.1" />
|
<PackageReference Include="MSTest.TestAdapter" Version="3.1.1" />
|
||||||
<PackageReference Include="MSTest.TestFramework" Version="3.1.1" />
|
<PackageReference Include="MSTest.TestFramework" Version="3.1.1" />
|
||||||
<PackageReference Include="OpenTK" Version="4.8.2" />
|
<PackageReference Include="OpenTK" Version="4.8.2" />
|
||||||
<PackageReference Include="StbImageSharp" Version="2.30.15" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user