Lit Texture

Notes:

Convert the phoing lighting to have a textured surface.

Vertex Shader:

#version 330 core
 
// Incoming per vertex... position and normal
in vec4 vVertex;
in vec3 vNormal;
in vec4 vTexture0;

uniform mat4	mvpMatrix;
uniform mat4	mvMatrix;
uniform mat3	normalMatrix;
uniform vec3	vLightPosition;

// Color to fragment program
smooth out vec3 vVaryingNormal;
smooth out vec3 vVaryingLightDir;
smooth out vec2 vTexCoords;

void main(void) 
{ 
    // Get the surface normal in eye coordinates
    vVaryingNormal = normalMatrix * vNormal;

    // Get vertex position in eye coordinates
    vec4 vPosition4 = mvMatrix * vVertex;
    vec3 vPosition3 = vPosition4.xyz / vPosition4.w;

    // Get vector to light source
    vVaryingLightDir = normalize(vLightPosition - vPosition3);

    // Pass along the texture coordinates
    vTexCoords = vTexture0.st;

    // Transform the geometry
    gl_Position = mvpMatrix * vVertex;
}

Fragment Shader:

#version 330 core

out vec4 vFragColor;

uniform vec4 ambientColor;
uniform vec4 diffuseColor;
uniform vec4 specularColor;
uniform sampler2D colorMap;

smooth in vec3 vVaryingNormal;
smooth in vec3 vVaryingLightDir;
smooth in vec2 vTexCoords;

void main(void)
{ 
    // Dot product gives us diffuse lighting
    float diff = max(0.0, dot(normalize(vVaryingNormal), normalize(vVaryingLightDir)));

    // Multiply intensity by diffuse color, force alpha to 1
    vFragColor = diff * diffuseColor;

    // Add in ambient light
    vFragColor += ambientColor;

    // Modulate in the texture
    vFragColor *= texture(colorMap, vTexCoords);

    // Specular light
    vec3 vReflection = normalize(reflect(-normalize(vVaryingLightDir), normalize(vVaryingNormal)));
    float spec = max(0.0, dot(normalize(vVaryingNormal), vReflection));

    // if diffuse light is zero, don't even bother with the pow function
    if (diff != 0)
    {
        float fSpec = pow(spec, 128.0);
        vFragColor.rgb += vec3(fSpec, fSpec, fSpec);
    }
}

Source:

// LitTexture.cpp
//
// Convert the phong shader program to have a texture

#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;
GLShaderManager         shaderManager;

GLuint                  ADSTextureShader;   // Lit texture
GLint                   locAmbient;     // Ambient light location
GLint                   locDiffuse;     // Diffuse light location
GLint                   locSpecular;    // Specular light location
GLint                   locLight;       // The location of the light in eye coordinates
GLint                   locMVP;
GLint                   locMV;
GLint                   locNM;
GLint                   locTexture;
GLuint                  texture;

//Screen dimension constants
const int SCREEN_WIDTH = 256;
const int SCREEN_HEIGHT = 256;
//const int SCREEN_WIDTH = 640;
//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 the screen
void render();

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

bool LoadTGATexture(const char *szFileName, GLenum minFilter, GLenum magFilter, GLenum wrapMode)
{
    GLbyte *pBits;
    int nWidth, nHeight, nComponents;
    GLenum eFormat;

    // Read the texture bits
    pBits = gltReadTGABits(szFileName, &nWidth, &nHeight, &nComponents, &eFormat);
    if (pBits == NULL)
    {
        return false;
    }
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapMode);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapMode);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);

    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    glTexImage2D(GL_TEXTURE_2D, 0, nComponents, nWidth, nHeight, 0, eFormat, GL_UNSIGNED_BYTE, pBits);

    free(pBits);

    if (minFilter == GL_LINEAR_MIPMAP_LINEAR ||
        minFilter == GL_LINEAR_MIPMAP_NEAREST ||
        minFilter == GL_NEAREST_MIPMAP_NEAREST ||
        minFilter == GL_NEAREST_MIPMAP_LINEAR)
    {
        glGenerateMipmap(GL_TEXTURE_2D);
    }

    return true;
}


//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("Lit Texture", 
                                    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 (background)
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

    // Enable depth testing
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_CULL_FACE);

    // Initialize the shader manger
    shaderManager.InitializeStockShaders();
    
    // set the object forward 
    viewFrame.MoveForward(4.0f);

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

    //Generate program
    ADSTextureShader = gltLoadShaderPairWithAttributes("glsl.vs", 
                                                       "glsl.fs", 
                                                       3, 
                                                       GLT_ATTRIBUTE_VERTEX, 
                                                       "vFragPos",
                                                       GLT_ATTRIBUTE_NORMAL,
                                                       "vNormal",
                                                       GLT_ATTRIBUTE_TEXTURE0,
                                                       "vTexture0");

    locAmbient      =   glGetUniformLocation(ADSTextureShader, "ambientColor");
    locDiffuse      =   glGetUniformLocation(ADSTextureShader, "diffuseColor");
    locSpecular     =   glGetUniformLocation(ADSTextureShader, "specularColor");
    locLight        =   glGetUniformLocation(ADSTextureShader, "vLightPosition");
    locMVP          =   glGetUniformLocation(ADSTextureShader, "mvpMatrix");
    locMV           =   glGetUniformLocation(ADSTextureShader, "mvMatrix");
    locNM           =   glGetUniformLocation(ADSTextureShader, "normalMatrix");
    locTexture      =   glGetUniformLocation(ADSTextureShader, "colorMap");

    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);
    LoadTGATexture("stone.tga", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR, GL_CLAMP_TO_EDGE);

    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()
{
    //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

    // light position
    GLfloat vEyeLight[] = { -100.0f, 100.0f, 100.0f };

    // our light colors
    GLfloat vAmbientColor[] = { 0.1f, 0.1f, 0.1f, 1.0f };
    GLfloat vDiffuseColor[] = { 0.8f, 0.8f, 0.8f, 1.0f };
    GLfloat vSpecularColor[] = { 1.0f, 1.0f, 1.0f, 1.0f };

    // Bind texture
    glBindTexture(GL_TEXTURE_2D, texture);

    //Bind program
    glUseProgram(ADSTextureShader);

    // send variables to shader
    glUniform4fv(locAmbient, 1, vAmbientColor);
    glUniform4fv(locDiffuse, 1, vDiffuseColor);
    glUniform4fv(locSpecular, 1, vSpecularColor);
    glUniform3fv(locLight, 1, vEyeLight);
    glUniformMatrix4fv(locMVP, 1, GL_FALSE, transformPipeline.GetModelViewProjectionMatrix());
    glUniformMatrix4fv(locMV, 1, GL_FALSE, transformPipeline.GetModelViewMatrix());
    glUniformMatrix3fv(locNM, 1, GL_FALSE, transformPipeline.GetNormalMatrix());
    glUniform1i(locTexture, 0);

    //Render
    torusBatch.Draw();

    modelViewMatrix.PopMatrix();
}

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

	//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();

		//While application is running
		while(!quit)
		{
			//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();
			
			//Update screen
			SDL_GL_SwapWindow(gWindow);
		}
		
		//Disable text input
		SDL_StopTextInput();
	}

	//Free resources and close SDL
	close();

	return 0;
}

Answer:


Back to index