198 lines
4.8 KiB
C++
198 lines
4.8 KiB
C++
#include <string>
|
|
#include <exception>
|
|
#include <stdexcept>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "gl_test.h"
|
|
#ifdef _WIN32
|
|
#include "wgl_test.h"
|
|
#else
|
|
#include "glx_test.h"
|
|
#endif
|
|
#include <GL/freeglut.h>
|
|
|
|
GLuint positionBufferObject;
|
|
GLuint program;
|
|
GLuint vao;
|
|
|
|
GLuint BuildShader(GLenum eShaderType, const std::string &shaderText)
|
|
{
|
|
GLuint shader = glCreateShader(eShaderType);
|
|
const char *strFileData = shaderText.c_str();
|
|
glShaderSource(shader, 1, &strFileData, NULL);
|
|
|
|
glCompileShader(shader);
|
|
|
|
GLint status;
|
|
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
|
|
if (status == GL_FALSE)
|
|
{
|
|
GLint infoLogLength;
|
|
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);
|
|
|
|
GLchar *strInfoLog = new GLchar[infoLogLength + 1];
|
|
glGetShaderInfoLog(shader, infoLogLength, NULL, strInfoLog);
|
|
|
|
const char *strShaderType = NULL;
|
|
switch(eShaderType)
|
|
{
|
|
case GL_VERTEX_SHADER: strShaderType = "vertex"; break;
|
|
// case GL_GEOMETRY_SHADER: strShaderType = "geometry"; break;
|
|
case GL_FRAGMENT_SHADER: strShaderType = "fragment"; break;
|
|
}
|
|
|
|
fprintf(stderr, "Compile failure in %s shader:\n%s\n", strShaderType, strInfoLog);
|
|
delete[] strInfoLog;
|
|
|
|
throw std::runtime_error("Compile failure in shader.");
|
|
}
|
|
|
|
return shader;
|
|
}
|
|
|
|
|
|
void init()
|
|
{
|
|
glGenVertexArrays(1, &vao);
|
|
glBindVertexArray(vao);
|
|
|
|
const float vertexPositions[] = {
|
|
0.75f, 0.75f, 0.0f, 1.0f,
|
|
0.75f, -0.75f, 0.0f, 1.0f,
|
|
-0.75f, -0.75f, 0.0f, 1.0f,
|
|
};
|
|
|
|
glGenBuffers(1, &positionBufferObject);
|
|
glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject);
|
|
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexPositions), vertexPositions, GL_STATIC_DRAW);
|
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
|
|
const std::string vertexShader(
|
|
"#version 330\n"
|
|
"layout(location = 0) in vec4 position;\n"
|
|
"void main()\n"
|
|
"{\n"
|
|
" gl_Position = position;\n"
|
|
"}\n"
|
|
);
|
|
|
|
const std::string fragmentShader(
|
|
"#version 330\n"
|
|
"out vec4 outputColor;\n"
|
|
"void main()\n"
|
|
"{\n"
|
|
" outputColor = vec4(0.0f, 0.0f, 0.0f, 1.0f);\n"
|
|
"}\n"
|
|
);
|
|
|
|
GLuint vertShader = BuildShader(GL_VERTEX_SHADER, vertexShader);
|
|
GLuint fragShader = BuildShader(GL_FRAGMENT_SHADER, fragmentShader);
|
|
|
|
program = glCreateProgram();
|
|
glAttachShader(program, vertShader);
|
|
glAttachShader(program, fragShader);
|
|
glLinkProgram(program);
|
|
|
|
GLint status;
|
|
glGetProgramiv (program, GL_LINK_STATUS, &status);
|
|
if (status == GL_FALSE)
|
|
{
|
|
GLint infoLogLength;
|
|
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLength);
|
|
|
|
GLchar *strInfoLog = new GLchar[infoLogLength + 1];
|
|
glGetProgramInfoLog(program, infoLogLength, NULL, strInfoLog);
|
|
fprintf(stderr, "Linker failure: %s\n", strInfoLog);
|
|
delete[] strInfoLog;
|
|
|
|
throw std::runtime_error("Shader could not be linked.");
|
|
}
|
|
}
|
|
|
|
//Called to update the display.
|
|
//You should call glutSwapBuffers after all of your rendering to display what you rendered.
|
|
//If you need continuous updates of the screen, call glutPostRedisplay() at the end of the function.
|
|
void display()
|
|
{
|
|
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
|
|
glClear(GL_COLOR_BUFFER_BIT);
|
|
|
|
glUseProgram(program);
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject);
|
|
glEnableVertexAttribArray(0);
|
|
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
|
|
|
|
glDrawArrays(GL_TRIANGLES, 0, 3);
|
|
|
|
glDisableVertexAttribArray(0);
|
|
glUseProgram(0);
|
|
|
|
glutSwapBuffers();
|
|
}
|
|
|
|
//Called whenever the window is resized. The new window size is given, in pixels.
|
|
//This is an opportunity to call glViewport or glScissor to keep up with the change in size.
|
|
void reshape (int w, int h)
|
|
{
|
|
glViewport(0, 0, (GLsizei) w, (GLsizei) h);
|
|
}
|
|
|
|
//Called whenever a key on the keyboard was pressed.
|
|
//The key is given by the ''key'' parameter, which is in ASCII.
|
|
//It's often a good idea to have the escape key (ASCII value 27) call glutLeaveMainLoop() to
|
|
//exit the program.
|
|
void keyboard(unsigned char key, int x, int y)
|
|
{
|
|
switch (key)
|
|
{
|
|
case 27:
|
|
glutLeaveMainLoop();
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
int main(int argc, char** argv)
|
|
{
|
|
glutInit(&argc, argv);
|
|
|
|
int width = 500;
|
|
int height = 500;
|
|
unsigned int displayMode = GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH | GLUT_STENCIL;
|
|
|
|
glutInitDisplayMode(displayMode);
|
|
glutInitContextVersion (3, 3);
|
|
glutInitContextProfile(GLUT_CORE_PROFILE);
|
|
glutInitWindowSize (width, height);
|
|
glutInitWindowPosition (300, 200);
|
|
glutCreateWindow (argv[0]);
|
|
|
|
glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION);
|
|
|
|
int loaded_gl = ogl_LoadFunctions();
|
|
if(!loaded_gl)
|
|
printf("Failed to load OpenGL.\n");
|
|
else
|
|
printf("OpenGL: %i\n", loaded_gl - ogl_LOAD_SUCCEEDED);
|
|
|
|
init();
|
|
|
|
#ifdef _WIN32
|
|
HDC hdc = wglGetCurrentDC();
|
|
int loaded_wgl = wgl_LoadFunctions(hdc);
|
|
if(!loaded_wgl)
|
|
printf("Failed to load WGL.\n");
|
|
else
|
|
printf("WGL: %i\n", loaded_wgl - wgl_LOAD_SUCCEEDED);
|
|
#else
|
|
#endif
|
|
|
|
glutDisplayFunc(display);
|
|
glutReshapeFunc(reshape);
|
|
glutKeyboardFunc(keyboard);
|
|
glutMainLoop();
|
|
return 0;
|
|
}
|