尝试使用 C++ 将着色器应用于 OpenGL 中的顶点数组时出现问题;
我有 4 维顶点(X,Y,A,B),我想将其绘制为 6 个独立的 2D 图(XxY,XxA,XxB,YxA,...)
我的顶点定义如下:
GLint data[MAX_N_POINT][4];
我可以绘制2D 图的第一个 (X,Y) 就可以了:
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(4, GL_INT, 4*sizeof(GLint), &data[0][0]);
glDrawArrays(GL_POINTS, 0, MAX_N_POINT-1);
glDisableclientState(GL_VERTEX_ARRAY);
为了绘制其他 2D 图(XxA、AxB 等...),我决定使用一个着色器根据我想要绘制的尺寸调整顶点的 X、Y、Z、W 尺寸。:
uniform int axes;
void main()
{
vec2 point;
if (axes == 0) {
point = gl_Vertex.xy;
} else if (axes == 1) {
point = gl_Vertex.xz;
} else if (axes == 2) {
point = gl_Vertex.xw;
} else if (axes == 3) {
point = gl_Vertex.yz;
} else if (axes == 4) {
point = gl_Vertex.yw;
} else if (axes == 5) {
point = gl_Vertex.zw;
}
gl_Position = gl_ModelViewProjectionMatrix * vec4(point.xy, 0.0, 1.0);
gl_FrontColor = gl_Color;
gl_BackColor = gl_Color;
}
我已成功加载、编译、添加到着色器到程序,并链接该程序。
现在我有了着色器程序,但不清楚如何使用该程序,这会影响我的顶点数组的绘制方式。我已经尝试了以下方法,但它似乎没有效果,因为它绘制的东西与没有着色器时完全相同:
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(4, GL_INT, 4*sizeof(GLint), &data1[0][0]);
//New shader code here
glUseProgram(shaderProg);
int plotAxes = rand()%4;
GLint axes = glGetUniformLocation(shaderProg, "axes");
glUniform1i(axes, plotAxes);
glDrawArrays(GL_POINTS, 0, MAX_N_POINT-1);
glDisableClientState(GL_VERTEX_ARRAY);
glUseProgram(0);
是否有一些我遗漏或不正确理解的基本内容?
编辑 2:我已根据 Christian 的建议更新了着色器代码。我还验证了着色加载没有错误,但是如果我在调用 glUseProgram 后检查 OpenGL 错误,则会收到 OpenGL 错误:无效操作
错误。
编辑 3:这是最终有效的着色器:
uniform int axes;
void main()
{
vec4 point;
if (axes == 0) {
point = gl_Vertex;
} else if (axes == 1) {
point = gl_Vertex.xzyw;
} else if (axes == 2) {
point = gl_Vertex.xwzy;
} else if (axes == 3) {
point = gl_Vertex.yzxw;
} else if (axes == 4) {
point = gl_Vertex.ywxz;
} else if (axes == 5) {
point = gl_Vertex.zwxy;
}
point.z = 0.0;
point.w = 1.0;
// eliminate w point
gl_Position = gl_ModelViewProjectionMatrix * point;
gl_FrontColor = gl_Color;
gl_BackColor = gl_Color;
}
I have 4 dimensional vertices(X,Y,A,B) that I'd like to draw as 6 separate 2D plots (XxY, XxA, XxB, YxA, ...)
My vertices are defined as follows:
GLint data[MAX_N_POINT][4];
I can draw the first (X,Y) of the 2D plots just fine with:
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(4, GL_INT, 4*sizeof(GLint), &data[0][0]);
glDrawArrays(GL_POINTS, 0, MAX_N_POINT-1);
glDisableclientState(GL_VERTEX_ARRAY);
To draw the other 2D plots (XxA, AxB, etc...) I've decided to use a shader that swizzles the X,Y,Z,W dimensions of the vertices depending on which dimensions I want to draw.:
uniform int axes;
void main()
{
vec2 point;
if (axes == 0) {
point = gl_Vertex.xy;
} else if (axes == 1) {
point = gl_Vertex.xz;
} else if (axes == 2) {
point = gl_Vertex.xw;
} else if (axes == 3) {
point = gl_Vertex.yz;
} else if (axes == 4) {
point = gl_Vertex.yw;
} else if (axes == 5) {
point = gl_Vertex.zw;
}
gl_Position = gl_ModelViewProjectionMatrix * vec4(point.xy, 0.0, 1.0);
gl_FrontColor = gl_Color;
gl_BackColor = gl_Color;
}
I've successfully loaded, compiled, added to the shader to a program, and linked the program.
Now that I have the shader program its not clear how to use the program such that is affects the way my vertex arrays are drawn. I've tried the following but it appears to have no effect as it draws things exactly like there were without the shader:
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(4, GL_INT, 4*sizeof(GLint), &data1[0][0]);
//New shader code here
glUseProgram(shaderProg);
int plotAxes = rand()%4;
GLint axes = glGetUniformLocation(shaderProg, "axes");
glUniform1i(axes, plotAxes);
glDrawArrays(GL_POINTS, 0, MAX_N_POINT-1);
glDisableClientState(GL_VERTEX_ARRAY);
glUseProgram(0);
Is there something fundamental that I am missing or don't understand properly?
Edit 2: I've updated the shader code per Christian's suggestions. I've also verified that shade loads without errors however if I check for OpenGl errors after I call glUseProgram I get an OpenGL Error: invalid operation
error.
Edit 3: Here is the final shader that worked:
uniform int axes;
void main()
{
vec4 point;
if (axes == 0) {
point = gl_Vertex;
} else if (axes == 1) {
point = gl_Vertex.xzyw;
} else if (axes == 2) {
point = gl_Vertex.xwzy;
} else if (axes == 3) {
point = gl_Vertex.yzxw;
} else if (axes == 4) {
point = gl_Vertex.ywxz;
} else if (axes == 5) {
point = gl_Vertex.zwxy;
}
point.z = 0.0;
point.w = 1.0;
// eliminate w point
gl_Position = gl_ModelViewProjectionMatrix * point;
gl_FrontColor = gl_Color;
gl_BackColor = gl_Color;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
在启用/使用程序(
glUseProgram
)后,您必须设置axes
统一(glUniform1i
),否则没有任何效果(并且你的axes制服保持其默认值,似乎是0)。但我希望您的程序还包含一个使用您的passcolor
变化的有效片段着色器,因为固定功能片段处理器不知道如何处理此变化。顺便说一句,虽然如果所有顶点都采用相同的路径,则不会花费太多成本,但从性能角度来看,使用 6 个不同的着色器将是一个更好的主意。您仍然可以使用预处理器宏来减少写入开销。
编辑:从您的更新来看,您似乎没有使用特殊的片段着色器。因此,您只需将内置片段管道与顶点着色器一起使用即可。尽管这是可能的,但您仍然需要匹配两个阶段才能协同工作。您的
passcolor
变化完全没有用,因为固定功能管道不知道如何处理它。只需使用内建颜色变化并替换为
您还应该检查您的着色器是否成功编译和链接,并检查信息日志,以防万一,因为我认为您的程序由于上述不同的不一致而无法链接。所以你最终没有使用着色器(并且有一堆
GL_INVALID_OPERATION
)而没有注意到它。You have to set the
axes
uniform (glUniform1i
) after you enabled/use the program (glUseProgram
), otherwise it doesn't have any effect (and youraxes
uniform keeps its default value, which seems to be 0). But I hope your program also contains a valid fragment shader that uses yourpasscolor
varying, as the fixed function fragment processor doesn't know what to do with this varying.And by the way, although it won't cost you that much if all vertices take the same path anyway, but using 6 different shaders would be a better idea performance-wise. You can still use preprocessor macros to reduce the writing overhead.
EDIT: From your update it seems you don't use a special fragment shader. So you just use the builtin fragment pipeline together with your vertex shader. Whereas this is possible, you still have to match both stages to work together. Your
passcolor
varying is completely useless, as the fixed-function pipeline doesn't know what to do with it. Just use the buitlin color varying and replacewith
You should also check if your shaders compile and link successfully and inspect the info log in case they don't, as I suppose your program won't link because of the above varying inconstencies. So you end up with not using the shader (and with a bunch of
GL_INVALID_OPERATION
s) without noting it.