Jump to content
  • Advertisement
Sign in to follow this  
redneon

OpenGL Trouble implementing RenderMonkey's ocean shader

This topic is 4484 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

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
Advertisement
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
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!