2016-05-09 10 views
1

私のコンピュータでは、Intelグラフィックカードを搭載したUbuntu 16.04が動作します。私はOpenGLプロファイルにMesa 11.2を使用しています。OpenGL:ポリゴンモードを切り替えるとsegfaultが発生する

私の謙虚なOpenGLプログラムは、ウィンドウ内に単純な正方形を表示します。私は、特定のキーを押した場合にし、ワイヤフレームモードのうち、プログラムの切り替えを作りたかったので、私は、次のコールバック関数を定義した:

残念ながら
void keyCallback(GLFWwindow *window, int key, int scancode, int action, int mode) { 
    if (key == GLFW_KEY_ESCAPE and action == GLFW_PRESS) { 
     glfwSetWindowShouldClose(window, GL_TRUE); 
    } 
    if (key == GLFW_KEY_M and action == GLFW_PRESS) { 
     // Find the rasterizing mode. 
     GLint rastMode; 
     glGetIntegerv(GL_POLYGON_MODE, &rastMode); 

     // Switch modes depending on current rasterizing mode. 
     if (rastMode == GL_FILL) { 
      glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
     } 
     else { 
      glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); 
     } 
    } 
} 

、私のプログラムは、セグメンテーションフォルトが発生します実行中にMを押します。不思議なことに、私のの他のコンピュータ(Ubuntu 16.04を実行していますが、Nvidia GPUを使用しています)では、私はそのような問題はなく、プログラムは期待通りに動作します。

問題はglPolygonModeではありません。それは私のmain機能の中に置くことができ、プログラムはモードを正常に切り替えます。問題はglGetIntegervであると思われます。私のmain関数内でその関数を呼び出すと(ゲームループの外で)、私の四角は表示されません(segfaultはありません)。 、前向きと後ろ向きポリゴンがポイントとしてラスタライズされているかどうかを示す定数シンボル:

#include <array> 
#include <fstream> 
#include <iostream> 
#include <sstream> 
#include <string> 
#include <GL/glew.h> 
#include <GLFW/glfw3.h> 

// Vertex and fragment shader source files. 
constexpr char VERTEX_SHADER_SOURCE_FILE[] = "simple_vertex.shader"; 
constexpr char FRAGMENT_SHADER_SOURCE_FILE[] = "simple_fragment.shader"; 

// Window properties. 
constexpr int WINDOW_WIDTH = 800; 
constexpr int WINDOW_HEIGHT = 800; 
constexpr char WINDOW_TITLE[] = "Triangle"; 

// Background colour. 
constexpr std::array<GLfloat, 4> bgColour { 0.3f, 0.1f, 0.3f, 1.0f }; 

/* 
* Instructs GLFW to close window if escape key is pressed and to toggle between rasterizing modes 
* if m is pressed. 
*/ 
void keyCallback(GLFWwindow *window, int key, int scancode, int action, int mode); 

