bambooflow Note

Cube描画

最終更新:

bambooflow

- view
メンバー限定 登録/ログイン

Cube描画



キューブが回転します。


シェーダプログラム


シェーダプログラムは次のようになります。
教科書どおりの書き方です。


  • simple.vert
#version 130
 
uniform mat4 modelMatrix;        // モデル・マトリックス
uniform mat4 viewMatrix;         // ビュー・マトリックス
uniform mat4 projectionMatrix;   // 射影・マトリックス
 
in vec3 a_vertex;
in vec3 a_normal;
 
out vec3 v_fragmentNormal;
 
void main(void)
{
    v_fragmentNormal = (viewMatrix*modelMatrix*vec4(a_normal, 0.0)).xyz;
 
    gl_Position = projectionMatrix*viewMatrix*modelMatrix*vec4(a_vertex.xyz, 1.0);
}
 

viewMatrix*modelMatrixをシェーダ側で計算させています。
CPU側とGPU側で負荷を分散させたいならば、CPU側で計算させてもよいかもしれません。
あと、projectionMatrix*viewMatrix*modelMatrixもCPU側であらかじめ計算させておく方法もあると思います。

ちなみに、法線ベクトルをModelViewマトリックスで計算するのはどうも間違いのようです。
法線ベクトルはオブジェクトはことなり、ModelViewマトリックスの逆転置行列(逆行列の転置)で計算するべきのようです。よくわかりませんが。
ということは、transpose(inverse(viewMatrix*modelMatrix))*normalということになるでしょうか。???不明。


  • simple.frag
#version 130
 
in vec3 v_fragmentNormal;
 
out vec4 fragColor;
 
void main(void)
{
    float intensity;
    intensity = max(dot(v_fragmentNormal, vec3(0.0,0.0,1.0)),0.0);
    fragColor = vec4(0.0,1.0,0.0,1.0)*intensity;
}
 



Cube.h


#include <GL/glew.h>
#include "Transform.h"
 
class Cube
{
private:
    GLuint vid[3];
    GLint vertexLocation;
    GLint normalLocation;
    GLuint numIndices;
 
    GLfloat matrix[16];
 
