diff --git a/main.c b/main.c index b209605..a1ea219 100644 --- a/main.c +++ b/main.c @@ -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; ilambdasCount; 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 @@ -213,48 +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); - float stepLambda = speedMode ? 10.0f : 1.0f; - - if (GuiButtonRepeat((Rectangle){startX, startY + 30, btnSize, 25}, "-", shouldRepeat)) mic->lambda -= stepLambda; - - Rectangle spectrumRect = {startX + btnSize + 5, startY + 30, spectrumWidth, 25}; + 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); - Color c = WavelengthToColor(l); - DrawLine(spectrumRect.x + i, spectrumRect.y, spectrumRect.x + i, spectrumRect.y + spectrumRect.height, c); + DrawLine(spectrumRect.x + i, spectrumRect.y, spectrumRect.x + i, spectrumRect.y + spectrumRect.height, WavelengthToColor(l)); } - DrawRectangleLinesEx(spectrumRect, 1, DARKGRAY); + DrawRectangleLinesEx(spectrumRect, 1, GRAY); - if (CheckCollisionPointRec(GetMousePosition(), spectrumRect)) { + Vector2 mousePos = GetMousePosition(); + float stepLambda = speedMode ? 10.0f : 1.0f; + + 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)) { - float mouseX = GetMouseX() - spectrumRect.x; - float ratio = mouseX / spectrumRect.width; - mic->lambda = 380.0f + ratio * (780.0f - 380.0f); + 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++; + } + } } } - float currentRatio = (mic->lambda - 380.0f) / (780.0f - 380.0f); - if (currentRatio < 0) currentRatio = 0; - if (currentRatio > 1) currentRatio = 1; - - float cursorX = spectrumRect.x + currentRatio * spectrumRect.width; - - DrawLine(cursorX - 1, spectrumRect.y, cursorX - 1, spectrumRect.y + spectrumRect.height, BLACK); - DrawLine(cursorX + 1, spectrumRect.y, cursorX + 1, spectrumRect.y + spectrumRect.height, BLACK); - DrawLine(cursorX, spectrumRect.y, cursorX, spectrumRect.y + spectrumRect.height, WHITE); + //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; - if (GuiButtonRepeat((Rectangle){startX + btnSize + spectrumWidth + 10, startY + 30, btnSize, 25}, "+", shouldRepeat)) mic->lambda += stepLambda; + 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->lambda < 380) mic->lambda = 380; - if (mic->lambda > 780) mic->lambda = 780; + 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 - @@ -316,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; @@ -331,7 +452,7 @@ 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.frag"); @@ -339,7 +460,9 @@ int main () { 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; diff --git a/michelson b/michelson index 11f75cb..796dee7 100755 Binary files a/michelson and b/michelson differ diff --git a/michelson.frag b/michelson.frag index a514568..f0c374c 100644 --- a/michelson.frag +++ b/michelson.frag @@ -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); }