【问题标题】:OpenGL draws nothing on Mac, Objective-COpenGL 在 Mac、Objective-C 上什么都不画
【发布时间】:2018-05-16 15:23:51
【问题描述】:

我正在尝试使用带有 VAO 和 VBO 对象的 OpenGL 绘制一些东西。为此,我只是将NSOpenGLView 子类化。默认使用的是OpenGL v2.1,所以,我放了一个PixelFormat,写了代码,解决了所有打印的错误。目前该应用程序运行良好,但窗口上没有任何内容,即使glClearColor 也没有效果。请帮助我找到并解决问题。我的操作系统是带有 OpenGL v4.1 的 Mac v10.12。

MyOpenGLView.m,第 1 部分:

#import "MyOpenGLView.h"
#include <OpenGL/gl3.h>
#include "error.h"

static const char *vertexShaderSource =
"#version 410\n"
"in vec3 posAttr;\n"
"in vec3 colAttr;\n"
"out vec3 col;\n"
"void main() {\n"
"   col = colAttr;\n"
"   gl_Position.xyz = posAttr;\n"
"   gl_Position.w = 1.0;\n"
"   col = colAttr;\n"
"}\n";

static const char *fragmentShaderSource =
"#version 410\n"
"in vec3 col;\n"
"out vec4 color;\n"
"void main() {\n"
"   color.rgb = col;\n"
"   color.a = 1.0;\n"
//"   color = vec4(1,1,1,1);\n"
"}\n";

// Shader properties
GLuint m_posAttr;
GLuint m_colAttr;
GLuint program;

// Arrays of positions and colors
float fTriangle[9];
float fTriangleColor[9];

// Low-level VBOs and VBAs
GLuint uiVBO[2];
GLuint uiVAO[1];


GLuint makeShader(GLenum type, const char *source) {
    GLuint shader;

    shader = glCreateShader(type);
    GetError();
    glShaderSource(shader, 1, &source, NULL);
    GetError();
    glCompileShader(shader);
    GetError();

#if defined(DEBUG)
    GLint logLength;

    glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logLength);
    GetError();
    if (logLength > 0) {
        GLchar *log = malloc((size_t)logLength);
        glGetShaderInfoLog(shader, logLength, &logLength, log);
        GetError();
        NSLog(@"Shader compilation failed with error:\n%s", log);
        free(log);
    }
#endif

    GLint status;
    glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
    GetError();
    if (0 == status) {
        glDeleteShader(shader);
        GetError();
        NSLog(@"Shader compilation failed from code!");
        assert(0);
    }

    return shader;
}

MyOpenGLView.m,第 2 部分:

//// General staff

@implementation MyOpenGLView

- (void)awakeFromNib {
    // Positions and colors of figures
    fTriangle[0] = -0.4f; fTriangle[1] = 0.1f; fTriangle[2] = 0.0f;
    fTriangle[3] = 0.4f; fTriangle[4] = 0.1f; fTriangle[5] = 0.0f;
    fTriangle[6] = 0.0f; fTriangle[7] = 0.7f; fTriangle[8] = 0.0f;
    fTriangleColor[0] = 1.0f; fTriangleColor[1] = 0.0f; fTriangleColor[2] = 0.0f;
    fTriangleColor[3] = 0.0f; fTriangleColor[4] = 1.0f; fTriangleColor[5] = 0.0f;
    fTriangleColor[6] = 0.0f; fTriangleColor[7] = 0.0f; fTriangleColor[8] = 1.0f;


    NSOpenGLPixelFormatAttribute attrs[] = {
        NSOpenGLPFADoubleBuffer,
        NSOpenGLPFADepthSize, 24,
        NSOpenGLPFAOpenGLProfile,
        NSOpenGLProfileVersion4_1Core,
        0
    };
    NSOpenGLPixelFormat *pf = [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs];
    if (!pf) {
        NSLog(@"No OpenGL pixel format");
    }
    NSOpenGLContext* context = [[NSOpenGLContext alloc] initWithFormat:pf shareContext:nil];
    [self setPixelFormat:pf];
    [self setOpenGLContext:context];
    NSLog(@"%s", glGetString(GL_VERSION));
    GetError();

    GLuint vertexShader = makeShader(GL_VERTEX_SHADER, vertexShaderSource);
    GLuint fragmentShader = makeShader(GL_FRAGMENT_SHADER, fragmentShaderSource);

    program = glCreateProgram();
    GetError();
    glAttachShader(program, vertexShader);
    GetError();
    glAttachShader(program, fragmentShader);
    GetError();
    glLinkProgram(program);
    GetError();
    GLint status;
    glGetProgramiv(program, GL_LINK_STATUS, &status);
    GetError();
    if (0 == status) {
        NSLog(@"Failed to link shader program");
        assert( 0 );
    }

    m_posAttr = glGetAttribLocation(program, "posAttr");
    GetError();
    m_colAttr = glGetAttribLocation(program, "colAttr");
    GetError();

    glGenVertexArrays(1, &uiVAO[0]);
    glGenBuffers(2, &uiVBO[0]);
    GetError();
}

