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:
- Is the equation being accessed correctly?
- 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