質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.49%
OpenGL

OpenGLは、プラットフォームから独立した、デスクトップやワークステーション、モバイルサービスで使用可能な映像処理用のAPIです。

GLSL

GLSL (OpenGL Shading Language) はC言語をベースとしたシェーディング言語です。

Q&A

解決済

2回答

3989閲覧

OpenGLのシェーダオブジェクトのリンク処理で困っています。

OWO

総合スコア11

OpenGL

OpenGLは、プラットフォームから独立した、デスクトップやワークステーション、モバイルサービスで使用可能な映像処理用のAPIです。

GLSL

GLSL (OpenGL Shading Language) はC言語をベースとしたシェーディング言語です。

0グッド

0クリップ

投稿2016/04/27 17:44

編集2016/04/28 13:45

現在、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シェーディング言語

よろしくお願いします!

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

自己解決しました!
原因はシェーダファイルの作成方法にありました。
シェーダファイルを開くプログラムを選択したことによって開くことができました。

投稿2016/04/29 14:48

OWO

総合スコア11

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

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() }; //配列にソースコードへのポインタを格納

投稿2016/04/27 22:05

satoren

総合スコア109

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

OWO

2016/04/28 14:04

ご回答いただき、ありがとうございます! 返信が遅くなってしまい申し訳ございませんでした。 アドバイスに習い、早速質問を編集させていただきました。 ありがとうございました! ご指摘していただいた点を修正したところ、ファイルの読み取りの時点で読み取りエラーが発生していました。只今、オブジェクトの寿命を考え、glShaderSource()関数と同じスコープ内でのファイルの読み取りや、別の読み取り手法を試しているのですが、うまくいきません。 お手数をおかけしますが、もし他にご指摘いただける点があればご教授頂けると幸いです。 よろしくお願いいたします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問