significado - tipos de datos en c++
Error mÃnimo de segmentación de C++ OpenGL (1)
Estoy siguiendo la primera entrega en el tutorial OpenGL moderno de Tom Dalling y cuando descargué su código funcionó perfectamente. Entonces quise crear mi propia versión mínima para ayudarme a entender cómo funcionaba todo.
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <GLM/glm.hpp>
#include <stdexcept>
GLFWwindow* gWindow = NULL;
GLint gProgram = 0;
GLuint gVertexShader = 0;
GLuint gFragmentShader = 0;
GLuint gVAO = 0;
GLuint gVBO = 0;
int main() {
/** Initialise GLFW **/
if (!glfwInit()){
throw std::runtime_error("GLFW not initialised.");
}
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_COMPAT_PROFILE);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
gWindow = glfwCreateWindow(800, 600, "OpenGL 3.2", NULL, NULL);
if(!gWindow) {
throw std::runtime_error("glfwCreateWindow failed.");
}
glfwMakeContextCurrent(gWindow);
/** Initialise GLEW **/
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK) {
throw std::runtime_error("Glew not initialised.");
}
if (!GLEW_VERSION_3_2) {
throw std::runtime_error("OpenGL 3.2 not supported.");
}
/** Set up shaders **/
gVertexShader = glCreateShader(GL_VERTEX_SHADER); //Segmentation fault here
gFragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(gVertexShader, 1, (const GLchar* const*)R"(
#version 150
in vec3 vertexPos
out vec colour;
void main() {
colour = vertexPos;
gl_Position = vec4(vertexPos, 1);
}
)", NULL);
glShaderSource(gFragmentShader, 1, (const GLchar* const*)R"(
#version 150
in vec3 colour;
out vec4 fragColour;
void main() {
fragColour = colour;
}
)", NULL);
glCompileShader(gVertexShader);
glCompileShader(gFragmentShader);
/** Set up program **/
gProgram = glCreateProgram();
glAttachShader(gProgram, gVertexShader);
glAttachShader(gProgram, gFragmentShader);
glLinkProgram(gProgram);
glDetachShader(gProgram, gVertexShader);
glDetachShader(gProgram, gFragmentShader);
glDeleteShader(gVertexShader);
glDeleteShader(gFragmentShader);
/** Set up VAO and VBO **/
float vertexData[] = {
// X, Y, Z
0.2f, 0.2f, 0.0f,
0.8f, 0.2f, 0.0f,
0.5f, 0.8f, 0.0f,
};
glGenVertexArrays(1, &gVAO);
glBindVertexArray(gVAO);
glGenBuffers(1, &gVBO);
glBindBuffer(GL_ARRAY_BUFFER, gVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(GL_FLOAT)*9, vertexData, GL_STATIC_DRAW);
glVertexAttribPointer(glGetAttribLocation(gProgram, "vertexPos"), 3, GL_FLOAT, GL_FALSE, 0, NULL);
/** Main Loop **/
while (!glfwWindowShouldClose(gWindow)) {
glfwPollEvents();
glBindBuffer(GL_ARRAY_BUFFER, gVBO);
glDrawArrays(GL_TRIANGLES, 0, 1);
glfwSwapBuffers(gWindow);
}
return 0;
}
Esto es lo que creé y se construye correctamente. Sin embargo, al ejecutarlo obtengo un error de segmentación al llamar a glCreateShader.
He buscado mucho para encontrar una solución a esto y hasta ahora he encontrado dos razones principales para que esto suceda:
- Una es que glewExperimental debe establecerse en GL_TRUE, sin embargo, nada cambió después de agregar esta línea.
- La segunda razón era que el contexto de OpenGL no se estaba configurando, pero creo que la llamada a glfwMakeContextCurrent cubre este punto.
Desde aquí no tengo ni idea de qué hacer, ¡así que cualquier consejo sería de gran ayuda!
EDIT: ¡Gracias a todos por su ayuda! Eventualmente logré que funcione y cargué el código para pegarlo para futuras referencias.
Solución del problema
Usted programa bloqueos no en la línea que señaló, sino en la primera llamada glShaderSource
. De hecho, pasa un puntero a una cadena como tercer argumento, fundiéndolo en (const GLchar* const*)
. Eso no es lo que glShaderSource
espera. Más bien se espera un puntero a una matriz de punteros a cadenas, cuya longitud (matriz de punteros) se debe pasar como segundo argumento (ver documentación ).
Como solución rápida y sucia para tu código, declaré lo siguiente:
const char *vs_source[] = {
"#version 150/n",
"in vec3 vertexPos/n",
"out vec colour;/n",
"void main() {/n",
" colour = vertexPos;/n",
" gl_Position = vec4(vertexPos, 1);/n",
"}/n"};
const char *fs_source[] = {
"#version 150/n",
"in vec3 colour;/n",
"out vec4 fragColour;/n",
"void main() {/n",
" fragColour = colour;/n",
"}/n"};
y reemplazó las llamadas a glShaderSource
para
glShaderSource(gVertexShader, 7, (const char**)vs_source, NULL);
glShaderSource(gFragmentShader, 6, (const char**)fs_source, NULL);
Ahora el programa funciona bien y muestra una ventana como se esperaba.
Sugerencias
Su código ni siquiera se compiló en mi máquina (utilizo gcc 4.8.3 @ Linux) debido a la
(const GLchar* const*)
de una cadena literal a(const GLchar* const*)
. Intente establecer indicadores más restrictivos en sus opciones de compilación y preste atención a las advertencias del compilador. Además, trata las advertencias como errores.Utilice algún tipo de generador de perfiles de memoria para determinar la ubicación exacta de los bloqueos. Por ejemplo, utilicé Valgrind para localizar el problema.