Chocoford
Chocoford

Reputation: 311

how to compile shader in swift, location always return -1

I have written a piece of code to compile a shader.

class DFShader {
    let ID: GLuint

    init(vPath: String, fPath: String) {
        ID = glCreateProgram()
        let vertex = compile(type: GLenum(GL_VERTEX_SHADER), path: vPath)
        let fragment = compile(type: GLenum(GL_FRAGMENT_SHADER), path: fPath)

        var success: GLint = 1
        glAttachShader(ID, vertex)
        glAttachShader(ID, fragment)
        glLinkProgram(ID)
        glGetProgramiv(ID, GLenum(GL_LINK_STATUS), &success)
        if success == GL_FALSE {
            let infoLog = UnsafeMutablePointer<GLchar>.allocate(capacity: 512)
            glGetProgramInfoLog(ID, 512, nil, infoLog)
            print("link program error. \(String.init(cString: infoLog))")
        }
        glDeleteShader(vertex)
        glDeleteShader(fragment)

        //log
        print("model", glGetUniformLocation(ID, "model")) // print 4
        print("projection", glGetUniformLocation(ID, "projection")) // print 0
        print(ID.description)
    }

    private func compile(type: GLenum, path: String) -> GLuint {
        let shader = glCreateShader(type)
        var success: GLint = 1
        do {
            let source = try String.init(contentsOfFile: path, encoding: String.Encoding.utf8).cString(using: String.Encoding.utf8)
            var castSource = UnsafePointer<GLchar>(source)
            glShaderSource(shader, 1, &castSource, nil)
            glCompileShader(shader)
            glGetShaderiv(shader, GLenum(GL_COMPILE_STATUS), &success)
            if success == GL_FALSE {
                let infoLog = UnsafeMutablePointer<GLchar>.allocate(capacity: 512)
                glGetShaderInfoLog(shader, 512, nil, &infoLog.pointee)
                print("compile error. \(String.init(cString: infoLog))")
            }
        } catch {
            print("failed to read from shader source file.")
        }
        return shader
    }

    func use() {
        glUseProgram(ID)
    }
}

//vertex shader code
#version 300 es
layout(location = 0) in vec2 position;
out vec4 VertexColor;
uniform mat4 model;
uniform mat4 projection;
uniform float pointSize;
uniform vec4 color;
void main() {
    VertexColor = color;
    gl_Position = projection * model * vec4(position, 0.0, 1.0);
gl_PointSize = 10.0f;
}

//fragment shader code
#version 300 es
precision mediump float;
out vec4 FragColor;
in vec4 VertexColor;
void main() {
    FragColor = VertexColor;
}

//In the view
...
func setupShaders() {
    shader.use()
    let projection = GLKMatrix4MakeOrtho(0, Float(width), 0, Float(height), -1, 1)
    shader.setMat4(name: "projection", value: projection)
    print("projection", glGetUniformLocation(shader.ID, "projection")) // print -1.

...
}

I want to get the right location of all uniform and attribute value.

But the uniform location I get from DFShader instance is -1. And I only get the right location in

init(vPath: String, fPath: String)

, which print 0 and 4 in the code above. However, when I get location in

setupShaders()

it return -1. I get location with shader.ID at any other place, I am also given -1.

Upvotes: 0

Views: 224

Answers (1)

Nicol Bolas
Nicol Bolas

Reputation: 473352

Shader objects don't have uniform locations. Only program objects do.

A shader object is nothing more than an intermediary between textual shaders and the final program. They don't actually do much. They don't have state to query.

Upvotes: 1

Related Questions