Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[SFML 2.X] Cienie w grze 2D RPG

Ostatnio zmodyfikowano 2024-11-21 00:22
Autor Wiadomość
tBane
Temat założony przez niniejszego użytkownika
» 2024-11-20 12:04:32
Hej! To znowu ja :-)
Nie podobają mi sie cienie, które generuje w grze. Szukałem jakichś poradników w internecie i nic poza kilkoma metodami generowania cienia w 3D nie znalazłem, ChatGPT również mi nie pomógł, stąd znowu się do Was zwracam. Nie wiem jak zrobić "dobre cienie". Próbowałem je generować na podstawie sf::Sprite ale za bardzo mi nie wyszło. Jak więc generować poprawnie cienie w grze tak by wyglądały naturalniej ? Może jakiś shader ? Tylko jak sie za to zabrać ?


Kod dla tych, którym jednak te cienie się podobają:

C/C++
shadow = sf::Sprite();
shadow.setTexture( * texshadow );
shadow.setColor( sf::Color( 0, 0, 0, 48 ) );
shadow.setOrigin( tex->getSize().x / 2, tex->getSize().y );
float angle = 52.0f * M_PI / 180.0f;
float shadowlen = collider->height * tan( angle );
sf::Vector2f scale( 1.1f, shadowlen / collider->height );
shadow.setScale( scale );
shadow.setPosition( position );
P-181934
tBane
Temat założony przez niniejszego użytkownika
» 2024-11-20 12:25:25
Znalazłem coś takiego. Może to mógłbym wykorzystać do mojej gry. Tylko jak zacząć ? sf::Sprite.getTexture() + Shader ? I jakie proporcje cienia ?
https://youtu.be/XxBZw2FEdK0?si=Tsu48hIdLDxdgSaY&t=297
P-181935
tBane
Temat założony przez niniejszego użytkownika
» 2024-11-20 17:04:25
Przepisałem ten shader z GitHuba ale nie działa tak jak powinien. Byłbym wdzięczny gdyby ktoś mi pomógł a jak nie to nie dodam cieni do gry - w końcu to moja pierwsza gra :P

// shadow.frag
uniform sampler2D texture;
uniform vec2 resolution;
uniform float time;
varying vec2 worldPos;
uniform vec2 camPosition;

void main()
{
    vec2 uv = gl_FragCoord.xy/resolution;
    vec2 u_cam = camPosition/resolution;
    u_cam = 1.0 - u_cam;
    vec4 pixel = texture2D(texture, gl_TexCoord[0].xy);
    float circle = 1.0 - length(uv-u_cam)*10.0;
    gl_FragColor = (0.1, 0.1, 0.1, circle*(1.0-pixel.y)*1.35);
}

Edit //
W sporadycznym przypadku działa jako tako ale nie rozumiem dlaczego tak a nie inaczej.
P-181936
pekfos
» 2024-11-20 19:14:30
Co w ogóle chcesz osiągnąć? Cienie nie wyglądały naturalnie bo wyglądały jakby każdy obiekt był oświetlony tylko i wyłącznie przez światło punktowe tuż przed nim. Nie napisałeś jakie oświetlenie chcesz uzyskać, a jak sam tego nie wiesz to skończysz w punkcie wyjścia. Shader który znalazłeś zakłada że widok jest z góry, co nie jest grą którą robisz. W twoim przypadku najwięcej sensu ma jedno odległe światło punktowe (słońce?), gdzie kąt padania jest minimalnie odchylony od osi Y ekranu. To możesz dalej zrobić na sprajtach. Odległe światło sprawia że kąty padania wszystkich promieni są równoległe do siebie, więc nie robisz powiększenia cienia względem obiektu. Umieść cień tuż za obiektem i odrobinę w bok, dosłownie plus minus kilkanaście pikseli. Nie robiąc nic specjalnego masz rozsądne przybliżenie rzeczywistości. Jeżeli cień wystawałby bardziej, bo słońce jest nisko, to powinien być rozciągnięty a nie po prostu większy. A jak słońce będzie oświetlać obiekty za bardzo z boku, to wtedy zaczynasz pokazywać niemożliwą geometrię i realizm wylatuje przez okno. Teraz masz do dyspozycji tylko informację jak obiekt wygląda prosto z przodu, a pod większym kątem cienia będziesz potrzebować sylwetkę obiektu z profilu, a tej informacji nie masz w ogóle i shader w tym nie pomoże.
Możesz sobie w Blenderze zrobić makietę i zobaczyć jak cienie wyglądają pod różnymi kątami. Przykładowo:
P-181937
tBane
Temat założony przez niniejszego użytkownika
» 2024-11-20 23:44:15
No i właśnie coś takiego jak na 1 chcę zrobić
P-181938
DejaVu
» 2024-11-21 00:22:19
GPT 4o input:
kontekst: C++ SFML, Sprajty 2D i robienie cieni.
Załóżmy, ze sprajt jest prostokątem. Mam obliczony już jego cień (czy tam zrobioną po prostu maskę cienia, która ma taki sam kształt jak obiekt z odpowiednim kanałem alfa). Czy da się narysować tą maskę na 'kopniętym' prostokącie w łatwy sposób? chodzi mi o to, że dolna krawędź ma być na tej samej pozycji co 'oryginalny obiekt', a górna krawędź ma być przesunięta np. o 3 stopnie (taki kopnięty prostokąt).

