/* ================================================================ Core ---------------- Core is somewhat like a service locator, but with larger engine capabilities - in essence, it is a lot of glue that would normally exist in a global scope. An instance of Core, "core," is provided in the global scope and is the instance that is referenced from other contexts. ================================================================ */ #include "Core.hpp" #include "Log.hpp" #include "RenderScene.hpp" #include "RenderCamera.hpp" #include "RenderSet.hpp" #include "RenderObject.hpp" Core core; Core::Core() { v_window = NULL; v_context = 0; v_fbo = 0; } Core::~Core() { } int Core::initSystem() { if (SDL_Init(SDL_INIT_EVERYTHING & ~SDL_INIT_HAPTIC) != 0) { LOG(LOG_ERROR) << FUNC_NAME << " " << SDL_GetError(); return 1; } #if defined(HAVE_OPENGLES) SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1); #endif // Get our maximum windowed display size and use it SDL_DisplayMode display_mode; SDL_GetDesktopDisplayMode(0, &display_mode); v_width = display_mode.w; v_height = display_mode.h; v_flags = SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE; // create our window v_window = SDL_CreateWindow("Roll them Bones", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, v_width, v_height, v_flags); if (v_window == NULL) { LOG(LOG_ERROR) << "SDL_CreateWindow: " << SDL_GetError(); return 1; } // Ensure our v_width/v_height match the window dimensions SDL_GetWindowSize(v_window, &v_width, &v_height); // Get our OpenGL context v_context = SDL_GL_CreateContext(v_window); if (v_context == NULL) { std::cerr << SDL_GetError(); LOG(LOG_ERROR) << "SDL_GL_CreateContext: " << SDL_GetError(); return 1; } // If using glew, initialize it (windows only thus far) #ifdef USE_GLEW glewExperimental = GL_TRUE; if (glewInit() != GLEW_OK) { LOG(LOG_ERROR) << "Could not initialize GLEW"; return 1; } #endif // bind content to window SDL_GL_MakeCurrent(v_window, v_context); // Get our window's FBO id for iOS glGetIntegerv(GL_FRAMEBUFFER_BINDING, &v_fbo); // enable depth testing glEnable(GL_DEPTH_TEST); // glDepthFunc(GL_LESS); // enable back-face culling //glEnable(GL_CULL_FACE); LOG(LOG_INFO) << "OpenGL Renderer: " << glGetString(GL_RENDERER) << "\nOpenGL Version: " << glGetString(GL_VERSION) << "\nGLSL Version: " << glGetString(GL_SHADING_LANGUAGE_VERSION); // FIXME: temporary location for adding cameras/etc. for testing // Create our basic RenderScene scene = new RenderScene(); // TEMP: our framebuffer rendering program Program *program = new Program(); // FIXME: check for GLSL version and automagically load the appropriate shader file #ifdef HAVE_OPENGLES if (program->addShader("data/shaders/fb_fs.100.glsl", GL_FRAGMENT_SHADER) != 0) { LOG(LOG_ERROR) << "Failed to add Shader!"; return 1; } if (program->addShader("data/shaders/fb_vs.100.glsl", GL_VERTEX_SHADER) != 0) { LOG(LOG_ERROR) << "Failed to add Shader!"; return 1; } if (program->doCompile() != 0) { LOG(LOG_ERROR) << "Failed to compile GLSL Program!"; return 1; } // TEMP: our model rendering program Program *program_model = new Program(); if (program_model->addShader("data/shaders/default_fs.100.glsl", GL_FRAGMENT_SHADER) != 0) { LOG(LOG_ERROR) << "Failed to add Shader!"; return 1; } if (program_model->addShader("data/shaders/default_vs.100.glsl", GL_VERTEX_SHADER) != 0) { LOG(LOG_ERROR) << "Failed to add Shdaer!"; return 1; } if (program_model->doCompile() != 0) { LOG(LOG_ERROR) << "Failed to compile GLSL Program!"; return 1; } #else if (program->addShader("data/shaders/fb_fs.glsl", GL_FRAGMENT_SHADER) != 0) { LOG(LOG_ERROR) << "Failed to add Shader!"; return 1; } if (program->addShader("data/shaders/fb_vs.glsl", GL_VERTEX_SHADER) != 0) { LOG(LOG_ERROR) << "Failed to add Shader!"; return 1; } if (program->doCompile() != 0) { LOG(LOG_ERROR) << "Failed to compile GLSL Program!"; return 1; } // TEMP: our model rendering program Program *program_model = new Program(); if (program_model->addShader("data/shaders/default_fs.glsl", GL_FRAGMENT_SHADER) != 0) { LOG(LOG_ERROR) << "Failed to add Shader!"; return 1; } if (program_model->addShader("data/shaders/default_vs.glsl", GL_VERTEX_SHADER) != 0) { LOG(LOG_ERROR) << "Failed to add Shdaer!"; return 1; } if (program_model->doCompile() != 0) { LOG(LOG_ERROR) << "Failed to compile GLSL Program!"; return 1; } #endif RenderCamera *camera = new RenderCamera(); camera->setRenderView(new RenderView(v_width, v_height)); camera->updateProjection(v_width, v_height); camera->setPitch(75.0f); camera->setPosition(0, 35, -10); camera->doRefresh(); scene->addCamera(camera); program->attachTexture(0, camera->getRenderView()->getFBO()); (camera->getRenderView()->setProgram(program)); RenderObject *objerct = new RenderObject(); Mesh *mersh = new Mesh("data/models/chest.obj"); mersh->buildMesh(); objerct->setMesh(mersh); RenderSet *sert = new RenderSet(); sert->setProgram(program_model); sert->addObject(objerct); scene->addSet(sert); glClearColor(1.0f, 1.0f, 1.0f, 0.0f); flags |= IS_RUNNING; return 0; } int Core::closeSystem() { SDL_Quit(); return 0; } /* doProcess */ void Core::doProcess() { SDL_Event event; while (SDL_PollEvent(&event)) { if (event.type == SDL_QUIT) { flags &= ~IS_RUNNING; } else if (event.type == SDL_WINDOWEVENT) { if (event.window.event == SDL_WINDOWEVENT_RESIZED) { v_width = event.window.data1; v_height = event.window.data2; RenderCamera *r_camera; RenderView *r_view; std::vector::iterator camera_it, camera_end; for (camera_it = scene->getCameras()->begin(), camera_end = scene->getCameras()->end(); camera_it != camera_end; ++camera_it) { r_camera = *camera_it; if ((r_view = r_camera->getRenderView()) == NULL) continue; r_camera->updateProjection(v_width, v_height); r_view->setView(v_width, v_height); } } } } doRender(); } void Core::doRender() { scene->doRender(); // Render our main scene using loaded cameras // Now let's actually render the framebuffers glBindFramebuffer(GL_FRAMEBUFFER, v_fbo); glViewport(0, 0, v_width, v_height); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); RenderCamera *r_camera; RenderView *r_view; Program *r_program; // Iterate over each camera's RenderView and send the FBO/mesh to the shader std::vector::iterator camera_it, camera_end; for (camera_it = scene->getCameras()->begin(), camera_end = scene->getCameras()->end(); camera_it != camera_end; ++camera_it) { r_camera = *camera_it; if ((r_view = r_camera->getRenderView()) == NULL) continue; if ((r_program = r_view->getProgram()) == NULL) continue; // FIXME: iOS doesn't like enabling the view's program - black screen if enabled. r_program->activate(); GLuint program_p = r_program->getProgram(); GLuint program_vp = glGetAttribLocation(program_p, "vp"); // enable vertex positions and UV map glEnableVertexAttribArray(program_vp); // Get our mesh Mesh *mesh = r_view->getMesh(); glBindBuffer(GL_ARRAY_BUFFER, mesh->vbo); glEnableVertexAttribArray(program_vp); glVertexAttribPointer(program_vp, 3, GL_FLOAT, GL_FALSE, 0, NULL); // and draw glDrawArrays(GL_TRIANGLES, 0, mesh->vertices.size()); // close 'em glDisableVertexAttribArray(program_vp); } // And update! SDL_GL_SwapWindow(v_window); } SDL_Window* Core::getWindow() { return v_window; }