Compare commits

...

4 Commits

Author SHA1 Message Date
911deefbf5 multiple labmda 2025-12-28 17:04:49 +01:00
d8e178fe06 spectrum 2025-12-28 15:58:02 +01:00
acbda14a43 todo 2025-12-28 15:31:31 +01:00
88d6ff6532 todo 2025-12-28 15:21:49 +01:00
4 changed files with 204 additions and 29 deletions

View File

@ -1,3 +1,5 @@
# TODO
- Spectre avec selecteur multiple
- Caper les fps au choix
- Compiler web

186
main.c
View File

@ -10,10 +10,14 @@
#define COLOR_TEXT_DIM (Color){ 180, 180, 190, 255 }
#define COLOR_TEXT_SEC (Color){ 160, 160, 170, 255 }
#define MAX_WAVELENGTHS 10
typedef struct {
float d1;
float d2;
float lambda;
float lambdas[MAX_WAVELENGTHS];
int lambdasCount;
int selectedLambdaIndex;
float angleM1;
float angleM1_Y;
Vector2 center;
@ -81,7 +85,18 @@ void DrawInterferenceViewGPU(Michelson *mic, Rectangle rec, Shader shader, bool
SetShaderValue(shader, GetShaderLocation(shader, "d1"), &mic->d1, SHADER_UNIFORM_FLOAT);
SetShaderValue(shader, GetShaderLocation(shader, "d2"), &d2_effective, SHADER_UNIFORM_FLOAT);
SetShaderValue(shader, GetShaderLocation(shader, "lambda"), &mic->lambda, SHADER_UNIFORM_FLOAT);
float lambdasData[MAX_WAVELENGTHS];
for(int i = 0; i < MAX_WAVELENGTHS; i++) {
if (i < mic->lambdasCount) lambdasData[i] = mic->lambdas[i];
else lambdasData[i] = 0.0f;
}
int locLambdas = GetShaderLocation(shader, "lambdas");
int locCount = GetShaderLocation(shader, "lambdasCount");
SetShaderValueV(shader, locLambdas, lambdasData, SHADER_UNIFORM_FLOAT, MAX_WAVELENGTHS);
SetShaderValue(shader, locCount, &mic->lambdasCount, SHADER_UNIFORM_INT);
//SetShaderValue(shader, GetShaderLocation(shader, "lambda"), &mic->lambda, SHADER_UNIFORM_FLOAT);
SetShaderValue(shader, GetShaderLocation(shader, "angleM1"), &mic->angleM1, SHADER_UNIFORM_FLOAT);
SetShaderValue(shader, GetShaderLocation(shader, "angleM1_Y"), &mic->angleM1_Y, SHADER_UNIFORM_FLOAT);
SetShaderValue(shader, GetShaderLocation(shader, "zoom"), &zoom, SHADER_UNIFORM_FLOAT);
@ -102,17 +117,28 @@ void DrawInterferenceViewGPU(Michelson *mic, Rectangle rec, Shader shader, bool
void DrawMichelsonSchema (Michelson *mic) {
Vector2 c = mic->center;
Color laserColor = WavelengthToColor(mic->lambda);
//Color laserColor = WavelengthToColor(mic->lambda);
float thickness = 3.0f;
float sourceLen = 450.0f;
float screenLen = 450.0f;
float mirrorSize = 140.0f;
Vector2 startSource = {c.x - sourceLen, c.y};
Vector2 posM2 = {c.x + mic->d2, c.y};
Vector2 posM1 = {c.x, c.y - mic->d1};
Vector2 endPointM2 = {c.x, c.y + screenLen};
float angleRad = -(mic->angleM1 * 2.0f) * (PI / 180.0f);
float yScreen = c.y + screenLen;
float vertDist = yScreen - posM1.y;
float xOff = vertDist * tanf(angleRad);
Vector2 endPointRetour = { posM1.x + xOff, yScreen };
// Laser
BeginBlendMode(BLEND_ADDITIVE);
/*
// Source
Vector2 startSource = {c.x - sourceLen, c.y};
DrawLaserBeam(startSource, c, laserColor, thickness);
// Miroir M2 (fixe)
@ -133,6 +159,24 @@ void DrawMichelsonSchema (Michelson *mic) {
Vector2 endPointM2 = {c.x, c.y + screenLen};
DrawLaserBeam(c, endPointM2, Fade(laserColor, 0.5f), thickness);
*/
float alphaFactor = 1.0f / (float)(mic->lambdasCount > 0 ? mic->lambdasCount : 1);
if(alphaFactor < 0.3f) alphaFactor = 0.3f; // Min de visibilité
for(int i=0; i<mic->lambdasCount; i++) {
Color laserColor = WavelengthToColor(mic->lambdas[i]);
laserColor = Fade(laserColor, alphaFactor);
// Source -> Centre
DrawLaserBeam(startSource, c, laserColor, thickness);
// Centre -> Miroir M2 (fixe)
DrawLaserBeam(c, posM2, laserColor, thickness);
// Centre -> Miroir M1 (mobile)
DrawLaserBeam(c, posM1, laserColor, thickness);
// Retour M1 -> Ecran
DrawLaserBeam(posM1, endPointRetour, Fade(laserColor, 0.6f), thickness);
// Retour M2 -> Ecran
DrawLaserBeam(c, endPointM2, Fade(laserColor, 0.5f), thickness);
}
EndBlendMode();
// Source
@ -190,7 +234,8 @@ void DrawControlPanel(Michelson *mic) {
int startY = 30;
int contentWidth = UI_WIDTH - 40;
int btnSize = 30;
int sliderWidth = contentWidth - (btnSize * 2) - 10;
int spectrumWidth = contentWidth - (btnSize * 2) - 10;
int sliderWidth = spectrumWidth;
GuiSetStyle(DEFAULT, TEXT_SIZE, 16);
GuiSetStyle(DEFAULT, BASE_COLOR_NORMAL, 0x2D2D2DFF);
@ -212,18 +257,124 @@ void DrawControlPanel(Michelson *mic) {
// Longueur d'onde
startY += 80;
DrawText(TextFormat("Longueur d'onde: %.0f nm", mic->lambda), startX, startY, 20, COLOR_TEXT_SEC);
DrawText("SPECTRE (Clic Droit: +/-)", startX, startY, 20, COLOR_TEXT_SEC);
int spectrumHeight = 35;
Rectangle spectrumRect = {startX, startY + 25, contentWidth, spectrumHeight};
// spectre
for (int i = 0; i < spectrumRect.width; i++) {
float prog = (float)i / spectrumRect.width;
float l = 380.0f + prog * (780.0f - 380.0f);
DrawLine(spectrumRect.x + i, spectrumRect.y, spectrumRect.x + i, spectrumRect.y + spectrumRect.height, WavelengthToColor(l));
}
DrawRectangleLinesEx(spectrumRect, 1, GRAY);
Vector2 mousePos = GetMousePosition();
float stepLambda = speedMode ? 10.0f : 1.0f;
if (GuiButtonRepeat((Rectangle){startX, startY + 30, btnSize, 25}, "-", shouldRepeat)) mic->lambda -= stepLambda;
GuiSlider((Rectangle){startX + btnSize + 5, startY + 30, sliderWidth - 40, 25}, NULL, NULL, &mic->lambda, 380, 780);
if (GuiButtonRepeat((Rectangle){startX + btnSize + sliderWidth - 30, startY + 30, btnSize, 25}, "+", shouldRepeat)) mic->lambda += stepLambda;
DrawRectangle(startX + contentWidth - 30, startY + 30, 30, 25, WavelengthToColor(mic->lambda));
if (CheckCollisionPointRec(mousePos, spectrumRect)) {
float mouseRatio = (mousePos.x - spectrumRect.x) / spectrumRect.width;
float mouseLambda = 380.0f + mouseRatio * (780.0f - 380.0f);
if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) {
if (mic->selectedLambdaIndex >= 0 && mic->selectedLambdaIndex < mic->lambdasCount) {
mic->lambdas[mic->selectedLambdaIndex] = mouseLambda;
}
}
if (IsMouseButtonPressed(MOUSE_RIGHT_BUTTON)) {
int foundIdx = -1;
for(int i = 0; i < mic->lambdasCount; i++) {
if (fabs(mic->lambdas[i] - mouseLambda) < 15.0f) {
foundIdx = i; break;
}
}
if (foundIdx != -1) {
if (mic->lambdasCount > 1) {
for(int k=foundIdx; k < mic->lambdasCount - 1; k++) {
mic->lambdas[k] = mic->lambdas[k+1];
}
mic->lambdasCount--;
mic->selectedLambdaIndex = 0;
}
} else {
if (mic->lambdasCount < MAX_WAVELENGTHS) {
mic->lambdas[mic->lambdasCount] = mouseLambda;
mic->selectedLambdaIndex = mic->lambdasCount;
mic->lambdasCount++;
}
}
}
}
//curseur
for (int i = 0; i < mic->lambdasCount; i++) {
if (mic->lambdas[i] < 380) mic->lambdas[i] = 380;
if (mic->lambdas[i] > 780) mic->lambdas[i] = 780;
float ratio = (mic->lambdas[i] - 380.0f) / (780.0f - 380.0f);
float lineX = spectrumRect.x + ratio * spectrumRect.width;
bool isSel = (i == mic->selectedLambdaIndex);
Color lineCol = isSel ? WHITE : GRAY;
float thick = isSel ? 3.0f : 2.0f;
DrawLineEx((Vector2){lineX, spectrumRect.y}, (Vector2){lineX, spectrumRect.y + spectrumRect.height}, thick, lineCol);
if(isSel) DrawTriangle((Vector2){lineX-5, spectrumRect.y-6}, (Vector2){lineX+5, spectrumRect.y-6}, (Vector2){lineX, spectrumRect.y}, WHITE);
}
// selction labmda
startY += spectrumHeight + 35;
if (mic->selectedLambdaIndex >= mic->lambdasCount)
mic->selectedLambdaIndex = 0;
float* currentVal = &mic->lambdas[mic->selectedLambdaIndex];
if (GuiButtonRepeat((Rectangle){startX, startY, 40, 30}, "-", shouldRepeat))
*currentVal -= stepLambda;
DrawRectangle(startX + 45, startY, contentWidth - 90, 30, COLOR_PANEL);
DrawRectangleLines(startX + 45, startY, contentWidth - 90, 30, GRAY);
Color activeCol = WavelengthToColor(*currentVal);
DrawRectangle(startX + 50, startY + 5, 20, 20, activeCol);
DrawText(TextFormat("%.1f nm", *currentVal), startX + 80, startY + 5, 20, WHITE);
if (GuiButtonRepeat((Rectangle){startX + contentWidth - 40, startY, 40, 30}, "+", shouldRepeat))
*currentVal += stepLambda;
// lambda acrifs
startY += 45;
DrawText("Longueurs d'onde actives :", startX, startY, 20, GRAY);
startY += 25;
int cols = 5;
int btnW = (contentWidth - (cols - 1) * 5) / cols;
int btnH = 30;
for(int i = 0; i < mic->lambdasCount; i++) {
int r = i / cols;
int c = i % cols;
Rectangle rectBtn = {startX + c * (btnW + 5), startY + r * (btnH + 5), btnW, btnH};
bool isSel = (i == mic->selectedLambdaIndex);
Color cVal = WavelengthToColor(mic->lambdas[i]);
if (GuiButton(rectBtn, TextFormat("%.0f", mic->lambdas[i])))
mic->selectedLambdaIndex = i;
if (isSel)
DrawRectangleLinesEx(rectBtn, 2, WHITE);
DrawRectangle(rectBtn.x + 2, rectBtn.y + 2, 5, rectBtn.height - 4, cVal);
}
int rows = (mic->lambdasCount + cols - 1) / cols;
startY += (rows * (btnH + 5)) + 20;
// Pos M1
startY += 90;
startY += 0;
DrawText(TextFormat("Position M1 : %.2f um", mic->d1), startX, startY, 20, ORANGE);
// Pas des + et -
@ -285,8 +436,9 @@ void DrawControlPanel(Michelson *mic) {
float delta = 2 * (mic->d1 - mic->d2);
DrawText(TextFormat("Delta = %.2f um", delta), startX, startY + 35, 20, WHITE);
float p = (delta * 1000.0f) / mic->lambda;
DrawText(TextFormat("Ordre p = %.2f", p), startX, startY + 65, 20, WHITE);
float refLambda = mic->lambdas[mic->selectedLambdaIndex];
float p = (delta * 1000.0f) / refLambda;
DrawText(TextFormat("Ordre p (sel) = %.2f", p), startX, startY + 65, 20, WHITE);
// Bas
int bottomY = GetScreenHeight() - 40;
@ -300,15 +452,17 @@ void DrawControlPanel(Michelson *mic) {
int main () {
SetConfigFlags(FLAG_MSAA_4X_HINT);
InitWindow(1920, 1080, "Interferometre de Michelson");
SetTargetFPS(144);
SetTargetFPS(10044);
Shader shader = LoadShader(0, "michelson.fs");
Shader shader = LoadShader(0, "michelson.frag");
Michelson mic = {0};
mic.center = (Vector2){ UI_WIDTH + (1920 - UI_WIDTH) / 2.0f - 100, 1080 / 2.0f };
mic.d1 = 250.0f;
mic.d2 = 250.0f;
mic.lambda = 550.0f;
mic.lambdas[0] = 550.0f;
mic.lambdasCount = 1;
mic.selectedLambdaIndex = 0;
mic.angleM1 = 0.0f;
mic.angleM1_Y = 0.0f;
mic.nGaz = 1.0f;

BIN
michelson

Binary file not shown.

View File

@ -8,13 +8,15 @@ out vec4 finalColor;
uniform vec2 center;
uniform float screenHeight;
uniform vec2 resolution;
//uniform vec2 resolution;
uniform float d1;
uniform float d2;
uniform float lambda;
//uniform float lambda;
uniform float angleM1;
uniform float angleM1_Y;
uniform float zoom;
uniform float lambdas[10];
uniform int lambdasCount;
const float PI = 3.14159265359;
@ -45,26 +47,43 @@ void main() {
float relX = (pixelX - center.x) * zoom;
float relY = (pixelY - center.y) * zoom;
vec3 baseColorVec = WavelengthToRGB(lambda);
// r^2
float radiusSq = relX * relX + relY * relY;
// Diff de marche lamme d'air 2 * e cos(i) mais petits angles => cos(i) ~ 1 - i^2/2 mais i ~ r/f et r^2 = x^2 + y^2
float ringFactor = radiusSq * 0.065;
float ringFactorBase = radiusSq * 0.065;
// Diff de marche du au coin d'air
float wDelta = (relX * angleM1 + relY * angleM1_Y) * 200.0f;
float wDelta = (relX * angleM1 + relY * angleM1_Y) * 200.0;
float currDelta = deltaLnm - ringFactor + wDelta;
float currDeltaBase = deltaLnm + wDelta;
// Formule de Fresnel : I = I_0 * cos^2(phi)
float K = PI / lambda;
float phase = currDelta * K;
float intensity = cos(phase);
intensity = intensity * intensity;
float currDelta = deltaLnm - ringFactorBase + wDelta;
vec3 finalVec = baseColorVec * intensity;
vec3 accumColor = vec3(0.0);
finalColor = vec4(finalVec, 1.0);
for(int i = 0; i < 10; i++) {
if (i >= lambdasCount) break;
float l = lambdas[i];
vec3 baseColorVec = WavelengthToRGB(l);
float currDelta = currDeltaBase - ringFactorBase;
float K = PI / l;
float phase = currDelta * K;
float intensity = cos(phase);
intensity = intensity * intensity;
accumColor += baseColorVec * intensity;
}
// finalColor = vec4(accumColor, 1.0);
// float K = PI / lambda;
// float phase = currDelta * K;
// float intensity = cos(phase);
// intensity = intensity * intensity;
// vec3 finalVec = baseColorVec * intensity;
//finalColor = vec4(finalVec, 1.0);
finalColor = vec4(accumColor, 1.0);
}