No se pueden crear sombreadores OpenGL 4.x

Estoy utilizando este tutorial. Tengo el hardware correcto para ejecutar esto (AMD 6870). He seguido el tutorial, pero solo aparece un parpadeo de la ventana antes de que se cierre. Cuando construyo el código, funciona bien, pero enumera una gran cantidad de archivos DLL que no pueden encontrar un PDB. Revisé mi código (estoy usando Visual Studio 2010 prof) y salí de mi función CreateShaders con el error de que no se pudieron crear. Revisé el tutorial sobre esa función y lo tengo copiado.

Aquí está el código:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <GL/glew.h>
#include <GL/freeglut.h>
#define WINDOW_TITLE_PREFIX "Chapter Two - A Triangle"

    //Global variable dclerations
 int CurrentWidth  = 800;
int CurrentHeight = 600;
int WindowHandle  = 0;

unsigned FrameCount = 0;

GLuint 
vertexShaderId,
fragmentShaderId,
programId,
vaoId,
vboId,
colorBufferId;


//contents of GLSL vertexshader
const GLchar* vertexShader =
{
"version 400\n"\
"layout(location=0) in vec4 in_Position;\n"\
"layout(location=1) in vec4 in_Color;\n"\
"out vec4 ex_Color;\n"\

"void main(void)\n"\
"{\n"\
"   gl_Position = in_Position;\n"\
"   ex_Color = in_Color;\n"\
"}\n"

};

 //contents of fragment shader

 const GLchar* fragmentShader =
{
"#version 400\n"\

"in vec4 ex_Color;\n"\
"out vec4 out_Color;\n"\

"void main(void)\n"\
"{\n"\
"   out_Color = ex_Color;\n"\
"}\n"
 };

//prototypes
 void Initialize(int,char*[]);
void InitWindow(int, char*[]);
void ResizeFunction(int, int);
void RenderFunction(void);
void TimerFunction(int);
void IdleFunction(void);
void CleanUp(void);
void CreateVBO(void);
void DestroyVBO(void);
void CreateShaders(void);
void DestroyShaders(void);


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

glutMainLoop();

exit(EXIT_SUCCESS);
}


void Initialize(int argc, char* argv[])
{
GLenum GlewInitResult;

InitWindow(argc, argv);

//glew is initialised after the openGL context is created,
//it needs an active context to implement calls
GlewInitResult = glewInit();

//if glew did not init correctly, print errors
if(GLEW_OK != GlewInitResult)
{
    fprintf(
        stderr,
        "ERROR: %s\n",
        glewGetErrorString(GlewInitResult)
        );
    exit(EXIT_FAILURE);
}

fprintf(
    stdout,
    "INFO: OpenGL Version: %s\n",
    glGetString(GL_VERSION));

CreateShaders();
CreateVBO();
glClearColor(0.0f, 0.0f, 0.0f,0.0f);

}

//uses freeglut to create a window
void InitWindow(int argc, char* argv[]) 
{
//initialises freeglut library
glutInit(&argc, argv);

//creates a forward compatible OpenGL 4.0 core profile
glutInitContextVersion(4,0);
glutInitContextFlags(GLUT_FORWARD_COMPATIBLE);
glutInitContextProfile(GLUT_CORE_PROFILE);

//when window closes, return to main loop
glutSetOption(
    GLUT_ACTION_ON_WINDOW_CLOSE,
    GLUT_ACTION_GLUTMAINLOOP_RETURNS
    );

glutInitWindowSize(CurrentWidth,CurrentHeight);

// enables depth buffer, double buffering, makes RGBA mode
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);

//makes window, passes it the value of defined window
WindowHandle = glutCreateWindow(WINDOW_TITLE_PREFIX);

if(WindowHandle < 1)
{
    fprintf(
        stderr,
        "ERROR: Could not create a new rendering window.\n"
        );
    exit(EXIT_FAILURE);
}

//called when window is resized
glutReshapeFunc(ResizeFunction);
//called when scene is to be drawn on screen
glutDisplayFunc(RenderFunction);
glutIdleFunc(IdleFunction);
//(ms passed before func is called, func to call, value to pass)
glutTimerFunc(0,TimerFunction,0);
glutCloseFunc(CleanUp);
}

