我很好奇您是否可以在 Open GL ES 2.0 程序中拥有多个着色器。
这是我的着色器代码。然而,属性和制服仅从rigid.vert 和rigid.frag 着色器中检索变量:
- (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;
}