2017-01-27 4 views
0

약간의 조명 쉐이더를 만들기 위해 노력해 왔습니다. 완벽하게 작동합니다. 즉, 빛이 사라져야한다는 것을 의미합니다. 내 캐릭터가 움직이는 주위의 원입니다. 크기 조정 이벤트가없는 경우에만 완벽 할 수 있습니다.창 크기를 조정할 때 조명 쉐이더가 이동했습니다.

SFML이 창 크기를 조정하면 모든 것이 확대되지만 이상한 모양이됩니다. 하지만 쉐이더는으로 확대되었습니다. 내 창 크기를 조정하려고했는데 (픽셀 그래프 게임의 크기를 조정하는 것이 가장 좋았습니다. 그래서 크기 조정 이벤트를 방지하고 싶지는 않습니다.) (32 × 32 텍스처에 맞게)

uniform vec3 light; 

void main(void) { 
    float distance = sqrt(pow(gl_FragCoord.x - light.x, 2) + pow(gl_FragCoord.y - light.y, 2)); 
    float alpha = 1.; 

    if (distance <= light.z) { 
     alpha = (1.0/light.z) * distance; 
    } 
    gl_FragColor = vec4(0., 0., 0., alpha); 

} 

그래서, 문제가, 내 윈도우 1280 X 736에서 보여되고, 나는 1920 × 1080 모니터를 가지고 :

여기 내 쉐이더입니다. 1920 x 1080 (제목 표시 줄 포함)에 맞게 창을 확대하면 모든 것이 올바르게 조정되지만 모든 것이 잘되지만 셰이더는 1920x1080 (제목 표시 줄 빼기)입니다. 따라서 셰이더에는 다른 좌표가 필요합니다 (x = 32, y = 0은 셰이더의 경우 x = 48 y = 0).

전체 창으로 쉐이더를 확대 할 수 있습니까? 이벤트 나 그와 비슷한 것을 사용해야합니까?

귀하의 답변을 주셔서 감사합니다 ^^

편집 : 여기 일부 사진 : 그것은 크기를 조정하기 전에 Before 그래서이 빛 쉐이더입니다 (해야하는데 것처럼, 사방하지만 플레이어에 어두운). After 그런 다음 창 크기를 조정하고 플레이어가 움직이지 않고 텍스처가 전체 창에 맞지만 조명이 움직입니다.

올바르게 설명하기 위해 창 크기를 조정할 때 모든 것이 창에 딱 들어 맞기 때문에 텍스처가 가득 찼습니다.하지만 그렇게하면 셰이더에 지정된 좌표가 크기 조정 전의 좌표가됩니다. 창 크기를 조정하지 않은 것처럼 움직여서 플레이어의 빛이 다시는 나오지 않습니다.

잘 모르겠지만 최선을 다했습니다.

EDIT2가 : 정말에만 쉐이더 좌표를 업데이트

void Graphics::UpdateLight() { 
    short radius = 65; // 265 on the pictures 

    int x = m_game->GetPlayer()->GetSprite()->getPosition().x + CASE_LEN/2; // Setting on the middle of the player sprite (CASE_LEN is a const which contains the size of a case (here 32)) 
    int y = HEIGHT - (m_game->GetPlayer()->GetSprite()->getPosition().y + CASE_LEN/2); // (the "HEIGHT -" part was set because it seems that y = 0 is on the bottom of the texture for GLSL) 

    sf::Vector3f shaderLight; 
    shaderLight.x = x; 
    shaderLight.y = y; 
    shaderLight.z = radius; 

    m_lightShader.setParameter("light", shaderLight); 
} 
+0

귀하의 설명을 이해하기 힘들었습니다. 그러나 정규화 된 장치 좌표 또는 창 해상도에 종속되지 않는 다른 종류의 좌표 대신 창 좌표 (gl_FragCoord)를 사용하기 때문에 확장이 잘되지 않는 것이 분명합니다. 버텍스 쉐이더에서 NDC를 가져 오거나 gl_FragCoord를 윈도우 해상도로 나눕니다 (유니폼 변수에서 가져옴) – dv1729

+0

어떤 부분을 이해하지 못했습니까? 나는 그것을 명확히하려고 노력할 수있다. ^^ ' 글쎄, 나는 버텍스 쉐이더를 사용하지 않는다, 나는 오직 frag 쉐이더만을 사용한다. (나는 glsl에 매우 익숙하다, 미안 : c) – FeelZoR

+0

나는 당신이 무엇을하려고하는지 분명히 이해하지 못한다. 이 화소 예술인가? 사진을 제공 할 수 있습니까? 서로 다른 윈도우 해상도를 정확하게 처리하려면 어떻게해야합니까? 1024x1024 창은 512x512 창과 정확히 같아야합니까? 또는 그것의 1/4 부분이어야 하는가? – dv1729

답변

1

코드는 당신이 보여주는 것 니펫을 (그리고 빠른 엿볼에서 잘 보이는) : 여기에 쉐이더를 호출 내 코드입니다. 버그는 실제로 당신이 실제로 그림을 그리는 곳에서 일어날 가능성이 큽니다. 여러 등 것들, 다른 광원과 같은

