2016-10-23 75 views
-1

我想學習OpenGL作爲學生。我花了很多時間試圖找出爲什麼這個簡單的應用程序不工作。這是我們教授給出的一個例子。 (我們使用visual studio在windows中工作,但我別無選擇,只能在家使用Linux,它不是一個隨心所欲的)。這裏是我寫的程序(在windows上工作完美),只是顯示一個黑色的窗口(它應該顯示一個三角形)。簡單的OpenGL應用程序

// 
// main.cpp 
// OpenGL_Shader_Example_step1 
// 
// Created by CGIS on 30/11/15. 
// Copyright © 2015 CGIS. All rights reserved. 
// 

#define GLEW_STATIC 

#include <iostream> 
#include "GL/glew.h" 
#include "GLFW/glfw3.h" 

#include <fstream> 
#include <sstream> 
#include <iostream> 
#include <string> 
#include <stdio.h> 
#include <stdlib.h> 
#include <vector> 

int glWindowWidth = 640; 
int glWindowHeight = 480; 
int retina_width, retina_height; 
GLFWwindow* glWindow = NULL; 

GLuint shaderProgram; 

GLfloat vertexCoordinates[] = { 
           0.0f, 0.5f, 0.0f, 
           0.5f, -0.5f, 0.0f, 
           -0.5f, -0.5f, 0.0f 
           }; 
GLuint verticesVBO; 
GLuint triangleVAO; 

void windowResizeCallback(GLFWwindow* window, int width, int height) 
{ 
    fprintf(stdout, "window resized to width: %d , and height: %d\n", width, height); 
    //TODO 
} 

void initObjects() 
{ 
    //generate a unique ID corresponding to the verticesVBO 
    glGenBuffers(1, &verticesVBO); 
    //bind the verticesVBO buffer to the GL_ARRAY_BUFFER target, 
    //any further buffer call made to GL_ARRAY_BUFFER will configure the 
    //currently bound buffer, which is verticesVBO 
    glBindBuffer(GL_ARRAY_BUFFER, verticesVBO); 
    //copy data into the currently bound buffer, the first argument specify 
    //the type of the buffer, the second argument specify the size (in bytes) of data, 
    //the third argument is the actual data we want to send, 
    //the last argument specify how should the graphic card manage the data 
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertexCoordinates), vertexCoordinates, GL_STATIC_DRAW); 

    //generate a unique ID corresponding to the triangleVAO 
    glGenVertexArrays(1, &triangleVAO); 
    glBindVertexArray(triangleVAO); 
    glBindBuffer(GL_ARRAY_BUFFER, verticesVBO); 
    //set the vertex attributes pointers 
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL); 
    glEnableVertexAttribArray(0); 
    //unbind the triangleVAO 
    glBindVertexArray(0); 
} 

bool initOpenGLWindow() 
{ 
    if (!glfwInit()) { 
     fprintf(stderr, "ERROR: could not start GLFW3\n"); 
     return false; 
    } 

    //for Mac OS X 
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); 
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1); 
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); 
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); 

    glWindow = glfwCreateWindow(glWindowWidth, glWindowHeight, "OpenGL Shader Example", NULL, NULL); 
    if (!glWindow) { 
     fprintf(stderr, "ERROR: could not open window with GLFW3\n"); 
     glfwTerminate(); 
     return false; 
    } 

    glfwSetWindowSizeCallback(glWindow, windowResizeCallback); 
    glfwMakeContextCurrent(glWindow); 

    glfwWindowHint(GLFW_SAMPLES, 4); 

    // start GLEW extension handler 
    glewExperimental = GL_TRUE; 
    glewInit(); 

    // get version info 
    const GLubyte* renderer = glGetString(GL_RENDERER); // get renderer string 
    const GLubyte* version = glGetString(GL_VERSION); // version as a string 
    printf("Renderer: %s\n", renderer); 
    printf("OpenGL version supported %s\n", version); 

    //for RETINA display 
    glfwGetFramebufferSize(glWindow, &retina_width, &retina_height); 

    return true;  
} 

