Skip to content
Snippets Groups Projects
Commit ebab56b6 authored by Kevin Bonga's avatar Kevin Bonga
Browse files

initial commit

parents
No related branches found
No related tags found
No related merge requests found
Showing
with 354 additions and 0 deletions
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
<?xml version="1.0" encoding="UTF-8"?>
<module type="CPP_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/geo_algo.iml" filepath="$PROJECT_DIR$/.idea/geo_algo.iml" />
</modules>
</component>
</project>
\ No newline at end of file
File added
File added
File added
File added
File added
File added
File added
File added
File added
const canvas = document.querySelector('canvas#drawing');
const ctx = canvas.getContext('2d');
/**
* Positions des sommets du cube
* Cube centré sur 0,0,0 de hauteur, largeur, profondeur de 1
*/
const positions = [
-0.5, -0.5, -0.5, 0.5, -0.5, -0.5,
0.5, 0.5, -0.5, -0.5, 0.5, -0.5,
-0.5, -0.5, 0.5, 0.5, -0.5, 0.5,
0.5, 0.5, 0.5, -0.5, 0.5, 0.5
];
const indices = [
0, 1, 2, 0, 2, 3, // devant
4, 5, 6, 4, 6, 7, // derrière
0, 1, 5, 0, 5, 4, // dessous
2, 3, 7, 2, 7, 6, // dessus
0, 3, 7, 0, 7, 4, // gauche
1, 2, 6, 1, 6, 5 // droite
];
function matXVect(mat, v) {
let result = [];
for (let i = 0; i < mat.length; i++) {
let sum = 0;
for (let j = 0; j < v.length; j++) {
sum += mat[i][j] * v[j];
}
result.push(sum);
}
return result;
}
function transformerVecteurParMatrice(matrice, vecteur) {
return matXVect(matrice, vecteur);
}
const worldMat = [
[0.5, 0.5, -0.7071067690849304, 0],
[-0.8535534143447876, 0.1464466154575348, -0.5, 0],
[-0.1464466154575348, 0.8535534143447876, 0.5, 0],
[0, 0, 0, 1]
];
const viewMat = [
[-0.7071067690849304, -0.5, -0.5, 0],
[0, 0.7071067690849304, -0.7071067690849304, 0],
[0.7071067690849304, -0.5, -0.5, 0],
[0, 0, 0, 1]
];
const projMat = [
[2.237522602081299, 0, 0, 0],
[0, 2.365222454071045, 0, 0],
[0, 0, 1.0002000331878662, 1],
[0, 0, -2.000200033187866, 0]
];
/**
* Transformer les coordonnées des triangles
*/
function transformerCoordonneesTriangle(idx, pos, worldMat, viewMat, projMat) {
const triangles = [];
for (let i = 0; i < idx.length; i += 3) {
const sommet1 = [pos[idx[i] * 3], pos[idx[i] * 3 + 1], pos[idx[i] * 3 + 2], 1];
const sommet2 = [pos[idx[i + 1] * 3], pos[idx[i + 1] * 3 + 1], pos[idx[i + 1] * 3 + 2], 1];
const sommet3 = [pos[idx[i + 2] * 3], pos[idx[i + 2] * 3 + 1], pos[idx[i + 2] * 3 + 2], 1];
let t1 = transformerVecteurParMatrice(worldMat, sommet1);
t1 = transformerVecteurParMatrice(viewMat, t1);
t1 = transformerVecteurParMatrice(projMat, t1);
let t2 = transformerVecteurParMatrice(worldMat, sommet2);
t2 = transformerVecteurParMatrice(viewMat, t2);
t2 = transformerVecteurParMatrice(projMat, t2);
let t3 = transformerVecteurParMatrice(worldMat, sommet3);
t3 = transformerVecteurParMatrice(viewMat, t3);
t3 = transformerVecteurParMatrice(projMat, t3);
triangles.push([t1, t2, t3]);
}
return triangles;
}
const trianglesTransformes = transformerCoordonneesTriangle(indices, positions, worldMat, viewMat, projMat);
//source: github copilot
function adapterCoordonnees(triangles) {
return triangles.map(triangle => {
return triangle.map(([x, y, z, w]) => {
return [
(x / w + 1) * 350,
(y / w + 1) * 350
];
});
});
}
const trianglesAdapted = adapterCoordonnees(trianglesTransformes);
ctx.beginPath();
ctx.lineWidth = 2;
ctx.strokeStyle = "white";
function dessinTriangle(triangles) {
triangles.forEach(triangle => {
ctx.moveTo(triangle[0][0], triangle[0][1]);
ctx.lineTo(triangle[1][0], triangle[1][1]);
ctx.lineTo(triangle[2][0], triangle[2][1]);
ctx.lineTo(triangle[0][0], triangle[0][1]);
});
}
/**
* Dessiner les triangles transformés sur le canvas
*/
dessinTriangle(trianglesAdapted);
/**
* Finalisation du dessin
*/
ctx.stroke();
precision highp float;
uniform float time;
uniform vec2 resolution;
varying vec3 fPosition;
varying vec3 fNormal;
void main()
{
int type = 3;
float brillance = 100.0;
vec3 lightPos = vec3(20.0, 20.0, 20.0);
float Ka = 1.0;
float Kd = 0.8;
float Ks = 1.0;
vec3 ambient_color = vec3(0.1, 0.1, 0.1);
vec3 diffuse_color = vec3(1.0, 1.0, 1.0);
vec3 specular_color = vec3(1.0, 1.0, 1.0);
vec3 N = normalize(fNormal);
vec3 ambient = Ka * ambient_color;
vec3 L = normalize(lightPos - fPosition);
float N_L = max(dot(N, L), 0.0);
vec3 diffuse = Kd * diffuse_color * N_L;
vec3 V = normalize(-fPosition);
vec3 R = reflect(-L, N);
float R_V = max(dot(R, V), 0.0);
vec3 specular = Ks * specular_color * pow(R_V, brillance);
// Calcul selon du type
vec3 finalColor;
if (type == 1) {
finalColor = ambient + diffuse + specular;
} else if (type == 2) {
finalColor = ambient;
} else if (type == 3) {
finalColor = diffuse;
} else if (type == 4) {
finalColor = specular;
} else {
finalColor = vec3(1.0); //default blanc
}
gl_FragColor = vec4(finalColor, 1.0);
}
\ No newline at end of file
const canvas = document.querySelector('canvas#scene');
const ctx = canvas.getContext('2d');
const cubeVertices = [
0.5, 0.5, -0.5, 0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, 0.5, -0.5,
0.5, 0.5, 0.5, -0.5, 0.5, 0.5, -0.5, -0.5, 0.5, 0.5, -0.5, 0.5,
0.5, 0.5, -0.5, 0.5, 0.5, 0.5, 0.5, -0.5, 0.5, 0.5, -0.5, -0.5,
0.5, -0.5, -0.5, 0.5, -0.5, 0.5, -0.5, -0.5, 0.5, -0.5, -0.5, -0.5,
-0.5, -0.5, -0.5,-0.5, -0.5, 0.5, -0.5, 0.5, 0.5, -0.5, 0.5, -0.5,
0.5, 0.5, 0.5, 0.5, 0.5, -0.5, -0.5, 0.5, -0.5, -0.5, 0.5, 0.5
];
const cubeIndices = [
0, 2, 3, 0, 1, 2, 4, 6, 7, 4, 5, 6,
8, 10,11, 8, 9, 10, 12,14,15, 12,13,14,
16,18,19, 16,17,18, 20,22,23, 20,21,22
];
const lightPos = [2, 2, -2];
const lightColor = [1, 1, 1];
const ambientStrength = 0.1;
const specularExponent = 50;
function normalize(vec) {
const len = Math.hypot(...vec);
return vec.map(v => v / len);
}
function subtract(v1, v2) {
return v1.map((v, i) => v - v2[i]);
}
function add(v1, v2) {
return v1.map((v, i) => v + v2[i]);
}
function dot(v1, v2) {
return v1.reduce((sum, v, i) => sum + v * v2[i], 0);
}
function cross(v1, v2) {
return [
v1[1] * v2[2] - v1[2] * v2[1],
v1[2] * v2[0] - v1[0] * v2[2],
v1[0] * v2[1] - v1[1] * v2[0]
];
}
function rayIntersectTriangle(origin, dir, v0, v1, v2) {
const EPSILON = 1e-7;
const edge1 = subtract(v1, v0);
const edge2 = subtract(v2, v0);
const h = cross(dir, edge2);
const a = dot(edge1, h);
if (a > -EPSILON && a < EPSILON) return null;
const f = 1 / a;
const s = subtract(origin, v0);
const u = f * dot(s, h);
if (u < 0 || u > 1) return null;
const q = cross(s, edge1);
const v = f * dot(dir, q);
if (v < 0 || u + v > 1) return null;
const t = f * dot(edge2, q);
if (t > EPSILON) return add(origin, dir.map(d => d * t));
return null;
}
function phongIllumination(point, normal, viewDir) {
const lightDir = normalize(subtract(lightPos, point));
const reflectDir = normalize(subtract(
lightDir.map(n => 2 * dot(lightDir, normal) * n),
lightDir
));
const ambient = ambientStrength;
const diffuse = Math.max(dot(normal, lightDir), 0);
const specular = Math.pow(Math.max(dot(viewDir, reflectDir), 0), specularExponent);
return [
lightColor[0] * (ambient + diffuse + specular),
lightColor[1] * (ambient + diffuse + specular),
lightColor[2] * (ambient + diffuse + specular)
];
}
function render() {
const width = canvas.width;
const height = canvas.height;
const imageData = ctx.createImageData(width, height);
const eye = [0, 0, -3];
const viewDir = [0, 0, 1];
const fov = Math.PI / 3;
for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) {
const nx = (2 * (x + 0.5) / width - 1) * Math.tan(fov / 2) * width / height;
const ny = -(2 * (y + 0.5) / height - 1) * Math.tan(fov / 2);
const rayDir = normalize([nx, ny, 1]);
let tMin = Infinity;
let hitPoint = null;
let hitNormal = null;
for (let i = 0; i < cubeIndices.length; i += 3) {
const v0 = [cubeVertices[3 * cubeIndices[i]], cubeVertices[3 * cubeIndices[i] + 1], cubeVertices[3 * cubeIndices[i] + 2]];
const v1 = [cubeVertices[3 * cubeIndices[i + 1]], cubeVertices[3 * cubeIndices[i + 1] + 1], cubeVertices[3 * cubeIndices[i + 1] + 2]];
const v2 = [cubeVertices[3 * cubeIndices[i + 2]], cubeVertices[3 * cubeIndices[i + 2] + 1], cubeVertices[3 * cubeIndices[i + 2] + 2]];
const intersection = rayIntersectTriangle(eye, rayDir, v0, v1, v2);
if (intersection) {
const t = subtract(intersection, eye)[2];
if (t < tMin) {
tMin = t;
hitPoint = intersection;
hitNormal = normalize(cross(subtract(v1, v0), subtract(v2, v0)));
}
}
}
if (hitPoint) {
const color = phongIllumination(hitPoint, hitNormal, rayDir);
const index = (y * width + x) * 4;
imageData.data[index] = Math.min(255, color[0] * 255);
imageData.data[index + 1] = Math.min(255, color[1] * 255);
imageData.data[index + 2] = Math.min(255, color[2] * 255);
imageData.data[index + 3] = 255;
}
}
}
ctx.putImageData(imageData, 0, 0);
}
render();
Construction de la normalMatrix (gl_NormalMatrix) :
La normalMatrix est utilisée pour transformer les vecteurs normaux des objets dans l'espace de la caméra). Elle est utilisée dans le vertex shader pour maintenir l'orientation correcte des normales lorsque l'objet est transformé (mis à l'échelle, tourné ou déplacé) dans l'espace de la vue. La normalMatrix est calculée en prenant la matrice inverse transposée de la matrice de modèle-view. Cette opération est nécessaire car les vecteurs normaux ne sont pas affectés par la translation, donc la partie de translation de la matrice de modèle-view est ignorée en prenant l'inverse, tandis que la partie de rotation et d'échelle est transposée pour conserver l'orientation correcte des normales.
Attribut varying :
L'attribut varying est utilisé pour transmettre des données entre le vertex shader et le fragment shader. Dans le vertex shader, vous définissez une variable varying avec une certaine valeur.
Différence entre la normal dans le vertex shader et la fNormal dans le fragment shader :
La variable Normal dans le vertex shader représente la normale de chaque sommet de l'objet. Elle est utilisée pour calculer l'éclairage au niveau des sommets. En revanche, fNormal est la normale interpolée pour chaque fragment de triangle.
Pourquoi il faut normaliser fNormal pour obtenir un rendu de meilleur qualité :
Il est important de normaliser la normale interpolée fNormal dans le fragment shader car les normales ne sont pas toujours unitaires après l'interpolation. La normalisation garantit que la normale a une longueur de 1, ce qui est crucial pour les calculs d'éclairage. Sans normalisation, les calculs d'éclairage tels que les réflexions spéculaires et les ombres peuvent donner des résultats inattendus ou incorrects.
Les trois composants principaux du modèle d'ombrage de Phong:
Lumière Ambiante :
Il s'agit d'une lumière uniforme qui est présente sur toute la surface d'un objet. Elle agit comme une lumière qui est refléchit par les objets environants et impacte en soit la couleur d'un objet. L'objet n'est pas influencé par une source de lumière lorsque parle de ce type de lumière
Lumière Diffuse :
Dans ce cas là, il s'agit d'une lumière généré par la réflexion de la lumière provenant des sources lumineuses. Elle dépend de l'angle entre la direction de la lumière incidente et la normale de la surface de l'objet. Plus cet angle est proche de 0 degré, plus la composante diffusée de la lumière est forte et intense.
Lumière Spéculaire :
L'éclairage spéculaire est responsable des reflets très brillants et nets observés sur les surfaces lisses et régulières. Elle est généré par la réflexion de la lumière provenant de sources lumineuses "puissants" qui éclairent une zone précise ex: les projecteurs sur les surfaces lisses.
File added
File added
File added
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment