func LoadTexture(name string) (tex gl.Texture, err error) { imgFile, err := asset.Open(name) if err != nil { return } img, _, err := image.Decode(imgFile) if err != nil { return } rgba := image.NewRGBA(img.Bounds()) image_draw.Draw(rgba, rgba.Bounds(), img, image.Point{0, 0}, image_draw.Src) tex = gl.CreateTexture() gl.ActiveTexture(gl.TEXTURE0) gl.BindTexture(gl.TEXTURE_2D, tex) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE) gl.TexImage2D( gl.TEXTURE_2D, 0, rgba.Rect.Size().X, rgba.Rect.Size().Y, gl.RGBA, gl.UNSIGNED_BYTE, rgba.Pix) return }
func (video *Video) drawFrame() { gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) gl.UseProgram(video.prog) gl.ActiveTexture(gl.TEXTURE0) gl.BindTexture(gl.TEXTURE_2D, video.texture) log.Print("Reading") frame := <-video.pixelBuffer buf := make([]float32, len(frame)) log.Print("Read frame") for k, v := range frame { buf[k] = float32(v) } log.Print("Writing") if video.pixelBuffer != nil { gl.TexImage2D(gl.TEXTURE_2D, 0, 256, 256, gl.RGBA, gl.UNSIGNED_SHORT_4_4_4_4, f32.Bytes(binary.LittleEndian, buf...)) } log.Print("Wrote") gl.DrawArrays(gl.TRIANGLES, 0, 6) video.fpsmanager.FramerateDelay() }
func (w *windowImpl) Draw(src2dst f64.Aff3, src screen.Texture, sr image.Rectangle, op draw.Op, opts *screen.DrawOptions) { t := src.(*textureImpl) a := w.vertexAff3(sr) gl.UseProgram(w.s.texture.program) writeAff3(w.s.texture.mvp, mul(a, src2dst)) // OpenGL's fragment shaders' UV coordinates run from (0,0)-(1,1), // unlike vertex shaders' XY coordinates running from (-1,+1)-(+1,-1). // // We are drawing a rectangle PQRS, defined by two of its // corners, onto the entire texture. The two quads may actually // be equal, but in the general case, PQRS can be smaller. // // (0,0) +---------------+ (1,0) // | P +-----+ Q | // | | | | // | S +-----+ R | // (0,1) +---------------+ (1,1) // // The PQRS quad is always axis-aligned. First of all, convert // from pixel space to texture space. tw := float64(t.size.X) th := float64(t.size.Y) px := float64(sr.Min.X-0) / tw py := float64(sr.Min.Y-0) / th qx := float64(sr.Max.X-0) / tw sy := float64(sr.Max.Y-0) / th // Due to axis alignment, qy = py and sx = px. // // The simultaneous equations are: // 0 + 0 + a02 = px // 0 + 0 + a12 = py // a00 + 0 + a02 = qx // a10 + 0 + a12 = qy = py // 0 + a01 + a02 = sx = px // 0 + a11 + a12 = sy writeAff3(w.s.texture.uvp, f64.Aff3{ qx - px, 0, px, 0, sy - py, py, }) gl.ActiveTexture(gl.TEXTURE0) gl.BindTexture(gl.TEXTURE_2D, t.id) gl.Uniform1i(w.s.texture.sample, 0) gl.BindBuffer(gl.ARRAY_BUFFER, w.s.texture.quadXY) gl.EnableVertexAttribArray(w.s.texture.pos) gl.VertexAttribPointer(w.s.texture.pos, 2, gl.FLOAT, false, 0, 0) gl.BindBuffer(gl.ARRAY_BUFFER, w.s.texture.quadUV) gl.EnableVertexAttribArray(w.s.texture.inUV) gl.VertexAttribPointer(w.s.texture.inUV, 2, gl.FLOAT, false, 0, 0) gl.DrawArrays(gl.TRIANGLE_STRIP, 0, 4) gl.DisableVertexAttribArray(w.s.texture.pos) gl.DisableVertexAttribArray(w.s.texture.inUV) }
func onPaint(sz size.Event) { gl.ClearColor(rgb(156), rgb(39), rgb(176), 1) gl.Clear(gl.COLOR_BUFFER_BIT) var rotationMatrix = []float32{ f32.Cos(-alpha), -f32.Sin(-alpha), 0.0, f32.Sin(-alpha), f32.Cos(-alpha), 0.0, 0.0, 0.0, 1.0, } gl.UseProgram(program) // setting color gl.Uniform4f(color, rgb(255), rgb(255), rgb(255), 1) gl.UniformMatrix3fv(matrixId, rotationMatrix) gl.Uniform1f(resolutionId, resIndex) gl.BindBuffer(gl.ARRAY_BUFFER, swasBuffer) gl.EnableVertexAttribArray(position) gl.VertexAttribPointer(position, 3, gl.FLOAT, false, 0, 0) gl.DrawArrays(gl.LINES, 0, 16) gl.DisableVertexAttribArray(position) gl.UseProgram(texProgram) // setting color gl.Uniform4f(color2, rgb(130), rgb(50), rgb(80), 1) gl.Uniform1f(resolutionId2, resIndex) gl.UniformMatrix3fv(matrixId2, rotationMatrix) gl.BindBuffer(gl.ARRAY_BUFFER, quadBuffer) gl.EnableVertexAttribArray(position2) gl.VertexAttribPointer(position2, 3, gl.FLOAT, false, 0, 0) gl.BindBuffer(gl.ARRAY_BUFFER, quadTexBuffer) gl.EnableVertexAttribArray(textureCoords) gl.VertexAttribPointer(textureCoords, 2, gl.FLOAT, false, 0, 0) gl.Uniform1i(gl.GetUniformLocation(texProgram, "myTexture"), 0) gl.ActiveTexture(gl.TEXTURE0) gl.BindTexture(gl.TEXTURE_2D, textureId) gl.DrawArrays(gl.TRIANGLES, 0, 6) gl.DisableVertexAttribArray(position2) gl.DisableVertexAttribArray(textureCoords) if spin == true { alpha += 0.1 } if alpha >= 360 { alpha = 0.0 } }
func (video *Video) initGL() { log.Print("Initing") video.fpsmanager = gfx.NewFramerate() video.fpsmanager.SetFramerate(60) gl.ClearColor(0.0, 0.0, 0.0, 1.0) gl.Enable(gl.CULL_FACE) gl.Enable(gl.DEPTH_TEST) log.Print("Creating program") video.prog = createProgram(vertShaderSrcDef, fragShaderSrcDef) log.Print("Attrib loc 1") posAttrib := attribLocation(video.prog, "vPosition") log.Print("Attrib loc 2") texCoordAttr := attribLocation(video.prog, "vTexCoord") log.Print("Uniform loc 1") paletteLoc := uniformLocation(video.prog, "palette") log.Print("Uniform loc 2") video.textureUni = uniformLocation(video.prog, "texture") log.Print("Gen Texture") video.texture = genTexture() gl.ActiveTexture(gl.TEXTURE0) gl.BindTexture(gl.TEXTURE_2D, video.texture) log.Print("TexParam") gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST) gl.UseProgram(video.prog) gl.EnableVertexAttribArray(posAttrib) gl.EnableVertexAttribArray(texCoordAttr) gl.Uniform3iv(paletteLoc, nes.SPaletteRgb) log.Print("VertBO") vertVBO := genBuffer() checkGLError() gl.BindBuffer(gl.ARRAY_BUFFER, vertVBO) verts := f32.Bytes(binary.LittleEndian, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0) gl.BufferData(gl.ARRAY_BUFFER, verts, gl.STATIC_DRAW) textCoorBuf := genBuffer() checkGLError() gl.BindBuffer(gl.ARRAY_BUFFER, textCoorBuf) texVerts := f32.Bytes(binary.LittleEndian, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0) gl.BufferData(gl.ARRAY_BUFFER, texVerts, gl.STATIC_DRAW) gl.VertexAttribPointer(posAttrib, 2, gl.FLOAT, false, 0, 0) gl.VertexAttribPointer(texCoordAttr, 2, gl.FLOAT, false, 0, 0) log.Print("Started") }
func (e *Engine) Draw(c event.Config) { since := time.Now().Sub(e.started) gl.Enable(gl.DEPTH_TEST) gl.DepthFunc(gl.LESS) gl.ClearColor(0, 0, 0, 1) gl.Clear(gl.COLOR_BUFFER_BIT) gl.Clear(gl.DEPTH_BUFFER_BIT) gl.UseProgram(e.shader.program) // Setup MVP var m mgl.Mat4 m = mgl.Perspective(0.785, float32(c.Width/c.Height), 0.1, 10.0) gl.UniformMatrix4fv(e.shader.projection, m[:]) m = mgl.LookAtV( mgl.Vec3{3, 3, 3}, // eye mgl.Vec3{0, 0, 0}, // center mgl.Vec3{0, 1, 0}, // up ) gl.UniformMatrix4fv(e.shader.view, m[:]) m = mgl.HomogRotate3D(float32(since.Seconds()), mgl.Vec3{0, 1, 0}) gl.UniformMatrix4fv(e.shader.model, m[:]) // Draw our shape gl.BindBuffer(gl.ARRAY_BUFFER, e.shape.buf) gl.EnableVertexAttribArray(e.shader.vertCoord) gl.VertexAttribPointer(e.shader.vertCoord, e.shape.coordsPerVertex, gl.FLOAT, false, 20, 0) // 4 bytes in float, 5 values per vertex gl.EnableVertexAttribArray(e.shader.vertTexCoord) gl.VertexAttribPointer(e.shader.vertTexCoord, e.shape.texCoordsPerVertex, gl.FLOAT, false, 20, 12) gl.ActiveTexture(gl.TEXTURE0) gl.BindTexture(gl.TEXTURE_2D, e.shape.texture) gl.DrawArrays(gl.TRIANGLES, 0, e.shape.vertexCount) gl.DisableVertexAttribArray(e.shader.vertCoord) //debug.DrawFPS(c) }
// Draw draws the srcBounds part of the image onto a parallelogram, defined by // three of its corners, in the current GL framebuffer. func (img *Image) Draw(topLeft, topRight, bottomLeft geom.Point, srcBounds image.Rectangle) { // TODO(crawshaw): Adjust viewport for the top bar on android? gl.UseProgram(glimage.program) { // We are drawing a parallelogram PQRS, defined by three of its // corners, onto the entire GL framebuffer ABCD. The two quads may // actually be equal, but in the general case, PQRS can be smaller, // and PQRS is not necessarily axis-aligned. // // A +---------------+ B // | P +-----+ Q | // | | | | // | S +-----+ R | // D +---------------+ C // // There are two co-ordinate spaces: geom space and framebuffer space. // In geom space, the ABCD rectangle is: // // (0, 0) (geom.Width, 0) // (0, geom.Height) (geom.Width, geom.Height) // // and the PQRS quad is: // // (topLeft.X, topLeft.Y) (topRight.X, topRight.Y) // (bottomLeft.X, bottomLeft.Y) (implicit, implicit) // // In framebuffer space, the ABCD rectangle is: // // (-1, +1) (+1, +1) // (-1, -1) (+1, -1) // // First of all, convert from geom space to framebuffer space. For // later convenience, we divide everything by 2 here: px2 is half of // the P.X co-ordinate (in framebuffer space). px2 := -0.5 + float32(topLeft.X/geom.Width) py2 := +0.5 - float32(topLeft.Y/geom.Height) qx2 := -0.5 + float32(topRight.X/geom.Width) qy2 := +0.5 - float32(topRight.Y/geom.Height) sx2 := -0.5 + float32(bottomLeft.X/geom.Width) sy2 := +0.5 - float32(bottomLeft.Y/geom.Height) // Next, solve for the affine transformation matrix // [ a00 a01 a02 ] // a = [ a10 a11 a12 ] // [ 0 0 1 ] // that maps A to P: // a × [ -1 +1 1 ]' = [ 2*px2 2*py2 1 ]' // and likewise maps B to Q and D to S. Solving those three constraints // implies that C maps to R, since affine transformations keep parallel // lines parallel. This gives 6 equations in 6 unknowns: // -a00 + a01 + a02 = 2*px2 // -a10 + a11 + a12 = 2*py2 // +a00 + a01 + a02 = 2*qx2 // +a10 + a11 + a12 = 2*qy2 // -a00 - a01 + a02 = 2*sx2 // -a10 - a11 + a12 = 2*sy2 // which gives: // a00 = (2*qx2 - 2*px2) / 2 = qx2 - px2 // and similarly for the other elements of a. glimage.mvp.WriteAffine(&f32.Affine{{ qx2 - px2, px2 - sx2, qx2 + sx2, }, { qy2 - py2, py2 - sy2, qy2 + sy2, }}) } { // Mapping texture co-ordinates is similar, except that in texture // space, the ABCD rectangle is: // // (0,0) (1,0) // (0,1) (1,1) // // and the PQRS quad is always axis-aligned. First of all, convert // from pixel space to texture space. w := float32(img.texWidth) h := float32(img.texHeight) px := float32(srcBounds.Min.X-img.Rect.Min.X) / w py := float32(srcBounds.Min.Y-img.Rect.Min.Y) / h qx := float32(srcBounds.Max.X-img.Rect.Min.X) / w sy := float32(srcBounds.Max.Y-img.Rect.Min.Y) / h // Due to axis alignment, qy = py and sx = px. // // The simultaneous equations are: // 0 + 0 + a02 = px // 0 + 0 + a12 = py // a00 + 0 + a02 = qx // a10 + 0 + a12 = qy = py // 0 + a01 + a02 = sx = px // 0 + a11 + a12 = sy glimage.uvp.WriteAffine(&f32.Affine{{ qx - px, 0, px, }, { 0, sy - py, py, }}) } gl.ActiveTexture(gl.TEXTURE0) gl.BindTexture(gl.TEXTURE_2D, img.Texture) gl.Uniform1i(glimage.textureSample, 0) gl.BindBuffer(gl.ARRAY_BUFFER, glimage.quadXY) gl.EnableVertexAttribArray(glimage.pos) gl.VertexAttribPointer(glimage.pos, 2, gl.FLOAT, false, 0, 0) gl.BindBuffer(gl.ARRAY_BUFFER, glimage.quadUV) gl.EnableVertexAttribArray(glimage.inUV) gl.VertexAttribPointer(glimage.inUV, 2, gl.FLOAT, false, 0, 0) gl.DrawArrays(gl.TRIANGLE_STRIP, 0, 4) gl.DisableVertexAttribArray(glimage.pos) gl.DisableVertexAttribArray(glimage.inUV) }