void ResizeFunction(int Width, int Height)
{
CurrentWidth = Width;
CurrentHeight = Height;
glViewport(0,0,CurrentWidth,CurrentHeight);
}

 void RenderFunction(void)
{
FrameCount++;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDrawArrays(GL_TRIANGLES,0,3);
glutSwapBuffers();
glutPostRedisplay();
}

 //redraws as soon as possible
void IdleFunction(void)
{
glutPostRedisplay();
}

void TimerFunction(int Value)
{
if(0 != Value)
{
    char* TempString = (char*)
        malloc(512 + strlen(WINDOW_TITLE_PREFIX));

    sprintf(
        TempString,
        "%s: %d Frames Per Second @ %d x %d",
        WINDOW_TITLE_PREFIX,
        //update every quarter of a second
        FrameCount * 4,
        CurrentWidth,
        CurrentHeight
        );

    glutSetWindowTitle(TempString);
    free(TempString);
}

FrameCount = 0;
glutTimerFunc(250, TimerFunction,1);
}


void CleanUp (void)
{
DestroyShaders();
DestroyVBO();
}

void CreateVBO(void)
{
GLfloat vertices[] = {
    -0.8f, -0.8f, 0.0f, 1.0f,
    0.0f,   0.8f, 0.0f, 1.0f,
    0.8f,   -0.8f, 0.0f, 1.0f
};

GLfloat colors[] = {
    1.0f, 0.0f, 0.0f, 1.0f,
    0.0f, 1.0f, 0.0f, 1.0f,
    0.0f, 0.0f, 1.0f, 1.0f
};

GLenum ErrorCheckValue = glGetError();

glGenVertexArrays(1, &vaoId);
glBindVertexArray(vaoId);

glGenBuffers(1, &vboId);
glBindBuffer(GL_ARRAY_BUFFER, vboId);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0,4,GL_FLOAT,GL_FALSE,0,0);
glEnableVertexAttribArray(0);

glGenBuffers(1, &colorBufferId);
glBindBuffer(GL_ARRAY_BUFFER, colorBufferId);
glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);
glVertexAttribPointer(0,4,GL_FLOAT,GL_FALSE,0,0);
glEnableVertexAttribArray(1);

ErrorCheckValue = glGetError();
if (ErrorCheckValue != GL_NO_ERROR)
{
    fprintf(
        stderr,
        "ERROR: Could not create a VBO: %s \n",
        gluErrorString(ErrorCheckValue)
        );

    exit(-1);
}


 }

 void DestroyVBO(void)
 {
GLenum ErrorCheckValue = glGetError();

glDisableVertexAttribArray(1);
glDisableVertexAttribArray(0);

glBindBuffer(GL_ARRAY_BUFFER,0);

glDeleteBuffers(1, &colorBufferId);
glDeleteBuffers(1, &vboId);

glBindVertexArray(0);
glDeleteVertexArrays(1, &vaoId);

ErrorCheckValue = glGetError();
if(ErrorCheckValue != GL_NO_ERROR)
{
    fprintf(
        stderr,
        "ERROR: Could not Destroy the VBO: %s \n",
        gluErrorString(ErrorCheckValue)
        );
    exit(-1);
}
}

void CreateShaders(void)
{
GLenum ErrorCheckValue = glGetError();

vertexShaderId =glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShaderId, 1, &vertexShader, NULL);
glCompileShader(vertexShaderId);

fragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShaderId, 1, &fragmentShader, NULL);
glCompileShader(fragmentShaderId);

programId = glCreateProgram();
    glAttachShader(programId, vertexShaderId);
    glAttachShader(programId,fragmentShaderId);
glLinkProgram(programId);
glUseProgram(programId);

