Sign in to follow this  
redneon

OpenGL Trouble implementing RenderMonkey's ocean shader

Recommended Posts

I'm trying to implement the ocean shader that comes with RenderMonkey (Reflections Refractions) in GLSL and have run into a couple of problems. I've read through most of NVidia's Cg Tutorial book but didn't really like it so went on to read the OpenGL orange book (OpenGL Shading Language). It's a great book but it doesn't give anywhere near enough details on how to actually implement shaders. In the end, I learnt how to implement shaders from the tutorials on lighthouse3d.com, at the recommendation of one of the posters on this forum. Anyway, I think I've implemented everything correctly apart from two uniform variables. One is a sampler3D, to deal with the noise and one is a samplerCube, which is the texture being used for the sky box. Unfortunately, on lighthouse3d.com, there are no explanations detailing how to implement sampler3D or samplerCube so I was hoping someone could help me out. Firstly, the vertex shader looks like this:
uniform vec4 view_position;
uniform vec4 scale;

varying vec3 vTexCoord;
varying vec3 vNormal;
varying vec3 vViewVec;

void main(void)
{
   vec4 Position = gl_Vertex.xyzw;
   
   // Get some size on the water
   Position.xy *= 1000.0;
   Position.z  = -30.0;
   

   vTexCoord   = Position.xyz * scale.xyz;
   vViewVec    = Position.xyz - view_position.xyz;
   vViewVec.z *=1.0;
   vNormal     = gl_Normal;   

   gl_Position = gl_ModelViewProjectionMatrix * Position;
}

And the fragment shader looks like this:
uniform sampler3D Noise;
uniform samplerCube skyBox;

uniform float time_0_X;
uniform vec4  waterColor;
uniform float fadeExp;
uniform float fadeBias;
uniform float noiseSpeed;
uniform vec4  scale;

uniform float waveSpeed;

varying vec3 vTexCoord;
varying vec3 vNormal;
varying vec3 vViewVec;


void main(void)
{
   vec3 tcoord = vTexCoord;
   tcoord.x += waveSpeed  * time_0_X;
   tcoord.z += noiseSpeed * time_0_X;

   vec4 noisy = texture3D(Noise, tcoord);

   // Signed noise 
   vec3 bump = 2.0 * noisy.xyz - 1.0;
   bump.xy *= 0.15;
   
   // Make sure the normal always points upwards
   bump.z = 0.8 * abs(bump.z) + 0.2;
   
   // Offset the surface normal with the bump
   bump = normalize(vNormal + bump);

   // Find the reflection vector
   vec3 reflVec = reflect(vViewVec, bump);
   vec4 refl = textureCube(skyBox, reflVec.yzx);

   float lrp = 1.0 - dot(-normalize(vViewVec), bump);

   // Interpolate between the water color and reflection
   gl_FragColor = mix(waterColor, refl, clamp(fadeBias + pow(lrp, fadeExp),0.0, 1.0));
}

This is what I have so far:
#ifdef WIN32
#include <windows.h>
#pragma comment(lib, "OpenGL32.lib")
#pragma comment(lib, "GlU32.lib")
#pragma comment(lib, "SDL.lib")
#pragma comment(lib, "SDLmain.lib")
#pragma comment(lib, "glew32.lib")
#endif

#include <iostream>
#include "glew.h"
#include "SDL.h"
#include "textfile.h"

GLhandleARB p,f,v;

