Posted by: Morten Nobel-Jørgensen | June 25, 2012

OpenGL 3.2 / GLSL 1.50 – A simple example using Visual Studio 2010, FreeGlut and GLEW


Creating a simple “hello world”-like example using OpenGL 3.2 using Core Profile can be surprisingly complicated. I’ll here show my simple example. The C++ example is based on the Cocoa-GL-Tutorial for OS/X.
The example includes a Visual Studio 2010 solution and project, but requires that FreeGlut and GLEW has been installed on properly. The application uses a few simple helper-files from the book “Interactive Computer Graphics – A Top-Down Approach with OpenGL” by Edward Angel and Dave Shreiner (Sixth Edition, Addison-Wesley 2012) (Amazon link) (Book website).

Download
Download the full project on GitHub: https://github.com/mortennobel/OpenGL_3.2_VS_2010_freeglut

Vertex shader
The vertex shader has no matrix transformations, but instead translates the quad using a simple offset-vector (the uniform p).

#version 150

uniform vec2 p;

in vec4 position;
in vec4 colour;

out vec4 colourV;

void main (void)
{
    colourV = colour;
    gl_Position = vec4(p, 0.0, 0.0) + position;
}

Fragment shader
A very simple fragment shader that colors the the pixel to a constant color (using Gouraud shading).

#version 150

in vec4 colourV;
out vec4 fragColour;

void main(void)
{
    fragColour = colourV;
}

main.cpp
[Click below to expand the source code].

#include
#include
#include <GL/glew.h>
#include <GL/freeglut.h>

#include "Angel.h"

using namespace std;
using namespace Angel;

int WINDOW_WIDTH = 800;
int WINDOW_HEIGHT = 800;

GLuint shaderProgram;
GLuint positionUniform;
GLuint colourAttribute, positionAttribute;
GLuint vertexArrayObject,
	vertexBuffer;

typedef struct
{
    vec4 position;
    vec4 colour;
} Vertex;

void loadShader();
void display();

void loadBufferData(){
	 Vertex vertexData[4] = {
        { vec4(-0.5, -0.5, 0.0, 1.0 ), vec4( 1.0, 0.0, 0.0, 1.0 ) },
        { vec4(-0.5,  0.5, 0.0, 1.0 ), vec4( 0.0, 1.0, 0.0, 1.0 ) },
        { vec4( 0.5,  0.5, 0.0, 1.0 ), vec4( 0.0, 0.0, 1.0, 1.0 ) },
        { vec4( 0.5, -0.5, 0.0, 1.0 ), vec4( 1.0, 1.0, 1.0, 1.0 ) }
    };

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

    glGenBuffers(1, &vertexBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, 4 * sizeof(Vertex), vertexData, GL_STATIC_DRAW);

    glEnableVertexAttribArray(positionAttribute);
    glEnableVertexAttribArray(colourAttribute);
    glVertexAttribPointer(positionAttribute, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid *)0);
    glVertexAttribPointer(colourAttribute  , 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid *)sizeof(vec4));
}

void loadShader(){
	shaderProgram = InitShader("beelsebob.vert",  "beelsebob.frag", "fragColour");
	positionUniform = glGetUniformLocation(shaderProgram, "p");
	if (positionUniform < 0) {
		cerr << "Shader did not contain the 'p' uniform."<<endl;
	}
	colourAttribute = glGetAttribLocation(shaderProgram, "colour");
	if (colourAttribute < 0) {
		cerr << "Shader did not contain the 'colour' attribute." << endl;
	}
	positionAttribute = glGetAttribLocation(shaderProgram, "position");
	if (positionAttribute < 0) {
		cerr << "Shader did not contain the 'position' attribute." << endl;
	}
}

void display() {
    glClearColor(0.0, 0.0, 0.0, 1.0);
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

	const float timeScale = 0.008f;

    glUseProgram(shaderProgram);

    GLfloat timeValue = glutGet(GLUT_ELAPSED_TIME)*timeScale;
    vec2 p( 0.5f * sinf(timeValue), 0.5f * cosf(timeValue) );
    glUniform2fv(positionUniform, 1, (const GLfloat *)&p);

    glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

	glutSwapBuffers();
}

void reshape(int W, int H) {
    WINDOW_WIDTH = W;
	WINDOW_HEIGHT = H;
	glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
}

void animate() {
	glutPostRedisplay();
}

void visible(int vis) {
	if (vis == GLUT_VISIBLE)
		glutIdleFunc(animate);
	else
		glutIdleFunc(0);
}

int main(int argc, char* argv[]) {
    glutInit(&argc, argv);
	glutInitContextVersion(3, 2);
    glutInitContextFlags(GLUT_FORWARD_COMPATIBLE);
    glutInitContextProfile(GLUT_CORE_PROFILE);

	glutSetOption(
        GLUT_ACTION_ON_WINDOW_CLOSE,
        GLUT_ACTION_GLUTMAINLOOP_RETURNS
    );

	glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE|GLUT_DEPTH);
	glutCreateWindow("02561");
	glutDisplayFunc(display);
	glutReshapeFunc(reshape);
	glutVisibilityFunc(visible);
	glutIdleFunc(animate);
	glutReshapeWindow(WINDOW_WIDTH, WINDOW_HEIGHT);
	glewExperimental = GL_TRUE;  // Added because of http://openglbook.com/glgenvertexarrays-access-violationsegfault-with-glew/
	GLint GlewInitResult = glewInit();
	if (GlewInitResult != GLEW_OK) {
		printf("ERROR: %s\n", glewGetErrorString(GlewInitResult));
	}

	glEnable(GL_DEPTH_TEST);

	loadShader();
    loadBufferData();

	glutMainLoop();
}

Similar projects:

Advertisements

Responses

  1. Thank you for your post.
    Your codes is very useful for beginning OpenGL3.x/GLSL on Windows.
    I have a comment.

    When I executed your codes at the first time, I got an error on the line:
    [main.cpp – line 40] glGenVertexArrays(1, &vertexArrayObject);

    I found the following solution for this issue, and I hope you to update the codes for others.

    // Add this code before ‘glewInit()’
    glewExperimental = GL_TRUE;


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Categories

%d bloggers like this: