I am clearly misunderstanding something pretty simple here to do with GLSL and all Google results point to the obvious answer that I'm not using the variable I'm trying to find and it has been optimised out - However I am using the variable in question. Consider the following very basic shaders:
Vertex shader
attribute vec2 TexCoord;
varying vec2 TexCoordA;
void main(){
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
TexCoordA = TexCoord;
}
Fragment shader
varying vec2 TexCoordA;
void main(){
gl_FragColor = vec3(TexCoordA.x, TexCoordA.y, 0);
}
They compile and link fine- no errors. However using "glGetAttribLocation" returns -1 when I try and find the location of "TexCoord". If I use TexCoordA for another purpose (such as a call to "texture2D()") then I am able to find the location of TexCoord correctly.
Why does this matter you're probably asking (because why else would you use UV coords for anything other than a texture call)? I am trying to render one pixel into a frame buffer for all the UV coordinates and then read them back again on a second pass - this is the only way I can guarantee the results I'm looking for.
TL;DR Why does "glGetAttribLocation" return -1 for the above shaders given they compile and link without a problem?
Requested information about code surrounding the problem area as follows (I am loading about 20-25 other shaders the same way so I'm confident the problem isn't here):
Problem lines:
mPassOneProgram = LoadShader("PCT_UV_CORRECTION_PASS_1.vert", "PCT_UV_CORRECTION_PASS_1.frag");
mPassOneUVLocation = glGetAttribLocation(mPassOneProgram, "TexCoord");
Shader loader code:
GLuint LoadShader(const char *vertex_path, const char *fragment_path) {
GLuint vertShader = glCreateShader(GL_VERTEX_SHADER);
GLuint fragShader = glCreateShader(GL_FRAGMENT_SHADER);
// Read shaders
std::string vertShaderStr = readFile(vertex_path);
std::string fragShaderStr = readFile(fragment_path);
const char *vertShaderSrc = vertShaderStr.c_str();
const char *fragShaderSrc = fragShaderStr.c_str();
GLint result = GL_FALSE;
int logLength;
// Compile vertex shader
std::cout << "Compiling vertex shader." << std::endl;
glShaderSource(vertShader, 1, &vertShaderSrc, NULL);
glCompileShader(vertShader);
// Check vertex shader
glGetShaderiv(vertShader, GL_COMPILE_STATUS, &result);
glGetShaderiv(vertShader, GL_INFO_LOG_LENGTH, &logLength);
std::vector<char> vertShaderError(logLength);
glGetShaderInfoLog(vertShader, logLength, NULL, &vertShaderError[0]);
std::cout << &vertShaderError[0] << std::endl;
OutputDebugString(&vertShaderError[0]);
// Compile fragment shader
std::cout << "Compiling fragment shader." << std::endl;
glShaderSource(fragShader, 1, &fragShaderSrc, NULL);
glCompileShader(fragShader);
// Check fragment shader
glGetShaderiv(fragShader, GL_COMPILE_STATUS, &result);
glGetShaderiv(fragShader, GL_INFO_LOG_LENGTH, &logLength);
std::vector<char> fragShaderError(logLength);
glGetShaderInfoLog(fragShader, logLength, NULL, &fragShaderError[0]);
std::cout << &fragShaderError[0] << std::endl;
OutputDebugString(&vertShaderError[0]);
std::cout << "Linking program" << std::endl;
GLuint program = glCreateProgram();
glAttachShader(program, vertShader);
glAttachShader(program, fragShader);
glLinkProgram(program);
glGetProgramiv(program, GL_LINK_STATUS, &result);
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength);
std::vector<char> programError( (logLength > 1) ? logLength : 1 );
glGetProgramInfoLog(program, logLength, NULL, &programError[0]);
std::cout << &programError[0] << std::endl;
OutputDebugString(&vertShaderError[0]);
glDeleteShader(vertShader);
glDeleteShader(fragShader);
return program;
}