Я попробовал tex2.setSmooth(false); и изменил альфа-значение для
sprite.setColor(sf::Color(shadeValue, shadeValue, shadeValue, 255));
В основном теряется, потому что стены и объекты визуализируются одинаково, но есть проблема только в одном направлении, а не в другом, см. код ниже.
Что я пытаюсь сделать:
рендерить все компоненты в этом порядке для моей функции рендеринга:
void TwoHalfD::Engine::render()
{
m_window.clear(sf::Color::Black);
m_renderTexture.clear(sf::Color::Transparent);
renderFloor();
renderWalls();
renderObjects();
m_renderTexture.display();
sf::Sprite sprite(m_renderTexture.getTexture());
sprite.setScale(static_cast(m_engineSettings.windowDim.x) / m_engineSettings.resolution.x,
static_cast(m_engineSettings.windowDim.y) / m_engineSettings.resolution.y);
m_window.draw(sprite);
m_window.display();
}
И стены, и объекты отображаются одинаково с помощью следующего фрагмента кода:
sf::Sprite sprite;
sprite.setTexture(tex);
sf::IntRect subRect(static_cast(texX), 0, sliceWidth, texSize.y);
sprite.setTextureRect(subRect);
sprite.setScale(1.0f, spriteHeightScreen / texSize.y);
sprite.setPosition(x * sliceWidth, topSpriteScreen);
float shade = std::min(1.0f, 256.0f / distToSprite);
sf::Uint8 shadeValue = static_cast(255 * shade);
sprite.setColor(sf::Color(shadeValue, shadeValue, shadeValue, 255));
m_renderTexture.draw(sprite);
Проблема, с которой я столкнулся:
Стены и пол обрабатывают спрайты, отображаемые спереди, нормально, а прозрачные части спрайта, которые я использую для проверки, не переопределяют пиксели позади них. Но спрайты, накладывающиеся друг на друга, имеют проблему: спрайты впереди «обрезают» спрайты позади, несмотря на то, что эта часть спрайта прозрачна.
Перекрытие вызывает проблемы с рендерингом:

Нет перекрытия – нет проблем:

