繁体   English   中英

C / C ++中OpenGL着色器的简易框架

Easy framework for OpenGL Shaders in C/C++

提示:本站收集StackOverFlow近2千万问答,支持中英文搜索,鼠标放在语句上弹窗显示对应的参考中文或英文, 本站还提供   中文繁体   英文版本   中英对照 版本,有任何建议请联系yoyou2525@163.com。

我只是想在平面图像上尝试一些着色器。 事实证明,编写一个C程序,它只是将图片作为纹理并应用,假设是高斯模糊,因为它上面的片段着色器并不那么容易:你必须初始化OpenGL,就像100行代码,然后理解GLBuffers等。另外要与窗口系统进行通信,必须使用另一个框架GLUT。

事实证明,Nvidia的Fx作曲家很适合使用着色器。但我仍然希望有一个简单的C或C ++程序,它只是将给定的片段着色器应用于图像并显示结果。 有人有例子还是有框架?

4 个回复

首先,我会避免使用过剩 - 这是错误的,大约十年没有更新,它的设计并不能很好地适应大多数人今天想要的东西(例如,尽管你可以用它来做动画,它主要用于生成静态显示)。 我在之前的回答中指出了一些过剩的替代品。

这(主要)留下代码来编译,链接和使用着色器。 我写了一个小课程,我觉得这个目的很方便:

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);
    }
};

对于一个简单的演示,一些“传递”着色器(只是模仿固定功能管道):

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",
    "}"
};

您使用的类似于:

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(); 等等,在绘制每个着色器要着色的对象之前。 例如,

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非常正确地指出的那样, static变量的使用延迟了破坏直到OpenGL上下文被破坏之后,所以当析构函数尝试使用glDeleteProgram / glDeleteShader ,结果是不可预测的(充其量)。

虽然这在演示程序中可能是可以原谅的,但它在实际使用中显然是不可取的。 同时,每次输入使用它们的函数时,通常希望重新编译着色器。

为了避免这两个问题,您通常希望将着色器对象创建为类实例的成员,而这些类实例的生命周期又依赖于它将变为阴影的生命周期:

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

这将在您创建该类型的角色时编译/链接着色器程序一次,并在销毁该角色时将其销毁。

当然,在少数情况下,这也不是完全可取的。 例如,考虑一下古代“杀死大量目标”游戏的3D版本,如Galaga或Centipede。 对于像这样的游戏,你可以相对快速地创建和销毁许多基本相同的目标。 给定大量基本相同的目标,您可能希望使用类似shared_ptr<shader_prog>东西来创建在特定目标类型的所有实例之间共享的着色器的单个实例。 鉴于您多次重复使用相同的目标类型,您可能希望比此更进一步,因此您在整个游戏中保持相同的着色器,而不仅仅是在显示特定类型的目标时。

无论如何,我们在这里有点偏离轨道。 关键是编译和链接着色器是一个相当昂贵的过程,所以你通常想要管理它们的生命周期,以避免比真正必要的更多地创建和销毁它们(尽管这并不是说在所有这些过程中创建它们都是至关重要的)游戏的开始,只在最后摧毁它们,或者)。

大约一年半前,我处于类似的位置。 我很快找到了一个简单的教程和使用GLSL的源代码..但我确实必须让GLUT和GLEW工作,我想我最终自己编译了至少一个。 由于我使用的是Windows(并且Windows在某种程度上是非标准的特殊情况,很少得到开放项目的全面处理),它还涉及一个荒谬的过程,我希望手动将DLL和头文件复制并粘贴到某些常见的位置。 这总是一种痛苦,我已经失去了生活中的一大部分,但是我按照指示跋涉过程,最终通常情况就是如此。

无论如何,我现在能找到的使用GLSL的最方便的着色器示例就是这个 - http://www.lighthouse3d.com/opengl/glsl/index.php?minimal

它没有按照你的意愿专门修改纹理..但根据我的经验,一旦你得到这样的代码编译和运行,体验将更加愉快,你将很快取得进展,并能够从其他教程拼接成碎片如有必要。 我可以说,一旦我运行了一个例子,我使用相同的框架来快速解决家庭和工作中的许多问题。

我很遗憾地说它确实利用了GLUT和GLEW。 如果你对这个问题有了更好的答案,我也会成为任何提供代码的网站的粉丝。 祝好运。

教程可能很有用(请注意,除了旧的Cg之外,它确实包含GLSL材料)。

请注意,我现在考虑编写着色器来实现非图形化的GPGPU类型的东西,这是一种过时的方法。 OpenCL或CUDA显然是未来的发展方向。

虽然它不是你的目标,但你可能会从Noel Llopis的OpenGL ES 2.0着色器样本中获得一些东西: http//www.mobileorchard.com/getting-started-with-opengl-es-20-on-the-iphone-3gs/

1 opengl着色器(glsl)中的c ++位标志

将我的位标志发送到片段着色器以便能够对它进行if()的最佳方法是什么? 我有以下位标记(枚举): 对应于表[] =将i,j放置在表中([位为整数]) 因此,当在我的实际表中的每一行中选择所有第一个选项时,我的位标记(选项)的可能值将为我提供273的值。在每一行中,只能选择一 ...

2 OpenGL / C ++-转换和VBO /着色器不让我转换吗?

我实际上在学习一些OpenGL,我设法加载了一个网格并将其显示在窗口中。 然后,我使用SDL制作了一个函数,该函数使我可以使用箭头键旋转网格。 但是当我深入着色器时,我做了一些更改,但是我无法对3D模型进行简单的旋转。 这是我的绘图功能: Theese是我的着色器: 片段 ...

3 C ++,OpenGL-几何着色器

我在OpenGL中陷入了几何着色器-C ++编程。 我想通过重复6次绘制一个旋转的墙来创建简单的多维数据集。 这是我的顶点着色器(每一个在序言中都有#version 330核心): 现在,几何着色器: 现在,片段着色器: 好吧,这里有一些垃圾,我想也将阴影添加到立方体 ...

4 C ++ OpenGL着色器不起作用

我刚刚开始学习c ++,并且我正在尝试制作一个使用着色器绘制颜色三角形的程序。 这是我的顶点着色器: 这是我的片段着色器: 我分别有一个坐标值和颜色值列表: 我初始化一个“顶点缓冲对象”和一个“顶点数组对象” 我编译一个着色器程序: 我为着色器定义了 ...

8 OpenGL着色器错误C1068:类型构造函数中的数据过多

我正在关注本网站www.learnopengl.com上的教程,并且在着色器教程的结尾,我尝试将自己的统一变量添加到片段着色器中,如下所示: 然后像这样编译和更改统一变量: ourShader.use()只是我们在教程中为Shader操作编写的Shader类的一种方法,它仅使用了 ...

9 属性的多个缓冲区如何在openGL(ES)着色器和C ++ API中工作

我有一个众所周知的多维数据集示例,并且一直在编写一些代码来对其进行测试并了解有关着色器的更多信息。 我的问题是关于如何在着色器中分配多个缓冲区以进行访问以及如何编写着色器代码以引用它们。 那里的样本似乎依赖于某种隐式引用默认值,这些默认值隐藏了实际发生的情况以及如何在样本中对其进行操作。 ...

10 OpenGL着色器?

我正在用Java写一个游戏,LJGWL(OpenGL)。 我正在使用一个为我处理大量杂乱细节的库,但需要找到更快的方法来实现这一点。 基本上我想设置屏幕上的每个像素尽可能快地说出随机颜色。 “随机颜色”只是一个每隔2-3秒更新一次的Array [] []。 我已经尝试过绘制rects ...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2022 STACKOOM.COM