2012-06-12 2 views
0

Я использую this tutorial. У меня есть правильное оборудование для его запуска (AMD 6870). Я следил за учебником, но перед тем, как он выйдет, я вижу только проблесковое окно. Когда я создаю код, он строит отлично, но перечисляет загрузку DLL, которая не может найти PDB. Я прошел через мой код (Im using Visual Studio 2010 prof), и он вышел из моей функции CreateShaders с ошибкой, которую они не могли создать. Я проверил учебник по этой функции, и я его скопировал.Не удается создать шейдеры OpenGL 4.x

Вот код:

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

} 
+1

Это руководство не должно использоваться, если только по той причине, что он не выполняет проверку ошибок компиляции шейдеров. –

+0

Хорошо. Благодаря :). Почему это плохо, когда включает проверку ошибок? Является ли это примером того, как лучше использовать или плохой практикой программирования использовать последние или другие причины. Существуют ли какие-либо другие учебные пособия, которые вы бы рекомендовали? Я посмотрел на подобные вопросы. Часто предлагаемые учебные пособия включают использование pre make или cmake, и я действительно просто хочу свернуть и сосредоточиться на современном подходе OpenGL на данный момент. –

+0

«Почему это плохо, когда оно включает проверку ошибок?» Он * не включает в себя [проверку ошибок;] (http://www.opengl.org/wiki/GLSL#Error_Checking), поэтому это плохо. Ошибка компиляции шейдера не дает ошибок, которые можно обнаружить с помощью 'glGetError'. Тот факт, что создатель этого учебника, по-видимому, не понимал, что это серьезная проблема, которая предполагает, что человек не знает OpenGL, а также считает, что он это делает. –

ответ

0

библиотека DLL/PDB вещь нормальная, я не думаю, что это имеет какое-либо влияние на ваш код (я считаю, что это включает в себя загрузку отладочной информации из библиотеки DLL, которая не является обязательный).

Шейдеры имеют свой механизм отчетности об ошибках, который находится вне glGetError, вы должны добавить его в свой код.

После компиляции каждого отдельного шейдера, вы хотите позвонить:

glGetShaderiv с опцией GL_COMPILE_STATUS (это возвращает истину/ложь, если компиляция прошла успешно).

Если компиляция не удалась, вы можете получить сообщение об ошибке с glGetShaderInfoLog.

Затем, после связывания программы, вы хотите позвонить glGetProgramiv, чтобы получить GL_LINK_STATUS, и снова получите сообщение об ошибке glGetProgramInfoLog.

+0

Спасибо за ваш вклад. Я смогу попробовать это, когда вернусь домой сегодня вечером. Простите меня, если это кажется очевидным, но я не настолько разбираюсь в этом. Когда вы говорите вызов glGetShaderiv после каждого отдельного шейдера, это значит, что я должен назвать это после компиляции vertexshaderid и после fragmentshaderid? Кроме того, что вы имеете в виду после ссылки на программу? Вы имеете в виду сразу после моего включения? Еще раз спасибо за вашу помощь :) –

+0

Да, вы проверяете ошибки для каждого шейдера (вершины и фрагмента) отдельно после 'glCompileShader'. Когда я говорю «после ссылки на программу», я имею в виду следующий шаг после вызова 'glLinkProgram'. (Я имею в виду объект OpenGL, а не всю вашу C++-программу) – Tim