3 Commits

Author SHA1 Message Date
Pc
5e41db643c fix: better values for shadows level and color 2026-01-28 02:57:50 +01:00
Pc
2fbd33901c feat: simple shader rendering 2026-01-28 02:49:27 +01:00
Pc
96b1692434 feat: new light + simple shader function 2026-01-28 02:46:31 +01:00

356
main.cpp
View File

@@ -61,6 +61,8 @@ static HINSTANCE hInstance;
GLFWwindow* window;
///////////////////////
void DisableQuickEdit();
void MakeShadowMatrix(GLfloat shadowMat[16], GLfloat groundplane[4], GLfloat lightpos[4]);
// Rotation amounts
static GLfloat xRot = 0.0f;
static GLfloat yRot = 0.0f;
@@ -94,7 +96,7 @@ FPSCounter fpsCounter;
float deltaTime = 0.0f;
static const int targetFPS = 444; // Celowany FPS
static const int targetFPS = 144; // Celowany FPS
//Fps counter
static void LimitFPS(int targetFPS) {
static auto lastTime = std::chrono::high_resolution_clock::now();
@@ -469,98 +471,92 @@ lazik user(10.0f, 0.0f, 0.0f, "res/models/lazik4.obj"); // obiekty eksportujemy
plane mapa( 0.0f, 0.0f, 0.0f, "res/models/mapka3_nofence_noplatform.obj");
static void SetupRC() {
glEnable(GL_MULTISAMPLE); //
glEnable(GL_LINE_SMOOTH);
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
// Light values and coordinates
GLfloat ambientLight[] = {0.3f, 0.3f, 0.3f, 1.0f};
GLfloat diffuseLight[] = {0.7f, 0.7f, 0.7f, 1.0f};
GLfloat specular[] = {1.0f, 1.0f, 1.0f, 1.0f};
GLfloat specref[] = {1.0f, 1.0f, 1.0f, 1.0f};
// Multiple light positions (for light coming from all sides)
GLfloat lightPos1[] = { 50.0f, -100.0f, 50.0f, 1.0f}; // Light 0 position
GLfloat lightPos2[] = {-50.0f, -100.0f, 50.0f, 1.0f}; // Light 1 position
GLfloat lightPos3[] = { 50.0f, -100.0f, -50.0f, 1.0f}; // Light 2 position
GLfloat lightPos4[] = {-50.0f, -100.0f, -50.0f, 1.0f}; // Light 3 position
glEnable(GL_DEPTH_TEST); // Hidden surface removal
glFrontFace(GL_CCW); // Counter clockwise polygons face out
// 1. Podstawowe ustawienia OpenGL
glEnable(GL_DEPTH_TEST); // Usuwanie niewidocznych powierzchni
glFrontFace(GL_CCW); // Przeciwnie do ruchu wskazówek zegara to przód
glDepthFunc(GL_LESS);
// Enable lighting
glEnable(GL_MULTISAMPLE); // Antyaliasing
glEnable(GL_LINE_SMOOTH);
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
// 2. KLUCZOWE: Normalizacja wektorów
// Bez tego, jeśli skalujesz modele, oświetlenie wariuje.
glEnable(GL_NORMALIZE);
// 3. Konfiguracja kolorów światła
// Ambient - światło otoczenia (cienie nie będą czarne, ale lekko szare)
GLfloat ambientLight[] = { 0.4f, 0.4f, 0.4f, 1.0f };
// Diffuse - główny kolor światła słonecznego (lekko ciepły biały)
GLfloat diffuseLight[] = { 0.9f, 0.9f, 0.8f, 1.0f };
// Specular - kolor odbłysku (zmniejszamy intensywność, żeby nie raziło)
GLfloat specular[] = { 0.5f, 0.5f, 0.5f, 1.0f };
// 4. Pozycje świateł
// LIGHT0 - SŁOŃCE (Kluczowa zmiana)
// Czwarty parametr 0.0f oznacza światło KIERUNKOWE (z nieskończoności), a nie punktowe.
// Ustawiamy je wysoko w górze (Y=100) i pod kątem.
GLfloat sunPos[] = { 100.0f, 150.0f, 100.0f, 0.0f };
// LIGHT1 - Doświetlenie cieni (opcjonalne, "fill light" z drugiej strony)
GLfloat fillPos[] = { -100.0f, 50.0f, -100.0f, 0.0f };
GLfloat fillDiffuse[] = { 0.3f, 0.3f, 0.4f, 1.0f }; // Niebieskawe, słabsze światło
// 5. Włączenie oświetlenia
glEnable(GL_LIGHTING);
// Setup and enable light 0
// Konfiguracja Słońca (LIGHT0)
glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);
glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
glLightfv(GL_LIGHT0, GL_POSITION, lightPos1);
glLightfv(GL_LIGHT0, GL_POSITION, sunPos);
glEnable(GL_LIGHT0);
// Setup and enable light 1
glLightfv(GL_LIGHT1, GL_AMBIENT, ambientLight);
glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuseLight);
glLightfv(GL_LIGHT1, GL_SPECULAR, specular);
glLightfv(GL_LIGHT1, GL_POSITION, lightPos2);
// Konfiguracja doświetlenia (LIGHT1) - łagodzi ostre cienie
glLightfv(GL_LIGHT1, GL_AMBIENT, ambientLight); // Wspólny ambient
glLightfv(GL_LIGHT1, GL_DIFFUSE, fillDiffuse);
glLightfv(GL_LIGHT1, GL_POSITION, fillPos);
glEnable(GL_LIGHT1);
// LIGHT2 i LIGHT3 możesz wyłączyć dla wydajności, chyba że robisz reflektory łazika
// Setup and enable light 2
glLightfv(GL_LIGHT2, GL_AMBIENT, ambientLight);
glLightfv(GL_LIGHT2, GL_DIFFUSE, diffuseLight);
glLightfv(GL_LIGHT2, GL_SPECULAR, specular);
glLightfv(GL_LIGHT2, GL_POSITION, lightPos3);
glEnable(GL_LIGHT2);
// Setup and enable light 3
// glLightfv(GL_LIGHT3, GL_AMBIENT, ambientLight);
// glLightfv(GL_LIGHT3, GL_DIFFUSE, diffuseLight);
// glLightfv(GL_LIGHT3, GL_SPECULAR, specular);
// glLightfv(GL_LIGHT3, GL_POSITION, lightPos4);
// glEnable(GL_LIGHT3);
// Enable color tracking
// 6. Materiały
glEnable(GL_COLOR_MATERIAL);
// Set Material properties to follow glColor values
// Kolor obiektu wpływa na światło rozproszone (diffuse) i otoczenia (ambient)
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
// All materials hereafter have full specular reflectivity
// with a high shine
GLfloat specref2[] = {0.2f, 0.2f, 0.2f, 0.2f};
// Zmniejszamy połyskliwość, żeby trawa nie wyglądała jak szkło
GLfloat specref2[] = { 0.1f, 0.1f, 0.1f, 1.0f }; // Bardzo słaby odbłysk materiału
glMaterialfv(GL_FRONT, GL_SPECULAR, specref2);
glMateriali(GL_FRONT, GL_SHININESS, 128);
glMateriali(GL_FRONT, GL_SHININESS, 10); // Zmniejszono ze 128 na 10 (bardziej matowe)
// White background
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
// Tło (Błękitne niebo zamiast białego)
glClearColor(0.53f, 0.81f, 0.92f, 1.0f);
// Initialize GLEW
// --- Reszta Twojej inicjalizacji (GLEW, GLFW, modele) bez zmian ---
timestampedCout("Inicjalizowanie GLEW...");
glewExperimental = true; // Needed for core profile
glewExperimental = true;
if (glewInit() != GLEW_OK) {
timestampedCout("Failed to initialize GLEW");
return;
}
// ... reszta kodu SetupRC ...
timestampedCout("Zainicjalizowano GLEW.");
// Sprawdź czy rozszerzenie jest dostępne i wyłącz V-Sync
if (wglewIsSupported("WGL_EXT_swap_control")) {
wglSwapIntervalEXT(0); // 0 = WYŁĄCZ V-Sync (nielimitowane FPS)
wglSwapIntervalEXT(0);
timestampedCout("V-Sync wylaczony (unlocked FPS).");
}
else {
timestampedCout("Brak obslugi WGL_EXT_swap_control - nie mozna programowo wylaczyc V-Sync.");
}
// Initialize GLFW3
timestampedCout("Inicjalizowanie GLFW3...");
if (!glfwInit()) {
timestampedCout("Failed to initialize GLFW");
}
timestampedCout("Zainicjalizowano GLFW3.");
// Load models
timestampedCout("Ladowanie modelu lazika...");
user.loadModel();
timestampedCout("Ladowanie modelu mapki...");
@@ -571,128 +567,137 @@ static void SetupRC() {
void static RenderScene(void) {
// PS: to nie zadziała, bo okno nie jest tworzone przez glfw
// Ustawienie liczby próbek dla antyaliasingu
glfwWindowHint(GLFW_SAMPLES, 16); // 4x MSAA (Wielokrotne próbkowanie)
// Włączenie antyaliasingu (MSAA)
// Ustawienia wstępne
glfwWindowHint(GLFW_SAMPLES, 16);
glEnable(GL_MULTISAMPLE);
glEnable(GL_NORMALIZE);
glLoadIdentity();
// Przywrócenie macierzy modelu i ustawienie obrotów
glPushMatrix();
// Tryb rysowania (linie/wypełnienie)
switch (polygonmode) {
case 1: glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
default: glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// ==========================================
// 1. OBSŁUGA KAMERY
// ==========================================
float rad = Rotation * GL_PI / 180.0f;
if (panoramic_view) {
// Widok z góry
gluLookAt(Foward, 400.0f, Sides, Foward, 0.0f, Sides, 1.0f, 0.0f, 0.0f);
}
else if (fpv_view) {
// Widok FPV
float lookAtX = Foward - 10.0f * sin(rad);
float lookAtZ = Sides - 10.0f * cos(rad);
gluLookAt(Foward, 15.0f, Sides, lookAtX, 15.0f, lookAtZ, 0.0f, 1.0f, 0.0f);
}
else {
// Widok TPP
float camX = Foward + CameraHeight * sin(rad);
float camZ = Sides + CameraHeight * cos(rad);
gluLookAt(camX, CameraHeight * 0.4f, camZ, Foward, 10.0f, Sides, 0.0f, 1.0f, 0.0f);
}
// Debugerskie obroty całej sceny
glRotatef(xRot, 1.0f, 0.0f, 0.0f);
glRotatef(yRot, 0.0f, 1.0f, 0.0f);
glRotatef(zRot, 0.0f, 0.0f, 1.0f);
// Ustawienie trybu rysowania wielokątów
switch (polygonmode) {
case 1:
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // Rysowanie linii
break;
default:
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); // Wypełnianie poligonów
}
// ==========================================
// 2. RYSOWANIE PODŁOGI I ELEMENTÓW GRY (TILES)
// ==========================================
// PRZENIESIONE NA GÓRĘ: Rysujemy to najpierw, żeby cienie padały NA te obiekty.
// Czyszczenie ekranu przed rysowaniem
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Widok panoramiczny (SHIFT/F5)
// Pomocnicza konwersja na radiany
float rad = Rotation * GL_PI / 180.0f;
if (panoramic_view) {
// --- WIDOK Z GÓRY ---
maxRotationSpeed = 1.0f;
rotationFriction = 0.5f;
float mapZoom = 400.0f;
gluLookAt(Foward, mapZoom, Sides, Foward, 0.0f, Sides, 1.0f, 0.0f, 0.0f);
}
else if (fpv_view) {
// --- WIDOK FIRST PERSON (FPV) ---
maxRotationSpeed = 0.5f;
rotationFriction = 0.1f;
float rad = Rotation * GL_PI / 180.0f;
// Pozycja oczu: środek łazika + lekko w górę
float eyeX = Foward;
float eyeY = 15.0f; // Wysokość "oczu" nad ziemią
float eyeZ = Sides;
// Kierunek patrzenia: zgodnie z rotacją łazika
// Używamy ujemnego sin/cos, bo w Twoim kodzie Rotation steruje modelem w ten sposób
float lookAtX = Foward - 10.0f * sin(rad);
float lookAtZ = Sides - 10.0f * cos(rad);
gluLookAt(
eyeX, eyeY, eyeZ, // Oko jest wewnątrz/nad łazikiem
lookAtX, eyeY, lookAtZ, // Patrzymy przed siebie (na tej samej wysokości)
0.0f, 1.0f, 0.0f // Góra to oś Y
);
}
else {
// --- WIDOK TRZECIOOSOBOWY (TPP) ---
maxRotationSpeed = 0.5f;
rotationFriction = 0.1f;
float rad = Rotation * GL_PI / 180.0f;
float camX = Foward + CameraHeight * sin(rad);
float camZ = Sides + CameraHeight * cos(rad);
float dynamicHeight = CameraHeight * 0.4f;
gluLookAt(camX, dynamicHeight, camZ, Foward, 10.0f, Sides, 0.0f, 1.0f, 0.0f);
}
// Rysowanie mapy
// a) Platforma bazowa
glPushMatrix();
// glColor3f(0.0, 1.0, 0.0); // Zielony kolor
// mapa.draw(); // nie rysuj mapy/terenu .obj
// Platforma niebędąca częścią siatki:
glColor3d(0.031, 0.51, 0.094); // ciemnozielony
glColor3d(0.031, 0.51, 0.094);
platforma(450.0f, 0.0f, -45.0f, 450.0f, 45.0f);
glPopMatrix();
// Rysowanie łazika
// b) Logika gry (Kratki na ziemi)
// Obliczamy pozycję, ale nie rysujemy jeszcze łazika
short grid_x, grid_z;
ustalPozycjeGracza(Foward, Sides, grid_x, grid_z);
// Najpierw aktualizujemy stan siatki
ustawSiatkeNaWzorNieNadpisujacPostepu();
aktualizujBiezacaKratke(grid_x, grid_z);
// TERAZ RYSUJEMY KRATKI (żeby cień mógł na nie paść)
// Zakładam, że ta funkcja rysuje GL_QUADS na Y ~ 0.0
tworzKratkiZSiatki();
// ==========================================
// 3. RYSOWANIE WSZYSTKICH CIENI
// ==========================================
{
GLfloat lightPos[] = { 100.0f, 150.0f, 100.0f, 0.0f };
// Podnosimy cień minimalnie wyżej (0.15f), żeby na pewno był nad kratkami gry
GLfloat groundPlane[] = { 0.0f, 1.0f, 0.0f, 0.0f };
GLfloat shadowMatrix[16];
MakeShadowMatrix(shadowMatrix, groundPlane, lightPos);
glPushMatrix();
// Spłaszczamy wszystko do cienia
glMultMatrixf(shadowMatrix);
// Wyłączamy światło i tekstury dla cienia
glDisable(GL_LIGHTING);
glDisable(GL_TEXTURE_2D);
glDisable(GL_DEPTH_TEST); // Wyłączamy Depth Test, żeby cień nie migotał z kratkami
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glColor4f(0.0f, 0.0f, 0.0f, 1.0f); // Półprzezroczysty czarny
// A. Cień Łazika
glPushMatrix();
glTranslatef(Foward, 0.0f, Sides);
glRotatef(Rotation, 0.0f, 1.0f, 0.0f);
user.draw();
glPopMatrix();
// Przywracamy ustawienia
glDisable(GL_BLEND);
glEnable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
glEnable(GL_LIGHTING);
glPopMatrix();
}
// ==========================================
// 4. RYSOWANIE PRAWDZIWYCH OBIEKTÓW 3D
// ==========================================
// A. Łazik
glPushMatrix();
glTranslatef(Foward, 0.0f, Sides); // Translacja łazika
glRotatef(Rotation, 0.0f, 1.0f, 0.0f); // Obrót łazika
glColor3f(1.0, 0.0, 0.0); // Czerwony kolor dla łazika
user.draw(); // Rysuj łazik z pomocą lazik.cpp
glTranslatef(Foward, 0.0f, Sides);
glRotatef(Rotation, 0.0f, 1.0f, 0.0f);
glColor3f(1.0f, 1.0f, 1.0f); // Reset koloru
user.draw();
UpdateRover(fences);
fpsCounter.update();
glPopMatrix();
// std::cout << "X: " << Foward << " Z: " << Sides << " Rotation: " << Rotation << "\n";
// Rysowanie innych obiektów
// 1 pole siatki = 90x90m
plot( 450.0f, 3.0f, -90.0f, 900.0f, 4.0f, 1); // 1 - poziomo
plot( 0.0f, 3.0f, 405.0f, 990.0f, 4.0f, 0); // 0 - pionowo
plot( 450.0f, 3.0f, 10*90.0f, 900.0f, 4.0f, 1); // 1 - poziomo
plot(10*90.0f, 3.0f, 405.0f, 990.0f, 4.0f, 0); // 0 - pionowo
// B. Stodoła
stodola(45.0f, 0.0f, -45.0f, 70.0f);
// Mechanika gry
short grid_x, grid_z;
ustalPozycjeGracza(Foward, Sides, grid_x, grid_z);
// std::cout << "grid_X: " << grid_x << " grid_Z: " << grid_z << " status: " << siatka[10*grid_x + (9 - grid_z)] << "\n";
ustawSiatkeNaWzorNieNadpisujacPostepu();
tworzKratkiZSiatki();
aktualizujBiezacaKratke(grid_x, grid_z);
// C. Płotki
plot(450.0f, 3.0f, -90.0f, 900.0f, 4.0f, 1);
plot(0.0f, 3.0f, 405.0f, 990.0f, 4.0f, 0);
plot(450.0f, 3.0f, 10 * 90.0f, 900.0f, 4.0f, 1);
plot(10 * 90.0f, 3.0f, 405.0f, 990.0f, 4.0f, 0);
// Zamiana buforów (double buffering)
// glfwSwapBuffers(window); // Przełączenie buforów
// glfwPollEvents(); // Obsługa zdarzeń
glPopMatrix(); // Przywrócenie poprzedniej macierzy
glMatrixMode(GL_MODELVIEW); // Ustawienie trybu modelu-widoku
// Wymuszenie wykonania wszystkich rysunków
glFlush();
}
@@ -1240,4 +1245,37 @@ void DisableQuickEdit() {
// Wyłączamy opcję ENABLE_QUICK_EDIT_MODE oraz ENABLE_INSERT_MODE
SetConsoleMode(hInput, prev_mode & ~ENABLE_QUICK_EDIT_MODE & ~ENABLE_INSERT_MODE);
}
// Funkcja tworząca macierz cienia (Shadow Matrix)
// groundplane: równanie płaszczyzny (Ax + By + Cz + D = 0)
// lightpos: pozycja światła
void MakeShadowMatrix(GLfloat shadowMat[16], GLfloat groundplane[4], GLfloat lightpos[4])
{
GLfloat dot;
// Iloczyn skalarny normalnej płaszczyzny i wektora światła
dot = groundplane[0] * lightpos[0] +
groundplane[1] * lightpos[1] +
groundplane[2] * lightpos[2] +
groundplane[3] * lightpos[3];
shadowMat[0] = dot - lightpos[0] * groundplane[0];
shadowMat[4] = 0.f - lightpos[0] * groundplane[1];
shadowMat[8] = 0.f - lightpos[0] * groundplane[2];
shadowMat[12] = 0.f - lightpos[0] * groundplane[3];
shadowMat[1] = 0.f - lightpos[1] * groundplane[0];
shadowMat[5] = dot - lightpos[1] * groundplane[1];
shadowMat[9] = 0.f - lightpos[1] * groundplane[2];
shadowMat[13] = 0.f - lightpos[1] * groundplane[3];
shadowMat[2] = 0.f - lightpos[2] * groundplane[0];
shadowMat[6] = 0.f - lightpos[2] * groundplane[1];
shadowMat[10] = dot - lightpos[2] * groundplane[2];
shadowMat[14] = 0.f - lightpos[2] * groundplane[3];
shadowMat[3] = 0.f - lightpos[3] * groundplane[0];
shadowMat[7] = 0.f - lightpos[3] * groundplane[1];
shadowMat[11] = 0.f - lightpos[3] * groundplane[2];
shadowMat[15] = dot - lightpos[3] * groundplane[3];
}