近い点をより大きく描画することで頂点がカメラに近づく表現をする。
#pragma warning(disable:4996) #pragma comment(lib,"glew32.lib") #include <gl/glew.h> #include <GL/glut.h> #include <fstream> #include <sstream> #include <vector> #include <algorithm> #include <array> typedef std::array<GLfloat,3> point_t; //モデルの座標用 x y z typedef std::array<GLfloat,4> color_t;//テクスチャ座標用 r g b a ////////////////////////////////////////// ////////////////////////////////////////// //////////////////////////////////////////
const char* vshader_program = R"( #version 460 core layout(location = 0) in vec3 vtx; layout(location = 1) in vec4 color; out vec4 vColor; uniform mat4 ModelViewMatrix; uniform mat4 ProjectionMatrix; // カメラ座標 uniform vec4 campos; void main() { gl_Position = ProjectionMatrix * ModelViewMatrix * vec4(vtx, 1.0); // 近いものほど大きく見せる float size = 50 / distance(campos,gl_Position); vColor = color; gl_PointSize = size; // 頂点のサイズ(ピクセル) } )";
////////////////////////////////////////// ////////////////////////////////////////// //////////////////////////////////////////
const char* fshader_program = R"( #version 460 core out vec4 FragColor; in vec4 vColor; void main() { FragColor = vColor; } )";
///////////////////////////////// //バッファとデータ GLuint vertexbufferName; GLuint colorbufferName; const GLuint v_count=100; GLuint VertexShaderID; void prepare_vertex_shader(); GLuint FragmentShaderID; void prepare_fragment_shader(); GLuint ProgramID; void link_program(); void init(void); void display(void); void timer(int value) { // 再描画 glutPostRedisplay(); // 100ミリ秒後にtimer関数を引数0で自分自身を呼び出す glutTimerFunc(100, timer, 0); }
int main(int argc, char* argv[]) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGBA); glutCreateWindow(argv[0]); glutDisplayFunc(display); glutReshapeWindow(300, 300); glewInit(); // glewの初期化 init(); glutTimerFunc(100, timer, 0); glutMainLoop(); return 0; } void prepare_buffers(); void init(void) { //頂点データと色情報の作成 prepare_buffers(); //頂点シェーダの準備 prepare_vertex_shader(); //フラグメントシェーダの準備 prepare_fragment_shader(); //プログラムのリンク link_program(); } //////////////////////////////////////////////////
void prepare_buffers() { ////////////////////////////////////////// ////////////////////////////////////////// std::vector< point_t > vertex; std::vector< color_t > color; float scale=50000.0f; for (size_t i = 0; i < v_count; i++){ float x = (rand() % (int)scale) * (1.0f / scale) - 0.5; float y = (rand() % (int)scale) * (1.0f / scale) - 0.5; float z = (rand() % (int)scale) * (1.0f / scale) - 0.5; vertex.emplace_back(point_t{ x*1.5f,y*1.5f,z*50 }); float r = (rand() % (int)scale) * (1.0f / scale); float g = (rand() % (int)scale) * (1.0f / scale); float b = (rand() % (int)scale) * (1.0f / scale); color.emplace_back(color_t{ r,g,b,1 }); } ////////////////////////////////////////// ////////////////////////////////////////// glGenBuffers(1, &vertexbufferName); glBindBuffer(GL_ARRAY_BUFFER, vertexbufferName); glBufferData(GL_ARRAY_BUFFER, 3 * v_count * sizeof(GLfloat), vertex.data(), GL_STATIC_DRAW); glGenBuffers(1, &colorbufferName); glBindBuffer(GL_ARRAY_BUFFER, colorbufferName); glBufferData(GL_ARRAY_BUFFER, 4 * v_count * sizeof(GLfloat), color.data(), GL_STATIC_DRAW); }
void prepare_vertex_shader() { ////////////////////////////////////////////// // シェーダを作ります // (作るといっても宣言みたいなもの) VertexShaderID = glCreateShader(GL_VERTEX_SHADER); //////////////////////////////////////////// // ファイルから頂点シェーダを読み込みます。 // 注意 ここはSTLのifstreamとかstringstreamの使い方の話で、 // OpenGL命令は一つも無い。 std::string VertexShaderCode = vshader_program; //////////////////////////////////////////// // 頂点シェーダをコンパイルします。 //printf("Compiling shader : %s\n", vertex_file_path); char const* VertexSourcePointer = VertexShaderCode.c_str(); glShaderSource(VertexShaderID, 1, &VertexSourcePointer, NULL); glCompileShader(VertexShaderID); //////////////////////////////////////////// // エラーチェック GLint Result = GL_FALSE; int InfoLogLength; // 頂点シェーダをチェックします。 glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result); glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength); if (Result == FALSE) { std::vector<char> VertexShaderErrorMessage(InfoLogLength); glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]); fprintf(stdout, "%s\n", &VertexShaderErrorMessage[0]); } }
void prepare_fragment_shader() { ///////////////////////////////////////////// // シェーダを作ります。 FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER); ///////////////////////////////////////////// // ファイルからフラグメントシェーダを読み込みます。 std::string FragmentShaderCode = fshader_program; ///////////////////////////////////////////// // フラグメントシェーダをコンパイルします。 //printf("Compiling shader : %s\n", fragment_file_path); char const* FragmentSourcePointer = FragmentShaderCode.c_str(); glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer, NULL); glCompileShader(FragmentShaderID); GLint Result = GL_FALSE; int InfoLogLength; ///////////////////////////////////////////// // フラグメントシェーダをチェックします。 glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result); glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength); if (Result == GL_FALSE) { std::vector<char> FragmentShaderErrorMessage(InfoLogLength); glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]); fprintf(stdout, "%s\n", &FragmentShaderErrorMessage[0]); } }
void link_program() { GLint Result = GL_FALSE; int InfoLogLength; //////////////////////////////////////// // プログラムをリンクします。 fprintf(stdout, "Linking program\n"); ProgramID = glCreateProgram(); glAttachShader(ProgramID, VertexShaderID); glAttachShader(ProgramID, FragmentShaderID); glLinkProgram(ProgramID); //////////////////////////////////////// // プログラムをチェックします。 glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result); glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength); std::vector<char> ProgramErrorMessage((std::max)(InfoLogLength, int(1))); glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]); fprintf(stdout, "%s\n", &ProgramErrorMessage[0]); }
void display(void) { glClearColor(0, 0, 0, 1); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_DEPTH_TEST); glLoadIdentity(); //glTranslated(0.5, 0.0, 0.0);//平行移動 glUseProgram(ProgramID); GLfloat mfproj[16]; GLfloat mftran[16]; mfproj[0] = 2.26961231; mfproj[1] = 0.0; mfproj[2] = 0.0; mfproj[3] = 0.0; mfproj[4] = 0.0; mfproj[5] = 2.41421366; mfproj[6] = 0.0; mfproj[7] = 0.0; mfproj[8] = 0.0; mfproj[9] = 0.0; mfproj[10] = -1.00020003; mfproj[11] = -1.00000000; mfproj[12] = 0.0; mfproj[13] = 0.0; mfproj[14] = -0.0200020000; mfproj[15] = 0.0; static float z = -10.0; z += 0.2; mftran[0] = 1.0; mftran[1] = 0.0; mftran[2] = 0.0; mftran[3] = 0.0; mftran[4] = 0.0; mftran[5] = 1.0; mftran[6] = 0.0; mftran[7] = 0.0; mftran[8] = 0.0; mftran[9] = 0.0; mftran[10] = 1.0; mftran[11] = 0.0; mftran[12] = 0.0;//x mftran[13] = 0.0;//y mftran[14] = z;//z mftran[15] = 1.0; GLint proj = glGetUniformLocation(ProgramID, "ProjectionMatrix"); GLint modl = glGetUniformLocation(ProgramID, "ModelViewMatrix"); glUniformMatrix4fv(proj, 1, GL_FALSE, mfproj); glUniformMatrix4fv(modl, 1, GL_FALSE, mftran); GLint campos = glGetUniformLocation(ProgramID, "campos"); GLfloat fcp[4] = { 0,0,z }; glUniform3fv(campos,1, fcp); //gl_PointSizeを有効にする glEnable(GL_VERTEX_PROGRAM_POINT_SIZE); // 頂点バッファ glEnableVertexAttribArray(0); glBindBuffer(GL_ARRAY_BUFFER, vertexbufferName); glVertexAttribPointer( 0, // 属性0 3, // 1要素の要素数 x y z GL_FLOAT, // タイプ GL_FALSE, // 正規化しない(データが整数型の時) 0, // ストライド (void*)0 // 配列バッファオフセット ); // カラーバッファ glEnableVertexAttribArray(1); glBindBuffer(GL_ARRAY_BUFFER, colorbufferName); glVertexAttribPointer( 1, // 属性1 4, // 1要素の要素数 r g b a GL_FLOAT, // タイプ GL_FALSE, // 正規化しない(データが整数型の時) 0, // ストライド (void*)0 // 配列バッファオフセット ); // 5頂点を描く glDrawArrays(GL_POINTS, 0, v_count); glDisableVertexAttribArray(0); glDisableVertexAttribArray(1); glDisableVertexAttribArray(2); //////////////////////////////////////// //////////////////////////////////////// glFlush(); }