#include <GL/glew.h>
#include "SDL.h"
#include <math.h>
#define start_width 800
#define start_height 600
volatile int done = 0;
volatile bool test = false;
volatile bool blur = false;
int current_time;
int last_time;
int charxvel = 0, charyvel = 0;
float light_pos[4] = { 5.0f, 6.0f, -1.0f , 1.0f };
float light_intensity[4] = { 1.0f, 1.0f, 1.0f , 1.0f };
GLfloat light_modelview_matrix[16];
GLfloat light_projection_matrix[16];
#define tex_count 5
GLuint textures[tex_count];
GLuint fbo[tex_count];
#define tex_size 512
#define blur_coeff 0.25
struct ShaderProgram
{
GLuint vertex;
GLuint fragment;
GLuint program;
} ShadowShader, ShadowRenderShader, BlurShader;
const char *shadow_shader_vertex =
"void main(void)\n"
"{\n"
" gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
"}\n"
;
const char *shadow_shader_fragment =
"void main(void)\n"
"{\n"
" float dx = dFdx(gl_FragCoord.z);\n"
" float dy = dFdy(gl_FragCoord.z);\n"
" gl_FragDepth = gl_FragCoord.z + 0.25*(dx*dx+dy*dy);\n"
" gl_FragDepth = gl_FragCoord.z * gl_FragCoord.z;\n"
"}\n"
;
const char *shadow_render_shader_vertex =
"uniform sampler2D depth_map;\n"
"uniform sampler2D depth_map_square;\n"
"uniform mat4 light_modelview_matrix;\n"
"uniform mat4 light_projection_matrix;\n"
"uniform vec4 light_pos;\n"
"uniform vec4 light_intensity;\n"
"\n"
"varying vec4 dt_color;\n"
"varying vec4 light_coord;\n"
"\n"
"void main(void)\n"
"{\n"
" gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
" dt_color = gl_Color;\n"
" light_coord = light_projection_matrix * light_modelview_matrix * gl_Vertex;\n"
"}\n"
;
const char *shadow_render_shader_fragment =
"uniform sampler2D depth_map;\n"
"uniform sampler2D depth_map_square;\n"
"uniform mat4 light_modelview_matrix;\n"
"uniform mat4 light_projection_matrix;\n"
"uniform vec4 light_pos;\n"
"uniform vec4 light_intensity;\n"
"\n"
"varying vec4 dt_color;\n"
"varying vec4 light_coord;\n"
"\n"
"void main(void)\n"
"{\n"
" light_coord.xyz = light_coord.xyz/light_coord.w;\n"
" light_coord.w = 1.0/light_coord.w;\n"
" light_coord.xyz = (light_coord.xyz + 1.0) / 2.0;\n"
" float depth = texture2D(depth_map, light_coord).r;"
" float depth_square = texture2D(depth_map_square, light_coord).r;"
" vec4 color = dt_color;\n"
" if ((light_coord.x >= 0.0) && (light_coord.x <= 1.0) && (light_coord.y >= 0.0) && (light_coord.y <= 1.0))\n"
" {\n"
" if (light_coord.z > depth)\n"
" {\n"
" float b = depth_square - depth*depth;\n"
" b = max(b,0.00002);\n"
" float p = b / (b + (light_coord.z - depth) * (light_coord.z - depth));\n"
" color.rgb *= p;\n"
" }\n"
" }\n"
//" else\n"
//" {\n"
//" color = vec4(0.5, 0.5, 0.5, 1.0);\n"
//" }\n"
" gl_FragColor = color;\n"
"}\n"
;
const char *blur_shader_vertex =
"void main(void)\n"
"{\n"
" gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
" gl_TexCoord[0] = gl_MultiTexCoord0;\n"
"}\n"
;
const char *blur_shader_fragment =
"uniform vec2 ScaleU;\n"
"uniform sampler2D textureSource;\n"
"\n"
"// Portability prevented us from using a const array of vec2\n"
"// Mac shader compiler don't support it.\n"
"/*\n"
"const vec2 gaussFilter[7] = \n"
"{ \n"
" -3.0, 0.015625,\n"
" -2.0, 0.09375,\n"
" -1.0, 0.234375,\n"
" 0.0, 0.3125,\n"
" 1.0, 0.234375,\n"
" 2.0, 0.09375,\n"
" 3.0, 0.015625\n"
"};\n"
"*/\n"
"\n"
"void main(void)\n"
"{\n"
" vec4 color = vec4(0.0);\n"
" //for( int i = 0; i < 9; i++ )\n"
" //{\n"
" // color += texture2D( textureSource, gl_TexCoord[0].st + vec2( gaussFilter[i].x*ScaleU.x, gaussFilter[i].x*ScaleU.y ) )*gaussFilter[i].y;\n"
" //}\n"
" color += texture2D( textureSource, gl_TexCoord[0].st + vec2( -3.0*ScaleU.x, -3.0*ScaleU.y ) ) * 0.015625;\n"
" color += texture2D( textureSource, gl_TexCoord[0].st + vec2( -2.0*ScaleU.x, -2.0*ScaleU.y ) )*0.09375;\n"
" color += texture2D( textureSource, gl_TexCoord[0].st + vec2( -1.0*ScaleU.x, -1.0*ScaleU.y ) )*0.234375;\n"
" color += texture2D( textureSource, gl_TexCoord[0].st + vec2( 0.0 , 0.0) )*0.3125;\n"
" color += texture2D( textureSource, gl_TexCoord[0].st + vec2( 1.0*ScaleU.x, 1.0*ScaleU.y ) )*0.234375;\n"
" color += texture2D( textureSource, gl_TexCoord[0].st + vec2( 2.0*ScaleU.x, 2.0*ScaleU.y ) )*0.09375;\n"
" color += texture2D( textureSource, gl_TexCoord[0].st + vec2( 3.0*ScaleU.x, -3.0*ScaleU.y ) ) * 0.015625;\n"
"\n"
" gl_FragDepth = color;\n"
"}\n"
;
GLint shader_depth_map;
GLint shader_depth_map_square;
GLint shader_modelview_matrix;
GLint shader_projection_matrix;
GLint shader_light_pos;
GLint shader_light_intensity;
GLint shader_blur_source;
GLint shader_blur_scale;
void loadShader(const char *vertex, const char *fragment, struct ShaderProgram *shader)
{
shader->vertex = glCreateShader(GL_VERTEX_SHADER);
if (shader->vertex == 0)
{
printf("Shader Error: couldn't create vertex shader\n");
done = 1;
return;
}
shader->fragment = glCreateShader(GL_FRAGMENT_SHADER);
if (shader->fragment == 0)
{
printf("Shader Error: couldn't create fragment shader\n");
done = 1;
return;
}
glShaderSource(shader->vertex, 1, (const GLcharARB**) &vertex, NULL);
glCompileShader(shader->vertex);
GLint request_value;
glGetShaderiv(shader->vertex, GL_COMPILE_STATUS, &request_value);
if (request_value == GL_TRUE)
{
printf("Vertex shader: ok\n");
}
else
{
glGetShaderiv(shader->vertex, GL_INFO_LOG_LENGTH, &request_value);
GLchar log[request_value+1];
log[request_value] = 0;
glGetShaderInfoLog(shader->vertex, request_value, NULL, log);
printf("Vertex shader log:\n%s\n",log);
}
glShaderSource(shader->fragment, 1, (const GLcharARB**) &fragment, NULL);
glCompileShader(shader->fragment);
glGetShaderiv(shader->fragment, GL_COMPILE_STATUS, &request_value);
if (request_value == GL_TRUE)
{
printf("Fragment shader: ok\n");
}
else
{
glGetShaderiv(shader->fragment, GL_INFO_LOG_LENGTH, &request_value);
GLchar log[request_value+1];
log[request_value] = 0;
glGetShaderInfoLog(shader->fragment, request_value, NULL, log);
printf("Fragment shader log:\n%s\n",log);
}
shader->program = glCreateProgram();
if (shader->program == 0)
{
printf("Shader Error: couldn't create shader program\n");
done = 1;
return;
}
glAttachShader(shader->program, shader->vertex);
glAttachShader(shader->program, shader->fragment);
glLinkProgram(shader->program);
glGetProgramiv(shader->program, GL_LINK_STATUS, &request_value);
if (request_value == GL_TRUE)
{
printf("Shader program: ok\n");
}
else
{
glGetProgramiv(shader->program, GL_INFO_LOG_LENGTH, &request_value);
GLchar log[request_value+1];
log[request_value] = 0;
glGetProgramInfoLog(shader->program, request_value, NULL, log);
printf("Shader program log:\n%s\n",log);
}
}
/* A general OpenGL initialization function. Sets all of the initial parameters. */
void InitGL(int Width, int Height) // We call this right after our OpenGL window is created.
{
if (Height == 0)
{
Height = 1;
}
glViewport(0, 0, Width, Height);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // This Will Clear The Background Color To Black
glClearDepth(1.0); // Enables Clearing Of The Depth Buffer
glDepthFunc(GL_LESS); // The Type Of Depth Test To Do
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
glShadeModel(GL_SMOOTH); // Enables Smooth Color Shading
glMatrixMode(GL_PROJECTION);
glLoadIdentity(); // Reset The Projection Matrix
gluPerspective(45.0f, (GLfloat)Width/(GLfloat)Height, 0.1f, 100.0f); // Calculate The Aspect Ratio Of The Window
glMatrixMode(GL_MODELVIEW);
// Init depth textures
glGenTextures(tex_count, textures);
for (int i = 0; i < tex_count; ++i)
{
glBindTexture(GL_TEXTURE_2D, textures[i]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, tex_size, tex_size, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);
}
// Init framebuffer
glGenFramebuffers(tex_count, fbo);
for (int i = 0; i < tex_count; ++i)
{
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo[i]);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, textures[i], 0);
glDrawBuffer(GL_NONE);
GLenum Status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (Status != GL_FRAMEBUFFER_COMPLETE)
{
printf("FB error, status: 0x%x\n", Status);
done = 1;
return;
}
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// Init shaders
// Shadow Pass shader
loadShader(shadow_shader_vertex, shadow_shader_fragment, &ShadowShader);
loadShader(shadow_render_shader_vertex, shadow_render_shader_fragment, &ShadowRenderShader);
loadShader(blur_shader_vertex, blur_shader_fragment, &BlurShader);
shader_depth_map = glGetUniformLocation(ShadowRenderShader.program, "depth_map");
shader_depth_map_square = glGetUniformLocation(ShadowRenderShader.program, "depth_map_square");
shader_modelview_matrix = glGetUniformLocation(ShadowRenderShader.program, "light_modelview_matrix");
shader_projection_matrix = glGetUniformLocation(ShadowRenderShader.program, "light_projection_matrix");
shader_light_pos = glGetUniformLocation(ShadowRenderShader.program, "light_pos");
shader_light_intensity = glGetUniformLocation(ShadowRenderShader.program, "light_intensity");
shader_blur_scale = glGetUniformLocation(BlurShader.program, "ScaleU");
shader_blur_source = glGetUniformLocation(BlurShader.program, "textureSource");
printf("%d %d %d %d %d %d\n", shader_depth_map, shader_depth_map_square, shader_modelview_matrix, shader_projection_matrix, shader_light_pos, shader_light_intensity);
printf("%d %d\n", shader_blur_scale, shader_blur_source);
glUseProgram(ShadowRenderShader.program);
glUniform1i(shader_depth_map, 0);
glUniform1i(shader_depth_map_square, 1);
glUseProgram(BlurShader.program);
glUniform1i(shader_blur_source, 0);
glUseProgram(0);
GLenum error;
while ((error = glGetError()) != GL_NO_ERROR)
{
printf("Error %x\n",error);
}
}
void DeinitGL(void)
{
glDeleteTextures(tex_count, textures);
glDeleteFramebuffers(tex_count, fbo);
glDeleteShader(ShadowShader.vertex);
glDeleteShader(ShadowShader.fragment);
glDeleteProgram(ShadowShader.program);
glDeleteShader(ShadowRenderShader.vertex);
glDeleteShader(ShadowRenderShader.fragment);
glDeleteProgram(ShadowRenderShader.program);
glDeleteShader(BlurShader.vertex);
glDeleteShader(BlurShader.fragment);
glDeleteProgram(BlurShader.program);
}
void DrawGeometry(void)
{
// draw floor
glColor3f(1.0f, 1.0f, 1.0f);
glBegin(GL_QUADS);
glNormal3f( 0.0f, 1.0f, 0.0f);
glVertex3f( -10.0f, 0.0f, -10.0f);
glVertex3f( -10.0f, 0.0f, 10.0f);
glVertex3f( 10.0f, 0.0f, 10.0f);
glVertex3f( 10.0f, 0.0f, -10.0f);
glEnd();
// draw cube
glColor3f(0.0f, 1.0f, 0.0f);
glBegin(GL_QUADS);
glNormal3f( 0.0f, 1.0f, 0.0f);
glVertex3f( 1.0f, 2.5f,-1.0f);
glVertex3f(-1.0f, 2.5f,-1.0f);
glVertex3f(-1.0f, 2.5f, 1.0f);
glVertex3f( 1.0f, 2.5f, 1.0f);
glNormal3f( 0.0f,-1.0f, 0.0f);
glVertex3f( 1.0f, 0.5f, 1.0f);
glVertex3f(-1.0f, 0.5f, 1.0f);
glVertex3f(-1.0f, 0.5f,-1.0f);
glVertex3f( 1.0f, 0.5f,-1.0f);
glNormal3f( 0.0f, 0.0f, 1.0f);
glVertex3f( 1.0f, 2.5f, 1.0f);
glVertex3f(-1.0f, 2.5f, 1.0f);
glVertex3f(-1.0f, 0.5f, 1.0f);
glVertex3f( 1.0f, 0.5f, 1.0f);
glNormal3f( 0.0f, 0.0f,-1.0f);
glVertex3f( 1.0f, 0.5f,-1.0f);
glVertex3f(-1.0f, 0.5f,-1.0f);
glVertex3f(-1.0f, 2.5f,-1.0f);
glVertex3f( 1.0f, 2.5f,-1.0f);
glNormal3f(-1.0f, 0.0f, 0.0f);
glVertex3f(-1.0f, 2.5f, 1.0f);
glVertex3f(-1.0f, 2.5f,-1.0f);
glVertex3f(-1.0f, 0.5f,-1.0f);
glVertex3f(-1.0f, 0.5f, 1.0f);
glNormal3f( 1.0f, 0.0f, 0.0f);
glVertex3f( 1.0f, 2.5f,-1.0f);
glVertex3f( 1.0f, 2.5f, 1.0f);
glVertex3f( 1.0f, 0.5f, 1.0f);
glVertex3f( 1.0f, 0.5f,-1.0f);
glEnd();
}
void ShadowPass()
{
glLoadIdentity();
gluLookAt(
light_pos[0], light_pos[1], light_pos[2],
0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f
);
glGetFloatv(GL_MODELVIEW_MATRIX, light_modelview_matrix);
glGetFloatv(GL_PROJECTION_MATRIX, light_projection_matrix);
/*static int first = 1;
if (first)
{
first = 0;
printf("modelview matrix:\n");
for (int i = 0; i < 4; ++i)
printf("%f %f %f %f\n", light_modelview_matrix[i], light_modelview_matrix[4 + i], light_modelview_matrix[8 + i], light_modelview_matrix[12 + i]);
printf("\nprojection matrix:\n");
for (int i = 0; i < 4; ++i)
printf("%f %f %f %f\n", light_projection_matrix[i], light_projection_matrix[4 + i], light_projection_matrix[8 + i], light_projection_matrix[12 + i]);
}*/
glViewport(0,0,tex_size,tex_size);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo[0]);
glClear(GL_DEPTH_BUFFER_BIT);
DrawGeometry();
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo[1]);
glClear(GL_DEPTH_BUFFER_BIT);
glUseProgram(ShadowShader.program);
DrawGeometry();
glUseProgram(0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
SDL_Surface *surface = SDL_GetVideoSurface();
glViewport(0,0,surface->w,surface->h);
}
void GaussianBlurPass()
{
// set view to ortho, texture-sized
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0f,tex_size,tex_size,0.0f,-1.0f,1.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glViewport(0,0,tex_size,tex_size);
glUseProgram(BlurShader.program);
// 2 blur passes for depth texture
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo[4]);
glBindTexture(GL_TEXTURE_2D, textures[0]);
glClear(GL_DEPTH_BUFFER_BIT);
glUniform2f(shader_blur_scale, 1.0/((float)tex_size * blur_coeff), 0.0);
glBegin(GL_QUADS);
glTexCoord2d(0,1); glVertex3f(0, 0, 0);
glTexCoord2d(1,1); glVertex3f(tex_size, 0, 0);
glTexCoord2d(1,0); glVertex3f(tex_size, tex_size, 0);
glTexCoord2d(0,0); glVertex3f(0, tex_size, 0);
glEnd();
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo[2]);
glBindTexture(GL_TEXTURE_2D, textures[4]);
glClear(GL_DEPTH_BUFFER_BIT);
glUniform2f(shader_blur_scale, 0.0, 1.0/((float)tex_size * blur_coeff));
glBegin(GL_QUADS);
glTexCoord2d(0,1); glVertex3f(0, 0, 0);
glTexCoord2d(1,1); glVertex3f(tex_size, 0, 0);
glTexCoord2d(1,0); glVertex3f(tex_size, tex_size, 0);
glTexCoord2d(0,0); glVertex3f(0, tex_size, 0);
glEnd();
// 2 blur passes for depth-square texture
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo[4]);
glBindTexture(GL_TEXTURE_2D, textures[1]);
glClear(GL_DEPTH_BUFFER_BIT);
glUniform2f(shader_blur_scale, 1.0/((float)tex_size * blur_coeff), 0.0);
glBegin(GL_QUADS);
glTexCoord2d(0,1); glVertex3f(0, 0, 0);
glTexCoord2d(1,1); glVertex3f(tex_size, 0, 0);
glTexCoord2d(1,0); glVertex3f(tex_size, tex_size, 0);
glTexCoord2d(0,0); glVertex3f(0, tex_size, 0);
glEnd();
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo[3]);
glBindTexture(GL_TEXTURE_2D, textures[4]);
glClear(GL_DEPTH_BUFFER_BIT);
glUniform2f(shader_blur_scale, 0.0, 1.0/((float)tex_size * blur_coeff));
glBegin(GL_QUADS);
glTexCoord2d(0,1); glVertex3f(0, 0, 0);
glTexCoord2d(1,1); glVertex3f(tex_size, 0, 0);
glTexCoord2d(1,0); glVertex3f(tex_size, tex_size, 0);
glTexCoord2d(0,0); glVertex3f(0, tex_size, 0);
glEnd();
glUseProgram(0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// restore view
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
SDL_Surface *surface = SDL_GetVideoSurface();
float height = surface->h;
if (height == 0)
{
height = 1;
}
gluPerspective(45.0f, (GLfloat)surface->w/(GLfloat)height, 0.1f, 100.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glViewport(0,0,surface->w,surface->h);
}
void TestPass()
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
SDL_Surface *surface = SDL_GetVideoSurface();
glOrtho(0.0f,surface->w,surface->h,0.0f,-1.0f,1.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glColor3f(1.0f, 1.0f, 1.0f);
glEnable(GL_TEXTURE_2D);
if (blur)
{
glBindTexture(GL_TEXTURE_2D, textures[2]);
}
else
{
glBindTexture(GL_TEXTURE_2D, textures[0]);
}
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 1.0f); glVertex3f( 0.0f, 0.0f, 0.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f( surface->w/2, 0.0f, 0.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f( surface->w/2, surface->h, 0.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f( 0.0f, surface->h, 0.0f);
glEnd();
if (blur)
{
glBindTexture(GL_TEXTURE_2D, textures[4]);
}
else
{
glBindTexture(GL_TEXTURE_2D, textures[1]);
}
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 1.0f); glVertex3f( surface->w/2, 0.0f, 0.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f( surface->w, 0.0f, 0.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f( surface->w, surface->h, 0.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f( surface->w/2, surface->h, 0.0f);
glEnd();
glDisable(GL_TEXTURE_2D);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
float height = surface->h;
if (height == 0)
{
height = 1;
}
gluPerspective(45.0f, (GLfloat)surface->w/(GLfloat)height, 0.1f, 100.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void RenderPass()
{
glLoadIdentity();
gluLookAt(
5.0f, 5.0f, 5.0f,
0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f
);
glUseProgram(ShadowRenderShader.program);
glActiveTexture(GL_TEXTURE0);
if (blur)
{
glBindTexture(GL_TEXTURE_2D, textures[2]);
}
else
{
glBindTexture(GL_TEXTURE_2D, textures[0]);
}
glActiveTexture(GL_TEXTURE1);
if (blur)
{
glBindTexture(GL_TEXTURE_2D, textures[3]);
}
else
{
glBindTexture(GL_TEXTURE_2D, textures[1]);
}
glActiveTexture(GL_TEXTURE0);
glUniformMatrix4fv(shader_modelview_matrix, 1, GL_FALSE, light_modelview_matrix);
glUniformMatrix4fv(shader_projection_matrix, 1, GL_FALSE, light_projection_matrix);
glUniform4fv(shader_light_pos, 1, light_pos);
glUniform4fv(shader_light_intensity, 1, light_intensity);
DrawGeometry();
glUseProgram(0);
}
/* The main drawing function. */
void DrawGLScene()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
ShadowPass();
if (blur)
{
GaussianBlurPass();
}
if (test)
{
TestPass();
}
else
{
RenderPass();
}
// swap buffers to display, since we're double buffered.
SDL_GL_SwapBuffers();
}
void ResizeScene(int width, int height)
{
if (height == 0)
{
height = 1;
}
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, (GLfloat)width/(GLfloat)height, 0.1f, 100.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
SDL_SetVideoMode(width, height, 0, SDL_GL_DOUBLEBUFFER | SDL_RESIZABLE | SDL_OPENGL);
}
void UpdateScene(void)
{
last_time = current_time;
current_time = SDL_GetTicks();
float delta_time = (current_time - delta_time) / 1000.0f;
delta_time /= 1000.0f;
light_pos[0] -= charyvel * delta_time;
light_pos[2] += charxvel * delta_time;
}
void ProcessEvents(void)
{
SDL_Event event;
while ( SDL_PollEvent(&event) )
{
if ( event.type == SDL_QUIT )
{
done = 1;
}
if (event.type == SDL_VIDEORESIZE)
{
ResizeScene(event.resize.w, event.resize.h);
}
if ( event.type == SDL_KEYDOWN )
{
switch (event.key.keysym.sym)
{
case SDLK_ESCAPE:
done = 1;
break;
case SDLK_F1:
blur = !blur;
break;
case SDLK_F2:
test = !test;
break;
case SDLK_LEFT:
charxvel = -1;
break;
case SDLK_RIGHT:
charxvel = 1;
break;
case SDLK_UP:
charyvel = -1;
break;
case SDLK_DOWN:
charyvel = 1;
break;
break;
}
}
if ( event.type == SDL_KEYUP )
{
switch (event.key.keysym.sym)
{
case SDLK_LEFT:
case SDLK_RIGHT:
charxvel = 0;
break;
case SDLK_UP:
case SDLK_DOWN:
charyvel = 0;
break;
break;
}
}
}
}
int main(int argc, char **argv)
{
/* Initialize SDL for video output */
if ( SDL_Init(SDL_INIT_VIDEO) < 0 )
{
fprintf(stderr, "Unable to initialize SDL: %s\n", SDL_GetError());
exit(1);
}
SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 8 );
SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 8 );
SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 8 );
SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 );
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
/* Create a 640x480 OpenGL screen */
if ( SDL_SetVideoMode(start_width, start_height, 0, SDL_GL_DOUBLEBUFFER | SDL_RESIZABLE | SDL_OPENGL) == NULL )
{
fprintf(stderr, "Unable to create OpenGL screen: %s\n", SDL_GetError());
SDL_Quit();
exit(2);
}
/* Set the title bar in environments that support it */
SDL_WM_SetCaption("DT's Variance Shadow Map tutorial", NULL);
GLenum err = glewInit();
if (GLEW_OK != err)
{
/* Problem: glewInit failed, something is seriously wrong. */
fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
SDL_Quit();
exit(3);
}
if (!GLEW_VERSION_2_0)
{
fprintf(stderr, "Error: OpenGL 2.0 isn't supported\n");
SDL_Quit();
exit(4);
}
if (!GLEW_EXT_framebuffer_object)
{
fprintf(stderr, "Error: OpenGL GL_EXT_framebuffer_object extension isn't supported\n");
SDL_Quit();
exit(5);
}
SDL_Surface *surface = SDL_GetVideoSurface();
InitGL(surface->w, surface->h);
current_time = SDL_GetTicks();
/* Loop, drawing and checking events */
while (!done)
{
UpdateScene();
DrawGLScene();
ProcessEvents();
}
DeinitGL();
SDL_Quit();
return 0;
}