git.haldean.org ana / 4df91cf
start experimenting with geometry shaders Haldean Brown 1 year, 9 months ago
7 changed file(s) with 434 addition(s) and 3 deletion(s). Raw diff Collapse all Expand all
55 find_package(SDL2 REQUIRED)
66 find_package(GLEW REQUIRED)
77
8 add_executable(ana src/ana.cpp)
9 target_link_libraries(ana glm SDL2 GLEW)
8 include_directories(lib)
9
10 add_executable(ana
11 src/ana.cpp
12 src/shaders.cpp
13 lib/wbogl/shader_utils.cpp)
14
15 target_link_libraries(ana glm SDL2 GLEW GL)
0 /**
1 * From the OpenGL Programming wikibook: http://en.wikibooks.org/wiki/OpenGL_Programming
2 * This file is in the public domain.
3 * Contributors: Sylvain Beucler
4 */
5
6 #include <iostream>
7 using namespace std;
8
9 #include <SDL2/SDL.h>
10 #include <GL/glew.h>
11
12 /**
13 * Store all the file's contents in memory, useful to pass shaders
14 * source code to OpenGL. Using SDL_RWops for Android asset support.
15 */
16 char* file_read(const char* filename, int* size) {
17 SDL_RWops *rw = SDL_RWFromFile(filename, "rb");
18 if (rw == NULL) return NULL;
19
20 Sint64 res_size = SDL_RWsize(rw);
21 char* res = (char*)malloc(res_size + 1);
22
23 Sint64 nb_read_total = 0, nb_read = 1;
24 char* buf = res;
25 while (nb_read_total < res_size && nb_read != 0) {
26 nb_read = SDL_RWread(rw, buf, 1, (res_size - nb_read_total));
27 nb_read_total += nb_read;
28 buf += nb_read;
29 }
30 SDL_RWclose(rw);
31 if (nb_read_total != res_size) {
32 free(res);
33 return NULL;
34 }
35
36 res[nb_read_total] = '\0';
37 if (size != NULL)
38 *size = nb_read_total;
39 return res;
40 }
41
42 /**
43 * Display compilation errors from the OpenGL shader compiler
44 */
45 void print_log(GLuint object) {
46 GLint log_length = 0;
47 if (glIsShader(object)) {
48 glGetShaderiv(object, GL_INFO_LOG_LENGTH, &log_length);
49 } else if (glIsProgram(object)) {
50 glGetProgramiv(object, GL_INFO_LOG_LENGTH, &log_length);
51 } else {
52 SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_ERROR,
53 "printlog: Not a shader or a program");
54 return;
55 }
56
57 char* log = (char*)malloc(log_length);
58
59 if (glIsShader(object))
60 glGetShaderInfoLog(object, log_length, NULL, log);
61 else if (glIsProgram(object))
62 glGetProgramInfoLog(object, log_length, NULL, log);
63
64 SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_ERROR, "%s\n", log);
65 free(log);
66 }
67
68 /**
69 * Compile the shader from file 'filename', with error handling
70 */
71 GLuint create_shader(const char* filename, GLenum type) {
72 const GLchar* source = file_read(filename, NULL);
73 if (source == NULL) {
74 SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_ERROR,
75 "Error opening %s: %s", filename, SDL_GetError());
76 return 0;
77 }
78 GLuint res = glCreateShader(type);
79
80 // GLSL version
81 const char* version;
82 int profile;
83 SDL_GL_GetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, &profile);
84 if (profile == SDL_GL_CONTEXT_PROFILE_ES)
85 version = "#version 100\n"; // OpenGL ES 2.0
86 else
87 version = "#version 120\n"; // OpenGL 2.1
88
89 // GLES2 precision specifiers
90 const char* precision;
91 precision =
92 "#ifdef GL_ES \n"
93 "# ifdef GL_FRAGMENT_PRECISION_HIGH \n"
94 " precision highp float; \n"
95 "# else \n"
96 " precision mediump float; \n"
97 "# endif \n"
98 "#else \n"
99 // Ignore unsupported precision specifiers
100 "# define lowp \n"
101 "# define mediump \n"
102 "# define highp \n"
103 "#endif \n";
104
105 const GLchar* sources[] = {
106 version,
107 precision,
108 source
109 };
110 glShaderSource(res, 3, sources, NULL);
111 free((void*)source);
112
113 glCompileShader(res);
114 GLint compile_ok = GL_FALSE;
115 glGetShaderiv(res, GL_COMPILE_STATUS, &compile_ok);
116 if (compile_ok == GL_FALSE) {
117 SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_ERROR, "%s:\n", filename);
118 print_log(res);
119 glDeleteShader(res);
120 return 0;
121 }
122
123 return res;
124 }
125
126 GLuint create_program(const char *vertexfile, const char *fragmentfile) {
127 GLuint program = glCreateProgram();
128 GLuint shader;
129
130 if(vertexfile) {
131 shader = create_shader(vertexfile, GL_VERTEX_SHADER);
132 if(!shader)
133 return 0;
134 glAttachShader(program, shader);
135 }
136
137 if(fragmentfile) {
138 shader = create_shader(fragmentfile, GL_FRAGMENT_SHADER);
139 if(!shader)
140 return 0;
141 glAttachShader(program, shader);
142 }
143
144 glLinkProgram(program);
145 GLint link_ok = GL_FALSE;
146 glGetProgramiv(program, GL_LINK_STATUS, &link_ok);
147 if (!link_ok) {
148 SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, "glLinkProgram:");
149 print_log(program);
150 glDeleteProgram(program);
151 return 0;
152 }
153
154 return program;
155 }
156
157 #ifdef GL_GEOMETRY_SHADER
158 GLuint create_gs_program(const char *vertexfile, const char *geometryfile, const char *fragmentfile, GLint input, GLint output, GLint vertices) {
159 GLuint program = glCreateProgram();
160 GLuint shader;
161
162 if(vertexfile) {
163 shader = create_shader(vertexfile, GL_VERTEX_SHADER);
164 if(!shader)
165 return 0;
166 glAttachShader(program, shader);
167 }
168
169 if(geometryfile) {
170 shader = create_shader(geometryfile, GL_GEOMETRY_SHADER);
171 if(!shader)
172 return 0;
173 glAttachShader(program, shader);
174
175 glProgramParameteriEXT(program, GL_GEOMETRY_INPUT_TYPE_EXT, input);
176 glProgramParameteriEXT(program, GL_GEOMETRY_OUTPUT_TYPE_EXT, output);
177 glProgramParameteriEXT(program, GL_GEOMETRY_VERTICES_OUT_EXT, vertices);
178 }
179
180 if(fragmentfile) {
181 shader = create_shader(fragmentfile, GL_FRAGMENT_SHADER);
182 if(!shader)
183 return 0;
184 glAttachShader(program, shader);
185 }
186
187 glLinkProgram(program);
188 GLint link_ok = GL_FALSE;
189 glGetProgramiv(program, GL_LINK_STATUS, &link_ok);
190 if (!link_ok) {
191 SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_ERROR, "glLinkProgram:");
192 print_log(program);
193 glDeleteProgram(program);
194 return 0;
195 }
196
197 return program;
198 }
199 #else
200 GLuint create_gs_program(const char *vertexfile, const char *geometryfile, const char *fragmentfile, GLint input, GLint output, GLint vertices) {
201 SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_ERROR,
202 "Missing support for geometry shaders.");
203 return 0;
204 }
205 #endif
206
207 GLint get_attrib(GLuint program, const char *name) {
208 GLint attribute = glGetAttribLocation(program, name);
209 if(attribute == -1)
210 SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_ERROR,
211 "Could not bind attribute %s", name);
212 return attribute;
213 }
214
215 GLint get_uniform(GLuint program, const char *name) {
216 GLint uniform = glGetUniformLocation(program, name);
217 if(uniform == -1)
218 SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_ERROR,
219 "Could not bind uniform %s", name);
220 return uniform;
221 }
222
223 void print_opengl_info() {
224 int major, minor, profile;
225 SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &major);
226 SDL_GL_GetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, &minor);
227 SDL_GL_GetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, &profile);
228 const char* profile_str = "";
229 if (profile & SDL_GL_CONTEXT_PROFILE_CORE)
230 profile_str = "CORE";
231 if (profile & SDL_GL_CONTEXT_PROFILE_COMPATIBILITY)
232 profile_str = "COMPATIBILITY";
233 if (profile & SDL_GL_CONTEXT_PROFILE_ES)
234 profile_str = "ES";
235
236 SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO,
237 "OpenGL %d.%d %s", major, minor, profile_str);
238 }
239
240 GLuint create_shader_from_string(const char* src, GLenum type) {
241 GLuint res = glCreateShader(type);
242 glShaderSource(res, 1, &src, nullptr);
243 glCompileShader(res);
244
245 GLint compile_ok = GL_FALSE;
246 glGetShaderiv(res, GL_COMPILE_STATUS, &compile_ok);
247 if (compile_ok == GL_FALSE) {
248 SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_ERROR, "error loading shader:");
249 print_log(res);
250 glDeleteShader(res);
251 return 0;
252 }
253 return res;
254 }
0 /**
1 * From the OpenGL Programming wikibook: http://en.wikibooks.org/wiki/OpenGL_Programming
2 * This file is in the public domain.
3 * Contributors: Sylvain Beucler
4 */
5 #ifndef _CREATE_SHADER_H
6 #define _CREATE_SHADER_H
7 #include <GL/glew.h>
8
9 extern char* file_read(const char* filename, int* size);
10 extern void print_log(GLuint object);
11 extern GLuint create_shader(const char* filename, GLenum type);
12 extern GLuint create_shader_from_string(const char* src, GLenum type);
13 extern GLuint create_program(const char* vertexfile, const char *fragmentfile);
14 extern GLuint create_gs_program(const char* vertexfile, const char *geometryfile, const char *fragmentfile, GLint input, GLint output, GLint vertices);
15 extern GLint get_attrib(GLuint program, const char *name);
16 extern GLint get_uniform(GLuint program, const char *name);
17 extern void print_opengl_info();
18
19 #endif
22 #include <GL/glew.h>
33 #include <SDL2/SDL.h>
44
5 #include "node.hpp"
6 #include "shaders.hpp"
7
8 float points[] = {
9 -0.5f, 0.5f,
10 0.5f, 0.5f,
11 0.5f, -0.5f,
12 -0.5f, -0.5f
13 };
14
515 int main() {
616 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
720 SDL_Window *w = SDL_CreateWindow(
821 "ana", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
922 640, 480, SDL_WINDOW_RESIZABLE | SDL_WINDOW_OPENGL);
1730 return EXIT_FAILURE;
1831 }
1932
33 if (!ana::shaders::init()) {
34 std::cerr << "[E] couldn't initialize shaders";
35 return EXIT_FAILURE;
36 }
37
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 }
43
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);
48
2049 bool ok = true;
2150 while (ok) {
2251 SDL_Event ev;
2554 ok = false;
2655 }
2756 }
28 // render(w);
57 glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
58 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
59
60 glUseProgram(ana::shaders::program());
61
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);
74
75 SDL_GL_SwapWindow(w);
2976 }
3077
3178 return EXIT_SUCCESS;
0 #include <glm/vec2.hpp>
1 #include <string>
2
3 struct node {
4 glm::vec2 loc;
5 std::string name;
6 };
0 #include "shaders.hpp"
1 #include "wbogl/shader_utils.hpp"
2
3 #include <iostream>
4 #include <string>
5
6 namespace ana {
7 namespace shaders {
8
9 static const std::string node_vert_src = R"(
10 #version 420 core
11 layout (location = 0) in vec2 coord2d;
12 void main(void) {
13 gl_Position = vec4(coord2d, 0.0, 1.0);
14 }
15 )";
16
17 static const std::string node_frag_src = R"(
18 #version 420 core
19 out vec4 Color;
20
21 void main()
22 {
23 Color = vec4(0.0, 1.0, 0.0, 1.0);
24 }
25 )";
26
27 static const std::string node_geo_src = R"(
28 #version 420 core
29 layout (points) in;
30 layout (triangle_strip, max_vertices = 4) out;
31
32 void main() {
33 vec4 p = gl_in[0].gl_Position;
34 gl_Position = p;
35 EmitVertex();
36 gl_Position = p + vec4(0.5, 0, 0, 0);
37 EmitVertex();
38 gl_Position = p + vec4(0, 0.5, 0, 0);
39 EmitVertex();
40 gl_Position = p + vec4(0.5, 0.5, 0, 0);
41 EmitVertex();
42 EndPrimitive();
43 }
44 )";
45
46 static GLuint program_id = 0;
47
48 bool init(void) {
49 GLuint vs, fs, gs;
50 if (!(vs = create_shader_from_string(node_vert_src.c_str(), GL_VERTEX_SHADER))) {
51 std::cerr << "[E] vert shader couldn't be loaded" << std::endl;
52 return false;
53 }
54 if (!(fs = create_shader_from_string(node_frag_src.c_str(), GL_FRAGMENT_SHADER))) {
55 std::cerr << "[E] frag shader couldn't be loaded" << std::endl;
56 return false;
57 }
58 if (!(gs = create_shader_from_string(node_geo_src.c_str(), GL_GEOMETRY_SHADER))) {
59 std::cerr << "[E] geometry shader couldn't be loaded" << std::endl;
60 return false;
61 }
62 program_id = glCreateProgram();
63 glAttachShader(program_id, vs);
64 glAttachShader(program_id, fs);
65 glAttachShader(program_id, gs);
66 glLinkProgram(program_id);
67 GLint link_ok;
68 glGetProgramiv(program_id, GL_LINK_STATUS, &link_ok);
69 if (!link_ok) {
70 std::cerr << "glLinkProgram: ";
71 print_log(program_id);
72 program_id = 0;
73 return false;
74 }
75 return true;
76 }
77
78 GLuint program(void) {
79 return program_id;
80 }
81
82 }
83 }
0 #pragma once
1
2 #include <GL/glew.h>
3
4 namespace ana {
5 namespace shaders {
6
7 bool init(void);
8 GLuint program(void);
9
10 }
11 }