PainterOGL2::PainterOGL2() { m_drawProgram = nullptr; resetState(); m_drawTexturedProgram = PainterShaderProgramPtr(new PainterShaderProgram); assert(m_drawTexturedProgram); m_drawTexturedProgram->addShaderFromSourceCode(Shader::Vertex, glslMainWithTexCoordsVertexShader + glslPositionOnlyVertexShader); m_drawTexturedProgram->addShaderFromSourceCode(Shader::Fragment, glslMainFragmentShader + glslTextureSrcFragmentShader); m_drawTexturedProgram->link(); m_drawSolidColorProgram = PainterShaderProgramPtr(new PainterShaderProgram); assert(m_drawSolidColorProgram); m_drawSolidColorProgram->addShaderFromSourceCode(Shader::Vertex, glslMainVertexShader + glslPositionOnlyVertexShader); m_drawSolidColorProgram->addShaderFromSourceCode(Shader::Fragment, glslMainFragmentShader + glslSolidColorFragmentShader); m_drawSolidColorProgram->link(); PainterShaderProgram::release(); }
void Map::draw(const Rect& rect) { if(!m_framebuffer) { m_framebuffer = FrameBufferPtr(new FrameBuffer(m_visibleSize.width() * NUM_TILE_PIXELS, m_visibleSize.height() * NUM_TILE_PIXELS)); program = PainterShaderProgramPtr(new PainterShaderProgram); program->addShaderFromSourceCode(Shader::Vertex, glslMainWithTexCoordsVertexShader + glslPositionOnlyVertexShader); program->addShaderFromSourceFile(Shader::Fragment, "/shadertest.frag"); assert(program->link()); } g_painter.setColor(Fw::white); m_framebuffer->bind(); // draw offsets LocalPlayerPtr localPlayer = g_game.getLocalPlayer(); if(localPlayer) m_drawOffset = localPlayer->getWalkOffset(); //TODO: cache first/last visible floor // draw from bottom floors to top floors int firstFloor = getFirstVisibleFloor(); const int lastFloor = MAX_Z-1; for(int iz = lastFloor; iz >= firstFloor; --iz) { // draw tiles like linus pauling's rule order const int numDiagonals = m_size.width() + m_size.height() - 1; for(int diagonal = 0; diagonal < numDiagonals; ++diagonal) { // loop through / diagonal tiles for(int ix = std::min(diagonal, m_size.width() - 1), iy = std::max(diagonal - m_size.width(), 0); ix >= 0 && iy < m_size.height(); --ix, ++iy) { // position on current floor Position tilePos(m_centralPosition.x + (ix - m_centralOffset.x), m_centralPosition.y + (iy - m_centralOffset.y), m_centralPosition.z); // adjust tilePos to the wanted floor tilePos.perspectiveUp(m_centralPosition.z - iz); //TODO: cache visible tiles, m_tiles[] has a high cost (50% fps decrease) if(const TilePtr& tile = m_tiles[tilePos]) { // skip tiles that are behind another tile //if(isCompletlyCovered(tilePos, firstFloor)) // continue; tile->draw(positionTo2D(tilePos) - m_drawOffset); } } } // after drawing all tiles, draw shots for(const MissilePtr& shot : m_missilesAtFloor[iz]) { Position missilePos = shot->getPosition(); shot->draw(positionTo2D(missilePos) - m_drawOffset); } } m_framebuffer->release(); g_painter.setCustomProgram(program); g_painter.setColor(Fw::white); m_framebuffer->draw(rect); g_painter.releaseCustomProgram(); // calculate stretch factor float horizontalStretchFactor = rect.width() / (float)(m_visibleSize.width() * NUM_TILE_PIXELS); float verticalStretchFactor = rect.height() / (float)(m_visibleSize.height() * NUM_TILE_PIXELS); // draw player names and health bars //TODO: this must be cached with creature walks for(int x = 0; x < m_visibleSize.width(); ++x) { for(int y = 0; y < m_visibleSize.height(); ++y) { Position tilePos = Position(m_centralPosition.x + (x - m_centralOffset.x + 1), m_centralPosition.y + (y - m_centralOffset.y + 1), m_centralPosition.z); if(const TilePtr& tile = m_tiles[tilePos]) { auto creatures = tile->getCreatures(); if(creatures.size() == 0) continue; for(const CreaturePtr& creature : creatures) { Point p((m_centralOffset.x - 1 + (tilePos.x - m_centralPosition.x))*NUM_TILE_PIXELS + 10 - tile->getDrawElevation(), (m_centralOffset.y - 1 + (tilePos.y - m_centralPosition.y))*NUM_TILE_PIXELS - 10 - tile->getDrawElevation()); if(creature != localPlayer) { p += creature->getWalkOffset() - m_drawOffset; } creature->drawInformation(rect.x() + p.x*horizontalStretchFactor, rect.y() + p.y*verticalStretchFactor, isCovered(tilePos, firstFloor), rect); } } } } }
PainterShaderProgramPtr PainterShaderManager::createShader() { if(!g_graphics.canUseShaders()) return nullptr; return PainterShaderProgramPtr(new PainterShaderProgram); }
void Creature::draw(const Point& p, const Rect&) { if(m_showVolatileSquare) { g_painter.setColor(m_volatileSquareColor); g_painter.drawBoundingRect(Rect(p + m_walkOffset - Point(m_type->parameters[ThingType::DisplacementX], m_type->parameters[ThingType::DisplacementY]) + 3, Size(28, 28)), 2); } if(m_showStaticSquare) { g_painter.setColor(m_staticSquareColor); g_painter.drawBoundingRect(Rect(p + m_walkOffset - Point(m_type->parameters[ThingType::DisplacementX], m_type->parameters[ThingType::DisplacementY]) + 1, Size(32, 32)), 2); } g_painter.setColor(Fw::white); if(!outfitProgram) { outfitProgram = PainterShaderProgramPtr(new PainterShaderProgram); outfitProgram->addShaderFromSourceCode(Shader::Vertex, glslMainWithTexCoordsVertexShader + glslPositionOnlyVertexShader); outfitProgram->addShaderFromSourceFile(Shader::Fragment, "/game_shaders/outfit.frag"); assert(outfitProgram->link()); outfitProgram->bindUniformLocation(HEAD_COLOR_UNIFORM, "headColor"); outfitProgram->bindUniformLocation(BODY_COLOR_UNIFORM, "bodyColor"); outfitProgram->bindUniformLocation(LEGS_COLOR_UNIFORM, "legsColor"); outfitProgram->bindUniformLocation(FEET_COLOR_UNIFORM, "feetColor"); outfitProgram->bindUniformLocation(MASK_TEXTURE_UNIFORM, "maskTexture"); } // Render creature if(m_outfit.getCategory() == ThingsType::Creature) { for(m_yPattern = 0; m_yPattern < m_type->dimensions[ThingType::PatternY]; m_yPattern++) { // continue if we dont have this addon. if(m_yPattern > 0 && !(m_outfit.getAddons() & (1 << (m_yPattern-1)))) continue; g_painter.setCustomProgram(outfitProgram); outfitProgram->bind(); outfitProgram->setUniformValue(HEAD_COLOR_UNIFORM, m_outfit.getHeadColor()); outfitProgram->setUniformValue(BODY_COLOR_UNIFORM, m_outfit.getBodyColor()); outfitProgram->setUniformValue(LEGS_COLOR_UNIFORM, m_outfit.getLegsColor()); outfitProgram->setUniformValue(FEET_COLOR_UNIFORM, m_outfit.getFeetColor()); for(int h = 0; h < m_type->dimensions[ThingType::Height]; h++) { for(int w = 0; w < m_type->dimensions[ThingType::Width]; w++) { int spriteId = m_type->getSpriteId(w, h, 0, m_xPattern, m_yPattern, m_zPattern, m_animation); if(!spriteId) continue; TexturePtr spriteTex = g_sprites.getSpriteTexture(spriteId); if(!spriteTex) continue; if(m_type->dimensions[ThingType::Layers] > 1) { int maskId = m_type->getSpriteId(w, h, 1, m_xPattern, m_yPattern, m_zPattern, m_animation); TexturePtr maskTex = g_sprites.getSpriteTexture(maskId); outfitProgram->setUniformTexture(MASK_TEXTURE_UNIFORM, maskTex, 1); } Rect drawRect(((p + m_walkOffset).x - w*32) - m_type->parameters[ThingType::DisplacementX], ((p + m_walkOffset).y - h*32) - m_type->parameters[ThingType::DisplacementY], 32, 32); g_painter.drawTexturedRect(drawRect, spriteTex); } } g_painter.releaseCustomProgram(); } } else if(m_outfit.getCategory() == ThingsType::Item) { for(int l = 0; l < m_type->dimensions[ThingType::Layers]; l++) internalDraw(p + m_walkOffset, l); } else if(m_outfit.getCategory() == ThingsType::Effect) internalDraw(p + m_walkOffset, 0); }
void Creature::draw(const Point& p) { // TODO: activate on attack, follow, discover how 'attacked' works if(m_showSquareColor) { g_painter.setColor(Outfit::getColor(m_squareColor)); g_painter.drawBoundingRect(Rect(p + m_walkOffset - 8, Size(32, 32)), 2); } if(!outfitProgram) { outfitProgram = PainterShaderProgramPtr(new PainterShaderProgram); outfitProgram->addShaderFromSourceCode(Shader::Vertex, glslMainWithTexCoordsVertexShader + glslPositionOnlyVertexShader); outfitProgram->addShaderFromSourceFile(Shader::Fragment, "/outfit.frag"); assert(outfitProgram->link()); outfitProgram->bindUniformLocation(HEAD_COLOR_UNIFORM, "headColor"); outfitProgram->bindUniformLocation(BODY_COLOR_UNIFORM, "bodyColor"); outfitProgram->bindUniformLocation(LEGS_COLOR_UNIFORM, "legsColor"); outfitProgram->bindUniformLocation(FEET_COLOR_UNIFORM, "feetColor"); outfitProgram->bindUniformLocation(MASK_TEXTURE_UNIFORM, "maskTexture"); } // Render creature for(m_yPattern = 0; m_yPattern < m_type->dimensions[ThingType::PatternY]; m_yPattern++) { // continue if we dont have this addon. if(m_yPattern > 0 && !(m_outfit.getAddons() & (1 << (m_yPattern-1)))) continue; g_painter.setCustomProgram(outfitProgram); outfitProgram->bind(); outfitProgram->setUniformValue(HEAD_COLOR_UNIFORM, m_outfit.getHeadColor()); outfitProgram->setUniformValue(BODY_COLOR_UNIFORM, m_outfit.getBodyColor()); outfitProgram->setUniformValue(LEGS_COLOR_UNIFORM, m_outfit.getLegsColor()); outfitProgram->setUniformValue(FEET_COLOR_UNIFORM, m_outfit.getFeetColor()); for(int yi = 0; yi < m_type->dimensions[ThingType::Height]; yi++) { for(int xi = 0; xi < m_type->dimensions[ThingType::Width]; xi++) { int sprIndex = ((((((m_animation % m_type->dimensions[ThingType::AnimationPhases]) * m_type->dimensions[ThingType::PatternZ] + m_zPattern) * m_type->dimensions[ThingType::PatternY] + m_yPattern) * m_type->dimensions[ThingType::PatternX] + m_xPattern) * m_type->dimensions[ThingType::Layers] + 0) * m_type->dimensions[ThingType::Height] + yi) * m_type->dimensions[ThingType::Width] + xi; if(m_type->dimensions[ThingType::Layers] > 1) { int maskIndex = ((((((m_animation % m_type->dimensions[ThingType::AnimationPhases]) * m_type->dimensions[ThingType::PatternZ] + m_zPattern) * m_type->dimensions[ThingType::PatternY] + m_yPattern) * m_type->dimensions[ThingType::PatternX] + m_xPattern) * m_type->dimensions[ThingType::Layers] + 1) * m_type->dimensions[ThingType::Height] + yi) * m_type->dimensions[ThingType::Width] + xi; int spriteId = m_type->sprites[maskIndex]; if(!spriteId) continue; TexturePtr maskTex = g_sprites.getSpriteTexture(spriteId); outfitProgram->setUniformTexture(MASK_TEXTURE_UNIFORM, maskTex, 1); } int spriteId = m_type->sprites[sprIndex]; if(!spriteId) continue; TexturePtr spriteTex = g_sprites.getSpriteTexture(spriteId); Rect drawRect(((p + m_walkOffset).x - xi*32) - m_type->parameters[ThingType::DisplacementX], ((p + m_walkOffset).y - yi*32) - m_type->parameters[ThingType::DisplacementY], 32, 32); g_painter.drawTexturedRect(drawRect, spriteTex); } } g_painter.releaseCustomProgram(); } }