現在、GLSLの勉強をしているのですが、シェーダオブジェクトをリンクする処理が失敗してしまい、困っています。
皆様の知識と経験をお貸しいただければ幸いです。
エラーメッセージ
シェーダプログラムのリンクに失敗しました
プログラム ログ:
ERROR:Definition for "void main()" not found.
該当のソースコード
言語:C,GLSL
///////////////////////////////////////////////////
//maincpp
///////////////////////////////////////////////////
//include
#include <iostream>
#include <fstream>
#include <sstream>
#include <GL/glew.h>
#include <GL/glut.h>
using namespace std;
//link
#pragma comment (lib, "glew32.lib")
//global
int windowPositionX = 100; //ウィンドウを開く位置
int windowPositionY = 100;
int windowWidth = 512; //ウィンドウ幅
int windowHeight = 512; //ウィンドウ高さ
char windowTitle[] = "GLSLプロジェクト"; //タイトル
GLuint vaoHandle;
//prototype
void Initialize();
void Display();
void Reshape(int x, int y);
void Keyboard(unsigned char key, int x, int y);
void CompileShder();
void LinkShaderObject(GLuint vertShader, GLuint fragShader);
const GLchar* ReadFile(const GLchar* file);
//=====================================
//初期化処理
//=====================================
void Initialize()
{
//GLEWの初期化
if (glewInit() != GLEW_OK)
{
cout << "Error : GLEWの初期化に失敗しました\n";
exit(0);
}
//ウィンドウを塗りつぶす際の色を指定
glClearColor(1.0, 1.0, 1.0, 1.0);
CompileShder();
}
//=========================================
//ウィンドウの拡大縮小に対する処理
//w:現在のウィンドウ幅
//h:現在のウィンドウの高さ
//=========================================
void Reshape(int x, int y)
{
windowWidth = x;
windowHeight = y;
//ウィンドウの最小サイズを制限
if (windowWidth < 1) windowWidth = 1;
if (windowHeight < 1) windowHeight = 1;
//ビューポートの設定
glViewport(0, 0, windowWidth, windowHeight);
}
//=========================================
//ウィンドウへの描画
//=========================================
void Display()
{
//ウィンドウを塗りつぶす(カラーバッファ指定)
glClear(GL_COLOR_BUFFER_BIT);
//ビューポートの設定
glViewport(0, 0, windowWidth, windowHeight);
glBindVertexArray(vaoHandle);
glDrawArrays(GL_TRIANGLES, 0, 3);
}
//=========================================
//キーボードから入力されたとき
//key:タイプされたキーの情報
//x,y:マウスの位置
//=========================================
void Keyboard(unsigned char key, int x, int y)
{
switch (key)
{
case '\033': //'\033'はESCのASCIIコード
exit(0);
break;
default:
break;
}
}
//=====================================
//メインエントリポイント
//=====================================
int main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitWindowPosition(windowPositionX, windowPositionY); //新たに開くウィンドウの位置を指定
glutInitWindowSize(windowWidth, windowHeight); //新たに開くウィンドウの幅と高さを指定
glutInitDisplayMode(GLUT_RGBA); //ディスプレイの表示モードを設定(RGBA指定)
glutCreateWindow(windowTitle); //ウィンドウを開く
glutDisplayFunc(Display); //ウィンドウ内に描画する関数へのポインタ(ウィンドウの再描画の際に呼ばれる)
glutReshapeFunc(Reshape); //ウィンドウがリサイズされたときに実行される関数へのポインタを渡す
//glutIdleFunc(Idle); //プログラムが暇なときに実行される関数へのポインタを渡す
//glutMouseFunc(Mouse); //マウスのボタンが押されたときに実行される関数へのポインタを渡す
//glutMotionFunc(Motion); //マウスのボタンを押しながら動かしたときに実行される関数へのポインタを渡す
//glutPassiveMotionFunc(PassiveMotion); //マウスのボタンを押さずに動かしたときに実行される関数へのポインタを渡す
//glutKeyboardFunc(Keyboard); //キーがタイプされたときに実行される関数へのポインタを渡す
//glutSpecialFunc(Special); //特殊キーがタイプされたときに実行される関数へのポインタを渡す
Initialize();
glutMainLoop();
return 0;
}
//=====================================
//シェーダオブジェクトのコンパイル
//=====================================
void CompileShder()
{
GLuint vertShader, fragShader;
//頂点シェーダのコンパイル
vertShader = glCreateShader(GL_VERTEX_SHADER); //シェーダオブジェクトのハンドル作成
if (0 == vertShader)
{
fprintf(stderr, "頂点シェーダ作成エラー\n");
exit(1);
}
//ソースコードをシェーダオブジェクトにコピー
const GLchar* vertShaderCode = ReadFile("shader/basic.vert"); //ファイルを読み込み
const GLchar* vertShaderCodeArry[] = { vertShaderCode }; //配列にソースコードへのポインタを格納
glShaderSource(vertShader, 1, vertShaderCodeArry, NULL); //ソースコードをシェーダオブジェクトへロード
//シェーダをコンパイル
glCompileShader(vertShader);
//コンパイルステータスを検証
GLint result;
glGetShaderiv(vertShader, GL_COMPILE_STATUS, &result); //コンパイルステータスを問い合わせる
if (GL_FALSE == result)
{
fprintf(stderr, "頂点シェーダのコンパイルに失敗しました\n");
GLint logLen;
glGetShaderiv(vertShader, GL_INFO_LOG_LENGTH, &logLen); //ログの長さを問い合わせる
if (logLen > 0)
{
char* log = (char*)malloc(logLen);
GLsizei written;
glGetShaderInfoLog(vertShader, logLen, &written, log); //ログを取り出す
fprintf(stderr, "シェーダ ログ: \n%s", log);
free(log);
}
}
//フラグメントシェーダのコンパイル
fragShader = glCreateShader(GL_FRAGMENT_SHADER); //シェーダオブジェクトのハンドル作成
if (0 == fragShader)
{
fprintf(stderr, "フラグメントシェーダ作成エラー\n");
exit(1);
}
//ソースコードをシェーダオブジェクトにコピー
const GLchar* fragShaderCode = ReadFile("shader/basic.frag"); //ファイルを読み込み
const GLchar* fragShaderCodeArray[] = { fragShaderCode }; //配列にソースコードへのポインタを格納
glShaderSource(fragShader, 1, fragShaderCodeArray, NULL); //ソースコードをシェーダオブジェクトへロード
//シェーダをコンパイル
glCompileShader(fragShader);
//コンパイルステータスを検証
glGetShaderiv(fragShader, GL_COMPILE_STATUS, &result); //コンパイルステータスを問い合わせる
if (GL_FALSE == result)
{
fprintf(stderr, "フラグメントシェーダのコンパイルに失敗しました\n");
GLint logLen;
glGetShaderiv(fragShader, GL_INFO_LOG_LENGTH, &logLen); //ログの長さを問い合わせる
if (logLen > 0)
{
char* log = (char*)malloc(logLen);
GLsizei written;
glGetShaderInfoLog(fragShader, logLen, &written, log); //ログを取り出す
fprintf(stderr, "シェーダ ログ: \n%s", log);
free(log);
}
}
LinkShaderObject(vertShader, fragShader);
float positionData[] = {
-0.8f, -0.8f, 0.0f,
0.8f, -0.8f, 0.0f,
0.0f, 0.8f, 0.0f };
float colorData[] = {
1.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 1.0f };
// 頂点バッファオブジェクトの作成
GLuint vboHandles[2]; //頂点バッファオブジェクトのメモリを参照するポインタを格納する配列
glGenBuffers(2, vboHandles); //頂点バッファオブジェクト作成して配列に格納
GLuint positionBufferHandle = vboHandles[0];
GLuint colorBufferHandle = vboHandles[1];
glBindBuffer(GL_ARRAY_BUFFER, positionBufferHandle); //バッファオブジェクト有効にする(頂点バッファオブジェクト指定)
glBufferData(GL_ARRAY_BUFFER, 9 * sizeof(float), positionData, GL_STATIC_DRAW); //バッファオブジェクトのメモリを確保して、そこにデータを転送(頂点バッファオブジェクト指定)
glBindBuffer(GL_ARRAY_BUFFER, colorBufferHandle);
glBufferData(GL_ARRAY_BUFFER, 9 * sizeof(float), colorData, GL_STATIC_DRAW);
glGenVertexArrays(1, &vaoHandle);
glBindVertexArray(vaoHandle);
glEnableVertexAttribArray(0); // Vertex position
glEnableVertexAttribArray(1); // Vertex color
glBindBuffer(GL_ARRAY_BUFFER, positionBufferHandle);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (GLubyte *)NULL);
glBindBuffer(GL_ARRAY_BUFFER, colorBufferHandle);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (GLubyte *)NULL);
}
//=====================================
//シェーダオブジェクトのリンク
//=====================================
void LinkShaderObject(GLuint vertShader, GLuint fragShader)
{
//プログラムオブジェクト作成
GLuint programHandle = glCreateProgram(); //プログラムオブジェクトのハンドル作成
if (0 == programHandle)
{
fprintf(stderr, "プログラムオブジェクト作成でエラーがありました\n");
exit(1);
}
//シェーダーをプログラムオブジェクトにアタッチ
glAttachShader(programHandle, vertShader);
glAttachShader(programHandle, fragShader);
//プログラムをリンク
glLinkProgram(programHandle);
//ステータスを検証
GLint status;
glGetProgramiv(programHandle, GL_LINK_STATUS, &status); //コンパイルステータスを問い合わせる
if (GL_FALSE == status)
{
fprintf(stderr, "シェーダ プログラムのリンクに失敗しました\n");
GLint logLen;
glGetProgramiv(programHandle, GL_INFO_LOG_LENGTH, &logLen); //ログの長さを問い合わせる
if (logLen > 0)
{
char* log = (char*)malloc(logLen);
GLsizei written;
glGetProgramInfoLog(programHandle, logLen, &written, log); //ログを取り出す
fprintf(stderr, "プログラム ログ: \n%s", log);
free(log);
}
}
else
{
glUseProgram(programHandle); //リンクが成功したら、プログラムをOpenGLパイプラインにインストール
}
}
//=====================================
//ファイルの読み込み
//file:読み込むソースファイル
//=====================================
const GLchar* ReadFile(const GLchar* file)
{
ifstream inFile(file); //ファイル読み込み
if (!inFile)
{
fprintf(stderr, "Error opening file: %s\n", file);
exit(1);
}
stringstream code;
code << inFile.rdbuf();
inFile.close();
string codeStr(code.str());
return codeStr.c_str(); //codeStrオブジェクトに含まれる文字列をヌル終端文字列に変換
}
///////////////////////////////////////////////////
//シェーダソース
//basic.vert
///////////////////////////////////////////////////
#version 430
layout (location=0) in vec3 vertexPosition;
layout (location=1) in vec3 vertexColor;
out vec3 color;
void main()
{
color = vertexColor;
gl_Position = vec4(vertexPosition, 1.0);
}
///////////////////////////////////////////////////
//シェーダソース
//basic.frag
///////////////////////////////////////////////////
#version 430
in vec3 color;
layout (location=0) out vec4 flagColor;
void main()
{
flagColor = vec4(color, 1.0);
}
ブレークポイントなどで調べてみたところ、glShaderSource()関数でシェーダオブジェクトへソースコードをロードした後、シェーダオブジェクトの中身は改行文字"\0"しか格納されておらず。それが原因かと考えているのですが。試行錯誤してもうまくいきませんでした。
使用しているPCが対応しているバージョンは以下の通りです。
OpenGL:4.30
GLSL:4.30
参考資料
OpenGL4.0シェーディング言語
よろしくお願いします!
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
0
まず、質問でコードを張るときは`三つの行で挟んでください
ReadFileが問題です。 std::string::c_strの返すポインタの生存期間はそれを呼んだオブジェクトと同じです。 ローカル変数のstd::string::c_strを返しても関数を抜けるとそのポインタの指す文字列は解放済みです。
CやC++などのGCの無い言語を扱う場合はそのオブジェクトの寿命を把握しましょう。
std::string ReadFile(const GLchar* file)
{
ifstream inFile(file); //ファイル読み込み
if (!inFile)
{
fprintf(stderr, "Error opening file: %s\n", file);
exit(1);
}
stringstream code;
code << inFile.rdbuf();
inFile.close();
return code.str();
}
//使用する箇所
std::string vertShaderCode = ReadFile("shader/basic.vert"); //ファイルを読み込み
const GLchar* vertShaderCodeArry[] = { vertShaderCode.c_str() }; //配列にソースコードへのポインタを格納
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
0
自己解決しました!
原因はシェーダファイルの作成方法にありました。
シェーダファイルを開くプログラムを選択したことによって開くことができました。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.37%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
2016/04/28 23:04
返信が遅くなってしまい申し訳ございませんでした。
アドバイスに習い、早速質問を編集させていただきました。
ありがとうございました!
ご指摘していただいた点を修正したところ、ファイルの読み取りの時点で読み取りエラーが発生していました。只今、オブジェクトの寿命を考え、glShaderSource()関数と同じスコープ内でのファイルの読み取りや、別の読み取り手法を試しているのですが、うまくいきません。
お手数をおかけしますが、もし他にご指摘いただける点があればご教授頂けると幸いです。
よろしくお願いいたします。