- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
1) 我是否正确理解要使用顶点数组或 VBO 进行绘制,我需要所有属性在着色器程序链接之前调用 glBindAttribLocation 或在着色器程序成功链接之后调用 glGetAttribLocation 然后使用绑定(bind)/获取的索引在 glVertexAttribPointer 和 glEnableVertexAttribArray 调用中?
更具体地说:这三个函数——glGetAttribLocation、glVertexAttribPointer 和 glEnableVertexAttribArray——它们都有一个名为“index”的输入参数。这三个都是相同的“索引”吗?它与 glGetAttribLocation 返回的是一回事吗?
如果是:2) 我一直在 OS X 上遇到问题,我在这里描述了它:https://stackoverflow.com/questions/28093919/using-default-attribute-location-doesnt-work-on-osx-osx-opengl-bug , 但遗憾的是没有得到任何回复。
问题是,根据我绑定(bind)到我的属性的属性位置,我在屏幕上看到或看不到任何东西。我只在装有 OS X 10.9.5 的 MacBook Pro 上看到这种行为;我试过在 Linux 和 Windows 上运行相同的代码,它似乎可以独立于我的属性绑定(bind)到的位置在这些平台上运行。
这是一个展示问题的代码示例(应该在屏幕上绘制一个红色三角形):
#include <iostream>
#include <GLFW/glfw3.h>
GLuint global_program_object;
GLint global_position_location;
GLint global_aspect_ratio_location;
GLuint global_buffer_names[1];
int LoadShader(GLenum type, const char *shader_source)
{
GLuint shader;
GLint compiled;
shader = glCreateShader(type);
if (shader == 0)
return 0;
glShaderSource(shader, 1, &shader_source, NULL);
glCompileShader(shader);
glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
if (!compiled)
{
GLint info_len = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &info_len);
if (info_len > 1)
{
char* info_log = new char[info_len];
glGetShaderInfoLog(shader, info_len, NULL, info_log);
std::cout << "Error compiling shader" << info_log << std::endl;
delete info_log;
}
glDeleteShader(shader);
return 0;
}
return shader;
}
int InitGL()
{
char vertex_shader_source[] =
"attribute vec4 att_position; \n"
"attribute float dummy;\n"
"uniform float uni_aspect_ratio; \n"
"void main() \n"
" { \n"
" vec4 test = att_position * dummy;\n"
" mat4 mat_projection = \n"
" mat4(1.0 / uni_aspect_ratio, 0.0, 0.0, 0.0, \n"
" 0.0, 1.0, 0.0, 0.0, \n"
" 0.0, 0.0, -1.0, 0.0, \n"
" 0.0, 0.0, 0.0, 1.0); \n"
" gl_Position = att_position; \n"
" gl_Position *= mat_projection; \n"
" } \n";
char fragment_shader_source[] =
"void main() \n"
" { \n"
" gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); \n"
" } \n";
GLuint vertex_shader;
GLuint fragment_shader;
GLuint program_object;
GLint linked;
vertex_shader = LoadShader(GL_VERTEX_SHADER , vertex_shader_source );
fragment_shader = LoadShader(GL_FRAGMENT_SHADER, fragment_shader_source);
program_object = glCreateProgram();
if(program_object == 0)
return 1;
glAttachShader(program_object, vertex_shader );
glAttachShader(program_object, fragment_shader);
// Here any index except 0 results in observing the black screen
glBindAttribLocation(program_object, 1, "att_position");
glLinkProgram(program_object);
glGetProgramiv(program_object, GL_LINK_STATUS, &linked);
if(!linked)
{
GLint info_len = 0;
glGetProgramiv(program_object, GL_INFO_LOG_LENGTH, &info_len);
if(info_len > 1)
{
char* info_log = new char[info_len];
glGetProgramInfoLog(program_object, info_len, NULL, info_log);
std::cout << "Error linking program" << info_log << std::endl;
delete info_log;
}
glDeleteProgram(program_object);
return 1;
}
global_program_object = program_object;
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glUseProgram(global_program_object);
global_position_location = glGetAttribLocation (global_program_object, "att_position");
global_aspect_ratio_location = glGetUniformLocation(global_program_object, "uni_aspect_ratio");
GLfloat vertices[] = {-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f};
glGenBuffers(1, global_buffer_names);
glBindBuffer(GL_ARRAY_BUFFER, global_buffer_names[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 9, vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
return 0;
}
void Render()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glUseProgram(global_program_object);
glBindBuffer(GL_ARRAY_BUFFER, global_buffer_names[0]);
glVertexAttribPointer(global_position_location, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(global_position_location);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableVertexAttribArray(global_position_location);
glUseProgram(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void FreeGL()
{
glDeleteBuffers(1, global_buffer_names);
glDeleteProgram(global_program_object);
}
void SetViewport(int width, int height)
{
glViewport(0, 0, width, height);
glUseProgram(global_program_object);
glUniform1f(global_aspect_ratio_location, static_cast<GLfloat>(width) / static_cast<GLfloat>(height));
}
int main(void)
{
GLFWwindow* window;
if (!glfwInit())
return -1;
window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);
if (!window)
{
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
InitGL();
// Double the resolution to correctly draw with Retina display
SetViewport(1280, 960);
while (!glfwWindowShouldClose(window))
{
Render();
glfwSwapBuffers(window);
glfwPollEvents();
}
FreeGL();
glfwTerminate();
return 0;
}
您觉得这像是一个错误吗?任何人都可以复制它吗?如果这是一个错误,我应该在哪里报告它?
附言我也试过 SDL 而不是 GLFW,行为是一样的......
最佳答案
根据规范,您看到的行为实际上是正确的,MacOSX 与此有关,但只是以非常间接的方式。
先回答问题1):你基本上是对的。使用现代 GLSL(>=3.30),您还可以直接在着色器代码中通过 layout(location=...)
限定符指定所需的索引,而不是使用 glBindAttribLocation()
,但这只是旁注。
您面临的问题是您使用的是遗留 GL 上下文。您没有指定所需的版本,因此您将获得与旧方式的最大兼容性。现在在 Windows 上,您很可能会获得实现支持的最高版本的兼容性配置文件(在非古代 GPU 上通常为 GL3.x 或 GL4.x)。
但是,在 OSX 上,您最多只能使用 GL2.1。这就是症结所在:您的代码在 GL2.x 中无效。为了解释这一点,我必须回顾 GL 的历史。一开始是立即模式,所以你画的是
glBegin(primType);
glColor3f(r,g,b);
glVertex3f(x,y,z);
[...]
glColor3f(r,g,b);
glVertex3f(x,y,z);
glEnd();
请注意,glVertex
调用实际上创建了一个顶点。所有其他的逐顶点属性基本上都是一些可以随时设置的当前顶点状态,但是调用glVertex
会将所有这些当前属性与位置一起构成送入管道的顶点。
现在添加顶点数组后,我们得到了glVertexPointer()
、glColorPointer()
等函数,并且每个属性数组都可以通过以下方式单独启用或禁用glEnableClientState()
。基于数组的绘制调用实际上是根据 OpenGL 2.1 specification 中的立即模式定义的。作为 glDrawArrays(GLenum mode, GLint first, GLsizei count)
等同于
glBegin(mode);
for (i=0; i<count; i++)
ArrayElement(first + i);
glEnd();
定义了ArrayElement(i)
(这个源自GL 1.5 spec的措辞):
if ( normal_array_enabled )
Normal3...( <i-th normal value> );
[...] // similiar for all other bultin attribs
if ( vertex_array_enabled)
Vertex...( <i-th vertex value> );
此定义有一些微妙的后果:您必须启用GL_VERTEX_ARRAY
属性数组,否则不会绘制任何内容,因为没有等效的glVertex
产生调用。
现在,当在 GL2.0 中添加通用属性时,做出了特殊保证:通用属性 0 是内置 glVertex
属性的别名 - 因此两者可以互换使用,在立即模式下也是如此就像在数组中一样。所以 glVertexAttrib3f(0,x,y,z)
以与 glVertex3f(x,y,z)
相同的方式“创建”一个顶点。将数组与 glEnableVertexAttribArray(0)
一起使用与 glEnableClientState(GL_VERTEX_ARRAY)
一样好。
在 GL 2.1 中,ArrayElement(i)
函数现在如下所示:
if ( normal_array_enabled )
Normal3...( <i-th normal value> );
[...] // similiar for all other bultin attribs
for (a=1; a<max_attribs; a++) {
if ( generic_attrib_a_enabled )
glVertexAttrib...(a, <i-th value of attrib a> );
}
if ( generic_attrib_0_enabled)
glVertexAttrib...(0, <i-th value of attrib 0> );
else if ( vertex_array_enabled)
Vertex...( <i-th vertex value> );
现在这就是发生在你身上的事情。您绝对需要 属性 0(或旧的 GL_VERTEX_ARRAY
属性)被启用,以便为管道生成任何顶点。
请注意,理论上只启用属性 0 应该是可能的,无论它是否在着色器中使用。您应该确保相应的属性指针指向有效内存,以确保 100% 安全。所以你可以简单地检查你的属性索引 0 是否被使用,如果没有,就像你为你的真实属性所做的那样,只需将相同的指针设置为属性 0,GL 应该会很高兴。但我还没有尝试过。
在更现代的 GL 中,这些要求不再存在,没有属性 0 的绘图将按预期工作,这就是您在其他系统上看到的。也许您应该考虑切换到现代 GL,比如 >= 3.2 core profile,这样问题就不会出现(但您需要稍微更新一下代码,包括着色器)。
关于c++ - glEnableVertexAttribArray 中 "index"参数的含义和(可能)OS X OpenGL 实现中的错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28156524/
我正在尝试浏览 OS X 上的 ArcSynthesis 教程,但在调用 glEnableVertexAttribArray 后收到 OpenGL 错误“无效操作”。根据 glEnableClient
我正在阅读: Dissecting Display, Chapter 1. Hello, Triangle! 。 glEnableVertexAttribArray 到底是做什么的?我认为它可以使用给
在我看来,glVertexAttribPointer(它指定与来自 VBO 的特定数据集关联的属性索引)和 glBindAttribLocation(它指定哪个程序顶点索引分配给的属性变量名称,实际上
后者是否会贬低前者? 我正在编写希望在着色器 2.0 硬件上运行的代码,但我想使用更新的编程约定,例如 VAO。 所以我一直在使用 glVertexAttribPointer 函数而不是 glVert
我在 Android 上使用 OpenGL ES 2.0,但我认为这个问题是一个通用的 OpenGL 问题。 我正在学习 OpenGL,并试图准确了解每一帧必须调用哪些 API,而不是只调用一次。我最
我正在尝试在 LWJGL 中创建 Pong 游戏。我已经成功地画出了“球棒”和球,我还可以使用 W 和 S 键让球棒上下移动。 现在我正在尝试使用 shaders 为 bat 着色,但是当我尝试时遇到
我正在将一个正常运行的 OpenGL 应用程序从 Windows 移植到 OSX,并在调用 glEnableVertexAttribArray() 后不断收到“无效操作”(代码 1282)错误。这是渲
调用后glVertexAttribPointer(GLuint index, ...)默认情况下,顶点属性被禁用为 docs说 By default, all client-side capabili
在调用 glVertexAttribPointer(GLuint index, ...) 之后,顶点属性默认禁用为 docs说 By default, all client-side capabili
越来越郁闷了。我一直在尝试让一个简单的 hello world 类型的程序运行,但它就是没有发生。 我使用的是 Windows 7,我的显卡支持较新的 OpenGL。用 freeglut 用 C 语言
我用 SDL 窗口编写了一个 OpenGL 应用程序。在 Mac OSX 10.9 上运行 OpenGL 4.1 的核心配置文件。命令 glClearColor 效果很好,我在屏幕上得到了正确的颜色。
我正在使用 https://github.com/d3kod/Texample2 中的代码在 OpenGL 2.0 中渲染文本。该项目的解释可以在 http://primalpond.wordpres
1) 我是否正确理解要使用顶点数组或 VBO 进行绘制,我需要所有属性在着色器程序链接之前调用 glBindAttribLocation 或在着色器程序成功链接之后调用 glGetAttribLoca
我是一名优秀的程序员,十分优秀!