ErrorCheckValue = glGetError();
if(ErrorCheckValue != GL_NO_ERROR)
{
    fprintf(
        stderr,
        "ERROR: Could not create the shaders: %s \n",
        gluErrorString(ErrorCheckValue)
        );

    exit(-1);
}
 }

 void DestroyShaders(void)
{
GLenum ErrorCheckValue = glGetError();

glUseProgram(0);

glDetachShader(programId,vertexShaderId);
glDetachShader(programId,fragmentShaderId);


glDeleteShader(fragmentShaderId);
glDeleteShader(vertexShaderId);

glDeleteProgram(programId);


ErrorCheckValue = glGetError();
if(ErrorCheckValue != GL_NO_ERROR)
{
    fprintf(
        stderr,
        "Error: Could not destroy the shaders %s\n",
        gluErrorString(ErrorCheckValue)
        );
    exit(-1);
}

}

preguntado el 12 de junio de 12 a las 20:06

Ese tutorial no debe usarse, aunque solo sea por el hecho de que no realiza ninguna verificación de errores de compilación de sombreadores. -

Está bien. Gracias :). ¿Por qué es algo malo cuando incluye la comprobación de errores? ¿Se trata de ser mejor usar o es una mala práctica de programación usar este último u otras razones? ¿Hay otros tutoriales que recomendarías? He mirado aquí para preguntas similares. A menudo, los tutoriales presentados incluyen el uso de premake o cmake y realmente solo quiero ponerme nervioso y centrarme en un enfoque moderno de OpenGL en este momento. -

"¿Por qué es algo malo cuando incluye la verificación de errores?" Eso no se incluiyendo comprobación de errores; por eso es malo. La falla de compilación de Shader no da errores que sean detectables con glGetError. El hecho de que el creador de ese tutorial aparentemente no se haya dado cuenta de eso es un problema grave, lo que sugiere que la persona no conoce OpenGL tan bien como cree. -

"Realmente solo quiero ponerme nervioso y concentrarme en un enfoque OpenGL moderno en este momento". La programación de gráficos no es un tema apropiado para un programador principiante. Debe sentirse razonablemente cómodo con C ++ en general antes de comenzar a trabajar en esta dirección. Y si no se siente lo suficientemente cómodo para usar un sistema de compilación, entonces ningún tutorial de gráficos realmente lo ayudará. -

Está bien. Gracias nuevamente por su respuesta. Tengo algo de experiencia con c++ pero no demasiado. Es por eso que también estoy aprendiendo eso al margen. Desafortunadamente, no tengo tiempo, ya que este es un trabajo de preparación para mi proyecto final en la universidad en septiembre. :D -

1 Respuestas

Lo de DLL/PDB es normal, no creo que tenga ningún efecto en su código (creo que implica cargar información de depuración de DLL, que no es necesario).

Los sombreadores tienen su propio mecanismo de informe de errores que está fuera de glGetError, debe agregarlo a su código.

Después de compilar cada sombreador individual, desea llamar:

glGetShaderiv con opcion GL_COMPILE_STATUS (esto devuelve verdadero/falso si la compilación fue exitosa).

Si la compilación falló, puede obtener el mensaje de error con glGetShaderInfoLog.

Luego, después de vincular el programa, desea llamar glGetProgramiv para obtener GL_LINK_STATUS, y vuelve a aparecer el mensaje de error con glGetProgramInfoLog.

Respondido el 12 de junio de 12 a las 20:06

Gracias por tu contribución. Voy a ser capaz de probar esto cuando llegue a casa esta noche. Perdóname si esto parece obvio, pero en realidad no tengo tanta experiencia con esto. Cuando dice llamar a glGetShaderiv después de cada sombreador individual, ¿eso significa que debería llamarlo después de compilar vertexshaderid y después de fragmentshaderid? Además, ¿qué quieres decir con después de vincular el programa? ¿Quieres decir justo después de mi incluye? De nuevo, gracias por tu ayuda :) - Ryan R Dizzle Graham

Sí, verifica los errores para cada sombreador (vértice y fragmento) individualmente después glCompileShader. Cuando digo "después de vincular el programa", me refiero al siguiente paso después de llamar glLinkProgram. (Me refiero al objeto del programa OpenGL, no a todo su programa C++) - Tim

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.