blob: 0a4d04dd8cfeb87fa7ef028729af9c508de7e5dc [file] [log] [blame]
/**
* Test shadow2DRectProj() and shadow2D() functions.
* Brian Paul
* 11 April 2007
*/
#define GL_GLEXT_PROTOTYPES
#include <assert.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <GL/glew.h>
#include <GL/glut.h>
/** Use GL_RECTANGLE texture (with projective texcoords)? */
#define USE_RECT 01
#define TEXSIZE 16
static char *FragProgFile = NULL;
static char *VertProgFile = NULL;
static GLuint fragShader;
static GLuint vertShader;
static GLuint program;
static GLint uTexture2D;
static GLint uTextureRect;
static GLint win = 0;
static GLenum Filter = GL_LINEAR;
static void
CheckError(int line)
{
GLenum err = glGetError();
if (err) {
printf("GL Error %s (0x%x) at line %d\n",
gluErrorString(err), (int) err, line);
}
}
static void
PrintString(const char *s)
{
while (*s) {
glutBitmapCharacter(GLUT_BITMAP_8_BY_13, (int) *s);
s++;
}
}
static void
Redisplay(void)
{
CheckError(__LINE__);
glClear(GL_COLOR_BUFFER_BIT);
glPushMatrix();
CheckError(__LINE__);
glUseProgram(program);
CheckError(__LINE__);
glBegin(GL_POLYGON);
#if USE_RECT
/* scale coords by two to test projection */
glTexCoord4f( 0, 0, 0, 2.0); glVertex2f(-1, -1);
glTexCoord4f(2*TEXSIZE, 0, 2*1, 2.0); glVertex2f( 1, -1);
glTexCoord4f(2*TEXSIZE, 2*TEXSIZE, 2*1, 2.0); glVertex2f( 1, 1);
glTexCoord4f( 0, 2*TEXSIZE, 0, 2.0); glVertex2f(-1, 1);
#else
glTexCoord3f(0, 0, 0); glVertex2f(-1, -1);
glTexCoord3f(1, 0, 1); glVertex2f( 1, -1);
glTexCoord3f(1, 1, 1); glVertex2f( 1, 1);
glTexCoord3f(0, 1, 0); glVertex2f(-1, 1);
#endif
glEnd();
glPopMatrix();
glUseProgram(0);
glWindowPos2iARB(80, 20);
PrintString("white black white black");
glutSwapBuffers();
}
static void
Reshape(int width, int height)
{
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 25.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0f, 0.0f, -8.0f);
}
static void
CleanUp(void)
{
glDeleteShader(fragShader);
glDeleteShader(vertShader);
glDeleteProgram(program);
glutDestroyWindow(win);
}
static void
Key(unsigned char key, int x, int y)
{
(void) x;
(void) y;
switch(key) {
case 27:
CleanUp();
exit(0);
break;
}
glutPostRedisplay();
}
static void
MakeTexture(void)
{
GLfloat image[TEXSIZE][TEXSIZE];
GLuint i, j;
for (i = 0; i < TEXSIZE; i++) {
for (j = 0; j < TEXSIZE; j++) {
if (j < (TEXSIZE / 2)) {
image[i][j] = 0.25;
}
else {
image[i][j] = 0.75;
}
}
}
glActiveTexture(GL_TEXTURE0); /* unit 0 */
glBindTexture(GL_TEXTURE_2D, 42);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, TEXSIZE, TEXSIZE, 0,
GL_DEPTH_COMPONENT, GL_FLOAT, image);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, Filter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, Filter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB,
GL_COMPARE_R_TO_TEXTURE_ARB);
CheckError(__LINE__);
glActiveTexture(GL_TEXTURE1); /* unit 1 */
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 43);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_DEPTH_COMPONENT,
TEXSIZE, 10, 0,/*16x10*/
GL_DEPTH_COMPONENT, GL_FLOAT, image);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, Filter);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, Filter);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_COMPARE_MODE_ARB,
GL_COMPARE_R_TO_TEXTURE_ARB);
CheckError(__LINE__);
}
static void
LoadAndCompileShader(GLuint shader, const char *text)
{
GLint stat;
glShaderSource(shader, 1, (const GLchar **) &text, NULL);
glCompileShader(shader);
glGetShaderiv(shader, GL_COMPILE_STATUS, &stat);
if (!stat) {
GLchar log[1000];
GLsizei len;
glGetShaderInfoLog(shader, 1000, &len, log);
fprintf(stderr, "fslight: problem compiling shader:\n%s\n", log);
exit(1);
}
}
/**
* Read a shader from a file.
*/
static void
ReadShader(GLuint shader, const char *filename)
{
const int max = 100*1000;
int n;
char *buffer = (char*) malloc(max);
FILE *f = fopen(filename, "r");
if (!f) {
fprintf(stderr, "fslight: Unable to open shader file %s\n", filename);
exit(1);
}
n = fread(buffer, 1, max, f);
printf("fslight: read %d bytes from shader file %s\n", n, filename);
if (n > 0) {
buffer[n] = 0;
LoadAndCompileShader(shader, buffer);
}
fclose(f);
free(buffer);
}
static void
CheckLink(GLuint prog)
{
GLint stat;
glGetProgramiv(prog, GL_LINK_STATUS, &stat);
if (!stat) {
GLchar log[1000];
GLsizei len;
glGetProgramInfoLog(prog, 1000, &len, log);
fprintf(stderr, "Linker error:\n%s\n", log);
}
}
static void
Init(void)
{
static const char *fragShaderText =
"uniform sampler2DShadow shadowTex2D; \n"
"uniform sampler2DRectShadow shadowTexRect; \n"
"void main() {\n"
#if USE_RECT
" gl_FragColor = shadow2DRectProj(shadowTexRect, gl_TexCoord[0]); \n"
#else
" gl_FragColor = shadow2D(shadowTex2D, gl_TexCoord[0].xyz); \n"
#endif
"}\n";
static const char *vertShaderText =
"void main() {\n"
" gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
" gl_TexCoord[0] = gl_MultiTexCoord0; \n"
"}\n";
const char *version;
#if USE_RECT
if (!glutExtensionSupported("GL_ARB_texture_rectangle")) {
printf("This program requires GL_ARB_texture_rectangle\n");
exit(1);
}
#endif
version = (const char *) glGetString(GL_VERSION);
if (version[0] != '2' || version[1] != '.') {
printf("This program requires OpenGL 2.x, found %s\n", version);
exit(1);
}
printf("GL_RENDERER = %s\n",(const char *) glGetString(GL_RENDERER));
fragShader = glCreateShader(GL_FRAGMENT_SHADER);
if (FragProgFile)
ReadShader(fragShader, FragProgFile);
else
LoadAndCompileShader(fragShader, fragShaderText);
vertShader = glCreateShader(GL_VERTEX_SHADER);
if (VertProgFile)
ReadShader(vertShader, VertProgFile);
else
LoadAndCompileShader(vertShader, vertShaderText);
program = glCreateProgram();
glAttachShader(program, fragShader);
glAttachShader(program, vertShader);
glLinkProgram(program);
CheckLink(program);
glUseProgram(program);
uTexture2D = glGetUniformLocation(program, "shadowTex2D");
uTextureRect = glGetUniformLocation(program, "shadowTexRect");
printf("uTexture2D %d uTextureRect %d\n", uTexture2D, uTextureRect);
if (uTexture2D >= 0) {
glUniform1i(uTexture2D, 0); /* use texture unit 0 */
}
if (uTextureRect >= 0) {
glUniform1i(uTextureRect, 1); /* use texture unit 0 */
}
CheckError(__LINE__);
glClearColor(0.3f, 0.3f, 0.3f, 0.0f);
glColor3f(1, 1, 1);
MakeTexture();
CheckError(__LINE__);
}
static void
ParseOptions(int argc, char *argv[])
{
int i;
for (i = 1; i < argc; i++) {
if (strcmp(argv[i], "-fs") == 0) {
FragProgFile = argv[i+1];
}
else if (strcmp(argv[i], "-vs") == 0) {
VertProgFile = argv[i+1];
}
}
}
int
main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitWindowPosition( 0, 0);
glutInitWindowSize(400, 300);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
win = glutCreateWindow(argv[0]);
glewInit();
glutReshapeFunc(Reshape);
glutKeyboardFunc(Key);
glutDisplayFunc(Redisplay);
ParseOptions(argc, argv);
Init();
glutMainLoop();
return 0;
}