Solving PDE's in OpenGL

Hi Everyone,
I am new to OpenGL and slowly understanding it.
I found vertex and fragment shaders for partial difference equations using Lax-Friedrichs scheme.
I wrote (gathered and wrote) a code that runs these shaders. The output is a window with a square (two triangles combined with different colors).
I know that the shaders are accessed at least once because if I modify the equation, by adding a number, the output colors change.
Please find my code below.

I have two questions:

  1. Is the equation being accessed correctly?
  2. How can I loop the equation (perhaps glutIdleFunc(reshape) ? )?

Please let me know if I am unclear.

My Code:

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <iostream>

#include <GL/glew.h>
#include <GL/glut.h>

#include <iostream>
#include "Timer.h"
#include "textfile.h"

using namespace std;

GLuint v, f, p; // Declared GLU int variables
GLuint p1;
GLuint QTex=0;
GLuint depth_tex;
int winwidth = 256, winheight = 256; // Assigning Window dimensions to the variables
float lpos[4] = {1,0.5,1,0};

#define printOpenGLError() printOglError(__FILE__, __LINE__)
int printOglError(char *file, int line)
{
    //
    // Returns 1 if an OpenGL error occurred, 0 otherwise.
    //
    GLenum glErr;
    int    retCode = 0;

    glErr = glGetError();
    while (glErr != GL_NO_ERROR)
    {
        printf("glError in file %s @ line %d: %s
", file, line, gluErrorString(glErr));
        retCode = 1;
        glErr = glGetError();
    }
    return retCode;
}

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);
		printf("%s
",infoLog);
        free(infoLog);
    }
}

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);
		printf("%s
",infoLog);
        free(infoLog);
    }
}

void checkFBOStatus(){
GLenum status;
status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
switch(status) {
case GL_FRAMEBUFFER_COMPLETE_EXT: // Everything's OK
cout << "FRAMEBUFFER COMPLETE !"<<endl;
break;
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
cout << "glift::CheckFramebufferStatus() ERROR:
	"
<< "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT
";
break;
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
cout << "glift::CheckFramebufferStatus() ERROR:
	"
<< "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT
";
break;
//case GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT:
//cout << "glift::CheckFramebufferStatus() ERROR:
	"
//<< "GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT
";
//break;
case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
cout << "glift::CheckFramebufferStatus() ERROR:
	"
<< "GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT
";
break;
case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
cout << "glift::CheckFramebufferStatus() ERROR:
	"
<< "GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT
";
break;
case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
cout << "glift::CheckFramebufferStatus() ERROR:
	"
<< "GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT
";
break;
case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
cout << "glift::CheckFramebufferStatus() ERROR:
	"
<< "GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT
";
break;
case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
cout << "glift::CheckFramebufferStatus() ERROR:
	"
<< "GL_FRAMEBUFFER_UNSUPPORTED_EXT
";
break;
// case GL_FRAMEBUFFER_STATUS_ERROR_EXT:
// cout << "glift::CheckFramebufferStatus() ERROR:
	"
// << "GL_FRAMEBUFFER_STATUS_ERROR_EXT
";
// break;
default:
cout << "glift::CheckFramebufferStatus() ERROR:
	"
<< "Unknown ERROR
";
}
}

void createTexture(GLuint texId, GLenum format, int w, int h, GLfloat *data){
	glBindTexture(GL_TEXTURE_2D,texId);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

	glTexImage2D(GL_TEXTURE_2D,0,format,w,h,0,GL_RGBA,GL_FLOAT,data);
}

void setupTextures(){
	int sz = 4;
	GLfloat *data = new GLfloat[winwidth*winheight*sz];
	for (int j=0;j<winheight;j++)
		for (int i=0;i<winwidth;i++)
		{
			int idx = j*winwidth*sz+i*sz;
			data[idx]= i/(j+1);
			data[idx+1]= 1-i/(j+1);
			data[idx+2]= 0.5;
			data[idx+3]=0.9;
		}
		createTexture(QTex,GL_RGBA,winwidth,winheight,data);
}

