Problem mit dem transparenten Sprite-Rendering-Overlay von SMFL PNGC++

Programme in C++. Entwicklerforum
Anonymous
 Problem mit dem transparenten Sprite-Rendering-Overlay von SMFL PNG

Post by Anonymous »

Ich mache ein Spiel im Raycast-Stil und habe die meisten Rendering-Sachen herausgefunden. Ich habe derzeit einen Fehler/ein Problem in meinem Code und kann nicht herausfinden, warum.
Ich habe tex2.setSmooth(false); ausprobiert und den Alphawert für
geändert

Code: Select all

sprite.setColor(sf::Color(shadeValue, shadeValue, shadeValue, 255));
Meistens verloren, weil die Wände und Objekte gleich gerendert werden, aber es gibt nur ein Problem in einer Richtung und nicht in der anderen, siehe Code unten.
Was versuche ich zu tun:
Alle Komponenten in dieser Reihenfolge für meine Renderfunktion rendern:

Code: Select all

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();
}
Wände und Objekte werden mit dem folgenden Codeausschnitt gleich gerendert:

Code: Select all

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);
Das Problem, auf das ich stoße:
Wände und der Boden bewältigen die Sprites, die vorne gerendert werden, einwandfrei, wobei die transparenten Teile des Sprites, die ich zum Testen verwende, die Pixel dahinter nicht überschreiben. Aber die Sprites, die sich überlagern, haben das Problem, dass Sprites vorne Sprites dahinter „abschneiden“, obwohl dieser Teil des Sprites transparent ist.
Überlappung verursacht Rendering-Probleme:
Image

Keine Überlappung – nein Probleme:
Image

Vollständige Funktion zum Rendern von Objekten

Code: Select all

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);
}
}
}

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post