GPT 4o output:
Tak, można narysować cień na "kopniętym" prostokącie w SFML, korzystając z transformacji obiektu typu `sf::VertexArray`. W SFML można definiować własne kształty poprzez wierzchołki (`sf::Vertex`), co pozwala na tworzenie nieregularnych kształtów.

Oto jak możesz to zrobić:

### 1. Przygotowanie maski cienia
Załóżmy, że masz już gotową teksturę maski cienia. Możesz wykorzystać `sf::VertexArray` w trybie `sf::Quads`, aby przekształcić kształt prostokąta na "kopnięty".

### 2. Kod źródłowy

C/C++
#include <SFML/Graphics.hpp>
#include <cmath>

int main() {
   
sf::RenderWindow window( sf::VideoMode( 800, 600 ), "Shadow Example" );
   
   
// Tekstura obiektu (opcjonalnie)
   
sf::Texture objectTexture;
   
objectTexture.loadFromFile( "object.png" ); // Zakładamy, że masz teksturę obiektu
   
   
sf::Sprite objectSprite( objectTexture );
   
objectSprite.setPosition( 400, 300 );
   
   
// Tekstura maski cienia
   
sf::Texture shadowTexture;
   
shadowTexture.loadFromFile( "shadow.png" ); // Tekstura maski cienia
   
   
sf::VertexArray shadowQuad( sf::Quads, 4 );
   
   
// Wymiary prostokąta i przesunięcie górnej krawędzi
   
sf::Vector2f size( objectTexture.getSize().x, objectTexture.getSize().y );
   
float skewOffset = 50.f; // Przesunięcie górnej krawędzi (kopnięcie)
   
    // Definiowanie wierzchołków cienia
   
sf::Vector2f position = objectSprite.getPosition();
   
shadowQuad[ 0 ].position = position; // Dolny lewy
   
shadowQuad[ 1 ].position = position + sf::Vector2f( size.x, 0 ); // Dolny prawy
   
shadowQuad[ 2 ].position = position + sf::Vector2f( size.x + skewOffset, - size.y ); // Górny prawy (kopnięty)
   
shadowQuad[ 3 ].position = position + sf::Vector2f( skewOffset, - size.y ); // Górny lewy (kopnięty)
   
    // Mapowanie tekstury
   
shadowQuad[ 0 ].texCoords = sf::Vector2f( 0, size.y ); // Dolny lewy
   
shadowQuad[ 1 ].texCoords = sf::Vector2f( size.x, size.y ); // Dolny prawy
   
shadowQuad[ 2 ].texCoords = sf::Vector2f( size.x, 0 ); // Górny prawy
   
shadowQuad[ 3 ].texCoords = sf::Vector2f( 0, 0 ); // Górny lewy
   
    // Główna pętla aplikacji
   
while( window.isOpen() ) {
       
sf::Event event;
       
while( window.pollEvent( event ) ) {
           
if( event.type == sf::Event::Closed )
               
 window.close();
           
       
}
       
       
window.clear();
       
       
// Rysowanie obiektu
       
window.draw( objectSprite );
       
       
// Rysowanie cienia
       
sf::RenderStates shadowState;
       
shadowState.texture = & shadowTexture;
       
window.draw( shadowQuad, shadowState );
       
       
window.display();
   
}
   
   
return 0;
}

### Wyjaśnienie
1. **VertexArray w trybie Quads**:
   - `sf::VertexArray` zawiera cztery wierzchołki, które definiują kształt prostokąta.
   - Przesunięcie górnych wierzchołków (`skewOffset`) tworzy "kopnięcie".

2. **Mapowanie tekstury**:
   - Wierzchołki tekstury (`texCoords`) dopasowują teksturę maski cienia do odpowiednich wierzchołków kształtu.

3. **RenderStates**:
   - `sf::RenderStates` pozwala na przypisanie tekstury do nieregularnego kształtu.

### Efekt
Uzyskasz prostokątną maskę cienia z "kopnięciem" górnej krawędzi w prawo. Możesz dostosować `skewOffset`, aby osiągnąć różne kąty i przesunięcia.
P-181939
1 « 2 »
Poprzednia strona Strona 2 z 2