tags:

views:

561

answers:

4

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..

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?

+2  A: 

I was in a similar position about a year and a half ago. I quickly found a simple tutorial and source code for using GLSL.. but I did have to get GLUT and GLEW working, and I think I ended up compiling at least one of those myself. Since I was using Windows (and Windows is somewhat of a non-standard special case which is rarely given full treatment by open projects), it also involved a ridiculous process where I was expected to manually copy and paste DLL's and header files to certain common locations. It's always a pain and I've lost a good chunk of my life doing that sort of thing, but I trudged through the process as directed and it worked out in the end as is generally the case.

Anyway, the most convenient shader example using GLSL that I can find right now is this one - http://www.lighthouse3d.com/opengl/glsl/index.php?minimal

It doesn't specifically modify a texture as you wish.. but in my experience, once you get code like this compiling and running the experience will be more enjoyable and you'll quickly make progress and be able to splice in pieces from other tutorials if necessary. I can say that once I got an example running, I used that same framework to quickly solve many problems at home and work.

I'm sorry to say that it does make use of GLUT and GLEW. If you get a better answer to this question, I too will become an instant fan of whichever site offers the code. Good luck.

guesser
OSX here.. maybe I was just too tired today, will try tomorrow
Nils
A: 

Although it's not your target, you might get something out of Noel Llopis's OpenGL ES 2.0 shader sample: http://www.mobileorchard.com/getting-started-with-opengl-es-20-on-the-iphone-3gs/

Matt Curtis
+5  A: 

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.

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

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();
}
Jerry Coffin
@Jerry Nice answer!
Matt Curtis
Thanks a lot for the code! Will try it out when I have time :)
Nils
+2  A: 

This tutorial might be useful (note that it does contain GLSL material besides the old Cg stuff).

Note that I'd consider writing shaders to implement non-graphical, GPGPU-type things to be an obsolete approach these days. OpenCL or CUDA are clearly they way to go in future.

timday
A pre CUDA GPGPU tutorial.. Interesting, thx :)
Nils