Render a Torus Using a Flat Shader Program

Notes:

This merges the previous tutorial with the OGLSB5 flat shader tutorial and includes the tools the book uses.

Makefile:

NAME = FlatShader
SRCPATH = ./
SHAREDPATH = ../GLTools/src/
SHAREDINCPATH = ../GLTools/include/
LIBDIRS = -L/usr/local/lib
INCDIRS = -I/usr/include -I/usr/local/include -I/usr/include/GL -I$(SHAREDINCPATH) -I$(SHAREDINCPATH)GL

CC = g++
CFLAGS = -g $(INCDIRS)
LIBS = -lGL -lGLU -lSDL2main -lSDL2 -lGLEW -lm

all: 
	$(CC) $(CFLAGS) $(LIBS) $(SRCPATH)$(NAME).cpp $(SHAREDPATH)GLTools.cpp $(SHAREDPATH)GLBatch.cpp $(SHAREDPATH)GLTriangleBatch.cpp $(SHAREDPATH)GLShaderManager.cpp $(SHAREDPATH)math3d.cpp -o $(NAME)

Vertex Shader:

#version 330 core
// Transformation matrix
uniform mat4 mvpMatrix;
// Incoming per vertex
in vec4 vVertex;
void main()
{
 // This is all we need to transform the geometry
   gl_Position = mvpMatrix * vVertex;
}

Fragment Shader:

#version 330 core
out vec4 FragColor;
uniform vec4 vColorValue; // we set this veriable in the OpenGL code.
void main()
{
   FragColor = vColorValue;
}

Source:

// FlatShader.cpp
//
// Attempting to reimplement the GLtools and other OGLSB5 libraries into the 
// tutorial code.

#include <GLTools.h>	// OpenGL toolkit
#include <GLMatrixStack.h>
#include <GLFrame.h>
#include <GLFrustum.h>
#include <GLGeometryTransform.h>
#include <math.h>

#include <stdio.h>
#include <GL/glew.h>    // glew likes to be before other GL stuff
#include <SDL2/SDL.h>
#include <SDL2/SDL_opengl.h>
#include <GL/glu.h>

// OGLSB5 variables
GLFrame                 viewFrame;
GLFrustum               viewFrustum;
GLTriangleBatch         torusBatch;
GLMatrixStack           modelViewMatrix;
GLMatrixStack           projectionMatrix;
GLGeometryTransform     transformPipeline;

GLuint                  flatShader; // The flat shader

GLint                   locMVP;     // The location of the model view projection matrix uniform
GLint                   locColor;   // The location of the color value uniform

//Screen dimension constants
const int SCREEN_WIDTH = 480;
const int SCREEN_HEIGHT = 480;

//Starts up SDL, creates window, and initializes OpenGL
bool init();

//Initializes rendering program and clear color
bool initGL();

//Input handler
int handleKeys(unsigned char key, int x, int y);

//Per frame update
void update();

//Renders quad to the screen
void render(GLfloat green);

//Frees media and shuts down SDL
void close();

//The window we'll be rendering to
SDL_Window* gWindow = NULL;

//OpenGL context
SDL_GLContext gContext;

bool init()
{
	//Initialization flag
	bool success = true;

	//Initialize SDL
	if (SDL_Init(SDL_INIT_VIDEO) < 0)
	{
		printf("SDL could not initialize! SDL Error: %s\n", SDL_GetError());
		success = false;
	}
	else
	{
		//Use OpenGL 3.3 core
		SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
		SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
		SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);

		//Create window
		gWindow = SDL_CreateWindow("SDL2 OpenGL", 
                                    SDL_WINDOWPOS_UNDEFINED, 
                                    SDL_WINDOWPOS_UNDEFINED, 
                                    SCREEN_WIDTH, 
                                    SCREEN_HEIGHT, 
                                    SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);
		if(gWindow == NULL)
		{
			printf("Window could not be created! SDL Error: %s\n", SDL_GetError());
			success = false;
		}
		else
		{
			//Create context
			gContext = SDL_GL_CreateContext(gWindow);
			if(gContext == NULL)
			{
				printf("OpenGL context could not be created! SDL Error: %s\n", SDL_GetError());
				success = false;
			}
			else
			{
				//Initialize GLEW
				glewExperimental = GL_TRUE; 
				GLenum glewError = glewInit();
				if(glewError != GLEW_OK)
				{
					printf("Error initializing GLEW! %s\n", glewGetErrorString(glewError));
				}

				//Use Vsync
				if(SDL_GL_SetSwapInterval(1) < 0)
				{
					printf("Warning: Unable to set VSync! SDL Error: %s\n", SDL_GetError());
				}

				//Initialize OpenGL
				if(!initGL())
				{
					printf("Unable to initialize OpenGL!\n");
					success = false;
				}
			}
		}
	}

	return success;
}

