void FloatingTextRenderer::render(Camera* cam, Layer* layer, RenderList& instances) { if (!m_font) { //no font selected.. nothing to render return; } RenderList::const_iterator instance_it = instances.begin(); uint32_t lm = m_renderbackend->getLightingModel(); SDL_Color old_color = m_font->getColor(); if(m_font_color) { m_font->setColor(m_color.r, m_color.g, m_color.b, m_color.unused); } for (;instance_it != instances.end(); ++instance_it) { Instance* instance = (*instance_it)->instance; const std::string* saytext = instance->getSayText(); if (saytext) { const Rect& ir = (*instance_it)->dimensions; Image* img = m_font->getAsImageMultiline(*saytext); Rect r; r.x = (ir.x + ir.w/2) - img->getWidth()/2; /// the center of the text rect is always aligned to the instance's rect center. r.y = ir.y- img->getHeight(); /// make the text rect floating higher than the instance. r.w = img->getWidth(); r.h = img->getHeight(); // Without this check it can happen that changeRenderInfos() call produces an out_of_range error // because the image rendering can be skipped, if it's not on the screen. // The result is that it tried to modify more objects as exist. if (r.right() < 0 || r.x > static_cast<int32_t>(m_renderbackend->getWidth()) || r.bottom() < 0 || r.y > static_cast<int32_t>(m_renderbackend->getHeight())) { continue; } if(m_background || m_backborder) { const int32_t overdraw = 5; Point p = Point(r.x-overdraw, r.y-overdraw); if(m_background) { m_renderbackend->fillRectangle(p, r.w+2*overdraw, r.h+2*overdraw, m_backcolor.r, m_backcolor.g, m_backcolor.b, m_backcolor.unused); } if(m_backborder) { m_renderbackend->drawRectangle(p, r.w+2*overdraw, r.h+2*overdraw, m_backbordercolor.r, m_backbordercolor.g, m_backbordercolor.b, m_backbordercolor.unused); } } img->render(r); if(lm > 0) { uint16_t elements = 1; if (m_background) { ++elements; } if (m_backborder) { ++elements; } m_renderbackend->changeRenderInfos(RENDER_DATA_WITHOUT_Z, elements, 4, 5, false, true, 255, REPLACE, ALWAYS); } } } if(m_font_color) { m_font->setColor(old_color.r, old_color.g, old_color.b, old_color.unused); } }
void LHydrogen::draw(RenderList& renderList) { if(!mBlinking) { renderList.addSprite(mAnim); renderList.addSprite(mSnurrAnim); } }
bool Renderer::RemoveFromList(RenderableObject* obj, RenderList& renderlist){ for( RenderIterator it = renderlist.begin(); it != renderlist.end(); ++it ){ if( (*it) == obj ){ renderlist.erase(it); return true; } } return false; }
inline void _AddTexToRender( RenderList& renlist, TexID tex, int left, int top, int width, int height ) { renlist.emplace_back(); RenderEntry& entry = renlist.back(); entry.textures.push_back( tex ); entry.SetScrPos( left, top ); entry.SetSize( width, height ); }
void FloatingTextRenderer::render(Camera* cam, Layer* layer, RenderList& instances) { if (!m_font) { //no font selected.. nothing to render return; } RenderList::const_iterator instance_it = instances.begin(); const std::string* saytext = NULL; uint32_t lm = m_renderbackend->getLightingModel(); SDL_Color old_color = m_font->getColor(); if(m_font_color) { m_font->setColor(m_color.r, m_color.g, m_color.b, m_color.unused); } for (;instance_it != instances.end(); ++instance_it) { Instance* instance = (*instance_it)->instance; saytext = instance->getSayText(); if (saytext) { const Rect& ir = (*instance_it)->dimensions; Image* img = m_font->getAsImageMultiline(*saytext); Rect r; r.x = (ir.x + ir.w/2) - img->getWidth()/2; /// the center of the text rect is always aligned to the instance's rect center. r.y = ir.y- img->getHeight(); /// make the text rect floating higher than the instance. r.w = img->getWidth(); r.h = img->getHeight(); if(m_background || m_backborder) { const int32_t overdraw = 5; Point p = Point(r.x-overdraw, r.y-overdraw); if(m_background) { m_renderbackend->fillRectangle(p, r.w+2*overdraw, r.h+2*overdraw, m_backcolor.r, m_backcolor.g, m_backcolor.b, m_backcolor.unused); } if(m_backborder) { m_renderbackend->drawRectangle(p, r.w+2*overdraw, r.h+2*overdraw, m_backbordercolor.r, m_backbordercolor.g, m_backbordercolor.b, m_backbordercolor.unused); } } img->render(r); if(lm > 0) { uint16_t elements = 1; if (m_background) { ++elements; } if (m_backborder) { ++elements; } m_renderbackend->changeRenderInfos(elements, 4, 5, false, true, 255, REPLACE, ALWAYS); } } } if(m_font_color) { m_font->setColor(old_color.r, old_color.g, old_color.b, old_color.unused); } }
void PrintRenderList( const RenderList& list ) { unsigned int flags = list.GetFlags(); std::stringstream debugStream; debugStream << "Rendering items"; if( flags ) { debugStream << " with:"; if( flags & RenderList::DEPTH_BUFFER_ENABLED ) { debugStream << " DEPTH_TEST"; } if( flags & RenderList::DEPTH_WRITE ) { debugStream << " DEPTH_WRITE"; } if( flags & RenderList::DEPTH_CLEAR ) { debugStream << " DEPTH_CLEAR"; } if( flags & RenderList::STENCIL_BUFFER_ENABLED ) { debugStream << " STENCIL_TEST"; } if( flags & RenderList::STENCIL_WRITE ) { debugStream << " STENCIL_WRITE"; } if( flags & RenderList::STENCIL_CLEAR ) { debugStream << " STENCIL_CLEAR"; } } else { debugStream << " without any DEPTH_TEST, DEPTH_WRITE etc"; } if( list.IsClipping() ) { debugStream << ", ClippingBox: " << list.GetClippingBox().x << "," << list.GetClippingBox().y << " " << list.GetClippingBox().width << "x" << list.GetClippingBox().height; } std::string debugString( debugStream.str() ); DALI_LOG_RENDER_INFO( " %s\n", debugString.c_str() ); }
RenderList Wall::visibleBricks() { RenderList renderList; for (int i = 0, e = m_bricks.size(); i < e; ++i) { if (m_bricks[i].visible()) { renderList.push_back(m_bricks[i].renderable()); } else if (m_collisionManager) { m_collisionManager->removePassiveCollider(&m_bricks[i]); } } return renderList; }
void EMPEffect::draw(RenderList& renderList, SpaceManImp* owner) { mAnim.getSprite().setRotation( owner->getBody().getAngle() * 57 ); mAnim.getSprite().setPosition( owner->getBody().getWorldCenter().x*30, owner->getBody().getWorldCenter().y*30); renderList.addSprite(mAnim); }
void Render() { RenderElement element; element.m_program = m_program; element.m_textureCount = 0; element.m_uniformBufferCount = 0; element.m_geometry = &m_geom; renderList.Push( element ); }
void BlockingInfoRenderer::render(Camera* cam, Layer* layer, RenderList& instances) { CellGrid* cg = layer->getCellGrid(); if (!cg) { FL_WARN(_log, "No cellgrid assigned to layer, cannot draw grid"); return; } Rect cv = cam->getViewPort(); RenderList::const_iterator instance_it = instances.begin(); for (;instance_it != instances.end(); ++instance_it) { Instance* instance = (*instance_it)->instance; if (!instance->getObject()->isBlocking() || !instance->isBlocking()) { continue; } std::vector<ExactModelCoordinate> vertices; cg->getVertices(vertices, instance->getLocationRef().getLayerCoordinates()); std::vector<ExactModelCoordinate>::const_iterator it = vertices.begin(); int halfind = vertices.size() / 2; ScreenPoint firstpt = cam->toScreenCoordinates(cg->toMapCoordinates(*it)); Point pt1(firstpt.x, firstpt.y); Point pt2; ++it; for (; it != vertices.end(); it++) { ScreenPoint pts = cam->toScreenCoordinates(cg->toMapCoordinates(*it)); pt2.x = pts.x; pt2.y = pts.y; Point cpt1 = pt1; Point cpt2 = pt2; m_renderbackend->drawLine(cpt1, cpt2, m_color.r, m_color.g, m_color.b); pt1 = pt2; } m_renderbackend->drawLine(pt2, Point(firstpt.x, firstpt.y), m_color.r, m_color.g, m_color.b); ScreenPoint spt1 = cam->toScreenCoordinates(cg->toMapCoordinates(vertices[0])); Point pt3(spt1.x, spt1.y); ScreenPoint spt2 = cam->toScreenCoordinates(cg->toMapCoordinates(vertices[halfind])); Point pt4(spt2.x, spt2.y); m_renderbackend->drawLine(pt3, pt4, m_color.r, m_color.g, m_color.b); } }
void OpenGLRenderer::drawBatched(const RenderList& list) { RW_PROFILE_SCOPE(__func__); #if 0 // Needs shader changes // Determine how many batches we need to process the entire list auto entries = list.size(); glBindBuffer(GL_UNIFORM_BUFFER, UBOObject); for (int b = 0; b < entries; b += maxObjectEntries) { auto toConsume = std::min((GLuint)entries, b + maxObjectEntries) - b; std::vector<ObjectUniformData> uploadBuffer; uploadBuffer.resize(toConsume); for (int d = 0; d < toConsume; ++d) { auto& draw = list[b+d]; uploadBuffer[d] = { draw.model, glm::vec4(draw.drawInfo.colour.r/255.f, draw.drawInfo.colour.g/255.f, draw.drawInfo.colour.b/255.f, 1.f), 1.f, 1.f, draw.drawInfo.colour.a/255.f }; } glBufferData(GL_UNIFORM_BUFFER, toConsume * sizeof(ObjectUniformData), uploadBuffer.data(), GL_STREAM_DRAW); // Dispatch individual draws for (int d = 0; d < toConsume; ++d) { auto& draw = list[b+d]; useDrawBuffer(draw.dbuff); for( GLuint u = 0; u < draw.drawInfo.textures.size(); ++u ) { useTexture(u, draw.drawInfo.textures[u]); } glDrawElements(draw.dbuff->getFaceType(), draw.drawInfo.count, GL_UNSIGNED_INT, reinterpret_cast<void*>(sizeof(RenderIndex) * draw.drawInfo.start)); } } #else for (auto& ri : list) { draw(ri.model, ri.dbuff, ri.drawInfo); } #endif }
void LayerCache::update(Camera::Transform transform, RenderList& renderlist) { const double OVERDRAW = 2.5; renderlist.clear(); m_needupdate = false; if(!m_layer->areInstancesVisible()) { FL_DBG(_log, "Layer instances hidden"); return; } bool isWarped = transform == Camera::WarpedTransform; if( isWarped ) { fullUpdate(); } Rect viewport = m_camera->getViewPort(); Rect screen_viewport = viewport; double zoom = m_camera->getZoom(); DoublePoint3D viewport_a = m_camera->screenToVirtualScreen(Point3D(viewport.x, viewport.y)); DoublePoint3D viewport_b = m_camera->screenToVirtualScreen(Point3D(viewport.right(), viewport.bottom())); viewport.x = static_cast<int32_t>(std::min(viewport_a.x, viewport_b.x)); viewport.y = static_cast<int32_t>(std::min(viewport_a.y, viewport_b.y)); viewport.w = static_cast<int32_t>(std::max(viewport_a.x, viewport_b.x) - viewport.x); viewport.h = static_cast<int32_t>(std::max(viewport_a.y, viewport_b.y) - viewport.y); uint8_t layer_trans = m_layer->getLayerTransparency(); double zmin = 0.0, zmax = 0.0; // FL_LOG(_log, LMsg("camera-update viewport") << viewport); std::vector<int32_t> index_list; collect(viewport, index_list); for(unsigned i=0; i!=index_list.size(); ++i) { Entry& entry = m_entries[index_list[i]]; // NOTE // An update is forced if the item has an animation/action. // This update only happens if it is _already_ included in the viewport // Nevertheless: Moving instances - which might move into the viewport will be updated // By the layer change listener. if(entry.force_update || !isWarped) { updateEntry(entry); } RenderItem& item = m_instances[entry.instance_index]; InstanceVisual* visual = item.instance->getVisual<InstanceVisual>(); bool visible = (visual->isVisible() != 0); uint8_t instance_trans = visual->getTransparency(); if(!item.image || !visible || (instance_trans == 255 && layer_trans == 0) || (instance_trans == 0 && layer_trans == 255)) { continue; } if(layer_trans != 0) { if(instance_trans != 0) { uint8_t calc_trans = layer_trans - instance_trans; if(calc_trans >= 0) { instance_trans = calc_trans; } else { instance_trans = 0; } } else { instance_trans = layer_trans; } } Point3D screen_point = m_camera->virtualScreenToScreen(item.screenpoint); // NOTE: // One would expect this to be necessary here, // however it works the same without, sofar // m_camera->calculateZValue(screen_point); // item.screenpoint.z = -screen_point.z; item.dimensions.x = screen_point.x; item.dimensions.y = screen_point.y; item.dimensions.w = item.bbox.w; item.dimensions.h = item.bbox.h; item.transparency = 255 - instance_trans; if (zoom != 1.0) { // NOTE: Due to image alignment, there is additional additions on image dimensions // There's probabaly some better solution for this, but works "good enough" for now. // In case additions are removed, gaps appear between tiles. item.dimensions.w = unsigned(double(item.bbox.w) * zoom + OVERDRAW); item.dimensions.h = unsigned(double(item.bbox.h) * zoom + OVERDRAW); } if (!m_need_sorting) { zmin = std::min(zmin, item.screenpoint.z); zmax = std::max(zmax, item.screenpoint.z); } if(item.dimensions.intersects(screen_viewport)) { renderlist.push_back(&item); } } if (m_need_sorting) { InstanceDistanceSort ids; std::stable_sort(renderlist.begin(), renderlist.end(), ids); } else { zmin -= 0.5; zmax += 0.5; // We want to put every z value in [-10,10] range. // To do it, we simply solve // { y1 = a*x1 + b // { y2 = a*x2 + b // where [y1,y2]' = [-10,10]' is required z range, // and [x1,x2]' is expected min,max z coords. double det = zmin - zmax; if (fabs(det) > FLT_EPSILON) { double det_a = -10.0 - 10.0; double det_b = 10.0 * zmin - (-10.0) * zmax; double a = static_cast<float>(det_a / det); double b = static_cast<float>(det_b / det); float estimate = sqrtf(static_cast<float>(renderlist.size())); float stack_delta = fabs(-10.0f - 10.0f) / estimate * 0.1f; RenderList::iterator it = renderlist.begin(); for ( ; it != renderlist.end(); ++it) { double& z = (*it)->screenpoint.z; z = a * z + b; InstanceVisual* vis = (*it)->instance->getVisual<InstanceVisual>(); z += vis->getStackPosition() * stack_delta; } } } // FL_LOG(_log, LMsg("camera-update ") << " N=" <<renderlist.size() << "/" << m_instances.size() << "/" << index_list.size()); }
void ObjectRenderer::renderGeometry(Geometry* geom, const glm::mat4& modelMatrix, GameObject* object, RenderList& outList) { for (SubGeometry& subgeom : geom->subgeom) { bool isTransparent = false; Renderer::DrawParameters dp; dp.colour = {255, 255, 255, 255}; dp.count = subgeom.numIndices; dp.start = subgeom.start; dp.textures = {0}; dp.visibility = 1.f; if (object && object->type() == GameObject::Instance) { auto modelinfo = object->getModelInfo<SimpleModelInfo>(); dp.depthWrite = !(modelinfo->flags & SimpleModelInfo::NO_ZBUFFER_WRITE); } if (geom->materials.size() > subgeom.material) { Geometry::Material& mat = geom->materials[subgeom.material]; if (!mat.textures.empty()) { auto tex = mat.textures[0].texture; if (tex) { if (tex->isTransparent()) { isTransparent = true; } dp.textures = {tex->getName()}; } } if ((geom->flags & RW::BSGeometry::ModuleMaterialColor) == RW::BSGeometry::ModuleMaterialColor) { dp.colour = mat.colour; if (object && object->type() == GameObject::Vehicle) { auto vehicle = static_cast<VehicleObject*>(object); if (dp.colour.r == 60 && dp.colour.g == 255 && dp.colour.b == 0) { dp.colour = glm::u8vec4(vehicle->colourPrimary, 255); } else if (dp.colour.r == 255 && dp.colour.g == 0 && dp.colour.b == 175) { dp.colour = glm::u8vec4(vehicle->colourSecondary, 255); } } } dp.visibility = 1.f; if (dp.colour.a < 255) { isTransparent = true; } dp.diffuse = mat.diffuseIntensity; dp.ambient = mat.ambientIntensity; } dp.blend = isTransparent; glm::vec3 position(modelMatrix[3]); float distance = glm::length(m_camera.position - position); float depth = (distance - m_camera.frustum.near) / (m_camera.frustum.far - m_camera.frustum.near); outList.emplace_back( createKey(isTransparent, depth * depth, dp.textures), modelMatrix, &geom->dbuff, dp); } }
namespace Level3_NS { const U32 FRAME_MAX_COUNT = 60; U64 clockTicks = 0; U32 frameCount = 0; const SizeT frameAllocatorSize = 10 * 1024; RenderDevice device3d; ProgramCache programCache; RenderList renderList; class RenderSimple : public RenderGeometry { public: void Draw() { RenderDevice::BeginGeometry( m_vertexDecl, m_vertexArray, m_indexBuffer ); RenderDevice::DrawIndexed( m_primitive, m_indexCount, m_indexType ); RenderDevice::EndGeometry( m_vertexDecl ); } PrimitiveType m_primitive; Handle m_vertexBuffer; VertexDeclaration m_vertexDecl; SizeT m_vertexCount; DataType m_indexType; Handle m_vertexArray; Handle m_indexBuffer; SizeT m_indexCount; }; class FullScreenQuadRenderer { public: FullScreenQuadRenderer() { } void Initialize() { U32 programId = ProgramCache::CreateId( "level3" ); m_program = programCache.GetProgram( programId ); m_geom.m_primitive = PT_TRIANGLES; VertexDeclaration& vDecl = m_geom.m_vertexDecl; vDecl.m_attributes[0].m_semantic = VS_POSITION; vDecl.m_attributes[0].m_type = DT_F32; vDecl.m_attributes[0].m_size = 4; vDecl.m_attributes[0].m_normalized = false; vDecl.m_attributes[0].m_offset = 0; vDecl.m_size = 16; vDecl.m_count = 1; m_geom.m_vertexCount = 4; const F32 vb[4][4] = { { -1.0f, -1.0f, 0.0f, 1.0f }, { +1.0f, -1.0f, 1.0f, 1.0f }, { -1.0f, +1.0f, 0.0f, 0.0f }, { +1.0f, +1.0f, 1.0f, 0.0f } }; m_geom.m_vertexBuffer = RenderDevice::CreateVertexBuffer( sizeof(vb), vb, BU_STATIC ); m_geom.m_indexType = DT_U8; const U8 ib[2][3] = { 0, 1, 2, 2, 1, 3, }; m_geom.m_indexBuffer = RenderDevice::CreateIndexBuffer( sizeof(ib), ib, BU_STATIC ); m_geom.m_vertexArray = RenderDevice::CreateVertexArray( vDecl, m_geom.m_vertexBuffer ); m_geom.m_indexCount = 6; } void Render() { RenderElement element; element.m_program = m_program; element.m_textureCount = 0; element.m_uniformBufferCount = 0; element.m_geometry = &m_geom; renderList.Push( element ); } void Destroy() { RenderDevice::DestroyVertexArray( m_geom.m_vertexArray ); RenderDevice::DestroyBuffer( m_geom.m_indexBuffer ); RenderDevice::DestroyBuffer( m_geom.m_vertexBuffer ); } private: ProgramHandle m_program; RenderSimple m_geom; }; LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { case WM_CLOSE: DestroyWindow(hwnd); break; case WM_DESTROY: PostQuitMessage(0); break; case WM_KEYDOWN: switch ( wParam ) { case VK_ESCAPE: PostQuitMessage(0); break; case VK_SPACE: { programCache.NotifySourceChange(); break; } } return 0; default: return DefWindowProc(hwnd, msg, wParam, lParam); } return 0; } Bool MessagePump( MSG * msg ) { // check for messages while ( PeekMessage( msg, NULL, 0, 0, PM_REMOVE ) ) { // handle or dispatch messages if ( msg->message == WM_QUIT ) { return false; } else { TranslateMessage( msg ); DispatchMessage( msg ); } } return true; } void DisplayFramerate( HWND hwnd ) { ++frameCount; if ( frameCount == FRAME_MAX_COUNT ) { U64 currentTicks = Core::TimeUtils::ClockTime(); F64 fps = FRAME_MAX_COUNT * Core::TimeUtils::ClockFrequency() / ( currentTicks - clockTicks ); clockTicks = currentTicks; frameCount = 0; Char text[ 32 ]; SetWindowText( hwnd, Core::StringUtils::FormatString( text, 32, "Level3 - [ %0.0f fps ]", fps ) ); } } }
void GameRenderer::renderWorld(GameWorld* world, const ViewCamera &camera, float alpha) { _renderAlpha = alpha; _renderWorld = world; // Store the input camera, _camera = camera; setupRender(); glBindVertexArray( vao ); float tod = world->getHour() + world->getMinute()/60.f; // Requires a float 0-24 auto weatherID = static_cast<WeatherLoader::WeatherCondition>(world->state->basic.nextWeather * 24); auto weather = world->data->weatherLoader.getWeatherData(weatherID, tod); glm::vec3 skyTop = weather.skyTopColor; glm::vec3 skyBottom = weather.skyBottomColor; glm::vec3 ambient = weather.ambientColor; glm::vec3 dynamic = weather.directLightColor; float theta = (tod/(60.f * 24.f) - 0.5f) * 2 * 3.14159265; glm::vec3 sunDirection{ sin(theta), 0.0, cos(theta), }; sunDirection = glm::normalize(sunDirection); _camera.frustum.near = world->state->cameraNear; _camera.frustum.far = weather.farClipping; auto view = _camera.getView(); auto proj = _camera.frustum.projection(); Renderer::SceneUniformData sceneParams { proj, view, glm::vec4{ambient, 0.0f}, glm::vec4{dynamic, 0.0f}, glm::vec4(skyBottom, 1.f), glm::vec4(camera.position, 0.f), weather.fogStart, camera.frustum.far }; renderer->setSceneParameters(sceneParams); renderer->clear(glm::vec4(skyBottom, 1.f)); _camera.frustum.update(proj * view); if (cullOverride) { cullingCamera.frustum.update( cullingCamera.frustum.projection() * cullingCamera.getView()); } culled = 0; renderer->useProgram(worldProg); //=============================================================== // Render List Construction //--------------------------------------------------------------- RW_PROFILE_BEGIN("RenderList"); // This is sequential at the moment, it should be easy to make it // run in parallel with a good threading system. RenderList renderList; // Naive optimisation, assume 10% hitrate renderList.reserve(world->allObjects.size() * 0.5f); RW_PROFILE_BEGIN("Build"); ObjectRenderer objectRenderer(_renderWorld, (cullOverride ? cullingCamera : _camera), _renderAlpha, getMissingTexture()); // World Objects for (auto object : world->allObjects) { objectRenderer.buildRenderList(object, renderList); } RW_PROFILE_END(); renderer->pushDebugGroup("Objects"); renderer->pushDebugGroup("RenderList"); // Also parallelizable RW_PROFILE_BEGIN("Sort"); std::sort(renderList.begin(), renderList.end(), [](const Renderer::RenderInstruction& a, const Renderer::RenderInstruction&b) { return a.sortKey < b.sortKey; }); RW_PROFILE_END(); RW_PROFILE_BEGIN("Draw"); renderer->drawBatched(renderList); RW_PROFILE_END(); renderer->popDebugGroup(); profObjects = renderer->popDebugGroup(); RW_PROFILE_END(); // Render arrows above anything that isn't radar only (or hidden) ModelRef& arrowModel = world->data->models["arrow"]; if( arrowModel && arrowModel->resource ) { auto arrowTex = world->data->textures[{"copblue",""}]; auto arrowFrame = arrowModel->resource->findFrame( "arrow" ); for( auto& blip : world->state->radarBlips ) { if( blip.second.display == BlipData::Show ) { glm::mat4 model; if( blip.second.target > 0 ) { // TODO restore arrows /*auto& pool = world->getTypeObjectPool(blip.second.target); auto object = pool.find(blip.second.target); if( object ) { model = object->getTimeAdjustedTransform( _renderAlpha ); }*/ } else { model = glm::translate( model, blip.second.coord ); } float a = world->getGameTime() * glm::pi<float>(); model = glm::translate( model, glm::vec3(0.f, 0.f, 2.5f + glm::sin( a ) * 0.5f) ); model = glm::rotate( model, a, glm::vec3(0.f, 0.f, 1.f) ); model = glm::scale( model, glm::vec3(1.5f, 1.5f, 1.5f) ); Renderer::DrawParameters dp; dp.textures = {arrowTex->getName()}; dp.ambient = 1.f; dp.colour = glm::u8vec4(255, 255, 255, 255); auto geom = arrowModel->resource->geometries[arrowFrame->getGeometries()[0]]; Model::SubGeometry& sg = geom->subgeom[0]; dp.start = sg.start; dp.count = sg.numIndices; dp.diffuse = 1.f; renderer->draw( model, &geom->dbuff, dp ); } } } // Draw goal indicators glDepthMask(GL_FALSE); renderer->useProgram( particleProg ); for(auto& i : world->getAreaIndicators()) { renderAreaIndicator( &i ); } glDepthMask(GL_TRUE); renderer->pushDebugGroup("Water"); water.render(this, world); profWater = renderer->popDebugGroup(); renderer->pushDebugGroup("Sky"); glBindVertexArray( vao ); Renderer::DrawParameters dp; dp.start = 0; dp.count = skydomeSegments * skydomeRows * 6; renderer->useProgram(skyProg); renderer->setUniform(skyProg, "TopColor", glm::vec4(skyTop, 1.f)); renderer->setUniform(skyProg, "BottomColor", glm::vec4(skyBottom, 1.f)); renderer->draw(glm::mat4(), &skyDbuff, dp); profSky = renderer->popDebugGroup(); renderer->pushDebugGroup("Effects"); renderEffects(world); profEffects = renderer->popDebugGroup(); glDisable(GL_DEPTH_TEST); GLuint splashTexName = 0; auto fc = world->state->fadeColour; if((fc.r + fc.g + fc.b) == 0 && world->state->currentSplash.size() > 0) { auto splash = world->data->findTexture(world->state->currentSplash); if ( splash ) { splashTexName = splash->getName(); } } if( (world->state->isCinematic || world->state->currentCutscene ) && splashTexName != 0 ) { renderLetterbox(); } float fadeTimer = world->getGameTime() - world->state->fadeStart; if( fadeTimer < world->state->fadeTime || !world->state->fadeOut ) { glUseProgram(ssRectProgram); glUniform2f(ssRectOffset, 0.f, 0.f); glUniform2f(ssRectSize, 1.f, 1.f); glUniform1i(ssRectTexture, 0); if(splashTexName != 0) { glBindTexture(GL_TEXTURE_2D, splashTexName); fc = glm::u16vec3(0, 0, 0); } else { glBindTexture(GL_TEXTURE_2D, 0); } float fadeFrac = 0.f; if( world->state->fadeTime > 0.f ) { fadeFrac = std::min(fadeTimer / world->state->fadeTime, 1.f); } float a = world->state->fadeOut ? 1.f - fadeFrac : fadeFrac; glm::vec4 fadeNormed(fc.r / 255.f, fc.g/ 255.f, fc.b/ 255.f, a); glUniform4fv(ssRectColour, 1, glm::value_ptr(fadeNormed)); glBindVertexArray( ssRectDraw.getVAOName() ); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } if( (world->state->isCinematic || world->state->currentCutscene ) && splashTexName == 0 ) { renderLetterbox(); } renderPostProcess(); glUseProgram(0); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glBindVertexArray( 0 ); }
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { GameState gameState = {}; gameState.RenderState = 0; gameState.State = 1; gameState.PlayerX = 200.0; gameState.PlayerY = 450.0; glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); GLFWwindow* window = glfwCreateWindow(gameState.ScreenWidth, gameState.ScreenHeight, "Neighbors", NULL, NULL); glfwMakeContextCurrent(window); glewExperimental = GL_TRUE; glewInit(); glGetError(); glfwSetKeyCallback(window, processWindowsCallback); // OpenGL configuration glViewport(0, 0, gameState.ScreenWidth, gameState.ScreenHeight); // Where in the window to render. glEnable(GL_CULL_FACE); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // Load shaders ResourceManager::LoadShader("shaders/sprite.vs", "shaders/sprite.frag", nullptr, "sprite"); // Configure shaders glm::mat4 projection = glm::ortho(0.0f, static_cast<GLfloat>(gameState.ScreenWidth), static_cast<GLfloat>(gameState.ScreenHeight), 0.0f, -1.0f, 1.0f); ResourceManager::GetShader("sprite").Use().SetInteger("image", 0); ResourceManager::GetShader("sprite").SetMatrix4("projection", projection); // Set render-specific controls Renderer = new SpriteRenderer(ResourceManager::GetShader("sprite")); AnimateRenderer = new AnimatedSpriteRenderer(ResourceManager::GetShader("sprite")); // Load textures ResourceManager::LoadTexture("textures/download.png", GL_TRUE, "face"); ResourceManager::LoadTexture("textures/download.jpg", GL_TRUE, "other"); ResourceManager::LoadTexture("textures/grass.png", GL_TRUE, "grass"); ResourceManager::LoadTexture("textures/floor.png", GL_TRUE, "floor"); ResourceManager::LoadTexture("textures/back_wall.png", GL_TRUE, "backwall"); ResourceManager::LoadSpriteSheet("textures/sonic.png", GL_TRUE, "sonic"); RenderList List; /* Loop until the user closes the window */ while (!glfwWindowShouldClose(window)) { // Clear IsDowns to false for incoming input and update WasDown's. for (int ButtonIndex = 0; ButtonIndex < ArrayCount(GlobalInput.Controller.Buttons); ButtonIndex++) { GlobalInput.Controller.Buttons[ButtonIndex].WasDown = GlobalInput.Controller.Buttons[ButtonIndex].IsDown; GlobalInput.Controller.Buttons[ButtonIndex].IsDown = false; } // Controller input handeling. if (glfwJoystickPresent(GLFW_JOYSTICK_1)) { int countButtons; const unsigned char *button = glfwGetJoystickButtons(GLFW_JOYSTICK_1, &countButtons); for (int i = 0; i < countButtons; i++) { if (button[i] == GLFW_PRESS) { GlobalInput.Controller.Buttons[i].IsDown = true; } } int countAxes; const float *axes = glfwGetJoystickAxes(GLFW_JOYSTICK_1, &countAxes); for (int i = 0; i < countAxes; i++) { GlobalInput.Controller.Axes[i] = axes[i]; } } /* Poll for and process events */ glfwPollEvents(); if (gameState.State == 0) glfwSetWindowShouldClose(window, 1); /* Render here */ GameUpdateAndRender(&gameState, &GlobalInput, &List); float cameraPosX = gameState.PlayerX - 500; float cameraPosY = gameState.PlayerY - 400; glm::mat4 projection = glm::ortho(cameraPosX, cameraPosX + static_cast<GLfloat>(gameState.ScreenWidth), cameraPosY + static_cast<GLfloat>(gameState.ScreenHeight), cameraPosY, -1.0f, 1.0f); ResourceManager::GetShader("sprite").Use().SetInteger("image", 0); ResourceManager::GetShader("sprite").SetMatrix4("projection", projection); glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); while (!List.isEmpty) { RenderObject * obj = List.Pop(); Renderer->DrawSprite(ResourceManager::GetTexture(obj->name), obj->position, obj->scale, 0.0f, obj->color); free(obj); } AnimateRenderer->DrawSprite(ResourceManager::GetSpriteSheet("sonic"), glm::vec2(cameraPosX, cameraPosY), glm::vec2(64, 72), 0.0f, glm::vec3(1.0f, 1.0f, 1.0f), gameState.RenderState); /* Swap front and back buffers */ glfwSwapBuffers(window); } glfwTerminate(); return 0; }
int Game_Main(void *parms) { // this is the workhorse of your game it will be called // continuously in real-time this is like main() in C // all the calls for you game go here! // game logic here... // 计时 StartClock(); // 清屏 renderer.fillSurface(0); /***************************** 处理输入 *****************************/ static DWORD m_deltaTime; DWORD curTime = timeGetTime(); static DWORD lastTime = curTime; m_deltaTime = curTime - lastTime; lastTime = curTime; if (KEY_DOWN('W') || KEY_DOWN(VK_UP)) { Vector4 delta = Vector4(0, 0, 0.01f * m_deltaTime, 1); Matrix4 mrot = camera.MatrixCamera.inverse(); delta = delta * mrot; camera.position = delta; } if (KEY_DOWN('S') || KEY_DOWN(VK_DOWN)) { Vector4 delta = Vector4(0, 0, -0.01f * m_deltaTime, 1); Matrix4 mrot = camera.MatrixCamera.inverse(); delta = delta * mrot; camera.position = delta; } if (KEY_DOWN('A') || KEY_DOWN(VK_LEFT)) { Vector4 delta = Vector4(-0.01f * m_deltaTime, 0, 0, 1); Matrix4 mrot = camera.MatrixCamera.inverse(); delta = delta * mrot; camera.position = delta; } if (KEY_DOWN('D') || KEY_DOWN(VK_RIGHT)) { Vector4 delta = Vector4(0.01f * m_deltaTime, 0, 0, 1); Matrix4 mrot = camera.MatrixCamera.inverse(); delta = delta * mrot; camera.position = delta; } if (KEY_DOWN(VK_PRIOR)) { Vector4 delta = Vector4(0, -0.01f * m_deltaTime, 0, 1); Matrix4 mrot = camera.MatrixCamera.inverse(); delta = delta * mrot; camera.position = delta; } if (KEY_DOWN(VK_NEXT)) { Vector4 delta = Vector4(0, 0.01f * m_deltaTime, 0, 1); Matrix4 mrot = camera.MatrixCamera.inverse(); delta = delta * mrot; camera.position = delta; } static float ang; camera.CameraUpdateMatrix(); rend_list.ResetList(); // 表面加锁 renderer.lockSurface(); renderer.clearZBuffer(); //开始 if (rot_pause == 0){ ++ang; } if (ang >= 360) ang = 0; //foreach object { //g_Obj.ObjectWorldTransform(); // 每次旋转一下物体 Matrix4 mrot = Matrix4(Quaternion::Euler(0.0f, ang * kPi / 180, 0.0f * kPi / 180));//20.0f * kPi / 180 g_Obj.ObjectTransform(mrot, RENDER_TRANSFORM_LOCALTOTRANS, 0); g_Obj.ObjectWorldTransform(); } { //g_Obj.ObjectWorldTransform(); // 每次旋转一下物体 Matrix4 mrot = Matrix4(Quaternion::Euler(ang * kPi / 180, 0.0f, 0.0f));//20.0f * kPi / 180 g_Obj_c.ObjectTransform(mrot, RENDER_TRANSFORM_LOCALTOTRANS, 0); g_Obj_c.ObjectWorldTransform(); } { Matrix4 mrot = Matrix4(Quaternion::Euler(0.0f, 0.0f, ang * kPi / 180));//20.0f * kPi / 180 g_Obj_s.ObjectTransform(mrot, RENDER_TRANSFORM_LOCALTOTRANS, 0); g_Obj_s.ObjectWorldTransform(); } rend_list.InsertGameObject(g_Obj); rend_list.InsertGameObject(g_Obj_c); rend_list.InsertGameObject(g_Obj_s); // 背面消除 rend_list.DeleteBackface(camera); // 相机变换 rend_list.CameraTransform(camera); //剪裁 rend_list.ClipPoly(camera); // 光照 if (open_light == 1) { directional_light.LightTransform(camera.MatrixCamera); rend_list.ProcessLight(camera, ambient_light, directional_light); } // 投影变换 rend_list.ProjectTransform(camera); // 视口变换 rend_list.ScreenTransform(camera); draw_polys = renderer.drawRenderList(rend_list); // 表面解锁 renderer.unlockSurface(); // 输出 renderer.flipSurface(); // 锁帧 WaitClock(); // return success return(1); } // end Game_Main
void Graphics::Plot(HDC hdc, RenderList& renderList) { for (RenderList::iterator ite = renderList.begin(); ite != renderList.end(); ++ite) { if (!ite->TestState(TriangleStateInactive) && !ite->TestState(TriangleStateBackface) && !ite->TestState(TriangleStateClipped)) PlotTriangle(hdc, *ite); } }