int main() { 
    // Initialize GLFW. 
    if (not glfwInit()) { 
     std::cerr << "ERROR: Failed to start GLFW.\n"; 
     return 1; 
    } 

    // Set required OpenGL version. 
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); 
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); 
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); 

    // Create a window object and bind it to the current context. 
    GLFWwindow *window = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_TITLE, nullptr, 
              nullptr); 
    if (not window) { 
     std::cerr << "ERROR: Failed to create GLFW window.\n"; 
     glfwTerminate(); 
     return 1; 
    } 
    glfwMakeContextCurrent(window); 

    // Set callback functions. 
    glfwSetKeyCallback(window, keyCallback); 

    // Initialize GLEW with experimental features enabled. 
    glewExperimental = GL_TRUE; 
    if (glewInit() != GLEW_OK) { 
     std::cerr << "ERROR: Failed to start GLEW.\n"; 
     glfwTerminate(); 
     return 1; 
    } 

    // Display information on the current GL connection. 
    std::cout << "Renderer: " << glGetString(GL_RENDERER) << std::endl; 
    std::cout << "Version: " << glGetString(GL_VERSION) << std::endl; 
    std::cout << "Shading Language: " << glGetString(GL_SHADING_LANGUAGE_VERSION) << std::endl; 

    // Define the viewport dimensions. 
    int width, height; 
    glfwGetFramebufferSize(window, &width, &height); 
    glViewport(0, 0, static_cast<GLsizei>(width), static_cast<GLsizei>(height)); 

    // Create a vertex shader object. 
    GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER); 

    // Load the vertex shader source code. 
    std::string vertexShaderSource; 
    std::ifstream vsfs(VERTEX_SHADER_SOURCE_FILE); 
    if (vsfs.is_open()) { 
     std::stringstream ss; 
     ss << vsfs.rdbuf(); 
     vertexShaderSource = ss.str(); 
    } 
    else { 
     std::cerr << "ERROR: File " << VERTEX_SHADER_SOURCE_FILE << " could not be found.\n"; 
     glfwTerminate(); 
     return 1; 
    } 

    // Attach the shader source code to the vertex shader object and compile. 
    const char *vertexShaderSource_cstr = vertexShaderSource.c_str(); 
    glShaderSource(vertexShader, 1, &vertexShaderSource_cstr, nullptr); 
    glCompileShader(vertexShader); 

    // Check if compilation was successful. 
    GLint success; 
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success); 
    if (not success) { 
     std::cerr << "ERROR: Vertex shader compilation failed.\n"; 
     glfwTerminate(); 
     return 1; 
    } 

    // Create a fragment shader object. 
    GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); 

    // Load the fragment shader source code. 
    std::string fragmentShaderSource; 
    std::ifstream fsfs(FRAGMENT_SHADER_SOURCE_FILE); 
    if (fsfs.is_open()) { 
     std::stringstream ss; 
     ss << fsfs.rdbuf(); 
     fragmentShaderSource = ss.str(); 
    } 
    else { 
     std::cerr << "ERROR: File " << FRAGMENT_SHADER_SOURCE_FILE << " could not be found.\n"; 
     glfwTerminate(); 
     return 1; 
    } 

    // Attach the shader source code to the fragment shader object and compile. 
    const char *fragmentShaderSource_cstr = fragmentShaderSource.c_str(); 
    glShaderSource(fragmentShader, 1, &fragmentShaderSource_cstr, nullptr); 
    glCompileShader(fragmentShader); 

    // Check if compilation was successful. 
    glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success); 
    if (not success) { 
     std::cerr << "ERROR: Fragment shader compilation failed.\n"; 
     glfwTerminate(); 
     return 1; 
    } 

    // Link the vertex and fragment shaders into a shader program. 
    GLuint shaderProgram = glCreateProgram(); 
    glAttachShader(shaderProgram, vertexShader); 
    glAttachShader(shaderProgram, fragmentShader); 
    glLinkProgram(shaderProgram); 

    // Check that shader program was successfully linked. 
    glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success); 
    if (not success) { 
     std::cerr << "ERROR: Shader program linking failed.\n"; 
     glfwTerminate(); 
     return 1; 
    } 

    // Delete shader objects. 
    glDeleteShader(vertexShader); 
    glDeleteShader(fragmentShader); 

    // Coordinates of square's vertices. 
    std::array<GLfloat, 12> vertices { 
     0.5f, 0.5f, 0.0f, 
     0.5f, -0.5f, 0.0f, 
     -0.5f, -0.5f, 0.0f, 
     -0.5f, 0.5f, 0.0f 
    }; 

    // Indices to draw. 
    std::array<GLuint, 6> indices { 
     0, 1, 3, 
     1, 2, 3 
    }; 

    // Create a vertex array object. 
    GLuint vao; 
    glGenVertexArrays(1, &vao); 
    glBindVertexArray(vao); 

    // Create a vertex buffer object. 
    GLuint vbo; 
    glGenBuffers(1, &vbo); 
    glBindBuffer(GL_ARRAY_BUFFER, vbo); 

    // Create an element buffer object. 
    GLuint ebo; 
    glGenBuffers(1, &ebo); 
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo); 

    // Pass vertex data into currently bound vertex buffer object. 
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices.data(), GL_STATIC_DRAW); 

    // Pass index data into currently bound element buffer object. 
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices.data(), GL_STATIC_DRAW); 

    // Create and enable a vertex attribute. 
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), static_cast<GLvoid*>(0)); 
    glEnableVertexAttribArray(0); 

    // It is good practice to unbind the vertex array object, vertex buffer object, and element 
    // buffer object. 
    glBindBuffer(GL_ARRAY_BUFFER, 0); 
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 
    glBindVertexArray(0); 

    // Set background colour. 
    glClearColor(bgColour[0], bgColour[1], bgColour[2], bgColour[3]); 

    // Main loop. 
    while (not glfwWindowShouldClose(window)) { 
     // Clear the screen of colours and poll for events. 
     glClear(GL_COLOR_BUFFER_BIT); 
     glfwPollEvents(); 

     // Inform OpenGL to use the shader program created above. 
     glUseProgram(shaderProgram); 

     // Bind the vertex array object and element buffer object. 
     glBindVertexArray(vao); 
     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo); 

     // Draw the triangle using glDrawElements. The first argument gives the OpenGL primitive to 
     // render, the second argument gives the number of vertices to draw, the third gives type 
     // used to represent an index, and finally the last argument gives a possible offset in the 
     // EBO. 
     glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, static_cast<GLvoid*>(0)); 

     // Unbind the vertex array object (good practice). 
     glBindVertexArray(0); 

     // Swap buffers. 
     glfwSwapBuffers(window); 
    } 

    // Clean up. 
    glDeleteVertexArrays(1, &vao); 
    glDeleteBuffers(1, &vbo); 
    glDeleteProgram(shaderProgram); 
    glfwDestroyWindow(window); 
    glfwTerminate(); 
    return 0; 
} 

