Loading Shader Code from Files

Started by
4 comments, last by D.V.D 11 years, 5 months ago
I was following some online tutorials about opengl and shader code and I encoutered a problem. They compiled their shader code from const char* variables but I wanted to find out how to do the same thing but reading the shaders from files. The problem I am having is this, when I run my program, I get no error messages from visual studio 2010 but in the console, I get this error message:

Error compiling shader type 35633: '0<1> : error c0000: syntax error, unexpected, $undefined at token "<undefined>"

I ran the same shader code before when it was in a string and it worked just fine. Im reading the file with this function:

[source lang="cpp"]const char* readShaderFile(const std::string fileName)
{
std::ifstream shaderFile( fileName.c_str() );

// find the file size
shaderFile.seekg(0,std::ios::end);
std::streampos length = shaderFile.tellg();
shaderFile.seekg(0,std::ios::beg);

// read whole file into a vector:
std::vector<char> buffer(length);
shaderFile.read(&buffer[0],length);

// convert to GLchar
const char* Shader = (std::string( buffer.begin(), buffer.end() )).c_str();

// return the shader string
return Shader;
}[/source]

and my shader code is here:

[source lang="cpp"]#version 330

in vec2 TexCoord0;
in vec3 Normal0;

out vec4 FragColor;

struct DirectionalLight
{
vec3 Color;
float AmbientIntensity;
float DiffuseIntensity;
vec3 Direction;
};

uniform DirectionalLight gDirectionalLight;
//uniform sampler2D gSampler;

void main()
{
vec4 AmbientColor = vec4(gDirectionalLight.Color, 1.0f) *
gDirectionalLight.AmbientIntensity;

float DiffuseFactor = dot(normalize(Normal0), -gDirectionalLight.Direction);

vec4 DiffuseColor;

if (DiffuseFactor > 0) {
DiffuseColor = vec4(gDirectionalLight.Color, 1.0f) *
gDirectionalLight.DiffuseIntensity *
DiffuseFactor;
}
else {
DiffuseColor = vec4(0, 0, 0, 0);
}

//FragColor = texture2D(gSampler, TexCoord0.xy) * (AmbientColor + DiffuseColor);
FragColor = vec4(1.0,0.0,0.0,1.0)*(AmbientColor + DiffuseColor);
}[/source]
Advertisement
You have just returned a pointer to garbage from within [font=courier new,courier,monospace]readShaderFile()[/font].
[font=courier new,courier,monospace]buffer[/font] is a local variable and then you use it to create yet another temporary copy. It is destroyed on the next statement and with it the memory it has allocated. If that code ever worked it would only be luck.
You can’t return a pointer to its buffer. Either return the buffer itself (not recommended) or pass a buffer to be used to hold the return (and return a reference to that).
As in:

std::string & readShaderFile(const std::string & fileName, std::string & buffer)
{
// Load file into buffer.
// Return buffer.
return buffer;
}



Notice also that [font=courier new,courier,monospace]fileName[/font] is now a reference. You should never pass std::string or other structures by copy.
Also notice that buffer is passed by reference. Not only is this once again a good idea, it is 100% necessary for this to work properly.


L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

Moving this to the OpenGL forum...
My bad I thought I posted in the GL forum.

Okay but what do I do with the buffer if I want to compile the shader? My compile function only takes GLenum ShaderType and const GLchar* pShaderText. Since the buffer holds the text for the object, do I convert it to a GLchar? My compile code looks like this:

EDIT: Woops I thought the buffer was of class buffer not std::string. I think I understand this better now, Ill simply convert it to GLchar and see if it works.

EDIT2: Woops, Im still confused with how to do this, any help?

[source lang="cpp"]bool ShaderManager::AddShaderFile(GLenum ShaderType, const GLchar* pShaderText)
{
GLuint ShaderObj = glCreateShader(ShaderType);

if (ShaderObj == 0) {
fprintf(stderr, "Error creating shader type %d\n", ShaderType);
Sleep(10000);
return false;
}

// Save the shader object - will be deleted in the destructor
shaderObjList.push_back(ShaderObj);

const GLchar* p[1];
p[0] = pShaderText;
GLint Lengths[1];
Lengths[0]= strlen(pShaderText);
glShaderSource(ShaderObj, 1, p, Lengths);

glCompileShader(ShaderObj);

GLint success;
glGetShaderiv(ShaderObj, GL_COMPILE_STATUS, &amp;success);

if (!success) {
GLchar InfoLog[1024];
glGetShaderInfoLog(ShaderObj, 1024, NULL, InfoLog);
fprintf(stderr, "Error compiling shader type %d: '%s'\n", ShaderType, InfoLog);
Sleep(10000);
return false;
}

glAttachShader(shaderProgram, ShaderObj);

return true;
}[/source]
you need to save the Shader object somehow smile.png otherwise, the program will be lost
you'll need to link the program together

lets say your function returns 0 if it fails, and non-zero if it returns a valid shader object!
then:
[source lang="cpp"]void CreateShader(file_v, file_f)
{
GLuint vertex = LoadShader(file_v, GL_VERTEX_SHADER_ARB);
GLuint frag = LoadShader(file_f, GL_FRAGMENT_SHADER_ARB);
GLuint prog = glCreateProgram();
glAttachShader(vertex);
glAttachShader(frag);

// bind your attrib locations here, either directly or through another function, but here is an example:
switch(prog) {
case shaders.dummy:
glBindAttribLocation(prog, 0, "in_vertex");
glBindAttribLocation(prog, 1, "in_texture");
break;
}

// link program
glLinkProgram(prog);
// check for errors!
// bind program, and set some common uniforms
glUseProgram(prog);

// set uniform locations here that never changes, either directly or through another function, example:
GLint location = glGetUniformLocation(prog, "texture");
if (location+1) glUniform1i(location, 0);
// remember to check for glGetError through the whole ordeal!
// finally close program
glUseProgram(null);

}
[/source]



note: only an example! i hope this helps you
edit: i see now that you do what is needed, in the loader
but, you can try setting null for length in glShaderSource!
see: http://content.gpwiki.org/index.php/OpenGL:Codes:Simple_GLSL_example

also, shader source is a glchar ptr ptr
so GLchar* p[1]; p[0] = &shaderSource;
glShaderSource (shader, 1, (glchar**) p, null);
Hmmm ill check the link out and hoepfully reply by tomorrow, i've been really busy with physics homework lately -.-. Ill edit this post by tomorrow!!

This topic is closed to new replies.

Advertisement