Sign in to follow this  
zaneski13

GLSL Not Working In App?

Recommended Posts

zaneski13    104
I've had problems like this in the past am I'm getting sick and tierd of not knowing how to correct my app. The problem is that when I try to implement shaders in my app they work only some of the time. A few weeks ago I made a simple level editor / game program which both had the same exact shader.h and shader.cpp source. When I run the level editor program the shaders work while when I run the game program the shaders magicly don't work :(. I'm implementing lighting in my game engine so I've been messing around with glsl. I made a very simple shader which takes in 4 uniform values LightColor, LightRadius, LightPosition, DiffuseTex. I'm not even using normals to calculate lighting, its just a very basic glsl program.

//VERTEX PROGRAM


varying vec2 texCoord;
varying vec3 vertPos;

void main(void)
{
   texCoord = gl_MultiTexCoord0.xy;
   
   
   gl_Position = ftransform();
   vertPos = gl_Position.xyz;
}


//FRAGMENT PROGRAM

uniform sampler2D diffuseTex;
uniform vec3 LightPosition;
uniform vec4 LightColor;
uniform float LightRadius;

varying vec2 texCoord;
varying vec3 vertPos;

void main(void)
{
   vec4 diffuseColor = texture2D(diffuseTex, texCoord);
   
   float percentLit = 1.0f - (distance(LightPosition, vertPos) / LightRadius);
   
   gl_FragColor = diffuseColor * percentLit * LightColor;
}




So its a pretty basic shader, and yet, it doesn't work in my application. A few months ago I made a shader class and it seems to be functioning. (In some apps, not in others) Here's my shader class

// HEADER FILE
#ifndef SHADER_H
#define SHADER_H

#include <GL/glew.h>

#include <string>
#include <fstream>
using std::string;

class Shader
{
public:
	Shader( string vertexFile, string fragFile );

	void useShader(void);

	static void disableShader(void);

	void setAttribute1i( string name, int x );
	void setAttribute2i( string name, int x, int y );
	void setAttribute3i( string name, int x, int y, int z );
	void setAttribute4i( string name, int x, int y, int z, int w );

	void setAttribute1f( string name, float x );
	void setAttribute2f( string name, float x, float y );
	void setAttribute3f( string name, float x, float y, float z );
	void setAttribute4f( string name, float x, float y, float z, float w );

	void setAttributeMat4( string name, float mat4[16] );

private:
	char * readFile(const char *fn);
private:
	GLhandleARB vertexShader;
	GLhandleARB fragmentShader;
	GLhandleARB program;
};

#endif


//CPP FILE


#include "shader.h"

Shader::Shader( string vertexFile, string fragFile )
{
	vertexShader = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
	fragmentShader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);

		const char *vv = readFile(vertexFile.data());
		const char *ff = readFile(fragFile.data());

		if ( vv != NULL && ff != NULL )
		{
			glShaderSourceARB( vertexShader, 1, &vv, NULL );
			glShaderSourceARB( fragmentShader, 1, &ff, NULL );

			delete [] vv;
			delete [] ff;

			glCompileShaderARB(vertexShader);
			glCompileShaderARB(fragmentShader);

			program = glCreateProgramObjectARB();

			glAttachObjectARB(program, vertexShader); //attach shader into program
			glAttachObjectARB(program, fragmentShader);

			glLinkProgramARB(program);
		}
}

void Shader::useShader(void)
{
	glUseProgramObjectARB(program);
}

void Shader::disableShader(void)
{
	glUseProgramObjectARB(NULL);
}

void Shader::setAttribute1i( string name, int x )
{
	glUniform1iARB( glGetUniformLocationARB(program, name.data()), x );
}
void Shader::setAttribute2i( string name, int x, int y )
{
	glUniform2iARB( glGetUniformLocationARB(program, name.data()), x, y );
}
void Shader::setAttribute3i( string name, int x, int y, int z )
{
	glUniform3iARB( glGetUniformLocationARB(program, name.data()), x, y, z );
}
void Shader::setAttribute4i( string name, int x, int y, int z, int w )
{
	glUniform4iARB( glGetUniformLocationARB(program, name.data()), x, y, z, w );
}


void Shader::setAttribute1f( string name, float x )
{
	glUniform1fARB( glGetUniformLocationARB(program, name.data()), x );
}
void Shader::setAttribute2f( string name, float x, float y )
{
	glUniform2fARB( glGetUniformLocationARB(program, name.data()), x, y );
}
void Shader::setAttribute3f( string name, float x, float y, float z )
{
	glUniform3fARB( glGetUniformLocationARB(program, name.data()), x, y, z );
}
void Shader::setAttribute4f( string name, float x, float y, float z, float w )
{
	glUniform4fARB( glGetUniformLocationARB(program, name.data()), x, y, z, w );
}

