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,7 +21,7 @@ endif()
21 21
 
22 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 26
 # The names have to be unique unfortunately.
27 27
 set(EXECUTABLE_NAME "slop")

+ 35
- 7
src/framebuffer.cpp View File

@@ -1,9 +1,6 @@
1 1
 #include "framebuffer.hpp"
2 2
 
3 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 4
     glGenFramebuffers( 1, &fbuffer );
8 5
     glBindFramebuffer( GL_FRAMEBUFFER, fbuffer );
9 6
     glGenTextures(1, &image);
@@ -11,6 +8,8 @@ slop::Framebuffer::Framebuffer( int w, int h ) {
11 8
     glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
12 9
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
13 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 13
     glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, image, 0);
15 14
     glBindFramebuffer(GL_FRAMEBUFFER, 0);
16 15
     // generate our vertex and uv buffers
@@ -36,11 +35,23 @@ slop::Framebuffer::Framebuffer( int w, int h ) {
36 35
     glBindBuffer( GL_ARRAY_BUFFER, buffers[1] );
37 36
     glBufferData( GL_ARRAY_BUFFER, uvs.size() * sizeof( glm::vec2 ), &uvs[0], GL_STATIC_DRAW );
38 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 57
 slop::Framebuffer::~Framebuffer() {
@@ -72,13 +83,30 @@ void slop::Framebuffer::unbind() {
72 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 87
     shader->bind();
77 88
     shader->setParameter( "texture", 0 );
78 89
     shader->setAttribute( "position", buffers[0], 2 );
79 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 103
     glActiveTexture(GL_TEXTURE0);
81 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 110
     glEnable( GL_TEXTURE_2D );
83 111
     glDrawArrays( GL_TRIANGLES, 0, vertCount );
84 112
     glDisable( GL_TEXTURE_2D );

+ 4
- 2
src/framebuffer.hpp View File

@@ -36,12 +36,14 @@ private:
36 36
     unsigned int image;
37 37
     unsigned int buffers[2];
38 38
     unsigned int vertCount;
39
+    unsigned int desktopImage;
40
+    bool generatedDesktopImage;
39 41
     Shader* shader;
40 42
 public:
41 43
     Framebuffer( int w, int h );
42 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 47
     void resize( int w, int h );
46 48
     void bind();
47 49
     void unbind();

+ 18
- 1
src/main.cpp View File

@@ -25,6 +25,21 @@
25 25
 
26 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 43
 SlopOptions* getOptions( Options& options ) {
29 44
     SlopOptions* foo = new SlopOptions();
30 45
     options.getFloat("bordersize", 'b', foo->borderSize);
@@ -35,7 +50,9 @@ SlopOptions* getOptions( Options& options ) {
35 50
     options.getBool("nokeyboard", 'k', foo->nokeyboard);
36 51
     options.getBool("noopengl", 'o', foo->noopengl);
37 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 56
     foo->r = color.r;
40 57
     foo->g = color.g;
41 58
     foo->b = color.b;

+ 11
- 0
src/shader.cpp View File

@@ -7,9 +7,15 @@ slop::Shader::Shader( std::string vert, std::string frag, bool file ) {
7 7
         vert = resource->getRealPath(vert);
8 8
         frag = resource->getRealPath(frag);
9 9
         std::ifstream v( vert.c_str() );
10
+        if (!v.is_open()) {
11
+            throw new std::runtime_error( "Failed to open " + vert );
12
+        }
10 13
         vert_contents = std::string((std::istreambuf_iterator<char>(v)),
11 14
                                    std::istreambuf_iterator<char>());
12 15
         std::ifstream f( frag.c_str() );
16
+        if (!f.is_open()) {
17
+            throw new std::runtime_error( "Failed to open " + frag );
18
+        }
13 19
         frag_contents = std::string((std::istreambuf_iterator<char>(f)),
14 20
                                   std::istreambuf_iterator<char>());
15 21
     } else {
@@ -128,6 +134,11 @@ unsigned int slop::Shader::getUniformLocation( std::string name ) {
128 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 142
 void slop::Shader::setParameter( std::string name, int foo ) {
132 143
     glUniform1i( getUniformLocation( name ), foo );
133 144
 }

+ 2
- 0
src/shader.hpp View File

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

+ 66
- 7
src/slop.cpp View File

@@ -41,7 +41,7 @@ slop::SlopOptions::SlopOptions() {
41 41
     nodecorations = false;
42 42
     tolerance = 2;
43 43
     padding = 0;
44
-    shader = "textured";
44
+    shaders.push_back("textured");
45 45
     highlight = false;
46 46
     r = 0.5;
47 47
     g = 0.5;
@@ -167,14 +167,28 @@ slop::SlopSelection slop::XShapeSlopSelect( slop::SlopOptions* options, bool* ca
167 167
 slop::SlopSelection slop::GLSlopSelect( slop::SlopOptions* options, bool* cancelled, SlopWindow* window ) {
168 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 182
     // Init our little state machine, memory is a tad of a misnomer
175 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 190
     // This is where we'll run through all of our stuffs
191
+    auto start = std::chrono::high_resolution_clock::now();
178 192
     while( memory.running ) {
179 193
         slop::mouse->update();
180 194
         if ( !options->nokeyboard ) {
@@ -184,18 +198,63 @@ slop::SlopSelection slop::GLSlopSelect( slop::SlopOptions* options, bool* cancel
184 198
         memory.update( 1 );
185 199
 
186 200
         // Then we draw our junk to a framebuffer.
201
+        window->framebuffer->setShader( textured );
187 202
         window->framebuffer->bind();
188 203
         glClearColor (0.0, 0.0, 0.0, 0.0);
189 204
         glClear (GL_COLOR_BUFFER_BIT);
190 205
         memory.draw( window->camera );
191 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 246
         window->display();
196 247
         GLenum err = glGetError();
197 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 259
         if ( (!options->nokeyboard && slop::keyboard->anyKeyDown()) || slop::mouse->getButton( 3 ) ) {
201 260
             memory.running = false;

+ 2
- 1
src/slop.hpp View File

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