bool initGL()
{
	//Success flag
	bool success = true;

    //Initialize clear color
    glClearColor(0.7f, 0.7f, 0.7f, 1.0f);

    // Enable depth testing
    glEnable(GL_DEPTH_TEST);
    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    
    // set the object forward 
    viewFrame.MoveForward(4.0f);

    // Make the Torus
    gltMakeTorus(torusBatch, 0.8f, 0.25f, 52, 26);

	//Generate program
    flatShader = gltLoadShaderPairWithAttributes("glsl.vs", "glsl.fs", 1, GLT_ATTRIBUTE_VERTEX, "vVertex");

    locMVP = glGetUniformLocation(flatShader, "mvpMatrix");
    locColor = glGetUniformLocation(flatShader, "vColorValue");

    viewFrustum.SetPerspective(35.0f, float(SCREEN_WIDTH) / float(SCREEN_HEIGHT), 1.0f, 100.0f);
    projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
    transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);

	return success;
}

int handleKeys(unsigned char key, int x, int y)
{
	//Toggle triangle
	if(key == 'q')
	{
        return 1;
	}
    
    return 0;
}

void update()
{
	//No per frame update needed
}

void render(GLfloat green)
{
	//Clear color buffer
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // Prepare or matrices
    modelViewMatrix.PushMatrix(viewFrame);
    modelViewMatrix.Rotate(SDL_GetTicks() * 0.2f, 0.0f, 1.0f, 0.0f); // modified for SDL

    // our color
    GLfloat vColor[] = { 0.1f, green, 0.1f, 1.0f};
	
    //Bind program
    glUseProgram(flatShader);

    // get color location for the shader
    glUniform4fv(locColor, 1, vColor);

    // get our matrix for the shader
    glUniformMatrix4fv(locMVP, 1, GL_FALSE, transformPipeline.GetModelViewProjectionMatrix());

    //Render
    torusBatch.Draw();

    modelViewMatrix.PopMatrix();
}

void close()
{
	//Deallocate program
	glDeleteProgram(flatShader);

	//Destroy window	
	SDL_DestroyWindow(gWindow);
	gWindow = NULL;

	//Quit SDL subsystems
	SDL_Quit();
}

int main(int argc, char* args[])
{
	//Start up SDL and create window
	if(!init())
	{
		printf("Failed to initialize!\n");
	}
	else
	{
		//Main loop flag
		bool quit = false;

        // Time variables
        unsigned int lastTime = 0, currentTime = 0;

		//Event handler
		SDL_Event e;
		
		//Enable text input
		SDL_StartTextInput();

        // our green color
        float green = 0.0;
        // is the color getting brighter or darker
        bool brighter = true;

		//While application is running
		while(!quit)
		{
            // Time handling
            currentTime = SDL_GetTicks();
            // increment time every 20 milliseconds
            if (currentTime > lastTime + 20)
            {
                lastTime = currentTime;
                // is the color getting brighter?
                if (brighter)
                {
                    green += 0.02f;
                    // reverse brightness if green reached 1.0
                    if (green > 1.0)
                    {
                        brighter = false;
                    }
                }
                else
                {
                    green -= 0.02f;
                    // reverse brightness if green reached 0.0
                    if (green < 0.0)
                    {
                        brighter = true;;
                    }
                }

            }

			//Handle events on queue
			while(SDL_PollEvent(&e) != 0)
			{
				//User requests quit
				if(e.type == SDL_QUIT)
				{
					quit = true;
				}
				//Handle keypress with current mouse position
				else if(e.type == SDL_TEXTINPUT)
				{
					int x = 0, y = 0;
					SDL_GetMouseState(&x, &y);
					if (handleKeys(e.text.text[0], x, y))
                    {
                        quit = true;
                    }
				}
			}

			//Render quad
			render(green);
			
			//Update screen
			SDL_GL_SwapWindow(gWindow);
		}
		
		//Disable text input
		SDL_StopTextInput();
	}

	//Free resources and close SDL
	close();

	return 0;
}

Answer:


Back to index