void PrintInfoLog(GLhandleARB obj)
{
    int infologLength = 0;
    int charsWritten  = 0;
    char *infoLog;

	glGetObjectParameterivARB(obj, GL_OBJECT_INFO_LOG_LENGTH_ARB,
                                         &infologLength);

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

void SetShaders() {
	char *vs, *fs;

	v = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
	f = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);

	vs = textFileRead("Ocean.vert");
	fs = textFileRead("Ocean.frag");

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

	glShaderSourceARB(v, 1, &vv, NULL);
	glShaderSourceARB(f, 1, &ff, NULL);

	free(vs);
	free(fs);

	glCompileShaderARB(v);
	glCompileShaderARB(f);

	PrintInfoLog(v);
	PrintInfoLog(f);

	p = glCreateProgramObjectARB();

	glAttachObjectARB(p,v);
	glAttachObjectARB(p,f);

	glLinkProgramARB(p);
	PrintInfoLog(p);

	glUseProgramObjectARB(p);

	GLint loc1, loc2, loc3, loc4, loc5, loc6, loc7, loc8;
	
	float view_position[4] = {0.0f, 0.0f, 0.0f, 1.0f};
	float scale[4] = {0.01001f, 0.00554f, 0.01f, 1.0f};
    
	float time_0_X = 0.0f;
	float waterColor[4] = {0.195489f, 0.345865f, 0.684210f, 1.0f};
	float fadeExp = 6.08f;
	float fadeBias = 0.3f;
	float noiseSpeed = 0.18f;
	float waveSpeed = 0.34f;

	loc1 = glGetUniformLocationARB(p, "view_position");
	glUniform4fARB(loc1, view_position[0], view_position[1], view_position[2], view_position[3]);

	loc2 = glGetUniformLocationARB(p, "scale");
	glUniform4fARB(loc2, scale[0], scale[1], scale[2], scale[3]);

	loc3 = glGetUniformLocationARB(p, "time_0_X");
	glUniform1fARB(loc3, time_0_X);

	loc4 = glGetUniformLocationARB(p, "waterColor");
	glUniform4fARB(loc4, waterColor[0], waterColor[1], waterColor[2], waterColor[3]);

	loc5 = glGetUniformLocationARB(p, "fadeExp");
	glUniform1fARB(loc5, fadeExp);

	loc6 = glGetUniformLocationARB(p, "fadeBias");
	glUniform1fARB(loc6, fadeBias);

	loc7 = glGetUniformLocationARB(p, "noiseSpeed");
	glUniform1fARB(loc7, noiseSpeed);

	loc8 = glGetUniformLocationARB(p, "waveSpeed");
	glUniform1fARB(loc8, waveSpeed);
}

bool SetupEnvironment() {
	if (SDL_Init(SDL_INIT_VIDEO) < 0)
		return false;
  
	if (SDL_SetVideoMode(800, 600, 16, SDL_OPENGL | SDL_DOUBLEBUF | SDL_HWSURFACE) == 0)
		return false;

	SDL_WM_SetCaption("Shader Test", NULL);
	glViewport(0, 0, 800, 600);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(45.0f, 800.0f / 600.0f, 0.1f, 100.0f);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
	glShadeModel(GL_SMOOTH);
	glClearDepth(1.0f);
	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LEQUAL);
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
	glEnable(GL_CULL_FACE);
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

	glewInit();
	if (GLEW_ARB_vertex_shader && GLEW_ARB_fragment_shader)
		std::cout << "Ready for GLSL.\n";
	else {
		std::cout << "Cannot use shaders.\n";
		SDL_Quit();
	}

	SetShaders();
	return true;
}

int main(int argc, char **argv) {
	if (!SetupEnvironment()) {
		std::cout << "Unable to setup the environment: " << SDL_GetError() << "\n";
		SDL_Quit();
	}

	bool running = true;
	SDL_Event event;

	while (running) {
		if (SDL_PollEvent(&event)) {
			switch (event.type) {
				case SDL_QUIT:
					running = false;
					break;
				case SDL_KEYDOWN:
					if (event.key.keysym.sym == SDLK_ESCAPE)
						running = false;
					break;
				default:
					break;
			}
		}

		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
		glLoadIdentity();
		gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

		glTranslatef(0.0, 0.0, 0.0);
		
		glPushMatrix();
		glBegin(GL_QUADS);
		glVertex3f(5.0f, -1.0f, 3.0f);
		glVertex3f(5.0f, -1.0f, -7.0f);
		glVertex3f(-5.0f, -1.0f, -7.0f);
		glVertex3f(-5.0f, -1.0f, 3.0f);
		glEnd();
		glPopMatrix();

		SDL_GL_SwapBuffers();
	}

	return 0;
}

Also, I'd appreciate it if anyone could point out any omissions that I have made.

Share this post


Link to post
Share on other sites
I don't see you setting the sampler uniforms anywhere?

It's really very simple; going by your code and using 2 texture units:

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_3D, noiseTex);
loc_Noise = glGetUniformLocationARB(p, "Noise");
glUniform1iARB(loc_Noise, 0);

glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_CUBE_MAP, skyBoxTex);
loc_skyBox = glGetUniformLocationARB(p, "Noise");
glUniform1iARB(loc_skyBox, 1);

Share this post


Link to post
Share on other sites
Thanks for the info. I think I'm now implementing all the uniform variables correctly but nothing is being displayed. I'm obviously missing something. Please help, it's driving me scatty, I've been trying to get this bugger to work for a week!

This is what I've got, now:


#ifdef WIN32
#include <windows.h>
#pragma comment(lib, "OpenGL32.lib")
#pragma comment(lib, "GlU32.lib")
#pragma comment(lib, "SDL.lib")
#pragma comment(lib, "SDLmain.lib")
#pragma comment(lib, "glew32.lib")
#pragma comment(lib, "DevIL.lib")
#endif

#include <iostream>
#include "glew.h"
#include "SDL.h"
#include <IL/il.h>

GLhandleARB p,f,v;
GLuint noiseTexture, skyBoxTexture;
ILuint noiseImage, skyBoxImage;

char *textFileRead(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);
}
}
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);
}

void PrintInfoLog(GLhandleARB obj)
{
int infologLength = 0;
int charsWritten = 0;
char *infoLog;

glGetObjectParameterivARB(obj, GL_OBJECT_INFO_LOG_LENGTH_ARB, &infologLength);

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

void SetShaders() {
char *vs, *fs;

v = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
f = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);

vs = textFileRead("Ocean.vert");
fs = textFileRead("Ocean.frag");

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

glShaderSourceARB(v, 1, &vv, NULL);
glShaderSourceARB(f, 1, &ff, NULL);

free(vs);
free(fs);

glCompileShaderARB(v);
glCompileShaderARB(f);

PrintInfoLog(v);
PrintInfoLog(f);

p = glCreateProgramObjectARB();

glAttachObjectARB(p,v);
glAttachObjectARB(p,f);

glLinkProgramARB(p);
PrintInfoLog(p);

glUseProgramObjectARB(p);

GLint loc1, loc2, loc3, loc4, loc5, loc6, loc7, loc8, loc9, loc10;

float view_position[4] = {0.0f, 0.0f, 0.0f, 1.0f};
float scale[4] = {0.01001f, 0.00554f, 0.01f, 1.0f};

float time_0_X = 1.0f;
float waterColor[4] = {0.195489f, 0.345865f, 0.684210f, 1.0f};
float fadeExp = 6.08f;
float fadeBias = 0.3f;
float noiseSpeed = 0.18f;
float waveSpeed = 0.34f;

loc1 = glGetUniformLocationARB(p, "view_position");
glUniform4fARB(loc1, view_position[0], view_position[1], view_position[2], view_position[3]);

loc2 = glGetUniformLocationARB(p, "scale");
glUniform4fARB(loc2, scale[0], scale[1], scale[2], scale[3]);

loc3 = glGetUniformLocationARB(p, "time_0_X");
glUniform1fARB(loc3, time_0_X);

loc4 = glGetUniformLocationARB(p, "waterColor");
glUniform4fARB(loc4, waterColor[0], waterColor[1], waterColor[2], waterColor[3]);

loc5 = glGetUniformLocationARB(p, "fadeExp");
glUniform1fARB(loc5, fadeExp);

loc6 = glGetUniformLocationARB(p, "fadeBias");
glUniform1fARB(loc6, fadeBias);

loc7 = glGetUniformLocationARB(p, "noiseSpeed");
glUniform1fARB(loc7, noiseSpeed);

loc8 = glGetUniformLocationARB(p, "waveSpeed");
glUniform1fARB(loc8, waveSpeed);

ilGenImages(1, &noiseImage);
ilBindImage(noiseImage);
ilLoadImage("NoiseVolume.dds");
glGenTextures(1, &noiseTexture);
glBindTexture(GL_TEXTURE_3D, noiseTexture);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage3D(GL_TEXTURE_3D, 0, ilGetInteger(IL_IMAGE_BPP), ilGetInteger(IL_IMAGE_WIDTH),
ilGetInteger(IL_IMAGE_HEIGHT), ilGetInteger(IL_IMAGE_DEPTH), 0, ilGetInteger(IL_IMAGE_FORMAT),
GL_UNSIGNED_BYTE, ilGetData());

ilGenImages(1, &skyBoxImage);
ilBindImage(skyBoxImage);
ilLoadImage("Snow.dds");
glGenTextures(1, &skyBoxTexture);
glBindTexture(GL_TEXTURE_CUBE_MAP, skyBoxTexture);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, ilGetInteger(IL_IMAGE_BPP), ilGetInteger(IL_IMAGE_WIDTH),
ilGetInteger(IL_IMAGE_HEIGHT),0, ilGetInteger(IL_IMAGE_FORMAT), GL_UNSIGNED_BYTE, ilGetData());
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, ilGetInteger(IL_IMAGE_BPP), ilGetInteger(IL_IMAGE_WIDTH),
ilGetInteger(IL_IMAGE_HEIGHT),0, ilGetInteger(IL_IMAGE_FORMAT), GL_UNSIGNED_BYTE, ilGetData());

glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, ilGetInteger(IL_IMAGE_BPP), ilGetInteger(IL_IMAGE_WIDTH),
ilGetInteger(IL_IMAGE_HEIGHT),0, ilGetInteger(IL_IMAGE_FORMAT), GL_UNSIGNED_BYTE, ilGetData());
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, ilGetInteger(IL_IMAGE_BPP), ilGetInteger(IL_IMAGE_WIDTH),
ilGetInteger(IL_IMAGE_HEIGHT),0, ilGetInteger(IL_IMAGE_FORMAT), GL_UNSIGNED_BYTE, ilGetData());

glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, ilGetInteger(IL_IMAGE_BPP), ilGetInteger(IL_IMAGE_WIDTH),
ilGetInteger(IL_IMAGE_HEIGHT),0, ilGetInteger(IL_IMAGE_FORMAT), GL_UNSIGNED_BYTE, ilGetData());
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, ilGetInteger(IL_IMAGE_BPP), ilGetInteger(IL_IMAGE_WIDTH),
ilGetInteger(IL_IMAGE_HEIGHT),0, ilGetInteger(IL_IMAGE_FORMAT), GL_UNSIGNED_BYTE, ilGetData());

glEnable(GL_TEXTURE_3D);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_3D, noiseTexture);
loc9 = glGetUniformLocationARB(p, "Noise");
glUniform1iARB(loc9, 0);

glEnable(GL_TEXTURE_CUBE_MAP);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_CUBE_MAP, skyBoxTexture);
loc10 = glGetUniformLocationARB(p, "skyBox");
glUniform1iARB(loc10, 1);
}

bool SetupEnvironment() {
if (SDL_Init(SDL_INIT_VIDEO) < 0)
return false;

if (SDL_SetVideoMode(800, 600, 16, SDL_OPENGL | SDL_DOUBLEBUF | SDL_HWSURFACE) == 0)
return false;

SDL_WM_SetCaption("Shader Test", NULL);
glViewport(0, 0, 800, 600);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, 800.0f / 600.0f, 0.1f, 100.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glShadeModel(GL_SMOOTH);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
glEnable(GL_CULL_FACE);

glewInit();
if (GLEW_ARB_vertex_shader && GLEW_ARB_fragment_shader)
std::cout << "Ready for GLSL.\n";
else {
std::cout << "Cannot use shaders.\n";
SDL_Quit();
}

ilInit();

SetShaders();
return true;
}

int main(int argc, char **argv) {
if (!SetupEnvironment()) {
std::cout << "Unable to setup the environment: " << SDL_GetError() << "\n";
SDL_Quit();
}

bool running = true;
SDL_Event event;

while (running) {
if (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_QUIT:
running = false;
break;
case SDL_KEYDOWN:
if (event.key.keysym.sym == SDLK_ESCAPE)
running = false;
break;
default:
break;
}
}

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

glBegin(GL_QUADS);
glVertex3f(5.0f, -1.0f, 3.0f);
glVertex3f(5.0f, -1.0f, -7.0f);
glVertex3f(-5.0f, -1.0f, -7.0f);
glVertex3f(-5.0f, -1.0f, 3.0f);
glEnd();

SDL_GL_SwapBuffers();
}

return 0;
}


Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this