Hi,
I have make a little sample that display something like your picture and where we can resize the inner and outer radius with the top/bottom/right/left keys
It have use DevIL for to have the possibity to load .jpg files
The shader.h file :
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <math.h>
#include <GL/glew.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
// Handlers for our vertex shader, fragment shader and program
extern GLuint vsid, fsid, psid;
// Textures
extern GLint tex0, tex1;
// Fog
extern GLint indist, outdist;
extern GLfloat innersize, outersize;
extern GLint centerxLoc, centeryLoc;
extern GLfloat centerx, centery;
// Read in a textfile (GLSL program)
// we need to pass it as a string to the GLSL driver
char *ReadGLSL(char *fn);
// Read in a textfile (GLSL program)
// we can use this to write to a text file
int WriteGLSL(char *fn, char *s);
// Setup shaders
void SetupShaders(char *vsrc, char *fsrc);
The shader.c file:
#include "shader.h"
//Handlers for our vertex, geometry, and fragment shaders
GLuint vsid, fsid, psid;
// variables on your fragment shader
GLint tex0;
GLint tex1;
GLint indist;
GLint outdist;
GLfloat innersize = 0.2f;
GLfloat outersize = 0.4f;
GLint centerxLoc;
GLint centeryLoc;
GLfloat centerx = 0.5f;
GLfloat centery = 0.5f;
//Function from: http://www.evl.uic.edu/aej/594/code/ogl.cpp
//Read in a textfile (GLSL program)
// we need to pass it as a string to the GLSL driver
char *ReadGLSL(char *fn)
{
FILE *fp;
char *content = NULL;
int count=0;
if (fn != NULL) {
fp = fopen(fn,"rt");
if (fp != NULL) {
fseek(fp, 0, SEEK_END);
count = ftell(fp);
rewind(fp);
if (count > 0) {
content = (char *)malloc(sizeof(char) * (count+1));
count = fread(content,sizeof(char),count,fp);
content[count] = '\0';
}
fclose(fp);
}
}
printf("%s
", content);
return content;
}
//Function from: http://www.evl.uic.edu/aej/594/code/ogl.cpp
//Read in a textfile (GLSL program)
// we can use this to write to a text file
int WriteGLSL(char *fn, char *s)
{
FILE *fp;
int status = 0;
if (fn != NULL) {
fp = fopen(fn,"w");
if (fp != NULL) {
if (fwrite(s,sizeof(char),strlen(s),fp) == strlen(s))
status = 1;
fclose(fp);
}
}
return(status);
}
//Got this from http://www.lighthouse3d.com/opengl/glsl/index.php?oglinfo
// it prints out shader info (debugging!)
void printShaderInfoLog(GLuint obj)
{
int infologLength = 0;
int charsWritten = 0;
char *infoLog;
glGetShaderiv(obj, GL_INFO_LOG_LENGTH,&infologLength);
if (infologLength > 0)
{
infoLog = (char *)malloc(infologLength);
glGetShaderInfoLog(obj, infologLength, &charsWritten, infoLog);
if( charsWritten > 0)
printf("printShaderInfoLog %d :
%s
", obj, infoLog);
free(infoLog);
}else{
printf("Shader Info Log: OK
");
}
}
//Got this from http://www.lighthouse3d.com/opengl/glsl/index.php?oglinfo
// it prints out shader info (debugging!)
void printProgramInfoLog(GLuint obj)
{
int infologLength = 0;
int charsWritten = 0;
char *infoLog;
glGetProgramiv(obj, GL_INFO_LOG_LENGTH,&infologLength);
if (infologLength > 0)
{
infoLog = (char *)malloc(infologLength);
glGetProgramInfoLog(obj, infologLength, &charsWritten, infoLog);
if( charsWritten > 0 )
printf("printProgramInfoLog %d :
%s
", obj, infoLog);
free(infoLog);
}else{
printf("Program Info Log: OK
");
}
}
//Setup shaders
void SetupShaders(char *vsrc, char *fsrc)
{
//Setup a few constant pointers for below
char *vs = NULL, *fs = NULL;
glewInit();
if (glewIsSupported("GL_VERSION_2_1"))
{
// printf("Ready for OpenGL 2.1
");
}
else {
printf("OpenGL 2.1 not supported
");
exit(1);
}
if (GLEW_ARB_vertex_shader && GLEW_ARB_fragment_shader )
{
// printf("Ready for GLSL vertex and fragment shaders
");
}
else {
printf("Not ready fot GLSL vertex and fragment shaders
");
exit(1);
}
vsid = glCreateShader(GL_VERTEX_SHADER);
if( vsid == 0)
{
printf("can't create a GL_VERTEX_SHADER :(
");
exit(0);
}else{
printf("VERTEX SHADER(%s) : id=%d
", vsrc, vsid);
vs = ReadGLSL(vsrc);
const char * vv = vs;
glShaderSource(vsid, 1, &vv, NULL);
// free(vs);
glCompileShader(vsid);
// printShaderInfoLog(vsid);
}
fsid = glCreateShader(GL_FRAGMENT_SHADER);
if( fsid == 0)
{
printf("can't create a GL_FRAGMENT_SHADER :(
");
exit(0);
}else{
printf("FRAGMENT SHADER(%s) : id=%d
", fsrc, fsid);
fs = ReadGLSL(fsrc);
const char * ff = fs;
glShaderSource(fsid, 1, &ff, NULL);
// free(fs);
glCompileShader(fsid);
// printShaderInfoLog(fsid);
}
psid = glCreateProgram();
glAttachShader(psid,fsid);
glAttachShader(psid,vsid);
glLinkProgram(psid);
glUseProgram(psid);
tex0 = glGetUniformLocation(psid, "tex0");
tex1 = glGetUniformLocation(psid, "tex1");
indist = glGetUniformLocation(psid, "indist");
outdist = glGetUniformLocation(psid, "outdist");
centerxLoc = glGetUniformLocation(psid, "centerx");
centeryLoc = glGetUniformLocation(psid, "centery");
glUniform1f(indist, 0.2f);
glUniform1f(outdist, 0.4f);
glUniform1f(centerxLoc, 0.5f);
glUniform1f(centeryLoc, 0.5f);
printf("PROGRAM SHADER : vertexshader=%d fragmentshader=%d program=%d tex0=%d tex1=%d indist=%d outdist=%d
",
vsid, fsid, psid, tex0, tex1, indist, outdist );
printProgramInfoLog(psid);
}
The fog.c file :
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <math.h>
#include <GL/glew.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
/* use devIL for texture loading */
#include <IL/il.h>
/* use OpenGL shaders */
#include "shader.h"
/* ascii code for the escape key */
#define ESCAPE 27
#define FALSE 0
#define TRUE 1
/* The number of our GLUT window */
int window;
// todo : handle/mix multiples windows
// int windows[];
// int nWindows;
/* The texture used */
GLuint Textures[1];
ILuint ilTextures[1];
char *dataTexture;
int twidth = 0, theight = 0, tformat = 0, tbpp = 0;
int wwidth = 320, wheight=200;
void DrawQuadZoom( int v0, int v1, float zoom)
{
float x0, y0, x1, y1;
x0 = y0 = v0 * zoom;
x1 = y1 = v1 * zoom;
glBegin(GL_QUADS);
//glColor3f(0,1,0);
//glTexCoord2i(1,0);
glTexCoord2i(1,1);
glVertex3f(x0,y0,v0);
//glColor3f(0,0,1);
//glTexCoord2i(0,0);
glTexCoord2i(0,1);
glVertex3f(x1,y0,v0);
//glColor3f(1,0,0);
//glTexCoord2i(0,1);
glTexCoord2i(0,0);
glVertex3f(x1,y1,v0);
//glColor3f(1,0,0);
//glTexCoord2i(1,1);
glTexCoord2i(1,0);
glVertex3f(x0,y1,v0);
glEnd();
}
void DrawQuad()
{
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindTexture(GL_TEXTURE_2D, Textures[0]);
glLoadIdentity ();
DrawQuadZoom(-1, 1, 1.0f);
glutSwapBuffers();
}
void InitDevIL(char *filename1, char *filename2)
{
ilInit();
ilGenImages(2, ilTextures);
ilBindImage(ilTextures[0]);
if( ilLoadImage(filename1) == 0)
{
printf("ilLoadImage %s KO
", filename1);
exit(0);
}
dataTexture = ilGetData();
twidth = ilGetInteger(IL_IMAGE_WIDTH);
theight = ilGetInteger(IL_IMAGE_HEIGHT);
tformat = ilGetInteger(IL_IMAGE_FORMAT);
tbpp = ilGetInteger(IL_IMAGE_BPP);
printf("ilLoad(%s) : data=%x width=%d, height=%d bpp=%d
", filename1, dataTexture,twidth,theight,tbpp);
glBindTexture(GL_TEXTURE_2D, Textures[0]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, twidth, theight, 0, GL_RGB, GL_UNSIGNED_BYTE, dataTexture);
/*
ilBindImage(ilTextures[1]);
if( ilLoadImage(filename2?filename2:filename1) == 0)
{
printf("ilLoadImage %s KO
", filename2?filename2:filename1);
exit(0);
}
dataTexture = ilGetData();
twidth = ilGetInteger(IL_IMAGE_WIDTH);
theight = ilGetInteger(IL_IMAGE_HEIGHT);
tformat = ilGetInteger(IL_IMAGE_FORMAT);
tbpp = ilGetInteger(IL_IMAGE_BPP);
printf("ilLoad(%s) : data=%x width=%d, height=%d bpp=%d
", filename2, dataTexture,twidth,theight,tbpp);
glBindTexture(GL_TEXTURE_2D, Textures[1]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, twidth, theight, 0, GL_RGB, GL_UNSIGNED_BYTE, dataTexture);
*/
}
/* 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.
{
// Start Of User Initialization
glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Realy Nice perspective calculations
glClearColor (0.7f, 0.7f, 0.7f, 0.0f); // Light Grey Background
glClearDepth (1.0f); // Depth Buffer Setup
glEnable(GL_TEXTURE_2D);
glGenTextures(2,Textures);
glBindTexture(GL_TEXTURE_2D, Textures[0]);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexEnvf ( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
/*
glBindTexture(GL_TEXTURE_2D, Textures[1]);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexEnvf ( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
*/
}
/* The function called when our window is resized */
void ReSizeGLScene(int Width, int Height)
{
// Prevent A Divide By Zero If The Window Is Too Small
if (Height==0) Height=1;
// Reset The Current Viewport And Perspective Transformation
glViewport(0, 0, Width, Height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, (GLfloat) Width / (GLfloat) Height, 0.1f, 100.0f);
glMatrixMode(GL_MODELVIEW);
wwidth = Width;
wheight = Height;
// printf("ReSizeGLScene(%d,%d)
", wwidth, wheight);
}
// Delete The Shader Texture
void Deinitialize (void)
{
glDeleteTextures (2, Textures);
}
/* The function called whenever a key is pressed. */
void keyPressed(unsigned char key, int x, int y)
{
/* avoid thrashing this procedure */
usleep(100);
/* If escape is pressed, kill everything. */
switch (key) {
case ESCAPE: // kill everything.
/* shut down our window */
Deinitialize();
glutDestroyWindow(window);
/* exit the program...normal termination. */
exit(1);
break; // redundant.
default:
printf ("Key %d pressed. No action there yet.
", key);
break;
}
glutPostRedisplay();
}
void specialKeyPressed(int key, int x, int y)
{
/* avoid thrashing this procedure */
usleep(100);
switch (key) {
case GLUT_KEY_UP:
printf("(%d) innersize++
",key);
innersize += 0.01f;
if( innersize >= outersize) innersize = outersize - 0.1f;
glUniform1f(indist, innersize);
break;
case GLUT_KEY_DOWN:
printf("(%d) innersize--
",key);
innersize -= 0.01f;
if( innersize < 0.0f) innersize= 0.0f;
glUniform1f(indist, innersize);
break;
case GLUT_KEY_LEFT :
printf("(%d) outersize--
",key);
outersize -= 0.01f;
if( outersize <= innersize) outersize = innersize + 0.1f;
glUniform1f(outdist, outersize);
break;
case GLUT_KEY_RIGHT :
printf("(%d) outersize++
",key);
outersize += 0.01f;
if( outersize > 1.0f) outersize= 1.0f;
glUniform1f(outdist, outersize);
break;
default:
printf ("Key %d pressed. No action there yet.
", key);
break;
}
glutPostRedisplay();
}
void MouseMoved(int x, int y)
{
printf("MouseMove(%d/%d,%d/%d)
", x, wwidth, y, wheight);
centerx = ((x-(wwidth /2.0f))/(-wwidth*2.0f)) + 0.5f;
centery = (((wheight/2.0f)-y)/(-wheight*2.0f)) + 0.5f;
printf("Center : %f %f
", centerx, centery);
glUniform1f(centerxLoc, centerx);
glUniform1f(centeryLoc, centery);
glutPostRedisplay();
}
int main(int argc, char **argv)
{
/* Initialize GLUT state - glut will take any command line arguments that pertain to it or
X Windows - look at its documentation at http://reality.sgi.com/mjk/spec3/spec3.html */
glutInit(&argc, argv);
/* Select type of Display mode */
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH);
/* get a width x height (640*480) window size */
glutInitWindowSize(wwidth, wheight);
/* the window starts at the upper left corner of the screen */
glutInitWindowPosition(0, 0);
/* Open a window */
window = glutCreateWindow("Quad Shader v0.1");
/* Register the function to do all our OpenGL drawing. */
glutDisplayFunc(&DrawQuad);
/* Register the function called when our window is resized. */
glutReshapeFunc(&ReSizeGLScene);
/* Register the function called when the keyboard is pressed. */
glutKeyboardFunc(&keyPressed);
glutSpecialFunc(&specialKeyPressed);
/* Register the function to do all our OpenGL drawing. */
glutMotionFunc(&MouseMoved);
/* Initialize our window. */
InitGL(wwidth, wheight);
InitDevIL(argv[1], argv[2]);
SetupShaders("shader.vert","shader.frag");
// glUniformlui(tex0, Textures[0]);
// glUniformlui(tex1, Textures[1]);
/* Start Event Processing Engine */
glutMainLoop();
return 1;
}
The shader.frag file :
// uniform sampler2D tex;
uniform sampler2D tex0;
uniform sampler2D tex1;
//float indist = 0.3;
//float outdist = 0.7;
uniform float indist;
uniform float outdist;
uniform float centerx;
uniform float centery;
void main()
{
// vec2 vdif = (gl_TexCoord[0].st - vec2(0.5,0.5)) * 4.0;
vec2 vdif = (gl_TexCoord[0].st - vec2(centerx, centery)) * 4.0;
float f = sqrt( vdif.x*vdif.x + vdif.y*vdif.y );
vec4 fade;
if( f < indist )
{
fade = texture2D(tex0, gl_TexCoord[0].st) * vec4(0.3,0.3,0.3,1.0);
}else{
if( f > outdist)
{
fade = texture2D(tex0, gl_TexCoord[0].st) * vec4(0.3,0.3,0.3,1.0);
}else{
fade = texture2D(tex0, gl_TexCoord[0].st);
}
}
gl_FragColor = fade;
}
The shader.vert file :
void main()
{
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
gl_Position = ftransform();
}
And finaly the Makefile :
all: fog shader.o
shader.o : shader.c shader.h
gcc -c shader.c -o shader.o -L/usr/X11R6/lib -lGL -lGLU -lglut -lIL -lGLEW
fog : fog.c shader.o
gcc fog.c shader.o -o fog -L/usr/X11R6/lib -lGL -lGLU -lglut -lIL -lGLEW
clean :
rm shader.o fog
You can compile this with the commande ‘make’ and run with ‘./fog myfilename.jpg’