|
|
- #include <iostream>
- #include <fstream>
- #include <sstream>
- #include <variant>
- #include <chrono>
- #include "commander.hpp"
- #include "nlohmann/json.hpp"
- #include <GL/glew.h>
- #define GLFW_DLL
- #include <GLFW/glfw3.h>
-
-
-
- std::variant<std::array<float,18>, std::vector<float>> points = std::array<float,18> {
- -1.0f, 1.0f, 0.0f,
- 1.0f, -1.0f, 0.0f,
- -1.0f, -1.0f, 0.0f,
- 1.0f, -1.0f, 0.0f,
- 1.0f, 1.0f, 0.0f,
- -1.0f, 1.0f, 0.0f
- };
-
- std::string check_shader(GLuint shader)
- {
- std::array<char,4096> text_buffer;
- GLsizei size;
- glGetShaderInfoLog(shader, text_buffer.size(),&size,text_buffer.data());
- return std::string{text_buffer.begin(), text_buffer.begin()+size};
- }
-
- std::string vertex_shader =
- "#version 400\n"
- "in vec3 vp;"
- "void main() {"
- " gl_Position = vec4(vp, 1.0);"
- "}";
-
- std::string fragment_shader =
- "#version 400\n"
- "out vec4 frag_colour;"
- "void main() {"
- " frag_colour = vec4(1.0, 0.0, 0.0, 1.0);"
- "}";
-
- std::pair<int,int> parse_resolution(const std::string& str)
- {
- auto x_it = std::find(str.begin(),str.end(),'x');
- auto x_str = std::string{str.begin(),x_it};
- auto y_str = std::string(x_it+1,str.end());
- return std::make_pair(std::stoi(x_str),std::stoi(y_str));
- }
-
- std::string slurp_file(const std::string& path)
- {
- std::ifstream input(path);
- std::stringstream sstr;
-
- while(input >> sstr.rdbuf());
-
- return sstr.str();
- }
-
- int main(int argc, char** argv)
- {
- // start GL context and O/S window using the GLFW helper library
- if (!glfwInit()) {
- std::cerr<<"ERROR: could not start GLFW3\n";
- return 1;
- }
-
- CMD::commander cli_args{argc,argv};
- auto res_str = cli_args.getFlagValue("-r");
- auto res = parse_resolution(res_str.empty()?"800x800":res_str);
- auto mesh_path = cli_args.getFlagValue("--mesh");
-
- if(!mesh_path.empty()) {
- auto mesh = nlohmann::json::parse(slurp_file(mesh_path));
- assert(mesh.is_array());
- points = std::vector<float>{mesh.begin(), mesh.end()};
- }
-
- auto vertshad_path = cli_args.getFlagValue("--vshader");
-
- if(!vertshad_path.empty()) {
- vertex_shader = slurp_file(vertshad_path);
- }
-
- auto fragshad_path = cli_args.getFlagValue("--fshader");
-
- if(!fragshad_path.empty()) {
- fragment_shader = slurp_file(fragshad_path);
- }
-
- // uncomment these lines if on Apple OS X
- /*glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
- glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
- glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
- glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);*/
-
- GLFWwindow* window = glfwCreateWindow(res.first, res.second, "sh_render", NULL, NULL);
-
- if (!window) {
- std::cerr<<"ERROR: could not open window with GLFW3\n";
- glfwTerminate();
- return 1;
- }
-
- glfwMakeContextCurrent(window);
-
- // start GLEW extension handler
- glewExperimental = GL_TRUE;
- glewInit();
-
- // get version info
- const GLubyte* renderer = glGetString(GL_RENDERER); // get renderer string
- const GLubyte* version = glGetString(GL_VERSION); // version as a string
- std::cout <<"Renderer: "<<renderer<<"\n"
- <<"OpenGL version supported "<<version<<"\n";
-
- // tell GL to only draw onto a pixel if the shape is closer to the viewer
- glEnable(GL_DEPTH_TEST); // enable depth-testing
- glDepthFunc(GL_LESS); // depth-testing interprets a smaller value as "closer"
-
- {
- GLuint vbo = 0;
- glGenBuffers(1, &vbo);
- glBindBuffer(GL_ARRAY_BUFFER, vbo);
- glBufferData(
- GL_ARRAY_BUFFER,
- std::visit([](auto& v)->size_t{return v.size();},points) * sizeof(float),
- std::visit([](auto& v)->float* {return (float*)v.data();},points),
- GL_STATIC_DRAW
- );
- auto num_triangles = std::visit([](auto& v)->size_t{return v.size();},points)/9;
-
- GLuint vao = 0;
- glGenVertexArrays(1, &vao);
- glBindVertexArray(vao);
- glEnableVertexAttribArray(0);
- glBindBuffer(GL_ARRAY_BUFFER, vbo);
- glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
-
- GLuint vs = glCreateShader(GL_VERTEX_SHADER);
- auto vsh = vertex_shader.data();
- glShaderSource(vs, 1, &vsh, NULL);
- glCompileShader(vs);
- std::cout<<"Vertex shader:"<<check_shader(vs)<<"\n";
- GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
- auto fsh = fragment_shader.data();
- glShaderSource(fs, 1, &fsh, NULL);
- glCompileShader(fs);
- std::cout<<"Fragment shader:"<<check_shader(fs)<<"\n";
-
- GLuint shader_programme = glCreateProgram();
- glAttachShader(shader_programme, fs);
- glAttachShader(shader_programme, vs);
- glLinkProgram(shader_programme);
-
- while(!glfwWindowShouldClose(window)) {
- // wipe the drawing surface clear
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- glUseProgram(shader_programme);
- glBindVertexArray(vao);
-
- // draw points 0-4 from the currently bound VAO with current in-use shader
- for(size_t tri_it = 0; tri_it<num_triangles; tri_it++) {
- glDrawArrays(GL_TRIANGLES, tri_it*3, 3);
- }
-
- // update other events like input handling
- glfwPollEvents();
- // put the stuff we've been drawing onto the display
- glfwSwapBuffers(window);
- }
-
- }
-
- // close GL context and any other GLFW resources
- glfwTerminate();
- return 0;
- }
|