int main() { initCrashSystem(); initMemorySystem(); SDL_Init(SDL_INIT_EVERYTHING); SDL_Window *window = SDL_CreateWindow("", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 640, SDL_WINDOW_OPENGL |SDL_WINDOW_RESIZABLE |SDL_WINDOW_SHOWN); SDL_GLContext context = createContext(window); SDL_GL_SetSwapInterval(1); bool running = true; float frametime = 0.0f; Renderer *renderer = NEW(Renderer, NEW(GLBackend)); ResourceManager *resMgr = renderer->getResourceManager(); Scene *scene = NEW(Scene, renderer); Scene *quadScene = NEW(Scene, renderer); RenderTarget *target = NEW(RenderTarget, renderer); RenderTarget *textureTarget = NEW(RenderTarget, renderer); Framebuffer *framebuffer = textureTarget->addFramebuffer(); framebuffer->addColor(resMgr->createTexture(Texture::Texture2D), Texture::RGBAU8_Norm_InternalFormat); framebuffer->addColor(resMgr->createTexture(Texture::Texture2D), Texture::Red32F_InternalFormat); framebuffer->addColor(resMgr->createTexture(Texture::Texture2D), Texture::RGBU8_Norm_InternalFormat); framebuffer->addColor(resMgr->createTexture(Texture::Texture2D), Texture::RGBAU8_Norm_InternalFormat); framebuffer->addColor(resMgr->createTexture(Texture::Texture2D), Texture::RGBU8_Norm_InternalFormat); framebuffer->addColor(resMgr->createTexture(Texture::Texture2D), Texture::RGBU8_Norm_InternalFormat); framebuffer->finish(); ResPtr<Model> model = resMgr->load("res/models/dragon.json").cast<Model>(); ResPtr<Mesh> quadMesh = resMgr->createMesh(resMgr->load("res/shaders/quad vertex.json").cast<Shader>(), Mesh::Triangles, 6); VertexBuffer *quadVB = quadMesh->addPositions(renderer, MeshComponent(2, MeshComponent::Float32))->getVertexBuffer(); quadVB->alloc(sizeof(glm::vec2)*6); glm::vec2 *quadPositions = (glm::vec2 *)quadVB->map(false, true); quadPositions[0] = glm::vec2(-1.0f, -1.0f); quadPositions[1] = glm::vec2( 1.0f, -1.0f); quadPositions[2] = glm::vec2(-1.0f, 1.0f); quadPositions[3] = glm::vec2(-1.0f, 1.0f); quadPositions[4] = glm::vec2( 1.0f, -1.0f); quadPositions[5] = glm::vec2( 1.0f, 1.0f); quadVB->unmap(); ResPtr<Material> quadMaterial = resMgr->createMaterial( resMgr->load("res/shaders/quad fragment.json").cast<Shader>()); quadMaterial->mUniforms["colorTexture"] = framebuffer->getColorTexture(0); quadMaterial->mUniforms["depthTexture"] = framebuffer->getColorTexture(1); quadMaterial->mUniforms["normalTexture"] = framebuffer->getColorTexture(2); quadMaterial->mUniforms["materialTexture"] = framebuffer->getColorTexture(3); quadMaterial->mUniforms["ambientTexture"] = framebuffer->getColorTexture(4); quadMaterial->mUniforms["specularTexture"] = framebuffer->getColorTexture(5); quadMaterial->mUniforms["lightDirection"] = glm::vec3(0.0f); ResPtr<Model> quadModel = resMgr->createModel(); quadModel->mLODs.push_back(LOD(quadMesh, quadMaterial, 0.0f)); quadModel->sortLODs(); quadScene->createEntity(quadModel); scene->mSkyboxTexture = resMgr->load("res/textures/enviroment texture.json").cast<Texture>(); Entity *entity = scene->createEntity(model); float t = 0.0f; bool fullscreen = false; glm::vec3 cameraPosition(0.0f, 0.0f, 5.0f); glm::vec2 cameraAngle(3.1415f, 0.0f); float cameraSpeed = 3.0f; float cameraRotateSpeed = 1.0f; while (running) { Uint64 start = SDL_GetPerformanceCounter(); SDL_Event event; while (SDL_PollEvent(&event)) { switch (event.type) { case SDL_QUIT: { running = false; break; } case SDL_KEYDOWN: { switch (event.key.keysym.scancode) { case SDL_SCANCODE_ESCAPE: { running = false; break; } case SDL_SCANCODE_F1: { fullscreen = not fullscreen; SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP*fullscreen); } default: {} } } } } const Uint8 *pressed = SDL_GetKeyboardState(NULL); glm::vec3 direction(std::cos(cameraAngle.y) * std::sin(cameraAngle.x), std::sin(cameraAngle.y), std::cos(cameraAngle.y) * std::cos(cameraAngle.x)); glm::vec3 right(std::sin(cameraAngle.x - 3.1415f / 2.0f), 0.0f, std::cos(cameraAngle.x - 3.1415f / 2.0f)); glm::vec3 up = glm::cross(right, direction); if (pressed[SDL_SCANCODE_LEFT]) { cameraAngle.x += cameraRotateSpeed * frametime; } else if (pressed[SDL_SCANCODE_RIGHT]) { cameraAngle.x -= cameraRotateSpeed * frametime; } else if (pressed[SDL_SCANCODE_UP]) { cameraAngle.y += cameraRotateSpeed * frametime; } else if (pressed[SDL_SCANCODE_DOWN]) { cameraAngle.y -= cameraRotateSpeed * frametime; } else if (pressed[SDL_SCANCODE_A]) { cameraPosition -= right * frametime * cameraSpeed; } else if (pressed[SDL_SCANCODE_D]) { cameraPosition += right * frametime * cameraSpeed; } else if (pressed[SDL_SCANCODE_W]) { cameraPosition += direction * frametime * cameraSpeed; } else if (pressed[SDL_SCANCODE_S]) { cameraPosition -= direction * frametime * cameraSpeed; } scene->mProjectionTransform.reset(); int windowWidth; int windowHeight; SDL_GetWindowSize(window, &windowWidth, &windowHeight); target->setWidthAndHeight(windowWidth, windowHeight); textureTarget->setWidthAndHeight(windowWidth, windowHeight); scene->mProjectionTransform.perspective(45.0f, float(windowWidth)/float(windowHeight), 0.1f, 100.0f); scene->mViewTransform.reset(); scene->mViewTransform.lookAt(cameraPosition, cameraPosition+direction, up); t += frametime; entity->mTransform.reset(); entity->mTransform.scale(glm::vec3(0.5f)); entity->mTransform.rotate(45.0f*t, glm::vec3(0.0f, 1.0f, 0.0f)); renderer->render(textureTarget, scene); quadMaterial->mUniforms["lightDirection"] = glm::mat3(scene->mViewTransform.getMatrix()) * glm::vec3(-1.0f, 1.0f, -1.0f); renderer->render(target, quadScene); SDL_GL_SwapWindow(window); resMgr->deleteUnusedResources(); Uint64 end = SDL_GetPerformanceCounter(); frametime = float(end - start) / float(SDL_GetPerformanceFrequency()); char title[256]; std::memset(title, 0, 256); std::snprintf(title, 256, "Frametime: %.4f, Framerate: %.0f", frametime, 1.0f/frametime); SDL_SetWindowTitle(window, title); } model = nullRes<Model>(); quadMesh = nullRes<Mesh>(); quadMaterial = nullRes<Material>(); quadModel = nullRes<Model>(); DELETE(RenderTarget, textureTarget); DELETE(RenderTarget, target); DELETE(Scene, quadScene); DELETE(Scene, scene); DELETE(Renderer, renderer); SDL_GL_DeleteContext(context); SDL_DestroyWindow(window); SDL_Quit(); deinitMemorySystem(); return 0; }
DemoScene raytracer::gui::constructDemoScene() { /// Load resources ResourceManager* resourceManager = ResourceManager::getInstance(); Texture* terrainTexture = new TerrainHeightTexture( // multitexture for terrain resourceManager->createImage("terrainImage1", "resources/terrain_dirt.tga"), resourceManager->createImage("terrainImage2", "resources/terrain_grass.tga"), resourceManager->createImage("terrainImage3", "resources/terrain_rock.tga"), resourceManager->createImage("terrainImage4", "resources/terrain_snow.tga") ); std::vector<Image*> skyBoxImages(6); skyBoxImages[0] = resourceManager->createImage("skyboxFront", "resources/miramar_ft.tga"); skyBoxImages[1] = resourceManager->createImage("skyboxRight", "resources/miramar_rt.tga"); skyBoxImages[2] = resourceManager->createImage("skyboxBack", "resources/miramar_bk.tga"); skyBoxImages[3] = resourceManager->createImage("skyboxLeft", "resources/miramar_lf.tga"); skyBoxImages[4] = resourceManager->createImage("skyboxUp", "resources/miramar_up.tga"); skyBoxImages[5] = resourceManager->createImage("skyboxDown", "resources/miramar_dn.tga"); std::vector<Texture*> skyBoxTextures(6); skyBoxTextures[0] = resourceManager->createTexture("skyboxFrontTexture", "skyboxFront"); skyBoxTextures[1] = resourceManager->createTexture("skyboxRightTexture", "skyboxRight"); skyBoxTextures[2] = resourceManager->createTexture("skyboxBackTexture", "skyboxBack"); skyBoxTextures[3] = resourceManager->createTexture("skyboxLeftTexture", "skyboxLeft"); skyBoxTextures[4] = resourceManager->createTexture("skyboxUpTexture", "skyboxUp"); skyBoxTextures[5] = resourceManager->createTexture("skyboxDownTexture", "skyboxDown"); // Define scene AABB sceneBoundary(Vector3(-1000, -1000, -1000), Vector3(1000, 1000, 1000)); ShapeList shapes; shapes.push_back(new Sphere(Vector3(0.0f, 8.0f, -25.0f), 2.0f, new Material(0.5f, 1.2f, 0.5f, 20.0f, Material::NO_REFLECTION, Material::NO_REFRACTION, Colour(0.4f, 0.4f, 0.8f), NULL) )); shapes.push_back(new Sphere(Vector3(-4.0f, 10.0f, -20.0f), 2.0f, new Material(0.5f, 3.0f, 1.0f, 20.0f, 1.0f, Material::NO_REFRACTION, Colour(), NULL) )); shapes.push_back(new Sphere(Vector3(0.0f, 5.0f, -15.0f), 2.0f, new Material(0.5f, 1.2f, 0.5f, 20.0f, 0.5f, 1.6666, Colour(0.8f, 0.2f, 0.2f), NULL) )); shapes.push_back(new Sphere(Vector3(3.0f, 5.0f, -26.5f), 1.0f, new Material(5.0f, 0.0f, 0.0f, 0.0f, 0.4f, Material::NO_REFRACTION, Colour(0.9f, 0.65f, 0.0f), NULL) )); // Load skybox shapes.push_back(shapeloaders::getSkyBox(common::SKYBOX_SIZE, skyBoxTextures)); // Define all possible viewpoints std::vector<Camera> cameras; cameras.reserve(3); cameras.push_back(Camera( Vector3(0, 5.0f, 0), Vector3(0, 0, -1), Vector3(0, 1, 0), Rect(-100, 100, -100, 100), 200, false)); cameras.push_back(Camera( Vector3(-10, 3.0f, -10.0f), Vector3(1, 0.2f, -1), Vector3(0, 1, 0), Rect(-100, 100, -100, 100), 200, false)); cameras.push_back(Camera( Vector3(5.0f, 30.0f, -50.0f), Vector3(0.0f, -0.6f, 1), Vector3(0, 1, 0), Rect(-100, 100, -100, 100), 200, false)); // Load all possible terrain std::vector<std::string> heightmapFilenames; heightmapFilenames.push_back("resources/heightmap.tga"); heightmapFilenames.push_back("resources/heightmap2.tga"); heightmapFilenames.push_back("resources/heightmap3.tga"); std::vector<Image*> heightmaps; for (unsigned int i = 0; (i < heightmapFilenames.size()); i++) heightmaps.push_back( resourceManager->createImage("heightmap", heightmapFilenames[i]) ); std::vector<Vector3> terrainOffsets; for (unsigned int i = 0; (i < heightmaps.size()); i++) { terrainOffsets.push_back(Vector3( -((common::TERRAIN_CELL_SIZE * heightmaps[i]->getWidth()) / 2.0f), 0.0f, -((common::TERRAIN_CELL_SIZE * heightmaps[i]->getHeight()) / 2.0f)) ); } ShapeList terrainVariants; for (unsigned int i = 0; (i < heightmaps.size()); i++) { Shape* unoptimisedTerrain = shapeloaders::getTerrainFromHeightmap( heightmapFilenames[i], common::TERRAIN_CELL_SIZE, common::TERRAIN_MAX_HEIGHT, terrainOffsets[i], terrainTexture, false); Shape* optimisedTerrain = shapeloaders::getTerrainFromHeightmap( heightmapFilenames[i], common::TERRAIN_CELL_SIZE, common::TERRAIN_MAX_HEIGHT, terrainOffsets[i], terrainTexture, true); terrainVariants.push_back(unoptimisedTerrain); terrainVariants.push_back(optimisedTerrain); } // Construct test shapes (lines of each terrain's octree) ShapeList octreeLines; for (unsigned int i = 0; (i < terrainVariants.size()); i += 2) // go in 2s so unoptimised terrain is skipped { LineList lines = dynamic_cast<Octree*>(terrainVariants[i + 1])->getBoundingLines(); ShapeList lineShapes = generateLines(lines, 0.4f, NULL); BoundingShape* rootOfLines = new BoundingShape(lineShapes, sceneBoundary); octreeLines.push_back(rootOfLines); } // Create renderer to render scene Raytracer* renderer = new Raytracer(cameras[0]); renderer->setRootShape(new BoundingShape(shapes, sceneBoundary)); // Add light sources std::vector<PointLight> pointLights; pointLights.push_back(PointLight( Vector3(-100, 70, 100), Colour(0.2f, 0.2f, 0.2f), Colour(0.4f, 0.4f, 0.4f), Colour(1.0f, 1.0f, 1.0f) )); pointLights.push_back(PointLight( Vector3(3.0f, 5.0f, -26.5f), Colour(0.0f, 0.0f, 0.0f), Colour(0.6f, 0.76f, 0.0f), Colour(1.0f, 0.3f, 0.0f) )); // Disable test shapes at start renderer->showTestShapes(false); // Return the entire scene DemoScene scene = { renderer, cameras, terrainVariants, octreeLines, pointLights }; return scene; }