ここでは、OpenGL Shader Languageを使うための準備を行います.
作成に用いた環境
- OpenGL3.2
- GLUT(freeglut) - 2.6.0
- GLEW - 1.5.7
GLSLの手続き
- バーテックスシェーダとフラグメントシェーダのシェーダオブジェクトを(glCreateShader)
- ソースプログラム読み込み(glShaderSource)
- 読み込んだソースプログラムをコンパイル (glCompileShader)
- プログラムオブジェクト作成 (glCreateProgram)
- プログラムオブジェクトにシェーダオブジェクト接続 (glAttachShader)
- シェーダプログラムをリンク(glLinkProgram)
- シェーダプログラム適用(glUseProgram)
- シェーダプログラムオブジェクト作成の流れ

シェーダプログラム作成用関数の準備
シェーダプログラムを作成する手順は、基本的に同じです。
なので、関数化して共通ファイルにしておきます。
なので、関数化して共通ファイルにしておきます。
- load_shader.h
#ifndef __LOAD_SHADER_H_
#define __LOAD_SHADER_H_
#include <GL/glew.h>
#include <GL/gl.h>
GLuint loadShaderFromFile(GLenum type, const char *fileName);
GLuint loadShader(GLenum type, const char *str, const char* fileName="");
GLuint createProgram(const char* vsName, const char* fsName);
#endif // __LOAD_SHADER_H_
- load_shader.cpp
#include <iostream>
#include <fstream>
#include "load_shader.h"
GLuint createProgram(const char* vsName, const char* fsName)
{
GLuint programObject;
GLuint vertexShader;
GLuint fragmentShader;
programObject = glCreateProgram();
if (programObject == 0) return 0;
vertexShader = loadShaderFromFile(GL_VERTEX_SHADER, vsName);
glAttachShader(programObject, vertexShader);
fragmentShader = loadShaderFromFile(GL_FRAGMENT_SHADER, fsName);
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 0;
}
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
return programObject;
}
GLuint loadShaderFromFile(GLenum type, const char *fileName)
{
std::fstream inputFile(fileName);
std::istreambuf_iterator<char> dataBegin(inputFile);
std::istreambuf_iterator<char> dataEnd;
std::string fileData(dataBegin, dataEnd);
const char *str = fileData.c_str();
return loadShader(type, str, fileName);
}
GLuint loadShader(GLenum type, const char *str, const char *fileName)
{
GLuint shader;
GLint compiled;
shader = glCreateShader(type);
if (shader == 0)
return 0;
glShaderSource(shader, 1, &str, 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;
}
使うAPIは次の1つだけ。
createProgram( "頂点シェーダファイル名", "フラグメントシェーダファイル名" ); 戻り値:GLuint シェーダプログラムオブジェクト
GLSLの空プロジェクト(GLUT版)
まずは空のプロジェクトを作ってみます。
ここではGLUTを使っています。
ここではGLUTを使っています。
#include <iostream>
#include <fstream>
#include <cstdlib>
#include "load_shader.h"
#include <GL/glew.h>
#include <GL/glut.h>
GLuint programObject;
void init();
void reshape(int w, int h);
void timer(int t);
void display();
void init()
{
glClearColor(0.5, 0.5, 0.5, 1.0);
glClearDepth(1.0f);
programObject = createProgram("simple.vert", "simple.frag");
}
void reshape(int w, int h)
{
glViewport(0, 0, w, h);
}
void timer(int t)
{
glutPostRedisplay();
glutTimerFunc(t, timer, 17);
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(programObject);
/* ここに描画記述 */
glUseProgram(0);
glutSwapBuffers();
}
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;
//glewExperimental = GL_TRUE; // 有効なエントリーポイントを持つ全ての拡張の公開が保証
err = glewInit();
if (err != GLEW_OK) {
std::cerr << "GLEW error : " << glewGetErrorString(err) << "\n";
std::exit(1);
}
if (!glewIsSupported("GL_VERSION_3_2"))
{
printf("OpenGL 3.2 not supported.");
std::exit(1);
}
init();
glutMainLoop();
return 0;
}
- simple.vert
void main(void)
{
gl_Position = vec4(0.0, 0.0, 0.0, 0.0);
}
シェーダでは、必ずgl_Positionが必要のようです。
- simple.frag
void main(void)
{
}
ダウンロード
