Jump to content

View more

Image of the Day

Adding some finishing touches...
Follow us for more
#screenshotsaturday #indiedev... by #MakeGoodGames https://t.co/Otbwywbm3a
IOTD | Top Screenshots

The latest, straight to your Inbox.

Subscribe to GameDev.net Direct to receive the latest updates and exclusive content.

Sign up now

Loading Shader Code from Files

4: Adsense

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
5 replies to this topic

#1 D.V.D   Members   


Posted 12 November 2012 - 05:33 PM

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]

#2 L. Spiro   Members   


Posted 12 November 2012 - 05:51 PM

You have just returned a pointer to garbage from within readShaderFile().
buffer 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 fileName 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

Edited by L. Spiro, 12 November 2012 - 06:01 PM.

#3 MJP   Moderators   


Posted 12 November 2012 - 07:47 PM

Moving this to the OpenGL forum...

#4 D.V.D   Members   


Posted 12 November 2012 - 09:14 PM

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]

Edited by D.V.D, 12 November 2012 - 09:23 PM.

#5 Kaptein   Prime Members   


Posted 13 November 2012 - 02:19 AM

you need to save the Shader object somehow Posted Image 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!
[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);

Edited by Kaptein, 13 November 2012 - 07:39 AM.

#6 D.V.D   Members   


Posted 15 November 2012 - 06:50 PM

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!!

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.