2014-09-13 208 views
4

目前,我試圖讓一個三角形使用OpenGL 3.3和C++與GLM,GLFW3和GLEW庫來渲染,而是得到一個錯誤試圖創建時我的shader程序。的OpenGL 3.3/GLSL&C++的錯誤:「必須寫入GL_POSITION」

Vertex info

(0) : error C5145: must write to gl_Position

我已經試圖找出爲什麼出現這種情況,並要求對其他論壇,但沒有人知道是什麼原因。有三種可能的點,其中該錯誤可能有他的起源 - 在我main.cpp中,在那裏我創建窗口,上下文,該程序,則VAO等...

#include <GL/glew.h> 
#include <GLFW/glfw3.h> 
#include <glm/glm.hpp> 

#include <iostream> 
#include <string> 

#include "util/shaderutil.hpp" 

#define WIDTH 800 
#define HEIGHT 600 

using namespace std; 
using namespace glm; 

GLuint vao; 
GLuint shaderprogram; 

void initialize() { 
    glGenVertexArrays(1, &vao); 
    glBindVertexArray(vao); 

    glClearColor(0.5, 0.7, 0.9, 1.0); 

    string vShaderPath = "shaders/shader.vert"; 
    string fShaderPath = "shaders/shader.frag"; 
    shaderprogram  = ShaderUtil::createProgram(vShaderPath.c_str(), fShaderPath.c_str()); 
} 

void render() { 
    glClear(GL_COLOR_BUFFER_BIT); 

    glUseProgram(shaderprogram); 

    glDrawArrays(GL_TRIANGLES, 0, 3); 
} 

void clean() { 
    glDeleteProgram(shaderprogram); 
} 


int main(int argc, char** argv) { 
    if (!glfwInit()) { 
    cerr << "GLFW ERROR!" << endl; 
    return -1; 
    } 

    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); 
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); 
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); 
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); 

    GLFWwindow* win = glfwCreateWindow(WIDTH, HEIGHT, "Rendering a triangle!", NULL, NULL); 
    glfwMakeContextCurrent(win); 
    glewExperimental = GL_TRUE; 

    if (glewInit() != GLEW_OK) { 
    cerr << "GLEW ERROR!" << endl; 
    return -1; 
    } else { 
    glGetError(); 
    //GLEW BUG: SETTING THE ERRORFLAG TO INVALID_ENUM; THEREFORE RESET 
    } 

    initialize(); 

    while (!glfwWindowShouldClose(win)) { 
    render(); 

    glfwPollEvents(); 
    glfwSwapBuffers(win); 
    } 

    clean(); 

    glfwDestroyWindow(win); 
    glfwTerminate(); 

    return 0; 
} 

...的ShaderUtil一流的,在這裏我在着色器文件中讀取,編譯它們,做錯誤檢查,並返回一個最終方案...

#include "shaderutil.hpp" 

#include <iostream> 
#include <string> 
#include <fstream> 
#include <vector> 

using namespace std; 