void renderScene() 
{ 
    //clear the color and depth buffer before rendering the current frame 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
    //specify the background color 
    glClearColor(0.8, 0.8, 0.8, 1.0); 
    //specify the viewport location and dimension 
    glViewport (0, 0, retina_width, retina_height); 

    //process the keyboard inputs 
    if (glfwGetKey(glWindow, GLFW_KEY_A)) { 
    //TODO 
    } 

    if (glfwGetKey(glWindow, GLFW_KEY_D)) { 
    //TODO 
    } 

    //bind the shader program, any further rendering call 
    //will use this shader program 
    glUseProgram(shaderProgram); 

    //bind the VAO 
    glBindVertexArray(triangleVAO); 
    //specify the type of primitive, the starting index and 
    //the number of indices to be rendered 
    glDrawArrays(GL_TRIANGLES, 0, 3); 
} 

std::string readShaderFile(std::string fileName) 
{ 
    std::ifstream shaderFile; 
    std::string shaderString; 

    //open shader file 
    shaderFile.open(fileName.c_str()); 

    std::stringstream shaderStringStream; 

    //read shader content into stream 
    shaderStringStream << shaderFile.rdbuf(); 

    //close shader file 
    shaderFile.close(); 

    //convert stream into GLchar array 
    shaderString = shaderStringStream.str(); 
    return shaderString; 
} 

void shaderCompileLog(GLuint shaderId) 
{ 
    GLint success; 
    GLchar infoLog[512]; 

    //check compilation info 
    glGetShaderiv(shaderId, GL_COMPILE_STATUS, &success); 
    if (!success) 
    { 
     glGetShaderInfoLog(shaderId, 512, NULL, infoLog); 
     std::cout << "Shader compilation error\n" << infoLog << std::endl; 
    } 
} 

void shaderLinkLog(GLuint shaderProgramId) 
{ 
    GLint success; 
    GLchar infoLog[512]; 

    //check linking info 
    glGetProgramiv(shaderProgramId, GL_LINK_STATUS, &success); 
    if (!success) { 
     glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog); 
     std::cout << "Shader linking error\n" << infoLog << std::endl; 
    } 
} 

GLuint initBasicShader(std::string vertexShaderFileName, std::string fragmentShaderFileName) 
{ 
    //read, parse and compile the vertex shader 
std::string v = readShaderFile(vertexShaderFileName); 
const GLchar* vertexShaderString = v.c_str(); 
GLuint vertexShader; 
vertexShader = glCreateShader(GL_VERTEX_SHADER); 
glShaderSource(vertexShader, 1, &vertexShaderString, NULL); 
glCompileShader(vertexShader); 
//check compilation status 
shaderCompileLog(vertexShader); 

//read, parse and compile the vertex shader 
std::string f = readShaderFile(fragmentShaderFileName); 
const GLchar* fragmentShaderString = f.c_str(); 
GLuint fragmentShader; 
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); 
glShaderSource(fragmentShader, 1, &fragmentShaderString, NULL); 
glCompileShader(fragmentShader); 
//check compilation status 
shaderCompileLog(fragmentShader); 

//attach and link the shader programs 
shaderProgram = glCreateProgram(); 
glAttachShader(shaderProgram, vertexShader); 
glAttachShader(shaderProgram, fragmentShader); 
glLinkProgram(shaderProgram); 
glDeleteShader(vertexShader); 
glDeleteShader(fragmentShader); 
//check linking info 
shaderLinkLog(shaderProgram); 

return shaderProgram; 
} 

int main(int argc, const char * argv[]) 
{ 
    initOpenGLWindow(); 

    initObjects(); 

    shaderProgram = initBasicShader("shaders/shader.vert", "shaders/shader.frag"); 

    while (!glfwWindowShouldClose(glWindow)) { 
     renderScene(); 

     glfwPollEvents(); 
     glfwSwapBuffers(glWindow); 
    } 

    //close GL context and any other GLFW resources 
    glfwTerminate(); 

    return 0; 
} 

