#include "game.h" #include "math/vector3f.h" #include "math/vector2f.h" #include "math/matrix4x4.h" #include "input.h" #include "util/util.h" #include "util/util_time.h" #include "light.h" #include "renderer/renderer.h" #include /** TODO: Shadows Texture Atlases Memory management +improve skybox | +->fog +->day/night +mouse picking (is it working perfectly?) +add cell shading? improve math package repair gui on renderer.c improve shape loading (tangent generation) (normal generation) improve normal mapping **/ void LoadResources(game_t *game); void Draw(game_t *game); void ProcessInput(game_t *game); void CleanUp(game_t *game); int main(int argc, char *argv[]) { SDL_Init(SDL_INIT_EVERYTHING); game_t game; game.gameState = RUNNING; game.window = Window_Create("Test", WINDOW_WIDTH, WINDOW_HEIGHT); GLenum err = glewInit(); if(err != GLEW_OK) { fputs(glewGetErrorString(err), stderr); Util_FatalError("Glew could no be started!"); } glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); glCullFace(GL_BACK); SDL_GL_SetSwapInterval(1); // glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); game.shaderProgram.ID = Shader_CompileShaders("resources/shaders/shader.vert", "resources/shaders/shader.frag"); game.terrainProgram.ID = Shader_CompileShaders("resources/shaders/terrainShader.vert", "resources/shaders/terrainShader.frag"); game.skyboxProgram.ID = Shader_CompileShaders("resources/shaders/skyboxShader.vert", "resources/shaders/skyboxShader.frag"); glUseProgram(game.shaderProgram.ID); Camera_Init(&game.camera); game.camera.projectionMatrix = mat4_perspective(60.0f, WINDOW_ASPECT_RATIO, 0.1f, 900.0f); LoadResources(&game); glClearColor(0.0f, 0.0f, 0.0f, 1.0f); Time_Init(); Time_SetMaxFramesPerSecond(60); while(game.gameState != EXIT) { Time_Begin(); ProcessInput(&game); Player_Update(&game.player, game.terrain); Draw(&game); float FPS = Time_End(); if( !( Time_GetCountedFrames() % (int)FPS ) ) fprintf(stderr, "FPS: %.4f\n", FPS); } Window_Destroy(game.window); CleanUp(&game); SDL_Quit(); return 0; } void CleanUp(game_t *game) { Shape_Free(game->entsShape); Shape_Free(game->sky.cube); Texture_Destroy(game->entsTexture); Texture_Destroy(game->sky.texture); Texture_Destroy(game->normalMap); Texture_Destroy(game->defaultNormalMap); Terrain_Destroy(game->terrain); Shader_Destroy(game->shaderProgram.ID); Shader_Destroy(game->terrainProgram.ID); Shader_Destroy(game->skyboxProgram.ID); Render_Quit(); } void LoadResources(game_t *game) { Render_Init(); Uint32 start = SDL_GetTicks(); game->entsShape = Shape_LoadOBJ("resources/barrel.obj"); game->entsTexture = Texture_Create2D("resources/textures/barrel.png"); Player_Init(&game->player); game->player.entity.texture = game->entsTexture; game->player.entity.shape = game->entsShape; { vec3_t position = { 0.0f, 3.0f, 0.0f }; float rotation[3] = { 0.0f, 0.0f, 0.0f }; game->ents[0].position = position; game->ents[0].rotX = rotation[0]; game->ents[0].rotY = rotation[1]; game->ents[0].rotZ = rotation[2]; game->ents[0].shape = game->entsShape; game->ents[0].texture = game->entsTexture; } { vec3_t position = { -400.0f, 0.0f, -400.0f }; GLuint blendmap = Texture_Create2D("resources/textures/blendmap.png"); TerrainTexturePack pack = { { Texture_Create2D("resources/textures/soil1.png"), Texture_Create2D("resources/textures/soil2.png"), Texture_Create2D("resources/textures/soil4.png"), Texture_Create2D("resources/textures/soil3.png"), } }; game->terrain = Terrain_Create(800, 800, "resources/textures/heightmap.png", blendmap, &pack); game->terrain->position = position; } { game->sky.rotation = 0.0f; game->sky.cube = Shape_MakeSkyBox(500.0f); const char *paths[6] = { "resources/textures/right.png", "resources/textures/left.png", "resources/textures/top.png", "resources/textures/bottom.png", "resources/textures/back.png", "resources/textures/front.png" }; game->sky.texture = Texture_CreateCubeMap(paths); } /* Shader Layouts */ Shader_Layout *layout = &game->shaderProgram; layout->Texture = Shader_GetUniformLocation(layout->ID, "Texture"); layout->modelToWorld = Shader_GetUniformLocation(layout->ID, "M_model"); layout->totalTransform = Shader_GetUniformLocation(layout->ID, "M_MVP"); layout->lightPosition = Shader_GetUniformLocation(layout->ID, "lightPosition"); layout->lightColor = Shader_GetUniformLocation(layout->ID, "lightColor"); layout->lightAttenuation = Shader_GetUniformLocation(layout->ID, "attenuation"); layout->Normal_Map = Shader_GetUniformLocation(layout->ID, "normalMap"); layout = &game->terrainProgram; layout->modelToWorld = Shader_GetUniformLocation(layout->ID, "M_model"); layout->totalTransform = Shader_GetUniformLocation(layout->ID, "M_MVP"); layout->lightPosition = Shader_GetUniformLocation(layout->ID, "lightPosition"); layout->lightColor = Shader_GetUniformLocation(layout->ID, "lightColor"); layout->lightAttenuation = Shader_GetUniformLocation(layout->ID, "attenuation"); layout->extra0 = Shader_GetUniformLocation(layout->ID, "Texture_Background"); layout->extra1 = Shader_GetUniformLocation(layout->ID, "Texture_R"); layout->extra2 = Shader_GetUniformLocation(layout->ID, "Texture_G"); layout->extra3 = Shader_GetUniformLocation(layout->ID, "Texture_B"); layout->extra4 = Shader_GetUniformLocation(layout->ID, "Texture_BlendMap"); layout = &game->skyboxProgram; layout->totalTransform = Shader_GetUniformLocation(layout->ID, "M_MVP"); layout->Texture = Shader_GetUniformLocation(layout->ID, "cubeMap"); game->normalMap = Texture_Create2D("resources/textures/normal_map.png"); game->defaultNormalMap = Texture_Create2D("resources/textures/default_normal_map.png"); fprintf(stderr, "Loading time: %u (ms)\n", SDL_GetTicks() - start); } void Draw(game_t *game) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); /*We upload all the light vectors*/ static const light_t diffuseLight[1] = { /* Sun Light */ { {5.0f, 40.0f, 2.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {1.0f, 0.0f, 0.0f} }, /* Other lights { {10.0f, 20.0f, 0.0f}, {1.0f, 0.0f, 0.0f, 1.0f}, {1.0f, 0.01f, 0.002f} }, { {20.0f, 20.0f, 0.0f}, {0.0f, 0.0f, 1.0f, 1.0f}, {1.0f, 0.01f, 0.002f} }, { {30.0f, 20.0f, 0.0f}, {0.0f, 1.0f, 0.0f, 1.0f}, {1.0f, 0.01f, 0.002f} },*/ }; Shader_SetUniformVec3(game->shaderProgram.ID, "World_eyePosition", (float*)&game->camera.position); Render_LoadLights(&game->shaderProgram, diffuseLight, 1); glActiveTexture(GL_TEXTURE13); glBindTexture(GL_TEXTURE_2D, game->normalMap); glUniform1i(game->shaderProgram.Normal_Map, 13); mat4_t viewMatrix, projectedViewMatrix; viewMatrix = Camera_GetModelToViewMatrix(&game->camera); projectedViewMatrix = mat4_mul(&game->camera.projectionMatrix, &viewMatrix); Render_DrawEntity(&game->shaderProgram, &projectedViewMatrix, &game->player.entity); Render_DrawEntity(&game->shaderProgram, &projectedViewMatrix, &game->ents[0]); glUseProgram(game->terrainProgram.ID); Shader_SetUniformVec3(game->terrainProgram.ID, "World_eyePosition", (float*)&game->camera.position); Render_LoadLights(&game->terrainProgram, diffuseLight, 1); Render_DrawTerrain(&game->terrainProgram, &projectedViewMatrix, game->terrain); glUseProgram(game->skyboxProgram.ID); Render_DrawSky(&game->skyboxProgram, &viewMatrix, &game->camera.projectionMatrix, &game->sky); glUseProgram(game->shaderProgram.ID); Window_Update(game->window); } void ProcessInput(game_t *game) { static vec2_t mousePosition; SDL_Event e; while(SDL_PollEvent(&e)) { switch(e.type) { case SDL_QUIT: game->gameState = EXIT; break; case SDL_MOUSEMOTION: mousePosition.x = (GLfloat) e.motion.x; mousePosition.y = (GLfloat) e.motion.y; Camera_MouseUpdate(&game->camera, &mousePosition); break; case SDL_KEYDOWN: Input_PressKey(e.key.keysym.scancode); break; case SDL_KEYUP: Input_ReleaseKey(e.key.keysym.scancode); break; } if(Input_isKeyPressed(SDL_SCANCODE_UP)) Camera_Move_Foward(&game->camera); if(Input_isKeyPressed(SDL_SCANCODE_DOWN)) Camera_Move_Backward(&game->camera); if(Input_isKeyPressed(SDL_SCANCODE_LEFT)) Camera_Move_Left(&game->camera); if(Input_isKeyPressed(SDL_SCANCODE_RIGHT)) Camera_Move_Right(&game->camera); if(Input_isKeyPressed(SDL_SCANCODE_ESCAPE)) game->gameState = EXIT; } }