gpt4 book ai didi

c++ - OpenGL:切换多边形模式导致段错误

转载 作者:搜寻专家 更新时间:2023-10-31 01:35:33 25 4
gpt4 key购买 nike

我的电脑使用 Intel 显卡运行 Ubuntu 16.04。我将 Mesa 11.2 用于我的 OpenGL 配置文件。

我简陋的 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 函数中调用该函数(比如,就在游戏循环之外),我的方 block 将拒绝出现(尽管没有段错误)。

完整代码如下:

#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);
}
}
}

最佳答案

文档说:

params returns two values: symbolic constants indicating whether front-facing and back-facing polygons are rasterized as points, lines, or filled polygons

结束@Wyzard 和我的评论:glGetIntegerv(GL_POLYGON_MODE, &rastMode); 需要两个整数的内存来写入。段错误是由于写入过去的 rastMode int

解决方案是传递两个整数的缓冲区。

关于c++ - OpenGL:切换多边形模式导致段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37115829/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com