GLuint fbo;
void fboCreation(){
	//fbo creation
	glGenFramebuffersEXT(1,&fbo);
	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,fbo);
	
	// create depth texture
	glGenTextures(1, &depth_tex);
	glBindTexture(GL_TEXTURE_2D, depth_tex);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, winwidth, winheight, 0,GL_RGBA, GL_UNSIGNED_BYTE, NULL);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

	glGenerateMipmapEXT(GL_TEXTURE_2D);

	// attach that texture to the depth
	// attachment point of the fbo
	glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, depth_tex, 0);
	
	checkFBOStatus();

	//************************************************************************************************************

	glPushAttrib(GL_VIEWPORT_BIT);
	glViewport(0,0,winwidth,winheight);

	GLboolean lighting;
	glGetBooleanv(GL_LIGHTING, &lighting);
	if (lighting) glDisable(GL_LIGHTING);

	GLint mode;
	glGetIntegerv(GL_MATRIX_MODE, & mode);

	glMatrixMode(GL_MODELVIEW);
	glPushMatrix();
	glLoadIdentity();
	glMatrixMode(GL_PROJECTION);
	glPushMatrix();
	glLoadIdentity();
	glOrtho(0.0,1.0,0.0,1.0,-1.0,1.0);
	glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_COMPARE_MODE,GL_NONE);
	glBindTexture(GL_TEXTURE_2D,-1);
	
	GLboolean depth_test;
	glGetBooleanv(GL_DEPTH_TEST, & depth_test);
	if (depth_test) glDisable(GL_DEPTH_TEST);
	float data[][5] = {	{ 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }, { 1.0f, 0.0f, 1.0f, 0.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f, 0.0f }, { 0.0f, 1.0f, 0.0f, 1.0f, 0.0f } };
	glInterleavedArrays(GL_T2F_V3F,0,data);
	glDrawArrays(GL_QUADS,0,4);
	
	if (depth_test) glEnable(GL_DEPTH_TEST);
	
	if (lighting) glEnable(GL_LIGHTING);

	glPopMatrix();
	glMatrixMode(GL_MODELVIEW);
	glPopMatrix();

	glMatrixMode(mode);
	glPopAttrib();
	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,0); //unbind
	//glDeleteFramebuffersEXT(1,&fbo);
	

	//**********************************************************************************************************
	glBindTexture(GL_TEXTURE_2D,depth_tex);
	glGenerateMipmapEXT(GL_TEXTURE_2D);
	glDeleteFramebuffersEXT(1,&fbo);

GLuint setShaders(){
	char *vs = NULL,*fs = NULL;

	v = glCreateShader(GL_VERTEX_SHADER);
	f = glCreateShader(GL_FRAGMENT_SHADER);

	vs = textFileRead("Lax_Friedrichs_VertexShdr.txt");
	fs = textFileRead("Lax_Friedrichs_FragmentShdr.txt");

	const char * vv = vs;
	const char * ff = fs;

	glShaderSource(v, 1,&vv,NULL);	//Sets the source code in 'v' in the array of pointer to strings "vv" 
									//vv contains a null terminated string
	glShaderSource(f, 1,&ff,NULL);	//Sets the source code in 'v' in the array of pointer to strings "vv" 
									//vv contains a null terminated string

	free(vs);free(fs);				//Deallocates or frees the memory blocks vs and fs

	glCompileShader(v);				//Compiles the vertex shader v
	glCompileShader(f);				//Compiles the fragment shader f

	printShaderInfoLog(v);
	printShaderInfoLog(f);

	p = glCreateProgram();			//Create a program object
	glAttachShader(p,v);			//Attaching the shader to the program
	glAttachShader(p,f);			//Attaching the shader to the program

	glLinkProgram(p);				//Linking the program

	printProgramInfoLog(p);

	return(p);
}

float a = 0;

	float delxy[2] = {0.5,0.5};
	float courant = 0.5;//0.5;
	float grav = 4.41;

void renderScene(void){


	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glEnable(GL_TEXTURE_2D);
	glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL);
	//glBindTexture(GL_TEXTURE_2D,texture);
	glBindTexture(GL_TEXTURE_2D,QTex);
	
	glUseProgram(p);				//Using the program
	//printProgramInfoLog(p);

	float delxy[2] = {0.5,0.5};
	float courant = 0.5;
	float grav = 4.41;
	GLint loc1, loc2, loc3;

	loc1 = glGetUniformLocation(p,"dXY");
	glUniform1fv(loc1,1,delxy);
	loc2 = glGetUniformLocation(p,"r");
	glUniform1f(p,courant);
	loc3 = glGetUniformLocation(p,"halfG");
	glUniform1f(p,grav);

	GLuint uniformLoc = glGetUniformLocation(p,"QTex");
	if (uniformLoc != -1)
	glUniform1i (uniformLoc, 0);
	courant +=0.1;
//***********************************************************************************************************************

	glBegin(GL_QUADS);
	glTexCoord2f(0.0,0.0); glVertex3f(-2.0,-1.0,0.0);	glTexCoord2f(0.0,1.0); glVertex3f(-2.0,1.0,0.0);	glTexCoord2f(1.0,1.0); glVertex3f(0.0,1.0,0.0);	glTexCoord2f(1.0,0.0); glVertex3f(0.0,-1.0,0.0);	
	glEnd();
	glFlush();
	glDisable(GL_TEXTURE_2D);

	glutSwapBuffers();
}

//GLUT reshape function
void reshape (int w, int h)
{

	glViewport(0,0,w,h);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(60.0,w/h,1.0,30.0);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	glTranslatef(0.0,0.0,-3.6);
}

void quit_menu(int id)
{
	if (id == 1) exit(0);
}

