Browse Source

flushed out shader support

naelstrof 7 years ago
parent
commit
1aaadbb1f6
8 changed files with 139 additions and 19 deletions
  1. 1
    1
      CMakeLists.txt
  2. 35
    7
      src/framebuffer.cpp
  3. 4
    2
      src/framebuffer.hpp
  4. 18
    1
      src/main.cpp
  5. 11
    0
      src/shader.cpp
  6. 2
    0
      src/shader.hpp
  7. 66
    7
      src/slop.cpp
  8. 2
    1
      src/slop.hpp

+ 1
- 1
CMakeLists.txt View File

21
 
21
 
22
 include_directories("${PROJECT_BINARY_DIR}")
22
 include_directories("${PROJECT_BINARY_DIR}")
23
 
23
 
24
-add_definitions(-DSLOP_VERSION="v5.3.34")
24
+add_definitions(-DSLOP_VERSION="v5.3.35")
25
 
25
 
26
 # The names have to be unique unfortunately.
26
 # The names have to be unique unfortunately.
27
 set(EXECUTABLE_NAME "slop")
27
 set(EXECUTABLE_NAME "slop")

+ 35
- 7
src/framebuffer.cpp View File

1
 #include "framebuffer.hpp"
1
 #include "framebuffer.hpp"
2
 
2
 
3
 slop::Framebuffer::Framebuffer( int w, int h ) {
3
 slop::Framebuffer::Framebuffer( int w, int h ) {
4
-    std::string vert = "#version 130\nattribute vec2 position;\nattribute vec2 uv;\nvarying vec2 uvCoord;\nvoid main()\n{\nuvCoord = uv;\ngl_Position = vec4(position,0,1);\n}\n";
5
-    std::string frag = "#version 130\n uniform sampler2D texture;\n varying vec2 uvCoord;\n out vec4 outColor;\n void main()\n {\n outColor = texture2D( texture, uvCoord );\n }\n";
6
-    shader = new Shader( vert, frag, false );
7
     glGenFramebuffers( 1, &fbuffer );
4
     glGenFramebuffers( 1, &fbuffer );
8
     glBindFramebuffer( GL_FRAMEBUFFER, fbuffer );
5
     glBindFramebuffer( GL_FRAMEBUFFER, fbuffer );
9
     glGenTextures(1, &image);
6
     glGenTextures(1, &image);
11
     glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
8
     glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
12
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
9
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
13
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
10
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
11
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
12
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
14
     glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, image, 0);
13
     glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, image, 0);
15
     glBindFramebuffer(GL_FRAMEBUFFER, 0);
14
     glBindFramebuffer(GL_FRAMEBUFFER, 0);
16
     // generate our vertex and uv buffers
15
     // generate our vertex and uv buffers
36
     glBindBuffer( GL_ARRAY_BUFFER, buffers[1] );
35
     glBindBuffer( GL_ARRAY_BUFFER, buffers[1] );
37
     glBufferData( GL_ARRAY_BUFFER, uvs.size() * sizeof( glm::vec2 ), &uvs[0], GL_STATIC_DRAW );
36
     glBufferData( GL_ARRAY_BUFFER, uvs.size() * sizeof( glm::vec2 ), &uvs[0], GL_STATIC_DRAW );
38
     vertCount = verts.size();
37
     vertCount = verts.size();
38
+    generatedDesktopImage = false;
39
 }
39
 }
40
 
40
 
41
-void slop::Framebuffer::setShader( std::string name ) {
42
-    delete shader;
43
-    shader = new Shader( name + ".vert", name + ".frag" );
41
+void slop::Framebuffer::setShader( slop::Shader* shader ) {
42
+    this->shader = shader;
43
+    if ( shader->hasParameter( "desktop" ) && !generatedDesktopImage ) {
44
+        XImage* image = XGetImage( x11->display, x11->root, 0, 0, WidthOfScreen( x11->screen ), HeightOfScreen( x11->screen ), 0xffffffff, ZPixmap );
45
+        glEnable(GL_TEXTURE_2D);
46
+        glGenTextures(1, &desktopImage);
47
+        glBindTexture(GL_TEXTURE_2D, desktopImage);
48
+        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
49
+        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
50
+        //glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
51
+        glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, WidthOfScreen( x11->screen ), HeightOfScreen( x11->screen ), 0, GL_BGRA, GL_UNSIGNED_BYTE, (void*)(&(image->data[0])));
52
+        XDestroyImage( image );
53
+        generatedDesktopImage = true;
54
+    }
44
 }
