あかすくぱるふぇ

同人サークル「あかすくぱるふぇ」のブログです。

OpenGL

・attributeとin/out
attributeは古い。
https://siguma-sig.hatenablog.com/entry/2017/04/25/203250

・glEnableClientStateとglEnableVertexAttribArray
glEnableClientStateはgl_Vertexなどの組み込み属性配列を利用する。
glEnableVertexAttribArrayはattribute変数を利用する。
https://jpcodeqa.com/q/a2b139f4eebef00e3630c83d6eaaaec9

・attribute変数の利用方法
#version 400
in vec4 position;

void main(void)
{
gl_Position = position;
}
#version 400
out vec4 color;

void main (void)
{
color = vec4(0.0, 1.0, 0.0, 1.0);
}
gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, vbo[0])
val positionId = gl.glGetAttribLocation(programId!!, "position")
gl.glEnableVertexAttribArray(positionId)
gl.glVertexAttribPointer(positionId, 3, GL2.GL_FLOAT, false, 0, 0)
gl.glDrawArrays(GL2.GL_QUADS, 0, vertices.size)
gl.glBindBuffer(GL2.GL_ARRAY_BUFFER, 0)

・その1
glBindAttribLocation()の第二引数が0の場合、.vertファイル内の変数名が第三引数と異なっていてもたまたまうまく動作してしまう場合がある。
1以上の値を用いた方が良い?

・その2
glEnableClientState()を使ってはいけない。
その代わりとしてglEnableVertexAttribArray()が存在する。

やっと全貌が見え始めてきたので。

・頂点描画方法
以下の記事の続き、補足です。
http://akasuku.blog.jp/archives/62740578.html
http://akasuku.blog.jp/archives/44623464.html

これについては、わかりやすくまとめられたページがあります。
http://mklearning.blogspot.jp/2014/08/opengl.html

glBegin()/glEnd()を用いる描画はOpenGL1.0のみであって、その後はずっとglVertex(Attrib)Pointerを使っているのですね。
そして、VBOまではOpenGL1.xの範疇。
OpenGL2.0でシェーダー対応、OpenGL3.0でVAO。

・シェーダー変数の変遷。
以下の記事の続き、補足です。
http://akasuku.blog.jp/archives/50856177.html

参考ページ
http://wlog.flatlib.jp/item/1633
http://marina.sys.wakayama-u.ac.jp/~tokoi/?date=20090827

OpenGL3.0(glsl ver1.3)以前はattribute/varying, 以降は.in/out。
glGetAttribLocationとglBindAttribLocationはどちらもOpenGL2.0から使えるようですね。

GLSLプログラムの最小構成です。
床井先生のページを参考にしています。
http://marina.sys.wakayama-u.ac.jp/~tokoi/?date=20051006

vertファイルとfragファイルは適当にどうぞ。
#include <stdio.h>
#include <gl/glew.h>
#include <gl/glut.h>

int readShaderSource(GLuint shader, const char *file)
{
FILE *fp;
const GLchar *source;
GLsizei length;
int ret;

/* ファイルを開く */
fp = fopen(file, "rb");
if (fp == NULL) {
perror(file);
return -1;
}

/* ファイルの末尾に移動し現在位置(つまりファイルサイズ)を得る */
fseek(fp, 0L, SEEK_END);
length = ftell(fp);

/* ファイルサイズのメモリを確保 */
source = (GLchar *)malloc(length);
if (source == NULL) {
fprintf(stderr, "Could not allocate read buffer.\n");
return -1;
}

/* ファイルを先頭から読み込む */
fseek(fp, 0L, SEEK_SET);
ret = fread((void *)source, 1, length, fp) != (size_t)length;
fclose(fp);

/* シェーダのソースプログラムのシェーダオブジェクトへの読み込み */
if (ret)
fprintf(stderr, "Could not read file: %s.\n", file);
else
glShaderSource(shader, 1, &source, &length);

/* 確保したメモリの開放 */
free((void *)source);

return ret;
}

