2017-12-07 8 views
1

현재 오픈 소스 GUI SFML 기반 라이브러리를 개발하고 있지만 셰이더를 사용하여 조금 어려움을 겪고 있습니다. 지금까지 나는 쉐이더를 문제없이 렌더링했지만, 현재의 객체에 쉐이더를 적용하는 대신 전체 윈도우에 적용했지만 객체 범위에서만 볼 수 있습니다.셰이더가 창 대신 캔버스로 vertexArray를 가져옴

여기 내 간단한 코드입니다 :

#include <SFML/Window.hpp> 
#include <SFML/Graphics.hpp> 

#include <iostream> 

const char *glsl = R"(
    #version 330 core 
    uniform vec2 u_resolution; 

    void main() { 
     vec2 pos = gl_FragCoord.xy/u_resolution; 
     float radius = 0.4; 
     float d = distance(pos, vec2(0.5)); 

     gl_FragColor = d <= radius ? vec4(pos.y,pos.y/2.,pos.y, 1.0) : vec4(d*0.8, d*0.8, d*0.8, 1.0); 


     //gl_FragColor = vec4(0.0, 0.5, 1.0, 1.0); 
    } 
)"; 

const char *pos = R"(
    // some default shader I've found 
    // adding #version 330 core will complain for outdated gl_Position variable.. 

    void main() { 
     gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; 

     gl_FrontColor = gl_Color; 
    } 
)"; 

int main() { 
    sf::RenderWindow window(sf::VideoMode(800, 600), "GLSL", sf::Style::Default); 

    // create a quad 
    sf::VertexArray quad(sf::Quads, 4); 
    // define it as a rectangle, located at (10, 10) and with size 100x100 
    quad[0].position = sf::Vector2f(100, 100); 
    quad[1].position = sf::Vector2f(410, 100); 
    quad[2].position = sf::Vector2f(410, 410); 
    quad[3].position = sf::Vector2f(100, 410); 


    sf::Shader shader; 
    // the following line is the same as shader.loadFromMemory(pos, glsl); 
    shader.loadFromMemory(glsl, sf::Shader::Fragment); 
    shader.setUniform("u_resolution", sf::Vector2f(800, 600)); 

    while (window.isOpen()) { 
     sf::Event event; 
     while (window.pollEvent(event)) { 
      if (event.type == sf::Event::Closed) 
       window.close(); 
     } 

     window.clear(sf::Color(244,244,244)); 

     window.draw(quad, &shader); 

     window.display(); 
    } 

    return 0; 
} 

지금까지 수행하지만 pos 셰이더는 렌더링을 수행하는 방법에 영향을해야한다고 생각 무엇인지 확실하지. 감사!

답변

3

약간의 변경이 필요합니다. 어떤 최신 버전의 쉐이더 버전에서도 가장 좋은 방법은 무엇인지 모르겠지만 레거시 코드를 사용하는 등 모든 버전 표시자를 생략하면 빠른 변경이 가능합니다.

우선, 개인 정점 (또는 더 구체적으로 렌더링 된 부분)은 그려지는 쿼드에 상대적인 위치를 알 수 없습니다. 다행히도 이것을 위해 텍스처 좌표를 남용 할 수 있습니다. 예를 들어 왼쪽 상단을 (0, 0), 오른쪽 하단을 (1, 1)으로 정의하십시오. 이 방법으로 조각의 위치에 따라 값의 범위는 0에서 1이됩니다. 이것은 기본적으로 기존 쉐이더 코드가 pos으로 계산하는 것입니다.

그래서 좌표의 텍스쳐를 추가하여 시작하자 :

quad[0].position = sf::Vector2f(100, 100); 
quad[0].texCoords = sf::Vector2f(0, 0); 
quad[1].position = sf::Vector2f(410, 100); 
quad[1].texCoords = sf::Vector2f(1, 0); 
quad[2].position = sf::Vector2f(410, 410); 
quad[2].texCoords = sf::Vector2f(1, 1); 
quad[3].position = sf::Vector2f(100, 410); 
quad[3].texCoords = sf::Vector2f(0, 1); 

을 이제 우리가해야 할 모든 텍스처가 pos 좌표를 지정 (또는 더 나은 pos completely을 제거)입니다. 단순화를 위해 나는 단지 지정과 함께 갈 것이다 :

vec2 pos = gl_TexCoord[0].xy; 

그러나,이 gl_TexCoord 제거있어 이후 쉐이더 컴파일러가 불평하게됩니다. 테스트를 위해 난 그냥 프리 D 파일러 라인을 제거하고 그 결과 당신이 생각했던 한 것 같습니다 그래서 것 같아요 :

Screenshot

+0

는 일을 할 것 같다,하지만 조금 하드 보인다. 내가 더 좋은 것을 얻지 못한다면 나는 이것을 대답으로 삼을 것이다. 고마워! –

+0

@RazvanAlex "하드 코딩 된"이란 무엇을 의미합니까? – Mario

+0

실제로 quad textCoords를 설정하시오 –