void Shader::setAttributeMat4( string name, float mat4[16] )
{
	glUniformMatrix4fvARB( glGetUniformLocationARB(program, name.data()), 16, false, mat4 );
}

//TODO PASS ARRAYS TO SHADER

//glUniform3fvARB(  this will pass an array of values to the shader

char * Shader::readFile(const char *fn)
{
	int length;
	char *buffer;

	std::ifstream file;

	file.open(fn, std::ios::binary);

	if ( file.is_open() == false )
		return NULL;

	file.seekg(0, std::ios::end);
	length = file.tellg();
	file.seekg(0, std::ios::beg);

	buffer = new char[length];

	file.read( buffer, length );

	file.close();

	return buffer;
}




It looks like it should work, at least to me it does. In my main program I'm Initializing the window and the shaders, then I'm starting the main loop and in there I handle events and render. I'll show you my InitShaders and my render function (cut down though)


//INIT SHADERS

if ( GLEW_ARB_vertex_shader && GLEW_ARB_fragment_shader ) //if shaders work
	{
		//setup shaders
		lightShader = new Shader("lightShader.vert", "lightShader.frag");
		lightShader->useShader();
		lightShader->setAttribute1i("diffuseTex", 0);
		lightShader->setAttribute3f("LightPosition", 0.0f, 3.0f, 10.0f);
		lightShader->setAttribute4f("LightColor", 1.0f, 1.0f, 1.0f, 1.0f);
		lightShader->setAttribute1f("LightRadius", 0.5f);

		glActiveTextureARB(GL_TEXTURE0_ARB);
		glEnable(GL_TEXTURE_2D);
	}



//RENDER THE SCENE

lightShader->useShader();

	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	cam->Update(keystate); //this just updates the camera position and rotation
	cam->SetMatrix();  //this sets up the projection and modelview matrix


	glMatrixMode(GL_MODELVIEW);

	glEnable(GL_TEXTURE_2D);

	

	//draw the carpet
	carpet->bindTexture();

	glBegin(GL_QUADS);

	//texCoords and Vertices

	glEnd();


	//draw the walls
	wall->bindTexture();

	glBegin(GL_QUADS);

	//texCoords and Vertices

	glEnd();


	//draw ceiling
	ceiling->bindTexture();

        glBegin(GL_QUADS);

	//texCoords and Vertices

	glEnd();

	lightShader->disableShader();

	glFlush();
	SDL_GL_SwapBuffers();




So I'm not sure what the problem is. As I said before, I've had this problem in the past and this problem only happens in some apps while other apps run fine. And the apps that run fine have the same exact shader class source files so that makes everything really confusing. However what you could draw from that I guess is that there's nothing wrong with the shader class, just the way I'm using it. Hopefully you can help me solve this headache of a problem. Thanks! [Edited by - zaneski13 on February 18, 2010 2:05:37 AM]

Share this post


Link to post
Share on other sites
aryx    402
Upon first glance, most things appear fine. I'll bring up a couple of things (which may or may not be causing your problem):
  1. You give a NULL pointer for the lengths array in glShaderSourceARB, but your strings returned from readFile aren't null terminated. Could this be an issue?
  2. I'd suggest clamping percentLit to a [0,1] range in your fragment shader
What is your actual problem though. You mention it does not work, but that's it. Knowing what shows up on screen might be helpful.

Share this post


Link to post
Share on other sites
zaneski13    104
well, I get the same results as I would if I had no lights in the scene. Its fully lit. Its as if I said glUseProgramObjectARB(NULL);


Heres a screenshot anyway

Share this post


Link to post
Share on other sites
aryx    402
Ahh, okay. I didn't know if you meant something else by "they don't work". So things aren't being lit. I notice the radius of your light is pretty small, but that all depends on your geometry (i.e., I'm guessing the room you display is roughly a unit cube?).

About the only help I can offer is to start trying out some shader debugging. For example, set gl_FragColor to things like vec4(1, 1, 1, 1)*distance(LightPosition, vertPos) / LightRadius and vec4(vertPos, 1.0) to see if the right values are showing up. To make sure your shader is even properly executing, you could even try outputting a solid red color for everything.

I guess if the exact same code is working then I'm out of ideas. Maybe someone more experienced will come along and help you. Sorry I couldn't be of more help!

Share this post