void init(void)
{
glClearColor(0.0f, 0.0f, 1.0f, 0.0f);

// shaderオブジェクトを作成
GLuint vertShader = glCreateShader(GL_VERTEX_SHADER);
GLuint fragShader = glCreateShader(GL_FRAGMENT_SHADER);

// shaderソースを入力
readShaderSource(vertShader, "basic.vert");
readShaderSource(fragShader, "basic.frag");

// shaderソースをコンパイル
glCompileShader(vertShader);
glCompileShader(fragShader);

// shaderプログラムを作成
GLuint shaderProgram = glCreateProgram();

// shaderプログラムにコンパイルしたshaderをアタッチ
glAttachShader(shaderProgram, vertShader);
glAttachShader(shaderProgram, fragShader);

// shaderプログラムをリンク
glLinkProgram(shaderProgram);

// shaderプログラムの適用
glUseProgram(shaderProgram);
}

void display(void)
{
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(1.0f, 0.0f, 0.0f);
glBegin(GL_QUADS);
glVertex2d(-0.9, -0.9);
glVertex2d(0.9, -0.9);
glVertex2d(0.9, 0.9);
glVertex2d(-0.9, 0.9);
glEnd();

glutSwapBuffers();
}

void resize(int w, int h)
{
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
}

int main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH);
glutCreateWindow(argv[0]);
glewInit();
glutReshapeFunc(resize);
glutDisplayFunc(display);
init();
glutMainLoop();
return 0;
}

ついでに、Visual StudioでGLSLのシンタックスハイライトを行うには以下のページにある.vsixファイルを実行すればよいです。
https://github.com/samizzo/nshader/releases/download/2.0/NShader.vsix

下記記事の実例。
ググればいくらでも出てくる内容だけど、整理しておきたかったので。
http://akasuku.blog.jp/archives/44623464.html

○単純な四角形の描画
以下が置き換え前。
GLdouble vertices[sizeOfVertices] = {
-1.0, -1.0, 0.0,
1.0, -1.0, 0.0,
1.0, 1.0, 0.0,
-1.0, 1.0, 0.0
};

void scene()
{
glColor3f(1.0f, 0.0f, 0.0f);
glBegin(GL_QUADS);
for (int i = 0; i < vertexNum; ++i) {
glVertex3d(vertices[i * dimNum], vertices[i * dimNum + 1],
vertices[i * dimNum + 2]);
}
glEnd();
}
VBOで置き換えると以下のようになる。
GLdouble vertices[sizeOfVertices] = {
-1.0, -1.0, 0.0,
1.0, -1.0, 0.0,
1.0, 1.0, 0.0,
-1.0, 1.0, 0.0
};
GLuint vrtVBO;

void init()
{
// バッファの生成
glGenBuffers(1, &vrtVBO);

// 頂点位置の転送
glBindBuffer(GL_ARRAY_BUFFER, vrtVBO);
glBufferData(GL_ARRAY_BUFFER, sizeOfVertices * sizeof(GLdouble),
vertices, GL_STATIC_DRAW);

glBindBuffer(GL_ARRAY_BUFFER, 0);
}

void scene()
{
// 頂点位置のデータ位置の指定
glBindBuffer(GL_ARRAY_BUFFER, vrtVBO);
glVertexPointer(dimNum, GL_DOUBLE, 0, 0);

// 描画
glEnableClientState(GL_VERTEX_ARRAY);
  glColor3f(1.0f, 0.0f, 0.0f);
 glDrawArrays(GL_QUADS, 0, vertexNum);
glDisableClientState(GL_VERTEX_ARRAY);

glBindBuffer(GL_ARRAY_BUFFER, 0);
}

○テクスチャマッピング
以下が置き換え前。
GLdouble vertices[sizeOfVertices] = {
-1.0, -1.0, 0.0,
1.0, -1.0, 0.0,
1.0, 1.0, 0.0,
-1.0, 1.0, 0.0
};
GLdouble texCoords[sizeOfTexCoords] = {
0.0, 1.0,
1.0, 1.0,
1.0, 0.0,
0.0, 0.0
};