GLuint ShaderUtil::createProgram(const char* vShaderPath, const char* fShaderPath) { 
    /*VARIABLES*/ 
    GLuint vertexShader; 
    GLuint fragmentShader; 
    GLuint program; 

    ifstream vSStream(vShaderPath); 
    ifstream fSStream(fShaderPath); 
    string vSCode, fSCode; 

    /*CREATING THE SHADER AND PROGRAM OBJECTS*/ 
    vertexShader = glCreateShader(GL_VERTEX_SHADER); 
    fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); 
    program = glCreateProgram(); 

    /*READING THE SHADERCODE*/ 
    /*CONVERTING THE SHADERCODE TO CHAR POINTERS*/ 
    while (vSStream.is_open()) { 
    string line = ""; 
    while (getline(vSStream, line)) { 
     vSCode += "\n" + line; 
    } 
    vSStream.close(); 
    } 
    const char* vSCodePointer = vSCode.c_str(); 

    while (fSStream.is_open()) { 
    string line = ""; 
    while (getline(fSStream, line)) { 
     fSCode += "\n" + line; 
    } 
    fSStream.close(); 
    } 
    const char* fSCodePointer = fSCode.c_str(); 

    /*COMPILING THE VERTEXSHADER*/ 
    glShaderSource(vertexShader, 1, &vSCodePointer, NULL); 
    glCompileShader(vertexShader); 

    /*VERTEXSHADER ERROR CHECKING*/ 
    GLint vInfoLogLength; 
    glGetShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &vInfoLogLength); 

    if (vInfoLogLength > 0) { 
    vector<char> vInfoLog(vInfoLogLength + 1); 
    glGetShaderInfoLog(vertexShader, vInfoLogLength, &vInfoLogLength, &vInfoLog[0]); 

    for(int i = 0; i < vInfoLogLength; i++) { 
     cerr << vInfoLog[i]; 
    } 
    } 

    /*COMPILING THE FRAGMENTSHADER*/ 
    glShaderSource(fragmentShader, 1, &fSCodePointer, NULL); 
    glCompileShader(fragmentShader); 

    /*FRAGMENTSHADER ERROR CHECKING*/ 
    GLint fInfoLogLength; 
    glGetShaderiv(fragmentShader, GL_INFO_LOG_LENGTH, &fInfoLogLength); 

    if (fInfoLogLength > 0) { 
    vector<char> fInfoLog(fInfoLogLength + 1); 
    glGetShaderInfoLog(fragmentShader, fInfoLogLength, &fInfoLogLength, &fInfoLog[0]); 

    for(int i = 0; i < fInfoLogLength; i++) { 
     cerr << fInfoLog[i]; 
    } 
    } 

    /*LINKING THE PROGRAM*/ 
    glAttachShader(program, vertexShader); 
    glAttachShader(program, fragmentShader); 
    glLinkProgram(program); 
    //glValidateProgram(program); 

    /*SHADERPROGRAM ERROR CHECKING*/ 
    GLint programInfoLogLength; 
    glGetProgramiv(program, GL_INFO_LOG_LENGTH, &programInfoLogLength); 

    if (programInfoLogLength > 0) { 
    vector<char> programInfoLog(programInfoLogLength + 1); 
    glGetProgramInfoLog(program, programInfoLogLength, &programInfoLogLength, &programInfoLog[0]); 

    for(int i = 0; i < programInfoLogLength; i++) { 
     cerr << programInfoLog[i]; 
    } 
    } 

    /*CLEANUP & RETURNING THE PROGRAM*/ 
    glDeleteShader(vertexShader); 
    glDeleteShader(fragmentShader); 

    return program; 
} 

...和頂點着色器本身,這是沒有什麼特別的。我只是創建一個頂點數組,並將它們推入gl_Position。

#version 330 core 

void main() { 
    const vec3 VERTICES[3] = vec3[3] { 
    0.0, 0.5, 0.5, 
    0.5,-0.5, 0.5, 
    -0.5,-0.5, 0.5 
    }; 

    gl_Position.xyz = VERTICES; 
    gl_Position.w = 1.0; 
} 

fragmentshader只輸出一個叫做color的vec4,它被設置爲(1.0,0.0,0.0,1.0)。編譯器不會顯示任何錯誤,但是當我嘗試執行該程序時,我只是得到一個沒有三角形的窗口和上面顯示的錯誤消息。

還有我已經嘗試過解決這個問題的幾件事情,但他們沒有工作:

  • 我嘗試創建我的main.cpp裏面的頂點,並通過頂點推入頂點着色器緩衝對象;我改變了一些受opengl-tutorials.org啓發的代碼,最後得到了一個三角形來顯示,但着色器沒有應用;我只有main.cpp中的頂點出現在屏幕上,但「必須寫入gl_Position」問題依然存在。

  • 我嘗試了不同的地方使用glGetError(),並得到了2個不同的錯誤代碼:1280和1282;第一個是由GLEW內部的一個錯誤引起的,這導致狀態從GL_NO_ERROR改變爲GL_INVALID_ENUM或類似的東西。我被告知忽略這個,並且在初始化GLEW之後通過使用glGetError()將狀態改回到GL_NO_ERROR。在渲染函數中使用glUseProgram()後出現了另一個錯誤代碼。我想從中獲得一些信息,但gluErrorString()函數在OpenGL 3.3中已被棄用,我找不到任何我的庫提供的替代方法。

  • 我試着將它鏈接驗證後通過glValidateProgram我的程序()。當我這樣做時,GL_POSITION錯誤信息沒有露面了,但三角形沒有任何,所以我認爲這個功能只是清除信息日誌把一些新的信息有關驗證過程

