views:

220

answers:

2

I'm having a bit of a problem with my code for compiling shaders, namely they both register as failed compiles and no log is received.

This is the shader compiling code:

/* Make the shader */

Uint size;
GLchar* file;

loadFileRaw(filePath, file, &size);

const char * pFile = file;
const GLint pSize = size;


newCashe.shader = glCreateShader(shaderType);
glShaderSource(newCashe.shader, 1, &pFile, &pSize); 
glCompileShader(newCashe.shader);

GLint shaderCompiled;

glGetShaderiv(newCashe.shader, GL_COMPILE_STATUS, &shaderCompiled);

if(shaderCompiled == GL_FALSE)
{
    ReportFiler->makeReport("ShaderCasher.cpp", "loadShader()", "Shader did not compile", "The shader " + filePath + " failed to compile, reporting the error - " + OpenGLServices::getShaderLog(newCashe.shader));

}

And these are the support functions:

bool loadFileRaw(string fileName, char* data, Uint* size)
{    
    if (fileName != "") 
    {
        FILE *file = fopen(fileName.c_str(), "rt");

        if (file != NULL) 
        {
            fseek(file, 0, SEEK_END);
            *size = ftell(file);
            rewind(file);

            if (*size > 0) 
            {
                data = (char*)malloc(sizeof(char) * (*size + 1));
                *size = fread(data, sizeof(char), *size, file);
                data[*size] = '\0';
            }

            fclose(file);
        }
    }

    return data;
}

string OpenGLServices::getShaderLog(GLuint obj)
{
    int infologLength = 0;

    int charsWritten  = 0;
    char *infoLog;

    glGetShaderiv(obj, GL_INFO_LOG_LENGTH,&infologLength);

    if (infologLength > 0)
    {
        infoLog = (char *)malloc(infologLength);
        glGetShaderInfoLog(obj, infologLength, &charsWritten, infoLog);

        string log = infoLog;

        free(infoLog);

        return log;
    }

    return "<Blank Log>";
}

and the shaders I'm loading:

void main(void)
{
    gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}

void main(void)
{
    gl_Position = ftransform();
}

In short I get

From: ShaderCasher.cpp, In: loadShader(), Subject: Shader did not compile
Message: The shader Data/Shaders/Standard/standard.vs failed to compile, reporting the error - <Blank Log>

for every shader I compile.

I've tried replacing the file reading with just a hard coded string but I get the same error so there must be something wrong with how I'm compiling them. I have run and compiled example programs with shaders, so I doubt my drivers are the issue, but in any case I'm on a Nvidia 8600m GT.

Can anyone help?

+1  A: 

Try with:

glShaderSource(newCashe.shader, 1, &pFile, NULL);

Which is the most commonly used call to load shader sources.

Matias Valdenegro
+3  A: 

In loadFileRaw, you pass char *data by value. Then you assign to it:

data = (char*)malloc(sizeof(char) * (*size + 1));

so your call

loadFileRaw(filePath, file, &size);

does not change the value of file! To change file, pass it in by pointer:

loadFileRaw(filePath, &file, &size);

and then change your function to

bool loadFileRaw(string fileName, char** data, Uint* size) { ... }

and in it,

*data = (char*)malloc(sizeof(char) * (*size + 1));

etc. (for the remaining references to data).

That said, since you're using C++, look into using std::vector<char> or std::string for your memory management. To get you started,

{
   std::vector<char> data;
   data.resize(100); // now it has 100 entries, initialized to zero
   silly_C_function_that_takes_a_char_pointer_and_a_size(&data[0], 100); // OK
} // presto, memory freed

Also, you can look into using std::ifstream for reading files, instead of using FILE *.

Jesse Beder
My original function used std::ifstream, but I copied the one shown off the internet once I had this problem.Urgh, now I'm getting bad access on glShaderSource
Tomas Cokis
If I make the read function use std::string, won't it need to use chars for the ifstream functions anyway?
Tomas Cokis
@Tomas, I don't follow your second question, but it looks like you're having some trouble with pointers, so why don't you put shaders on hold for a moment and carefully work some simpler examples with pointers (including, but not only, C-style strings) until you feel more comfortable.
Jesse Beder
I changed my function into one which used strings instead and everything working fine - thanks for the advice.What I was trying to say one comment up was that since fstream's functions all take pointers to chars to send data back, getting it in that form then converting it to a string, only to convert it back for opengl seemed a bit redundant. In any case I found a workaround in an article somewhere which used stringstream and reader->rdbuf() - it seems like a waste of time, but hey, it works.Cheers for the advice and all
Tomas Cokis