void scene()
{
glEnable(GL_TEXTURE_2D);

glBegin(GL_QUADS);
for (int i = 0; i < vertexNum; ++i) {
glTexCoord2d(texCoords[i * 2], texCoords[i * 2 + 1]);
glVertex3d(vertices[i * dimNum], vertices[i * dimNum + 1],
vertices[i * dimNum + 2]);
}
glEnd();

glDisable(GL_TEXTURE_2D);
}
VBOで置き換えると以下のようになる。
GLdouble vertices[sizeOfVertices] = {
-1.0, -1.0, 0.0,
1.0, -1.0, 0.0,
1.0, 1.0, 0.0,
-1.0, 1.0, 0.0
};
GLdouble texCoords[sizeOfTexCoords] = {
0.0, 1.0,
1.0, 1.0,
1.0, 0.0,
0.0, 0.0
};
GLuint vrtVBO;
GLuint uvVBO;

void init()
{
// バッファの生成
glGenBuffers(1, &vrtVBO);
glGenBuffers(1, &uvVBO);

// 頂点位置の転送
glBindBuffer(GL_ARRAY_BUFFER, vrtVBO);
glBufferData(GL_ARRAY_BUFFER, sizeOfVertices * sizeof(GLdouble),
vertices, GL_STATIC_DRAW);

// UV座標の転送
glBindBuffer(GL_ARRAY_BUFFER, uvVBO);
glBufferData(GL_ARRAY_BUFFER, sizeOfTexCoords * sizeof(GLdouble),
texCoords, GL_STATIC_DRAW);

glBindBuffer(GL_ARRAY_BUFFER, 0);
}

void scene()
{
// 頂点位置のデータ位置の指定
glBindBuffer(GL_ARRAY_BUFFER, vrtVBO);
glVertexPointer(dimNum, GL_DOUBLE, 0, 0);

// UV座標のデータ位置の指定
glBindBuffer(GL_ARRAY_BUFFER, uvVBO);
glTexCoordPointer(2, GL_DOUBLE, 0, 0);

// 描画
glEnableClientState(GL_VERTEX_ARRAY);
glEnable(GL_TEXTURE_2D);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glDrawArrays(GL_QUADS, 0, vertexNum);
glDisableClientState(GL_VERTEX_ARRAY);
glDisable(GL_TEXTURE_2D);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);

glBindBuffer(GL_ARRAY_BUFFER, 0);
}
○VAO
ついでに、VAOへ置き換えると以下のようになる。
GLdouble vertices[sizeOfVertices] = {
-1.0, -1.0, 0.0,
1.0, -1.0, 0.0,
1.0, 1.0, 0.0,
-1.0, 1.0, 0.0
};
GLdouble texCoords[sizeOfTexCoords] = {
0.0, 1.0,
1.0, 1.0,
1.0, 0.0,
0.0, 0.0
};
GLuint vrtVBO;
GLuint uvVBO;
GLuint vao;

void init()
{
// VAOの生成
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);

// VBOの生成
glGenBuffers(1, &vrtVBO);
glGenBuffers(1, &uvVBO);

// 頂点の位置と設定の転送
glBindBuffer(GL_ARRAY_BUFFER, vrtVBO);
glBufferData(GL_ARRAY_BUFFER, sizeOfVertices * sizeof(GLdouble),
vertices, GL_STATIC_DRAW);
glVertexPointer(dimNum, GL_DOUBLE, 0, 0);
glEnableClientState(GL_VERTEX_ARRAY);

// UV座標の転送
glBindBuffer(GL_ARRAY_BUFFER, uvVBO);
glBufferData(GL_ARRAY_BUFFER, sizeOfTexCoords * sizeof(GLdouble),
texCoords, GL_STATIC_DRAW);
glTexCoordPointer(2, GL_DOUBLE, 0, 0);
glEnable(GL_TEXTURE_2D);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);

glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}

void scene()
{
glBindVertexArray(vao);
glDrawArrays(GL_QUADS, 0, vertexNum);
glBindVertexArray(vao);
}

↑このページのトップヘ