OGLplus で画像の描画
OGLplus を使用したテクスチャの描画です。
OGLplus では、libpng で .png の画像ファイルを読み込むことが出来るので、今回はそれを使用します。
使用するためには予め libpng を導入しておく必要があります。
example だと
まぁやっていることはそんなに変わらないはず。
[ソース]
#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/texture.hpp> #include <oglplus/image.hpp> #include <oglplus/images/load.hpp> #include <oglplus/shapes/draw.hpp> #include <GL/Glut.h> #include <gl/graphics.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 texture : boost::noncopyable{ texture(){ load_shader(); // bind the VAO for the texture vertex_array.Bind(); // bind the VBO for the texture vertices verts.Bind(glp::Buffer::Target::Array); { GLfloat data[12] = { 1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, -1.0f }; // upload the data glp::Buffer::Data(glp::Buffer::Target::Array, 12, data ); // setup the vertex attribs array for the vertices glp::VertexAttribArray vert_attr(prog, "Position"); vert_attr.Setup(2, glp::DataType::Float); vert_attr.Enable(); } texcoords.Bind(glp::Buffer::Target::Array); { GLfloat data[12] = { 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f }; // upload the data glp::Buffer::Data(glp::Buffer::Target::Array, 12, data ); glp::VertexAttribArray attr(prog, "TexCoord"); attr.Setup(2, glp::DataType::Float); attr.Enable(); } // setup the texture tex.Bind(glp::Texture::Target::_2D); { tex.MinFilter(glp::Texture::Target::_2D, glp::TextureMinFilter::Linear); tex.MagFilter(glp::Texture::Target::_2D, glp::TextureMagFilter::Linear); tex.WrapS(glp::Texture::Target::_2D, glp::TextureWrap::Repeat); tex.WrapT(glp::Texture::Target::_2D, glp::TextureWrap::Repeat); std::ifstream file("cpplands.png", std::ios::binary); tex.Image2D( glp::Texture::Target::_2D, glp::images::PNG(file) ); // OGLplus で用意されている読み込み処理では // std::ios::binary が付いておらず失敗する // tex.Image2D(glp::Texture::Target::_2D, glp::images::LoadTexture("cpplands")); } } void render() const{ vertex_array.Bind(); glc::DrawArrays(glp::PrimitiveType::Triangles, 0, 6); } 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 texture glp::VertexArray vertex_array; // VBO for the texture's vertices glp::Buffer verts; glp::Buffer texcoords; // The stained glass texture glp::Texture tex; }; int main(int argc, char *argv[]) try{ namespace glp = oglplus; typedef glp::Context glc; gl::graphics g(argc, argv, 800, 600, "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); // テクスチャポリゴンの生成 texture tex; //---------------------------------------------------------------------- gl::displayfunc(g, [&](){ glc::Clear().ColorBuffer().DepthBuffer(); tex.render(); }); gl::reshapefunc(g, [&](int width, int height){ glc::Viewport(width, height); }); // キー入力イベント gl::keyboardfunc(g, [&tex](unsigned char key, int x, int y){ if(key == 'q') return exit(0); if(key == 'u') return tex.reload_shader(), glutPostRedisplay(); }); g.run(); return 0; } catch(glp::Error const& error){ std::cout << error.what() << std::endl; std::cout << "GLSymbol " << error.GLSymbol () << std::endl; std::cout << "File " << error.File () << std::endl; std::cout << "Func " << error.Func () << std::endl; std::cout << "Line " << error.Line () << std::endl; std::cout << "ClassName " << error.ClassName () << std::endl; std::cout << "ObjectDescription " << error.ObjectDescription () << std::endl; }
[basic.vert]
#version 330 in vec4 Position; in vec2 TexCoord; out vec2 vertTexCoord; void main(void){ vertTexCoord = TexCoord; gl_Position = Position; }
[basic.frag]
#version 330 uniform sampler2D TexUnit; in vec2 vertTexCoord; out vec4 fragColor; void main(void){ fragColor = texture(TexUnit, vertTexCoord); vec4 t = texture(TexUnit, vertTexCoord); fragColor = vec4(t.rgb, 1.0); }
[注意]
oglplus::images::LoadTexture を使用して画像ファイルを読み込む場合、std::ios::binary オプションが付いておらずに読み込みに失敗してしまいます。
これを防ぐためには、OGLplus のコードを直接書き換えるか、ユーザコードで、std::ifstream で読み込む必要があります。
[OGLplus]
- 0.7.0