git.haldean.org ana / f4f70af
drawing nodes Haldean Brown 1 year, 9 months ago
9 changed file(s) with 229 addition(s) and 98 deletion(s). Raw diff Collapse all Expand all
55 find_package(SDL2 REQUIRED)
66 find_package(GLEW REQUIRED)
77
8 set(CMAKE_CXX_FLAGS "-Wall -Werror")
9
810 include_directories(lib)
911
1012 add_executable(ana
1113 src/ana.cpp
14 src/node.cpp
1215 src/shaders.cpp
1316 lib/wbogl/shader_utils.cpp)
1417
237237 "OpenGL %d.%d %s", major, minor, profile_str);
238238 }
239239
240 GLuint create_shader_from_string(const char* src, GLenum type) {
240 GLuint create_shader_from_string(const std::string &src, GLenum type) {
241241 GLuint res = glCreateShader(type);
242 glShaderSource(res, 1, &src, nullptr);
242 const GLchar *csrc = src.c_str();
243 GLint len = src.length();
244 glShaderSource(res, 1, &csrc, &len);
243245 glCompileShader(res);
244246
245247 GLint compile_ok = GL_FALSE;
22 * This file is in the public domain.
33 * Contributors: Sylvain Beucler
44 */
5 #ifndef _CREATE_SHADER_H
6 #define _CREATE_SHADER_H
5 #pragma once
76 #include <GL/glew.h>
7 #include <string>
88
99 extern char* file_read(const char* filename, int* size);
1010 extern void print_log(GLuint object);
1111 extern GLuint create_shader(const char* filename, GLenum type);
12 extern GLuint create_shader_from_string(const char* src, GLenum type);
12 extern GLuint create_shader_from_string(const std::string &src, GLenum type);
1313 extern GLuint create_program(const char* vertexfile, const char *fragmentfile);
1414 extern GLuint create_gs_program(const char* vertexfile, const char *geometryfile, const char *fragmentfile, GLint input, GLint output, GLint vertices);
1515 extern GLint get_attrib(GLuint program, const char *name);
1616 extern GLint get_uniform(GLuint program, const char *name);
1717 extern void print_opengl_info();
18
19 #endif
0
1 #include <cstdlib>
02 #include <iostream>
13
24 #include <GL/glew.h>
57 #include "node.hpp"
68 #include "shaders.hpp"
79
8 float points[] = {
9 -0.5f, 0.5f,
10 0.5f, 0.5f,
11 0.5f, -0.5f,
12 -0.5f, -0.5f
13 };
10 int main(void) {
11 SDL_Init(SDL_INIT_VIDEO);
12 SDL_Window* window = SDL_CreateWindow("ana",
13 SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 400,
14 SDL_WINDOW_RESIZABLE | SDL_WINDOW_OPENGL);
1415
15 int main() {
16 SDL_Init(SDL_INIT_VIDEO);
17 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
18 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
19
20 SDL_Window *w = SDL_CreateWindow(
21 "ana", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
22 640, 480, SDL_WINDOW_RESIZABLE | SDL_WINDOW_OPENGL);
23 SDL_GL_CreateContext(w);
24
25 GLenum glew_status = glewInit();
26 if (glew_status != GLEW_OK) {
27 std::cerr << "[E] glewInit: "
28 << glewGetErrorString(glew_status)
29 << std::endl;
16 if (window == NULL) {
17 std::cerr << "[E] create window: " << SDL_GetError() << std::endl;
18 return EXIT_FAILURE;
19 }
20 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
21 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
22 SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
23 SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 1);
24 if (SDL_GL_CreateContext(window) == NULL) {
25 std::cerr << "[E] SDL_GL_CreateContext: " << SDL_GetError() << std::endl;
3026 return EXIT_FAILURE;
3127 }
3228
33 if (!ana::shaders::init()) {
34 std::cerr << "[E] couldn't initialize shaders";
35 return EXIT_FAILURE;
36 }
29 GLenum glew_status = glewInit();
30 if (glew_status != GLEW_OK) {
31 std::cerr << "[E] glewInit: " << glewGetErrorString(glew_status) << std::endl;
32 return EXIT_FAILURE;
33 }
3734
38 GLint attrib_coord2d = glGetAttribLocation(ana::shaders::program(), "coord2d");
39 if (attrib_coord2d == -1) {
40 std::cerr << "[E] couldn't bind to coord2d" << std::endl;
41 return EXIT_FAILURE;
42 }
35 if (!ana::shaders::init())
36 return EXIT_FAILURE;
4337
44 GLuint vbo_locs;
45 glGenBuffers(1, &vbo_locs);
46 glBindBuffer(GL_ARRAY_BUFFER, vbo_locs);
47 glBufferData(GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW);
38 glEnable(GL_BLEND);
39 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4840
49 bool ok = true;
50 while (ok) {
51 SDL_Event ev;
52 while (SDL_PollEvent(&ev)) {
53 if (ev.type == SDL_QUIT) {
54 ok = false;
41 ana::nodeset nodes;
42 nodes.nodes.push_back(ana::node{glm::vec2(0, 0), glm::vec2(0.1, 0.2), "hello"});
43 nodes.nodes.push_back(ana::node{glm::vec2(-0.5, -0.5), glm::vec2(0.2, 0.2), "hello"});
44
45 bool run = true;
46 while (run) {
47 SDL_Event ev;
48 while (SDL_PollEvent(&ev)) {
49 if (ev.type == SDL_QUIT) {
50 run = false;
51 } else if (ev.type == SDL_WINDOWEVENT) {
52 if (ev.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
53 glViewport(0, 0, ev.window.data1, ev.window.data2);
54 }
5555 }
56 }
57 glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
58 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
56 }
57 glClearColor(0.15, 0.12, 0.1, 1.0);
58 glClear(GL_COLOR_BUFFER_BIT);
5959
60 glUseProgram(ana::shaders::program());
60 ana::shaders::draw(nodes);
6161
62 glBindBuffer(GL_ARRAY_BUFFER, vbo_locs);
63 glEnableVertexAttribArray(attrib_coord2d);
64 glVertexAttribPointer(
65 attrib_coord2d,
66 2, // number of elements per vertex, here (x,y)
67 GL_FLOAT, // the type of each element
68 GL_FALSE, // take our values as-is
69 0, // no extra data between each position
70 0 // offset of first element
71 );
72 glDrawArrays(GL_POINTS, 0, 4);
73 glDisableVertexAttribArray(attrib_coord2d);
62 SDL_GL_SwapWindow(window);
63 }
7464
75 SDL_GL_SwapWindow(w);
76 }
77
78 return EXIT_SUCCESS;
65 ana::shaders::destroy();
66 return EXIT_SUCCESS;
7967 }
0 #pragma once
1 #include <iostream>
2 #include <GL/gl.h>
3
4 namespace ana {
5 namespace glerr {
6 extern inline void
7 print(int line, GLenum err) {
8 std::cerr << "[W] gl error on line " << line << ": ";
9 std::string msg;
10 switch (err) {
11 case GL_INVALID_ENUM: msg = "GL_INVALID_ENUM"; break;
12 case GL_INVALID_VALUE: msg = "GL_INVALID_VALUE"; break;
13 case GL_INVALID_OPERATION: msg = "GL_INVALID_OPERATION"; break;
14 case GL_INVALID_FRAMEBUFFER_OPERATION: msg = "GL_INVALID_FRAMEBUFFER_OPERATION"; break;
15 case GL_OUT_OF_MEMORY: msg = "GL_OUT_OF_MEMORY"; break;
16 case GL_STACK_UNDERFLOW: msg = "GL_STACK_UNDERFLOW"; break;
17 case GL_STACK_OVERFLOW: msg = "GL_STACK_OVERFLOW"; break;
18 default: msg = "UNKNOWN"; break;
19 }
20 std::cerr << msg << " (code " << err << ")" << std::endl;
21 }
22 }
23 }
24
25 #define INSERT_GL_ERROR_CHECK do { GLenum err = glGetError(); if (err != 0) ana::glerr::print(__LINE__, err); } while(0)
0 #include "node.hpp"
1
2 namespace ana {
3
4 node::node(glm::vec2 loc, glm::vec2 size, std::string n)
5 : loc(loc), size(size), name(n) {}
6
7 size_t nodeset::size() const {
8 return nodes.size();
9 }
10
11 }
0 #pragma once
01 #include <glm/vec2.hpp>
12 #include <string>
3 #include <vector>
4
5 namespace ana {
26
37 struct node {
48 glm::vec2 loc;
9 glm::vec2 size;
510 std::string name;
11
12 node() = default;
13 node(const node&) = default;
14 node(glm::vec2 loc, glm::vec2 size, std::string n);
615 };
16
17 struct nodeset {
18 std::vector<node> nodes;
19 size_t size() const;
20 };
21
22 }
00 #include "shaders.hpp"
1 #include "glerr.hpp"
2 #include "node.hpp"
13 #include "wbogl/shader_utils.hpp"
24
35 #include <iostream>
68 namespace ana {
79 namespace shaders {
810
9 static const std::string node_vert_src = R"(
10 #version 420 core
11 layout (location = 0) in vec2 coord2d;
11 static const std::string node_vert_src = R"(
12 #version 330 core
13 layout (location = 0) in vec2 pos;
14 layout (location = 1) in vec2 size;
15 out NODE_DATA {
16 vec2 size;
17 } node_data;
18
1219 void main(void) {
13 gl_Position = vec4(coord2d, 0.0, 1.0);
20 gl_Position = vec4(pos, 0.0, 1.0);
21 node_data.size = size;
1422 }
1523 )";
1624
17 static const std::string node_frag_src = R"(
18 #version 420 core
25 static const std::string node_frag_src = R"(
26 #version 330 core
1927 out vec4 Color;
2028
2129 void main()
2230 {
23 Color = vec4(0.0, 1.0, 0.0, 1.0);
31 Color = vec4(1.0, 1.0, 1.0, 0.8);
2432 }
2533 )";
2634
27 static const std::string node_geo_src = R"(
28 #version 420 core
35 static const std::string node_geo_src = R"(
36 #version 330 core
2937 layout (points) in;
3038 layout (triangle_strip, max_vertices = 4) out;
39 in NODE_DATA {
40 vec2 size;
41 } nd[];
3142
3243 void main() {
3344 vec4 p = gl_in[0].gl_Position;
45 vec2 s = nd[0].size;
3446 gl_Position = p;
3547 EmitVertex();
36 gl_Position = p + vec4(0.5, 0, 0, 0);
48 gl_Position = p + vec4(s[0], 0, 0, 0);
3749 EmitVertex();
38 gl_Position = p + vec4(0, 0.5, 0, 0);
50 gl_Position = p + vec4(0, s[1], 0, 0);
3951 EmitVertex();
40 gl_Position = p + vec4(0.5, 0.5, 0, 0);
52 gl_Position = p + vec4(s[0], s[1], 0, 0);
4153 EmitVertex();
4254 EndPrimitive();
4355 }
4456 )";
4557
46 static GLuint program_id = 0;
58 static GLuint node_program_id = 0;
59 static GLint node_program_pos = -1;
60 static GLint node_program_size = -1;
61 static GLuint node_loc_buf = 0;
62 static GLuint node_size_buf = 0;
4763
4864 bool init(void) {
4965 GLuint vs, fs, gs;
50 if (!(vs = create_shader_from_string(node_vert_src.c_str(), GL_VERTEX_SHADER))) {
66 if (!(vs = create_shader_from_string(node_vert_src, GL_VERTEX_SHADER))) {
5167 std::cerr << "[E] vert shader couldn't be loaded" << std::endl;
5268 return false;
5369 }
54 if (!(fs = create_shader_from_string(node_frag_src.c_str(), GL_FRAGMENT_SHADER))) {
70 if (!(fs = create_shader_from_string(node_frag_src, GL_FRAGMENT_SHADER))) {
5571 std::cerr << "[E] frag shader couldn't be loaded" << std::endl;
5672 return false;
5773 }
58 if (!(gs = create_shader_from_string(node_geo_src.c_str(), GL_GEOMETRY_SHADER))) {
74 if (!(gs = create_shader_from_string(node_geo_src, GL_GEOMETRY_SHADER))) {
5975 std::cerr << "[E] geometry shader couldn't be loaded" << std::endl;
6076 return false;
6177 }
62 program_id = glCreateProgram();
63 glAttachShader(program_id, vs);
64 glAttachShader(program_id, fs);
65 glAttachShader(program_id, gs);
66 glLinkProgram(program_id);
78 node_program_id = glCreateProgram();
79 glAttachShader(node_program_id, vs);
80 glAttachShader(node_program_id, fs);
81 glAttachShader(node_program_id, gs);
82 glLinkProgram(node_program_id);
6783 GLint link_ok;
68 glGetProgramiv(program_id, GL_LINK_STATUS, &link_ok);
84 glGetProgramiv(node_program_id, GL_LINK_STATUS, &link_ok);
6985 if (!link_ok) {
70 std::cerr << "glLinkProgram: ";
71 print_log(program_id);
72 program_id = 0;
73 return false;
74 }
86 std::cerr << "[E] glLinkProgram: ";
87 print_log(node_program_id);
88 std::cerr << std::endl << "vert src:" << std::endl << node_vert_src;
89 std::cerr << std::endl << "frag src:" << std::endl << node_frag_src;
90 std::cerr << std::endl << "geo src:" << std::endl << node_geo_src;
91 node_program_id = 0;
92 return false;
93 }
94
95 node_program_pos = glGetAttribLocation(node_program_id, "pos");
96 if (node_program_pos == -1) {
97 std::cerr << "[E] glGetAttribLocation failed for pos" << std::endl;
98 return false;
99 }
100 node_program_size = glGetAttribLocation(node_program_id, "size");
101 if (node_program_pos == -1) {
102 std::cerr << "[E] glGetAttribLocation failed for pos" << std::endl;
103 return false;
104 }
105
106 GLuint vao;
107 glGenVertexArrays(1, &vao);
108 INSERT_GL_ERROR_CHECK;
109 glBindVertexArray(vao);
110 INSERT_GL_ERROR_CHECK;
111
112 GLuint bufs[2];
113 glGenBuffers(2, bufs);
114 INSERT_GL_ERROR_CHECK;
115 node_loc_buf = bufs[0];
116 node_size_buf = bufs[1];
117
75118 return true;
76119 }
77120
78 GLuint program(void) {
79 return program_id;
121 GLuint node_program(void) {
122 return node_program_id;
123 }
124
125 void draw(const ana::nodeset &nodes) {
126 size_t elems = nodes.size() * 2;
127 GLfloat *pos = (GLfloat*) calloc(sizeof(GLfloat), elems);
128 GLfloat *size = (GLfloat*) calloc(sizeof(GLfloat), elems);
129 int i = 0;
130 for (const ana::node &n : nodes.nodes) {
131 pos[2 * i + 0] = n.loc.x;
132 pos[2 * i + 1] = n.loc.y;
133 size[2 * i + 0] = n.size.x;
134 size[2 * i + 1] = n.size.y;
135 i++;
136 }
137
138 glBindBuffer(GL_ARRAY_BUFFER, node_loc_buf);
139 INSERT_GL_ERROR_CHECK;
140 glBufferData(GL_ARRAY_BUFFER, elems * sizeof(GLfloat), pos, GL_DYNAMIC_DRAW);
141 INSERT_GL_ERROR_CHECK;
142 glBindBuffer(GL_ARRAY_BUFFER, node_size_buf);
143 INSERT_GL_ERROR_CHECK;
144 glBufferData(GL_ARRAY_BUFFER, elems * sizeof(GLfloat), size, GL_DYNAMIC_DRAW);
145 INSERT_GL_ERROR_CHECK;
146
147 free(pos);
148 free(size);
149
150 glUseProgram(node_program_id); INSERT_GL_ERROR_CHECK;
151 glEnableVertexAttribArray(node_program_pos); INSERT_GL_ERROR_CHECK;
152 glEnableVertexAttribArray(node_program_size); INSERT_GL_ERROR_CHECK;
153 glBindBuffer(GL_ARRAY_BUFFER, node_loc_buf); INSERT_GL_ERROR_CHECK;
154 glVertexAttribPointer(node_program_pos, 2, GL_FLOAT, GL_FALSE, 0, 0); INSERT_GL_ERROR_CHECK;
155 glBindBuffer(GL_ARRAY_BUFFER, node_size_buf); INSERT_GL_ERROR_CHECK;
156 glVertexAttribPointer(node_program_size, 2, GL_FLOAT, GL_FALSE, 0, 0); INSERT_GL_ERROR_CHECK;
157 glDrawArrays(GL_POINTS, 0, nodes.size()); INSERT_GL_ERROR_CHECK;
158 glDisableVertexAttribArray(node_program_pos); INSERT_GL_ERROR_CHECK;
159 glDisableVertexAttribArray(node_program_size); INSERT_GL_ERROR_CHECK;
160 }
161
162 void destroy(void) {
163 glDeleteProgram(node_program_id);
164 glDeleteBuffers(1, &node_loc_buf);
80165 }
81166
82167 }
00 #pragma once
11
22 #include <GL/glew.h>
3 #include "node.hpp"
34
45 namespace ana {
56 namespace shaders {
67
78 bool init(void);
8 GLuint program(void);
9
9 void destroy(void);
10 void draw(const ana::nodeset &nodes);
1011 }
1112 }