void renderUpdate(void) { glMatrixMode(GL_PROJECTION); glLoadIdentity(); glViewport(0, 0, renderEnv.viewWidth, renderEnv.viewHeight); float fieldOfView = renderEnv.scene.camera.fieldOfView / renderEnv.scene.camera.zoom; float aspectRatio = renderEnv.viewWidth / renderEnv.viewHeight; float nearDist = renderEnv.scene.camera.nearDist; float farDist = renderEnv.scene.camera.farDist; gluPerspective(fieldOfView, aspectRatio, nearDist, farDist); fieldOfView *= M_PI / 180.0f; renderEnv.scene.camera.nearHeight = 2.0f * tan(fieldOfView / 2.0f) * nearDist; renderEnv.scene.camera.nearWidth = renderEnv.scene.camera.nearHeight * aspectRatio; renderEnv.scene.camera.farHeight = 2.0f * tan(fieldOfView / 2.0f) * farDist; renderEnv.scene.camera.farWidth = renderEnv.scene.camera.farHeight * aspectRatio; cameraUpdate(&renderEnv.scene.camera); }
int _main_(int /*_argc*/, char** /*_argv*/) { uint32_t width = 1280; uint32_t height = 720; uint32_t debug = BGFX_DEBUG_TEXT; uint32_t reset = BGFX_RESET_VSYNC; bgfx::init(); bgfx::reset(width, height, reset); // Enable debug text. bgfx::setDebug(debug); // Set clear color palette for index 0 bgfx::setClearColor(0, UINT32_C(0x00000000) ); // Set clear color palette for index 1 bgfx::setClearColor(1, UINT32_C(0x303030ff) ); // Set geometry pass view clear state. bgfx::setViewClear(RENDER_PASS_GEOMETRY_ID , BGFX_CLEAR_COLOR|BGFX_CLEAR_DEPTH , 1.0f , 0 , 1 ); // Set light pass view clear state. bgfx::setViewClear(RENDER_PASS_LIGHT_ID , BGFX_CLEAR_COLOR|BGFX_CLEAR_DEPTH , 1.0f , 0 , 0 ); // Create vertex stream declaration. PosNormalTangentTexcoordVertex::init(); PosTexCoord0Vertex::init(); DebugVertex::init(); calcTangents(s_cubeVertices , BX_COUNTOF(s_cubeVertices) , PosNormalTangentTexcoordVertex::ms_decl , s_cubeIndices , BX_COUNTOF(s_cubeIndices) ); // Create static vertex buffer. bgfx::VertexBufferHandle vbh = bgfx::createVertexBuffer( bgfx::makeRef(s_cubeVertices, sizeof(s_cubeVertices) ) , PosNormalTangentTexcoordVertex::ms_decl ); // Create static index buffer. bgfx::IndexBufferHandle ibh = bgfx::createIndexBuffer(bgfx::makeRef(s_cubeIndices, sizeof(s_cubeIndices) ) ); // Create texture sampler uniforms. bgfx::UniformHandle s_texColor = bgfx::createUniform("s_texColor", bgfx::UniformType::Uniform1iv); bgfx::UniformHandle s_texNormal = bgfx::createUniform("s_texNormal", bgfx::UniformType::Uniform1iv); bgfx::UniformHandle s_albedo = bgfx::createUniform("s_albedo", bgfx::UniformType::Uniform1iv); bgfx::UniformHandle s_normal = bgfx::createUniform("s_normal", bgfx::UniformType::Uniform1iv); bgfx::UniformHandle s_depth = bgfx::createUniform("s_depth", bgfx::UniformType::Uniform1iv); bgfx::UniformHandle s_light = bgfx::createUniform("s_light", bgfx::UniformType::Uniform1iv); bgfx::UniformHandle u_mtx = bgfx::createUniform("u_mtx", bgfx::UniformType::Uniform4x4fv); bgfx::UniformHandle u_lightPosRadius = bgfx::createUniform("u_lightPosRadius", bgfx::UniformType::Uniform4fv); bgfx::UniformHandle u_lightRgbInnerR = bgfx::createUniform("u_lightRgbInnerR", bgfx::UniformType::Uniform4fv); // Create program from shaders. bgfx::ProgramHandle geomProgram = loadProgram("vs_deferred_geom", "fs_deferred_geom"); bgfx::ProgramHandle lightProgram = loadProgram("vs_deferred_light", "fs_deferred_light"); bgfx::ProgramHandle combineProgram = loadProgram("vs_deferred_combine", "fs_deferred_combine"); bgfx::ProgramHandle debugProgram = loadProgram("vs_deferred_debug", "fs_deferred_debug"); bgfx::ProgramHandle lineProgram = loadProgram("vs_deferred_debug_line", "fs_deferred_debug_line"); // Load diffuse texture. bgfx::TextureHandle textureColor = loadTexture("fieldstone-rgba.dds"); // Load normal texture. bgfx::TextureHandle textureNormal = loadTexture("fieldstone-n.dds"); bgfx::TextureHandle gbufferTex[3] = { BGFX_INVALID_HANDLE, BGFX_INVALID_HANDLE, BGFX_INVALID_HANDLE }; bgfx::FrameBufferHandle gbuffer = BGFX_INVALID_HANDLE; bgfx::FrameBufferHandle lightBuffer = BGFX_INVALID_HANDLE; // Imgui. imguiCreate(); const int64_t timeOffset = bx::getHPCounter(); const bgfx::RendererType::Enum renderer = bgfx::getRendererType(); const float texelHalf = bgfx::RendererType::Direct3D9 == renderer ? 0.5f : 0.0f; s_originBottomLeft = bgfx::RendererType::OpenGL == renderer || bgfx::RendererType::OpenGLES == renderer; // Get renderer capabilities info. const bgfx::Caps* caps = bgfx::getCaps(); uint32_t oldWidth = 0; uint32_t oldHeight = 0; uint32_t oldReset = reset; int32_t scrollArea = 0; int32_t numLights = 512; float lightAnimationSpeed = 0.3f; bool animateMesh = true; bool showScissorRects = false; bool showGBuffer = true; float view[16]; float initialPos[3] = { 0.0f, 0.0f, -15.0f }; cameraCreate(); cameraSetPosition(initialPos); cameraSetVerticalAngle(0.0f); cameraGetViewMtx(view); entry::MouseState mouseState; while (!entry::processEvents(width, height, debug, reset, &mouseState) ) { int64_t now = bx::getHPCounter(); static int64_t last = now; const int64_t frameTime = now - last; last = now; const double freq = double(bx::getHPFrequency() ); const double toMs = 1000.0/freq; const float deltaTime = float(frameTime/freq); float time = (float)( (now-timeOffset)/freq); // Use debug font to print information about this example. bgfx::dbgTextClear(); bgfx::dbgTextPrintf(0, 1, 0x4f, "bgfx/examples/21-deferred"); bgfx::dbgTextPrintf(0, 2, 0x6f, "Description: MRT rendering and deferred shading."); bgfx::dbgTextPrintf(0, 3, 0x0f, "Frame: % 7.3f[ms]", double(frameTime)*toMs); if (2 > caps->maxFBAttachments) { // When multiple render targets (MRT) is not supported by GPU, // implement alternative code path that doesn't use MRT. bool blink = uint32_t(time*3.0f)&1; bgfx::dbgTextPrintf(0, 5, blink ? 0x1f : 0x01, " MRT not supported by GPU. "); // Set view 0 default viewport. bgfx::setViewRect(0, 0, 0, width, height); // This dummy draw call is here to make sure that view 0 is cleared // if no other draw calls are submitted to view 0. bgfx::submit(0); } else { if (oldWidth != width || oldHeight != height || oldReset != reset || !bgfx::isValid(gbuffer) ) { // Recreate variable size render targets when resolution changes. oldWidth = width; oldHeight = height; oldReset = reset; if (bgfx::isValid(gbuffer) ) { bgfx::destroyFrameBuffer(gbuffer); } const uint32_t samplerFlags = 0 | BGFX_TEXTURE_RT | BGFX_TEXTURE_MIN_POINT | BGFX_TEXTURE_MAG_POINT | BGFX_TEXTURE_MIP_POINT | BGFX_TEXTURE_U_CLAMP | BGFX_TEXTURE_V_CLAMP ; gbufferTex[0] = bgfx::createTexture2D(width, height, 1, bgfx::TextureFormat::BGRA8, samplerFlags); gbufferTex[1] = bgfx::createTexture2D(width, height, 1, bgfx::TextureFormat::BGRA8, samplerFlags); gbufferTex[2] = bgfx::createTexture2D(width, height, 1, bgfx::TextureFormat::D24, samplerFlags); gbuffer = bgfx::createFrameBuffer(BX_COUNTOF(gbufferTex), gbufferTex, true); if (bgfx::isValid(lightBuffer) ) { bgfx::destroyFrameBuffer(lightBuffer); } lightBuffer = bgfx::createFrameBuffer(width, height, bgfx::TextureFormat::BGRA8, samplerFlags); } imguiBeginFrame(mouseState.m_mx , mouseState.m_my , (mouseState.m_buttons[entry::MouseButton::Left ] ? IMGUI_MBUT_LEFT : 0) | (mouseState.m_buttons[entry::MouseButton::Right ] ? IMGUI_MBUT_RIGHT : 0) , 0 , width , height ); imguiBeginScrollArea("Settings", width - width / 5 - 10, 10, width / 5, height / 3, &scrollArea); imguiSeparatorLine(); imguiSlider("Num lights", numLights, 1, 2048); if (imguiCheck("Show G-Buffer.", showGBuffer) ) { showGBuffer = !showGBuffer; } if (imguiCheck("Show light scissor.", showScissorRects) ) { showScissorRects = !showScissorRects; } if (imguiCheck("Animate mesh.", animateMesh) ) { animateMesh = !animateMesh; } imguiSlider("Lights animation speed", lightAnimationSpeed, 0.0f, 0.4f, 0.01f); imguiEndScrollArea(); imguiEndFrame(); // Update camera. cameraUpdate(deltaTime, mouseState); cameraGetViewMtx(view); // Setup views float vp[16]; float invMvp[16]; { bgfx::setViewRect(RENDER_PASS_GEOMETRY_ID, 0, 0, width, height); bgfx::setViewRect(RENDER_PASS_LIGHT_ID, 0, 0, width, height); bgfx::setViewRect(RENDER_PASS_COMBINE_ID, 0, 0, width, height); bgfx::setViewRect(RENDER_PASS_DEBUG_LIGHTS_ID, 0, 0, width, height); bgfx::setViewRect(RENDER_PASS_DEBUG_GBUFFER_ID, 0, 0, width, height); bgfx::setViewFrameBuffer(RENDER_PASS_LIGHT_ID, lightBuffer); float proj[16]; mtxProj(proj, 60.0f, float(width)/float(height), 0.1f, 100.0f); bgfx::setViewFrameBuffer(RENDER_PASS_GEOMETRY_ID, gbuffer); bgfx::setViewTransform(RENDER_PASS_GEOMETRY_ID, view, proj); bx::mtxMul(vp, view, proj); bx::mtxInverse(invMvp, vp); bx::mtxOrtho(proj, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 100.0f); bgfx::setViewTransform(RENDER_PASS_LIGHT_ID, NULL, proj); bgfx::setViewTransform(RENDER_PASS_COMBINE_ID, NULL, proj); const float aspectRatio = float(height)/float(width); const float size = 10.0f; bx::mtxOrtho(proj, -size, size, size*aspectRatio, -size*aspectRatio, 0.0f, 1000.0f); bgfx::setViewTransform(RENDER_PASS_DEBUG_GBUFFER_ID, NULL, proj); bx::mtxOrtho(proj, 0.0f, (float)width, 0.0f, (float)height, 0.0f, 1000.0f); bgfx::setViewTransform(RENDER_PASS_DEBUG_LIGHTS_ID, NULL, proj); } const uint32_t dim = 11; const float offset = (float(dim-1) * 3.0f) * 0.5f; // Draw into geometry pass. for (uint32_t yy = 0; yy < dim; ++yy) { for (uint32_t xx = 0; xx < dim; ++xx) { float mtx[16]; if (animateMesh) { bx::mtxRotateXY(mtx, time*1.023f + xx*0.21f, time*0.03f + yy*0.37f); } else { bx::mtxIdentity(mtx); } mtx[12] = -offset + float(xx)*3.0f; mtx[13] = -offset + float(yy)*3.0f; mtx[14] = 0.0f; // Set transform for draw call. bgfx::setTransform(mtx); // Set vertex and fragment shaders. bgfx::setProgram(geomProgram); // Set vertex and index buffer. bgfx::setVertexBuffer(vbh); bgfx::setIndexBuffer(ibh); // Bind textures. bgfx::setTexture(0, s_texColor, textureColor); bgfx::setTexture(1, s_texNormal, textureNormal); // Set render states. bgfx::setState(0 | BGFX_STATE_RGB_WRITE | BGFX_STATE_ALPHA_WRITE | BGFX_STATE_DEPTH_WRITE | BGFX_STATE_DEPTH_TEST_LESS | BGFX_STATE_MSAA ); // Submit primitive for rendering to view 0. bgfx::submit(RENDER_PASS_GEOMETRY_ID); } } // Draw lights into light buffer. for (int32_t light = 0; light < numLights; ++light) { Sphere lightPosRadius; float lightTime = time * lightAnimationSpeed * (sinf(light/float(numLights) * bx::piHalf ) * 0.5f + 0.5f); lightPosRadius.m_center[0] = sinf( ( (lightTime + light*0.47f) + bx::piHalf*1.37f ) )*offset; lightPosRadius.m_center[1] = cosf( ( (lightTime + light*0.69f) + bx::piHalf*1.49f ) )*offset; lightPosRadius.m_center[2] = sinf( ( (lightTime + light*0.37f) + bx::piHalf*1.57f ) )*2.0f; lightPosRadius.m_radius = 2.0f; Aabb aabb; sphereToAabb(aabb, lightPosRadius); float box[8][3] = { { aabb.m_min[0], aabb.m_min[1], aabb.m_min[2] }, { aabb.m_min[0], aabb.m_min[1], aabb.m_max[2] }, { aabb.m_min[0], aabb.m_max[1], aabb.m_min[2] }, { aabb.m_min[0], aabb.m_max[1], aabb.m_max[2] }, { aabb.m_max[0], aabb.m_min[1], aabb.m_min[2] }, { aabb.m_max[0], aabb.m_min[1], aabb.m_max[2] }, { aabb.m_max[0], aabb.m_max[1], aabb.m_min[2] }, { aabb.m_max[0], aabb.m_max[1], aabb.m_max[2] }, }; float xyz[3]; bx::vec3MulMtxH(xyz, box[0], vp); float minx = xyz[0]; float miny = xyz[1]; float maxx = xyz[0]; float maxy = xyz[1]; float maxz = xyz[2]; for (uint32_t ii = 1; ii < 8; ++ii) { bx::vec3MulMtxH(xyz, box[ii], vp); minx = bx::fmin(minx, xyz[0]); miny = bx::fmin(miny, xyz[1]); maxx = bx::fmax(maxx, xyz[0]); maxy = bx::fmax(maxy, xyz[1]); maxz = bx::fmax(maxz, xyz[2]); } // Cull light if it's fully behind camera. if (maxz >= 0.0f) { float x0 = bx::fclamp( (minx * 0.5f + 0.5f) * width, 0.0f, (float)width); float y0 = bx::fclamp( (miny * 0.5f + 0.5f) * height, 0.0f, (float)height); float x1 = bx::fclamp( (maxx * 0.5f + 0.5f) * width, 0.0f, (float)width); float y1 = bx::fclamp( (maxy * 0.5f + 0.5f) * height, 0.0f, (float)height); if (showScissorRects) { bgfx::TransientVertexBuffer tvb; bgfx::TransientIndexBuffer tib; if (bgfx::allocTransientBuffers(&tvb, DebugVertex::ms_decl, 4, &tib, 8) ) { uint32_t abgr = 0x8000ff00; DebugVertex* vertex = (DebugVertex*)tvb.data; vertex->m_x = x0; vertex->m_y = y0; vertex->m_z = 0.0f; vertex->m_abgr = abgr; ++vertex; vertex->m_x = x1; vertex->m_y = y0; vertex->m_z = 0.0f; vertex->m_abgr = abgr; ++vertex; vertex->m_x = x1; vertex->m_y = y1; vertex->m_z = 0.0f; vertex->m_abgr = abgr; ++vertex; vertex->m_x = x0; vertex->m_y = y1; vertex->m_z = 0.0f; vertex->m_abgr = abgr; uint16_t* indices = (uint16_t*)tib.data; *indices++ = 0; *indices++ = 1; *indices++ = 1; *indices++ = 2; *indices++ = 2; *indices++ = 3; *indices++ = 3; *indices++ = 0; bgfx::setProgram(lineProgram); bgfx::setVertexBuffer(&tvb); bgfx::setIndexBuffer(&tib); bgfx::setState(0 | BGFX_STATE_RGB_WRITE | BGFX_STATE_PT_LINES | BGFX_STATE_BLEND_ALPHA ); bgfx::submit(RENDER_PASS_DEBUG_LIGHTS_ID); } } uint8_t val = light&7; float lightRgbInnerR[4] = { val & 0x1 ? 1.0f : 0.25f, val & 0x2 ? 1.0f : 0.25f, val & 0x4 ? 1.0f : 0.25f, 0.8f, }; // Draw light. bgfx::setUniform(u_lightPosRadius, &lightPosRadius); bgfx::setUniform(u_lightRgbInnerR, lightRgbInnerR); bgfx::setUniform(u_mtx, invMvp); const uint16_t scissorHeight = uint16_t(y1-y0); bgfx::setScissor(uint16_t(x0), height-scissorHeight-uint16_t(y0), uint16_t(x1-x0), scissorHeight); bgfx::setTexture(0, s_normal, gbuffer, 1); bgfx::setTexture(1, s_depth, gbuffer, 2); bgfx::setProgram(lightProgram); bgfx::setState(0 | BGFX_STATE_RGB_WRITE | BGFX_STATE_ALPHA_WRITE | BGFX_STATE_BLEND_ADD ); screenSpaceQuad( (float)width, (float)height, texelHalf, s_originBottomLeft); bgfx::submit(RENDER_PASS_LIGHT_ID); } } // Combine color and light buffers. bgfx::setTexture(0, s_albedo, gbuffer, 0); bgfx::setTexture(1, s_light, lightBuffer, 0); bgfx::setProgram(combineProgram); bgfx::setState(0 | BGFX_STATE_RGB_WRITE | BGFX_STATE_ALPHA_WRITE ); screenSpaceQuad( (float)width, (float)height, texelHalf, s_originBottomLeft); bgfx::submit(RENDER_PASS_COMBINE_ID); if (showGBuffer) { const float aspectRatio = float(width)/float(height); // Draw debug GBuffer. for (uint32_t ii = 0; ii < BX_COUNTOF(gbufferTex); ++ii) { float mtx[16]; bx::mtxSRT(mtx , aspectRatio, 1.0f, 1.0f , 0.0f, 0.0f, 0.0f , -7.9f - BX_COUNTOF(gbufferTex)*0.1f*0.5f + ii*2.1f*aspectRatio, 4.0f, 0.0f ); bgfx::setTransform(mtx); bgfx::setProgram(debugProgram); bgfx::setVertexBuffer(vbh); bgfx::setIndexBuffer(ibh, 0, 6); bgfx::setTexture(0, s_texColor, gbufferTex[ii]); bgfx::setState(BGFX_STATE_RGB_WRITE); bgfx::submit(RENDER_PASS_DEBUG_GBUFFER_ID); } } } // Advance to next frame. Rendering thread will be kicked to // process submitted rendering primitives. bgfx::frame(); } // Cleanup. cameraDestroy(); imguiDestroy(); if (bgfx::isValid(gbuffer) ) { bgfx::destroyFrameBuffer(gbuffer); bgfx::destroyFrameBuffer(lightBuffer); } bgfx::destroyIndexBuffer(ibh); bgfx::destroyVertexBuffer(vbh); bgfx::destroyProgram(geomProgram); bgfx::destroyProgram(lightProgram); bgfx::destroyProgram(combineProgram); bgfx::destroyProgram(debugProgram); bgfx::destroyProgram(lineProgram); bgfx::destroyTexture(textureColor); bgfx::destroyTexture(textureNormal); bgfx::destroyUniform(s_texColor); bgfx::destroyUniform(s_texNormal); bgfx::destroyUniform(s_albedo); bgfx::destroyUniform(s_normal); bgfx::destroyUniform(s_depth); bgfx::destroyUniform(s_light); bgfx::destroyUniform(u_lightPosRadius); bgfx::destroyUniform(u_lightRgbInnerR); bgfx::destroyUniform(u_mtx); // Shutdown bgfx. bgfx::shutdown(); return 0; }
//-------------------------------------------------------------- void testApp::update(){ cameraUpdate(); /* squirrelModel.setRotation(1, 270 + ofGetElapsedTimef() * 60, 0, 0, 1); */ }
int MonopolyGame::run() { // Start the timer's so that revisions are properly drawn. al_start_timer( m_alTimer ); al_start_timer( m_alFrameTimer ); // Perform the first display update. al_flip_display(); // Zero the FPS counters. m_oldFps = 0.0; m_currFps = 0.0; m_framesDone = 0.0; al_flush_event_queue( m_alEventQueue ); // Run until the exit flag is thrown. while( !m_exitGame ) { ALLEGRO_EVENT alEvent; al_wait_for_event( m_alEventQueue, &alEvent ); al_get_keyboard_state( &m_alKeyState ); // If the user clicks the window's 'close (X)' button. if( alEvent.type == ALLEGRO_EVENT_DISPLAY_CLOSE ) { // Exit the game. m_exitGame = true; } // Or if the user hits the 'ESC' key. else if( al_key_down( &m_alKeyState, ALLEGRO_KEY_ESCAPE ) ) { // Exit the game. m_exitGame = true; } // Process any timed events that have been triggered. else if( alEvent.type == ALLEGRO_EVENT_TIMER ) { if( alEvent.timer.source == m_alTimer ) { // This is the hook into the turn logic. handleTurn(); // We will update the camera position only if the timer has been triggered. cameraUpdate( m_alCamera.cameraPosition, // X and Y location of the camera. m_playerList[m_playersTurn].get_x(), // Player's x position. m_playerList[m_playersTurn].get_y(), // Player's y position. 32, 32 ); // Width and height of player's image. } else if( alEvent.timer.source == m_alFrameTimer ) { for( int pCounter = 0; pCounter < NUM_PLAYERS; pCounter++ ) { // If this player has more than '0' money. if( m_playerList[pCounter].get_money() > 0 ) { // For each player, update the image we will display this frame. m_playerList[pCounter].animationLogic(); } } } // Do some camera transform magic. al_identity_transform( &m_alCamera.alCameraTransform ); // Adjust the camera so that it is centered over our player's position. al_translate_transform( &m_alCamera.alCameraTransform, -m_alCamera.cameraPosition[Positions::X_POS], -m_alCamera.cameraPosition[Positions::Y_POS] ); // Push the camera's changes. al_use_transform( &m_alCamera.alCameraTransform ); // Since the screen has been updated, we want to flag the screen to be redrawn. m_redrawScreen = true; } //if( m_redrawScreen ) { if( m_redrawScreen && al_is_event_queue_empty( m_alEventQueue ) ) { m_redrawScreen = false; m_framesDone++; draw(); } calcFramerate(); } return 0; }
void CG_DemosDrawActiveFrame( int serverTime, stereoFrame_t stereoView ) { int deltaTime; qboolean hadSkip; qboolean captureFrame; float captureFPS; float frameSpeed; int blurTotal, blurIndex; float blurFraction; float stereoSep = CG_Cvar_Get( "r_stereoSeparation" ); int inwater, entityNum; if (!demo.initDone) { if ( !cg.snap ) { demoProcessSnapShots( qtrue ); } if ( !cg.snap ) { CG_Error( "No Initial demo snapshot found" ); } demoPlaybackInit(); } cg.demoPlayback = 2; // update cvars CG_UpdateCvars(); // if we are only updating the screen as a loading // pacifier, don't even try to read snapshots if ( cg.loading ) { CG_DrawInformation(); return; } captureFrame = demo.capture.active && !demo.play.paused; if ( captureFrame ) { trap_MME_BlurInfo( &blurTotal, &blurIndex ); captureFPS = mov_captureFPS.value; if ( blurTotal > 0) { captureFPS *= blurTotal; blurFraction = blurIndex / (float)blurTotal; } else { blurFraction = 0; } } else { } /* Forward the demo */ deltaTime = serverTime - demo.serverTime; if (deltaTime > 50) deltaTime = 50; demo.serverTime = serverTime; demo.serverDeltaTime = 0.001 * deltaTime; cg.oldTime = cg.time; cg.oldTimeFraction = cg.timeFraction; if (demo.play.time < 0) { demo.play.time = demo.play.fraction = 0; } demo.play.oldTime = demo.play.time; /* Handle the music */ if ( demo.play.paused ) { if ( lastMusicStart >= 0) demoSynchMusic( -1, 0 ); } else { int musicStart = (demo.play.time - mov_musicStart.value * 1000 ); if ( musicStart <= 0 ) { if (lastMusicStart >= 0 ) demoSynchMusic( -1, 0 ); } else { if ( demo.play.time != demo.play.lastTime || lastMusicStart < 0) demoSynchMusic( musicStart, 0 ); } } /* forward the time a bit till the moment of capture */ if ( captureFrame && demo.capture.locked && demo.play.time < demo.capture.start ) { int left = demo.capture.start - demo.play.time; if ( left > 2000) { left -= 1000; captureFrame = qfalse; } else if (left > 5) { captureFrame = qfalse; left = 5; } demo.play.time += left; } else if ( captureFrame && demo.loop.total && blurTotal ) { float loopFraction = demo.loop.index / (float)demo.loop.total; demo.play.time = demo.loop.start; demo.play.fraction = demo.loop.range * loopFraction; demo.play.time += (int)demo.play.fraction; demo.play.fraction -= (int)demo.play.fraction; } else if (captureFrame) { float frameDelay = 1000.0f / captureFPS; demo.play.fraction += frameDelay * demo.play.speed; demo.play.time += (int)demo.play.fraction; demo.play.fraction -= (int)demo.play.fraction; } else if ( demo.find ) { demo.play.time = demo.play.oldTime + 20; demo.play.fraction = 0; if ( demo.play.paused ) demo.find = findNone; } else if (!demo.play.paused) { float delta = demo.play.fraction + deltaTime * demo.play.speed; demo.play.time += (int)delta; demo.play.fraction = delta - (int)delta; } demo.play.lastTime = demo.play.time; if ( demo.loop.total && captureFrame && blurTotal ) { //Delay till we hit the right part at the start int time; float timeFraction; if ( demo.loop.lineDelay && !blurIndex ) { time = demo.loop.start - demo.loop.lineDelay; timeFraction = 0; if ( demo.loop.lineDelay > 8 ) demo.loop.lineDelay -= 8; else demo.loop.lineDelay = 0; captureFrame = qfalse; } else { if ( blurIndex == blurTotal - 1 ) { //We'll restart back to the start again demo.loop.lineDelay = 2000; if ( ++demo.loop.index >= demo.loop.total ) { demo.loop.total = 0; } } time = demo.loop.start; timeFraction = demo.loop.range * blurFraction; } time += (int)timeFraction; timeFraction -= (int)timeFraction; lineAt( time, timeFraction, &demo.line.time, &cg.timeFraction, &frameSpeed ); } else { lineAt( demo.play.time, demo.play.fraction, &demo.line.time, &cg.timeFraction, &frameSpeed ); } /* Set the correct time */ cg.time = trap_MME_SeekTime( demo.line.time ); /* cg.time is shifted ahead a bit to correct some issues.. */ frameSpeed *= demo.play.speed; cg.frametime = (cg.time - cg.oldTime) + (cg.timeFraction - cg.oldTimeFraction); if (cg.frametime < 0) { int i; cg.frametime = 0; hadSkip = qtrue; cg.oldTime = cg.time; cg.oldTimeFraction = cg.timeFraction; CG_InitLocalEntities(); CG_InitMarkPolys(); CG_ClearParticles (); trap_FX_Reset( ); trap_R_DecalReset(); cg.centerPrintTime = 0; cg.damageTime = 0; cg.powerupTime = 0; cg.rewardTime = 0; cg.scoreFadeTime = 0; cg.lastKillTime = 0; cg.attackerTime = 0; cg.soundTime = 0; cg.itemPickupTime = 0; cg.itemPickupBlendTime = 0; cg.weaponSelectTime = 0; cg.headEndTime = 0; cg.headStartTime = 0; cg.v_dmg_time = 0; cg.rewardCount[0] = 0; cg.rewardStack = 0; cg.rewardTime = 0; trap_S_ClearLoopingSounds(qtrue); for (i = 0; i < MAX_CHATBOX_ITEMS; i++) cg.chatItems[i].time = 0; } else if (cg.frametime > 100) { hadSkip = qtrue; } else { hadSkip = qfalse; } /* Make sure the random seed is the same each time we hit this frame */ srand( (cg.time % 10000000) + cg.timeFraction * 1000); /* Prepare to render the screen */ trap_S_ClearLoopingSounds(qfalse); trap_R_ClearScene(); /* Update demo related information */ trap_SetUserCmdValue( cg.weaponSelect, 1 ); demoProcessSnapShots( hadSkip ); if ( !cg.snap ) { CG_DrawInformation(); return; } CG_PreparePacketEntities( ); CG_DemosUpdatePlayer( ); chaseUpdate( demo.play.time, demo.play.fraction ); cameraUpdate( demo.play.time, demo.play.fraction ); dofUpdate( demo.play.time, demo.play.fraction ); demoEffectUpdate( demo.play.time, demo.play.fraction ); cg.clientFrame++; // update cg.predictedPlayerState CG_InterpolatePlayerState( qfalse ); BG_PlayerStateToEntityState( &cg.predictedPlayerState, &cg.predictedPlayerEntity.currentState, qfalse ); if ( cg.cpma.detected ) { if ( cg.predictedPlayerState.pm_type >= 4 ) cg.predictedPlayerEntity.currentState.eType = ET_INVISIBLE; } cg.predictedPlayerEntity.currentValid = qtrue; VectorCopy( cg.predictedPlayerEntity.currentState.pos.trBase, cg.predictedPlayerEntity.lerpOrigin ); VectorCopy( cg.predictedPlayerEntity.currentState.apos.trBase, cg.predictedPlayerEntity.lerpAngles ); inwater = demoSetupView(); CG_TileClear(); trap_FX_Begin( cg.time, cg.timeFraction ); scriptRun( hadSkip ); CG_AddPacketEntities(); CG_AddMarks(); CG_AddParticles (); CG_AddLocalEntities(); if ( cg.playerCent == &cg.predictedPlayerEntity ) { // warning sounds when powerup is wearing off CG_PowerupTimerSounds(); CG_AddViewWeapon( &cg.predictedPlayerState ); } else if ( cg.playerCent && cg.playerCent->currentState.number < MAX_CLIENTS ) { CG_AddViewWeaponDirect( cg.playerCent ); } trap_S_UpdateEntityPosition(ENTITYNUM_NONE, cg.refdef.vieworg); CG_PlayBufferedSounds(); CG_PlayBufferedVoiceChats(); cg.refdef.time = cg.time; memcpy( cg.refdef.areamask, cg.snap->areamask, sizeof( cg.refdef.areamask ) ); /* Render some extra demo related stuff */ if (!captureFrame) { switch (demo.editType) { case editCamera: cameraDraw( demo.play.time, demo.play.fraction ); break; case editChase: chaseDraw( demo.play.time, demo.play.fraction ); break; case editDof: dofDraw( demo.play.time, demo.play.fraction ); break; case editEffect: demoEffectDraw( demo.play.time, demo.play.fraction ); break; } /* Add bounding boxes for easy aiming */ if ( demo.editType && ( demo.cmd.buttons & BUTTON_ATTACK) && ( demo.cmd.buttons & BUTTON_AFFIRMATIVE) ) { int i; centity_t *targetCent; for (i = 0;i<MAX_GENTITIES;i++) { targetCent = demoTargetEntity( i ); if (targetCent) { vec3_t container, traceStart, traceImpact, forward; const float *color; demoCentityBoxSize( targetCent, container ); VectorSubtract( demo.viewOrigin, targetCent->lerpOrigin, traceStart ); AngleVectors( demo.viewAngles, forward, 0, 0 ); if (BoxTraceImpact( traceStart, forward, container, traceImpact )) { color = colorRed; } else { color = colorYellow; } demoDrawBox( targetCent->lerpOrigin, container, color ); } } } if ( mov_gridStep.value > 0 && mov_gridRange.value > 0) { vec4_t color; vec3_t offset; qhandle_t shader = trap_R_RegisterShader( "mme/gridline" ); color[0] = color[1] = color[2] = 1; color[3] = 0; offset[0] = offset[1] = offset[2] = 0; Q_parseColor( mov_gridColor.string, ospColors, color ); demoDrawGrid( demo.viewOrigin, color, offset, mov_gridWidth.value, mov_gridStep.value, mov_gridRange.value, shader ); } } if (frameSpeed > 5) frameSpeed = 5; trap_S_UpdateScale( frameSpeed ); if (cg.playerCent && cg.predictedPlayerState.pm_type == PM_INTERMISSION) { entityNum = cg.snap->ps.clientNum; } else if (cg.playerCent) { entityNum = cg.playerCent->currentState.number; } else { entityNum = ENTITYNUM_NONE; } trap_S_Respatialize( entityNum, cg.refdef.vieworg, cg.refdef.viewaxis, inwater); trap_FX_End(); if (captureFrame && stereoSep > 0.0f) trap_Cvar_Set("r_stereoSeparation", va("%f", -stereoSep)); trap_MME_TimeFraction(cg.timeFraction); trap_R_RenderScene( &cg.refdef ); if ( demo.viewType == viewChase && cg.playerCent && ( cg.playerCent->currentState.number < MAX_CLIENTS ) ) CG_Draw2D(); // CG_DrawSmallString( 0, 0, va( "height %d", cg.playerCent->pe.viewHeight ), 1 ); if (captureFrame) { char fileName[MAX_OSPATH]; Com_sprintf( fileName, sizeof( fileName ), "capture/%s/%s", mme_demoFileName.string, mov_captureName.string ); trap_MME_Capture( fileName, captureFPS, demo.viewFocus, demo.viewRadius ); if ( mov_captureCamera.integer ) demoAddViewPos( fileName, demo.viewOrigin, demo.viewAngles, demo.viewFov ); } else { if (demo.editType && !cg.playerCent) demoDrawCrosshair(); hudDraw(); if (demo.editType) { demoDrawProgress(trap_MME_ProgressTime()); } } //checkCaptureEnd: if ( demo.capture.active && demo.capture.locked && demo.play.time > demo.capture.end ) { Com_Printf( "Capturing ended\n" ); if (demo.autoLoad) { trap_SendConsoleCommand( "disconnect\n" ); } demo.capture.active = qfalse; } }
int _main_(int /*_argc*/, char** /*_argv*/) { uint32_t width = 1280; uint32_t height = 720; uint32_t debug = BGFX_DEBUG_TEXT; uint32_t reset = BGFX_RESET_VSYNC; bgfx::init(); bgfx::reset(width, height, reset); // Enable debug text. bgfx::setDebug(debug); // Set view 0 clear state. bgfx::setViewClear(0 , BGFX_CLEAR_COLOR|BGFX_CLEAR_DEPTH , 0x303030ff , 1.0f , 0 ); const bgfx::Caps* caps = bgfx::getCaps(); const bool computeSupported = !!(caps->supported & BGFX_CAPS_COMPUTE); const bool indirectSupported = !!(caps->supported & BGFX_CAPS_DRAW_INDIRECT); if (computeSupported) { // Imgui. imguiCreate(); bgfx::VertexDecl quadVertexDecl; quadVertexDecl.begin() .add(bgfx::Attrib::Position, 2, bgfx::AttribType::Float) .end(); // Create static vertex buffer. bgfx::VertexBufferHandle vbh = bgfx::createVertexBuffer( // Static data can be passed with bgfx::makeRef bgfx::makeRef(s_quadVertices, sizeof(s_quadVertices) ) , quadVertexDecl ); // Create static index buffer. bgfx::IndexBufferHandle ibh = bgfx::createIndexBuffer( // Static data can be passed with bgfx::makeRef bgfx::makeRef(s_quadIndices, sizeof(s_quadIndices) ) ); // Create particle program from shaders. bgfx::ProgramHandle particleProgram = loadProgram("vs_particle", "fs_particle"); // Setup compute buffers bgfx::VertexDecl computeVertexDecl; computeVertexDecl.begin() .add(bgfx::Attrib::TexCoord0, 4, bgfx::AttribType::Float) .end(); const uint32_t threadGroupUpdateSize = 512; const uint32_t maxParticleCount = 32 * 1024; bgfx::DynamicVertexBufferHandle currPositionBuffer0 = bgfx::createDynamicVertexBuffer(1 << 15, computeVertexDecl, BGFX_BUFFER_COMPUTE_READ_WRITE); bgfx::DynamicVertexBufferHandle currPositionBuffer1 = bgfx::createDynamicVertexBuffer(1 << 15, computeVertexDecl, BGFX_BUFFER_COMPUTE_READ_WRITE); bgfx::DynamicVertexBufferHandle prevPositionBuffer0 = bgfx::createDynamicVertexBuffer(1 << 15, computeVertexDecl, BGFX_BUFFER_COMPUTE_READ_WRITE); bgfx::DynamicVertexBufferHandle prevPositionBuffer1 = bgfx::createDynamicVertexBuffer(1 << 15, computeVertexDecl, BGFX_BUFFER_COMPUTE_READ_WRITE); bgfx::UniformHandle u_params = bgfx::createUniform("u_params", bgfx::UniformType::Vec4, 3); bgfx::ProgramHandle initInstancesProgram = bgfx::createProgram(loadShader("cs_init_instances"), true); bgfx::ProgramHandle updateInstancesProgram = bgfx::createProgram(loadShader("cs_update_instances"), true); bgfx::ProgramHandle indirectProgram = BGFX_INVALID_HANDLE; bgfx::IndirectBufferHandle indirectBuffer = BGFX_INVALID_HANDLE; if (indirectSupported) { indirectProgram = bgfx::createProgram(loadShader("cs_indirect"), true); indirectBuffer = bgfx::createIndirectBuffer(2); } u_paramsDataStruct u_paramsData; InitializeParams(0, &u_paramsData); bgfx::setUniform(u_params, &u_paramsData, 3); bgfx::setBuffer(0, prevPositionBuffer0, bgfx::Access::Write); bgfx::setBuffer(1, currPositionBuffer0, bgfx::Access::Write); bgfx::dispatch(0, initInstancesProgram, maxParticleCount / threadGroupUpdateSize, 1, 1); float view[16]; float initialPos[3] = { 0.0f, 0.0f, -45.0f }; cameraCreate(); cameraSetPosition(initialPos); cameraSetVerticalAngle(0.0f); cameraGetViewMtx(view); int32_t scrollArea = 0; bool useIndirect = false; entry::MouseState mouseState; while (!entry::processEvents(width, height, debug, reset, &mouseState) ) { int64_t now = bx::getHPCounter(); static int64_t last = now; const int64_t frameTime = now - last; last = now; const double freq = double(bx::getHPFrequency() ); const float deltaTime = float(frameTime/freq); if (deltaTime > 1000.0) { abort(); } // Set view 0 default viewport. bgfx::setViewRect(0, 0, 0, width, height); // Use debug font to print information about this example. bgfx::dbgTextClear(); bgfx::dbgTextPrintf(0, 1, 0x4f, "bgfx/examples/24-nbody"); bgfx::dbgTextPrintf(0, 2, 0x6f, "Description: N-body simulation with compute shaders using buffers."); imguiBeginFrame(mouseState.m_mx , mouseState.m_my , (mouseState.m_buttons[entry::MouseButton::Left ] ? IMGUI_MBUT_LEFT : 0) | (mouseState.m_buttons[entry::MouseButton::Right ] ? IMGUI_MBUT_RIGHT : 0) , mouseState.m_mz , width , height ); imguiBeginScrollArea("Settings", width - width / 4 - 10, 10, width / 4, 500, &scrollArea); imguiSlider("Random seed", u_paramsData.baseSeed, 0, 100); int32_t shape = imguiChoose(u_paramsData.initialShape, "Point", "Sphere", "Box", "Donut"); imguiSlider("Initial speed", u_paramsData.initialSpeed, 0.0f, 300.0f, 0.1f); bool defaults = imguiButton("Reset"); imguiSeparatorLine(); imguiSlider("Particle count (x512)", u_paramsData.dispatchSize, 1, 64); imguiSlider("Gravity", u_paramsData.gravity, 0.0f, 0.3f, 0.001f); imguiSlider("Damping", u_paramsData.damping, 0.0f, 1.0f, 0.01f); imguiSlider("Max acceleration", u_paramsData.maxAccel, 0.0f, 100.0f, 0.01f); imguiSlider("Time step", u_paramsData.timeStep, 0.0f, 0.02f, 0.0001f); imguiSeparatorLine(); imguiSlider("Particle intensity", u_paramsData.particleIntensity, 0.0f, 1.0f, 0.001f); imguiSlider("Particle size", u_paramsData.particleSize, 0.0f, 1.0f, 0.001f); imguiSlider("Particle power", u_paramsData.particlePower, 0.001f, 16.0f, 0.01f); imguiSeparatorLine(); if (imguiCheck("Use draw/dispatch indirect", useIndirect, indirectSupported) ) { useIndirect = !useIndirect; } imguiEndScrollArea(); imguiEndFrame(); // Modify parameters and reset if shape is changed if (shape != u_paramsData.initialShape) { defaults = true; InitializeParams(shape, &u_paramsData); } if (defaults) { bgfx::setBuffer(0, prevPositionBuffer0, bgfx::Access::Write); bgfx::setBuffer(1, currPositionBuffer0, bgfx::Access::Write); bgfx::setUniform(u_params, &u_paramsData, 3); bgfx::dispatch(0, initInstancesProgram, maxParticleCount / threadGroupUpdateSize, 1, 1); } if (useIndirect) { bgfx::setUniform(u_params, &u_paramsData, 3); bgfx::setBuffer(0, indirectBuffer, bgfx::Access::Write); bgfx::dispatch(0, indirectProgram); } bgfx::setBuffer(0, prevPositionBuffer0, bgfx::Access::Read); bgfx::setBuffer(1, currPositionBuffer0, bgfx::Access::Read); bgfx::setBuffer(2, prevPositionBuffer1, bgfx::Access::Write); bgfx::setBuffer(3, currPositionBuffer1, bgfx::Access::Write); bgfx::setUniform(u_params, &u_paramsData, 3); if (useIndirect) { bgfx::dispatch(0, updateInstancesProgram, indirectBuffer, 1); } else { bgfx::dispatch(0, updateInstancesProgram, u_paramsData.dispatchSize, 1, 1); } bx::xchg(currPositionBuffer0, currPositionBuffer1); bx::xchg(prevPositionBuffer0, prevPositionBuffer1); // Update camera. cameraUpdate(deltaTime, mouseState); cameraGetViewMtx(view); // Set view and projection matrix for view 0. const bgfx::HMD* hmd = bgfx::getHMD(); if (NULL != hmd && 0 != (hmd->flags & BGFX_HMD_RENDERING) ) { float viewHead[16]; float eye[3] = {}; bx::mtxQuatTranslationHMD(viewHead, hmd->eye[0].rotation, eye); float tmp[16]; bx::mtxMul(tmp, view, viewHead); float proj[16]; bx::mtxProj(proj, hmd->eye[0].fov, 0.1f, 10000.0f); bgfx::setViewTransform(0, tmp, proj); // Set view 0 default viewport. // // Use HMD's width/height since HMD's internal frame buffer size // might be much larger than window size. bgfx::setViewRect(0, 0, 0, hmd->width, hmd->height); } else { float proj[16]; bx::mtxProj(proj, 90.0f, float(width)/float(height), 0.1f, 10000.0f); bgfx::setViewTransform(0, view, proj); // Set view 0 default viewport. bgfx::setViewRect(0, 0, 0, width, height); } // Set vertex and index buffer. bgfx::setVertexBuffer(vbh); bgfx::setIndexBuffer(ibh); bgfx::setInstanceDataBuffer(currPositionBuffer0, 0, u_paramsData.dispatchSize * threadGroupUpdateSize); // Set render states. bgfx::setState(0 | BGFX_STATE_RGB_WRITE | BGFX_STATE_BLEND_ADD | BGFX_STATE_DEPTH_TEST_ALWAYS ); // Submit primitive for rendering to view 0. if (useIndirect) { bgfx::submit(0, particleProgram, indirectBuffer, 0); } else { bgfx::submit(0, particleProgram); } // Advance to next frame. Rendering thread will be kicked to // process submitted rendering primitives. bgfx::frame(); } // Cleanup. cameraDestroy(); imguiDestroy(); if (indirectSupported) { bgfx::destroyProgram(indirectProgram); bgfx::destroyIndirectBuffer(indirectBuffer); } bgfx::destroyUniform(u_params); bgfx::destroyDynamicVertexBuffer(currPositionBuffer0); bgfx::destroyDynamicVertexBuffer(currPositionBuffer1); bgfx::destroyDynamicVertexBuffer(prevPositionBuffer0); bgfx::destroyDynamicVertexBuffer(prevPositionBuffer1); bgfx::destroyProgram(updateInstancesProgram); bgfx::destroyProgram(initInstancesProgram); bgfx::destroyIndexBuffer(ibh); bgfx::destroyVertexBuffer(vbh); bgfx::destroyProgram(particleProgram); } else { int64_t timeOffset = bx::getHPCounter(); entry::MouseState mouseState; while (!entry::processEvents(width, height, debug, reset, &mouseState) ) { int64_t now = bx::getHPCounter(); float time = (float)( (now - timeOffset)/double(bx::getHPFrequency() ) ); bgfx::setViewRect(0, 0, 0, width, height); bgfx::dbgTextClear(); bgfx::dbgTextPrintf(0, 1, 0x4f, "bgfx/examples/24-nbody"); bgfx::dbgTextPrintf(0, 2, 0x6f, "Description: N-body simulation with compute shaders using buffers."); bool blink = uint32_t(time*3.0f)&1; bgfx::dbgTextPrintf(0, 5, blink ? 0x1f : 0x01, " Compute is not supported by GPU. "); bgfx::touch(0); bgfx::frame(); } } // Shutdown bgfx. bgfx::shutdown(); return 0; }