// int main(int argc, char* argv[]) int GameMain() { // assert(argc || argv[0]); // Fixes the compiler complaining about unused values; GameState* game_state = CreateNewGameState("EnGen", 1600, 900); Renderer* renderer = game_state->renderer; game_state->active_scene = PushScene(&game_state->permanent_memory, MAX_GAME_ENTITES); TileMap* tilemap = game_state->active_scene->tilemap; for (int32 i = 0; i < 10; ++i) { Vec2 pos = { (float)i, 2.f }; AddTileToMap(tilemap, pos); } for (int32 i = 0; i < 10; ++i) { Vec2 pos = { 0, (float)i }; AddTileToMap(tilemap, pos); } for (int32 i = 0; i < 10; ++i) { Vec2 pos = { 10.f, (float)i }; AddTileToMap(tilemap, pos); } UIWindow* ui = PushStruct(&game_state->permanent_memory, UIWindow); SetTitle(ui, "Editor UI!"); SetSize(ui, { 0.1f, 0.3f, 0.2f, 0.2f }, 0.05f); UIWindow* ui2 = PushStruct(&game_state->permanent_memory, UIWindow); SetTitle(ui2, "Editor UI2!"); SetSize(ui2, { 0.2f, 0.3f, 0.2f, 0.2f }, 0.05f); InitializeDebugConsole(); #if 0 InitializeAudio(); char* test_sound_file = "C:\\projects\\imperial_march.wav"; bool test_sound_loaded = LoadWavFile(test_sound_file); if(test_sound_loaded) { printf("Loaded File\n"); } PauseAudio(false); #endif Camera default_camera = {}; // maybe put this in game_state? default_camera.position = vec2(0, 0); default_camera.viewport_size.x = 16; default_camera.viewport_size.y = 9; uint32 frame_count = 0; uint32 fps = 0; double last_fps_time = 0; bool running = true; while (running) { ProfileBeginFrame(); ProfileBeginSection(Profile_Frame); ProfileBeginSection(Profile_Input); Platform_RunMessageLoop(game_state->input); Camera* draw_camera = game_state->active_camera ? game_state->active_camera : &default_camera; game_state->window.resolution = Platform_GetResolution(); UpdateMouseWorldPosition(game_state->input, game_state->window.resolution, draw_camera->viewport_size, draw_camera->position); ProfileEndSection(Profile_Input); Vec2i mouse_pos = MousePosition(game_state->input); //DebugPrintf("Mouse World Position: (%.2f, %.2f)", mouse_pos.x, mouse_pos.y); DebugPrintf("Mouse World Position: (%d, %d)", mouse_pos.x, mouse_pos.y); DebugPrintf("Main Camera Position: (%.2f, %.2f)", default_camera.position.x, default_camera.position.y); DebugPrintf("Key Pressed: %s", IsDown(game_state->input, KeyCode_a) ? "TRUE" : "FALSE"); if (OnDown(game_state->input, KeyCode_ESCAPE)) { running = false; break; } #if 0 // TODO: Platform layer if (OnDown(game_state->input, KeyCode_z)) { ForceColorClear(); SwapBuffer(game_state); //WindowSetScreenMode(&game_state->window, ScreenMode_Windowed); } else if (OnDown(game_state->input, KeyCode_c)) { ForceColorClear(); SwapBuffer(game_state); //WindowSetScreenMode(&game_state->window, ScreenMode_Borderless); } #endif static bool draw_debug = true; if (OnDown(game_state->input, KeyCode_BACKQUOTE)) { draw_debug = !draw_debug; } Renderer* debug_renderer = draw_debug ? renderer : 0; TimeBeginFrame(game_state); // Update the scene first, pushing draw calls if necessary. // Then call begin_frame which builds matrices and clears buffers; float current_time = CurrentTime(game_state); if (current_time - last_fps_time > 1.0f) { last_fps_time = current_time; fps = frame_count; frame_count = 0; } frame_count++; DebugPrintf("FPS: \t\t%d \tFrames: \t%d", fps, FrameCount(game_state)); DebugControlCamera(game_state, &default_camera); // TODO(cgenova): separate update and render calls so that things can be set up when rendering begins; BeginFrame(renderer, &game_state->window); ProfileBeginSection(Profile_SceneUpdate); DebugPrintPushColor(vec4(1.0f, 0, 0, 1.0f)); DebugPrintf("Active scene entity usage: (%d / %d)", game_state->active_scene->active_entities, MAX_GAME_ENTITES); DebugPrintPopColor(); UpdateSceneEntities(game_state, game_state->active_scene); DrawSceneEntities(game_state->active_scene, renderer); ProfileEndSection(Profile_SceneUpdate); #if 1 // Spaghetti test const size_t num_verts = 200; static SimpleVertex v[num_verts]; static bool initialized = false; if (!initialized) { initialized = true; for (uint32 i = 0; i < num_verts; ++i) { SimpleVertex verts = {}; verts.position = vec2((float)(i / 50.f) - 2.f, (float)i); verts.color = vec4(1, 1, 0, 1.f); v[i] = verts; } } else { for (uint32 i = 0; i < num_verts; ++i) { v[i].position.y = sin(CurrentTime(game_state) + i / (PI * 20)); } } PrimitiveDrawParams spaghetti_params = {}; spaghetti_params.line_draw_flags |= PrimitiveDraw_Smooth; // spaghetti_params.line_draw_flags |= Draw_ScreenSpace; spaghetti_params.line_width = 0; DrawLine(renderer, v, num_verts, spaghetti_params); #endif DrawTileMap(game_state, game_state->active_scene->tilemap); UpdateUIWindow(game_state, ui); UpdateUIWindow(game_state, ui2); RenderDrawBuffer(renderer, draw_camera); ProfileEndSection(Profile_Frame); ProfileEndFrame(debug_renderer, TARGET_FPS); DebugDrawConsole(debug_renderer); // NOTE: // For drawing Debug info, the profiling in this section will be discarded, // but it is only drawing text and the debug graph. RenderDrawBuffer(renderer, draw_camera); SwapBuffer(game_state); // TODO(cgenova): High granularity sleep function! ResetArena(&game_state->temporary_memory); }// End main loop return 1; }
void Asteroids::Render(float frameTime, const OrbitCamera& camera, const Settings& settings) { ProfileBeginFrame(0); ProfileBeginRender(); // Frame data ProfileBeginSimUpdate(); mAsteroids->Update(frameTime, camera.Eye(), settings); auto staticAsteroidData = mAsteroids->StaticData(); auto dynamicAsteroidData = mAsteroids->DynamicData(); ProfileEndSimUpdate(); // Clear the render target float clearcol[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; mDeviceCtxt->ClearRenderTargetView(mRenderTargetView, clearcol); mDeviceCtxt->ClearDepthStencilView(mDepthStencilView, D3D11_CLEAR_DEPTH, 0.0f, 0); { ID3D11Buffer* ia_buffers[] = { mVertexBuffer }; UINT ia_strides[] = { sizeof(Vertex) }; UINT ia_offsets[] = { 0 }; mDeviceCtxt->IASetInputLayout(mInputLayout); mDeviceCtxt->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); mDeviceCtxt->IASetVertexBuffers(0, 1, ia_buffers, ia_strides, ia_offsets); mDeviceCtxt->IASetIndexBuffer(mIndexBuffer, DXGI_FORMAT_R16_UINT, 0); } mDeviceCtxt->VSSetShader(mVertexShader, nullptr, 0); mDeviceCtxt->VSSetConstantBuffers(0, 1, &mDrawConstantBuffer); mDeviceCtxt->RSSetViewports(1, &mViewPort); mDeviceCtxt->RSSetScissorRects(1, &mScissorRect); mDeviceCtxt->PSSetShader(mPixelShader, nullptr, 0); mDeviceCtxt->PSSetSamplers(0, 1, &mSamplerState); mDeviceCtxt->OMSetRenderTargets(1, &mRenderTargetView, mDepthStencilView); mDeviceCtxt->OMSetDepthStencilState(mDepthStencilState, 0); mDeviceCtxt->OMSetBlendState(mBlendState, nullptr, 0xFFFFFFFF); ProfileBeginRenderSubset(); auto viewProjection = camera.ViewProjection(); for (UINT drawIdx = 0; drawIdx < NUM_ASTEROIDS; ++drawIdx) { auto staticData = &staticAsteroidData[drawIdx]; auto dynamicData = &dynamicAsteroidData[drawIdx]; D3D11_MAPPED_SUBRESOURCE mapped = {}; ThrowIfFailed(mDeviceCtxt->Map(mDrawConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped)); auto drawConstants = (DrawConstantBuffer*) mapped.pData; XMStoreFloat4x4(&drawConstants->mWorld, dynamicData->world); XMStoreFloat4x4(&drawConstants->mViewProjection, viewProjection); drawConstants->mSurfaceColor = staticData->surfaceColor; drawConstants->mDeepColor = staticData->deepColor; mDeviceCtxt->Unmap(mDrawConstantBuffer, 0); mDeviceCtxt->PSSetShaderResources(0, 1, &mTextureSRVs[staticData->textureIndex]); mDeviceCtxt->DrawIndexedInstanced(dynamicData->indexCount, 1, dynamicData->indexStart, staticData->vertexStart, 0); } ProfileEndRenderSubset(); // Draw skybox { D3D11_MAPPED_SUBRESOURCE mapped = {}; ThrowIfFailed(mDeviceCtxt->Map(mSkyboxConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped)); auto skyboxConstants = (SkyboxConstantBuffer*) mapped.pData; XMStoreFloat4x4(&skyboxConstants->mViewProjection, camera.ViewProjection()); mDeviceCtxt->Unmap(mSkyboxConstantBuffer, 0); ID3D11Buffer* ia_buffers[] = { mSkyboxVertexBuffer }; UINT ia_strides[] = { sizeof(SkyboxVertex) }; UINT ia_offsets[] = { 0 }; mDeviceCtxt->IASetInputLayout(mSkyboxInputLayout); mDeviceCtxt->IASetVertexBuffers(0, 1, ia_buffers, ia_strides, ia_offsets); mDeviceCtxt->VSSetShader(mSkyboxVertexShader, nullptr, 0); mDeviceCtxt->VSSetConstantBuffers(0, 1, &mSkyboxConstantBuffer); mDeviceCtxt->PSSetShader(mSkyboxPixelShader, nullptr, 0); mDeviceCtxt->PSSetSamplers(0, 1, &mSamplerState); mDeviceCtxt->PSSetShaderResources(0, 1, &mSkyboxSRV); mDeviceCtxt->Draw(6*6, 0); } mDeviceCtxt->OMSetRenderTargets(1, &mRenderTargetView, 0); // No more depth buffer // Draw sprites and fonts { // Fill in vertices (TODO: could move this vector to be a member - not a big deal) std::vector<UINT> controlVertices; controlVertices.reserve(mGUI->size()); { D3D11_MAPPED_SUBRESOURCE mapped = {}; ThrowIfFailed(mDeviceCtxt->Map(mSpriteVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped)); auto vertexBase = (SpriteVertex*)mapped.pData; auto vertexEnd = vertexBase; for (size_t i = 0; i < mGUI->size(); ++i) { auto control = (*mGUI)[i]; controlVertices.push_back((UINT)(control->Draw(mViewPort.Width, mViewPort.Height, vertexEnd) - vertexEnd)); vertexEnd += controlVertices.back(); } mDeviceCtxt->Unmap(mSpriteVertexBuffer, 0); } ID3D11Buffer* ia_buffers[] = { mSpriteVertexBuffer }; UINT ia_strides[] = { sizeof(SpriteVertex) }; UINT ia_offsets[] = { 0 }; mDeviceCtxt->IASetInputLayout(mSpriteInputLayout); mDeviceCtxt->IASetVertexBuffers(0, 1, ia_buffers, ia_strides, ia_offsets); mDeviceCtxt->VSSetShader(mSpriteVertexShader, 0, 0); mDeviceCtxt->OMSetBlendState(mSpriteBlendState, nullptr, 0xFFFFFFFF); // Draw UINT vertexStart = 0; for (size_t i = 0; i < mGUI->size(); ++i) { auto control = (*mGUI)[i]; if (control->Visible()) { if (control->TextureFile().length() == 0) { // Font mDeviceCtxt->PSSetShader(mFontPixelShader, 0, 0); mDeviceCtxt->PSSetShaderResources(0, 1, &mFontTextureSRV); } else { // Sprite auto textureSRV = mSpriteTextures[control->TextureFile()]; mDeviceCtxt->PSSetShader(mSpritePixelShader, 0, 0); mDeviceCtxt->PSSetShaderResources(0, 1, &textureSRV); } mDeviceCtxt->Draw(controlVertices[i], vertexStart); } vertexStart += controlVertices[i]; } } ProfileEndRender(); ProfileBeginPresent(); mSwapChain->Present(settings.vsync ? 1 : 0, 0); ProfileEndPresent(); ProfileEndFrame(); }