我在绘制一个简单的三角形时遇到问题。我在Android Native Activity中正确设置了OpenGL ES 2.0,因为我可以执行glClear()并且它可以工作。
当我尝试绘制一个带有3个顶点的三角形时,它会在glDrawArrays调用中崩溃,或者如果我尝试执行glDrawElements,则没有任何反应,但是我收到以下消息:GLES_V2 // GLESv2Imp.cpp:glDrawElements:669错误量0x500
我查了一下,但我认为我没有任何无效的枚举,我一直在查看我的代码并试验了几天,但是绘制调用只是不起作用。我还读到如果glDrawArrays尝试访问错误的内存块会崩溃,但据我所知,我的设置是正确的。任何人都可以帮助我理解为什么它可能会崩溃吗?
这是我的三角函数的调用方式。这部分只是一个模拟
start()
{
setTriangle();
}
renderLoop()
{
drawTriangle();
}
以下是我的着色器:
static const std::string triVertShader = "\
attribute vec4 vPosition;\
void main()\
{\
gl_Position = vPosition;\
}\
";
static const std::string triFragShader = "\
precision mediump float;\
uniform vec4 vColor;\
void main()\
{\
gl_FragColor = vColor;\
}\
";
这是我编译它们和链接程序的地方。我没有包括我的支票,但着色器编译成功,程序链接成功:
GLuint LoadShaders(const std::string &vertexShader, const std::string &fragmentShader)
{
GLint result = GL_TRUE;
int infoLogLength;
//Create the shaders
GLuint vertShaderID = glCreateShader(GL_VERTEX_SHADER);
GLuint fragShaderID = glCreateShader(GL_FRAGMENT_SHADER);
const char * vertShaderSource = vertexShader.data();
const char * fragShaderSource = fragmentShader.data();
//Compile Vertex Shader
glShaderSource(vertShaderID, 1, &vertShaderSource, NULL);
glCompileShader(vertShaderID);
//Compile Fragment Shader
glShaderSource(fragShaderID, 1, &fragShaderSource, NULL);
glCompileShader(fragShaderID);
//Link the program
GLuint programID = glCreateProgram();
glAttachShader(programID, vertShaderID);
glAttachShader(programID, fragShaderID);
glBindAttribLocation(programID, 0, "vPosition");
glLinkProgram(programID);
// glDeleteShader(vertShaderID);
// glDeleteShader(fragShaderID);
return programID;
}
这是我设置缓冲区对象的地方:
void setTriangle()
{
glClearColor(0, 1, 0, 1);
GLfloat triVerts[] = { 0.0f, 0.5f, 0.0f,
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f };
GLuint triVertBufferID;
glGenBuffers(1, &triVertBufferID);
glBindBuffer(GL_ARRAY_BUFFER, triVertBufferID);
glBufferData(GL_ARRAY_BUFFER,
sizeof(triVerts),
triVerts,
GL_STATIC_DRAW);
program = LoadShaders(triVertShader, triFragShader); //note: "program" is a global variable of type GLuint
}
以下是平局调用:
void drawTriangle()
{
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(program);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
//glDrawElements(GL_TRIANGLES, 3, GL_FLOAT, (void*)0 );
//glDrawArrays always crashes immediately
glDrawArrays(GL_TRIANGLES, 0, 3);
}
答案 0 :(得分:0)
此通话无效:
glDrawElements(GL_TRIANGLES, 3, GL_FLOAT, (void*)0 );
参数GL_FLOAT
不是索引数据的有效数据类型,GLES 2.x仅支持GL_UNSIGNED_BYTE
和GL_UNSIGNED_SHORT
。
但是,我认为您根本不打算使用glDrawElements()
。那是indexed rendering。在您的代码中,您不准备任何GL_ELEMENT_ARRAY_BUFFER
,也不需要一个。
您可能想要使用
glDrawArrays(GL_TRIANGLES, 0, 3);
在triVertBufferID
GL_ARRAY_BUFFER
来电时,确保glVertexAttribPointer()
仍然是当前绑定的drawTriangle()
。目前,您只在程序初始化时绑定它setTriangle()
。只要您从未将任何其他内容绑定到该缓冲区目标(或明确解除绑定),这将起作用。如果您想稍后添加不同的对象,这将导致问题。
答案 1 :(得分:0)
简而言之,您没有索引和颜色数据,也没有绑定作为顶点缓冲区的VBO。如果在Frag Shader代码中取消颜色,则无需颜色。把gl_FragColor = vec(1.0,0.0,0.0,1.0);而是测试它是否运作良好。
更新)的
使局部顶点数组成为全局数组。
GLfloat triVerts [] = {0.0f,0.5f,0.0f, -0.5f,-0.5f,0.0f, 0.5f,-0.5f,0.0f};
使用渲染循环中func中的变量 triVertBufferID 来绑定vbo
当你使用VBO并且它是静态的(永不改变)时,不要每次都调用glVertexAttribPointer(),glEnableVertexAttribArray()。你可以在setTriangle()中设置一次,你不确定它的句柄id是否为'0'。你应该调用glGetAttribLocation()来了解它。
当你不使用VBO时,每次使用顶点数组的指针调用这些func。
答案 2 :(得分:-1)
我可以看到一些小问题导致您的应用无法渲染:
您已将vPosition属性声明为vec4,但是您使用的数据不足以初始化它。 OpenGL将使用默认值填充缺失的数据,但这仍可能导致意外行为。
//call me after programID = loadShaders(...)
int vPosLoc = GLES20.getAttributeLocation(programID,"vPosition"); //pass me to EnableVertexAttribArray()!
就像初始化数据时一样,渲染时需要绑定缓冲区以将其连接到着色器输入 - 所以:
glUseProgram(program);
glEnableVertexAttribArray(vPosLoc); //you use 0 for vPosLoc, which only works because you called glBindAttributeLocation()
glBindBuffer(GL_ARRAY_BUFFER, triVertBufferID); //triVertBufferID - make it a class member?
glVertexAttribPointer(vPosLoc, 3, GL_FLOAT, GL_FALSE, 0, 0); //you might need to change the second argument from 3 to 4, if you're gonna stick with vec4 for vPosition in the shader.
请注意,我在vertexAttribPointer和enableVertexAttribArray()中将0改为vPosLoc,只是为了使用变量而不是常量。
您(在您显示的代码中)从未设置vColor统一变量 - 您需要这样做,并且您需要查找其着色器位置:
//set me up right after loadShaders()
int vColorLoc = glGetUniformLocation(programID,"vColor");
//and later, in draw
glUniform4f(vColorLoc,1.0,0.0,0.0,1.0); //red!
现在,您应该可以调用glDrawArrays()!