Skip to content

Commit

Permalink
Goroud shading
Browse files Browse the repository at this point in the history
  • Loading branch information
fszewczyk committed Oct 19, 2024
1 parent 5a23307 commit 25c4e7c
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 69 deletions.
52 changes: 49 additions & 3 deletions resources/shaders/fragment/uber.glsl
Original file line number Diff line number Diff line change
@@ -1,9 +1,55 @@
#version 330 core

out vec4 FragColor;
out vec4 FragColor; // Final fragment color

in vec3 VertexColor; // Interpolated color from the vertex shader
in vec3 FragPos; // Fragment position in world space
in vec3 Normal; // Normal in world space

uniform vec3 viewPos; // Camera position

// Light structure
struct Light {
vec3 position; // Light position
vec3 ambient; // Ambient light color
vec3 diffuse; // Diffuse light color
vec3 specular; // Specular light color
};

uniform int numLights; // Number of active lights
uniform Light lights[16]; // Array of lights (supporting up to 16 point lights)

// Material structure
struct Material {
vec3 diffuse; // Diffuse material color
vec3 specular; // Specular material color
float shininess; // Shininess factor
};

uniform Material material; // Material properties

void main() {
FragColor = vec4(VertexColor, 1.0); // Output the interpolated color
vec3 result = vec3(0.0); // Initialize lighting result

// Process each light source
for (int i = 0; i < numLights; ++i) {
// Ambient component
vec3 ambient = lights[i].ambient * material.diffuse;

// Diffuse component
vec3 lightDir = normalize(lights[i].position - FragPos);
float diff = max(dot(Normal, lightDir), 0.0);
vec3 diffuse = lights[i].diffuse * diff * material.diffuse;

// Specular component
vec3 viewDir = normalize(viewPos - FragPos);
vec3 reflectDir = reflect(-lightDir, Normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
vec3 specular = lights[i].specular * spec * material.specular;

// Accumulate the lighting
result += ambient + diffuse + specular;
}

FragColor =
vec4(result, 1.0); // Set the final fragment color with full opacity
}
66 changes: 12 additions & 54 deletions resources/shaders/vertex/camera_view.glsl
Original file line number Diff line number Diff line change
@@ -1,63 +1,21 @@
#version 330 core

layout(location = 0) in vec3 position;
layout(location = 1) in vec3 normal;
layout(location = 0) in vec3 position; // Vertex position
layout(location = 1) in vec3 normal; // Vertex normal

uniform mat4 modelMatrix;
uniform mat4 viewMatrix;
uniform mat4 projectionMatrix;
uniform mat4 modelMatrix; // Model matrix
uniform mat4 viewMatrix; // View matrix
uniform mat4 projectionMatrix; // Projection matrix

out vec3 FragPos;
out vec3 Normal;
out vec3 VertexColor; // Color output for Gouraud shading

// Light structure
struct Light {
vec3 position; // Light position
vec3 ambient;
vec3 diffuse;
vec3 specular;
};

// Material structure
struct Material {
vec3 diffuse;
vec3 specular;
float shininess;
};

uniform int numLights; // Number of active lights
uniform Light lights[16]; // Array of lights (supporting up to 16 point lights)
uniform Material material; // Material properties
uniform vec3 viewPos; // Camera position
out vec3 FragPos; // Fragment position in world space
out vec3 Normal; // Normal in world space

void main() {
FragPos = vec3(modelMatrix * vec4(position, 1.0)); // World space position
FragPos = vec3(modelMatrix *
vec4(position, 1.0)); // Transform position to world space
Normal = normalize(mat3(transpose(inverse(modelMatrix))) *
normal); // Normal in world space

// Initialize lighting result for Gouraud shading
vec3 result = vec3(0.0);
vec3 viewDir =
normalize(viewPos - FragPos); // Direction from fragment to view

// Process each light
for (int i = 0; i < numLights; ++i) {
vec3 ambient = lights[i].ambient * material.diffuse;

vec3 lightDir = normalize(lights[i].position - FragPos);
float diff = max(dot(Normal, lightDir), 0.0);
vec3 diffuse = lights[i].diffuse * diff * material.diffuse;

vec3 reflectDir = reflect(-lightDir, Normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
vec3 specular = lights[i].specular * spec * material.specular;

result += ambient + diffuse + specular; // Accumulate the lighting
}

VertexColor = result; // Pass the computed color to the fragment shader
normal); // Transform normal to world space

gl_Position =
projectionMatrix * viewMatrix * vec4(FragPos, 1.0); // MVP transform
// Transform the vertex position to clip space
gl_Position = projectionMatrix * viewMatrix * vec4(FragPos, 1.0);
}
47 changes: 35 additions & 12 deletions src/AssetManager/Mesh.cpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,22 @@
#include <iostream>
#include <fstream>
#include <sstream>
#include <unordered_map>
#include <functional>

#include <AssetManager/Mesh.hpp>
// Assuming you are using a simple OBJ loader. You could integrate a library like Assimp for more advanced formats.
#include <tiny_obj_loader.h>

namespace std {
template <>
struct std::hash<glm::vec3> {
size_t operator()(const glm::vec3& vec) const {
return std::hash<float>()(vec.x) ^ std::hash<float>()(vec.y) ^ std::hash<float>()(vec.z);
}
};
}

namespace shkyera {

// Constructor that loads the model from a file
Expand All @@ -20,9 +31,10 @@ Mesh::~Mesh() {
glDeleteBuffers(1, &_ebo);
}


static std::vector<glm::vec3> calculateNormals(const std::vector<Mesh::Vertex>& vertices, const std::vector<unsigned int>& indices) {
std::vector<std::vector<size_t>> vertexToFaceIndex(vertices.size());
std::vector<glm::vec3> faceToNormal(indices.size(), glm::vec3(0.0f));
std::unordered_map<glm::vec3, glm::vec3> vertexToNormalMap;
std::unordered_map<glm::vec3, std::vector<glm::vec3>> faceNormals;

for (size_t faceIndex = 0; faceIndex < indices.size(); faceIndex += 3) {
unsigned int idx0 = indices[faceIndex];
Expand All @@ -35,21 +47,32 @@ static std::vector<glm::vec3> calculateNormals(const std::vector<Mesh::Vertex>&

glm::vec3 edge1 = v1 - v0;
glm::vec3 edge2 = v2 - v0;
glm::vec3 normal = glm::normalize(glm::cross(edge1, edge2));
glm::vec3 faceNormal = glm::normalize(glm::cross(edge1, edge2));

faceToNormal[faceIndex] = normal;
vertexToFaceIndex[idx0].push_back(faceIndex);
vertexToFaceIndex[idx1].push_back(faceIndex);
vertexToFaceIndex[idx2].push_back(faceIndex);
faceNormals[v0].push_back(faceNormal);
faceNormals[v1].push_back(faceNormal);
faceNormals[v2].push_back(faceNormal);
}

std::vector<glm::vec3> vertexToNormal(vertices.size(), glm::vec3(0.0f));
for(size_t vertex = 0; vertex < vertices.size(); ++vertex) {
for(const auto& face : vertexToFaceIndex[vertex]) {
vertexToNormal[vertex] += faceToNormal[face];

for (const auto& entry : faceNormals) {
const glm::vec3& position = entry.first;
const std::vector<glm::vec3>& normals = entry.second;

// Average the face normals for each position
glm::vec3 averagedNormal = glm::vec3(0.0f);
for (const glm::vec3& normal : normals) {
averagedNormal += normal;
}
vertexToNormal[vertex] /= vertexToFaceIndex[vertex].size();
vertexToNormal[vertex] = glm::normalize(vertexToNormal[vertex]);
averagedNormal = glm::normalize(averagedNormal);

// Map the averaged normal back to the vertices
vertexToNormalMap[position] = averagedNormal;
}

for (size_t i = 0; i < vertices.size(); ++i) {
vertexToNormal[i] = vertexToNormalMap[vertices[i].position];
}

return vertexToNormal;
Expand Down

0 comments on commit 25c4e7c

Please sign in to comment.