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() }
// NewImage creates an Image of the given size. // // Both a host-memory *image.RGBA and a GL texture are created. func NewImage(w, h int) *Image { dx := roundToPower2(w) dy := roundToPower2(h) // TODO(crawshaw): Using VertexAttribPointer we can pass texture // data with a stride, which would let us use the exact number of // pixels on the host instead of the rounded up power 2 size. m := image.NewRGBA(image.Rect(0, 0, dx, dy)) glimage.Do(glInit) img := &Image{ RGBA: m.SubImage(image.Rect(0, 0, w, h)).(*image.RGBA), Texture: gl.GenTexture(), texWidth: dx, texHeight: dy, } // TODO(crawshaw): We don't have the context on a finalizer. Find a way. // runtime.SetFinalizer(img, func(img *Image) { gl.DeleteTexture(img.Texture) }) gl.BindTexture(gl.TEXTURE_2D, img.Texture) gl.TexImage2D(gl.TEXTURE_2D, 0, dx, dy, gl.RGBA, gl.UNSIGNED_BYTE, nil) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_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) return img }
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 (t *textureImpl) Upload(dp image.Point, src screen.Buffer, sr image.Rectangle, sender screen.Sender) { // TODO: adjust if dp is outside dst bounds, or sr is outside src bounds. gl.BindTexture(gl.TEXTURE_2D, t.id) m := src.RGBA().SubImage(sr).(*image.RGBA) b := m.Bounds() // TODO check m bounds smaller than t.size gl.TexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, b.Dx(), b.Dy(), gl.RGBA, gl.UNSIGNED_BYTE, m.Pix) // TODO: send a screen.UploadedEvent. }
func (e *Engine) Draw(c size.Event) { gl.Enable(gl.DEPTH_TEST) gl.DepthFunc(gl.LESS) gl.ClearColor(0.2, 0.2, 0.2, 1) gl.Clear(gl.COLOR_BUFFER_BIT) gl.Clear(gl.DEPTH_BUFFER_BIT) gl.UseProgram(e.shader.program) m := mgl32.Perspective(0.785, float32(c.WidthPt/c.HeightPt), 0.1, 10.0) gl.UniformMatrix4fv(e.shader.projection, m[:]) eye := mgl32.Vec3{0, 0, 8} center := mgl32.Vec3{0, 0, 0} up := mgl32.Vec3{0, 1, 0} m = mgl32.LookAtV(eye, center, up) gl.UniformMatrix4fv(e.shader.view, m[:]) m = mgl32.HomogRotate3D(float32(e.touchLoc.X/c.WidthPt-0.5)*3.14*2, mgl32.Vec3{0, 1, 0}) gl.UniformMatrix4fv(e.shader.modelx, m[:]) m = mgl32.HomogRotate3D(float32(e.touchLoc.Y/c.HeightPt-0.5)*3.14, mgl32.Vec3{1, 0, 0}) gl.UniformMatrix4fv(e.shader.modely, m[:]) coordsPerVertex := 3 for _, obj := range e.shape.Objs { gl.BindBuffer(gl.ARRAY_BUFFER, obj.coord) gl.EnableVertexAttribArray(e.shader.vertCoord) gl.VertexAttribPointer(e.shader.vertCoord, coordsPerVertex, gl.FLOAT, false, 12, 0) if obj.useuv == true { gl.Uniform1i(e.shader.useuv, 1) texCoordsPerVertex := 2 gl.BindBuffer(gl.ARRAY_BUFFER, obj.uvcoord) gl.EnableVertexAttribArray(e.shader.vertTexCoord) gl.VertexAttribPointer(e.shader.vertTexCoord, texCoordsPerVertex, gl.FLOAT, false, 8, 0) gl.BindTexture(gl.TEXTURE_2D, obj.tex) } else { gl.Uniform1i(e.shader.useuv, 0) gl.Uniform4f(e.shader.color, obj.color[0], obj.color[1], obj.color[2], obj.color[3]) } gl.DrawArrays(gl.TRIANGLES, 0, obj.vcount) if obj.useuv { gl.DisableVertexAttribArray(e.shader.vertTexCoord) } gl.DisableVertexAttribArray(e.shader.vertCoord) } debug.DrawFPS(c) }
func (e *Engine) Draw(c size.Event) { gl.Enable(gl.DEPTH_TEST) gl.DepthFunc(gl.LESS) gl.ClearColor(0.5, 0.8, 0.8, 1) gl.Clear(gl.COLOR_BUFFER_BIT) gl.Clear(gl.DEPTH_BUFFER_BIT) gl.UseProgram(e.shader.program) gl.Uniform3fv(e.shader.lightdir, []float32{0.5, 0.6, 0.7}) m := mgl32.Perspective(1.3, float32(c.WidthPt/c.HeightPt), 0.1, 10.0) gl.UniformMatrix4fv(e.shader.projectionmatrix, m[:]) eye := mgl32.Vec3{0, 0, 0.2} center := mgl32.Vec3{0, 0, 0} up := mgl32.Vec3{0, 1, 0} m = mgl32.LookAtV(eye, center, up) gl.UniformMatrix4fv(e.shader.viewmatrix, m[:]) m = mgl32.HomogRotate3D((e.touchx/float32(c.WidthPt)-0.5)*6.28, mgl32.Vec3{0, 1, 0}) gl.UniformMatrix4fv(e.shader.modelmatrix, m[:]) m = mgl32.HomogRotate3D((e.touchx/float32(c.WidthPt)-0.5)*6.28, mgl32.Vec3{0, -1, 0}) gl.UniformMatrix4fv(e.shader.lightmatrix, m[:]) coordsPerVertex := 3 for _, obj := range e.shape.Objs { gl.BindBuffer(gl.ARRAY_BUFFER, obj.coord) gl.EnableVertexAttribArray(e.shader.vertCoord) gl.VertexAttribPointer(e.shader.vertCoord, coordsPerVertex, gl.FLOAT, false, 12, 0) texCoordsPerVertex := 2 gl.BindBuffer(gl.ARRAY_BUFFER, obj.uvcoord) gl.EnableVertexAttribArray(e.shader.texcoord) gl.VertexAttribPointer(e.shader.texcoord, texCoordsPerVertex, gl.FLOAT, false, 8, 0) gl.BindBuffer(gl.ARRAY_BUFFER, obj.normal) gl.EnableVertexAttribArray(e.shader.normal) gl.VertexAttribPointer(e.shader.normal, 3, gl.FLOAT, false, 12, 0) gl.BindTexture(gl.TEXTURE_2D, obj.tex) gl.DrawArrays(gl.TRIANGLES, 0, obj.vcount) gl.DisableVertexAttribArray(e.shader.texcoord) gl.DisableVertexAttribArray(e.shader.normal) gl.DisableVertexAttribArray(e.shader.vertCoord) } debug.DrawFPS(c) }
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 size.Event) { since := time.Now().Sub(e.started) //gl.Enable() 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) m := mgl32.Perspective(0.785, float32(c.WidthPt/c.HeightPt), 0.1, 10.0) gl.UniformMatrix4fv(e.shader.projection, m[:]) eye := mgl32.Vec3{3, 3, 3} center := mgl32.Vec3{0, 0, 0} up := mgl32.Vec3{0, 1, 0} m = mgl32.LookAtV(eye, center, up) gl.UniformMatrix4fv(e.shader.view, m[:]) m = mgl32.HomogRotate3D(float32(since.Seconds()), mgl32.Vec3{0, 1, 0}) gl.UniformMatrix4fv(e.shader.model, m[:]) gl.BindBuffer(gl.ARRAY_BUFFER, e.shape.buf) coordsPerVertex := 3 texCoordsPerVertex := 2 vertexCount := len(cubeData) / (coordsPerVertex + texCoordsPerVertex) gl.EnableVertexAttribArray(e.shader.vertCoord) gl.VertexAttribPointer(e.shader.vertCoord, coordsPerVertex, gl.FLOAT, false, 20, 0) // 4 bytes in float, 5 values per vertex gl.EnableVertexAttribArray(e.shader.vertTexCoord) gl.VertexAttribPointer(e.shader.vertTexCoord, texCoordsPerVertex, gl.FLOAT, false, 20, 12) gl.BindTexture(gl.TEXTURE_2D, e.shape.texture) gl.DrawArrays(gl.TRIANGLES, 0, vertexCount) gl.DisableVertexAttribArray(e.shader.vertCoord) debug.DrawFPS(c) }
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) }
func onStart() { gl.Enable(gl.BLEND) gl.BlendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA) texture := loadImages("495.png") textureId = gl.CreateTexture() gl.BindTexture(gl.TEXTURE_2D, textureId) 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.REPEAT) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT) gl.TexImage2D(gl.TEXTURE_2D, 0, texture.Rect.Size().X, texture.Rect.Size().Y, gl.RGBA, gl.UNSIGNED_BYTE, texture.Pix) // loading Shaders & linking programs program = createProgram("vShader.vs", "fShader.vs") texProgram = createProgram("vTexShader.vs", "fTexShader.vs") quadBuffer = gl.CreateBuffer() gl.BindBuffer(gl.ARRAY_BUFFER, quadBuffer) gl.BufferData(gl.ARRAY_BUFFER, quadData, gl.STATIC_DRAW) quadTexBuffer = gl.CreateBuffer() gl.BindBuffer(gl.ARRAY_BUFFER, quadTexBuffer) gl.BufferData(gl.ARRAY_BUFFER, quadTexData, gl.STATIC_DRAW) swasBuffer = gl.CreateBuffer() gl.BindBuffer(gl.ARRAY_BUFFER, swasBuffer) gl.BufferData(gl.ARRAY_BUFFER, swastikaData, gl.STATIC_DRAW) position = gl.GetAttribLocation(program, "position") color = gl.GetUniformLocation(program, "color") matrixId = gl.GetUniformLocation(program, "rotationMatrix") resolutionId = gl.GetUniformLocation(program, "resIndex") position2 = gl.GetAttribLocation(texProgram, "position") textureCoords = gl.GetAttribLocation(texProgram, "texCoords") matrixId2 = gl.GetUniformLocation(texProgram, "rotationMatrix") resolutionId2 = gl.GetUniformLocation(texProgram, "resIndex") color2 = gl.GetUniformLocation(texProgram, "color") }
// init creates an underlying GL texture for a key. // Must be called with a valid GL context. // Must hold tm.Mutex before calling. func (tm *texmapCache) init(key texmapKey) { tex := tm.texs[key] if tex.gltex.Value != 0 { panic(fmt.Sprintf("attempting to init key (%v) with valid texture", key)) } tex.gltex = gl.CreateTexture() gl.BindTexture(gl.TEXTURE_2D, tex.gltex) gl.TexImage2D(gl.TEXTURE_2D, 0, tex.width, tex.height, gl.RGBA, gl.UNSIGNED_BYTE, nil) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_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) for _, t := range tm.toDelete { gl.DeleteTexture(t) } tm.toDelete = nil }
func (s *screenImpl) NewTexture(size image.Point) (screen.Texture, error) { s.mu.Lock() defer s.mu.Unlock() if !gl.IsProgram(s.texture.program) { p, err := compileProgram(textureVertexSrc, textureFragmentSrc) if err != nil { return nil, err } s.texture.program = p s.texture.pos = gl.GetAttribLocation(p, "pos") s.texture.mvp = gl.GetUniformLocation(p, "mvp") s.texture.uvp = gl.GetUniformLocation(p, "uvp") s.texture.inUV = gl.GetAttribLocation(p, "inUV") s.texture.sample = gl.GetUniformLocation(p, "sample") s.texture.quadXY = gl.CreateBuffer() s.texture.quadUV = gl.CreateBuffer() gl.BindBuffer(gl.ARRAY_BUFFER, s.texture.quadXY) gl.BufferData(gl.ARRAY_BUFFER, quadXYCoords, gl.STATIC_DRAW) gl.BindBuffer(gl.ARRAY_BUFFER, s.texture.quadUV) gl.BufferData(gl.ARRAY_BUFFER, quadUVCoords, gl.STATIC_DRAW) } t := &textureImpl{ id: gl.CreateTexture(), size: size, } gl.BindTexture(gl.TEXTURE_2D, t.id) gl.TexImage2D(gl.TEXTURE_2D, 0, size.X, size.Y, gl.RGBA, gl.UNSIGNED_BYTE, nil) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_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) return t, nil }
func (shape *Skybox) Draw(camera Camera) { shader := shape.shader gl.DepthFunc(gl.LEQUAL) gl.DepthMask(false) projection, view := camera.Projection(), camera.View().Mat3().Mat4() gl.UniformMatrix4fv(shader.Uniform("projection"), projection[:]) gl.UniformMatrix4fv(shader.Uniform("view"), view[:]) gl.BindTexture(gl.TEXTURE_CUBE_MAP, shape.Texture) gl.BindBuffer(gl.ARRAY_BUFFER, shape.VBO) gl.EnableVertexAttribArray(shader.Attrib("vertCoord")) gl.VertexAttribPointer(shader.Attrib("vertCoord"), vertexDim, gl.FLOAT, false, shape.Stride(), 0) gl.BindBuffer(gl.ELEMENT_ARRAY_BUFFER, shape.IBO) gl.DrawElements(gl.TRIANGLES, len(shape.indices), gl.UNSIGNED_BYTE, 0) gl.DisableVertexAttribArray(shader.Attrib("vertCoord")) gl.DepthMask(true) gl.DepthFunc(gl.LESS) }
// 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) }
// Upload copies the host image data to the GL device. func (img *Image) Upload() { gl.BindTexture(gl.TEXTURE_2D, img.Texture) gl.TexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, img.texWidth, img.texHeight, gl.RGBA, gl.UNSIGNED_BYTE, img.Pix) }
// Upload copies the host image data to the GL device. func (img *Image) Upload() { tex := texmap.get(*img.key) gl.BindTexture(gl.TEXTURE_2D, tex.gltex) gl.TexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, tex.width, tex.height, gl.RGBA, gl.UNSIGNED_BYTE, img.RGBA.Pix) }