我正在尝试在我的程序中创建自己的顶点和片段着色器(这基本上是一个用VBO显示三角形的非常简单的程序)。但是,当我尝试运行它时,我总是会看到一个没有任何显示的黑屏。我检查了编译日志,它返回没有错误。我还没有使用我自己的自定义着色器运行程序,这让我想知道我在这里做错了什么。我在OpenGL 3.2和GLSL 1.5上运行我的代码
以下是我正在尝试运行的代码
GLuint vbo;
GLfloat data[] = {0.0, 0.0, -5.0,
1.0, 0.0, -5.0,
1.0, 1.0, -5.0
};
const char *vertexShader = "\n\
#version 150\n\
\n\
layout (location=0) in vec4 position;\n\
void main()\n\
{\n\
gl_Position = position;\n\
}\n\
";
const char *fragmentShader = "\n\
#version 150\n\
\n\
out vec4 outColor;\n\
\n\
void main()\n\
{\n\
outColor = vec4(1.0, 0.0, 0.0, 1.0);\n\
}";
- (void)drawRect:(NSRect)dirtyRect
{
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glUseProgram(programId);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, 0);
glDrawArrays(GL_TRIANGLES, 0, sizeof(data));
glFlush();
glDisableClientState(GL_VERTEX_ARRAY);
}
-(void)reshape
{
glViewport(0, 0, w, h);
gluPerspective(45.0, //The camera angle
(double)w / (double)h, //The width-to-height ratio
1.0, //The near z clipping coordinate
200.0);
}
-(void)prepareOpenGL
{
glEnable(GL_DEPTH_TEST);
glGenBuffersARB(1, &vbo);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(data), data, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, 0, 0, 0);
vertexShaderId = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShaderId, 1, &vertexShader, NULL);
glCompileShader(vertexShaderId);
GLint completed;
glGetShaderiv(vertexShaderId, GL_COMPILE_STATUS, &completed);
if (!completed)
{
GLint length;
GLchar *log;
glGetShaderiv(vertexShaderId, GL_INFO_LOG_LENGTH, &length);
log = (GLchar *)malloc(length);
glGetShaderInfoLog(vertexShaderId, length, &length, log);
fprintf(stderr, "Vertex compile log = '%s'\n", log);
}
fragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShaderId, 1, &fragmentShader, NULL);
glCompileShader(fragmentShaderId);
GLint complete;
glGetShaderiv(fragmentShaderId, GL_COMPILE_STATUS, &complete);
if (!complete)
{
GLint length;
GLchar *log;
glGetShaderiv(fragmentShaderId, GL_INFO_LOG_LENGTH, &length);
log = (GLchar *)malloc(length);
glGetShaderInfoLog(fragmentShaderId, length, &length, log);
fprintf(stderr, "fragment compile log = '%s'\n", log);
}
programId = glCreateProgram();
glAttachShader(programId, vertexShaderId);
glAttachShader(programId, fragmentShaderId);
glLinkProgram(programId);
glUseProgram(programId);
}
答案 0 :(得分:9)
这里有几个问题。从上到下:
GLfloat data[] = {0.0, 0.0, -5.0,
1.0, 0.0, -5.0,
1.0, 1.0, -5.0
};
此数据不可见,因为Z值超出了查看量[-1,1]。尝试使用0.0代替。
#version 150\n\
\n\
layout (location=0) in vec4 position;
layout(location=0)
仅适用于两种情况下的顶点着色器输入:
#version 150
。#extension
声明才能在着色器中激活它。另外,我知道OSX的GL 3.2支持确实不提供此扩展。所以你需要用老式的方式来做:用glBindAttribLocation
。 Use this function before you link your program
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, 0);
这不仅是不必要的,它还会对您要完成的操作产生主动破坏性,因为它会在您尝试渲染时导致生成OpenGL错误。
如果您使用的是通用属性,则不需要旧式属性。
glDrawArrays(GL_TRIANGLES, 0, sizeof(data));
sizeof(data)
是data
数组的字节中的大小。在大多数机器上,那将是36.你不渲染36个顶点;你正在渲染三个。所以这应该是:
glDrawArrays(GL_TRIANGLES, 0, 3);
gluPerspective(45.0, //The camera angle
(double)w / (double)h, //The width-to-height ratio
1.0, //The near z clipping coordinate
200.0);
这不是一个完全没有意义的问题。您使用着色器进行渲染,而您没有使用内置矩阵。这确实没有。
glGenBuffersARB(1, &vbo);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(data), data, GL_STATIC_DRAW);
这也可能不是“问题”,但也可能是。以“ARB”结尾的函数和枚举器代表OpenGL扩展。所以你正在使用ARB_vertex_buffer_object扩展所公开的函数。
此扩展程序自GL 1.4以来一直是核心。实际上,您甚至没有使用一致扩展名(这可能会出现问题)。您正在使用ARB扩展设置缓冲区的数据,但在渲染时使用核心功能。
放弃ARB扩展程序并使用核心功能。
log = (GLchar *)malloc(length);
glGetShaderInfoLog(vertexShaderId, length, &length, log);
fprintf(stderr, "Vertex compile log = '%s'\n", log);
这不会导致错误,但是......您对free
的呼叫在哪里?
glLinkProgram(programId);
glUseProgram(programId);
编辑着色器或链接程序后,总是 check for errors。
您的代码似乎已经从各种来源复制粘贴,形成某种科学怪人的程序。您的大部分问题源于不同的代码,这些代码与您计划使用它们的方式有所不同。你真的应该调查这些东西是如何运作的;这样,你就不会遇到这些问题。