// CreateProgram creates, compiles, and links a gl.Program. func CreateProgram(vertexSrc, fragmentSrc string) (gl.Program, error) { program := gl.CreateProgram() if !program.Valid() { return gl.Program{}, fmt.Errorf("glutil: no programs available") } vertexShader, err := loadShader(gl.VERTEX_SHADER, vertexSrc) if err != nil { return gl.Program{}, err } fragmentShader, err := loadShader(gl.FRAGMENT_SHADER, fragmentSrc) if err != nil { gl.DeleteShader(vertexShader) return gl.Program{}, err } gl.AttachShader(program, vertexShader) gl.AttachShader(program, fragmentShader) gl.LinkProgram(program) // Flag shaders for deletion when program is unlinked. gl.DeleteShader(vertexShader) gl.DeleteShader(fragmentShader) if gl.GetProgrami(program, gl.LINK_STATUS) == 0 { defer gl.DeleteProgram(program) return gl.Program{}, fmt.Errorf("glutil: %s", gl.GetProgramInfoLog(program)) } return program, nil }
func newShaderProgram(ctx *context, vsSource, fsSource string) *shaderProgram { vs := compile(vsSource, gl.VERTEX_SHADER) fs := compile(fsSource, gl.FRAGMENT_SHADER) program := gl.CreateProgram() gl.AttachShader(program, vs) gl.AttachShader(program, fs) gl.LinkProgram(program) if gl.GetProgrami(program, gl.LINK_STATUS) != gl.TRUE { panic(gl.GetProgramInfoLog(program)) } gl.UseProgram(program) checkError() uniformCount := gl.GetProgrami(program, gl.ACTIVE_UNIFORMS) uniforms := make([]shaderUniform, uniformCount) textureUnit := 0 for i := range uniforms { name, size, ty := gl.GetActiveUniform(program, uint32(i)) location := gl.GetUniformLocation(program, name) uniforms[i] = shaderUniform{ name: name, size: size, ty: shaderDataType(ty), location: location, textureUnit: textureUnit, } if ty == gl.SAMPLER_2D { textureUnit++ } } attributeCount := gl.GetProgrami(program, gl.ACTIVE_ATTRIBUTES) attributes := make([]shaderAttribute, attributeCount) for i := range attributes { name, size, ty := gl.GetActiveAttrib(program, uint32(i)) location := gl.GetAttribLocation(program, name) attributes[i] = shaderAttribute{ name: name, size: size, ty: shaderDataType(ty), location: location, } } ctx.stats.shaderProgramCount++ return &shaderProgram{ program: program, uniforms: uniforms, attributes: attributes, } }
func dumpProgramError(program gl.Program, name string) error { str := gl.GetProgramInfoLog(program) msg := fmt.Sprintf("Program %s error:\n%s\n", name, str) dumpLog(msg) return errors.New(msg) }