int main(int argc, char **argv){
	
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DEPTH |GLUT_SINGLE | GLUT_RGBA);
	glutInitWindowPosition(100,100);
	glutInitWindowSize(winwidth,winheight);
	glutCreateWindow("Flood GPU");

	setupTextures();
	
	glutDisplayFunc(renderScene);
	glutIdleFunc(renderScene);
	glutReshapeFunc(reshape);

	glEnable(GL_DEPTH_TEST);
	glClearColor(0.0,0.0,0.0,1.0);

	glewInit();
	if (glewIsSupported("GL_VERSION_2_0"))
		printf("Ready for OpenGL 2.0
");
	else {
		printf("OpenGL 2.0 not supported
");
		exit(1);
	}

	// Create a menu item
	glutCreateMenu(quit_menu);
	glutAddMenuEntry("quit",1);
	glutAttachMenu(GLUT_RIGHT_BUTTON);
	
	p1 = setShaders();
	glutMainLoop(); //End of the main function 
	return 0;
}

My Vertex Shader(Lax_Friedrichs_VertexShdr.txt):

varying vec4 texXcoord;
varying vec4 texYcoord;
uniform vec2 dXY;
void main (void)
{
texXcoord = gl_MultiTexCoord0.yxxx+vec4(0.0,0.0,-1.0,1.0)*dXY.x;
texYcoord = gl_MultiTexCoord0.xyyy+vec4(0.0,0.0,-1.0,1.0)*dXY.y;
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}

My Fragment Shader(Lax_Friedrichs_FragmentShdr.txt):

varying vec4 texXcoord;
varying vec4 texYcoord;
uniform sampler2D QTex;
uniform float r;
uniform float halfG;
vec4 fflux(in vec4 Q)
{
	float u = Q.y/Q.x;
	return vec4(Q.y,(Q.y*u+halfG*Q.x*Q.x),Q.z*u,0.0);
}

vec4 gflux(in vec4 Q)
{
	float v = Q.z/Q.x;
	return vec4(Q.z,Q.y*v, (Q.z*v+halfG*Q.x*Q.x),0.0);
}
void main(void)
{
	vec4 QE = texture2D(QTex,texXcoord.wx);
	vec4 QW = texture2D(QTex,texXcoord.zx);
	vec4 QN = texture2D(QTex,texYcoord.xw);
	vec4 QS = texture2D(QTex,texYcoord.xz);
gl_FragColor = 0.25*(QE+QW+QN+QS)-0.5*r*(fflux(QE)-fflux(QW))-0.5*r*(gflux(QN)-gflux(QS))+(r/10.0);
}

I have used the textfile.cpp and textfile.h from lighthouse3d.com

Any help is greatly appreciated.

Thank you,
Alfred

Hi Everyone,

I am adding the textfile.cpp and textfile.h files here. Also this helps me in making my post current:)

Also, i am using NVidia GeForce 8400 video card.

I really need this to work so i understand how it works. I can see it is accessing the shader and running the equation. But for some reason, it is just giving a constant output/color, even though i increment the variable so the output changes every time.

Here is textfile.cpp"

// textfile.cpp
//
// simple reading and writing for text files
//
// www.lighthouse3d.com
//
// You may use these functions freely.
// they are provided as is, and no warranties, either implicit,
// or explicit are given
//////////////////////////////////////////////////////////////////////

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *textFileRead(char *fn) {
	
	FILE *fp;
	char *content = NULL;

	int count = 0;

	if (fn != NULL) {				// Check to see if the function name is null or not
		fp = fopen(fn,"rt");		//Open a text file
		
		if (fp != NULL) {			//Check to see if the file is empty or not
			fseek(fp,0,SEEK_END);	//Seek the end of the file
			count = ftell(fp);		//Get the position of the end of file
			rewind(fp);				//Reset the pointer to the beginning of the file

			if (count>0) {
				content = (char *)malloc(sizeof(char)*(count+1));	//As much as i can understand now, this line allocates 
									//memory blocks for no. of lines +1 of type char and linked to the pointer "content"

				count = fread(content,sizeof(char),count,fp);		//Read data from a stream, fp
				content[count]='\0';//Replacing spaces at the location "count" with \0 -- 'escape sequence'
									//Strings ending in a null character are said to be null-terminated
			}
			fclose(fp);
		}
	}
	return content;
}

int textFileWrite(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);
}

Here is textfile.h:

// textfile.h: interface for reading and writing text files
// www.lighthouse3d.com
//
// You may use these functions freely.
// they are provided as is, and no warranties, either implicit,
// or explicit are given
//////////////////////////////////////////////////////////////////////

char *textFileRead(char *fn);
int textFileWrite(char *fn, char *s);

Any help, suggestions, comments or links to resources help.

Thank you very much,
Alfred

Hi everyone,

I finally figured it out…

I did two things…

  1. I updated my driver to “6.14.11.7824 - nVIDIA ForceWare 78.24”. Previously, i used to get Unhandled exception, but this upgrade seemed to have rectified it.

  2. Corrected my code in renderScene()
    It used to be glUniform1f(p,courant); what was wrong because p was handler for program object, i changed it to glUniform1f(loc2,courant); where loc2 is GLint.

This seems to have done the trick and the output is changing colors till it becomes uniform color.

Thank you everyone for trying.
Alfred