对OpenGL着色器在C / C容易框架++ [英] Easy framework for OpenGL Shaders in C/C++

查看:95
本文介绍了对OpenGL着色器在C / C容易框架++的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我只是想尝试一个平面图像上的一些着色器。原来,写一个C程序,它只是需要一个图像作为纹理并应用,比方说,一个高斯模糊,因为它片段着色器是不是很简单:你必须初始化的OpenGL这是像100线$​​ C $的C,然后理解GLBuffers等。此外,以与该视窗系统中的一个具有使用GLUT这是另一种框架..

I just wanted to try out some shaders on a flat image. Turns out that writing a C program, which just takes a picture as a texture and applies, let's say a gaussian blur, as a fragment shader on it is not that easy: You have to initialize OpenGL which are like 100 lines of code, then understanding the GLBuffers, etc.. Also to communicate with the windowing system one has to use GLUT which is another framework..

原来是Nvidia的FX作曲家是好的着色器玩。但我还是想有一个简单的C或C ++程序刚刚应用于一个给定的片段着色器到图像,并显示结果。没有任何人有一个例子,还是有一个框架?

Turns out that Nvidia's Fx composer is nice to play with shaders.. But I still would like to have a simple C or C++ program which just applies a given fragment shader to an image and displays the result. Does anybody have an example or is there a framework?

推荐答案

首先,我会避免使用过剩 - 这是越野车,也没有大致十年进行了更新,它的设计并不真正适合非常好,今天大多数人都希望(例如,虽然你的可以的使用它的动画,它的真正目的主要生产静态展示)。我指出一些替代品中餍足<一个href=\"http://stackoverflow.com/questions/2254706/how-to-start-developing-with-opengl-and-c-what-tools-do-i-need-to-install-on-w/2254966#2254966\">a previous答案。

