我正在尝试在iPhone上的OpenGL ES 2.0中使用顶点缓冲区对象和自定义着色器.我试图交错来自以下类型的一系列自定义结构的顶点数据:
typedef struct { float x,y; // Position. float radius; float colR,colG,colB,colA; // Color rgba components. } VType;
位置,半径和颜色字节分别考虑顶点位置,点大小和颜色.这些的ID已初始化:
ID_ATT_Pos = 0; ID_ATT_Radius = 1; ID_ATT_Color = 2; // Note: I have also tried values of 1,2,3 but no difference.
这些的步幅在每个glVertexAttribPointer调用中指定.
意图是每个顶点在其x,y位置绘制,具有指定的颜色和半径的点数.与每个上述属性相关联的是顶点着色器属性,它们是“a_position”,“a_color”和“a_radius”.以下是顶点和片段着色器:
VertexShader.txt
attribute vec2 a_position; attribute vec4 a_color; attribute float a_radius; varying vec4 v_color; void main() { gl_Position = vec4(a_position,0.0,1.0); gl_PointSize = a_radius; v_color = a_color; }
FragmentShader.txt
#ifdef GL_FRAGMENT_PRECISION_HIGH precision highp float; #else precision mediump float; #endif void main() { gl_FragColor = vec4(1.0,1.0); }
我想知道顶点着色器中是否需要投影矩阵?我创建的所有点都是iPhone屏幕尺寸的2D,正如您所看到的,它们每个都在上面的顶点着色器中附加’z,w’作为’0.0,1.0′.
下面列出了使用glDrawElements设置VBO和渲染的剩余核心代码.当运行此代码时,很明显glClear已经成功,并且NSLog打印确实确认了这一点,但是视口中没有通过下面列出的DrawFrame代码绘制VType顶点.顶点坐标完全在屏幕尺寸内,例如x,y:(92,454).
请注意,以下代码中的任何未声明的变量都是类属性,并且具有适当的类型,例如’vao’是GLuint,’vbos’是GLuint [2],’program’是GLuint程序句柄.我还遗漏了样板OpenGL设置代码,该代码已经过不同代码内部测试并显示可以工作.
加载着色器代码
-(GLuint)loadShaderType:(GLenum)type From:(NSString*)shaderFile { GLuint shader; GLint compiled; // Create and compile vertex shader. NSString *filepath = [[NSBundle mainBundle] pathForResource:shaderFile ofType:@"txt"]; const GLchar *shaderSrc = (GLchar *)[[NSString stringWithContentsOfFile:filepath encoding:NSUTF8StringEncoding error:nil] UTF8String]; if (!shaderSrc) { NSLog(@"Failed to load vertex shader"); return 0; } // Create shader object. shader = glCreateShader(type); if (shader == 0) return 0; // Load shader source. glShaderSource(shader,1,&shaderSrc,NULL); // Compile shader. glCompileShader(shader); // Check compile status. glGetShaderiv(shader,GL_COMPILE_STATUS,&compiled); if (!compiled) { GLint infoLen = 0; glGetShaderiv(shader,GL_INFO_LOG_LENGTH,&infoLen); if (infoLen > 1) { char * infoLog = (char*)malloc(sizeof(char)*infoLen); glGetShaderInfoLog(shader,infoLen,NULL,infoLog); NSLog(@"Error compiling shader:\n%s\n",infoLog); free(infoLog); } glDeleteShader(shader); return 0; } return shader; }
初始化代码
GLfloat screenHeight = [[UIScreen mainScreen] bounds].size.height; GLfloat screenWidth = [[UIScreen mainScreen] bounds].size.width; glViewport(0,screenWidth,screenHeight); glGenVertexArraysOES(1,&vao); glBindVertexArrayOES(vao); // Generate buffer,bind to use now,set initial data. glGenBuffers(2,vbos); glBindBuffer(GL_ARRAY_BUFFER,vbos[0]); glBufferData(GL_ARRAY_BUFFER,vxBufSize,squidVxs,GL_STATIC_DRAW); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,vbos[1]); glBufferData(GL_ELEMENT_ARRAY_BUFFER,ixBufSize,squidIxs,GL_STATIC_DRAW); glEnableVertexAttribArray(ID_ATT_Pos); // Pos glVertexAttribPointer(ID_ATT_Pos,GL_FLOAT,GL_FALSE,sizeof(VType),BUFFER_OFFSET(0)); glEnableVertexAttribArray(ID_ATT_Radius);// Radius glVertexAttribPointer(ID_ATT_Radius,BUFFER_OFFSET(sizeof(float)*2)); glEnableVertexAttribArray(ID_ATT_Color);// Color glVertexAttribPointer(ID_ATT_Color,4,BUFFER_OFFSET(sizeof(float)*3)); GLuint shaders[2]; shaders[0] = [self loadShaderType:GL_VERTEX_SHADER From:@"VertexShader"]; shaders[1] = [self loadShaderType:GL_FRAGMENT_SHADER From:@"FragmentShader"]; program = glCreateProgram(); glAttachShader(program,shaders[0]); glAttachShader(program,shaders[1]); glBindAttribLocation(program,ID_ATT_Pos,"a_position"); glBindAttribLocation(program,ID_ATT_Radius,"a_radius"); glBindAttribLocation(program,ID_ATT_Color,"a_color"); glLinkProgram(program); GLint linked; glGetProgramiv(program,GL_LINK_STATUS,&linked); if (!linked) { GLint infoLen = 0; glGetProgramiv(program,&infoLen); if (infoLen > 1) { char* infoLog = (char*)malloc(sizeof(char)*infoLen); glGetProgramInfoLog(program,infoLog); NSLog(@"Error linking program:\n%s\n",infoLog); free(infoLog); } glDeleteProgram(program); }
DrawFrame代码
// Note: Framebuffer swapping is taken care of before/after these // lines,and has been shown to work. glClearColor(0.33f,0.0f,0.33f,1.0f); glClear(GL_COLOR_BUFFER_BIT); glUseProgram(program); glDrawElements(GL_POINTS,numPoints,GL_UNSIGNED_SHORT,BUFFER_OFFSET(0));
如果需要任何其他信息,请告诉我,谢谢你的时间.
解决方法
编辑:我不知道OpenGL ES如何处理这个问题,但是在桌面GL(至少高达2.1)中你需要为顶点着色器调用glEnable(GL_VERTEX_PROGRAM_POINT_SIZE)以便能够控制点大小.