root / trunk / tbeta / Windows / addons / ofxNCore / src / Filters / GPUImageFilter.cpp @ 160

View | Annotate | Download (6.7 KB)

1
/*
2
*  GPUImageFilter.cpp
3
*  
4
*
5
*  Created on 2/2/09.
6
*  Copyright 2009 NUI Group. All rights reserved.
7
*
8
*/
9
10
#include "GPUImageFilter.h"
11
#include <stdio.h>
12
#include "tinyxml.h"
13
#include "ofUtils.h"
14
15
//helper functon, should go somewhere else
16
void getFrameBufferForTexture(GLuint* fbo, GLuint* tex, int sizeX, int sizeY){
17
    GLenum status;
18
19
    //allocate ouput buffer on GPU using FBO
20
    glEnable(GL_TEXTURE_2D);
21
    glGenTextures(1, tex);
22
    glBindTexture(GL_TEXTURE_2D, *tex);
23
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
24
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8,  sizeX, sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
25
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
26
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
27
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
28
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
29
    //glGenerateMipmapEXT(GL_TEXTURE_2D);
30
31
    glBindTexture(GL_TEXTURE_2D, 0);
32
33
    //generate fbo
34
    glGenFramebuffersEXT(1, fbo);
35
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, *fbo);
36
37
    //attach texture to fbo
38
    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, *tex, 0);
39
40
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
41
42
    status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
43
    printf("Frame buffer status: %d\n", status);
44
}
45
46
47
48
49
50
51
GPUImageFilter::GPUImageFilter(const char* fname, int sx, int sy){
52
//read the filter description file and creates a filter based on the shaders and parameters given in that file
53
//allocates output buffer/texture
54
55
        res_x = sx; res_y = sy;
56
        useGeometryShader =false;
57
        //this->shader = shaderProg;
58
        glGenTextures(1, &output_texture );
59
        getFrameBufferForTexture(&output_buffer, &output_texture, res_x, res_y);
60
        this->parseXML(fname);
61
62
}
63
64
65
void GPUImageFilter::parseXML(const char* fname){
66
        //load filter description file
67
        printf("Loading Filter...\n");
68
69
70
        //load and parse xml filter description file
71
        TiXmlDocument doc(ofToDataPath(fname).c_str());
72
        if (!doc.LoadFile()) printf("error loading filter description file");
73
74
75
        //get the name of the filter
76
        TiXmlElement* root_node = doc.RootElement();
77
78
        this->name = root_node->Attribute("name");
79
80
        printf("Filter Name:%s\n", this->name);
81
82
83
        //get the  shader source file names
84
        TiXmlElement* node = root_node;
85
86
        node = root_node->FirstChildElement("VertexShader");
87
        const char* vertSrc = node ? node->GetText() : NULL;
88
89
        node = root_node->FirstChildElement("GeometryShader");
90
        const char* geomSrc = node ? node->GetText() : NULL;
91
        if (geomSrc != NULL){ //We are using a geometry shader
92
                this->useGeometryShader = true;
93
        }
94
95
        node = root_node->FirstChildElement("FragmentShader");
96
        const char* fragSrc = node ? node->GetText() : NULL;
97
98
    this->shader = new ShaderProgram(vertSrc, geomSrc, ofToDataPath(fragSrc).c_str());
99
100
101
        //get parameters
102
        //TODO: add type handling
103
        while( (node = (TiXmlElement*)node->NextSibling("Parameter")) ){
104
                const char* name = node->Attribute("name");
105
                float type = atof(node->Attribute("type"));
106
                float min = atof(node->Attribute("min"));
107
                float max = atof(node->Attribute("max"));
108
                float val = atof(node->GetText());
109
110
111
                parameters["size_cx"] = new FilterParameter("size_cx", (float)res_x, 0, 0, 0 );
112
                parameters["size_cy"] = new FilterParameter("size_cy", (float)res_y, 0, 0, 0 );
113
                parameters[std::string(name)] = new FilterParameter(name, val, min, max, (int)type );
114
        }
115
}
116
117
118
//applies the filter to a GL texture.
119
//
120
//saves opengl states, and binds this filter's output buffer (render to texture)
121
//sets up ortho projection for drawing just the texture using teh filters shaders
122
//parameters are set as uniforms for the shaders
123
GLuint GPUImageFilter::apply(GLuint inputTexture, GLuint inputTexture2){
124
125
        glPushAttrib(GL_VIEWPORT_BIT);
126
    glPushAttrib(GL_ENABLE_BIT);
127
128
    glMatrixMode(GL_MODELVIEW);
129
    glPushMatrix();
130
    glMatrixMode(GL_PROJECTION);
131
    glPushMatrix();
132
133
    //render to the fbo using the shader
134
    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, output_buffer);
