在Swift / Mac OS X中编译着色器

时间:2015-02-27 00:25:44

标签: macos swift opengl

我在Swift中创建了一个自定义NGOpenGLView,我正在尝试编译一些着色器。我得到着色器编译错误,但glGetShaderInfoLog什么也没有返回......无法调试。 然而,着色器使用OpenGL Shader构建器进行编译,因此我不知道出了什么问题。

这就是我编译着色器并尝试获取信息的方式,

class CustomOpenGLView : NSOpenGLView {

    override func awakeFromNib() {
        var attributes : [NSOpenGLPixelFormatAttribute] = [
            NSOpenGLPixelFormatAttribute(NSOpenGLPFADepthSize), 
            NSOpenGLPixelFormatAttribute(24), 
            NSOpenGLPixelFormatAttribute(NSOpenGLPFAOpenGLProfile), 
            NSOpenGLPixelFormatAttribute(NSOpenGLProfileVersion3_2Core), 
            NSOpenGLPixelFormatAttribute(0)]

        self.pixelFormat = NSOpenGLPixelFormat(attributes: attributes)

        initShaders()
    }
    override func drawRect(dirtyRect: NSRect) {
        glClearColor(0, 0, 0, 1)
        glClear(GLbitfield(GL_COLOR_BUFFER_BIT))
        //drawAnObject()
        glFlush()
    }


    func compileShader(shaderName: NSString, shaderType: GLenum) -> GLuint {

        let shaderPath: NSString? = NSBundle.mainBundle().pathForResource(shaderName, ofType: nil)
        if shaderPath == nil {
            println("Can't find shader \(shaderName)")
            return 0
        }
        var error: NSError? = nil
        let shaderString = NSString(contentsOfFile: shaderPath!, encoding: NSUTF8StringEncoding, error: &error)
        if shaderString == nil {
            println("Failed to set contents shader of shader file!")
            return 0
        }

        var shaderHandle: GLuint = glCreateShader(shaderType)

        var shaderStringUTF8 = shaderString!.cStringUsingEncoding(NSUTF8StringEncoding)
        var shaderStringLength: GLint = GLint(shaderString!.length)
        glShaderSource(shaderHandle, 1, &shaderStringUTF8, &shaderStringLength)

        glCompileShader(shaderHandle)

        var compileSuccess: GLint = GLint()
        glGetShaderiv(shaderHandle, GLenum(GL_COMPILE_STATUS), &compileSuccess)
        if (compileSuccess == GL_FALSE) {
            println("Failed to compile shader! \(shaderName)")
            var value: GLint = 0
            glGetShaderiv(shaderHandle, GLenum(GL_INFO_LOG_LENGTH), &value)
            var infoLog: [GLchar] = [GLchar](count: Int(value), repeatedValue: 0)
            var infoLogLength: GLsizei = 0
            glGetShaderInfoLog(shaderHandle, value, &infoLogLength, &infoLog)
            var s = NSString(bytes: infoLog, length: Int(infoLogLength), encoding: NSASCIIStringEncoding)
            println(s)
            return 0
        }
        return shaderHandle
    }

    func initShaders() {

        // Compile our vertex and fragment shaders.
        var vertexShader: GLuint = self.compileShader("geometryColor.vs", shaderType: GLenum(GL_VERTEX_SHADER))
        var fragmentShader: GLuint = self.compileShader("color.fs", shaderType: GLenum(GL_FRAGMENT_SHADER))
    // ... etc
    }
}

vs shader就是这个,

attribute vec3 position;
attribute vec4 color;
uniform mat4 Pmatrix;
uniform mat4 Vmatrix;
uniform mat4 Mmatrix;
varying vec4 vColor;
void main(void) { // pre-built function
    gl_Position = Pmatrix * Vmatrix * Mmatrix * vec4(position, 1.);
    vColor = color;
}

但我也尝试过更新的语法

in vec3 position;
in vec4 color;
uniform mat4 Pmatrix;
uniform mat4 Vmatrix;
uniform mat4 Mmatrix;
out vec4 vColor;
void main(void) { // pre-built function
    gl_Position = Pmatrix * Vmatrix * Mmatrix * vec4(position, 1.);
    vColor = color;
}

glClear正在工作,所以视图本身似乎很好。 如何调试这个?

2 个答案:

答案 0 :(得分:0)

尝试在创建和编译着色器之前使上下文保持最新状态,我不熟悉swift,但在您发布的代码中似乎没有做任何事情。

我遇到了同样的问题,这个答案还有另一个问题,但我找不到......

答案 1 :(得分:0)

使用桥接文件在objc中实现。这对我有用。 对于桥接标题:

/**
 * return 0 on failure
 */
extern GLuint CompileShader(GLenum shaderType, NSString* _Nonnull source);
/***
  * get last gl error message
  */
extern NSString* _Nullable GetLastGLErrorMessage();

其实施:

static NSString* ___AM_global_error_message__;

GLuint CompileShader(GLenum shaderType, NSString* _Nonnull source)
{
    GLuint shader = glCreateShader(shaderType);
    const GLchar* glSource = (GLchar*) source.UTF8String;
    glShaderSource(shader, 1, &glSource, 0);
    glCompileShader(shader);
    GLint compileResult;
    glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
    if (GL_FALSE == compileResult)
    {
        GLchar messages[4090];
        glGetShaderInfoLog(shader, sizeof(messages), 0, &messages[0]);
        NSLog(@"- shader compile error!!! : %s", messages);
        ___AM_global_error_message__ = [NSString stringWithFormat:@"%s", messages];
        return shader;
    }
    return shader;
}

NSString* GetLastGLErrorMessage()
{
    return ___AM_global_error_message__;
}

在swift文件中使用:

private func __createShader(type: GLenum, filename: String) -> GLuint {
    let resourcePath = NSBundle.mainBundle().pathForResource(filename, ofType: "shader")
    // failed to load the file return 0 indicates error occured.
    guard resourcePath != nil else { return 0 }
    let fileContent = try! String(contentsOfFile: resourcePath!)
    let ret = CompileShader(type, fileContent)
    if ret == 0
    {
        print(GetLastGLErrorMessage())
        return 0
    }
    return ret
}