Функция полного рендеринга объектов
void TwoHalfD::Engine::renderObjects()
{
float cameraDirRad = m_cameraObject.cameraPos.direction;
sf::Vector2f direction{std::cos(cameraDirRad), std::sin(cameraDirRad)};
sf::Vector2f plane{-direction.y * m_engineSettings.fovScale, direction.x * m_engineSettings.fovScale};
const float planeLen = std::sqrt(plane.x * plane.x + plane.y * plane.y);
const sf::Vector2f normalizedPlane = {plane.x / planeLen, plane.y / planeLen};
float focalLength = (m_engineSettings.resolution.x / 2.0f) / m_engineSettings.fovScale;
for (int x = 0; x < m_engineSettings.numRays; ++x)
{
float cameraX =
2.0f * x * (1.0f * m_engineSettings.resolution.x / m_engineSettings.numRays) / static_cast(m_engineSettings.resolution.x) - 1.0f;
sf::Vector2f rayDir = direction + plane * cameraX;
float rayLength = std::sqrt(rayDir.x * rayDir.x + rayDir.y * rayDir.y);
rayDir.x /= rayLength;
rayDir.y /= rayLength;
float rayDirX = rayDir.x;
float rayDirY = rayDir.y;
auto cmp = [](const auto &a, const auto &b) { return a.first < b.first; };
std::priority_queue
spriteOrderedDistance(cmp);
for (const auto &object : m_level.sprites)
{
if (object.textureId == -1)
continue;
// https://en.wikipedia.org/wiki/Line–line_intersection
const float x1 = m_cameraObject.cameraPos.pos.x, y1 = m_cameraObject.cameraPos.pos.y;
const float x2 = x1 + 1000.0f * rayDirX, y2 = y1 + 1000.0f * rayDirY;
const float x3 = object.pos.posf.x + object.radius * normalizedPlane.x, y3 = object.pos.posf.y + object.radius * normalizedPlane.y;
const float x4 = object.pos.posf.x - object.radius * normalizedPlane.x, y4 = object.pos.posf.y - object.radius * normalizedPlane.y;
float denom = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);
if (std::abs(denom) < 0.00001f)
continue;
float numeratorT = (x1 - x3) * (y3 - y4) - (y1 - y3) * (x3 - x4);
float numeratorU = -((x1 - x2) * (y1 - y3) - (y1 - y2) * (x1 - x3));
float t = numeratorT / denom;
float u = numeratorU / denom;
if (u < 0 || u > 1 || t < 0)
continue;
spriteOrderedDistance.push({t * 1000.0f, object});
}
while (!spriteOrderedDistance.empty())
{
const auto &distSpritePair = spriteOrderedDistance.top();
spriteOrderedDistance.pop();
const float distToSprite = distSpritePair.first;
const TwoHalfD::SpriteEntity currSprite = distSpritePair.second;
const auto &textureIt = m_textures.find(currSprite.textureId);
if (textureIt == m_textures.end())
{
exit(1);
}
const sf::Texture &tex = textureIt->second;
const sf::Vector2u texSize = tex.getSize();
float perpWorldDistance = distToSprite * (rayDirX * direction.x + rayDirY * direction.y);
const float bottomOfSpriteScreen = focalLength * m_cameraObject.cameraHeight / perpWorldDistance + m_engineSettings.resolution.y / 2.0f;
const float topSpriteScreen =
focalLength * (m_cameraObject.cameraHeight - currSprite.height) / perpWorldDistance + m_engineSettings.resolution.y / 2.0f;
const float spriteHeightScreen = bottomOfSpriteScreen - topSpriteScreen;
const sf::Vector2f spriteStartPos = {currSprite.pos.posf.x - currSprite.radius * normalizedPlane.x,
currSprite.pos.posf.y - currSprite.radius * normalizedPlane.y};
const sf::Vector2f spriteEndPos = {currSprite.pos.posf.x + currSprite.radius * normalizedPlane.x,
currSprite.pos.posf.y + currSprite.radius * normalizedPlane.y};
const float intersectX = m_cameraObject.cameraPos.pos.x + distToSprite * rayDirX;
const float intersectY = m_cameraObject.cameraPos.pos.y + distToSprite * rayDirY;
float spriteDirX = spriteEndPos.x - spriteStartPos.x;
float spriteDirY = spriteEndPos.y - spriteStartPos.y;
const float wallLen = std::sqrtf(spriteDirX * spriteDirX + spriteDirY * spriteDirY);
spriteDirX /= wallLen;
spriteDirY /= wallLen;
const float toIntersectX = intersectX - spriteStartPos.x;
const float toIntersectY = intersectY - spriteStartPos.y;
float lenToIntercept = toIntersectX * spriteDirX + toIntersectY * spriteDirY;
float texX = (lenToIntercept / (2.0f * currSprite.radius)) * texSize.x;
texX = std::max(0.0f, std::min(texX, static_cast(texSize.x - 1)));
int sliceWidth = m_engineSettings.resolution.x / m_engineSettings.numRays;
sf::Sprite sprite;
sprite.setTexture(tex);
sf::IntRect subRect(static_cast(texX), 0, sliceWidth, texSize.y);
sprite.setTextureRect(subRect);
sprite.setScale(1.0f, spriteHeightScreen / texSize.y);
sprite.setPosition(x * sliceWidth, topSpriteScreen);
float shade = std::min(1.0f, 256.0f / distToSprite);
sf::Uint8 shadeValue = static_cast(255 * shade);
sprite.setColor(sf::Color(shadeValue, shadeValue, shadeValue, 255));
m_renderTexture.draw(sprite);
}
}
}
Подробнее здесь: https://stackoverflow.com/questions/798 ... rlay-issue
Мобильная версия