Link to post
Share on other sites
zaneski13    104
So I got it to work without changing any code? Basically I changed the shader to output the color white and it did just that. I then changed it back to what it originally was and it worked. So I have a basic light in my scene. yay. Its just kind of annoying because I still can't figure out why in my level editor / game program(s) worked some of the time. The level editor program had shaders working 100 % of the time while the game's shaders work only about 5 % of the time, which is weird because how does it sometimes work and then sometimes not work? The really confusing part is both the programs have the same shader class and the same exact glsl shader code. I've stopped that project so I don't really care anymore but I'd still like to know the source of the problem. Like the current program for example, at first it didn't work but when I commented out the line of code that said gl_FragColor = diffuseColor * shade * lightColor; and added the new line gl_FragColor = vec4(1.0f, 1.0f, 1.0f, 1.0f); everything worked. Then when I got rid of the gl_FragColor = vec4(1.0f, 1.0f, 1.0f, 1.0f); line and commented out the gl_FragColor = diffuseColor * shade * lightColor; line everything worked fine. Its very strange!

Well anyway, now that this current shader is working, and hopefully will continue working, I noticed that the light moves around when my camera moves. The camera directly modifies the modelview matrix so multiplying the LightPosition by the modelviewmatrix doesn't make the light stay where it is. How should I make the light stay where it is?

Share this post


Link to post
Share on other sites
aryx    402
Glad to hear that it's working now. To keep the light "static" you could multiply its position by the camera's view matrix so that both vertPos and LightPosition will be in view space. Note that ftransform will do projection too, which you don't want. You could do something like vertPos = (gl_ModelViewMatrix * gl_Vertex).xyz. To make LightPosition be in view space also by multiplying the light's position by the camera's transformation matrix. Best to only do this when the camera's view changes.

Another option that would require no adjustment to the light's position is to have a uniform (in your vertex shader) which specifies the transformation matrix that brings your models/quads/etc into "world" space. That way you only need to multiply vertPos by that matrix and you're done. The light's position is (probably) already in world space, hence no need to transform it.

Share this post


Link to post
Share on other sites
zaneski13    104
I wonder if the problem is that I'm editing the shader source in notepad at times. Perhaps notepad is doing something weird when I indent, because when I use WordPad the shader works after I make small edits. (assuming the code is correct)

Share this post


Link to post
Share on other sites
zaneski13    104
Now somethings really wrong. I just had lights working before, even 2 lights in a loop with arrays, which I problems with before, and now I can't even get a basic color shader to work.

Heres my shader code



//VERT

const int NUM_LIGHTS = 2;

uniform vec3 LightPosition[NUM_LIGHTS];

uniform mat4 CameraViewMatrix;
varying vec2 texCoord;
varying vec3 vertPos;
varying vec3 lightPos[NUM_LIGHTS];

void main(void)
{
texCoord = gl_MultiTexCoord0.xy;


for ( int i = 0; i < NUM_LIGHTS; i++ )
{
lightPos[i] = (vec4(LightPosition[i],1.0f) * CameraViewMatrix).xyz;
}

gl_Position = ftransform();

vertPos = (gl_Vertex* gl_ModelViewMatrix).xyz;
}


//FRAG

const int NUM_LIGHTS = 2;

uniform sampler2D diffuseTex;

uniform vec4 LightColor[NUM_LIGHTS];
uniform float LightRadius[NUM_LIGHTS];

varying vec2 texCoord;
varying vec3 vertPos;
varying vec3 lightPos[NUM_LIGHTS];

void main(void)
{
vec4 diffuseColor = texture2D(diffuseTex, texCoord);

vec4 colorAcum = vec4(0.0f, 0.0f, 0.0f, 1.0f);



float percentLit;


for ( int i = 0; i < NUM_LIGHTS; i++ )
{
percentLit = 1.0f - (distance(lightPos[i], vertPos) / LightRadius[i]);
if ( percentLit < 0.0f )
percentLit = 0.0f;

colorAcum += (vec4(percentLit,percentLit,percentLit,1.0f) * LightColor[i]);

}

if ( colorAcum.r > 1.0f )
colorAcum.r = 1.0f;
if ( colorAcum.g > 1.0f )
colorAcum.g = 1.0f;
if ( colorAcum.b > 1.0f )
colorAcum.b = 1.0f;
if ( colorAcum.a > 1.0f )
colorAcum.a = 1.0f;

if ( colorAcum.r < 0.3f && colorAcum.g < 0.3f && colorAcum.b < 0.3f )
colorAcum = vec4(0.3f, 0.3f, 0.3f, 1.0f);


gl_FragColor = diffuseColor * colorAcum;

}