First of all, I'd avoid using glut -- it's buggy, hasn't been updated in roughly a decade, and its design doesn't really fit very well with what most people want today (e.g., though you can use it for animations, it's really intended primarily to produce a static display). I pointed out a number of alternatives to glut in a previous answer.

这(大部分)离开code编译,链接,并使用着色器。我写了一个小班,我觉得得心应手为此:

That (mostly) leaves the code to compile, link, and use shaders. I've written a small class I find handy for this purpose:

class shader_prog {
    GLuint vertex_shader, fragment_shader, prog;

    template <int N>
    GLuint compile(GLuint type, char const *(&source)[N]) {
        GLuint shader = glCreateShader(type);
        glShaderSource(shader, N, source, NULL);
        glCompileShader(shader);
        GLint compiled;
        glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
        if (!compiled) {
            GLint length;
            glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
            std::string log(length, ' ');
            glGetShaderInfoLog(shader, length, &length, &log[0]);
            throw std::logic_error(log);
            return false;
        }
        return shader;
    }
public:
    template <int N, int M>
    shader_prog(GLchar const *(&v_source)[N], GLchar const *(&f_source)[M]) {
        vertex_shader = compile(GL_VERTEX_SHADER, v_source);
        fragment_shader = compile(GL_FRAGMENT_SHADER, f_source);
        prog = glCreateProgram();
        glAttachShader(prog, vertex_shader);
        glAttachShader(prog, fragment_shader);
        glLinkProgram(prog);
    }

    operator GLuint() { return prog; }
    void operator()() { glUseProgram(prog); }

    ~shader_prog() {
        glDeleteProgram(prog);
        glDeleteShader(vertex_shader);
        glDeleteShader(fragment_shader);
    }
};

对于一个简单的演示,一对夫妇的直通的着色器(只是模仿固定管道功能):

For a simple demo, a couple of "pass-through" shaders (just imitate the fixed-functionality pipeline):

const GLchar *vertex_shader[] = {
    "void main(void) {\n",
    "    gl_Position = ftransform();\n",
    "    gl_FrontColor = gl_Color;\n",
    "}"
};

const GLchar *color_shader[] = {
    "void main() {\n",
    "    gl_FragColor = gl_Color;\n",
    "}"
};

您会使用这样的:

Which you'd use something like:

void draw() { 
    // compile and link the specified shaders:
    static shader_prog prog(vertex_shader, color_shader);

    // Use the compiled shaders:    
    prog(); 

    // Draw something:
    glBegin(GL_TRIANGLES);
        glColor3f(0.0f, 0.0f, 1.0f);
        glVertex3f(-1.0f, 0.0f, -1.0f);
        glColor3f(0.0f, 1.0f, 0.0f);
        glVertex3f(1.0f, 0.0f, -1.0f);
        glColor3f(1.0f, 0.0f, 0.0f);
        glVertex3d(0.0, -1.0, -1.0);
    glEnd();
}

如果你打算使用,例如,在绘制场景的过程中许多不同的片段着色的,您只需为每个静态对象,然后执行 PROG1(); PROG2(); 等,只是事先绘制希望与每个着色器阴影的对象。例如,

If you're going to use, for example, a number of different fragment shaders in the course of drawing your scene, you simply define a static object for each, then execute prog1();, prog2();, etc., just prior drawing the objects you want shaded with each shader. E.g.,

void draw() { 
    static shader_prog wall_shader("wall_vertex", "wall_frag");
    static shader_prog skin_shader("skin_vertex", "skin_frag");

    wall_shader();
    draw_walls();

    skin_shader();
    draw_skin();
}

编辑:@rotoglup非常正确指出的,这种使用静态变量延迟破坏,直到OpenGL上下文已被破坏之后,所以当析构函数尝试使用 glDeleteProgram / glDeleteShader ,结果未predictable(最好)。

As @rotoglup quite correctly points out, this use of static variables delays destruction until after the OpenGL context has been destroyed, so when the destructors attempt to use glDeleteProgram/glDeleteShader, results are unpredictable (at best).

虽然这可能是一个演示程序情有可原,它在实际使用断然不可取。与此同时,你一般做的的要重新编译你的着色器输入的功能(S)使用它们的每一次。

While this may be excusable in a demo program, it's decidedly undesirable in real use. At the same time, you generally do not want to re-compile your shader(s) every time you enter the function(s) that use them.

要避免这两个问题,你通常要创建着色器对象作为一个类的实例,其寿命是的成员,反过来,绑不管它要遮荫的寿命:

To avoid both problems, you generally want to create your shader objects as members of a class instance whose lifetime is, in turn, tied to the lifetime of whatever it's going to shade:

class some_character_type { 
    shader_prog skin_shader;
public:
    // ...
};

这将编译当您创建一个该类型的字符/次链接着色器程序,并在销毁该字符摧毁它。

This will compile/link the shader program once when you create a character of that type, and destroy it when you destroy that character.

当然,在少数情况下,这是不完全可取无论是。只是举例,认为古代的3D版杀死大量的目标游戏,像小蜜蜂或蜈蚣。对于这样的比赛,你创建和相对快速地摧毁大量基本相同的目标。由于大量的基本相同的目标,你可能想使用的东西像的shared_ptr&LT; shader_prog&GT; 打造了一个所有实例之间共享的着色器的单个实例特定的目标类型。既然你再次使用相同的目标类型很多次,你可能想比这还要去一个远一点,让你在整个游戏中保持相同的着色器,不只是当正在显示目标的特定类型。

Of course, in a few cases, this isn't exactly desirable either. Just for example, consider a 3D version of the ancient "kill lots of targets" games like Galaga or Centipede. For games like this, you're creating and destroying lots of essentially identical targets relatively quickly. Given a large number of essentially identical targets, you probably want to use something like a shared_ptr<shader_prog> to create a single instance of the shader that's shared between all the instances of a particular target type. Given that you re-use the same target types many times, you may want to go a bit further even than that, so you maintain the same shaders through the entire game, not just when a particular type of target is being shown.

在任何情况下,我们变得有点偏离轨道在这里。关键在于,编译和链接的着色器是一个的非常的昂贵的过程,所以你通常要管理自己的生命周期,以避免造成更频繁毁坏了他们很多不是真正需要的(尽管这并不是说它关键在游戏开始创建所有这些,只在最后消灭他们,无论是)。

In any case, we're getting a bit off-track here. The point is that compiling and linking shaders is a fairly expensive process, so you normally want to manage their lifetime to avoid creating and destroying them a lot more often than truly necessary (though that's not to say that it's critical to create them all at the beginning of the game and only destroy them at the end, either).

这篇关于对OpenGL着色器在C / C容易框架++的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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