Drawing Command

drawing-command.png

頂点シェーダ

drawing_command.vert

#version 420 core
layout(location = 0) in vec4 vPosition;
uniform mat4 uProjectionMatrix;
uniform mat4 uMatrix;
void main()
{
    gl_Position = uProjectionMatrix * uMatrix * vPosition;
}

フラグメントシェーダ

drawing_command.frag

#version 420 core
out vec4 fColor;
uniform vec4 uColor;
void main()
{
    fColor = uColor;
}

.cpp

drawing_command.cpp

#include <iostream>
#include <fstream>   // ifstream, ofstream
#include <filesystem>//tr2::sys::pathに必要
#include <cassert>
using namespace std;
#include <GL/glew.h>
#include <GL/freeglut.h>
//glm
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtx/string_cast.hpp>
#include <glm/mat4x4.hpp>
#include <glm/gtc/quaternion.hpp>
#include <glm/gtc/matrix_transform.hpp>
 
GLuint vao;
GLuint render_model_matrix_loc;
GLuint color_loc;
/*
* @return シェーダIDを返す
*/
GLuint loadShader(const string& _shaderfilepath)
{
    //テキストファイルの読み込み
    tr2::sys::path path(_shaderfilepath);
    GLenum shadartype;
    string extention = path.extension().string();
    if (extention == ".vert") { shadartype = GL_VERTEX_SHADER; }
    else if (extention == ".frag") { shadartype = GL_FRAGMENT_SHADER; }
    else { shadartype = GL_GEOMETRY_SHADER_EXT; }
    GLuint shaderid = glCreateShader(shadartype);
    ifstream is(_shaderfilepath, ios::in);
    if (!is.is_open()) {
        tr2::sys::path mypath;
        cout << "現在のディレクトリ" << tr2::sys::current_path().string() << endl;
        cout << "開こうとしたファイル:" << _shaderfilepath << endl;
        assert(!"シェーダファイルが存在しません。");
        return 0;
    }
    //ファイルの長さを調べる
    is.seekg(0, ios::end);
    int filebytes = is.tellg();
    is.seekg(0, ios::beg);//先頭まで移動
    char* pSource = new char[filebytes];
 
    is.read(pSource, filebytes);
    is.close();
    pSource[filebytes - 1] = '\0';
 
    GLuint shader = glCreateShader(shadartype);
    glShaderSource(shader, 1, &pSource, NULL);
    delete[] pSource;
 
    glCompileShader(shader);//シェーダをコンパイルする。
                            //シェーダがちゃんとコンパイルできたかどうかチェック
    GLint compiled;
    // シェーダのコンパイル時のログの長さを取得する 
    glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
    if (!compiled) {
#ifdef _DEBUG
        GLsizei len;
        glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &len);
 
        GLchar* log = new GLchar[len + 1];
        //シェーダのコンパイル時のログの内容を取得する 
        glGetShaderInfoLog(shader, len, &len, log);
        cerr << "Shader compilation failed: " << log << endl;
        delete[] log;
#endif /* DEBUG */
        return 0;
    }
    return shader;
}
/**
* @return シェーダID
*/
GLuint loadShaders(const string& _vertexpath, const string& _fragmentpath)
{
    // シェーダプログラムをロードする
    GLuint vertexShader = loadShader(_vertexpath);
    if (!vertexShader) { return -1; }
    GLuint fragmentShader = loadShader(_fragmentpath);
    if (!fragmentShader) { return -2; }
 
    GLuint program = glCreateProgram();
    if (!program) { return -3; }
 
    glAttachShader(program, vertexShader);
    glAttachShader(program, fragmentShader);
 
    glLinkProgram(program);
    //リンクステータスのチェック
    GLint linked;
    glGetProgramiv(program, GL_LINK_STATUS, &linked);
    if (!linked) {
#ifdef _DEBUG
        GLsizei len;
        glGetProgramiv(program, GL_INFO_LOG_LENGTH, &len);
        GLchar* log = new GLchar[len + 1];
        glGetProgramInfoLog(program, len, &len, log);
        cerr << "Shader linking failed: " << log << endl;
        delete[] log;
#endif /* DEBUG */
        glDeleteShader(vertexShader);
        glDeleteShader(fragmentShader);
        return 0;
    }
    return program;
}
void init(void)
{
    static const GLfloat vertex_positions[] =
    {
        -1.0f, -1.0f, 0.0f, 1.0f,
        1.0f, -1.0f, 0.0f, 1.0f,
        -1.0f, 1.0f, 0.0f, 1.0f,
        1.0f, 1.0f, 0.0f, 1.0f,//glDrawElementsBaseVertexの実験のため
    };
    // Color for each vertex
    static const GLfloat vertex_colors[] =
    {
        1.0f, 1.0f, 1.0f, 1.0f,
        1.0f, 1.0f, 0.0f, 1.0f,
        1.0f, 0.0f, 1.0f, 1.0f,
        0.0f, 1.0f, 1.0f, 1.0f
    };
    // Three indices (we’re going to draw one triangle at a time
    static const GLushort vertex_indices[] =
    {
        0, 1, 2
    };
    //頂点アトリビュート
    glGenVertexArrays(1, &vao);
    glBindVertexArray(vao);
    //インデックス用のバッファ
    GLuint ebo;
    glGenBuffers(1,&ebo);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(vertex_indices), vertex_indices, GL_STATIC_DRAW);
 
    GLuint vbo;
    glGenBuffers(1,&vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glBufferData(GL_ARRAY_BUFFER,sizeof(vertex_positions) + sizeof(vertex_colors),NULL, GL_STATIC_DRAW);
    glBufferSubData(GL_ARRAY_BUFFER, 0,sizeof(vertex_positions), vertex_positions);
    glBufferSubData(GL_ARRAY_BUFFER,sizeof(vertex_positions), sizeof(vertex_colors),vertex_colors);
 
    GLuint program = loadShaders("drawing_command.vert", "drawing_command.frag");
    glUseProgram(program);
    render_model_matrix_loc = glGetUniformLocation(program,"uMatrix");
    color_loc = glGetUniformLocation(program,"uColor");
    glm::mat4 proj = glm::ortho(-5.0,5.0,-5.0,5.0);
    GLuint proj_matrix_loc = glGetUniformLocation(program, "uProjectionMatrix");
    glUniformMatrix4fv(proj_matrix_loc, 1, GL_FALSE, &proj[0][0]);
    int vPosition = glGetAttribLocation(program,"vPosition");
 
    glVertexAttribPointer(vPosition, 4, GL_FLOAT, GL_FALSE, 0, (GLvoid*)0);
    glEnableVertexAttribArray(vPosition);
}
void display(void)
{
    glClearColor(83.0 / 255.0, 62.0 / 255.0, 37.0 / 255.0, 1.0);
    glClear(GL_COLOR_BUFFER_BIT);
 
    glBindVertexArray(vao);
    glm::mat4  model_matrix = glm::translate(glm::mat4(), glm::vec3(-3.0f, 0.0f, 0.0f));
    glUniform4f(color_loc, 57.0 / 255.0, 217.0 / 255.0, 221.0 / 255.0, 1.0);//green
    glUniformMatrix4fv(render_model_matrix_loc, 4, GL_FALSE, glm::value_ptr(model_matrix));
    glDrawArrays(GL_TRIANGLES, 0, 3);
    //頂点インデックスを使用した描画 DrawElements
    model_matrix = glm::translate(glm::mat4(), glm::vec3(-1.0f, 0.0f, -0.0f));
    glUniform4f(color_loc, 202.0 / 255.0, 210.0 / 255.0, 213.0 / 255.0, 1.0);//grey
    glUniformMatrix4fv(render_model_matrix_loc, 4, GL_FALSE, glm::value_ptr(model_matrix));
    glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, NULL);
    // DrawElementsBaseVertexで1つ頂点インデックスをずらして描画(0,1,2)->(1,2,3)になります
    model_matrix = glm::translate(glm::mat4(), glm::vec3(1.0f, 0.0f, -0.0f));
    glUniform4f(color_loc, 85.0 / 255.0, 85.0 / 255.0, 221.0 / 255.0, 1.0);//blue
    glUniformMatrix4fv(render_model_matrix_loc, 4, GL_FALSE, glm::value_ptr(model_matrix));
    glDrawElementsBaseVertex(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, NULL, 1);
    // DrawArraysInstanced
    model_matrix = glm::translate(glm::mat4(), glm::vec3(3.0f, 0.0f, -0.0f));
    glUniform4f(color_loc, 226.0 / 255.0, 65.0 / 255.0, 145.0 / 255.0, 1.0);//pink
    glUniformMatrix4fv(render_model_matrix_loc, 4, GL_FALSE, glm::value_ptr(model_matrix));
    glDrawArraysInstanced(GL_TRIANGLES, 0, 3, 1);
    glutSwapBuffers();
}
void reshape(int width, int height)
{
    glViewport(0, 0, width, height);
}
int main(int argc, char** argv)
{
 
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
    glutInitWindowSize(200, 200);
    glutInitContextVersion(4, 2);
    glutInitContextProfile(GLUT_CORE_PROFILE);
    glutInitContextFlags(GLUT_FORWARD_COMPATIBLE | GLUT_DEBUG);
 
    glutCreateWindow("drawing_command");
 
    if (glewInit()) {
        cerr << "Unable to initialize GLEW ... exiting" << endl;
        exit(EXIT_FAILURE);
    }
    init();
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutMainLoop();
}

gldrawelementsbasevertex instanced-rendering

サポートサイト Wikidot.com gldrawelementsbasevertexinstanced-rendering