OGLplus を使ってシェーダで遊んでみた
実行時にシェーダファイルをリロードできるようにして遊んでみました。
[main.cpp]
#include <vector> #include <GL/glew.h> #include <oglplus/gl.hpp> // OGLplus 0.5.0 以降だと near far を undef しておかないと動かない #undef near #undef far //#include <oglplus/all.hpp> #include <oglplus/context.hpp> #include <oglplus/buffer.hpp> #include <oglplus/vertex_attrib.hpp> #include <oglplus/vertex_array.hpp> #include <oglplus/shader.hpp> #include <oglplus/program.hpp> #include <oglplus/pixel_data.hpp> #include <oglplus/image.hpp> #include <GL/Glut.h> #include <cstdlib> #include <string> #include <gl/graphics.hpp> #include <boost/thread.hpp> #include <boost/optional.hpp> #include <fstream> #include <sstream> namespace glp = oglplus; typedef glp::Context glc; template<typename Shader, typename Char> boost::optional<std::string> shader_compile(Shader& shader, Char const* source){ shader.Source(source); try{ shader.Compile(); return boost::none; } catch (glp::CompileError const& error) { std::cout << error.what() << std::endl; return error.Log(); } } template<typename Shader, typename Char> boost::optional<std::string> shader_compile(Shader& shader, std::basic_ifstream<Char> const& file){ std::stringstream buffer; buffer << file.rdbuf(); return shader_compile(shader, buffer.str().c_str()); } struct triangle : boost::noncopyable{ triangle(std::initializer_list<GLfloat> triangle_verts){ load_shader(); // bind the VAO for the triangle vertex_array.Bind(); // bind the VBO for the triangle vertices verts.Bind(glp::Buffer::Target::Array); // upload the data glp::Buffer::Data(glp::Buffer::Target::Array, triangle_verts.size(), triangle_verts.begin() ); // setup the vertex attribs array for the vertices glp::VertexAttribArray vert_attr(prog, "Position"); vert_attr.Setup(3, glp::DataType::Float); vert_attr.Enable(); } void render() const{ vertex_array.Bind(); glc::DrawArrays(glp::PrimitiveType::Triangles, 0, 3); } void reload_shader(std::string name = "basic"){ prog.DetachShader(vs); prog.DetachShader(fs); load_shader(name); std::cout << "reloaded shader" << std::endl; } private: void load_shader(std::string name = "basic"){ if(auto error = shader_compile(vs, std::ifstream(name + ".vert"))){ std::cout << "==== VertexShader Compile Error ====" << std::endl; std::cout << *error << std::endl; return; } if(auto error = shader_compile(fs, std::ifstream(name + ".frag"))){ std::cout << "==== FragmentShader Compile Error ====" << std::endl; std::cout << *error << std::endl; return; } // attach the shaders to the program prog.AttachShader(vs); prog.AttachShader(fs); // link and use it prog.Link(); prog.Use(); } // Vertex shader glp::VertexShader vs; // Fragment shader glp::FragmentShader fs; // Program glp::Program prog; // A vertex array object for the rendered triangle glp::VertexArray vertex_array; // VBO for the triangle's vertices glp::Buffer verts; }; int main(int argc, char *argv[]){ namespace glp = oglplus; typedef glp::Context glc; gl::graphics g(argc, argv, 500, 500, "test"); // glew の初期化 auto err = glewInit(); if (err != GLEW_OK) { fprintf(stderr, "Error: %s\n", glewGetErrorString(err)); } glc::ClearColor(0.5f, 0.7f, 0.9f, 1.0f); glc::ClearDepth(1.0f); // △ポリゴンの生成 triangle obj1({ 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f }); triangle obj2({ 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f }); //---------------------------------------------------------------------- gl::displayfunc(g, [&](){ glc::Clear().ColorBuffer().DepthBuffer(); obj1.render(); obj2.render(); }); gl::reshapefunc(g, [&](int width, int height){ glc::Viewport(width, height); }); // キー入力イベント gl::keyboardfunc(g, [&obj1](unsigned char key, int x, int y){ if(key == 'q') return exit(0); if(key == 'u') return obj1.reload_shader(); }); // idle gl::idlefunc(g, [&](){ boost::this_thread::sleep(boost::posix_time::milliseconds(16)); glutPostRedisplay(); }); g.run(); return 0; }
[basic.vert]
#version 330 in vec3 Position; out vec4 vertColor; void main(void){ gl_Position = vec4(Position, 1.0); vec3 color = (Position + 1.0) / 2.0; vertColor = vec4(color, 1.0); }
[basic.frag]
#version 330 in vec4 vertColor; out vec4 fragColor; void main(void){ fragColor = vertColor; }
[OGLplus]
- 0.6.0