From 7c6b5766fa8c2a9a9ccbaec8c4d0a31a357a68f6 Mon Sep 17 00:00:00 2001 From: Ivan Mahonin Date: Aug 22 2015 18:43:54 +0000 Subject: OpenGL 3.3 --- diff --git a/c++/contourgl/Makefile b/c++/contourgl/Makefile index fdd894d..b550e82 100644 --- a/c++/contourgl/Makefile +++ b/c++/contourgl/Makefile @@ -1,9 +1,9 @@ DEPLIBS = gl x11 CXXFLAGS = -O3 -Wall -fmessage-length=0 `pkg-config --libs $(DEPLIBS)` -DGL_GLEXT_PROTOTYPES -DEPS = contour.h contourbuilder.h geometry.h polyspan.h rendersw.h test.h \ - contour.cpp contourbuilder.cpp polyspan.cpp rendersw.cpp test.cpp -OBJS = contour.o contourgl.o contourbuilder.o polyspan.o rendersw.o test.o +DEPS = contour.h contourbuilder.h geometry.h polyspan.h rendersw.h shaders.h test.h \ + contour.cpp contourbuilder.cpp polyspan.cpp rendersw.cpp shaders.cpp test.cpp +OBJS = contour.o contourgl.o contourbuilder.o polyspan.o rendersw.o shaders.o test.o LIBS = `pkg-config --libs $(DEPLIBS)` TARGET = contourgl diff --git a/c++/contourgl/contourgl.cpp b/c++/contourgl/contourgl.cpp index 9da6579..762c5e7 100644 --- a/c++/contourgl/contourgl.cpp +++ b/c++/contourgl/contourgl.cpp @@ -26,6 +26,7 @@ #include #include "test.h" +#include "shaders.h" #define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091 @@ -78,8 +79,8 @@ int main() { // create context int context_attribs[] = { - GLX_CONTEXT_MAJOR_VERSION_ARB, 2, - GLX_CONTEXT_MINOR_VERSION_ARB, 1, + GLX_CONTEXT_MAJOR_VERSION_ARB, 3, + GLX_CONTEXT_MINOR_VERSION_ARB, 3, None }; GLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB = (GLXCREATECONTEXTATTRIBSARBPROC) glXGetProcAddress((const GLubyte*)"glXCreateContextAttribsARB"); GLXContext context = glXCreateContextAttribsARB(display, config, NULL, True, context_attribs); @@ -91,11 +92,15 @@ int main() { // set view port glViewport(0, 0, pbuffer_width, pbuffer_height); + Shaders::initialize(); + // do something - Test::test1(); + //Test::test1(); Test::test2(); Test::test3(); + Shaders::deinitialize(); + // deinitialization glXMakeContextCurrent(display, None, None, NULL); glXDestroyContext(display, context); diff --git a/c++/contourgl/geometry.h b/c++/contourgl/geometry.h index 50f6d0c..b2e018a 100644 --- a/c++/contourgl/geometry.h +++ b/c++/contourgl/geometry.h @@ -53,7 +53,7 @@ public: union { struct { type x, y; }; - struct { type coords[]; }; + struct { type coords[2]; }; }; vec2(): diff --git a/c++/contourgl/polyspan.cpp b/c++/contourgl/polyspan.cpp index ebcea9e..6967c88 100644 --- a/c++/contourgl/polyspan.cpp +++ b/c++/contourgl/polyspan.cpp @@ -81,7 +81,7 @@ void Polyspan::merge_all() { // will sort the marks if they are not sorted void Polyspan::sort_marks() { if (flags & NotSorted) { - //only sort the open index + // only sort the open index addcurrent(); current.setcover(0, 0); diff --git a/c++/contourgl/rendersw.h b/c++/contourgl/rendersw.h index 2da0811..3237b79 100644 --- a/c++/contourgl/rendersw.h +++ b/c++/contourgl/rendersw.h @@ -25,7 +25,11 @@ class Color { public: typedef float type; - type r, g, b, a; + union { + struct { type r, g, b, a; }; + struct { type channels[4]; }; + }; + Color(): r(), g(), b(), a() { } Color(type r, type g, type b, type a): r(r), g(g), b(b), a(a) { } Color(const Color &color, type a): r(color.r), g(color.g), b(color.b), a(color.a*a) { } diff --git a/c++/contourgl/shaders.cpp b/c++/contourgl/shaders.cpp new file mode 100644 index 0000000..87d34cc --- /dev/null +++ b/c++/contourgl/shaders.cpp @@ -0,0 +1,162 @@ +/* + ......... 2015 Ivan Mahonin + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include + +#include + +#include "shaders.h" + + +using namespace std; + + +Shaders* Shaders::instance = NULL; + +void Shaders::initialize() { + assert(!instance); + instance = new Shaders(); +} + +void Shaders::deinitialize() { + assert(instance); + delete instance; +} + +Shaders::Shaders(): + simple_vertex_id(), + simpleProgramId(), + color_fragment_id(), + colorProgramId(), + colorUniform() +{ + // simple + const char *simpleVertexSource = + "in vec2 position;\n" + "void main() { gl_Position = vec4(position, 0.0, 1.0); }\n"; + + simple_vertex_id = glCreateShader(GL_VERTEX_SHADER); + glShaderSource(simple_vertex_id, 1, &simpleVertexSource, NULL); + glCompileShader(simple_vertex_id); + check_shader(simple_vertex_id, simpleVertexSource); + + simpleProgramId = glCreateProgram(); + glAttachShader(simpleProgramId, simple_vertex_id); + glBindAttribLocation(simpleProgramId, 0, "position"); + glLinkProgram(simpleProgramId); + check_program(simpleProgramId, "simple"); + + // color + const char *colorFragmentSource = + "uniform vec4 color;\n" + //"out vec4 colorOut;\n" + "void main() { gl_FragColor = color; }\n"; + + color_fragment_id = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(color_fragment_id, 1, &colorFragmentSource, NULL); + glCompileShader(color_fragment_id); + check_shader(color_fragment_id, colorFragmentSource); + + colorProgramId = glCreateProgram(); + glAttachShader(colorProgramId, simple_vertex_id); + glAttachShader(colorProgramId, color_fragment_id); + glBindAttribLocation(colorProgramId, 0, "position"); + //glBindFragDataLocation(color_program_id, 0, "colorOut"); + glLinkProgram(colorProgramId); + check_program(colorProgramId, "color"); + colorUniform = glGetUniformLocation(colorProgramId, "color"); +} + +Shaders::~Shaders() { + glUseProgram(0); + glDeleteProgram(colorProgramId); + glDeleteProgram(simpleProgramId); + glDeleteShader(color_fragment_id); + glDeleteShader(simple_vertex_id); +} + +void Shaders::check_shader(GLuint id, const char *src) { + GLint compileStatus = 0; + glGetShaderiv(id, GL_COMPILE_STATUS, &compileStatus); + if (!compileStatus) { + GLint infoLogLength = 0; + glGetShaderiv(id, GL_INFO_LOG_LENGTH, &infoLogLength); + std::string infoLog; + infoLog.resize(infoLogLength); + glGetShaderInfoLog(id, infoLog.size(), &infoLogLength, &infoLog[0]); + infoLog.resize(infoLogLength); + cout << "~~~~~~~~~~~~~~~~~~~~~~~~~~~" << endl + << "cannot compile shader:" << endl + << "~~~~~~source~~~~~~~~~~~~~~~" << endl + << src << endl + << "~~~~~~log~~~~~~~~~~~~~~~~~~" << endl + << infoLog << endl + << "~~~~~~~~~~~~~~~~~~~~~~~~~~~" << endl; + } +} + +void Shaders::check_program(GLuint id, const char *name) { + GLint linkStatus = 0; + glGetProgramiv(id, GL_LINK_STATUS, &linkStatus); + if (!linkStatus) { + GLint infoLogLength = 0; + glGetProgramiv(id, GL_INFO_LOG_LENGTH, &infoLogLength); + std::string infoLog; + infoLog.resize(infoLogLength); + glGetProgramInfoLog(id, infoLog.size(), &infoLogLength, &infoLog[0]); + infoLog.resize(infoLogLength); + cout << "~~~~~~~~~~~~~~~~~~~~~~~~~~~" << endl + << "cannot link program " << name << ":" << endl + << "~~~~~~name~~~~~~~~~~~~~~~~~" << endl + << name << endl + << "~~~~~~log~~~~~~~~~~~~~~~~~~" << endl + << infoLog << endl + << "~~~~~~~~~~~~~~~~~~~~~~~~~~~" << endl; + } + + glValidateProgram(id); + GLint validateStatus = 0; + glGetProgramiv(id, GL_VALIDATE_STATUS, &validateStatus); + if (!validateStatus) { + GLint infoLogLength = 0; + glGetProgramiv(id, GL_INFO_LOG_LENGTH, &infoLogLength); + std::string infoLog; + infoLog.resize(infoLogLength); + glGetProgramInfoLog(id, infoLog.size(), &infoLogLength, &infoLog[0]); + infoLog.resize(infoLogLength); + cout << "~~~~~~~~~~~~~~~~~~~~~~~~~~~" << endl + << "program not validated " << name << ":" << endl + << "~~~~~~name~~~~~~~~~~~~~~~~~" << endl + << name << endl + << "~~~~~~log~~~~~~~~~~~~~~~~~~" << endl + << infoLog << endl + << "~~~~~~~~~~~~~~~~~~~~~~~~~~~" << endl; + } +} + +void Shaders::simple() { + assert(instance); + glUseProgram(instance->simpleProgramId); +} + +void Shaders::color(const Color &c) { + assert(instance); + glUseProgram(instance->colorProgramId); + glUniform4fv(instance->colorUniform, 1, c.channels); +} + + diff --git a/c++/contourgl/shaders.h b/c++/contourgl/shaders.h new file mode 100644 index 0000000..33d9fa5 --- /dev/null +++ b/c++/contourgl/shaders.h @@ -0,0 +1,47 @@ +/* + ......... 2015 Ivan Mahonin + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include +#include +#include + +#include "rendersw.h" + +class Shaders { +private: + GLuint simple_vertex_id; + GLuint simpleProgramId; + + GLuint color_fragment_id; + GLuint colorProgramId; + GLint colorUniform; + + Shaders(); + ~Shaders(); + + static Shaders *instance; + + void check_shader(GLuint id, const char *src); + void check_program(GLuint id, const char *name); + +public: + static void initialize(); + static void deinitialize(); + + static void simple(); + static void color(const Color &c); +}; diff --git a/c++/contourgl/test.cpp b/c++/contourgl/test.cpp index e1e9f16..13fbcbf 100644 --- a/c++/contourgl/test.cpp +++ b/c++/contourgl/test.cpp @@ -15,6 +15,8 @@ along with this program. If not, see . */ +#include + #include #include #include @@ -28,6 +30,7 @@ #include "contour.h" #include "rendersw.h" #include "contourbuilder.h" +#include "shaders.h" using namespace std; @@ -132,12 +135,11 @@ public: } static void draw_contour_strip(const int &count) { - glDrawArrays(GL_TRIANGLE_STRIP, 0, count); + glDrawArrays(GL_TRIANGLE_STRIP, 4, count); } template static void draw_contour(const T &c, bool even_odd, bool invert) { - glPushAttrib(GL_ALL_ATTRIB_BITS); glEnable(GL_STENCIL_TEST); // render mask @@ -150,6 +152,7 @@ public: glStencilOpSeparate(GL_FRONT, GL_INCR_WRAP, GL_INCR_WRAP, GL_INCR_WRAP); glStencilOpSeparate(GL_BACK, GL_DECR_WRAP, GL_DECR_WRAP, GL_DECR_WRAP); } + Shaders::simple(); draw_contour_strip(c); // fill mask @@ -164,14 +167,10 @@ public: if ( even_odd && invert) glStencilFunc(GL_EQUAL, 0, 1); - glBegin(GL_TRIANGLE_STRIP); - glVertex2d(-1.0, -1.0); - glVertex2d( 1.0, -1.0); - glVertex2d(-1.0, 1.0); - glVertex2d( 1.0, 1.0); - glEnd(); + Shaders::color(Color(0.f, 0.f, 1.f, 1.f)); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - glPopAttrib(); + glDisable(GL_STENCIL_TEST); } }; @@ -210,7 +209,16 @@ Test::Wrapper::~Wrapper() { } } +void Test::check_gl(const std::string &s) { + GLenum error = glGetError(); + if (error) { + cout << s << " GL error: 0x" << setbase(16) << error << setbase(10) << endl; + } +} + void Test::test1() { + // OpenGl 2 code + vector c; ContourBuilder::build_simple(c); cout << c.size() << " vertices" << endl; @@ -277,33 +285,41 @@ void Test::test2() { const Contour::ChunkList &chunks = c.get_chunks(); cout << chunks.size() << " vertices" << endl; - glPushAttrib(GL_ALL_ATTRIB_BITS); - glColor4d(0.0, 0.0, 1.0, 1.0); - - GLuint buf_id = 0; + GLuint buffer_id = 0; + GLuint array_id = 0; int count = 0; vector< vec2 > vertices; { Wrapper t("test_2_init_buffer"); - vertices.resize(4*chunks.size()); - glGenBuffers(1, &buf_id); - glBindBuffer(GL_ARRAY_BUFFER, buf_id); + vertices.resize(4+4*chunks.size()); + glGenBuffers(1, &buffer_id); + glBindBuffer(GL_ARRAY_BUFFER, buffer_id); glBufferData( GL_ARRAY_BUFFER, vertices.size()*sizeof(vec2), &vertices.front(), GL_DYNAMIC_DRAW ); vertices.clear(); - vertices.reserve(4*chunks.size()); + vertices.reserve(4+4*chunks.size()); - glEnableClientState(GL_VERTEX_ARRAY); - glDrawArrays(GL_TRIANGLES, 0, vertices.size()); + glGenVertexArrays(1, &array_id); + glBindVertexArray(array_id); + + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 2, GL_FLOAT, GL_TRUE, 0, NULL); + Shaders::color(Color(0.f, 0.f, 1.f, 1.f)); + glDrawArrays(GL_TRIANGLE_STRIP, 0, vertices.size()); + glFinish(); glClear(GL_COLOR_BUFFER_BIT); glFinish(); } { Wrapper t("test_2_prepare_data"); + vertices.push_back(vec2(bounds.p0.x, bounds.p0.y)); + vertices.push_back(vec2(bounds.p0.x, bounds.p1.y)); + vertices.push_back(vec2(bounds.p1.x, bounds.p0.y)); + vertices.push_back(vec2(bounds.p1.x, bounds.p1.y)); vertices.push_back(vec2()); vertices.push_back(vec2()); for(Contour::ChunkList::const_iterator i = chunks.begin(); i != chunks.end(); ++i) { @@ -319,33 +335,29 @@ void Test::test2() { vertices.push_back(vertices.back()); } } - count = vertices.size(); + count = vertices.size() - 4; } { Wrapper t("test_2_send_data"); glBufferSubData( GL_ARRAY_BUFFER, 0, - vertices.size()*sizeof(vec2), + vertices.size()*sizeof(vertices.front()), &vertices.front() ); - glVertexPointer(2, GL_FLOAT, sizeof(vec2), 0); } + { - Wrapper t("test_2_contour.tga"); - glBegin(GL_LINE_STRIP); - for(Contour::ChunkList::const_iterator i = chunks.begin(); i != chunks.end(); ++i) - glVertex2d(i->p1.x, i->p1.y); - glEnd(); + Wrapper t("test_2_simple_fill.tga"); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } - glPushAttrib(GL_ALL_ATTRIB_BITS); - //glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); { Wrapper t("test_2_array.tga"); - glDrawArrays(GL_POINTS, 0, count); + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + glDrawArrays(GL_TRIANGLE_STRIP, 4, count); + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); } - glPopAttrib(); { Wrapper t("test_2_contour_fill.tga"); @@ -367,10 +379,8 @@ void Test::test2() { Helper::draw_contour(count, true, true); } - glDisableClientState(GL_VERTEX_ARRAY); glBindBuffer(GL_ARRAY_BUFFER, 0); - glDeleteBuffers(1, &buf_id); - glPopAttrib(); + glDeleteBuffers(1, &buffer_id); } void Test::test3() { diff --git a/c++/contourgl/test.h b/c++/contourgl/test.h index 6bfa1ce..c204199 100644 --- a/c++/contourgl/test.h +++ b/c++/contourgl/test.h @@ -46,6 +46,8 @@ private: class Helper; public: + static void check_gl(const std::string &s = std::string()); + static void test1(); static void test2(); static void test3();