mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-24 18:58:54 +01:00
Add image.DrawRects (experimental)
This commit is contained in:
parent
f0519b8604
commit
0328b049d0
74
example/shapes/main.go
Normal file
74
example/shapes/main.go
Normal file
@ -0,0 +1,74 @@
|
||||
// Copyright 2015 Hajime Hoshi
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
"image"
|
||||
"image/color"
|
||||
"log"
|
||||
"math/rand"
|
||||
)
|
||||
|
||||
const (
|
||||
screenWidth = 320
|
||||
screenHeight = 240
|
||||
)
|
||||
|
||||
var rectsToDraw = make([]image.Rectangle, 100)
|
||||
|
||||
func min(a, b int) int {
|
||||
if a < b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func max(a, b int) int {
|
||||
if a < b {
|
||||
return b
|
||||
}
|
||||
return a
|
||||
}
|
||||
|
||||
func init() {
|
||||
for i, _ := range rectsToDraw {
|
||||
x0, x1 := rand.Intn(screenWidth), rand.Intn(screenWidth)
|
||||
y0, y1 := rand.Intn(screenHeight), rand.Intn(screenHeight)
|
||||
rectsToDraw[i] = image.Rect(min(x0, x1), min(y0, y1), max(x0, x1), max(y0, y1))
|
||||
}
|
||||
}
|
||||
|
||||
type rects []image.Rectangle
|
||||
|
||||
func (r rects) Len() int {
|
||||
return len(r)
|
||||
}
|
||||
|
||||
func (r rects) Points(i int) (x0, y0, x1, y1 int) {
|
||||
rect := &r[i]
|
||||
return rect.Min.X, rect.Min.Y, rect.Max.X, rect.Max.Y
|
||||
}
|
||||
|
||||
func update(screen *ebiten.Image) error {
|
||||
screen.DrawRects(color.NRGBA{0x80, 0x80, 0xff, 0x80}, rects(rectsToDraw))
|
||||
return nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
if err := ebiten.Run(update, screenWidth, screenHeight, 2, "Shapes (Ebiten Demo)"); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
30
image.go
30
image.go
@ -94,6 +94,36 @@ func (i *Image) DrawImage(image *Image, options *DrawImageOptions) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// A Rects represents the set of rectangles.
|
||||
type Rects interface {
|
||||
Len() int
|
||||
Points(i int) (x0, y0, x1, y1 int)
|
||||
}
|
||||
|
||||
type rectVertexQuads struct {
|
||||
Rects
|
||||
}
|
||||
|
||||
func (l rectVertexQuads) Len() int {
|
||||
return l.Rects.Len()
|
||||
}
|
||||
|
||||
func (l rectVertexQuads) Vertex(i int) (x0, y0, x1, y1 float32) {
|
||||
ix0, iy0, ix1, iy1 := l.Rects.Points(i)
|
||||
return float32(ix0), float32(iy0), float32(ix1), float32(iy1)
|
||||
}
|
||||
|
||||
// DrawRects draws rectangles on the image.
|
||||
//
|
||||
// NOTE: This method is experimental.
|
||||
func (i *Image) DrawRects(clr color.Color, rects Rects) (err error) {
|
||||
r, g, b, a := internal.RGBA(clr)
|
||||
ui.Use(func(c *opengl.Context) {
|
||||
err = i.framebuffer.DrawRects(c, r, g, b, a, &rectVertexQuads{rects})
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// Bounds returns the bounds of the image.
|
||||
func (i *Image) Bounds() image.Rectangle {
|
||||
w, h := i.Size()
|
||||
|
@ -109,6 +109,19 @@ func (f *Framebuffer) DrawTexture(c *opengl.Context, t *Texture, quads TextureQu
|
||||
if err := f.setAsViewport(c); err != nil {
|
||||
return err
|
||||
}
|
||||
projectionMatrix := f.projectionMatrix()
|
||||
return shader.DrawTexture(c, t.native, projectionMatrix, quads, geo, clr)
|
||||
p := f.projectionMatrix()
|
||||
return shader.DrawTexture(c, t.native, p, quads, geo, clr)
|
||||
}
|
||||
|
||||
type VertexQuads interface {
|
||||
Len() int
|
||||
Vertex(i int) (x0, y0, x1, y1 float32)
|
||||
}
|
||||
|
||||
func (f *Framebuffer) DrawRects(c *opengl.Context, r, g, b, a float64, quads VertexQuads) error {
|
||||
if err := f.setAsViewport(c); err != nil {
|
||||
return err
|
||||
}
|
||||
p := f.projectionMatrix()
|
||||
return shader.DrawRects(c, p, r, g, b, a, quads)
|
||||
}
|
||||
|
@ -43,6 +43,7 @@ func DrawTexture(c *opengl.Context, texture opengl.Texture, projectionMatrix *[4
|
||||
// TODO: WebGL doesn't seem to have Check gl.MAX_ELEMENTS_VERTICES or gl.MAX_ELEMENTS_INDICES so far.
|
||||
// Let's use them to compare to len(quads) in the future.
|
||||
|
||||
// TODO: Unify stride or other consts
|
||||
const stride = 4 * 4
|
||||
|
||||
if !initialized {
|
||||
@ -80,3 +81,54 @@ func DrawTexture(c *opengl.Context, texture opengl.Texture, projectionMatrix *[4
|
||||
c.DrawElements(6 * len(vertices) / 16)
|
||||
return nil
|
||||
}
|
||||
|
||||
type VertexQuads interface {
|
||||
Len() int
|
||||
Vertex(i int) (x0, y0, x1, y1 float32)
|
||||
}
|
||||
|
||||
func max(a, b float32) float32 {
|
||||
if a < b {
|
||||
return b
|
||||
}
|
||||
return a
|
||||
}
|
||||
|
||||
func DrawRects(c *opengl.Context, projectionMatrix *[4][4]float64, r, g, b, a float64, quads VertexQuads) error {
|
||||
const stride = 4 * 4
|
||||
|
||||
if !initialized {
|
||||
if err := initialize(c); err != nil {
|
||||
return err
|
||||
}
|
||||
initialized = true
|
||||
}
|
||||
|
||||
if quads.Len() == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
f := useProgramRect(c, glMatrix(projectionMatrix), r, g, b, a)
|
||||
defer f.FinishProgram()
|
||||
|
||||
vertices := make([]float32, 0, stride*quads.Len())
|
||||
for i := 0; i < quads.Len(); i++ {
|
||||
x0, y0, x1, y1 := quads.Vertex(i)
|
||||
if x0 == x1 || y0 == y1 {
|
||||
continue
|
||||
}
|
||||
vertices = append(vertices,
|
||||
x0, y0, 0, 0,
|
||||
x1, y0, 1, 0,
|
||||
x0, y1, 0, 1,
|
||||
x1, y1, 1, 1,
|
||||
)
|
||||
}
|
||||
if len(vertices) == 0 {
|
||||
return nil
|
||||
}
|
||||
c.BufferSubData(c.ArrayBuffer, vertices)
|
||||
c.DrawElements(6 * len(vertices) / 16)
|
||||
|
||||
return nil
|
||||
}
|
@ -18,7 +18,10 @@ import (
|
||||
"github.com/hajimehoshi/ebiten/internal/opengl"
|
||||
)
|
||||
|
||||
var programTexture opengl.Program
|
||||
var (
|
||||
programTexture opengl.Program
|
||||
programRect opengl.Program
|
||||
)
|
||||
|
||||
func initialize(c *opengl.Context) error {
|
||||
const size = 10000
|
||||
@ -36,11 +39,24 @@ func initialize(c *opengl.Context) error {
|
||||
}
|
||||
defer c.DeleteShader(shaderFragmentTextureNative)
|
||||
|
||||
shaders := []opengl.Shader{
|
||||
shaderFragmentRectNative, err := c.NewShader(c.FragmentShader, shader(c, shaderFragmentRect))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer c.DeleteShader(shaderFragmentRectNative)
|
||||
|
||||
programTexture, err = c.NewProgram([]opengl.Shader{
|
||||
shaderVertexNative,
|
||||
shaderFragmentTextureNative,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
programTexture, err = c.NewProgram(shaders)
|
||||
|
||||
programRect, err = c.NewProgram([]opengl.Shader{
|
||||
shaderVertexNative,
|
||||
shaderFragmentRectNative,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -132,3 +148,38 @@ func useProgramTexture(c *opengl.Context, projectionMatrix []float32, texture op
|
||||
c.DisableVertexAttribArray(program, "vertex")
|
||||
}
|
||||
}
|
||||
|
||||
func useProgramRect(c *opengl.Context, projectionMatrix []float32, r, g, b, a float64) programFinisher {
|
||||
const float32Size = 4
|
||||
const stride = 4 * 4
|
||||
|
||||
if lastProgram != programRect {
|
||||
c.UseProgram(programRect)
|
||||
lastProgram = programRect
|
||||
}
|
||||
program := programRect
|
||||
|
||||
c.UniformFloats(program, "projection_matrix", projectionMatrix)
|
||||
|
||||
glModelviewMatrix := []float32{
|
||||
1, 0, 0, 0,
|
||||
0, 1, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
0, 0, 0, 1,
|
||||
}
|
||||
c.UniformFloats(program, "modelview_matrix", glModelviewMatrix)
|
||||
|
||||
clr := []float32{float32(r), float32(g), float32(b), float32(a)}
|
||||
c.UniformFloats(program, "color", clr)
|
||||
|
||||
c.EnableVertexAttribArray(program, "vertex")
|
||||
c.EnableVertexAttribArray(program, "tex_coord")
|
||||
|
||||
c.VertexAttribPointer(program, "vertex", stride, uintptr(float32Size*0))
|
||||
c.VertexAttribPointer(program, "tex_coord", stride, uintptr(float32Size*2))
|
||||
|
||||
return func() {
|
||||
c.DisableVertexAttribArray(program, "tex_coord")
|
||||
c.DisableVertexAttribArray(program, "vertex")
|
||||
}
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ type shaderId int
|
||||
const (
|
||||
shaderVertex shaderId = iota
|
||||
shaderFragmentTexture
|
||||
shaderFragmentRect
|
||||
)
|
||||
|
||||
func shader(c *opengl.Context, id shaderId) string {
|
||||
@ -69,5 +70,13 @@ void main(void) {
|
||||
|
||||
gl_FragColor = color;
|
||||
}
|
||||
`,
|
||||
shaderFragmentRect: `
|
||||
uniform lowp vec4 color;
|
||||
varying highp vec2 vertex_out_tex_coord;
|
||||
|
||||
void main(void) {
|
||||
gl_FragColor = color;
|
||||
}
|
||||
`,
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user