Kom*_*ave 7 shader opengl-es vbo ios opengl-es-2.0
如果任何人都可以揭示这是怎么回事错在这里光,也许GL命令或其他一些不兼容的指令序列的乱序,我将是你的帮助极大感谢.尽管谷歌在"OpenGL ES 2.0编程指南"中进行了大量研究和研究,但我一直试图让这些代码整天都没有成功.
我正在尝试在iPhone上的OpenGL ES 2.0中使用顶点缓冲区对象和自定义着色器.我试图交错来自以下类型的一系列自定义结构的顶点数据:
typedef struct {
float x, y; // Position.
float radius;
float colR,colG,colB,colA; // Color rgba components.
} VType;
Run Code Online (Sandbox Code Playgroud)
位置,半径和颜色字节分别考虑顶点位置,点大小和颜色.这些的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.
Run Code Online (Sandbox Code Playgroud)
这些的步幅在每个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;
}
Run Code Online (Sandbox Code Playgroud)
FragmentShader.txt
#ifdef GL_FRAGMENT_PRECISION_HIGH
precision highp float;
#else
precision mediump float;
#endif
void main()
{
gl_FragColor = vec4(1.0,0.0,0.0,1.0);
}
Run Code Online (Sandbox Code Playgroud)
我想知道顶点着色器中是否需要投影矩阵?我创建的所有点都是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;
}
Run Code Online (Sandbox Code Playgroud)
初始化代码
GLfloat screenHeight = [[UIScreen mainScreen] bounds].size.height;
GLfloat screenWidth = [[UIScreen mainScreen] bounds].size.width;
glViewport(0, 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, 2, GL_FLOAT, GL_FALSE, sizeof(VType), BUFFER_OFFSET(0));
glEnableVertexAttribArray(ID_ATT_Radius);// Radius
glVertexAttribPointer(ID_ATT_Radius, 1, GL_FLOAT, GL_FALSE, sizeof(VType), BUFFER_OFFSET(sizeof(float)*2));
glEnableVertexAttribArray(ID_ATT_Color);// Color
glVertexAttribPointer(ID_ATT_Color, 4, GL_FLOAT, GL_FALSE, sizeof(VType), 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, GL_INFO_LOG_LENGTH, &infoLen);
if (infoLen > 1) {
char* infoLog = (char*)malloc(sizeof(char)*infoLen);
glGetProgramInfoLog(program, infoLen, NULL, infoLog);
NSLog(@"Error linking program:\n%s\n",infoLog);
free(infoLog);
}
glDeleteProgram(program);
}
Run Code Online (Sandbox Code Playgroud)
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));
Run Code Online (Sandbox Code Playgroud)
如果需要任何其他信息,请告诉我,谢谢你的时间.
您不一定需要 2d 顶点的投影矩阵,但您肯定需要将所有 3 个坐标转换为 [-1,1] 范围(您已经通过将 z 设置为 0 来完成此操作)。然后,GL 使用当前视口变换(通常应与您的屏幕尺寸匹配)对这些坐标进行变换。因此,如果坐标采用屏幕尺寸,则在着色器中将它们转换为 [-1,1],或者仅在应用程序中使用 [-1,1] 坐标(这也与分辨率无关)。
编辑:我不知道 OpenGL ES 如何处理这个问题,但在桌面 GL(至少高达 2.1)中,您需要调用glEnable(GL_VERTEX_PROGRAM_POINT_SIZE)顶点着色器才能改变点大小。