GLSLのUBO。普通のUniform変数はlinkしたプログラムごとに設定するが、UBOは全てのプログラムで共通の変数を使うことができる。
今回はとりあえず動かすことに成功したのでひとまずコードを張っておきたい。
なおシェーダの準備などは作り置きの関数を使用。
GLSLのシェーダ関係の処理を関数化(C++)
#include <iostream> #include <Windows.h> #include "prepare_shader.hpp" #include <gl/GL.h> #include <gl/GLU.h> #include <gl/freeglut.h> #include <cassert> #pragma comment(lib,"glew32.lib") //ウィンドウの幅と高さ int width, height; GLuint buf_points1; GLuint buf_points2; GLuint programIDR; GLuint programIDG; GLuint uniformBufferID; struct CMatrices { GLfloat mproj[16]; GLfloat mmodel[16]; } _matrices; void GetZRotate(GLfloat* m, GLfloat rad);
// シェーダとデータの設定 void init() { std::vector<GLfloat> points; GLfloat s=0.0; GLfloat v = 0.8; push_3(points, 0 + s, 0, 0);//座標 XYZ push_3(points, 0 + s, v, 0); push_3(points, v + s, 0, 0); prepare_buffer(&buf_points1, points.data(), points.size() * sizeof(GLfloat), GL_STATIC_DRAW); s = 0.1; points.clear(); push_3(points, 0 + s, 0, 0);//座標 XYZ push_3(points, 0 + s, v, 0); push_3(points, v + s, 0, 0); prepare_buffer(&buf_points2, points.data(), points.size() * sizeof(GLfloat), GL_STATIC_DRAW); GLuint vtxShader; GLuint flagShaderR; GLuint flagShaderG; const char* vtxfile = "default.vert"; const char* fragfileR = "default-R.frag"; const char* fragfileG = "default-G.frag"; std::string verr; std::string ferr; prepare_shader_byfile(&vtxShader, GL_VERTEX_SHADER, vtxfile, &verr); prepare_shader_byfile(&flagShaderR, GL_FRAGMENT_SHADER, fragfileR, &ferr); prepare_shader_byfile(&flagShaderG, GL_FRAGMENT_SHADER, fragfileG, &ferr); std::cout << verr << std::endl; std::cout << ferr << std::endl; std::string linkerr; link_program(&programIDR, { vtxShader ,flagShaderR }, nullptr, &linkerr); link_program(&programIDG, { vtxShader ,flagShaderG }, nullptr, &linkerr); loadidentity44(_matrices.mproj); loadidentity44(_matrices.mmodel); // UBOを作成 glGenBuffers(1, &uniformBufferID); glBindBuffer(GL_UNIFORM_BUFFER, uniformBufferID); glBufferData(GL_UNIFORM_BUFFER, sizeof(CMatrices), &_matrices, GL_DYNAMIC_DRAW); //UBOの内容を書き込み glBindBuffer(GL_UNIFORM_BUFFER, 0); }
//描画関数 void disp(void) { glViewport(0, 0, width, height); glClearColor(0.2, 0.2, 0.2, 1); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); static int angle = 0; GetZRotate(_matrices.mmodel, angle++ * (3.14159 / 180.0)); glBindBuffer(GL_UNIFORM_BUFFER, uniformBufferID); glBufferData(GL_UNIFORM_BUFFER, sizeof(CMatrices), &_matrices, GL_DYNAMIC_DRAW); glBindBuffer(GL_UNIFORM_BUFFER, 0); GLuint block_index_r = glGetUniformBlockIndex(programIDR, "Matrices");
GLuint block_index_g = glGetUniformBlockIndex(programIDG, "Matrices");
GLuint index = 0; //この数字はGL_MAX_UNIFORM_BUFFER_BINDINGS未満ならなんでもいい assert(index < GL_MAX_UNIFORM_BUFFER_BINDINGS);
glUseProgram(programIDR);//使用するプログラムを変更 glBindBufferBase(GL_UNIFORM_BUFFER, index, uniformBufferID); glUniformBlockBinding(programIDR, block_index_r, index); { auto bindbufP = EnableAndBindFArrayBuffer(0, buf_points1, 3, GL_FLOAT);//prepare_shader.hpp glDrawArrays(GL_TRIANGLES, 0, 3); }
glUseProgram(programIDG);//使用するプログラムを変更 glBindBufferBase(GL_UNIFORM_BUFFER, index, uniformBufferID); glUniformBlockBinding(programIDG, block_index_g, index); { auto bindbufP = EnableAndBindFArrayBuffer(0, buf_points2, 3, GL_FLOAT);//prepare_shader.hpp glDrawArrays(GL_TRIANGLES, 0, 3); }
glUseProgram(0); glFlush(); }
//ウィンドウサイズの変化時に呼び出される void reshape(int w, int h) { width = w; height = h; disp(); } void timer(int value) { glutPostRedisplay(); glutTimerFunc(50, timer, 0); } //エントリポイント int main(int argc, char** argv) { glutInit(&argc, argv); glutInitWindowPosition(100, 50); glutInitWindowSize(500, 500); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA); glutCreateWindow("sample"); glutDisplayFunc(disp); glutReshapeFunc(reshape); glutTimerFunc(10, timer, 0); glewInit(); init(); glutMainLoop(); return 0; } //! @brief X軸回転行列を作成する //! @param [out] m 結果を格納する要素数16の配列 //! @param [in] rad 回転角(ラジアン) //! @return なし void GetZRotate(GLfloat* m, GLfloat rad) { m[0] = cos(rad); m[1] = sin(rad); m[2] = 0; m[3] = 0; m[4] = -sin(rad); m[5] = cos(rad); m[6] = 0; m[7] = 0; m[8] = 0; m[9] = 0; m[10] = 1; m[11] = 0; m[12] = 0; m[13] = 0; m[14] = 0; m[15] = 1; }
#version 460 core layout (location = 0) in vec3 coord; out vec4 vColor; //Uniformブロック std140はメモリ配置方法 layout (std140) uniform Matrices { mat4 ProjectionMatrix; mat4 ModelViewMatrix; }; void main() { gl_Position = ProjectionMatrix * ModelViewMatrix * vec4(coord, 1.0); }
#version 460 core in vec4 vColor; out vec4 FragColor; void main() { FragColor[0] = 0.0; FragColor[1] = 1.0; FragColor[2] = 0.0; FragColor[3] = 1.0; }
#version 460 core in vec4 vColor; out vec4 FragColor; void main() { FragColor[0] = 1.0; FragColor[1] = 0.0; FragColor[2] = 0.0; FragColor[3] = 1.0; }