Opengl为啥这个着色器不起作用?
Posted
技术标签:
【中文标题】Opengl为啥这个着色器不起作用?【英文标题】:Opengl why doesn't this Shader Work?Opengl为什么这个着色器不起作用? 【发布时间】:2017-08-16 19:26:12 【问题描述】:我试图创建一个类来绘制一个正方形,这个类将被实例化一次,每次我想绘制一个正方形时,我都会... Square::draw(float posx, float posy ,float大小,浮动大小)。 我这样做的方式是在着色器上安装一个 unifor vec4,我将在其中传输 pos 和 size。 在 vbo 上:GLint _vertID[4] = 0,1,2,3 一个标识,这样我就可以知道着色器正在处理哪个顶点,这样我就可以放置正确的位置
问题是它没有画正方形,而是随机画一些三角形。(有问题)。 我想知道是我的逻辑错了,还是实现错了。
代码如下:
void Square::initVertex()
GLint _vertID[4] = 0,1,2,3;
GLfloat _uvs[8] = 0,0,1,0,1,1,0,1;
glGenVertexArrays(1, vao);
glBindVertexArray(vao[0]);
glGenBuffers(2, vbo);
glBindBuffer( GL_ARRAY_BUFFER, vbo[0]);
glBufferData( GL_ARRAY_BUFFER, 4 * sizeof(GLint), _vertID, GL_STATIC_DRAW);
glVertexAttribPointer(0, 1, GL_INT, false, 0, 0);
glEnableVertexAttribArray(0);
glBindBuffer( GL_ARRAY_BUFFER, vbo[1]);
glBufferData( GL_ARRAY_BUFFER, 8 * sizeof(GLfloat), _uvs, GL_STATIC_DRAW);
glVertexAttribPointer(1, 2, GL_FLOAT, false, 0, 0);
glEnableVertexAttribArray(1);
和顶点着色器: posSh 是 vec4,每次我想画一个正方形时我都会在其中传递位置,而 vertID 是让我知道正在处理哪个 vert 的 vbo
#version 150
in int vertID;
in vec2 uvs;
in vec4 posSh;
out vec2 ex_uvs;
void main(void)
vec2 pos;
if(vertID == 0)
pos = vec2(posSh.x, posSh.y);
else if(vertID == 1)
pos = vec2(posSh.x + posSh.z, posSh.y);
else if(vertID == 2)
pos = vec2(posSh.x + posSh.z, posSh.y + posSh.w);
else if(vertID == 3)
pos = vec2(posSh.x, posSh.y + posSh.w);
gl_Position = vec4(pos.x, pos.y, 1,1);
ex_uvs = uvs;
【问题讨论】:
看看你的渲染方法会很有帮助,但从外观上看你永远不会绑定顶点数据。 您知道glDrawElements
函数可以像在着色器中那样执行索引绘制吗?此外,您的代码没有错误处理,您应该在每个其他 gl 调用之后调用 glGetError
并检查返回的值。
#version 150 支持输出变量吗?
整数属性不能用glVertexAttribPointer
设置。看看this question 或this answer。但是,对于您的用例来说,这有点实际意义,因为 gl_VertexID
确实存在。
【参考方案1】:
我宁愿删除这些 _vertID
索引。
在我看来,您似乎正试图通过使用单个 vec4 来渲染 4 个顶点而不是 4x vec2(或 vec3,如果需要)来节省内存。 vertID
、uvs
和 posSh
都是属性,这意味着它们必须具有相同的元素数。例如:
position: 1[x, y, z], 2[x, y, z], 3[x, y, z]
uvCoords: 1[x, y] , 2[x, y] , 3[x, y]
如果我是对的,posSh
的情况并非如此。
这是我在您的设置和着色器代码中看到的:
vertID: 1[n] , 2[n] , 3[n] , 4[n]
uvs: 1[x, y] , 2[x, y] , 3[x, y] , 4[x, y]
posSh: 1[x, y, z, w] , ??? , ??? , ???
所以,如果是这种情况,我们现在就解决这个问题。
将vbo[0]
从 GL_ARRAY_BUFFER
更改为 GL_ELEMENT_ARRAY_BUFFER
。元素数组缓冲区包含您绑定的数组缓冲区的每个元素的索引(查看上面的代码部分,数字是您可以指定的索引)。 (请记住,vbo[0]
将保持绑定,直到绑定另一个 GL_ELEMENT_ARRAY_BUFFER)
从 GL_ELEMENT_ARRAY_BUFFER 中删除 glVertexAttribPointer 和 glEnableVertexAttribArray,因为它只需要绑定并且已经绑定。
在您的vbo[]
数组中创建第三个 vbo,它将包含您的四边形的所有位置。这将替换posSh
。您必须像 _uvs
的数组缓冲区一样设置它(这将是一个 vec2 位置)
在第三个 vbo 上使用 glVertexAttribPointer 和 glEnableVertexAttribArray。
你就是这样做的。 试试这个代码(我还没有测试过):
void Square::initVertex()
GLint _vertID[4] = 0,1,2,3;
GLfloat _uvs[8] = 0,0,1,0,1,1,0,1;
GLfloat _pos[8] = 0.5f, 0.5f, -0.5f, 0.5f, -0.5f, -0.5f, 0.5f, -0.5f ;
glGenVertexArrays(1, vao);
glBindVertexArray(vao[0]);
glGenBuffers(3, vbo); // the first index is an Element Array Buffer!
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, vbo[0]);
glBufferData( GL_ELEMENT_ARRAY_BUFFER, 4 * sizeof(GLint), _vertID, GL_STATIC_DRAW);
glBindBuffer( GL_ARRAY_BUFFER, vbo[1]);
glBufferData( GL_ARRAY_BUFFER, 8 * sizeof(GLfloat), _pos, GL_STATIC_DRAW);
glVertexAttribPointer(0, 2, GL_FLOAT, false, 0, 0);
glEnableVertexAttribArray(0);
glBindBuffer( GL_ARRAY_BUFFER, vbo[2]);
glBufferData( GL_ARRAY_BUFFER, 8 * sizeof(GLfloat), _pos, GL_STATIC_DRAW);
glVertexAttribPointer(1, 2, GL_FLOAT, false, 0, 0);
glEnableVertexAttribArray(1);
着色器代码:
#version 150
in vec2 uvs;
in vec2 pos;
out vec2 ex_uvs;
void main(void)
gl_Position = vec4(pos.x, pos.y, 1,1);
ex_uvs = uvs;
你的绘图代码:
glDrawElements(
GL_QUADS, // mode
4, // count
GL_UNSIGNED_INT, // type
(void*)0 // element array buffer offset
);
希望对你有所帮助。试试代码,不知道有没有错别字,我用notepad++写的。
这里是如何正确渲染 VBO 的高级教程:Tutorial 9 : VBO Indexing
【讨论】:
以上是关于Opengl为啥这个着色器不起作用?的主要内容,如果未能解决你的问题,请参考以下文章