2017-12-02 265 views
0

我想繪製一些使用OpenGL與VAO和VBO對象的東西。要做到這一點,我只需要分類NSOpenGLView。默認情況下,使用OpenGL v2.1,所以,我放了一個PixelFormat,編寫代碼,並解決了所有打印錯誤。目前該應用運行良好,但沒有任何東西在窗口繪製,即使glClearColor也沒有效果。請幫助我找到並解決問題。我的操作系統是帶有OpenGL v4.1的Mac v10.12。OpenGL在Mac上沒有繪製任何東西,Objective-C

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__ */ 
+0

我看到的第一件事就是你必須在** glClear之前調用glClearColor **。否則它不起作用。下一步:在VAO設置代碼之後綁定VAO - >當VAO綁定時沒有存儲在VAO中的信息 - >所有設置均被重置。下一步:你不應該在每一幀重新創建VAO和VBO。它們應該生成一次,然後在繪圖方法中使用。 – BDL

+1

既然有太多不同的東西看起來不對,你應該考慮尋找一個好的教程。 – BDL

+0

@BDL謝謝!我會盡力解決它並更新問題。我搜索了很好的教程,但我只找到了舊教程。我試圖按照[這一個](https://github.com/beelsebob/Cocoa-GL-Tutorial) –

回答

0

經過大量努力和代碼的修改,我發現:唯一真正的問題是NSOpenGLPixelFormatAttribute陣列中的NSOpenGLPFADoubleBuffer選項。評論這個選項後,我得到了所需的輸出。

在我看來,原因是我有2個輸出圖形緩衝區。但是,代碼只執行一次,第一個緩衝區被繪製,然後交換。所以,繪製了第二個空的緩衝區。