這裏是着色器程序: shader.frag:

#version 300 es 
precision mediump float; 

in vec3 colour; 
out vec4 frag_colour; 

void main() { 
    frag_colour = vec4 (colour, 1.0); 
} 

和shader.vert:

#version 300 es 

layout (location = 0) in vec3 vertex_position; 

out vec3 colour; 

void main() { 
    colour = vec3(1.0, 0.0, 0.0); 
    gl_Position = vec4(vertex_position, 1.0); 
} 

,並在這裏被用來編譯程序的命令(我使用視覺工作室代碼):

{ 
    // See https://go.microsoft.com/fwlink/?LinkId=733558 
    // for the documentation about the tasks.json format 
    "version": "0.1.0", 
    "command": "g++", 
    "isShellCommand": true, 
    "args": ["-g", 
      "-Wall", 
      "-o", "lab2.exe", 
      "main.cpp", 
      "-I/usr/include/c++/4.8.5", 
      "-I/usr/include/GL", 
      "-I/usr/include/glm", 
      "-I/usr/local/include/GLFW", 
      "-L/usr/local/lib", "-lGLEW", "-lGLU", "-lglfw3", "-lGL", "-lm", "-ldl", "-lXrender", "-ldrm", 
      "-lXdamage", "-lX11-xcb", "-lxcb-glx", "-lxcb-dri2", "-lxcb-dri3", "-lxcb-present", "-lxcb-sync", "-lxshmfence", "-lXxf86vm", 
      "-lXfixes", "-lXext", "-lX11", "-lpthread", "-lxcb", "-lXau", "-lXdmcp", 
      "-lXrandr", "-lXi", "-lXxf86vm", "-lXcursor"], 
    "showOutput": "always" 
} 

args參數給予g ++。 如果我會有一個錯誤,我會從一個點開始,但是像這樣我不知道該怎麼做。

這裏是glxinfo | grep OpenGL命令的結果:

OpenGL vendor string: Intel Open Source Technology Center 
OpenGL renderer string: Mesa DRI Intel(R) Haswell Mobile 
OpenGL core profile version string: 3.3 (Core Profile) Mesa 11.2.0 
OpenGL core profile shading language version string: 3.30 
OpenGL core profile context flags: (none) 
OpenGL core profile profile mask: core profile 
OpenGL core profile extensions: 
OpenGL version string: 3.0 Mesa 11.2.0 
OpenGL shading language version string: 1.30 
OpenGL context flags: (none) 
OpenGL extensions: 
+1

調試幫助問題需要[mcve]按照[幫助]。你的代碼不是最小的。請[編輯]你的問題,以確保你的代碼是最小的(只有在你的問題中重現你的問題所需的代碼),完整(用戶不需要其他任何東西來重現你的問題),和可驗證的(提供的代碼重現你正面臨的確切問題)。因爲這是你的問題是堆棧溢出的主題。請注意,這也是一個常見的[downvote reason](http://idownvotedyoubecause.com/so/TooMuchCode)。 –

+0

你似乎沒有關於編程的實際具體問題。您只需閱讀[如何調試小程序]就可以獲得更多益處(https://ericlippert.com/2014/03/05/how-to-debug-small-programs/)。 – StoryTeller

+2

你要求的是opengl 4.1,但驅動程序只支持3.3。我沒有仔細檢查你是否真的使用了需要更新版本的東西。但要檢查出現什麼問題,您想使用gl調試或跟蹤來查看哪些opengl/glx調用失敗。這將有助於找出實際存在的問題。 –

回答

0

我建議使用一個OpenGL/GLSL調試器,看看是怎麼回事。這已經有一段時間了,但我以前使用glslDevil獲得了很多成功 - 它與Linux兼容,可能會幫助您發現opengl錯誤 - 尤其是硬件/平臺上不支持的功能。