    float angle;
public:
    void setup(GLuint programObj)
    {
        angle = 0.0;
 
        GLfloat vertices[] = {
            -0.5f, -0.5f, -0.5f,
            -0.5f, -0.5f, +0.5f,
            +0.5f, -0.5f, +0.5f,
            +0.5f, -0.5f, -0.5f,
            -0.5f, +0.5f, -0.5f,
            -0.5f, +0.5f, +0.5f,
            +0.5f, +0.5f, +0.5f,
            +0.5f, +0.5f, -0.5f,
            -0.5f, -0.5f, -0.5f,
            -0.5f, +0.5f, -0.5f,
            +0.5f, +0.5f, -0.5f,
            +0.5f, -0.5f, -0.5f,
            -0.5f, -0.5f, +0.5f,
            -0.5f, +0.5f, +0.5f,
            +0.5f, +0.5f, +0.5f,
            +0.5f, -0.5f, +0.5f,
            -0.5f, -0.5f, -0.5f,
            -0.5f, -0.5f, +0.5f,
            -0.5f, +0.5f, +0.5f,
            -0.5f, +0.5f, -0.5f,
            +0.5f, -0.5f, -0.5f,
            +0.5f, -0.5f, +0.5f,
            +0.5f, +0.5f, +0.5f,
            +0.5f, +0.5f, -0.5f
        };
        GLfloat normals[] = {
            +0.0f, -1.0f, +0.0f,
            +0.0f, -1.0f, +0.0f,
            +0.0f, -1.0f, +0.0f,
            +0.0f, -1.0f, +0.0f,
            +0.0f, +1.0f, +0.0f,
            +0.0f, +1.0f, +0.0f,
            +0.0f, +1.0f, +0.0f,
            +0.0f, +1.0f, +0.0f,
            +0.0f, +0.0f, -1.0f,
            +0.0f, +0.0f, -1.0f,
            +0.0f, +0.0f, -1.0f,
            +0.0f, +0.0f, -1.0f,
            +0.0f, +0.0f, +1.0f,
            +0.0f, +0.0f, +1.0f,
            +0.0f, +0.0f, +1.0f,
            +0.0f, +0.0f, +1.0f,
            -1.0f, +0.0f, +0.0f,
            -1.0f, +0.0f, +0.0f,
            -1.0f, +0.0f, +0.0f,
            -1.0f, +0.0f, +0.0f,
            +1.0f, +0.0f, +0.0f,
            +1.0f, +0.0f, +0.0f,
            +1.0f, +0.0f, +0.0f,
            +1.0f, +0.0f, +0.0f
        };
        GLuint indices[] = {
            0, 2, 1,
            0, 3, 2,
            4, 5, 6,
            4, 6, 7,
            8, 9, 10,
            8, 10, 11,
            12, 15, 14,
            12, 14, 13,
            16, 17, 18,
            16, 18, 19,
            20, 23, 22,
            20, 22, 21
        };
        numIndices = sizeof(indices)/4;
 
        vertexLocation = glGetAttribLocation(programObj, "a_vertex");
        normalLocation = glGetAttribLocation(programObj, "a_normal");
 
        glGenBuffers(3, vid);
        glBindBuffer(GL_ARRAY_BUFFER, vid[0]);
        glBufferData(GL_ARRAY_BUFFER, sizeof(vertices)*sizeof(GLfloat), vertices, GL_STATIC_DRAW);
 
        glBindBuffer(GL_ARRAY_BUFFER, vid[1]);
        glBufferData(GL_ARRAY_BUFFER, sizeof(normals)*sizeof(GLfloat), normals, GL_STATIC_DRAW);
 
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vid[2]);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices)*sizeof(GLuint), indices, GL_STATIC_DRAW);
 
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
        glBindBuffer(GL_ARRAY_BUFFER, 0);
    }
 
    void render()
    {
        glBindBuffer(GL_ARRAY_BUFFER, vid[0]);
        glVertexAttribPointer(vertexLocation, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*3, 0); 
 
        glBindBuffer(GL_ARRAY_BUFFER, vid[1]);
        glVertexAttribPointer(normalLocation, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*3, 0); 
 
        glEnableVertexAttribArray(vertexLocation);
        glEnableVertexAttribArray(normalLocation);
 
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vid[2]);
 
        glDrawElements(GL_TRIANGLES, numIndices, GL_UNSIGNED_INT, 0);
    }
 
    void update() {
        sl_LoadIdentityf(matrix);
        //sl_Translatef(matrix, 0.0f,0.0f,1.0f);
        sl_Rotatef(matrix, angle, 0.0f, 1.0f, 0.0f);
        angle += 1.0;
    }
 
    GLfloat* m() {
        return matrix;
    }
};
 



メインプログラム


#include <iostream>
#include <fstream>
#include <cstdlib>
 
#include <GL/glew.h>
#include <GL/glut.h>
#include "Transform.h"
#include "Cube.h"
 
GLuint programObject;
GLuint vertexShader;
GLuint fragmentShader;
 
GLint modelLocation;
GLint viewLocation;
GLint projectionLocation;
GLfloat viewMatrix[16];
GLfloat projectionMatrix[16];
 
Cube cube;
 
void display();
void reshape(int w, int h);
void timer(int t);
void init();
bool initGlsl();
GLuint LoadShader(GLenum type, const char *fileName);
 
 
void display()
{
    cube.update();
 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
    glUseProgram(programObject);
 
    glUniformMatrix4fv(modelLocation, 1, GL_FALSE, cube.m());
    glUniformMatrix4fv(viewLocation, 1, GL_FALSE, viewMatrix);
    glUniformMatrix4fv(projectionLocation, 1, GL_FALSE, projectionMatrix);
 
    cube.render();
 
    glUseProgram(0);
 
    glutSwapBuffers();
}
 
 
void reshape(int w, int h)
{
    glViewport(0, 0, w, h); 
 
    sl_LoadIdentityf(projectionMatrix);
    sl_Perspectivef(projectionMatrix, 30, (GLfloat)w/(GLfloat)h, 1.0f, 100.0f);
}
 
 
void timer(int t)
{
    glutPostRedisplay();
    glutTimerFunc(t, timer, 17);
}
 
 
void init()
{
    glClearColor(0.5, 0.5, 0.5, 1.0);
    glClearDepth(1.0f);
 
    sl_LoadIdentityf(viewMatrix);
    sl_LookAtf(viewMatrix, 3.0f, 4.0f, 5.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
 
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_CULL_FACE);
}
 
 
bool initGlsl()
{
    programObject = glCreateProgram();
    if (programObject == 0) return false;
 
    vertexShader = LoadShader(GL_VERTEX_SHADER, "simple.vert");
    glAttachShader(programObject, vertexShader);
 
    fragmentShader = LoadShader(GL_FRAGMENT_SHADER, "simple.frag");
    glAttachShader(programObject, fragmentShader);
 
    GLint linked;
    glLinkProgram(programObject);
    glGetProgramiv(programObject, GL_LINK_STATUS, &linked);
    if (!linked) {
        GLint infoLen = 0;
 
        glGetProgramiv(programObject, GL_INFO_LOG_LENGTH, &infoLen);
        if (infoLen > 1) {
            char *infoLog = new char[sizeof(char)*infoLen];
 
            glGetProgramInfoLog(programObject, infoLen, NULL, infoLog);
            std::cerr << "Error linking program:\n" << infoLog << "\n";
            delete [] infoLog;
        }
        glDeleteProgram(programObject);
        return false;
    }
 
    glBindFragDataLocation(programObject, 0, "fragColor");
 
    modelLocation = glGetUniformLocation(programObject, "modelMatrix");
    viewLocation = glGetUniformLocation(programObject, "viewMatrix");
    projectionLocation = glGetUniformLocation(programObject, "projectionMatrix");
 
    cube.setup(programObject);
 
    return true;
}
 