void keyCallback(GLFWwindow *window, int key, int scancode, int action, int mode) { 
    if (key == GLFW_KEY_ESCAPE and action == GLFW_PRESS) { 
     glfwSetWindowShouldClose(window, GL_TRUE); 
    } 
    if (key == GLFW_KEY_M and action == GLFW_PRESS) { 
     // Find the rasterizing mode. 
     GLint rastMode; 
     glGetIntegerv(GL_POLYGON_MODE, &rastMode); 

     // Switch modes depending on current rasterizing mode. 
     if (rastMode == GL_FILL) { 
      glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
     } 
     else { 
      glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); 
     } 
    } 
} 
+3

ドキュメンテーションはこれを言っていませんが。より大きなメモリ位置へのポインタを渡すことをお勧めします.GLint [2]はGL_FRONTに1つ、GL_BACKには1つと言います。 – mrVoid

+0

ドキュメンテーション*は次のように言っています: "* params *は、正面ポリゴンと後ろ向きポリゴンを点、線、または塗りつぶしポリゴンとしてラスタライズするかどうかを示す記号定数の2つの値を返します。 – Wyzard

+0

@mrVoidあなたの提案はうまくいった。あなたが答えとしてそれを書くなら、私はそれを受け入れるでしょう。 –

答えて

2

ドキュメントがそれを言う:

のparamsは、2つの値を返す

はここで完全なコードです線または塗りつぶしポリゴン

@Wyzardと私のコメント:glGetIntegerv(GL_POLYGON_MODE, &rastMode);には2つの整数のメモリが必要です。セグメンテーションは過去の書き込みによるものでした。rastMode int

解決策は、2つの整数のバッファを渡すことです。

関連する問題