- (void)drawRect:(NSRect)dirtyRect {
    [super drawRect:dirtyRect];

    glClearColor(0, 0, 0, 0);
    glClear(GL_COLOR_BUFFER_BIT);

    glUseProgram(program);
    GetError();

    glBindVertexArray(uiVAO[0]);
    GetError();

    glBindBuffer(GL_ARRAY_BUFFER, uiVBO[0]);
    glBufferData(GL_ARRAY_BUFFER, 9*sizeof(float), fTriangle, GL_STATIC_DRAW);
    glEnableVertexAttribArray(m_posAttr);
    GetError();
    glVertexAttribPointer(m_posAttr, 3, GL_FLOAT, GL_FALSE, 0, 0);
    GetError();

    glBindBuffer(GL_ARRAY_BUFFER, uiVBO[1]);
    glBufferData(GL_ARRAY_BUFFER, 9*sizeof(float), fTriangleColor, GL_STATIC_DRAW);
    glEnableVertexAttribArray(m_colAttr);
    GetError();
    glVertexAttribPointer(m_colAttr, 3, GL_FLOAT, GL_FALSE, 0, 0);
    GetError();

    glDrawArrays(GL_TRIANGLES, 0, 3);
    GetError();

    glDisableVertexAttribArray(m_posAttr);
    glDisableVertexAttribArray(m_colAttr);

    glFlush();
    GetError();
}

- (void)dealloc {
    glDeleteProgram(program);
    glDeleteBuffers(2, uiVBO);
    glDeleteVertexArrays(1, uiVAO);
    GetError();
}

@end

error.h:

//// Prints OpenGL errors

#ifndef __ERROR_H__
#define __ERROR_H__

#include <stdlib.h>
#include <assert.h>

#ifdef  DEBUG

#define GetError( )\
{\
for ( GLenum Error = glGetError( ); ( GL_NO_ERROR != Error ); Error = glGetError( ) )\
{\
switch ( Error )\
{\
case GL_INVALID_ENUM:      printf( "\n%s\n\n", "GL_INVALID_ENUM"      ); assert( 0 ); break;\
case GL_INVALID_VALUE:     printf( "\n%s\n\n", "GL_INVALID_VALUE"     ); assert( 0 ); break;\
case GL_INVALID_OPERATION: printf( "\n%s\n\n", "GL_INVALID_OPERATION" ); assert( 0 ); break;\
case GL_OUT_OF_MEMORY:     printf( "\n%s\n\n", "GL_OUT_OF_MEMORY"     ); assert( 0 ); break;\
default:                                                                              break;\
}\
}\
}

#else

#define GetError( )

#endif /*   DEBUG     */
#endif /* __ERROR_H__ */

【问题讨论】:

  • 我看到的第一件事是你必须打电话给glClearColor 之前 glClear。否则没有效果。下一步:在 VAO 设置代码之后绑定 VAO -> 没有信息存储在 VAO 中 -> 当 VAO 被绑定时,一切都被重置。下一步:您不应该在每一帧中重新创建 VAO 和 VBO。它们应该生成一次,然后在绘图方法中使用。
  • 既然有很多不同的东西看起来不对,你应该考虑找一个好的教程。
  • @BDL 谢谢!我将尝试解决它并更新问题。我搜索了很好的教程,但我只找到了旧的。我试着关注this one

标签: objective-c c macos opengl shader


【解决方案1】:

经过大量努力和代码修改后,我发现了:唯一真正的问题是 NSOpenGLPixelFormatAttribute 数组中的 NSOpenGLPFADoubleBuffer 选项。评论此选项后,我得到了所需的输出。

在我看来,原因是我有 2 个输出图形缓冲区。然而,代码被执行了一次,第一个缓冲区被绘制然后交换。因此,绘制了第二个空缓冲区。

【讨论】:

    猜你喜欢
    • 2012-02-16
    • 2015-09-24
    • 1970-01-01
    • 2023-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多