GLuint LoadShader(GLenum type, const char *fileName)
{
    GLuint shader;
    GLint compiled;
 
    std::fstream inputFile(fileName);
    std::istreambuf_iterator<char> dataBegin(inputFile);
    std::istreambuf_iterator<char> dataEnd;
    std::string fileData(dataBegin, dataEnd);
    const char *file = fileData.c_str();
 
    shader = glCreateShader(type);
    if (shader == 0) return 0;
 
    glShaderSource(shader, 1, &file, NULL);
    glCompileShader(shader);
    glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
    if (!compiled) {
        GLint infoLen = 0;
        glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
        if (infoLen > 1) {
            char* infoLog = new char[sizeof(char)*infoLen];
            glGetShaderInfoLog(shader, infoLen, NULL, infoLog);
            std::cerr << "Error compiling shader: " << fileName << "\n" << infoLog << "\n";
            delete [] infoLog;
        }
        glDeleteShader(shader);
        return 0;
    }
    return shader;
}
 
 
int main(int argc, char *argv[])
{
    glutInit(&argc, argv);
    glutInitWindowSize(600, 400);
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
    glutCreateWindow("test");
 
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutTimerFunc(100, timer, 17);
 
    GLenum err;
    err = glewInit();
    if (err != GLEW_OK) {
        std::cerr << "GLEW error : " << glewGetErrorString(err) << "\n";
        std::exit(1);
    }   
 
    init();
    initGlsl();
 
    glutMainLoop();
 
    return 0;
}
 

座標系と変換マトリックス


座標系

座標系:coordinate system(空間:space)には次のようなものに分かれる。
  • オブジェクト座標系(object space)
    • モデリング座標系、ローカル座標系とも言う
  • ワールド座標系(world space)
    • グローバル座標系とも言う
  • 視点座標系座標系(eye space)
    • 眼点座標系とも書かれる
  • クリップ座標系(clip space)
  • 正規化デバイス座標系(normalized device space)
  • ウィンドウ座標系(window space)

変換方法


ModelMatrix

オブジェクト座標系からワールド座標系に変換するマトリックス。
WorldMatrixとも呼ぶ。

OpenGLのAPIで言うならば、
  • glScale
  • glRotate
  • glTranslate
がそれにあたると思われます。


ViewMatrix

ワールド座標系から視点座標系に変換するマトリックス。

OpenGLのAPIで言うならば、
  • gluLookAt
がそれにあたると思われます。


ProjectionMatrix

視点座標系からクリップ座標系に変換するマトリックス。
射影変換をすること。
射影変換には、
  • 正射影変換
  • 透視変換
があると思います。


OpenGLのAPIで言うならば、
  • glFrustum
  • glOrtho
  • gluPerspective
がそれにあたると思われます。

perspective divide

クリップ座標系から正規化デバイス座標系に変換する。
クリップ座標系の各点の同次座標の x, y, z 成分を w で割ると正規化デバイス座標系になる?

OpenGLでは、固定パイプラインなので、ユーザは意識する必要はない。


ビューポート変換&デプス・レンジ

正規化デバイス座標系からウィンドウ座標系に変換すること。

OpenGLのAPIで言うならば、
  • glViewport
がそれに当たると思われます。

タグ:

OpenGL GLSL
添付ファイル
記事メニュー
目安箱バナー