55
 }
45
 
56
 
46
 slop::Framebuffer::~Framebuffer() {
57
 slop::Framebuffer::~Framebuffer() {
72
     glBindFramebuffer( GL_FRAMEBUFFER, 0 );
83
     glBindFramebuffer( GL_FRAMEBUFFER, 0 );
73
 }
84
 }
74
 
85
 
75
-void slop::Framebuffer::draw(){
86
+void slop::Framebuffer::draw(glm::vec2 mouse, float time, glm::vec4 color){
76
     shader->bind();
87
     shader->bind();
77
     shader->setParameter( "texture", 0 );
88
     shader->setParameter( "texture", 0 );
78
     shader->setAttribute( "position", buffers[0], 2 );
89
     shader->setAttribute( "position", buffers[0], 2 );
79
     shader->setAttribute( "uv", buffers[1], 2 );
90
     shader->setAttribute( "uv", buffers[1], 2 );
91
+    if ( shader->hasParameter( "mouse" ) ) {
92
+        shader->setParameter( "mouse", mouse );
93
+    }
94
+    if ( shader->hasParameter( "color" ) ) {
95
+        shader->setParameter( "color", color );
96
+    }
97
+    if ( shader->hasParameter( "screenSize" ) ) {
98
+        shader->setParameter( "screenSize", glm::vec2( WidthOfScreen( x11->screen ), HeightOfScreen( x11->screen ) ));
99
+    }
100
+    if ( shader->hasParameter( "time" ) ) {
101
+        shader->setParameter( "time", time );
102
+    }
80
     glActiveTexture(GL_TEXTURE0);
103
     glActiveTexture(GL_TEXTURE0);
81
     glBindTexture( GL_TEXTURE_2D, image );
104
     glBindTexture( GL_TEXTURE_2D, image );
105
+    if ( shader->hasParameter( "desktop" ) ) {
106
+		shader->setParameter( "desktop", 1 );
107
+        glActiveTexture(GL_TEXTURE0 + 1);
108
+        glBindTexture( GL_TEXTURE_2D, desktopImage );
109
+    }
82
     glEnable( GL_TEXTURE_2D );
110
     glEnable( GL_TEXTURE_2D );
83
     glDrawArrays( GL_TRIANGLES, 0, vertCount );
111
     glDrawArrays( GL_TRIANGLES, 0, vertCount );
84
     glDisable( GL_TEXTURE_2D );
112
     glDisable( GL_TEXTURE_2D );

+ 4
- 2
src/framebuffer.hpp View File

36
     unsigned int image;
36
     unsigned int image;
37
     unsigned int buffers[2];
37
     unsigned int buffers[2];
38
     unsigned int vertCount;
38
     unsigned int vertCount;
39
+    unsigned int desktopImage;
40
+    bool generatedDesktopImage;
39
     Shader* shader;
41
     Shader* shader;
40
 public:
42
 public:
41
     Framebuffer( int w, int h );
43
     Framebuffer( int w, int h );
42
     ~Framebuffer();
44
     ~Framebuffer();
43
-    void setShader( std::string );
44
-    void draw();
45
+    void setShader( slop::Shader* shader );
46
+    void draw(glm::vec2 mouse, float time, glm::vec4 color);
45
     void resize( int w, int h );
47
     void resize( int w, int h );
46
     void bind();
48
     void bind();
47
     void unbind();
49
     void unbind();

+ 18
- 1
src/main.cpp View File

25
 
25
 
26
 using namespace slop;
26
 using namespace slop;
27
 
27
 
28
+template<typename Out>
29
+static void split(const std::string &s, char delim, Out result) {
30
+    std::stringstream ss;
31
+    ss.str(s);
32
+    std::string item;
33
+    while (std::getline(ss, item, delim)) {
34
+        *(result++) = item;
35
+    }
36
+}
37
+static std::vector<std::string> split(const std::string &s, char delim) {
38
+    std::vector<std::string> elems;
39
+    split(s, delim, std::back_inserter(elems));
40
+    return elems;
41
+}
42
+
28
 SlopOptions* getOptions( Options& options ) {
43
 SlopOptions* getOptions( Options& options ) {
29
     SlopOptions* foo = new SlopOptions();
44
     SlopOptions* foo = new SlopOptions();
30
     options.getFloat("bordersize", 'b', foo->borderSize);
45
     options.getFloat("bordersize", 'b', foo->borderSize);
35
     options.getBool("nokeyboard", 'k', foo->nokeyboard);
50
     options.getBool("nokeyboard", 'k', foo->nokeyboard);
36
     options.getBool("noopengl", 'o', foo->noopengl);
51
     options.getBool("noopengl", 'o', foo->noopengl);
37
     options.getString( "xdisplay", 'x', foo->xdisplay );
52
     options.getString( "xdisplay", 'x', foo->xdisplay );
38
-    options.getString( "shader", 's', foo->shader );
53
+    std::string shaders = "textured";
54
+    options.getString( "shader", 'r', shaders );
55
+    foo->shaders = split( shaders, ',' );
39
     foo->r = color.r;
56
     foo->r = color.r;
40
     foo->g = color.g;
57
     foo->g = color.g;
41
     foo->b = color.b;
58
     foo->b = color.b;

+ 11
- 0
src/shader.cpp View File

7
         vert = resource->getRealPath(vert);
7
         vert = resource->getRealPath(vert);
8
         frag = resource->getRealPath(frag);
8
         frag = resource->getRealPath(frag);
9
         std::ifstream v( vert.c_str() );
9
         std::ifstream v( vert.c_str() );
10
+        if (!v.is_open()) {
11
+            throw new std::runtime_error( "Failed to open " + vert );
12
+        }
10
         vert_contents = std::string((std::istreambuf_iterator<char>(v)),
13
         vert_contents = std::string((std::istreambuf_iterator<char>(v)),
11
                                    std::istreambuf_iterator<char>());
14
                                    std::istreambuf_iterator<char>());
12
         std::ifstream f( frag.c_str() );
15
         std::ifstream f( frag.c_str() );
16
+        if (!f.is_open()) {
17
+            throw new std::runtime_error( "Failed to open " + frag );
18
+        }
13
         frag_contents = std::string((std::istreambuf_iterator<char>(f)),
19
         frag_contents = std::string((std::istreambuf_iterator<char>(f)),
14
                                   std::istreambuf_iterator<char>());
20
                                   std::istreambuf_iterator<char>());
15
     } else {
21
     } else {
128
     return glGetUniformLocation( program, name.c_str() );
134
     return glGetUniformLocation( program, name.c_str() );
129
 }
135
 }
130
 
136
 
137
+bool slop::Shader::hasParameter( std::string name ) {
138
+    glUseProgram( program );
139
+    return glGetUniformLocation( program, name.c_str() ) != -1;
140
+}
141
+
131
 void slop::Shader::setParameter( std::string name, int foo ) {
142
 void slop::Shader::setParameter( std::string name, int foo ) {
132
     glUniform1i( getUniformLocation( name ), foo );
143
     glUniform1i( getUniformLocation( name ), foo );
133
 }
144
 }

+ 2
- 0
src/shader.hpp View File

33
 #include <GL/gl.h>
33
 #include <GL/gl.h>
34
 
34
 
35
 #include "resource.hpp"
35
 #include "resource.hpp"
36
+#include "x.hpp"
36
 
37
 
37
 namespace slop {
38
 namespace slop {
38
 
39
 
43
     unsigned int    getProgram();
44
     unsigned int    getProgram();
44
     void            bind();
45
     void            bind();
45
     void            unbind();
46
     void            unbind();
47
+    bool            hasParameter( std::string name );
46
     void            setParameter( std::string name, int foo );
48
     void            setParameter( std::string name, int foo );
47
     void            setParameter( std::string name, float foo );
49
     void            setParameter( std::string name, float foo );
48
     void            setParameter( std::string name, glm::mat4& foo );
50
     void            setParameter( std::string name, glm::mat4& foo );

+ 66
- 7
src/slop.cpp View File

41
     nodecorations = false;
41
     nodecorations = false;
42
     tolerance = 2;
42
     tolerance = 2;
43
     padding = 0;
43
     padding = 0;
44
-    shader = "textured";
44
+    shaders.push_back("textured");
45
     highlight = false;
45
     highlight = false;
46
     r = 0.5;
46
     r = 0.5;
47
     g = 0.5;
47
     g = 0.5;
167
 slop::SlopSelection slop::GLSlopSelect( slop::SlopOptions* options, bool* cancelled, SlopWindow* window ) {
167
 slop::SlopSelection slop::GLSlopSelect( slop::SlopOptions* options, bool* cancelled, SlopWindow* window ) {
168
     slop::mouse = new slop::Mouse( x11, options->nodecorations, window->window );
168
     slop::mouse = new slop::Mouse( x11, options->nodecorations, window->window );
169
 
169
 
170
-    if ( options->shader != "textured" ) {
171
-        window->framebuffer->setShader( options->shader );
170
+    std::string vert = "#version 130\nattribute vec2 position;\nattribute vec2 uv;\nvarying vec2 uvCoord;\nvoid main()\n{\nuvCoord = uv;\ngl_Position = vec4(position,0,1);\n}\n";
171
+    std::string frag = "#version 130\n uniform sampler2D texture;\n varying vec2 uvCoord;\n out vec4 outColor;\n void main()\n {\n outColor = texture2D( texture, uvCoord );\n }\n";
172
+    slop::Shader* textured = new slop::Shader( vert, frag, false );
173
+    std::vector<slop::Shader*> shaders;
174
+    for( int i=0;i<options->shaders.size();i++ ) {
175
+        std::string sn = options->shaders[i];
176
+        if ( sn != "textured" ) {
177
+            shaders.push_back( new slop::Shader( sn + ".vert", sn + ".frag" ) );
178
+        } else {
179
+            shaders.push_back( textured );
180
+        }
172
     }
181
     }
173
-
174
     // Init our little state machine, memory is a tad of a misnomer
182
     // Init our little state machine, memory is a tad of a misnomer
175
     slop::SlopMemory memory( options, new GLRectangle(glm::vec2(0,0), glm::vec2(0,0), options->borderSize, options->padding, glm::vec4( options->r, options->g, options->b, options->a ), options->highlight) );
183
     slop::SlopMemory memory( options, new GLRectangle(glm::vec2(0,0), glm::vec2(0,0), options->borderSize, options->padding, glm::vec4( options->r, options->g, options->b, options->a ), options->highlight) );
176
 
184
 
185
+    slop::Framebuffer* pingpong;
186
+    if ( shaders.size() > 1 ) {
187
+        pingpong = new slop::Framebuffer(WidthOfScreen(x11->screen), HeightOfScreen(x11->screen));
188
+    }
189
+
177
     // This is where we'll run through all of our stuffs
190
     // This is where we'll run through all of our stuffs
191
+    auto start = std::chrono::high_resolution_clock::now();
178
     while( memory.running ) {
192
     while( memory.running ) {
179
         slop::mouse->update();
193
         slop::mouse->update();
180
         if ( !options->nokeyboard ) {
194
         if ( !options->nokeyboard ) {
184
         memory.update( 1 );
198
         memory.update( 1 );
185
 
199
 
186
         // Then we draw our junk to a framebuffer.
200
         // Then we draw our junk to a framebuffer.
201
+        window->framebuffer->setShader( textured );
187
         window->framebuffer->bind();
202
         window->framebuffer->bind();
188
         glClearColor (0.0, 0.0, 0.0, 0.0);
203
         glClearColor (0.0, 0.0, 0.0, 0.0);
189
         glClear (GL_COLOR_BUFFER_BIT);
204
         glClear (GL_COLOR_BUFFER_BIT);
190
         memory.draw( window->camera );
205
         memory.draw( window->camera );
191
         window->framebuffer->unbind();
206
         window->framebuffer->unbind();
192
 
207
 
193
-        // Then we draw the framebuffer to the screen
194
-        window->framebuffer->draw();
208
+        auto end = std::chrono::high_resolution_clock::now();
209
+        std::chrono::duration<double, std::milli> elapsed = end-start;
210
+        if ( shaders.size() > 1 ) {
211
+            int i;
212
+            // We have our clean buffer, now to slather it with some juicy shader chains.
213
+            for (i=0;i<=(int)shaders.size()-2;i+=2) {
214
+                pingpong->bind();
215
+                glClearColor (0.0, 0.0, 0.0, 0.0);
216
+                glClear (GL_COLOR_BUFFER_BIT);
217
+                window->framebuffer->setShader( shaders[i] );
218
+                window->framebuffer->draw(slop::mouse->getMousePos(), elapsed.count()/1000.f, glm::vec4( options->r, options->g, options->b, options->a ) );
219
+                pingpong->unbind();
220
+
221
+                window->framebuffer->bind();
222
+                glClearColor (0.0, 0.0, 0.0, 0.0);
223
+                glClear (GL_COLOR_BUFFER_BIT);
224
+                pingpong->setShader( shaders[i+1] );
225
+                pingpong->draw(slop::mouse->getMousePos(), elapsed.count()/1000.f, glm::vec4( options->r, options->g, options->b, options->a ) );
226
+                window->framebuffer->unbind();
227
+            }
228
+            for (;i<shaders.size();i++) {
229
+                pingpong->bind();
230
+                glClearColor (0.0, 0.0, 0.0, 0.0);
231
+                glClear (GL_COLOR_BUFFER_BIT);
232
+                window->framebuffer->setShader( shaders[i] );
233
+                window->framebuffer->draw(slop::mouse->getMousePos(), elapsed.count()/1000.f, glm::vec4( options->r, options->g, options->b, options->a ) );
234
+                pingpong->unbind();
235
+            }
236
+            if ( i%2 != 0 ) {
237
+                window->framebuffer->draw(slop::mouse->getMousePos(), elapsed.count()/1000.f, glm::vec4( options->r, options->g, options->b, options->a ) );
238
+            } else {
239
+                pingpong->draw(slop::mouse->getMousePos(), elapsed.count()/1000.f, glm::vec4( options->r, options->g, options->b, options->a ) );
240
+            }
241
+        } else {
242
+            window->framebuffer->setShader( shaders[0] );
243
+            window->framebuffer->draw(slop::mouse->getMousePos(), elapsed.count()/1000.f, glm::vec4( options->r, options->g, options->b, options->a ) );
244
+        }
245
+
195
         window->display();
246
         window->display();
196
         GLenum err = glGetError();
247
         GLenum err = glGetError();
197
         if ( err != GL_NO_ERROR ) {
248
         if ( err != GL_NO_ERROR ) {
198
-            throw err;
249
+            std::string error;
250
+            switch(err) {
251
+                case GL_INVALID_OPERATION: error="INVALID_OPERATION"; break;
252
+                case GL_INVALID_ENUM: error="INVALID_ENUM"; break;
253
+                case GL_INVALID_VALUE: error="INVALID_VALUE"; break;
254
+                case GL_OUT_OF_MEMORY: error="OUT_OF_MEMORY"; break;
255
+                case GL_INVALID_FRAMEBUFFER_OPERATION: error="INVALID_FRAMEBUFFER_OPERATION"; break;
256
+            }
257
+            throw new std::runtime_error( "OpenGL threw an error: " + error );
199
         }
258
         }
200
         if ( (!options->nokeyboard && slop::keyboard->anyKeyDown()) || slop::mouse->getButton( 3 ) ) {
259
         if ( (!options->nokeyboard && slop::keyboard->anyKeyDown()) || slop::mouse->getButton( 3 ) ) {
201
             memory.running = false;
260
             memory.running = false;

+ 2
- 1
src/slop.hpp View File

22
 #define N_SLOP_H_
22
 #define N_SLOP_H_
23
 
23
 
24
 #include <string>
24
 #include <string>
25
+#include <vector>
25
 
26
 
26
 namespace slop {
27
 namespace slop {
27
 
28
 
35
     bool noopengl;
36
     bool noopengl;
36
     bool nokeyboard;
37
     bool nokeyboard;
37
     int nodecorations;
38
     int nodecorations;
38
-    std::string shader;
39
+    std::vector<std::string> shaders;
39
     float r;
40
     float r;
40
     float g;
41
     float g;
41
     float b;
42
     float b;