mirror of
https://github.com/UOH-CS-Level5/551455-graphics-programming-2526-the-repo-Zyb3rWolfi.git
synced 2025-11-29 00:43:08 +00:00
Compare commits
No commits in common. "da9990908ac7e33bffdd836379b289b5e06419cb" and "fe63a6d9380fed35006642dd44d3fe33e78e2595" have entirely different histories.
da9990908a
...
fe63a6d938
@ -1,67 +0,0 @@
|
|||||||
using OpenTK.Mathematics;
|
|
||||||
|
|
||||||
namespace TheLabs;
|
|
||||||
|
|
||||||
public static class Helpers
|
|
||||||
{
|
|
||||||
public static void CalculateTangent(ref Vertex v1, ref Vertex v2, ref Vertex v3)
|
|
||||||
{
|
|
||||||
// 1. Calculate Edge Vectors (Geometry)
|
|
||||||
Vector3 edge1 = v2.Position - v1.Position;
|
|
||||||
Vector3 edge2 = v3.Position - v1.Position;
|
|
||||||
|
|
||||||
// 2. Calculate Edge Vectors (Texture Space)
|
|
||||||
Vector2 deltaUV1 = v2.TexCoords - v1.TexCoords;
|
|
||||||
Vector2 deltaUV2 = v3.TexCoords - v1.TexCoords;
|
|
||||||
|
|
||||||
// 3. The Math (Solving linear equations)
|
|
||||||
float f = 1.0f / (deltaUV1.X * deltaUV2.Y - deltaUV2.X * deltaUV1.Y);
|
|
||||||
|
|
||||||
Vector3 tangent;
|
|
||||||
tangent.X = f * (deltaUV2.Y * edge1.X - deltaUV1.Y * edge2.X);
|
|
||||||
tangent.Y = f * (deltaUV2.Y * edge1.Y - deltaUV1.Y * edge2.Y);
|
|
||||||
tangent.Z = f * (deltaUV2.Y * edge1.Z - deltaUV1.Y * edge2.Z);
|
|
||||||
|
|
||||||
// Normalize it
|
|
||||||
tangent = Vector3.Normalize(tangent);
|
|
||||||
Vector3 bitangent = Vector3.Normalize(Vector3.Cross(edge1, edge2));
|
|
||||||
|
|
||||||
// 4. Assign the same tangent to all 3 vertices of the triangle
|
|
||||||
// (For smooth objects, you would average them, but for a cube, this is fine)
|
|
||||||
v1.Tangent = tangent; v1.Bitangent = bitangent;
|
|
||||||
v2.Tangent = tangent; v2.Bitangent = bitangent;
|
|
||||||
v3.Tangent = tangent; v3.Bitangent = bitangent;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void AddFace(List<Vertex> vertices, List<uint> indices,
|
|
||||||
Vertex v0, Vertex v1, Vertex v2, Vertex v3)
|
|
||||||
{
|
|
||||||
// 1. Calculate Tangents
|
|
||||||
// We calculate it twice to ensure the tangent is consistent across the whole face
|
|
||||||
// Triangle 1 (Bottom-Left, Bottom-Right, Top-Right)
|
|
||||||
CalculateTangent(ref v0, ref v1, ref v2);
|
|
||||||
// Triangle 2 (Bottom-Left, Top-Right, Top-Left)
|
|
||||||
CalculateTangent(ref v0, ref v2, ref v3);
|
|
||||||
|
|
||||||
// 2. Track where these new vertices start in the main list
|
|
||||||
// (If the list has 4 items, the new ones start at index 4)
|
|
||||||
uint offset = (uint)vertices.Count;
|
|
||||||
|
|
||||||
// 3. Add Vertices to the list
|
|
||||||
vertices.Add(v0); // Index: offset + 0
|
|
||||||
vertices.Add(v1); // Index: offset + 1
|
|
||||||
vertices.Add(v2); // Index: offset + 2
|
|
||||||
vertices.Add(v3); // Index: offset + 3
|
|
||||||
|
|
||||||
// 4. Add Indices for the two triangles (Standard Quad)
|
|
||||||
// Triangle 1
|
|
||||||
indices.Add(offset + 0);
|
|
||||||
indices.Add(offset + 1);
|
|
||||||
indices.Add(offset + 2);
|
|
||||||
|
|
||||||
// Triangle 2
|
|
||||||
indices.Add(offset + 0);
|
|
||||||
indices.Add(offset + 2);
|
|
||||||
indices.Add(offset + 3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -11,21 +11,12 @@ public struct Lighting
|
|||||||
public Vector3 diffuseColour;
|
public Vector3 diffuseColour;
|
||||||
public Vector3 specularColour;
|
public Vector3 specularColour;
|
||||||
|
|
||||||
public float constant;
|
|
||||||
public float linear;
|
|
||||||
public float quadratic;
|
|
||||||
|
|
||||||
public Lighting(Vector3 pos, Vector3 ambient, Vector3 diffuse, Vector3 specular)
|
public Lighting(Vector3 pos, Vector3 ambient, Vector3 diffuse, Vector3 specular)
|
||||||
{
|
{
|
||||||
position = pos;
|
position = pos;
|
||||||
ambientColour = ambient;
|
ambientColour = ambient;
|
||||||
diffuseColour = diffuse;
|
diffuseColour = diffuse;
|
||||||
specularColour = specular;
|
specularColour = specular;
|
||||||
|
|
||||||
constant = 1.0f;
|
|
||||||
linear = 0.09f;
|
|
||||||
quadratic = 0.032f;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Apply(Shader shader)
|
public void Apply(Shader shader)
|
||||||
@ -34,10 +25,5 @@ public struct Lighting
|
|||||||
GL.Uniform3(GL.GetUniformLocation(shader.Handle, "uPointLight.ambientColour"), ref ambientColour);
|
GL.Uniform3(GL.GetUniformLocation(shader.Handle, "uPointLight.ambientColour"), ref ambientColour);
|
||||||
GL.Uniform3(GL.GetUniformLocation(shader.Handle, "uPointLight.diffuseColour"), ref diffuseColour);
|
GL.Uniform3(GL.GetUniformLocation(shader.Handle, "uPointLight.diffuseColour"), ref diffuseColour);
|
||||||
GL.Uniform3(GL.GetUniformLocation(shader.Handle, "uPointLight.specularColour"), ref specularColour);
|
GL.Uniform3(GL.GetUniformLocation(shader.Handle, "uPointLight.specularColour"), ref specularColour);
|
||||||
|
|
||||||
GL.Uniform1(GL.GetUniformLocation(shader.Handle, "uPointLight.constant"), constant);
|
|
||||||
GL.Uniform1(GL.GetUniformLocation(shader.Handle, "uPointLight.linear"), linear);
|
|
||||||
GL.Uniform1(GL.GetUniformLocation(shader.Handle, "uPointLight.quadratic"), quadratic);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -12,7 +12,7 @@ public class Mesh : IDisposable
|
|||||||
private readonly int _vertexCount;
|
private readonly int _vertexCount;
|
||||||
private readonly bool _useIndices;
|
private readonly bool _useIndices;
|
||||||
|
|
||||||
public enum VertexLayout { PosColor, PosTex, PosTexNormal, PosTexNormalTangent }
|
public enum VertexLayout { PosColor, PosTex, PosTexNormal }
|
||||||
|
|
||||||
public Mesh(float[] vertices, uint[] indices, VertexLayout layout)
|
public Mesh(float[] vertices, uint[] indices, VertexLayout layout)
|
||||||
{
|
{
|
||||||
@ -65,7 +65,7 @@ public class Mesh : IDisposable
|
|||||||
if (layout == VertexLayout.PosColor)
|
if (layout == VertexLayout.PosColor)
|
||||||
{
|
{
|
||||||
// Stride = 7 floats (3 Pos + 4 Color)
|
// Stride = 7 floats (3 Pos + 4 Color)
|
||||||
var stride = 14 * sizeof(float);
|
var stride = 7 * sizeof(float);
|
||||||
|
|
||||||
// Location 0: Position
|
// Location 0: Position
|
||||||
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, stride, 0);
|
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, stride, 0);
|
||||||
@ -77,13 +77,6 @@ public class Mesh : IDisposable
|
|||||||
|
|
||||||
GL.VertexAttribPointer(2, 2, VertexAttribPointerType.Float, false, stride, 3 * sizeof(float));
|
GL.VertexAttribPointer(2, 2, VertexAttribPointerType.Float, false, stride, 3 * sizeof(float));
|
||||||
GL.EnableVertexAttribArray(2);
|
GL.EnableVertexAttribArray(2);
|
||||||
|
|
||||||
GL.VertexAttribPointer(3, 3, VertexAttribPointerType.Float, false, stride, 8 * sizeof(float));
|
|
||||||
GL.EnableVertexAttribArray(3);
|
|
||||||
|
|
||||||
// Loc 4: Bitangent (Offset 11) <-- NEW
|
|
||||||
GL.VertexAttribPointer(4, 3, VertexAttribPointerType.Float, false, stride, 11 * sizeof(float));
|
|
||||||
GL.EnableVertexAttribArray(4);
|
|
||||||
}
|
}
|
||||||
else if (layout == VertexLayout.PosTex)
|
else if (layout == VertexLayout.PosTex)
|
||||||
{
|
{
|
||||||
@ -103,7 +96,7 @@ public class Mesh : IDisposable
|
|||||||
else if (layout == VertexLayout.PosTexNormal)
|
else if (layout == VertexLayout.PosTexNormal)
|
||||||
{
|
{
|
||||||
// Stride = 8 floats (3 Pos + 3 Normal + 2 Tex)
|
// Stride = 8 floats (3 Pos + 3 Normal + 2 Tex)
|
||||||
var stride = 14 * sizeof(float);
|
var stride = 8 * sizeof(float);
|
||||||
|
|
||||||
// Location 0: Position
|
// Location 0: Position
|
||||||
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, stride, 0);
|
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, stride, 0);
|
||||||
@ -116,32 +109,6 @@ public class Mesh : IDisposable
|
|||||||
// Location 2: TexCoord (Offset 6 floats: 3 pos + 3 normal)
|
// Location 2: TexCoord (Offset 6 floats: 3 pos + 3 normal)
|
||||||
GL.VertexAttribPointer(2, 2, VertexAttribPointerType.Float, false, stride, 6 * sizeof(float));
|
GL.VertexAttribPointer(2, 2, VertexAttribPointerType.Float, false, stride, 6 * sizeof(float));
|
||||||
GL.EnableVertexAttribArray(2);
|
GL.EnableVertexAttribArray(2);
|
||||||
|
|
||||||
}
|
|
||||||
else if (layout == VertexLayout.PosTexNormalTangent)
|
|
||||||
{
|
|
||||||
// --- NEW LOGIC FOR CUBES (Stride 14) ---
|
|
||||||
var stride = 14 * sizeof(float);
|
|
||||||
|
|
||||||
// Loc 0: Position
|
|
||||||
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, stride, 0);
|
|
||||||
GL.EnableVertexAttribArray(0);
|
|
||||||
|
|
||||||
// Loc 1: Normal
|
|
||||||
GL.VertexAttribPointer(1, 3, VertexAttribPointerType.Float, false, stride, 3 * sizeof(float));
|
|
||||||
GL.EnableVertexAttribArray(1);
|
|
||||||
|
|
||||||
// Loc 2: TexCoord
|
|
||||||
GL.VertexAttribPointer(2, 2, VertexAttribPointerType.Float, false, stride, 6 * sizeof(float));
|
|
||||||
GL.EnableVertexAttribArray(2);
|
|
||||||
|
|
||||||
// Loc 3: Tangent
|
|
||||||
GL.VertexAttribPointer(3, 3, VertexAttribPointerType.Float, false, stride, 8 * sizeof(float));
|
|
||||||
GL.EnableVertexAttribArray(3);
|
|
||||||
|
|
||||||
// Loc 4: Bitangent
|
|
||||||
GL.VertexAttribPointer(4, 3, VertexAttribPointerType.Float, false, stride, 11 * sizeof(float));
|
|
||||||
GL.EnableVertexAttribArray(4);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -58,9 +58,8 @@ namespace TheLabs
|
|||||||
base.OnLoad();
|
base.OnLoad();
|
||||||
|
|
||||||
// --- Set up Lighting and Material ---
|
// --- Set up Lighting and Material ---
|
||||||
_mainLight = new Lighting(new Vector3(
|
_mainLight = new Lighting(new Vector3(1.2f, 1.0f, 2.0f),
|
||||||
1.2f, 1.0f, 2.0f),
|
new Vector3(0.3f),
|
||||||
new Vector3(0.5f),
|
|
||||||
new Vector3(1.5f),
|
new Vector3(1.5f),
|
||||||
new Vector3(1.0f));
|
new Vector3(1.0f));
|
||||||
|
|
||||||
@ -79,17 +78,14 @@ namespace TheLabs
|
|||||||
|
|
||||||
// -- Load Shaders, Textures, and Create Scene Objects ---
|
// -- Load Shaders, Textures, and Create Scene Objects ---
|
||||||
_shader = new Shader("Shaders/shader.vert", "Shaders/shader.frag");
|
_shader = new Shader("Shaders/shader.vert", "Shaders/shader.frag");
|
||||||
_texture = new Texture("Textures/cobble.jpg");
|
_texture = new Texture("Textures/placeholder.png");
|
||||||
Texture _normalMap = new Texture("Textures/cobbleNormal.jpg");
|
|
||||||
|
|
||||||
|
|
||||||
// --- Create Scene Graph ---
|
// --- Create Scene Graph ---
|
||||||
_rootNode = new SceneNode();
|
_rootNode = new SceneNode();
|
||||||
|
|
||||||
// Create Example Object
|
// Create Example Object
|
||||||
_buildingObject = ShapeFactory.CreateTexturedCube();
|
_buildingObject = ShapeFactory.CreateTexturedSphere();
|
||||||
_buildingRender = new RenderObject(_buildingObject, _shader, _texture, _defaultMaterial, _mainLight);
|
_buildingRender = new RenderObject(_buildingObject, _shader, _texture, _defaultMaterial, _mainLight);
|
||||||
_buildingRender.NormalMap = _normalMap;
|
|
||||||
_buildingNode = new SceneNode(_buildingRender);
|
_buildingNode = new SceneNode(_buildingRender);
|
||||||
_buildingNode.Position = new Vector3(2.0f, -1.0f, 0.0f);
|
_buildingNode.Position = new Vector3(2.0f, -1.0f, 0.0f);
|
||||||
_buildingNode.Scale = new Vector3(0.1f, 0.1f, 0.1f);
|
_buildingNode.Scale = new Vector3(0.1f, 0.1f, 0.1f);
|
||||||
|
|||||||
@ -9,7 +9,6 @@ public class RenderObject
|
|||||||
public Mesh Mesh;
|
public Mesh Mesh;
|
||||||
public Shader Shader;
|
public Shader Shader;
|
||||||
public Texture Texture;
|
public Texture Texture;
|
||||||
public Texture NormalMap;
|
|
||||||
public Material Material;
|
public Material Material;
|
||||||
public Lighting Lighting;
|
public Lighting Lighting;
|
||||||
|
|
||||||
@ -17,7 +16,6 @@ public class RenderObject
|
|||||||
public Matrix4 Transform = Matrix4.Identity;
|
public Matrix4 Transform = Matrix4.Identity;
|
||||||
public Quaternion Rotation = Quaternion.Identity;
|
public Quaternion Rotation = Quaternion.Identity;
|
||||||
public Vector3 Scale = Vector3.One;
|
public Vector3 Scale = Vector3.One;
|
||||||
public bool UseTexture = true;
|
|
||||||
|
|
||||||
public RenderObject(Mesh mesh, Shader shader, Texture texture, Material material, Lighting lighting)
|
public RenderObject(Mesh mesh, Shader shader, Texture texture, Material material, Lighting lighting)
|
||||||
{
|
{
|
||||||
@ -40,27 +38,8 @@ public class RenderObject
|
|||||||
Material mat = new Material(pink * 0.1f, pink * 0.6f, Vector3.One, 32.0f);
|
Material mat = new Material(pink * 0.1f, pink * 0.6f, Vector3.One, 32.0f);
|
||||||
|
|
||||||
Shader.Use();
|
Shader.Use();
|
||||||
if (Texture != null && UseTexture)
|
Texture.Use();
|
||||||
{
|
Shader.SetInt("uTexture", 0);
|
||||||
Texture.Use(TextureUnit.Texture0);
|
|
||||||
Shader.SetInt("uTexture", 0);
|
|
||||||
GL.Uniform1(GL.GetUniformLocation(Shader.Handle, "uUseTexture"), 1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
GL.Uniform1(GL.GetUniformLocation(Shader.Handle, "uUseTexture"), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NormalMap != null)
|
|
||||||
{
|
|
||||||
NormalMap.Use(TextureUnit.Texture1);
|
|
||||||
Shader.SetInt("uNormalMap", 1);
|
|
||||||
GL.Uniform1(GL.GetUniformLocation(Shader.Handle, "uUseNormalMap"), 1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
GL.Uniform1(GL.GetUniformLocation(Shader.Handle, "uUseNormalMap"), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
Material.Apply(Shader);
|
Material.Apply(Shader);
|
||||||
light.Apply(Shader);
|
light.Apply(Shader);
|
||||||
|
|||||||
@ -9,7 +9,6 @@ out vec4 outputColor; // The final output color of the fragment
|
|||||||
in vec3 FragPos;
|
in vec3 FragPos;
|
||||||
in vec3 Normal;
|
in vec3 Normal;
|
||||||
in vec2 TexCoord;
|
in vec2 TexCoord;
|
||||||
in mat3 vTBN; // Tangent, Bitangent, Normal matrix
|
|
||||||
|
|
||||||
struct MaterialProperty {
|
struct MaterialProperty {
|
||||||
vec3 ambientColour;
|
vec3 ambientColour;
|
||||||
@ -23,75 +22,60 @@ struct LightProperty {
|
|||||||
vec3 ambientColour;
|
vec3 ambientColour;
|
||||||
vec3 diffuseColour;
|
vec3 diffuseColour;
|
||||||
vec3 specularColour;
|
vec3 specularColour;
|
||||||
|
|
||||||
float constant;
|
|
||||||
float linear;
|
|
||||||
float quadratic;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- UNIFORMS ---
|
// --- UNIFORMS ---
|
||||||
uniform sampler2D uTexture; // Image Texture
|
uniform sampler2D uTexture; // Image Texture
|
||||||
uniform sampler2D uNormalMap; // Normal Map Texture
|
|
||||||
uniform vec3 uViewPos; // Camera Position
|
uniform vec3 uViewPos; // Camera Position
|
||||||
uniform MaterialProperty uMaterial; // Material Properties
|
uniform MaterialProperty uMaterial; // Material Properties
|
||||||
uniform LightProperty uPointLight; // Light Properties
|
uniform LightProperty uPointLight; // Light Properties
|
||||||
uniform int uUseTexture; // Flag to indicate if texture should be used
|
|
||||||
uniform int uUseNormalMap; // Flag to indicate if normal map should be used
|
|
||||||
|
|
||||||
|
|
||||||
vec3 CalcPointLight(LightProperty light, vec3 normal, vec3 fragPos, vec3 viewDir) {
|
|
||||||
vec3 lightDir = normalize(light.position - fragPos);
|
|
||||||
|
|
||||||
// 1. Diffuse shading
|
|
||||||
float diff = max(dot(normal, lightDir), 0.0);
|
|
||||||
|
|
||||||
// 2. Specular shading
|
|
||||||
vec3 reflectDir = reflect(-lightDir, normal);
|
|
||||||
float spec = pow(max(dot(viewDir, reflectDir), 0.0), uMaterial.shininess);
|
|
||||||
|
|
||||||
// 3. Attenuation
|
|
||||||
float distance = length(light.position - fragPos);
|
|
||||||
float attenuation = 1.0 / (light.constant + light.linear * distance +
|
|
||||||
light.quadratic * (distance * distance));
|
|
||||||
|
|
||||||
// 4. Combine results
|
|
||||||
vec3 ambient = light.ambientColour * uMaterial.ambientColour;
|
|
||||||
vec3 diffuse = light.diffuseColour * diff * uMaterial.diffuseColour;
|
|
||||||
vec3 specular = light.specularColour * spec * uMaterial.specularColour;
|
|
||||||
|
|
||||||
ambient *= attenuation;
|
|
||||||
diffuse *= attenuation;
|
|
||||||
specular *= attenuation;
|
|
||||||
|
|
||||||
return (ambient + diffuse + specular);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
vec3 norm;
|
// --- LIGHTING CALCULATIONS ---
|
||||||
|
// Lighting Setup (hardcoded for simplicity)
|
||||||
|
vec3 lightPos = vec3(1.2f, 1.0f, 2.0f);
|
||||||
|
vec3 lightColor = vec3(1.0f, 1.0f, 1.0f);
|
||||||
|
|
||||||
|
// 1. Get Texture Color
|
||||||
|
// Sample the texture at the given texture coordinates
|
||||||
|
vec4 objColor = texture(uTexture, TexCoord);
|
||||||
|
|
||||||
|
// 2. Ambient strength
|
||||||
|
// A constant, dim light that ensure s object are not completely dark
|
||||||
|
// It simply multiplies the light color by a small factor
|
||||||
|
float ambientStrength = 0.1f;
|
||||||
|
vec3 ambient = uMaterial.ambientColour * uPointLight.ambientColour;
|
||||||
|
|
||||||
|
// 3. Diffuse
|
||||||
|
// Creates the "matte" effect by calculating the angle between the light direction and the surface normal
|
||||||
|
|
||||||
if (uUseNormalMap == 1) {
|
// Normalize the normal vector and calculate the light direction
|
||||||
vec3 normalFromTexture = texture(uNormalMap, TexCoord).rgb;
|
vec3 norm = normalize(Normal);
|
||||||
vec3 colourShift = normalFromTexture * 2.0 - 1.0; // Transform from [0,1] to [-1,1]
|
vec3 lightDir = normalize(uPointLight.position - FragPos);
|
||||||
// 1. Setup Vectors
|
|
||||||
norm = normalize(vTBN * colourShift);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
norm = normalize(Normal);
|
|
||||||
}
|
|
||||||
|
|
||||||
vec3 viewDir = normalize(uViewPos - FragPos);
|
|
||||||
|
|
||||||
// 2. Calculate Lighting using the Function
|
|
||||||
vec3 result = CalcPointLight(uPointLight, norm, FragPos, viewDir);
|
|
||||||
|
|
||||||
// 3. Apply Texture Switch
|
|
||||||
if (uUseTexture == 1) {
|
|
||||||
|
|
||||||
outputColor = vec4(result, 1.0) * texture(uTexture, TexCoord);
|
|
||||||
} else {
|
|
||||||
outputColor = vec4(result, 1.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// The dot product gives us the cosine of the angle between the two vectors
|
||||||
|
// The max function ensures we don't get negative values (light coming from behind the surface)
|
||||||
|
float diff = max(dot(norm, lightDir), 0.0f);
|
||||||
|
vec3 diffuse = (uPointLight.diffuseColour * diff) * uMaterial.diffuseColour;
|
||||||
|
|
||||||
|
// 4. Specular
|
||||||
|
// Creates the shiny highlights on the surface
|
||||||
|
float shininess = 32.0f;
|
||||||
|
// Calculate the view direction and the reflection direction
|
||||||
|
vec3 viewDirection = normalize(uViewPos - FragPos);
|
||||||
|
// If the light is coming from the light direction, we need to negate it for reflection
|
||||||
|
vec3 reflectDirection = reflect(-lightDir, normalize(Normal));
|
||||||
|
|
||||||
|
// Calculate the specular component using the dot product and shininess factor
|
||||||
|
float spec = pow(max(dot(viewDirection, reflectDirection), 0.0f), shininess);
|
||||||
|
vec3 specular = uMaterial.specularColour * spec * uPointLight.specularColour;
|
||||||
|
|
||||||
|
// 5. Combine
|
||||||
|
// We multiply (Ambient + Diffuse) by the Texture Color.
|
||||||
|
// We ADD Specular afterwards so the highlights look bright white (like plastic/metal).
|
||||||
|
vec3 result = (ambient + diffuse) * objColor.rgb + specular;
|
||||||
|
|
||||||
|
outputColor = vec4(result, objColor.a);
|
||||||
}
|
}
|
||||||
@ -7,15 +7,12 @@
|
|||||||
layout(location = 0) in vec3 aPosition; // Raw 3D position
|
layout(location = 0) in vec3 aPosition; // Raw 3D position
|
||||||
layout(location = 1) in vec3 aNormal; // The direction perpendicular to the surface
|
layout(location = 1) in vec3 aNormal; // The direction perpendicular to the surface
|
||||||
layout(location = 2) in vec2 aTexCoord; // The U,V texture coordinates
|
layout(location = 2) in vec2 aTexCoord; // The U,V texture coordinates
|
||||||
layout(location = 3) in vec3 aTangent; // Tangent vector for normal mapping
|
|
||||||
layout(location = 4) in vec3 aBitangent; // Bitangent vector for normal mapping
|
|
||||||
|
|
||||||
// --- OUTPUTS ---
|
// --- OUTPUTS ---
|
||||||
// We can pass data to the fragment shader through these
|
// We can pass data to the fragment shader through these
|
||||||
out vec3 FragPos;
|
out vec3 FragPos;
|
||||||
out vec3 Normal;
|
out vec3 Normal;
|
||||||
out vec2 TexCoord;
|
out vec2 TexCoord;
|
||||||
out mat3 vTBN;
|
|
||||||
|
|
||||||
// --- UNIFORMS ---
|
// --- UNIFORMS ---
|
||||||
// These are matrices that help transform our vertices
|
// These are matrices that help transform our vertices
|
||||||
@ -25,12 +22,6 @@ uniform mat4 projection;
|
|||||||
|
|
||||||
void main(void)
|
void main(void)
|
||||||
{
|
{
|
||||||
vec3 T = normalize(vec3(model * vec4(aTangent, 0.0)));
|
|
||||||
vec3 B = normalize(vec3(model * vec4(aBitangent, 0.0)));
|
|
||||||
vec3 N = normalize(vec3(model * vec4(aNormal, 0.0)));
|
|
||||||
|
|
||||||
vTBN = mat3(T, B, N);
|
|
||||||
|
|
||||||
// 1. Calculate World Position
|
// 1. Calculate World Position
|
||||||
FragPos = vec3(model * vec4(aPosition, 1.0));
|
FragPos = vec3(model * vec4(aPosition, 1.0));
|
||||||
|
|
||||||
|
|||||||
@ -1,83 +1,72 @@
|
|||||||
using OpenTK.Mathematics;
|
namespace TheLabs;
|
||||||
|
|
||||||
namespace TheLabs;
|
|
||||||
|
|
||||||
public static class ShapeFactory
|
public static class ShapeFactory
|
||||||
{
|
{
|
||||||
public static Mesh CreateTexturedCube()
|
public static Mesh CreateTexturedCube()
|
||||||
{
|
{
|
||||||
List<Vertex> vertices = new List<Vertex>();
|
float[] vertices = {
|
||||||
List<uint> indices = new List<uint>();
|
// Format: X, Y, Z, NX, NY, NZ, U, V
|
||||||
|
|
||||||
// --- FRONT FACE (Normal 0, 0, 1) ---
|
// --- Front Face (Normal points +Z: 0, 0, 1) ---
|
||||||
// Sequence: Bottom-Left -> Bottom-Right -> Top-Right -> Top-Left
|
-0.5f, -0.5f, 0.5f, 0f, 0f, 1f, 0f, 0f, // Bottom-left
|
||||||
Helpers.AddFace(vertices, indices,
|
0.5f, -0.5f, 0.5f, 0f, 0f, 1f, 1f, 0f, // Bottom-right
|
||||||
new Vertex(new Vector3(-0.5f, -0.5f, 0.5f), new Vector3(0, 0, 1), new Vector2(0, 0), Vector3.Zero, Vector3.Zero), // BL
|
0.5f, 0.5f, 0.5f, 0f, 0f, 1f, 1f, 1f, // Top-right
|
||||||
new Vertex(new Vector3( 0.5f, -0.5f, 0.5f), new Vector3(0, 0, 1), new Vector2(1, 0), Vector3.Zero, Vector3.Zero), // BR
|
-0.5f, 0.5f, 0.5f, 0f, 0f, 1f, 0f, 1f, // Top-left
|
||||||
new Vertex(new Vector3( 0.5f, 0.5f, 0.5f), new Vector3(0, 0, 1), new Vector2(1, 1), Vector3.Zero, Vector3.Zero), // TR
|
|
||||||
new Vertex(new Vector3(-0.5f, 0.5f, 0.5f), new Vector3(0, 0, 1), new Vector2(0, 1), Vector3.Zero, Vector3.Zero) // TL
|
|
||||||
);
|
|
||||||
|
|
||||||
// --- BACK FACE (Normal 0, 0, -1) ---
|
// --- Back Face (Normal points -Z: 0, 0, -1) ---
|
||||||
// Sequence: Bottom-Right -> Bottom-Left -> Top-Left -> Top-Right (Relative to Front view)
|
-0.5f, -0.5f, -0.5f, 0f, 0f, -1f, 1f, 0f,
|
||||||
Helpers.AddFace(vertices, indices,
|
0.5f, -0.5f, -0.5f, 0f, 0f, -1f, 0f, 0f,
|
||||||
new Vertex(new Vector3( 0.5f, -0.5f, -0.5f), new Vector3(0, 0, -1), new Vector2(0, 0), Vector3.Zero, Vector3.Zero), // BR
|
0.5f, 0.5f, -0.5f, 0f, 0f, -1f, 0f, 1f,
|
||||||
new Vertex(new Vector3(-0.5f, -0.5f, -0.5f), new Vector3(0, 0, -1), new Vector2(1, 0), Vector3.Zero, Vector3.Zero), // BL
|
-0.5f, 0.5f, -0.5f, 0f, 0f, -1f, 1f, 1f,
|
||||||
new Vertex(new Vector3(-0.5f, 0.5f, -0.5f), new Vector3(0, 0, -1), new Vector2(1, 1), Vector3.Zero, Vector3.Zero), // TL
|
|
||||||
new Vertex(new Vector3( 0.5f, 0.5f, -0.5f), new Vector3(0, 0, -1), new Vector2(0, 1), Vector3.Zero, Vector3.Zero) // TR
|
|
||||||
);
|
|
||||||
|
|
||||||
// --- LEFT FACE (Normal -1, 0, 0) ---
|
// --- Left Face (Normal points -X: -1, 0, 0) ---
|
||||||
// Sequence: Back-Left -> Front-Left -> Front-Top -> Back-Top
|
-0.5f, -0.5f, -0.5f, -1f, 0f, 0f, 0f, 0f,
|
||||||
Helpers.AddFace(vertices, indices,
|
-0.5f, -0.5f, 0.5f, -1f, 0f, 0f, 1f, 0f,
|
||||||
new Vertex(new Vector3(-0.5f, -0.5f, -0.5f), new Vector3(-1, 0, 0), new Vector2(0, 0), Vector3.Zero, Vector3.Zero), // BL
|
-0.5f, 0.5f, 0.5f, -1f, 0f, 0f, 1f, 1f,
|
||||||
new Vertex(new Vector3(-0.5f, -0.5f, 0.5f), new Vector3(-1, 0, 0), new Vector2(1, 0), Vector3.Zero, Vector3.Zero), // FL
|
-0.5f, 0.5f, -0.5f, -1f, 0f, 0f, 0f, 1f,
|
||||||
new Vertex(new Vector3(-0.5f, 0.5f, 0.5f), new Vector3(-1, 0, 0), new Vector2(1, 1), Vector3.Zero, Vector3.Zero), // FT
|
|
||||||
new Vertex(new Vector3(-0.5f, 0.5f, -0.5f), new Vector3(-1, 0, 0), new Vector2(0, 1), Vector3.Zero, Vector3.Zero) // BT
|
|
||||||
);
|
|
||||||
|
|
||||||
// --- RIGHT FACE (Normal 1, 0, 0) ---
|
// --- Right Face (Normal points +X: 1, 0, 0) ---
|
||||||
// Sequence: Front-Right -> Back-Right -> Back-Top -> Front-Top
|
0.5f, -0.5f, -0.5f, 1f, 0f, 0f, 1f, 0f,
|
||||||
Helpers.AddFace(vertices, indices,
|
0.5f, -0.5f, 0.5f, 1f, 0f, 0f, 0f, 0f,
|
||||||
new Vertex(new Vector3( 0.5f, -0.5f, 0.5f), new Vector3(1, 0, 0), new Vector2(0, 0), Vector3.Zero, Vector3.Zero), // FR
|
0.5f, 0.5f, 0.5f, 1f, 0f, 0f, 0f, 1f,
|
||||||
new Vertex(new Vector3( 0.5f, -0.5f, -0.5f), new Vector3(1, 0, 0), new Vector2(1, 0), Vector3.Zero, Vector3.Zero), // BR
|
0.5f, 0.5f, -0.5f, 1f, 0f, 0f, 1f, 1f,
|
||||||
new Vertex(new Vector3( 0.5f, 0.5f, -0.5f), new Vector3(1, 0, 0), new Vector2(1, 1), Vector3.Zero, Vector3.Zero), // BT
|
|
||||||
new Vertex(new Vector3( 0.5f, 0.5f, 0.5f), new Vector3(1, 0, 0), new Vector2(0, 1), Vector3.Zero, Vector3.Zero) // FT
|
|
||||||
);
|
|
||||||
|
|
||||||
// --- TOP FACE (Normal 0, 1, 0) ---
|
// --- Top Face (Normal points +Y: 0, 1, 0) ---
|
||||||
// Sequence: Front-Left -> Front-Right -> Back-Right -> Back-Left
|
-0.5f, 0.5f, -0.5f, 0f, 1f, 0f, 0f, 1f,
|
||||||
Helpers.AddFace(vertices, indices,
|
0.5f, 0.5f, -0.5f, 0f, 1f, 0f, 1f, 1f,
|
||||||
new Vertex(new Vector3(-0.5f, 0.5f, 0.5f), new Vector3(0, 1, 0), new Vector2(0, 0), Vector3.Zero, Vector3.Zero), // FL
|
0.5f, 0.5f, 0.5f, 0f, 1f, 0f, 1f, 0f,
|
||||||
new Vertex(new Vector3( 0.5f, 0.5f, 0.5f), new Vector3(0, 1, 0), new Vector2(1, 0), Vector3.Zero, Vector3.Zero), // FR
|
-0.5f, 0.5f, 0.5f, 0f, 1f, 0f, 0f, 0f,
|
||||||
new Vertex(new Vector3( 0.5f, 0.5f, -0.5f), new Vector3(0, 1, 0), new Vector2(1, 1), Vector3.Zero, Vector3.Zero), // BR
|
|
||||||
new Vertex(new Vector3(-0.5f, 0.5f, -0.5f), new Vector3(0, 1, 0), new Vector2(0, 1), Vector3.Zero, Vector3.Zero) // BL
|
|
||||||
);
|
|
||||||
|
|
||||||
// --- BOTTOM FACE (Normal 0, -1, 0) ---
|
// --- Bottom Face (Normal points -Y: 0, -1, 0) ---
|
||||||
// Sequence: Front-Left -> Back-Left -> Back-Right -> Front-Right
|
-0.5f, -0.5f, -0.5f, 0f, -1f, 0f, 1f, 1f,
|
||||||
Helpers.AddFace(vertices, indices,
|
0.5f, -0.5f, -0.5f, 0f, -1f, 0f, 0f, 1f,
|
||||||
new Vertex(new Vector3(-0.5f, -0.5f, 0.5f), new Vector3(0, -1, 0), new Vector2(0, 1), Vector3.Zero, Vector3.Zero), // FL
|
0.5f, -0.5f, 0.5f, 0f, -1f, 0f, 0f, 0f,
|
||||||
new Vertex(new Vector3(-0.5f, -0.5f, -0.5f), new Vector3(0, -1, 0), new Vector2(0, 0), Vector3.Zero, Vector3.Zero), // BL
|
-0.5f, -0.5f, 0.5f, 0f, -1f, 0f, 1f, 0f
|
||||||
new Vertex(new Vector3( 0.5f, -0.5f, -0.5f), new Vector3(0, -1, 0), new Vector2(1, 0), Vector3.Zero, Vector3.Zero), // BR
|
|
||||||
new Vertex(new Vector3( 0.5f, -0.5f, 0.5f), new Vector3(0, -1, 0), new Vector2(1, 1), Vector3.Zero, Vector3.Zero) // FR
|
};
|
||||||
);
|
|
||||||
|
|
||||||
|
uint[] indices = {
|
||||||
List<float> finalFloats = new List<float>();
|
// Front face
|
||||||
|
0, 2, 1,
|
||||||
foreach (var v in vertices)
|
0, 2, 3,
|
||||||
{
|
// Back face
|
||||||
finalFloats.Add(v.Position.X); finalFloats.Add(v.Position.Y); finalFloats.Add(v.Position.Z);
|
4, 5, 6,
|
||||||
finalFloats.Add(v.Normal.X); finalFloats.Add(v.Normal.Y); finalFloats.Add(v.Normal.Z);
|
4, 6, 7,
|
||||||
finalFloats.Add(v.TexCoords.X); finalFloats.Add(v.TexCoords.Y);
|
// Left face
|
||||||
|
8, 9, 10,
|
||||||
// --- NEW: Add Tangent and Bitangent ---
|
8, 10, 11,
|
||||||
finalFloats.Add(v.Tangent.X); finalFloats.Add(v.Tangent.Y); finalFloats.Add(v.Tangent.Z);
|
// Right face
|
||||||
finalFloats.Add(v.Bitangent.X); finalFloats.Add(v.Bitangent.Y); finalFloats.Add(v.Bitangent.Z);
|
12, 14, 13,
|
||||||
}
|
12, 14, 15,
|
||||||
|
// Top face
|
||||||
|
16, 17, 18,
|
||||||
|
16, 18, 19,
|
||||||
|
// Bottom face
|
||||||
|
20, 22, 21,
|
||||||
|
20, 22, 23
|
||||||
|
};
|
||||||
|
|
||||||
return new Mesh(finalFloats.ToArray(), indices.ToArray(), Mesh.VertexLayout.PosTexNormalTangent);
|
return new Mesh(vertices, indices, Mesh.VertexLayout.PosTexNormal);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Mesh CreateColouredCircle()
|
public static Mesh CreateColouredCircle()
|
||||||
@ -332,26 +321,6 @@ public static class ShapeFactory
|
|||||||
|
|
||||||
return new Mesh(vertices.ToArray(), indices.ToArray(), Mesh.VertexLayout.PosTexNormal);
|
return new Mesh(vertices.ToArray(), indices.ToArray(), Mesh.VertexLayout.PosTexNormal);
|
||||||
}
|
}
|
||||||
public static Mesh createTexturedSquare()
|
|
||||||
{
|
|
||||||
float[] vertices = {
|
|
||||||
// Format: X, Y, Z, U, V
|
|
||||||
|
|
||||||
// --- Front Face ---
|
|
||||||
-0.5f, -0.5f, 0.0f, 0f, 0f, // Bottom-left
|
|
||||||
0.5f, -0.5f, 0.0f, 1f, 0f, // Bottom-right
|
|
||||||
0.5f, 0.5f, 0.0f, 1f, 1f, // Top-right
|
|
||||||
-0.5f, 0.5f, 0.0f, 0f, 1f, // Top-left
|
|
||||||
};
|
|
||||||
|
|
||||||
uint[] indices = {
|
|
||||||
// Front face
|
|
||||||
0, 2, 1,
|
|
||||||
0, 2, 3,
|
|
||||||
};
|
|
||||||
|
|
||||||
return new Mesh(vertices, indices, Mesh.VertexLayout.PosTex);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1,22 +0,0 @@
|
|||||||
using OpenTK.Mathematics;
|
|
||||||
|
|
||||||
namespace TheLabs;
|
|
||||||
|
|
||||||
public struct Vertex
|
|
||||||
{
|
|
||||||
public Vector3 Position;
|
|
||||||
public Vector3 Normal;
|
|
||||||
public Vector2 TexCoords;
|
|
||||||
public Vector3 Tangent;
|
|
||||||
public Vector3 Bitangent;
|
|
||||||
|
|
||||||
// A constructor to make creating them easy
|
|
||||||
public Vertex(Vector3 position, Vector3 normal, Vector2 texCoords, Vector3 tangent, Vector3 bitangent)
|
|
||||||
{
|
|
||||||
Position = position;
|
|
||||||
Normal = normal;
|
|
||||||
TexCoords = texCoords;
|
|
||||||
Tangent = tangent;
|
|
||||||
Bitangent = bitangent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
x
Reference in New Issue
Block a user