func (r *Renderer) drawMesh(ns *nativeShader, m *gfx.Mesh) { // Grab the native mesh. native := m.NativeMesh.(*nativeMesh) // Use vertices data. location, ok := r.findAttribLocation(ns, "Vertex") if ok { r.render.BindBuffer(gl.ARRAY_BUFFER, native.vertices) r.render.EnableVertexAttribArray(location) defer r.render.DisableVertexAttribArray(location) r.render.VertexAttribPointer(location, 3, gl.FLOAT, gl.GLBool(false), 0, nil) } if native.colors != 0 { // Use colors data. location, ok = r.findAttribLocation(ns, "Color") if ok { r.render.BindBuffer(gl.ARRAY_BUFFER, native.colors) r.render.EnableVertexAttribArray(location) defer r.render.DisableVertexAttribArray(location) r.render.VertexAttribPointer(location, 4, gl.FLOAT, gl.GLBool(false), 0, nil) } } if native.bary != 0 { // Use bary data. location, ok = r.findAttribLocation(ns, "Bary") if ok { r.render.BindBuffer(gl.ARRAY_BUFFER, native.bary) r.render.EnableVertexAttribArray(location) defer r.render.DisableVertexAttribArray(location) r.render.VertexAttribPointer(location, 3, gl.FLOAT, gl.GLBool(false), 0, nil) } } // Use each texture coordinate set data. for index, texCoords := range native.texCoords { name := texCoordName(index) location, ok = r.findAttribLocation(ns, name) if ok { r.render.BindBuffer(gl.ARRAY_BUFFER, texCoords) r.render.EnableVertexAttribArray(location) defer r.render.DisableVertexAttribArray(location) r.render.VertexAttribPointer(location, 2, gl.FLOAT, gl.GLBool(false), 0, nil) } } if native.indicesCount > 0 { // Draw indexed mesh. r.render.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, native.indices) r.render.DrawElements(gl.TRIANGLES, native.indicesCount, gl.UNSIGNED_INT, nil) } else { // Draw regular mesh. r.render.DrawArrays(gl.TRIANGLES, 0, native.verticesCount) } // Unbind buffer to avoid carrying OpenGL state. r.render.BindBuffer(gl.ARRAY_BUFFER, 0) }
func (r *Renderer) stateDepthWrite(enabled bool) { if r.last.depthWrite != enabled { r.last.depthWrite = enabled if enabled { r.render.DepthMask(gl.GLBool(true)) } else { r.render.DepthMask(gl.GLBool(false)) } } }
func (r *Renderer) stateColorWrite(cr, g, b, a bool) { cw := [4]bool{cr, g, b, a} if r.last.colorWrite != cw { r.last.colorWrite = cw r.render.ColorMask( gl.GLBool(cr), gl.GLBool(g), gl.GLBool(b), gl.GLBool(a), ) } }
func (r *Renderer) updateUniform(native *nativeShader, name string, value interface{}) { location := r.findUniformLocation(native, name) if location == -1 { // The uniform is not used by the shader program and should just be // dropped. return } switch v := value.(type) { case texSlot: // Special case: Texture input uniform. r.render.Uniform1i(location, int32(v)) case bool: var intBool int32 if v { intBool = 1 } r.render.Uniform1iv(location, 1, &intBool) case float32: r.render.Uniform1fv(location, 1, &v) case []float32: if len(v) > 0 { r.render.Uniform1fv(location, uint32(len(v)), &v[0]) } case gfx.Vec3: r.render.Uniform3fv(location, 1, &v.X) case []gfx.Vec3: if len(v) > 0 { r.render.Uniform3fv(location, uint32(len(v)), &v[0].X) } case gfx.Mat4: r.render.UniformMatrix4fv(location, 1, gl.GLBool(false), &v[0][0]) case []gfx.Mat4: if len(v) > 0 { r.render.UniformMatrix4fv(location, uint32(len(v)), gl.GLBool(false), &v[0][0][0]) } default: // We don't know of the type at all, ignore it. } }