PDA

View Full Version : Solving PDE's in OpenGL



Alfred Kalyanapu
10-24-2008, 11:39 AM
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\n", 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,&amp;infologLength);

if (infologLength > 0)
{
infoLog = (char *)malloc(infologLength);
glGetShaderInfoLog(obj, infologLength, &amp;charsWritten, infoLog);
printf("%s\n",infoLog);
free(infoLog);
}
}

void printProgramInfoLog(GLuint obj)
{
int infologLength = 0;
int charsWritten = 0;
char *infoLog;

glGetProgramiv(obj, GL_INFO_LOG_LENGTH,&amp;infologLength);

if (infologLength > 0)
{
infoLog = (char *)malloc(infologLength);
glGetProgramInfoLog(obj, infologLength, &amp;charsWritten, infoLog);
printf("%s\n",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:\n\t"
<< "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT\n";
break;
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
cout << "glift::CheckFramebufferStatus() ERROR:\n\t"
<< "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT\n";
break;
//case GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT :
//cout << "glift::CheckFramebufferStatus() ERROR:\n\t"
//<< "GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT \n";
//break;
case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
cout << "glift::CheckFramebufferStatus() ERROR:\n\t"
<< "GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT\n";
break;
case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
cout << "glift::CheckFramebufferStatus() ERROR:\n\t"
<< "GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT\n";
break;
case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
cout << "glift::CheckFramebufferStatus() ERROR:\n\t"
<< "GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT\n";
break;
case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
cout << "glift::CheckFramebufferStatus() ERROR:\n\t"
<< "GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT\n";
break;
case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
cout << "glift::CheckFramebufferStatus() ERROR:\n\t"
<< "GL_FRAMEBUFFER_UNSUPPORTED_EXT\n";
break;
// case GL_FRAMEBUFFER_STATUS_ERROR_EXT:
// cout << "glift::CheckFramebufferStatus() ERROR:\n\t"
// << "GL_FRAMEBUFFER_STATUS_ERROR_EXT\n";
// break;
default:
cout << "glift::CheckFramebufferStatus() ERROR:\n\t"
<< "Unknown ERROR\n";
}
}

void createTexture(GLuint texId, GLenum format, int w, int h, GLfloat *data){
glBindTexture(GL_TEXTURE_2D,texId);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTE R, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTE R, 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,&amp;fbo);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,fbo);

// create depth texture
glGenTextures(1, &amp;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, &amp;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_M ODE,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,&amp;fbo);


//************************************************** ************************************************** ******
glBindTexture(GL_TEXTURE_2D,depth_tex);
glGenerateMipmapEXT(GL_TEXTURE_2D);
glDeleteFramebuffersEXT(1,&amp;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,&amp;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,&amp;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_DE CAL);
//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(&amp;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\n");
else {
printf("OpenGL 2.0 not supported\n");
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

Alfred Kalyanapu
10-28-2008, 11:18 AM
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

Alfred Kalyanapu
10-28-2008, 12:53 PM
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