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
Finished lighting shaders
This commit is contained in:
parent
4de01aa53b
commit
fe63a6d938
@ -6,6 +6,8 @@
|
||||
<Path>TheLabs/Textures</Path>
|
||||
</attachedFolders>
|
||||
<explicitIncludes />
|
||||
<explicitExcludes />
|
||||
<explicitExcludes>
|
||||
<Path>TheLabs/Shapes/Bus.cs</Path>
|
||||
</explicitExcludes>
|
||||
</component>
|
||||
</project>
|
||||
29
TheRepo/TheLabs/Lighting.cs
Normal file
29
TheRepo/TheLabs/Lighting.cs
Normal file
@ -0,0 +1,29 @@
|
||||
using LearnOpenTK.Common;
|
||||
using OpenTK.Graphics.OpenGL;
|
||||
using OpenTK.Mathematics;
|
||||
|
||||
namespace TheLabs;
|
||||
|
||||
public struct Lighting
|
||||
{
|
||||
public Vector3 position;
|
||||
public Vector3 ambientColour;
|
||||
public Vector3 diffuseColour;
|
||||
public Vector3 specularColour;
|
||||
|
||||
public Lighting(Vector3 pos, Vector3 ambient, Vector3 diffuse, Vector3 specular)
|
||||
{
|
||||
position = pos;
|
||||
ambientColour = ambient;
|
||||
diffuseColour = diffuse;
|
||||
specularColour = specular;
|
||||
}
|
||||
|
||||
public void Apply(Shader shader)
|
||||
{
|
||||
GL.Uniform3(GL.GetUniformLocation(shader.Handle, "uPointLight.position"), ref position);
|
||||
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.specularColour"), ref specularColour);
|
||||
}
|
||||
}
|
||||
30
TheRepo/TheLabs/Material.cs
Normal file
30
TheRepo/TheLabs/Material.cs
Normal file
@ -0,0 +1,30 @@
|
||||
using LearnOpenTK.Common;
|
||||
using OpenTK.Graphics.OpenGL;
|
||||
using OpenTK.Mathematics;
|
||||
|
||||
namespace TheLabs;
|
||||
|
||||
public struct Material
|
||||
{
|
||||
public Vector3 ambientColour;
|
||||
public Vector3 diffuseColour;
|
||||
public Vector3 specularColour;
|
||||
public float shininess;
|
||||
|
||||
public Material(Vector3 ambient, Vector3 diffuse, Vector3 specular, float shininessFactor)
|
||||
{
|
||||
ambientColour = ambient;
|
||||
diffuseColour = diffuse;
|
||||
specularColour = specular;
|
||||
shininess = shininessFactor;
|
||||
}
|
||||
|
||||
public void Apply(Shader shader)
|
||||
{
|
||||
GL.Uniform3(GL.GetUniformLocation(shader.Handle, "uMaterial.ambientColour"), ref ambientColour);
|
||||
GL.Uniform3(GL.GetUniformLocation(shader.Handle, "uMaterial.diffuseColour"), ref diffuseColour);
|
||||
GL.Uniform3(GL.GetUniformLocation(shader.Handle, "uMaterial.specularColour"), ref specularColour);
|
||||
GL.Uniform1(GL.GetUniformLocation(shader.Handle, "uMaterial.shininess"), shininess);
|
||||
}
|
||||
|
||||
}
|
||||
@ -11,39 +11,37 @@ namespace TheLabs
|
||||
{
|
||||
public class MyExampleWindow : GameWindow
|
||||
{
|
||||
// Create the vertices for our triangle. These are listed in normalized device coordinates (NDC)
|
||||
// In NDC, (0, 0) is the center of the screen.
|
||||
// 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.
|
||||
// OpenGL only supports rendering in 3D, so to create a flat triangle, the Z coordinate will be kept as 0.
|
||||
|
||||
// -- Scene Graph Nodes
|
||||
private SceneNode _rootNode;
|
||||
private SceneNode _characterNode;
|
||||
private SceneNode _buildingNode;
|
||||
|
||||
// -- OpenGL Resources
|
||||
private Shader _shader;
|
||||
private Camera _camera;
|
||||
|
||||
// - Resources that only need to be created once
|
||||
private Mesh _exampleObject;
|
||||
private Mesh _buildingObject;
|
||||
private Texture _texture;
|
||||
private RenderObject _render;
|
||||
private RenderObject _buildingRender;
|
||||
float _rotation = 0.0f;
|
||||
|
||||
// -- Scene Objects
|
||||
|
||||
// Camera parameters
|
||||
private Vector3 _cameraPosition = new Vector3(0.0f, 0.0f, -3.0f);
|
||||
private Vector3 _cameraFront = new Vector3(0.0f, 0.0f, -1.0f);
|
||||
|
||||
private Vector3 _cameraUp = Vector3.UnitY;
|
||||
|
||||
private float _yaw = -90.0f;
|
||||
private float _pitch = 0.0f;
|
||||
|
||||
private float _cameraSpeed = 2.5f;
|
||||
private float _rotationSpeed = 50.0f;
|
||||
|
||||
private float _mouseSensitivity = 0.1f;
|
||||
private float _pitch = 0.0f;
|
||||
private float _rotation = 0.0f;
|
||||
|
||||
// Materials and Lighting
|
||||
private Lighting _mainLight;
|
||||
private Material _defaultMaterial;
|
||||
|
||||
// This prevents a large camera jump when the window first gets focus
|
||||
private bool _firstMove = true;
|
||||
@ -58,24 +56,42 @@ namespace TheLabs
|
||||
{
|
||||
// This is called when the window is created and is where we can set up OpenGL resources.
|
||||
base.OnLoad();
|
||||
//GL.Disable(EnableCap.CullFace);
|
||||
|
||||
//GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line);
|
||||
// --- Set up Lighting and Material ---
|
||||
_mainLight = new Lighting(new Vector3(1.2f, 1.0f, 2.0f),
|
||||
new Vector3(0.3f),
|
||||
new Vector3(1.5f),
|
||||
new Vector3(1.0f));
|
||||
|
||||
_defaultMaterial = new Material(
|
||||
new Vector3(0.5f, 0.5f, 0.5f) * 0.1f,
|
||||
new Vector3(0.5f, 0.5f, 0.5f) * 0.6f,
|
||||
new Vector3(1.0f, 1.0f, 1.0f),
|
||||
32.0f);
|
||||
|
||||
// --- Set up OpenGL State ---
|
||||
GL.ClearColor(0.2f, 0.3f, 0.3f, 1.0f);
|
||||
GL.Enable(EnableCap.DepthTest);
|
||||
|
||||
// --- Set up Camera ---
|
||||
_camera = new Camera(_cameraPosition, _cameraFront, _cameraUp);
|
||||
|
||||
// -- Load Shaders, Textures, and Create Scene Objects ---
|
||||
_shader = new Shader("Shaders/shader.vert", "Shaders/shader.frag");
|
||||
_texture = new Texture("Textures/placeholder.png");
|
||||
|
||||
// --- Create Scene Graph ---
|
||||
_rootNode = new SceneNode();
|
||||
_buildingObject = ShapeFactory.CreateTexturedCube();
|
||||
_buildingRender = new RenderObject(_buildingObject, _shader, _texture);
|
||||
|
||||
// Create Example Object
|
||||
_buildingObject = ShapeFactory.CreateTexturedSphere();
|
||||
_buildingRender = new RenderObject(_buildingObject, _shader, _texture, _defaultMaterial, _mainLight);
|
||||
_buildingNode = new SceneNode(_buildingRender);
|
||||
_buildingNode.Position = new Vector3(2.0f, -1.0f, 0.0f);
|
||||
_buildingNode.Scale = new Vector3(0.1f, 0.1f, 0.1f);
|
||||
_rootNode.AddChild(_buildingNode);
|
||||
|
||||
// Create Character Object
|
||||
CursorState = CursorState.Grabbed;
|
||||
|
||||
|
||||
@ -89,8 +105,6 @@ namespace TheLabs
|
||||
base.OnRenderFrame(e);
|
||||
// Clear the color buffer and the depth buffer
|
||||
GL.Clear(ClearBufferMask.DepthBufferBit | ClearBufferMask.ColorBufferBit);
|
||||
//_cubeObject.Rotation = Quaternion.FromEulerAngles(_rotation * 0.5f, _rotation, 0); //
|
||||
//_cubeObject2.Rotation = Quaternion.FromEulerAngles(-_rotation * 0.5f, -_rotation, 0);
|
||||
|
||||
// --- Set up Camera ---
|
||||
Matrix4 view = _camera.LookAt();
|
||||
@ -101,15 +115,17 @@ namespace TheLabs
|
||||
{
|
||||
aspectRatio = 1.0f; // Default to 1:1 if window is minimized
|
||||
}
|
||||
|
||||
// 3. Create the projection matrix
|
||||
Matrix4 projection = Matrix4.CreatePerspectiveFieldOfView(
|
||||
MathHelper.DegreesToRadians(45f),
|
||||
aspectRatio,
|
||||
0.1f,
|
||||
100.0f
|
||||
);
|
||||
// --- Draw Scene Objects ---
|
||||
_rootNode.Draw(view, projection, Matrix4.Identity);
|
||||
|
||||
// --- Draw Scene Objects ---
|
||||
_rootNode.Draw(view, projection, Matrix4.Identity, _mainLight);
|
||||
SwapBuffers();
|
||||
}
|
||||
|
||||
|
||||
@ -9,17 +9,21 @@ public class RenderObject
|
||||
public Mesh Mesh;
|
||||
public Shader Shader;
|
||||
public Texture Texture;
|
||||
public Material Material;
|
||||
public Lighting Lighting;
|
||||
|
||||
public Vector3 Position = Vector3.Zero;
|
||||
public Matrix4 Transform = Matrix4.Identity;
|
||||
public Quaternion Rotation = Quaternion.Identity;
|
||||
public Vector3 Scale = Vector3.One;
|
||||
|
||||
public RenderObject(Mesh mesh, Shader shader, Texture texture)
|
||||
public RenderObject(Mesh mesh, Shader shader, Texture texture, Material material, Lighting lighting)
|
||||
{
|
||||
Mesh = mesh;
|
||||
Shader = shader;
|
||||
Texture = texture;
|
||||
Material = material;
|
||||
Lighting = lighting;
|
||||
}
|
||||
|
||||
public RenderObject(Mesh mesh, Shader shader)
|
||||
@ -28,14 +32,20 @@ public class RenderObject
|
||||
Shader = shader;
|
||||
}
|
||||
|
||||
public void Draw(Matrix4 view, Matrix4 projection)
|
||||
public void Draw(Matrix4 view, Matrix4 projection, Lighting light)
|
||||
{
|
||||
// 1. Activate Shader
|
||||
Vector3 pink = new Vector3(0.5f, 0.5f, 0.5f);
|
||||
Material mat = new Material(pink * 0.1f, pink * 0.6f, Vector3.One, 32.0f);
|
||||
|
||||
Shader.Use();
|
||||
// 2. Bind Texture
|
||||
Texture.Use();
|
||||
Shader.SetInt("uTexture", 0);
|
||||
// 3. Calculate Model Matrix
|
||||
|
||||
Material.Apply(Shader);
|
||||
light.Apply(Shader);
|
||||
|
||||
Vector3 cameraPos = view.Inverted().ExtractTranslation();
|
||||
Shader.SetVector3("uViewPos", cameraPos);
|
||||
|
||||
Matrix4 model = Matrix4.CreateScale(Scale) * Matrix4.CreateFromQuaternion(Rotation) * Matrix4.CreateTranslation(Position);
|
||||
int modelLoc = GL.GetUniformLocation(Shader.Handle, "model");
|
||||
@ -47,7 +57,9 @@ public class RenderObject
|
||||
int projLoc = GL.GetUniformLocation(Shader.Handle, "projection");
|
||||
GL.UniformMatrix4(projLoc, false, ref projection); // Try TRUE here
|
||||
|
||||
|
||||
// 5. Tell the Mesh to draw itself
|
||||
Mesh.Draw();
|
||||
}
|
||||
|
||||
}
|
||||
@ -23,7 +23,7 @@ public class SceneNode
|
||||
Children.Add(child);
|
||||
}
|
||||
|
||||
public void Draw(Matrix4 view, Matrix4 projection, Matrix4 parentTransform)
|
||||
public void Draw(Matrix4 view, Matrix4 projection, Matrix4 parentTransform, Lighting light)
|
||||
{
|
||||
Matrix4 localTransform = Matrix4.CreateScale(Scale) * Matrix4.CreateFromQuaternion(Rotation) * Matrix4.CreateTranslation(Position);
|
||||
Matrix4 globalTransform = localTransform * parentTransform;
|
||||
@ -34,12 +34,12 @@ public class SceneNode
|
||||
RenderObject.Rotation = Quaternion.Identity;
|
||||
RenderObject.Scale = Vector3.One;
|
||||
|
||||
RenderObject.Draw(view, projection);
|
||||
RenderObject.Draw(view, projection, light);
|
||||
}
|
||||
|
||||
foreach (var child in Children)
|
||||
{
|
||||
child.Draw(view, projection, globalTransform);
|
||||
child.Draw(view, projection, globalTransform, light);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,37 +1,81 @@
|
||||
#version 330 core
|
||||
|
||||
out vec4 outputColor;
|
||||
// Fragment shader for basic lighting with texture mapping
|
||||
|
||||
out vec4 outputColor; // The final output color of the fragment
|
||||
|
||||
// --- INPUTS ---
|
||||
// These come from the Vertex Shader
|
||||
in vec3 FragPos;
|
||||
in vec3 Normal;
|
||||
in vec2 TexCoord;
|
||||
|
||||
struct MaterialProperty {
|
||||
vec3 ambientColour;
|
||||
vec3 diffuseColour;
|
||||
vec3 specularColour;
|
||||
float shininess;
|
||||
};
|
||||
|
||||
struct LightProperty {
|
||||
vec3 position;
|
||||
vec3 ambientColour;
|
||||
vec3 diffuseColour;
|
||||
vec3 specularColour;
|
||||
};
|
||||
|
||||
// --- UNIFORMS ---
|
||||
uniform sampler2D uTexture;
|
||||
uniform sampler2D uTexture; // Image Texture
|
||||
uniform vec3 uViewPos; // Camera Position
|
||||
uniform MaterialProperty uMaterial; // Material Properties
|
||||
uniform LightProperty uPointLight; // Light Properties
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
// Lighting Setup
|
||||
// --- 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 (Keep it as vec4!)
|
||||
// 1. Get Texture Color
|
||||
// Sample the texture at the given texture coordinates
|
||||
vec4 objColor = texture(uTexture, TexCoord);
|
||||
|
||||
// 2. Ambient
|
||||
// 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 = ambientStrength * lightColor;
|
||||
vec3 ambient = uMaterial.ambientColour * uPointLight.ambientColour;
|
||||
|
||||
// 3. Diffuse
|
||||
vec3 norm = normalize(Normal);
|
||||
vec3 lightDir = normalize(lightPos - FragPos);
|
||||
float diff = max(dot(norm, lightDir), 0.0f);
|
||||
vec3 diffuse = diff * lightColor;
|
||||
// Creates the "matte" effect by calculating the angle between the light direction and the surface normal
|
||||
|
||||
// 4. Combine
|
||||
// Note: We use objColor.rgb (vec3) to match the lighting calculation
|
||||
vec3 result = (ambient + diffuse) * objColor.rgb;
|
||||
// Normalize the normal vector and calculate the light direction
|
||||
vec3 norm = normalize(Normal);
|
||||
vec3 lightDir = normalize(uPointLight.position - FragPos);
|
||||
|
||||
// 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);
|
||||
}
|
||||
@ -1,16 +1,21 @@
|
||||
#version 330 core
|
||||
|
||||
// Vertex shader decides where each vertex is in 3D space
|
||||
|
||||
// --- INPUTS ---
|
||||
layout(location = 0) in vec3 aPosition;
|
||||
layout(location = 1) in vec3 aNormal;
|
||||
layout(location = 2) in vec2 aTexCoord;
|
||||
// Comes directly from the vertex buffer
|
||||
layout(location = 0) in vec3 aPosition; // Raw 3D position
|
||||
layout(location = 1) in vec3 aNormal; // The direction perpendicular to the surface
|
||||
layout(location = 2) in vec2 aTexCoord; // The U,V texture coordinates
|
||||
|
||||
// --- OUTPUTS ---
|
||||
// We can pass data to the fragment shader through these
|
||||
out vec3 FragPos;
|
||||
out vec3 Normal;
|
||||
out vec2 TexCoord;
|
||||
|
||||
// --- UNIFORMS ---
|
||||
// These are matrices that help transform our vertices
|
||||
uniform mat4 model;
|
||||
uniform mat4 view;
|
||||
uniform mat4 projection;
|
||||
|
||||
@ -253,6 +253,74 @@ public static class ShapeFactory
|
||||
// --- 4. Create the Mesh ---
|
||||
return new Mesh(vertices.ToArray(), indices.ToArray(), Mesh.VertexLayout.PosTex);
|
||||
}
|
||||
public static Mesh CreateTexturedSphere(float radius = 0.5f, int stacks = 20, int slices = 20)
|
||||
{
|
||||
var vertices = new List<float>();
|
||||
var indices = new List<uint>();
|
||||
|
||||
// 1. Generate Vertices
|
||||
for (int i = 0; i <= stacks; i++)
|
||||
{
|
||||
// V ranges from 0.0 to 1.0 (bottom to top)
|
||||
float v = (float)i / stacks;
|
||||
|
||||
// Phi ranges from -PI/2 (bottom) to +PI/2 (top)
|
||||
float phi = v * MathF.PI - MathF.PI / 2;
|
||||
|
||||
for (int j = 0; j <= slices; j++)
|
||||
{
|
||||
// U ranges from 0.0 to 1.0 (around the sphere)
|
||||
float u = (float)j / slices;
|
||||
|
||||
// Theta ranges from 0 to 2*PI
|
||||
float theta = u * 2 * MathF.PI;
|
||||
|
||||
// Calculate Position (Spherical Coordinates)
|
||||
float x = radius * MathF.Cos(phi) * MathF.Cos(theta);
|
||||
float y = radius * MathF.Sin(phi);
|
||||
float z = radius * MathF.Cos(phi) * MathF.Sin(theta);
|
||||
|
||||
// Calculate Normal (Normalized position)
|
||||
// Since center is (0,0,0), normal is just (x,y,z) normalized.
|
||||
// Or simpler: (x/r, y/r, z/r)
|
||||
float nx = x / radius;
|
||||
float ny = y / radius;
|
||||
float nz = z / radius;
|
||||
|
||||
// Add Vertex Data: Pos (3) + Normal (3) + Tex (2)
|
||||
vertices.Add(x); vertices.Add(y); vertices.Add(z); // Position
|
||||
vertices.Add(nx); vertices.Add(ny); vertices.Add(nz); // Normal
|
||||
vertices.Add(u); vertices.Add(v); // Texture
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Generate Indices
|
||||
for (int i = 0; i < stacks; i++)
|
||||
{
|
||||
for (int j = 0; j < slices; j++)
|
||||
{
|
||||
// We are building a quad from 4 vertices:
|
||||
// TopLeft (TL), TopRight (TR), BottomLeft (BL), BottomRight (BR)
|
||||
|
||||
uint bl = (uint)(i * (slices + 1) + j);
|
||||
uint br = (uint)(i * (slices + 1) + (j + 1));
|
||||
uint tl = (uint)((i + 1) * (slices + 1) + j);
|
||||
uint tr = (uint)((i + 1) * (slices + 1) + (j + 1));
|
||||
|
||||
// Triangle 1
|
||||
indices.Add(bl);
|
||||
indices.Add(br);
|
||||
indices.Add(tl);
|
||||
|
||||
// Triangle 2
|
||||
indices.Add(br);
|
||||
indices.Add(tr);
|
||||
indices.Add(tl);
|
||||
}
|
||||
}
|
||||
|
||||
return new Mesh(vertices.ToArray(), indices.ToArray(), Mesh.VertexLayout.PosTexNormal);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -52,7 +52,7 @@ public class Bus
|
||||
|
||||
foreach (var pos in wheelPositions)
|
||||
{
|
||||
var wheelObj = new RenderObject(_wheelMesh, shader, wheelTexture);
|
||||
//var wheelObj = new RenderObject(_wheelMesh, shader, wheelTexture);
|
||||
var wheelNode = new SceneNode(wheelObj);
|
||||
|
||||
wheelNode.Position = pos; // Relative to the MainNode!
|
||||
@ -68,7 +68,7 @@ public class Bus
|
||||
|
||||
public void Draw(Matrix4 view, Matrix4 projection)
|
||||
{
|
||||
MainNode.Draw(view, projection, Matrix4.Identity);
|
||||
//MainNode.Draw(view, projection, Matrix4.Identity);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -30,4 +30,8 @@
|
||||
<None Include="..\..\README.md" Link="README.md" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Remove="Shapes\Bus.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user