2017-12-07 15 views
1

現在、オープンソースのGUI SFMLベースのライブラリを開発していますが、シェイダーで少し苦労しています。これまではシェーダを問題なくレンダリングすることができましたが、シェーダを現在のオブジェクトに適用するのではなく、ウィンドウ全体に適用しますが、オブジェクト範囲でしか表示されません。shaderは、ウィンドウの代わりに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を外してしまったので、シェーダコンパイラは、文句を言うことになります。テストのために私はちょうどプリコンパイラの行を削除し、結果はあなたが心の中に持っていたもののように見えるので、私は推測する:

Screenshot

+0

は、仕事をするようだが、少しハードコードされたようです。私は何かをより良くすることができないなら、これを答えとして取るでしょう、ありがとう! –

+0

@RazvanAlex "ハードコードされた"とはどういう意味ですか? – Mario

+0

実際にクワッドのtextCoordsを設定する –

関連する問題