내가 당신을 건의 할 것입니다 렌더링하고 한 번 쉐이더 접근 방식은 오히려 지루한 얻을 수 있기 때문에


나는 완전히 다른 접근 방식을 사용하십시오 렌더링 텍스처에 라이트 맵을 렌더링합니다 (기본적으로 "검은 색 = 빛 없음, 색상 = 해당 색상의 빛"과 같음).

텍스트로 모든 것을 설명하려고하는 것이 아니라 화면에 창을 그려 배경 이미지 위에 광원을 옮기는 간단한 주석 프로그램을 작성했습니다 (SFML의 쉐이더와 함께 제공되는 것을 사용했습니다). 예) :

Screenshot of the example code in action

시동 경로에 "background.jpg"라는 파일을 가지고 이외의 다른 요구 사항이 없습니다.

이 코드를 복사하거나 영감을 얻고 자유롭게 사용하십시오. 이것이 최적화되지 않았으며 일반적인 아이디어를 보여주기위한 간단한 편집 만한다는 것을 명심하십시오.

#include <SFML/Graphics.hpp> 
#include <vector> 
#include <cmath> 

const float PI = 3.1415f; 

struct Light 
{ 
    sf::Vector2f position; 
    sf::Color color; 
    float radius; 
}; 

int main() 
{ 
    // Let's setup a window 
    sf::RenderWindow window(sf::VideoMode(640, 480), "SFML Lights"); 
    window.setVerticalSyncEnabled(false); 
    window.setFramerateLimit(60); 

    // Create something simple to draw 
    sf::Texture texture; 
    texture.loadFromFile("background.jpg"); 
    sf::Sprite background(texture); 

    // Setup everything for the lightmap 
    sf::RenderTexture lightmapTex; 
    // We're using a 512x512 render texture for max. compatibility 
    // On modern hardware it could match the window resolution of course 
    lightmapTex.create(512, 512); 
    sf::Sprite lightmap(lightmapTex.getTexture()); 
    // Scale the sprite to fill the window 
    lightmap.setScale(640/512.f, 480/512.f); 
    // Set the lightmap's view to the same as the window 
    lightmapTex.setView(window.getDefaultView()); 

    // Drawable helper to draw lights 
    // We'll just have to adjust the first vertex's color to tint it 
    sf::VertexArray light(sf::PrimitiveType::TriangleFan); 
    light.append({sf::Vector2f(0, 0), sf::Color::White}); 
    // This is inaccurate, but for demo purposes… 
    // This could be more elaborate to allow better graduation etc. 
    for (float i = 0; i <= 2 * PI; i += PI * .125f) 
     light.append({sf::Vector2f(std::sin(i), std::cos(i)), sf::Color::Transparent}); 

    // Setup some lights 
    std::vector<Light> lights; 
    lights.push_back({sf::Vector2f(50.f, 50.f), sf::Color::White, 100.f }); 
    lights.push_back({sf::Vector2f(350.f, 150.f), sf::Color::Red, 150.f }); 
    lights.push_back({sf::Vector2f(150.f, 250.f), sf::Color::Yellow, 200.f }); 
    lights.push_back({sf::Vector2f(250.f, 450.f), sf::Color::Cyan, 100.f }); 

    // RenderStates helper to transform and draw lights 
    sf::RenderStates rs(sf::BlendAdd); 

    while (window.isOpen()) { 
     sf::Event event; 
     while (window.pollEvent(event)) { 
      switch (event.type) { 
       case sf::Event::Closed: 
        window.close(); 
        break; 
      } 
     } 

     bool flip = false; // simple toggle to animate differently 

     // Draw the light map 
     lightmapTex.clear(sf::Color::Black); 
     for(Light &l : lights) 
     { 
      // Apply all light attributes and render it 

      // Reset the transformation 
      rs.transform = sf::Transform::Identity; 

      // Move the light 
      rs.transform.translate(l.position); 

      // And scale it (this could be animated to create flicker) 
      rs.transform.scale(l.radius, l.radius); 

      // Adjust the light color (first vertex) 
      light[0].color = l.color; 

      // Draw the light 
      lightmapTex.draw(light, rs); 

      // To make things a bit more interesting 
      // We're moving the lights 
      l.position.x += flip ? 2 : -2; 
      flip = !flip; 
      if (l.position.x > 640) 
       l.position.x -= 640; 
      else if (l.position.x < 0) 
       l.position.x += 640; 
     } 
     lightmapTex.display(); 

     window.clear(sf::Color::White); 
     // Draw the background/game 
     window.draw(background); 
     // Draw the lightmap 
     window.draw(lightmap, sf::BlendMultiply); 
     window.display(); 
    } 
} 
+0

와우 나는 그 xD에 대한 준비가 안됐다. 꽤 멋지다. 나는 이것을 시험해 볼 것이다. 고마워! – FeelZoR

+0

@FeelZoR 명확하지 않은 경우를 대비하여 어떤 모양 으로든 조명을 그릴 수 있으므로 스포트라이트 또는 기타 비 원형 광원을 그리는 것이 쉽지 않습니다. – Mario

관련 문제