使着色器将vertexArray作为画布而不是窗口 [英] Making shader takes vertexArray as canvas instead of the window

查看:90
本文介绍了使着色器将vertexArray作为画布而不是窗口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当前正在开发基于开源GUI SFML的库,但是在着色器方面有些挣扎.到目前为止,我已经成功地实现了着色器的渲染,但没有将着色器应用于当前对象,而是将其应用于整个窗口,但仅在对象范围内可见.

Currently developing an open source GUI SFML based library, but struggling a bit with shaders. So far I've managed to render shader with no problem, but instead of applying the shader on the current object, it's apply it for the whole window, but only visible in the object range.

这是我的简单代码:

#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着色器应该影响渲染的完成方式.谢谢!

Not sure what do to for now, but I guess that pos shader should affect how the rendering is done. Thanks!

推荐答案

只需进行一些小的更改.我不确定要在任何更现代的着色器版本中完成它的最佳方法是什么,但是如果您省略任何版本标记(即使用旧版代码),则可以快速进行更改:

Just some minor changes needed. I'm not exactly sure what's the best way to get it done in any more modern shader version, but if you omit any version markers (i.e. using legacy code), it's quick to change:

首先,您的各个顶点(或更具体而言,已渲染的片段)不知道它们相对于要绘制的四边形的位置.幸运的是,您可以为此滥用纹理坐标.例如,将左上角定义为(0, 0),将右下角定义为(1, 1).这样,根据片段的位置,它们的值将在0到1的范围内.基本上,这就是您现有的着色器代码计算为pos的结果.

First of all, your individual vertices (or more specific the rendered fragments) don't know where they are relative to the quad being drawn. Luckily you can abuse texture coordinates for this. For example, define the top left as (0, 0) and the bottom right as (1, 1). This way their values will range from 0 to 1 based on where the fragment is. This is basically what your existing shader code calculates as pos.

因此,我们先添加纹理坐标:

So let's start by adding the texture coordinates:

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).为简化起见,我将仅进行分配:

Now all we have to do is assign the texture coordinates to pos (or better remove pos completely). For simplification I'll just go with the assignment:

vec2 pos = gl_TexCoord[0].xy;

但是,由于删除了gl_TexCoord,这将导致着色器编译器抱怨.因此,为了进行测试,我删除了预编译器行,结果看起来就像您想的那样:

However, this will cause the shader compiler to complain, since gl_TexCoord got removed. So for testing I just removed the precompiler line and the result looks like what you've had in mind I guess:

这篇关于使着色器将vertexArray作为画布而不是窗口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