mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-25 19:28:57 +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
|
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.
|
// Bounds returns the bounds of the image.
|
||||||
func (i *Image) Bounds() image.Rectangle {
|
func (i *Image) Bounds() image.Rectangle {
|
||||||
w, h := i.Size()
|
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 {
|
if err := f.setAsViewport(c); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
projectionMatrix := f.projectionMatrix()
|
p := f.projectionMatrix()
|
||||||
return shader.DrawTexture(c, t.native, projectionMatrix, quads, geo, clr)
|
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.
|
// 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.
|
// Let's use them to compare to len(quads) in the future.
|
||||||
|
|
||||||
|
// TODO: Unify stride or other consts
|
||||||
const stride = 4 * 4
|
const stride = 4 * 4
|
||||||
|
|
||||||
if !initialized {
|
if !initialized {
|
||||||
@ -80,3 +81,54 @@ func DrawTexture(c *opengl.Context, texture opengl.Texture, projectionMatrix *[4
|
|||||||
c.DrawElements(6 * len(vertices) / 16)
|
c.DrawElements(6 * len(vertices) / 16)
|
||||||
return nil
|
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"
|
"github.com/hajimehoshi/ebiten/internal/opengl"
|
||||||
)
|
)
|
||||||
|
|
||||||
var programTexture opengl.Program
|
var (
|
||||||
|
programTexture opengl.Program
|
||||||
|
programRect opengl.Program
|
||||||
|
)
|
||||||
|
|
||||||
func initialize(c *opengl.Context) error {
|
func initialize(c *opengl.Context) error {
|
||||||
const size = 10000
|
const size = 10000
|
||||||
@ -36,11 +39,24 @@ func initialize(c *opengl.Context) error {
|
|||||||
}
|
}
|
||||||
defer c.DeleteShader(shaderFragmentTextureNative)
|
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,
|
shaderVertexNative,
|
||||||
shaderFragmentTextureNative,
|
shaderFragmentTextureNative,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
programTexture, err = c.NewProgram(shaders)
|
|
||||||
|
programRect, err = c.NewProgram([]opengl.Shader{
|
||||||
|
shaderVertexNative,
|
||||||
|
shaderFragmentRectNative,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -132,3 +148,38 @@ func useProgramTexture(c *opengl.Context, projectionMatrix []float32, texture op
|
|||||||
c.DisableVertexAttribArray(program, "vertex")
|
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 (
|
const (
|
||||||
shaderVertex shaderId = iota
|
shaderVertex shaderId = iota
|
||||||
shaderFragmentTexture
|
shaderFragmentTexture
|
||||||
|
shaderFragmentRect
|
||||||
)
|
)
|
||||||
|
|
||||||
func shader(c *opengl.Context, id shaderId) string {
|
func shader(c *opengl.Context, id shaderId) string {
|
||||||
@ -69,5 +70,13 @@ void main(void) {
|
|||||||
|
|
||||||
gl_FragColor = color;
|
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