Reputation: 4241
I'm having a problem with my shader loading code. The bizarre thing that's confusing me is that it works maybe once in 5 times, but then only sort of works. For instance, it'll load the frag shader, but then texturing won't work properly (it'll draw a strange semblance of the texture over the geometry instead). I think the problem is with the loading code, so that's what my question is about. Can anyone spot an error I haven't found in the code below?
char* vs, * fs;
vertexShaderHandle = glCreateShader(GL_VERTEX_SHADER);
fragmentShaderHandle = glCreateShader(GL_FRAGMENT_SHADER);
long sizeOfVShaderFile = getSizeOfFile(VERTEX_SHADER_FILE_NAME);
long sizeOfFShaderFile = getSizeOfFile(FRAGMENT_SHADER_FILE_NAME);
if(sizeOfVShaderFile == -1)
{
cerr << VERTEX_SHADER_FILE_NAME<<" is null! Exiting..." << endl;
return;
}
if(sizeOfFShaderFile == -1)
{
cerr << FRAGMENT_SHADER_FILE_NAME<<" is null! Exiting..." << endl;
return;
}
vs = readFile(VERTEX_SHADER_FILE_NAME);
fs = readFile(FRAGMENT_SHADER_FILE_NAME);
const char* vv = vs, *ff = fs;
glShaderSource(vertexShaderHandle , 1, &vv, NULL);
cout << "DEBUGGING SHADERS" << endl;
cout << "VERTEX SHADER: ";
printShaderInfoLog(vertexShaderHandle);
cout << endl;
glShaderSource(fragmentShaderHandle, 1, &ff, NULL);
cout << "FRAGMENT SHADER: ";
printShaderInfoLog(fragmentShaderHandle);
cout << endl;
glCompileShader(vertexShaderHandle);
cout << "VERTEX SHADER: ";
printShaderInfoLog(vertexShaderHandle);
cout << endl;
glCompileShader(fragmentShaderHandle);
cout << "FRAGMENT SHADER: ";
printShaderInfoLog(fragmentShaderHandle);
cout << endl;
programHandle = glCreateProgram();
cout << "DEBUGGING PROGRAM" << endl;
glAttachShader(programHandle, vertexShaderHandle);
printProgramInfoLog(programHandle);
glAttachShader(programHandle, fragmentShaderHandle);
printProgramInfoLog(programHandle);
glLinkProgram(programHandle);
printProgramInfoLog(programHandle);
glUseProgram(programHandle);
printProgramInfoLog(programHandle);
delete[] vs; delete[] fs;
Here's the readFile function:
char* readFile(const char* path)
{
unsigned int fileSize = getSizeOfFile(path);
char* file_data = new char[fileSize];
ifstream input_stream;
input_stream.open(path, ios::binary);
input_stream.read(file_data, fileSize);
input_stream.close();
//this is deleted at the end of the shader code
return file_data;
}
All of the below messages are from the exact same executable (no rebuild).
Here's the first possible error message:
BallGLWidget::initializeGL called
DEBUGGING SHADERS
VERTEX SHADER:
FRAGMENT SHADER:
VERTEX SHADER: ERROR: 0:17: '<' : syntax error syntax error
FRAGMENT SHADER:
DEBUGGING PROGRAM
ERROR: One or more attached shaders not successfully compiled
ERROR: One or more attached shaders not successfully compiled
glGetError enum value: GL_NO_ERROR
Another possible error message:
BallGLWidget::initializeGL called
DEBUGGING SHADERS
VERTEX SHADER:
FRAGMENT SHADER:
VERTEX SHADER: ERROR: 0:17: 'tt' : syntax error syntax error
FRAGMENT SHADER: ERROR: 0:33: '?' : syntax error syntax error
DEBUGGING PROGRAM
ERROR: One or more attached shaders not successfully compiled
ERROR: One or more attached shaders not successfully compiled
Here's the output when it works (maybe 1 in 5 or 6 times)
BallGLWidget::initializeGL called
DEBUGGING SHADERS
VERTEX SHADER:
FRAGMENT SHADER:
VERTEX SHADER:
FRAGMENT SHADER:
DEBUGGING PROGRAM
Image format is GL_RGB
Checking textures...
glGetError enum value: GL_NO_ERROR
I seriously doubt its the shaders themselves since they do work sometimes... and the reported errors are garbage.
If any more information would be helpful I'll gladly provide it.
EDIT: Here's the shaders
The vertex shader:
attribute vec2 a_v_position;
attribute vec2 a_tex_position;
varying vec2 tex_coord_output;
void main()
{
tex_coord_output = a_tex_position;
gl_Position = vec4(a_v_position, 0.0, 1.0);
}
The fragment shader:
varying vec2 tex_coord_output;
uniform sampler2D ballsampler;
void main()
{
gl_FragColor = texture2D(ballsampler, tex_coord_output);
}
Upvotes: 4
Views: 6582
Reputation: 162164
Your question is a duplicate of Getting garbage chars when reading GLSL files and here's my answer to it:
You're using C++, so I suggest you leverage that. Instead of reading into a self allocated char array I suggest you read into a std::string:
#include <string>
#include <fstream>
std::string loadFileToString(char const * const fname)
{
std::ifstream ifile(fname);
std::string filetext;
while( ifile.good() ) {
std::string line;
std::getline(ifile, line);
filetext.append(line + "\n");
}
return filetext;
}
That automatically takes care of all memory allocation and proper delimiting -- the keyword is RAII: Resource Allocation Is Initialization. Later on you can upload the shader source with something like
void glcppShaderSource(GLuint shader, std::string const &shader_string)
{
GLchar const *shader_source = shader_string.c_str();
GLint const shader_length = shader_string.size();
glShaderSource(shader, 1, &shader_source, &shader_length);
}
void load_shader(GLuint shaderobject, char * const shadersourcefilename)
{
glcppShaderSource(shaderobject, loadFileToString(shadersourcefilename));
}
Upvotes: 4
Reputation: 7131
You are reading the files but as far as I can see you are not zero-terminating the text. Try allocating filesize+1 and set the last char to zero.
Upvotes: 3