135
136
    glClearColor(0.0,1.0,0.0,1.0);
137
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
138
    glViewport(0,0,res_x, res_y);
139
140
    glMatrixMode(GL_PROJECTION);
141
    glLoadIdentity();
142
    glOrtho(-1, 1.0, -1, 1.0, -1, 1.0);
143
    glMatrixMode(GL_MODELVIEW);
144
    glLoadIdentity();
145
146
        glEnable(GL_TEXTURE_2D);
147
    glBindTexture(GL_TEXTURE_2D, inputTexture);
148
149
150
151
    this->shader->enable();
152
153
    //set the parameters for the filters
154
        for(std::map<std::string, FilterParameter*>::const_iterator it = parameters.begin(); it != parameters.end(); ++it){
155
                    const char* test = it->first.c_str();
156
                float test2 = it->second->value;
157
                        this->shader->setUniform1f(it->first.c_str(), it->second->value);
158
        }
159
160
        if (inputTexture2 !=0){
161
                this->shader->setUniform1i("tex2", 1);
162
        }
163
164
165
        //use geometry shader threads to process image blocks
166
        if(useGeometryShader){
167
                        //send n number of threads
168
                int numThreads = (int) parameters["threads"]->value;
169
                        glBegin(GL_POINTS);
170
171
                //glVertex2d(3,3);
172
                int i=0;
173
                for(i=0; i<numThreads; i++){
174
                                float x = (float)((i/numThreads ) / (float)numThreads -0.5f) * 2.0f;
175
                                float y = (float)((i%numThreads ) / (float)numThreads  -0.5f)* 2.0f;
176
                                glVertex2d(x,y);
177
                }
178
                        glEnd();
179
        }else{
180
181
                //draw full screen quad with input texture aplied
182
                glActiveTexture(GL_TEXTURE0);
183
                glEnable(GL_TEXTURE_2D);
184
        glBindTexture(GL_TEXTURE_2D, inputTexture);
185
                glActiveTexture(GL_TEXTURE1);
186
                glEnable(GL_TEXTURE_2D);
187
        glBindTexture(GL_TEXTURE_2D, inputTexture2);
188
189
                this->shader->enable();
190
        glBegin(GL_QUADS);
191
        glColor3d(1.0, 0.0, 0.0);
192
        glTexCoord2f(0, 0); glVertex3f(-1, -1, 0);
193
        glTexCoord2f(1, 0); glVertex3f(1, -1, 0);
194
        glTexCoord2f(1, 1); glVertex3f(1, 1, 0);
195
        glTexCoord2f(0, 1); glVertex3f(-1, 1, 0);
196
        glEnd();
197
        }
198
199
200
201
        this->shader->disable();
202
203
        glPopMatrix();
204
        glMatrixMode(GL_PROJECTION);
205
        glPopMatrix();
206
        glPopAttrib();
207
        glPopAttrib();
208
209
        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);  //should maybe have a stack
210
211
        glActiveTexture(GL_TEXTURE1);
212
        glBindTexture(GL_TEXTURE_2D,0);
213
        glActiveTexture(GL_TEXTURE0);
214
        glBindTexture(GL_TEXTURE_2D,0);
215
216
217
        return output_texture;
218
219
220
};
221
222
223
224
225
226
227
void GPUImageFilter::drawOutputTexture(float x,float y, float w, float h){
228
        glEnable(GL_TEXTURE_2D);
229
        glBindTexture(GL_TEXTURE_2D, this->output_texture);
230
        glPushMatrix();
231
        glBegin( GL_QUADS );
232
                glTexCoord2f(0,0);                        glVertex3i(x, y,0);
233
                glTexCoord2f(1,0);                        glVertex3i(x+w, y,0);
234
                glTexCoord2f(1,1);                        glVertex3i(x+w, y+h,0);
235
                glTexCoord2f(0,1);                        glVertex3i(x, y+h,0);
236
        glEnd();
237
        glPopMatrix();
238
}
239
240
241
242
243
//destructor
244
GPUImageFilter::~GPUImageFilter()
245
{
246
}