我正在尝试破解通用Xcode iOS OpenGL游戏模板来绘制两个顶点缓冲区对象,并使用不同的GLSL着色器渲染它们。 我想'我正在渲染两个VBO? (因为我在通过第一个着色器程序运行两个VBO时都看到它们)但是,我的第二个着色器似乎根本没有呈现我的第二个对象。
这是两个正方形的顶点数据:
GLfloat gCubeVertexData[36] =
{
// Data layout for each line below is:
// positionX, positionY, positionZ, normalX, normalY, normalZ,
0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f
};
GLfloat fooVertexData[36] =
{
// Data layout for each line below is:
// positionX, positionY, positionZ, normalX, normalY, normalZ
0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f
};
这是我尝试生成两个VBO并将它们绑定到数据的位置。不知道'glBindVertexArrayOES(0)'的目的是什么呢?:
- (void)setupGL
{
[EAGLContext setCurrentContext:self.context];
[self loadShaders];
//---- First Vertex Array Object --------
glGenVertexArraysOES(1, &_vertexArray1);
glGenBuffers(1, &_vertexBuffer1);
glBindVertexArrayOES(_vertexArray1);
glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer1);
glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW);
glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0));
glEnableVertexAttribArray(GLKVertexAttribNormal);
glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12));
//----- Second Vertex Array Object ----------
glGenVertexArraysOES(1, &_vertexArray2);
glGenBuffers(1, &_vertexBuffer2);
glBindVertexArrayOES(_vertexArray2);
glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer2);
glBufferData(GL_ARRAY_BUFFER, sizeof(fooVertexData), fooVertexData, GL_STATIC_DRAW);
glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0));
glEnableVertexAttribArray(GLKVertexAttribNormal);
glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12));
glBindBuffer(GL_ARRAY_BUFFER,0);
glBindVertexArrayOES(0);
}
我正在使用此更新代码为模型 - 视图 - 投影矩阵设置动画:
- (void)update
{
_rotation += self.timeSinceLastUpdate * 0.2f;
float aspect = fabsf(self.view.bounds.size.width / self.view.bounds.size.height);
GLKMatrix4 projectionMatrix = GLKMatrix4MakeOrtho(-1.0f, 1.0f, -1.0f / aspect, 1.0f / aspect, -10.0f, 10.0f);
GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.5f, 0.0f, 0.0f);
modelViewMatrix = GLKMatrix4Multiply(modelViewMatrix, GLKMatrix4MakeZRotation(0.0 - _rotation));
_modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix);
GLKMatrix4 modelViewMatrix2 = GLKMatrix4MakeTranslation(-0.5f, 0.0f, 0.0f);
modelViewMatrix2 = GLKMatrix4Multiply(modelViewMatrix2, GLKMatrix4MakeZRotation(_rotation));
_modelViewProjectionMatrix2 = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix2);
}
当我调用'_program2'着色器时,我看不到第二个方块:
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{
glClearColor(0.65f, 0.65f, 0.65f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glBindVertexArrayOES(_vertexArray1);
glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer1);
glUseProgram(_program);
glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m);
glDrawArrays(GL_TRIANGLES, 0, 6);
///////// second object and shader program:
glBindVertexArrayOES(_vertexArray2);
glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer2);
glUseProgram(_program2);
glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX2], 1, 0, _modelViewProjectionMatrix2.m);
glDrawArrays(GL_TRIANGLES, 0, 6);
}
我基本上尝试重复加载第一个着色器的代码,加载第二个着色器。我怀疑我可能在这里做错了什么......但我不确定是什么:
- (BOOL)loadShaders
{
GLuint vertShader, fragShader, vertShader2, fragShader2;
NSString *vertShaderPathname, *fragShaderPathname, *vertShaderPathname2, *fragShaderPathname2;
// Create shader program.
_program = glCreateProgram();
// Create and compile vertex shader.
vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"];
if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) {
NSLog(@"Failed to compile vertex shader");
return NO;
}
// Create and compile fragment shader.
fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"];
if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) {
NSLog(@"Failed to compile fragment shader");
return NO;
}
// Attach vertex shader to program.
glAttachShader(_program, vertShader);
// Attach fragment shader to program.
glAttachShader(_program, fragShader);
// Bind attribute locations.
// This needs to be done prior to linking.
glBindAttribLocation(_program, ATTRIB_VERTEX, "position");
// Link program.
if (![self linkProgram:_program]) {
NSLog(@"Failed to link program: %d", _program);
if (vertShader) {
glDeleteShader(vertShader);
vertShader = 0;
}
if (fragShader) {
glDeleteShader(fragShader);
fragShader = 0;
}
if (_program) {
glDeleteProgram(_program);
_program = 0;
}
return NO;
}
// Get uniform locations.
uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix");
// Release vertex and fragment shaders.
if (vertShader) {
glDetachShader(_program, vertShader);
glDeleteShader(vertShader);
}
if (fragShader) {
glDetachShader(_program, fragShader);
glDeleteShader(fragShader);
}
///////////////// the second shader:
_program2 = glCreateProgram();
vertShaderPathname2 = [[NSBundle mainBundle] pathForResource:@"Shader2" ofType:@"vsh"];
if (![self compileShader:&vertShader2 type:GL_VERTEX_SHADER file:vertShaderPathname2]) {
NSLog(@"Failed to compile vertex shader2");
return NO;
}
fragShaderPathname2 = [[NSBundle mainBundle] pathForResource:@"Shader2" ofType:@"fsh"];
if (![self compileShader:&fragShader2 type:GL_FRAGMENT_SHADER file:fragShaderPathname2]) {
NSLog(@"Failed to compile fragment shader2");
return NO;
}
glAttachShader(_program2, vertShader2);
glAttachShader(_program2, fragShader2);
glBindAttribLocation(_program2, ATTRIB_VERTEX2, "position2");
if (![self linkProgram:_program2]) {
NSLog(@"Failed to link program: %d", _program2);
if (vertShader2) {
glDeleteShader(vertShader2);
vertShader2 = 0;
}
if (fragShader2) {
glDeleteShader(fragShader2);
fragShader2 = 0;
}
if (_program2) {
glDeleteProgram(_program2);
_program2 = 0;
}
return NO;
}
uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX2] = glGetUniformLocation(_program2, "modelViewProjectionMatrix2");
if (vertShader2) {
glDetachShader(_program2, vertShader2);
glDeleteShader(vertShader2);
}
if (fragShader2) {
glDetachShader(_program2, fragShader2);
glDeleteShader(fragShader2);
}
return YES;
}
- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file
{
GLint status;
const GLchar *source;
source = (GLchar *)[[NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil] UTF8String];
if (!source) {
NSLog(@"Failed to load vertex shader");
return NO;
}
*shader = glCreateShader(type);
glShaderSource(*shader, 1, &source, NULL);
glCompileShader(*shader);
#if defined(DEBUG)
GLint logLength;
glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength);
if (logLength > 0) {
GLchar *log = (GLchar *)malloc(logLength);
glGetShaderInfoLog(*shader, logLength, &logLength, log);
NSLog(@"Shader compile log:\n%s", log);
free(log);
}
#endif
glGetShaderiv(*shader, GL_COMPILE_STATUS, &status);
if (status == 0) {
glDeleteShader(*shader);
return NO;
}
return YES;
}
- (BOOL)linkProgram:(GLuint)prog
{
GLint status;
glLinkProgram(prog);
#if defined(DEBUG)
GLint logLength;
glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength);
if (logLength > 0) {
GLchar *log = (GLchar *)malloc(logLength);
glGetProgramInfoLog(prog, logLength, &logLength, log);
NSLog(@"Program link log:\n%s", log);
free(log);
}
#endif
glGetProgramiv(prog, GL_LINK_STATUS, &status);
if (status == 0) {
return NO;
}
return YES;
}
- (BOOL)validateProgram:(GLuint)prog
{
GLint logLength, status;
glValidateProgram(prog);
glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logLength);
if (logLength > 0) {
GLchar *log = (GLchar *)malloc(logLength);
glGetProgramInfoLog(prog, logLength, &logLength, log);
NSLog(@"Program validate log:\n%s", log);
free(log);
}
glGetProgramiv(prog, GL_VALIDATE_STATUS, &status);
if (status == 0) {
return NO;
}
return YES;
}
我的顶点和片段着色器很简单:
// vert shader1:
attribute vec4 position;
uniform mat4 modelViewProjectionMatrix;
void main()
{
gl_Position = modelViewProjectionMatrix * position;
}
// vert shader2:
attribute vec4 position2;
uniform mat4 modelViewProjectionMatrix2;
void main()
{
gl_Position = modelViewProjectionMatrix2 * position2;
}
// frag shader(s):
void main()
{
gl_FragColor = vec4(0.12,0.32,0.54,1.0);
}
答案 0 :(得分:2)
使用OpenGL ES时最重要的一点是,您正在使用OOP语言中的过程语言。
一次只能将一个顶点数组绑定到顶点缓冲区。
将两个顶点数组一个接一个地绑定到VBO,然后应用转换,只会转换附加到VBO的最后一个顶点数组。
在主循环中,您必须遍历顶点数组列表。对于每个顶点数组,将其绑定到VBO,然后执行任何转换。
答案 1 :(得分:2)
主要问题是我绑定了第二个顶点着色器的'position'属性位置。我一直在我的枚举中使用'单独的'ATTRIB_VERTEX2。一旦我将'position'属性位置绑定到ARRTIB_VERTEX,我就可以看到应用了其他着色器程序的第二个VBO ...以下是为具有相同问题/问题的任何人整理的代码:
// Uniform index.
enum
{
UNIFORM_MODELVIEWPROJECTION_MATRIX,
UNIFORM_MODELVIEWPROJECTION_MATRIX2,
NUM_UNIFORMS
};
GLint uniforms[NUM_UNIFORMS];
// Attribute index.
enum
{
ATTRIB_VERTEX,
NUM_ATTRIBUTES
};
GLfloat square1Data[18] =
{
// Data layout for each line below is:
// positionX, positionY, positionZ
0.5f, 0.5f, 0.5f,
-0.5f, 0.5f, 0.5f,
0.5f, -0.5f, 0.5f,
0.5f, -0.5f, 0.5f,
-0.5f, 0.5f, 0.5f,
-0.5f, -0.5f, 0.5f
};
GLfloat square2Data[18] =
{
// Data layout for each line below is:
// positionX, positionY, positionZ
0.5f, 0.5f, 0.5f,
-0.5f, 0.5f, 0.5f,
0.5f, -0.5f, 0.5f,
0.5f, -0.5f, 0.5f,
-0.5f, 0.5f, 0.5f,
-0.5f, -0.5f, 0.5f
};
- (void)setupGL
{
[EAGLContext setCurrentContext:self.context];
[self loadShaders];
//---- First Vertex Array Object --------
glGenVertexArraysOES(1, &_vertexArray1);
glGenBuffers(1, &_vertexBuffer1);
glBindVertexArrayOES(_vertexArray1);
glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer1);
glBufferData(GL_ARRAY_BUFFER, sizeof(square1Data), square1Data, GL_STATIC_DRAW);
glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 12, BUFFER_OFFSET(0));
// glEnableVertexAttribArray(GLKVertexAttribNormal);
// glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12));
//----- Second Vertex Array Object ----------
glGenBuffers(1, &_vertexBuffer2);
glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer2);
glBufferData(GL_ARRAY_BUFFER, sizeof(square2Data), square2Data, GL_STATIC_DRAW);
glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 12, BUFFER_OFFSET(0));
// glEnableVertexAttribArray(GLKVertexAttribNormal);
// glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12));
glBindBuffer(GL_ARRAY_BUFFER,0);
glBindVertexArrayOES(0);
}
- (void)update
{
_rotation += self.timeSinceLastUpdate * 0.2f;
float aspect = fabsf(self.view.bounds.size.width / self.view.bounds.size.height);
GLKMatrix4 projectionMatrix = GLKMatrix4MakeOrtho(-1.0f, 1.0f, -1.0f / aspect, 1.0f / aspect, -10.0f, 10.0f);
GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.5f, 0.0f, 0.0f);
modelViewMatrix = GLKMatrix4Multiply(modelViewMatrix, GLKMatrix4MakeZRotation(0.0 - _rotation));
_modelViewProjectionMatrix = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix);
GLKMatrix4 modelViewMatrix2 = GLKMatrix4MakeTranslation(-0.5f, 0.0f, 0.0f);
modelViewMatrix2 = GLKMatrix4Multiply(modelViewMatrix2, GLKMatrix4MakeZRotation(_rotation));
_modelViewProjectionMatrix2 = GLKMatrix4Multiply(projectionMatrix, modelViewMatrix2);
}
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{
glClearColor(0.65f, 0.65f, 0.65f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glBindVertexArrayOES(_vertexArray1);
glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer1);
glUseProgram(_program);
glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m);
glDrawArrays(GL_TRIANGLES, 0, 6);
///////// second VBO and shader program:
glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer2);
glUseProgram(_program2);
glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX2], 1, 0, _modelViewProjectionMatrix2.m);
glDrawArrays(GL_TRIANGLES, 0, 6);
}
- (BOOL)loadShaders
{
GLuint vertShader, fragShader, vertShader2, fragShader2;
NSString *vertShaderPathname, *fragShaderPathname, *vertShaderPathname2, *fragShaderPathname2;
// Create shader program.
_program = glCreateProgram();
_program2 = glCreateProgram();
// Create and compile vertex shader.
vertShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"vsh"];
if (![self compileShader:&vertShader type:GL_VERTEX_SHADER file:vertShaderPathname]) {
NSLog(@"Failed to compile vertex shader");
return NO;
}
// Create and compile fragment shader.
fragShaderPathname = [[NSBundle mainBundle] pathForResource:@"Shader" ofType:@"fsh"];
if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:fragShaderPathname]) {
NSLog(@"Failed to compile fragment shader");
return NO;
}
// Create and compile vertex shader.
vertShaderPathname2 = [[NSBundle mainBundle] pathForResource:@"Shader2" ofType:@"vsh"];
if (![self compileShader:&vertShader2 type:GL_VERTEX_SHADER file:vertShaderPathname2]) {
NSLog(@"Failed to compile vertex shader");
return NO;
}
// Create and compile fragment shader.
fragShaderPathname2 = [[NSBundle mainBundle] pathForResource:@"Shader2" ofType:@"fsh"];
if (![self compileShader:&fragShader2 type:GL_FRAGMENT_SHADER file:fragShaderPathname2]) {
NSLog(@"Failed to compile fragment shader");
return NO;
}
// Attach vertex shader to program.
glAttachShader(_program, vertShader);
glAttachShader(_program2, vertShader2);
// Attach fragment shader to program.
glAttachShader(_program, fragShader);
glAttachShader(_program2, fragShader2);
// Bind attribute locations.
// This needs to be done prior to linking.
glBindAttribLocation(_program, ATTRIB_VERTEX, "position");
glBindAttribLocation(_program2, ATTRIB_VERTEX, "position");
// Link program.
if (![self linkProgram:_program]) {
NSLog(@"Failed to link program: %d", _program);
if (vertShader) {
glDeleteShader(vertShader);
vertShader = 0;
}
if (fragShader) {
glDeleteShader(fragShader);
fragShader = 0;
}
if (_program) {
glDeleteProgram(_program);
_program = 0;
}
return NO;
}
if (![self linkProgram:_program2]) {
NSLog(@"Failed to link program: %d", _program2);
if (vertShader2) {
glDeleteShader(vertShader2);
vertShader2 = 0;
}
if (fragShader2) {
glDeleteShader(fragShader2);
fragShader2 = 0;
}
if (_program2) {
glDeleteProgram(_program2);
_program2 = 0;
}
return NO;
}
// Get uniform locations.
uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix");
uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX2] = glGetUniformLocation(_program2, "modelViewProjectionMatrix2");
// Release vertex and fragment shaders.
if (vertShader) {
glDetachShader(_program, vertShader);
glDeleteShader(vertShader);
}
if (fragShader) {
glDetachShader(_program, fragShader);
glDeleteShader(fragShader);
}
if (vertShader2) {
glDetachShader(_program2, vertShader2);
glDeleteShader(vertShader2);
}
if (fragShader2) {
glDetachShader(_program2, fragShader2);
glDeleteShader(fragShader2);
}
return YES;
}