func (s shape) draw(ctx *context, shader *shaderProgram, ub uniformBindings) { shader.bind(ctx, s.vb, ub) if s.ib != nil { ctx.getOrCreateIndexBufferContext(s.ib).render(s.drawMode) } else { gl.DrawArrays(gl.Enum(s.drawMode), 0, s.vb.count) } shader.unbind(ctx) checkError() }
func compile(source string, ty int) gl.Shader { shader := gl.CreateShader(gl.Enum(ty)) gl.ShaderSource(shader, source) gl.CompileShader(shader) if gl.GetShaderi(shader, gl.COMPILE_STATUS) != gl.TRUE { panic(gl.GetShaderInfoLog(shader)) } checkError() return shader }
func (s *glShader) createShader(name, header, opts, vShader, fShader string) error { program := gl.CreateProgram() vertexShader := gl.CreateShader(gl.VERTEX_SHADER) gl.ShaderSource(vertexShader, strings.Join([]string{header, opts, vShader}, "\n")) gl.CompileShader(vertexShader) status := gl.Enum(gl.GetShaderi(vertexShader, gl.COMPILE_STATUS)) if status != gl.TRUE { return dumpShaderError(vertexShader, name, "vert") } fragmentShader := gl.CreateShader(gl.FRAGMENT_SHADER) gl.ShaderSource(fragmentShader, strings.Join([]string{header, opts, fShader}, "\n")) gl.CompileShader(fragmentShader) status = gl.Enum(gl.GetShaderi(fragmentShader, gl.COMPILE_STATUS)) if status != gl.TRUE { return dumpShaderError(fragmentShader, name, "vert") } gl.AttachShader(program, vertexShader) gl.AttachShader(program, fragmentShader) gl.LinkProgram(program) status = gl.Enum(gl.GetProgrami(program, gl.LINK_STATUS)) if status != gl.TRUE { return dumpProgramError(program, name) } s.vertexAttrib = gl.GetAttribLocation(program, "vertex") s.tcoordAttrib = gl.GetAttribLocation(program, "tcoord") s.program = program s.vertex = vertexShader s.fragment = fragmentShader return nil }
func (u *shaderUniform) bind(context *context, v interface{}) { switch u.ty { case stFloatMat2: gl.UniformMatrix2fv(u.location, v.([]float32)) case stFloatMat3: switch m := v.(type) { case math.Mat3: gl.UniformMatrix3fv(u.location, m[:]) case []float32: gl.UniformMatrix3fv(u.location, m) } case stFloatMat4: gl.UniformMatrix4fv(u.location, v.([]float32)) case stFloatVec1: switch v := v.(type) { case float32: gl.Uniform1f(u.location, v) case []float32: gl.Uniform1fv(u.location, v) } case stFloatVec2: switch v := v.(type) { case math.Vec2: gl.Uniform2fv(u.location, []float32{v.X, v.Y}) case []float32: if len(v)%2 != 0 { panic(fmt.Errorf("Uniform '%s' of type vec2 should be an float32 array with a multiple of two length", u.name)) } gl.Uniform2fv(u.location, v) } case stFloatVec3: switch v := v.(type) { case math.Vec3: gl.Uniform3fv(u.location, []float32{v.X, v.Y, v.Z}) case []float32: if len(v)%3 != 0 { panic(fmt.Errorf("Uniform '%s' of type vec3 should be an float32 array with a multiple of three length", u.name)) } gl.Uniform3fv(u.location, v) } case stFloatVec4: switch v := v.(type) { case math.Vec4: gl.Uniform4fv(u.location, []float32{v.X, v.Y, v.Z, v.W}) case gxui.Color: gl.Uniform4fv(u.location, []float32{v.R, v.G, v.B, v.A}) case []float32: if len(v)%4 != 0 { panic(fmt.Errorf("Uniform '%s' of type vec4 should be an float32 array with a multiple of four length", u.name)) } gl.Uniform4fv(u.location, v) } case stSampler2d: tc := v.(*textureContext) gl.ActiveTexture(gl.Enum(gl.TEXTURE0 + u.textureUnit)) gl.BindTexture(gl.TEXTURE_2D, tc.texture) gl.Uniform1i(u.location, u.textureUnit) default: panic(fmt.Errorf("Uniform of unsupported type %s", u.ty)) } }
func (c *indexBufferContext) render(drawMode drawMode) { gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, c.buffer) gl.DrawElements(gl.Enum(drawMode), c.length, gl.Enum(c.ty), 0) gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, gl.Buffer{}) checkError() }
func (a shaderAttribute) attribPointer(size int32, ty uint32, normalized bool, stride int32, offset int) { gl.VertexAttribPointer(a.location, int(size), gl.Enum(ty), normalized, int(stride), offset) }