Reputation: 1073
I am curious as to whether you can have more than one shader in an Open GL ES 2.0 program.
Here is my code the shaders. The attributes and uniforms however only retrieve the variables from the rigid.vert and rigid.frag shader:
- (BOOL)loadShaders
{
GLuint rigidVertShader, rigidFragShader, skinningVertShader, skinningFragShader;
NSString *rigidVertShaderPathname, *rigidFragShaderPathname, *skinningVertShaderPathname, *skinningFragShaderPathname;
// Create shader program.
_program = glCreateProgram();
// Create and compile rigid vertex shader.
rigidVertShaderPathname = [[NSBundle mainBundle] pathForResource:@"rigid" ofType:@"vert"];
if (![self compileShader:&rigidVertShader type:GL_VERTEX_SHADER file:rigidVertShaderPathname]) {
NSLog(@"Failed to compile rigid vertex shader");
return NO;
}
// Create and compile rigid fragment shader.
rigidFragShaderPathname = [[NSBundle mainBundle] pathForResource:@"rigid" ofType:@"frag"];
if (![self compileShader:&rigidFragShader type:GL_FRAGMENT_SHADER file:rigidFragShaderPathname]) {
NSLog(@"Failed to compile rigid fragment shader");
return NO;
}
// Create and compile skinning vertex shader.
skinningVertShaderPathname = [[NSBundle mainBundle] pathForResource:@"skinning" ofType:@"vert"];
if (![self compileShader:&skinningVertShader type:GL_VERTEX_SHADER file:skinningVertShaderPathname]) {
NSLog(@"Failed to compile skinning vertex shader");
return NO;
}
// Create and compile skinning fragment shader.
skinningFragShaderPathname = [[NSBundle mainBundle] pathForResource:@"skinning" ofType:@"frag"];
if (![self compileShader:&skinningFragShader type:GL_FRAGMENT_SHADER file:skinningFragShaderPathname]) {
NSLog(@"Failed to compile skinning fragment shader");
return NO;
}
// Attach rigid vertex shader to program.
glAttachShader(_program, rigidVertShader);
// Attach rigid fragment shader to program.
glAttachShader(_program, rigidFragShader);
// Attach skinning vertex shader to program.
glAttachShader(_program, skinningVertShader);
// Attach skinning fragment shader to program.
glAttachShader(_program, skinningFragShader);
// Link program.
if (![self linkProgram:_program]) {
NSLog(@"Failed to link program: %d", _program);
if (rigidVertShader) {
glDeleteShader(rigidVertShader);
rigidVertShader = 0;
}
if (rigidFragShader) {
glDeleteShader(rigidFragShader);
rigidFragShader = 0;
}
if (skinningVertShader) {
glDeleteShader(skinningVertShader);
skinningVertShader = 0;
}
if (skinningFragShader) {
glDeleteShader(skinningFragShader);
skinningFragShader = 0;
}
if (_program) {
glDeleteProgram(_program);
_program = 0;
}
return NO;
}
// GET UNIFORM LOCATIONS
// Dictionary to store each active uniform
NSMutableDictionary *m_uniforms = [[NSMutableDictionary alloc] init];
int m_nUniforms = -1;
glGetProgramiv( _program, GL_ACTIVE_UNIFORMS, &m_nUniforms );
for(GLuint i = 0; i < m_nUniforms; i++) {
int name_len=-1, num=-1;
GLenum type = GL_ZERO;
char uniformName[100];
glGetActiveUniform( _program, i, sizeof(uniformName)-1, &name_len, &num, &type, uniformName );
uniformName[name_len] = 0;
GLuint uniform = glGetUniformLocation( _program, uniformName );
[m_uniforms setObject:[NSNumber numberWithUnsignedInt:uniform]
forKey:[NSString stringWithUTF8String:uniformName]];
}
// GET ATTRIBUTE LOCATIONS
// Dictionary to store each active attribute
NSMutableDictionary *m_attributes = [[NSMutableDictionary alloc] init];
int m_nAttributes = -1;
glGetProgramiv( _program, GL_ACTIVE_ATTRIBUTES, &m_nAttributes );
for(GLuint i = 0; i < m_nAttributes; i++) {
int name_len=-1, num=-1;
GLenum type = GL_ZERO;
char attributesName[100];
glGetActiveAttrib( _program, i, sizeof(attributesName)-1, &name_len, &num, &type, attributesName );
attributesName[name_len] = 0;
GLuint attributes = glGetAttribLocation( _program, attributesName );
[m_attributes setObject:[NSNumber numberWithUnsignedInt:attributes]
forKey:[NSString stringWithUTF8String:attributesName]];
}
// Release vertex and fragment shaders.
if (rigidVertShader) {
glDetachShader(_program, rigidVertShader);
glDeleteShader(rigidVertShader);
}
if (rigidFragShader) {
glDetachShader(_program, rigidFragShader);
glDeleteShader(rigidFragShader);
}
if (skinningVertShader) {
glDetachShader(_program, skinningVertShader);
glDeleteShader(skinningVertShader);
}
if (skinningFragShader) {
glDetachShader(_program, skinningFragShader);
glDeleteShader(skinningFragShader);
}
return YES;
}
Upvotes: 0
Views: 364
Reputation: 33602
OpenGL ES does not allow multiple shaders of the same type in a program, unlike "desktop" OpenGL (but it only allows you to declare common functions/variables, so it's approximately the same as concatenating shader source anyway). From the glAttachShader() spec:
Multiple shader objects of the same type may not be attached to a single program object.
...
Errors
...
GL_INVALID_OPERATION
is generated if shader is already attached to program, or if another shader object of the same type as shader is already attached to program.
I strongly suspect that the third and fourth calls to glAttachShader()
set GL_INVALID_OPERATION
.
Check your errors! I call glGetError()
in a loop until it returns GL_NO_ERROR
.
Upvotes: 2
Reputation: 3562
You can use only one fragment and one vertex shader per shader program in OpenGL ES. Otherwise it just won't work.
Upvotes: 0