所以現在,我不知道是什麼原因導致了這個錯誤。

+5

'VERTICES'是三個'vec3'實例的數組。 'gl_Position.xyz'是一個'vec3'。不計算。 – 2014-09-13 01:09:36

+0

是的,頂點着色器不會編譯。如果你遇到錯誤情況,你有沒有檢查過調試器?出於某種原因,您可能看不到錯誤輸出。例如,打印錯誤後,您不會輸出換行符。嘗試添加一個'cerr << endl'。 – 2014-09-13 01:32:12

回答

2

頂點着色上的每個頂點運行獨立,所以GL_POSITION是輸出頂點無論轉換後要適用於頂點着色器正在處理的頂點,所以試圖發出多個頂點就沒有意義了。幾何着色器可以即時發出其他幾何圖形,例如可用於創建運動模糊。

對於典型繪圖,您可以像綁定頂點數組一樣綁定頂點數組對象,但將數據放入名爲Vertex Buffer Objects的緩衝區中,並告訴OpenGL如何使用glVertexAttrib解釋數據的「屬性」,您可以在着色器中讀取它們。

+0

我創建了一個像你說的VBO,在我的main.cpp中創建了一個GLFloats數組,並將它放入VBO中,並嘗試繪製它。我的三角現在出現了,但是「gl_Position」 - 錯誤仍然存​​在,着色器似乎沒有被應用。這是目前的樣子:http://pastebin.com/fZs16288 – DocCoock 2014-09-13 12:19:58

+0

Cpp看起來不錯,你可以發佈你的着色器源代碼嗎? – MtRoad 2014-09-13 14:08:09

+0

當然! 頂點着色器:http://pastebin.com/VSRHQG6g 片段着色器:http://pastebin.com/nhqUT2T7 – DocCoock 2014-09-13 14:55:44

8

問題解決了!我試圖打印OpenGL試圖編譯的源代碼,並看到ifstream沒有加載源代碼。事情我不得不改變:

  1. 更改 「而(vVStream.is_open())」,以 「如果(vVStream.is_open())」。
  2. 錯誤檢查,如果我先列出的條件執行(加「否則{CERR < <‘糟糕!’< < ENDL}
  3. 添加第二個參數來我創建了ifstreams:改變」 ifstream的(路徑)「到」ifstream(path,ios :: in)「
  4. 將我從相對路徑(例如」../shaders/shader.vert「)傳遞到絕對路徑(例如」/ home/USERNAME/Desktop/project/src/shaders/shader.vert「);這是必須的,因爲相對路徑不被理解;使用絕對路徑並不是永久的解決方案,但它解決了未找到着色器。

現在它實際上加載和編譯着色器;仍然有一些錯誤需要解決,但是如果某人具有相同的「必須寫入gl_Position」問題,則double,no,triple-check檢查您試圖編譯的源是否實際加載,以及ifstream是否實際打開。

我感謝所有試圖幫助我的人,特別是@MtRoad。這個問題幾乎讓我變得禿頭。

0

最近遇到此問題&我懷疑原因可能與您的相同。

我不熟悉g ++,但是,在VS的構建環境&您的* EXE運行時的位置可能會影響您的調試。 例如,一個這樣的設置:

Project Properties -> General -> Output directory -> 

Visual Studios Express - change debug output directory

和另一個相似的問題在這裏"The system cannot find the file specified" when running C++ program

你需要確保你已經改變構建環境,你從一個調試不同的輸出目錄,任何相關文件都與執行* exe的位置相關。

這可以解釋爲什麼你不得不求助於使用「如果(vVStream.is_open())」,我懷疑發生故障,&所以隨後使用着色器的完整文件路徑爲原始引用文件不相。

我的問題與您的問題完全相同,但僅限於發佈模式。一旦我將我的着色器複製到* exe可以訪問它們的發佈文件夾中,問題就消失了。

相關問題