void Particle_Group::Init(){ First_Run=false; ReloadShaders(); Particle_Vertex v; v.pos = vec3(0, 0, 0); v.vel = vec3(0, 40, 0); v.Timer=0; v.Type=0; Graphics::Buffer particle_start; particle_start.Create(1, sizeof(Particle_Vertex), VERTEX_BUFFER, DEFAULT, CPU_NONE, &v); Particle_In.Create(MAX_PARTICLES, sizeof(Particle_Vertex), STREAM_BUFFER_OR_VERTEX_BUFFER); Particle_Out.Create(MAX_PARTICLES, sizeof(Particle_Vertex), STREAM_BUFFER_OR_VERTEX_BUFFER); CBuffer.Create(1, sizeof(cbuffer), CONSTANT_BUFFER); int iNumRandValues = 1024; srand( timeGetTime() ); std::vector<float> ptr; ptr.resize(iNumRandValues * 4); for( int i = 0; i < iNumRandValues * 4; i++ ) { ptr[i] = float( ( rand() % 10000 ) - 5000 ); } Random_Tex.Create(&ptr[0], iNumRandValues, 1, 1, DEFAULT, CPU_NONE, NO_FLAG, FORMAT_RGBA32F); Particle_Tex.Create("particle.dds"); particle_start.BindAsVertexBuffer(); _Update(0.0f); Graphics::DrawVertices(1, 0); Graphics::Buffer::UnBindSOBuffer(); Graphics::Buffer::UnBindVertexBuffer(); std::swap(From, To); }
bool D3DPostProcessor::Initialize() { D3D12_DESCRIPTOR_HEAP_DESC sampler_descriptor_heap_desc = {}; sampler_descriptor_heap_desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; sampler_descriptor_heap_desc.NumDescriptors = 8; sampler_descriptor_heap_desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER; HRESULT hr = D3D::device->CreateDescriptorHeap(&sampler_descriptor_heap_desc, IID_PPV_ARGS(m_texture_samplers_descriptor_heap.ReleaseAndGetAddressOf())); if (FAILED(hr)) { return false; } texture_sampler_cpu_handle = m_texture_samplers_descriptor_heap->GetCPUDescriptorHandleForHeapStart(); // Lookup tables for samplers static const D3D12_FILTER d3d_sampler_filters[] = { D3D12_FILTER_MIN_MAG_MIP_POINT, D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT }; static const D3D12_TEXTURE_ADDRESS_MODE d3d_address_modes[] = { D3D12_TEXTURE_ADDRESS_MODE_CLAMP, D3D12_TEXTURE_ADDRESS_MODE_WRAP, D3D12_TEXTURE_ADDRESS_MODE_BORDER }; // Create sampler objects to match posible configuration values D3D12_SAMPLER_DESC sampler_desc = { d3d_sampler_filters[0], d3d_address_modes[0], d3d_address_modes[0], D3D12_TEXTURE_ADDRESS_MODE_CLAMP, 0.0f, 1, D3D12_COMPARISON_FUNC_ALWAYS, { 0.0f, 0.0f, 0.0f, 0.0f }, 0.0f, 0.0f }; for (size_t i = 0; i < 2; i++) { for (size_t j = 0; j < 3; j++) { sampler_desc.Filter = d3d_sampler_filters[i]; sampler_desc.AddressU = d3d_address_modes[j]; sampler_desc.AddressV = d3d_address_modes[j]; D3D12_CPU_DESCRIPTOR_HANDLE cpu_handle{ texture_sampler_cpu_handle.ptr + (i * 3 + j) * D3D::sampler_descriptor_size }; D3D::device->CreateSampler(&sampler_desc, cpu_handle); } } // Create VS/GS if (!CreateCommonShaders()) return false; // Uniform buffer if (!CreateUniformBuffer()) return false; // Load the currently-configured shader (this may fail, and that's okay) ReloadShaders(); return true; }
bool GraphicsGL3::Init( const std::string & shader_path, unsigned resx, unsigned resy, unsigned antialiasing, bool shadows, int /*shadow_distance*/, int /*shadow_quality*/, int reflection_type, const std::string & static_reflectionmap_file, const std::string & /*static_ambientmap_file*/, int anisotropy, int texturesize, int /*lighting_quality*/, bool bloom, bool normalmaps, bool /*dynamicsky*/, const std::string & render_config, std::ostream & info_output, std::ostream & error_output) { rendercfg = render_config; shaderpath = shader_path; // first, see if we support the required gl version by attempting to initialize the GL wrapper gl.setInfoOutput(info_output); gl.setErrorOutput(error_output); if (!gl.initialize()) { error_output << "Initialization of GL3 failed." << std::endl; return false; } #ifdef _WIN32 // workaround for broken vao implementation Intel/Windows { const std::string vendor = (const char*)glGetString(GL_VENDOR); if (vendor == "Intel") vertex_buffer.BindElementBufferExplicitly(); } #endif // set up our graphical configuration option conditions bool fsaa = (antialiasing > 1); // add the conditions to the set #define ADDCONDITION(x) if (x) conditions.insert(#x) ADDCONDITION(bloom); ADDCONDITION(normalmaps); ADDCONDITION(fsaa); ADDCONDITION(shadows); #undef ADDCONDITION if (reflection_type >= 1) conditions.insert("reflections_low"); if (reflection_type >= 2) conditions.insert("reflections_high"); // load the reflection cubemap if (!static_reflectionmap_file.empty()) { TextureInfo t; t.cube = true; t.verticalcross = true; t.mipmap = true; t.anisotropy = anisotropy; t.maxsize = TextureInfo::Size(texturesize); static_reflection.Load(static_reflectionmap_file, t, error_output); } // this information is needed to initialize the renderer in ReloadShaders w = resx; h = resy; // initialize the renderer bool success = ReloadShaders(info_output, error_output); initialized = success; return success; }
static inline void HandleEvent(struct Game* game, ALLEGRO_EVENT* ev) { switch (ev->type) { case ALLEGRO_EVENT_DISPLAY_HALT_DRAWING: PauseExecution(game); al_acknowledge_drawing_halt(game->display); break; case ALLEGRO_EVENT_DISPLAY_RESUME_DRAWING: al_acknowledge_drawing_resume(game->display); ReloadGamestates(game); ResumeExecution(game); break; case ALLEGRO_EVENT_DISPLAY_SWITCH_OUT: if (game->config.autopause) { PrintConsole(game, "Focus lost, autopausing..."); PauseExecution(game); } break; case ALLEGRO_EVENT_DISPLAY_SWITCH_IN: if (game->config.autopause) { if (game->config.debug.enabled && game->config.debug.livereload) { ReloadCode(game); } ResumeExecution(game); } break; case ALLEGRO_EVENT_DISPLAY_RESIZE: PrintConsole(game, "Resize event: %dx%d", ev->display.width, ev->display.height); #ifdef LIBSUPERDERPY_IMGUI ImGui_ImplAllegro5_InvalidateDeviceObjects(); #endif al_acknowledge_resize(game->display); #ifdef LIBSUPERDERPY_IMGUI ImGui_ImplAllegro5_CreateDeviceObjects(); #endif // SetupViewport can be expensive, so don't do it when the resize event is already outdated or doesn't change anything if (((ev->display.width != game->_priv.window_width) || (ev->display.height != game->_priv.window_height)) && (ev->display.width == al_get_display_width(game->display)) && (ev->display.height == al_get_display_height(game->display))) { SetupViewport(game); } break; case ALLEGRO_EVENT_KEY_DOWN: #ifdef ALLEGRO_ANDROID if ((ev->keyboard.keycode == ALLEGRO_KEY_MENU) || (ev->keyboard.keycode == ALLEGRO_KEY_TILDE) || (ev->keyboard.keycode == ALLEGRO_KEY_BACKQUOTE)) { #else if ((ev->keyboard.keycode == ALLEGRO_KEY_TILDE) || (ev->keyboard.keycode == ALLEGRO_KEY_BACKQUOTE)) { #endif game->_priv.showconsole = !game->_priv.showconsole; if ((ev->keyboard.modifiers & ALLEGRO_KEYMOD_CTRL) && (game->config.debug.enabled)) { game->_priv.showtimeline = game->_priv.showconsole; } } if (ev->keyboard.keycode == ALLEGRO_KEY_F12) { DrawGamestates(game); int flags = al_get_new_bitmap_flags(); al_set_new_bitmap_flags(ALLEGRO_MEMORY_BITMAP); ALLEGRO_BITMAP* bitmap = al_create_bitmap(al_get_display_width(game->display), al_get_display_height(game->display)); al_set_new_bitmap_flags(flags); ALLEGRO_BITMAP* target = al_get_target_bitmap(); al_set_target_bitmap(bitmap); al_draw_bitmap(al_get_backbuffer(game->display), 0, 0, 0); al_set_target_bitmap(target); PrintConsole(game, "Screenshot made! Storing..."); struct ScreenshotThreadData* data = malloc(sizeof(struct ScreenshotThreadData)); data->game = game; data->bitmap = bitmap; #ifndef LIBSUPERDERPY_SINGLE_THREAD al_run_detached_thread(ScreenshotThread, data); #else ScreenshotThread(data); #endif } break; default: break; } #ifdef MAEMO5 // on Maemo we get mouse events instead of touch ones, so we'll rewrite them by ourselves if ((ev->type == ALLEGRO_EVENT_MOUSE_AXES) || (ev->type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN) || (ev->type == ALLEGRO_EVENT_MOUSE_BUTTON_UP)) { switch (ev->type) { case ALLEGRO_EVENT_MOUSE_BUTTON_DOWN: ev->type = ALLEGRO_EVENT_TOUCH_BEGIN; break; case ALLEGRO_EVENT_MOUSE_BUTTON_UP: ev->type = ALLEGRO_EVENT_TOUCH_END; break; case ALLEGRO_EVENT_MOUSE_AXES: ev->type = ALLEGRO_EVENT_TOUCH_MOVE; break; default: break; } ALLEGRO_DISPLAY* display = ev->mouse.display; float dx = ev->mouse.dx; float dy = ev->mouse.dy; float x = ev->mouse.x; float y = ev->mouse.y; double timestamp = ev->mouse.timestamp; ev->touch.display = display; ev->touch.dx = dx; ev->touch.dy = dy; ev->touch.id = 0; ev->touch.primary = true; ev->touch.source = (ALLEGRO_TOUCH_INPUT*)al_get_touch_input_event_source(); ev->touch.timestamp = timestamp; ev->touch.x = x; ev->touch.y = y; } #endif } static inline void HandleDebugEvent(struct Game* game, ALLEGRO_EVENT* ev) { switch (ev->type) { case ALLEGRO_EVENT_KEY_DOWN: switch (ev->keyboard.keycode) { case ALLEGRO_KEY_F1: if (!game->_priv.paused) { PauseExecution(game); } else { ReloadCode(game); ResumeExecution(game); } break; case ALLEGRO_KEY_F9: game->_priv.speed = ALLEGRO_BPS_TO_SECS(60.0); game->_priv.showconsole = true; PrintConsole(game, "DEBUG: Gameplay speed: 1.00x"); break; case ALLEGRO_KEY_F10: { double speed = ALLEGRO_BPS_TO_SECS(game->_priv.speed); // inverting speed -= 10; if (speed < 10) { speed = 10; } game->_priv.speed = ALLEGRO_BPS_TO_SECS(speed); game->_priv.showconsole = true; PrintConsole(game, "DEBUG: Gameplay speed: %.2fx", speed / 60.0); } break; case ALLEGRO_KEY_F11: { double speed = ALLEGRO_BPS_TO_SECS(game->_priv.speed); // inverting speed += 10; if (speed > 600) { speed = 600; } game->_priv.speed = ALLEGRO_BPS_TO_SECS(speed); game->_priv.showconsole = true; PrintConsole(game, "DEBUG: Gameplay speed: %.2fx", speed / 60.0); } break; } break; default: break; } } static inline bool MainloopEvents(struct Game* game) { do { ALLEGRO_EVENT ev; if (game->_priv.paused && !IS_EMSCRIPTEN) { // there's no frame flipping when paused, so avoid pointless busylooping al_wait_for_event(game->_priv.event_queue, &ev); } else if (!al_get_next_event(game->_priv.event_queue, &ev)) { break; } #ifdef LIBSUPERDERPY_IMGUI ImGui_ImplAllegro5_ProcessEvent(&ev); switch (ev.type) { case ALLEGRO_EVENT_KEY_CHAR: case ALLEGRO_EVENT_KEY_DOWN: case ALLEGRO_EVENT_KEY_UP: if (igGetIO()->WantCaptureKeyboard) { continue; } break; case ALLEGRO_EVENT_MOUSE_AXES: case ALLEGRO_EVENT_MOUSE_BUTTON_DOWN: case ALLEGRO_EVENT_MOUSE_BUTTON_UP: case ALLEGRO_EVENT_TOUCH_BEGIN: case ALLEGRO_EVENT_TOUCH_CANCEL: case ALLEGRO_EVENT_TOUCH_END: case ALLEGRO_EVENT_TOUCH_MOVE: if (igGetIO()->WantCaptureMouse) { continue; } break; default: break; } #endif if (game->_priv.params.handlers.event) { if ((*game->_priv.params.handlers.event)(game, &ev)) { continue; } } if (ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) { EventGamestates(game, &ev); return false; } HandleEvent(game, &ev); if (game->config.debug.enabled) { HandleDebugEvent(game, &ev); } EventGamestates(game, &ev); } while (!al_is_event_queue_empty(game->_priv.event_queue)); return true; } static inline bool MainloopTick(struct Game* game) { if (game->_priv.paused) { return true; } struct Gamestate* tmp = game->_priv.gamestates; #ifdef __EMSCRIPTEN__ emscripten_pause_main_loop(); #endif game->_priv.loading.to_load = 0; game->_priv.loading.loaded = 0; game->_priv.loading.lock = true; game->loading.progress = 0; // TODO: support gamestate dependences/ordering while (tmp) { if (tmp->pending_stop) { PrintConsole(game, "Stopping gamestate \"%s\"...", tmp->name); game->_priv.current_gamestate = tmp; (*tmp->api->stop)(game, tmp->data); tmp->started = false; tmp->pending_stop = false; PrintConsole(game, "Gamestate \"%s\" stopped successfully.", tmp->name); } if (tmp->pending_load) { game->_priv.loading.to_load++; } tmp = tmp->next; } tmp = game->_priv.gamestates; while (tmp) { if (tmp->pending_unload) { #ifdef __EMSCRIPTEN__ al_detach_voice(game->audio.v); #endif PrintConsole(game, "Unloading gamestate \"%s\"...", tmp->name); tmp->loaded = false; tmp->pending_unload = false; game->_priv.current_gamestate = tmp; (*tmp->api->unload)(game, tmp->data); PrintConsole(game, "Gamestate \"%s\" unloaded successfully.", tmp->name); #ifdef __EMSCRIPTEN__ al_attach_mixer_to_voice(game->audio.mixer, game->audio.v); #endif } if (tmp->pending_load) { #ifdef __EMSCRIPTEN__ al_detach_voice(game->audio.v); #endif if (tmp->show_loading && game->_priv.loading.gamestate->open) { (*game->_priv.loading.gamestate->api->start)(game, game->_priv.loading.gamestate->data); } if (!tmp->api) { if (!OpenGamestate(game, tmp, true) || !LinkGamestate(game, tmp)) { tmp->pending_load = false; tmp->pending_start = false; continue; } } if (tmp->api) { PrintConsole(game, "Loading gamestate \"%s\"...", tmp->name); game->_priv.loading.progress = 0; game->_priv.loading.current = tmp; game->_priv.current_gamestate = tmp; struct GamestateLoadingThreadData data = {.game = game, .gamestate = tmp, .bitmap_flags = al_get_new_bitmap_flags()}; game->_priv.loading.in_progress = true; double time = al_get_time(); game->_priv.loading.time = time; CalculateProgress(game); if (tmp->show_loading) { game->loading.shown = true; DrawGamestates(game); DrawConsole(game); al_flip_display(); #ifdef __EMSCRIPTEN__ emscripten_sleep(0); #endif } #ifndef LIBSUPERDERPY_SINGLE_THREAD al_run_detached_thread(GamestateLoadingThread, &data); while (game->_priv.loading.in_progress) { double delta = al_get_time() - game->_priv.loading.time; game->time += delta; // TODO: ability to disable passing time during loading game->_priv.loading.time += delta; if (game->loading.shown && game->_priv.loading.gamestate->open) { (*game->_priv.loading.gamestate->api->logic)(game, game->_priv.loading.gamestate->data, delta); } DrawGamestates(game); if (game->_priv.texture_sync) { al_convert_memory_bitmaps(); game->_priv.texture_sync = false; al_signal_cond(game->_priv.texture_sync_cond); game->_priv.loading.time = al_get_time(); // TODO: rethink time management during loading } DrawConsole(game); al_flip_display(); if (game->_priv.bsod_sync) { al_set_target_bitmap(NULL); game->_priv.bsod_sync = false; al_signal_cond(game->_priv.bsod_cond); } al_lock_mutex(game->_priv.bsod_mutex); while (game->_priv.in_bsod) { al_wait_cond(game->_priv.bsod_cond, game->_priv.bsod_mutex); } al_unlock_mutex(game->_priv.bsod_mutex); } #else GamestateLoadingThread(&data); DrawGamestates(game); DrawConsole(game); al_flip_display(); #ifdef __EMSCRIPTEN__ emscripten_sleep(0); #endif al_convert_memory_bitmaps(); #endif al_set_new_bitmap_flags(data.bitmap_flags); ReloadShaders(game, false); if (tmp->api->post_load) { PrintConsole(game, "[%s] Post-loading...", tmp->name); tmp->api->post_load(game, tmp->data); } game->_priv.loading.progress++; CalculateProgress(game); PrintConsole(game, "Gamestate \"%s\" loaded successfully in %f seconds.", tmp->name, al_get_time() - time); game->_priv.loading.loaded++; DrawGamestates(game); DrawConsole(game); al_flip_display(); #ifdef __EMSCRIPTEN__ emscripten_sleep(0); #endif tmp->loaded = true; tmp->pending_load = false; } if (tmp->show_loading && game->_priv.loading.gamestate->open) { (*game->_priv.loading.gamestate->api->stop)(game, game->_priv.loading.gamestate->data); } tmp->show_loading = true; game->loading.shown = false; game->_priv.timestamp = al_get_time(); #ifdef __EMSCRIPTEN__ al_attach_mixer_to_voice(game->audio.mixer, game->audio.v); #endif } tmp = tmp->next; }