In my app I have the data set up correctly. IE: position array has 6 elements.
I even went into my frag shader and set the frag color output to be white and the scene looked exactly the same as the screenshot I posted before. Nothing was lit.

Share this post


Link to post
Share on other sites
zaneski13    104
So heres what I've found


this shader works



//VERT

const int NUM_LIGHTS = 2;

uniform vec3 LightPosition[NUM_LIGHTS];

uniform mat4 CameraViewMatrix;
varying vec2 texCoord;
varying vec3 vertPos;
varying vec3 lightPos[NUM_LIGHTS];

void main(void)
{
texCoord = gl_MultiTexCoord0.xy;


lightPos[0] = (vec4(LightPosition[0],1.0f) * CameraViewMatrix).xyz;
lightPos[1] = (vec4(LightPosition[1],1.0f) * CameraViewMatrix).xyz;

gl_Position = ftransform();

vertPos = (gl_Vertex* gl_ModelViewMatrix).xyz;
}


//FRAG


const int NUM_LIGHTS = 2;

uniform sampler2D diffuseTex;

uniform vec4 LightColor[NUM_LIGHTS];
uniform float LightRadius[NUM_LIGHTS];

varying vec2 texCoord;
varying vec3 vertPos;
varying vec3 lightPos[NUM_LIGHTS];

void main(void)
{
vec4 diffuseColor = texture2D(diffuseTex, texCoord);

vec4 colorAcum = vec4(0.0f, 0.0f, 0.0f, 1.0f);



float percentLit;


//light 1
percentLit = 1.0f - (distance(lightPos[0], vertPos) / LightRadius[0]);
if ( percentLit < 0.0f )
percentLit = 0.0f;

colorAcum += (vec4(percentLit,percentLit,percentLit,1.0f) * LightColor[0]);

//light 2
percentLit = 1.0f - (distance(lightPos[1], vertPos) / LightRadius[1]);
if ( percentLit < 0.0f )
percentLit = 0.0f;

colorAcum += (vec4(percentLit,percentLit,percentLit,1.0f) * LightColor[1]);



if ( colorAcum.r < 0.3f && colorAcum.g < 0.3f && colorAcum.b < 0.3f )
colorAcum = vec4(0.3f, 0.3f, 0.3f, 1.0f);


gl_FragColor = diffuseColor * colorAcum;
}







While this one doesn't




//VERT

const int NUM_LIGHTS = 2;

uniform vec3 LightPosition[NUM_LIGHTS];

uniform mat4 CameraViewMatrix;
varying vec2 texCoord;
varying vec3 vertPos;
varying vec3 lightPos[NUM_LIGHTS];

void main(void)
{
texCoord = gl_MultiTexCoord0.xy;


for ( int i = 0; i < NUM_LIGHTS; i++ )
{
lightPos[i] = (vec4(LightPosition[i],1.0f) * CameraViewMatrix).xyz;
}

gl_Position = ftransform();

vertPos = (gl_Vertex* gl_ModelViewMatrix).xyz;
}


//FRAG

const int NUM_LIGHTS = 2;

uniform sampler2D diffuseTex;

uniform vec4 LightColor[NUM_LIGHTS];
uniform float LightRadius[NUM_LIGHTS];

varying vec2 texCoord;
varying vec3 vertPos;
varying vec3 lightPos[NUM_LIGHTS];

void main(void)
{
vec4 diffuseColor = texture2D(diffuseTex, texCoord);

vec4 colorAcum = vec4(0.0f, 0.0f, 0.0f, 1.0f);



float percentLit;


for ( int i = 0; i < NUM_LIGHTS; i++ )
{
percentLit = 1.0f - (distance(lightPos[i], vertPos) / LightRadius[i]);
if ( percentLit < 0.0f )
percentLit = 0.0f;

colorAcum += (vec4(percentLit,percentLit,percentLit,1.0f) * LightColor[i]);

}

if ( colorAcum.r > 1.0f )
colorAcum.r = 1.0f;
if ( colorAcum.g > 1.0f )
colorAcum.g = 1.0f;
if ( colorAcum.b > 1.0f )
colorAcum.b = 1.0f;
if ( colorAcum.a > 1.0f )
colorAcum.a = 1.0f;

if ( colorAcum.r < 0.3f && colorAcum.g < 0.3f && colorAcum.b < 0.3f )
colorAcum = vec4(0.3f, 0.3f, 0.3f, 1.0f);


gl_FragColor = diffuseColor * colorAcum;

}







And yet the second one compiles fine in render monkey

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