[SFML] Cienie
Ostatnio zmodyfikowano 2014-07-19 12:25
unkn9wn Temat założony przez niniejszego użytkownika |
[SFML] Cienie » 2014-07-17 17:50:41 Witam, czy ktoś obeznany mógłby sprawdzić co mam źle, gdyż od kilku godzin nie mogę nic kontynuować próbuję stworzyć własne cienie dla obiektów ConvexShape według artykułu http://www.gamedev.net/page/resources/_/technical/graphics-programming-and-theory/dynamic-2d-soft-shadows-r2032i za nic nie mogę odnaleźć tych dwóch punktów prawidłowo, gdzie przy pierwszym zaczyna się cień, przy drugim kończy Opisane to zostało na strońce powyżej pt.: Finding the boundary points zacytuję Our first step is to determine which points our shadow should be cast from. The list of points that make up the ConvexHull is looped though, and each edge is classified in regard to the light position. In pseudo code: For every edge: *Find normal for edge< *Classify edge as front facing or back facing *Determine if either edge points are boundary points or not. The normal for the edge is found as:
float nx = currentPoint.y - prevPoint.y; float ny = currentPoint.x - prevPoint.x;
Then a dot product is performed with this vector and the vector to the light. If this is greater than zero, the edge is front facing. Once and edge has been classified, it is compared against the previous edge. If one is front facing and the other back facing, then the shared vertex is a boundary point. As we walk around the edge of the hull (in an anti-clockwise direction) the boundary point from light to shadow is the start shadow point. The boundary from shadow to light is the end shadow point. |
void Shadow::updateShadow( sf::ConvexShape object, sf::Vector2f lightSourcePos, float lightSourceRadius ) { std::vector < sf::Vector2f > realObjectPos; for( size_t i = 0; i < object.getPointCount(); i++ ) realObjectPos.push_back( object.getPosition() + object.getPoint( i ) ); int boundaryPoint1 = 0; int boundaryPoint2 = 0; float dotProduct; sf::Vector2f edgeNormal; sf::Vector2f lightDistanceFromPoint; bool frontFacing; bool prevFrontFacing; edgeNormal.x = realObjectPos[ 0 ].y - realObjectPos[ object.getPointCount() - 1 ].y; edgeNormal.y = realObjectPos[ 0 ].x - realObjectPos[ object.getPointCount() - 1 ].x; lightDistanceFromPoint = realObjectPos[ 0 ] - lightSourcePos; dotProduct =( edgeNormal.x * lightDistanceFromPoint.x ) +( edgeNormal.y * lightDistanceFromPoint.y ); if( dotProduct > 0 ) prevFrontFacing = true; else prevFrontFacing = false; for( int i = 0; i < object.getPointCount(); i++ ) { if( i == 0 ) { edgeNormal.x = realObjectPos[ 0 ].y - realObjectPos[ object.getPointCount() - 1 ].y; edgeNormal.y = realObjectPos[ 0 ].x - realObjectPos[ object.getPointCount() - 1 ].x; } else { edgeNormal.x = realObjectPos[ i ].y - realObjectPos[ i - 1 ].y; edgeNormal.y = realObjectPos[ i ].x - realObjectPos[ i - 1 ].x; } lightDistanceFromPoint = realObjectPos[ i ] - lightSourcePos; dotProduct =( edgeNormal.x * lightDistanceFromPoint.x ) +( edgeNormal.y * lightDistanceFromPoint.y ); if( dotProduct > 0 ) { frontFacing = true; if( !prevFrontFacing && frontFacing ) boundaryPoint2 = i; } else { frontFacing = false; if( prevFrontFacing && !frontFacing ) boundaryPoint1 = i; } prevFrontFacing = frontFacing; } } # poprawiłem kilka zmiennych, gdyż ConvexShape::getPoint() nie zwraca pozycji na ekranie jak miałem przedtem. Teraz przynajmniej zmieniają się odpowiednio wartości boundaryPoint1 i boundaryPoint2, gdy namierzam źródłem światła z różnych stron, tyle że są one złe |
|
unkn9wn Temat założony przez niniejszego użytkownika |
» 2014-07-18 13:20:01 Problem rozwiązany
float nx = currentPoint.y - prevPoint.y; float ny = currentPoint.x - prevPoint.x;
| błąd autora artykułu?
zmieniłem na
float nx = currentPoint.x - prevPoint.x; float ny = currentPoint.y - prevPoint.y; i o dziwo cienie rysują się tak jak powinny, choć muszę poprawić rysowanie wielokątów. Na razie efekt działa poprawnie na czworokącie
efekt w gif'ie : http://mkerala.com/n/di/TTJ0/capture2.gif |
|
arczi14 |
» 2014-07-18 14:13:46 Dzięki za artykuł z pewnością skorzystam :D |
|
unkn9wn Temat założony przez niniejszego użytkownika |
» 2014-07-19 12:25:30 Jednak błąd miałem u siebie, a to że się prawidłowo narysował cień - czysty przypadek Dodaję prawidłowy kod do rysowania cienia ConvexShape'a, z jakąkolwiek liczbą wierzchołków (oczywiście większą niż 0). Być może ktoś skorzysta. potrzebna deklaracja cienia - sf::VertexArray shadow(sf::TrianglesStrip); void Shadow::updateShadow( sf::ConvexShape & object, sf::Vector2f lightSourcePos ) { int totalVerticesCount = object.getPointCount(); std::vector < sf::Vector2f > realVertexPos; for( size_t i = 0; i < object.getPointCount(); i++ ) realVertexPos.push_back( object.getPosition() + object.getPoint( i ) ); float dotProduct; sf::Vector2f edgeMiddle; sf::Vector2f edgeNormal; sf::Vector2f lightDistanceFromEdgeM; sf::Vector2f currentVertex; sf::Vector2f nextVertex; std::vector < bool > backFacingEdge; backFacingEdge.resize( totalVerticesCount ); int backFacingEdgesCount = 0; for( int i = 0; i < totalVerticesCount; i++ ) { currentVertex = realVertexPos[ i ]; nextVertex = realVertexPos[( i + 1 ) % totalVerticesCount ]; edgeMiddle = sf::Vector2f(( currentVertex.x + nextVertex.x ) / 2,( currentVertex.y + nextVertex.y ) / 2 ); edgeNormal.x = -( nextVertex.y - currentVertex.y ); edgeNormal.y = nextVertex.x - currentVertex.x; lightDistanceFromEdgeM = lightSourcePos - edgeMiddle; dotProduct =( edgeNormal.x * lightDistanceFromEdgeM.x ) +( edgeNormal.y * lightDistanceFromEdgeM.y ); if( dotProduct > 0 ) { backFacingEdge[ i ] = false; backFacingEdgesCount++; } else { backFacingEdge[ i ] = true; } } int boundaryPointFirst = 0; int boundaryPointSecond = 0; int currentEdge; int nextEdge; for( int i = 0; i < totalVerticesCount; i++ ) { currentEdge = i; nextEdge =( i + 1 ) % totalVerticesCount; if( backFacingEdge[ currentEdge ] && !backFacingEdge[ nextEdge ] ) boundaryPointSecond = nextEdge; if( !backFacingEdge[ currentEdge ] && backFacingEdge[ nextEdge ] ) boundaryPointFirst = nextEdge; } int shadowPointsCount; shadowPointsCount = backFacingEdgesCount * 2 + 2; shadow.resize( shadowPointsCount ); int currentShadowPoint = boundaryPointFirst; int shadowNum = 0; while( shadowNum < shadowPointsCount ) { if( currentShadowPoint < 0 ) currentShadowPoint = object.getPointCount() - 1; shadow[ shadowNum ].texCoords = shadow[ shadowNum ].position = realVertexPos[ currentShadowPoint ]; shadow[ shadowNum ].color = sf::Color( 0, 0, 0, 0 ); shadowNum++; shadow[ shadowNum ].texCoords = shadow[ shadowNum ].position = realVertexPos[ currentShadowPoint ] +( realVertexPos[ currentShadowPoint ] - lightSourcePos ) +( realVertexPos[ currentShadowPoint ] - lightSourcePos ); shadow[ shadowNum ].color = sf::Color( 0, 0, 0, 0 ); shadowNum++; currentShadowPoint--; } } |
|
« 1 » |