mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-24 10:48:53 +01:00
parent
08e931782a
commit
2360b2930f
120
examples/triangle/main.go
Normal file
120
examples/triangle/main.go
Normal file
@ -0,0 +1,120 @@
|
||||
// Copyright 2018 The Ebiten Authors
|
||||
//
|
||||
// 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.
|
||||
|
||||
// +build example jsgo
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"image/color"
|
||||
"log"
|
||||
"math"
|
||||
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
"github.com/hajimehoshi/ebiten/ebitenutil"
|
||||
)
|
||||
|
||||
const (
|
||||
screenWidth = 640
|
||||
screenHeight = 480
|
||||
)
|
||||
|
||||
var (
|
||||
emptyImage, _ = ebiten.NewImage(16, 16, ebiten.FilterDefault)
|
||||
)
|
||||
|
||||
func init() {
|
||||
emptyImage.Fill(color.White)
|
||||
}
|
||||
|
||||
var (
|
||||
vertices []ebiten.Vertex
|
||||
indices []uint16
|
||||
)
|
||||
|
||||
func init() {
|
||||
const (
|
||||
num = 120
|
||||
centerX = screenWidth / 2
|
||||
centerY = screenHeight / 2
|
||||
r = 160
|
||||
)
|
||||
|
||||
for i := 0; i < num; i++ {
|
||||
theta := float64(i) / num * 2 * math.Pi
|
||||
cr := float32(0)
|
||||
cg := float32(0)
|
||||
cb := float32(0)
|
||||
if 0 <= i && i < 2*num/3 {
|
||||
cr = 2 * float32(i) / float32(num/3)
|
||||
}
|
||||
if num/3 <= i && i < 2*num/3 {
|
||||
cr = 2 - 2*float32(i-num/3)/float32(num/3)
|
||||
}
|
||||
if num/3 <= i && i < 2*num/3 {
|
||||
cg = 2 * float32(i-num/3) / float32(num/3)
|
||||
}
|
||||
if 2*num/3 <= i && i < num {
|
||||
cg = 2 - 2*float32(i-2*num/3)/float32(num/3)
|
||||
}
|
||||
if 2*num/3 <= i && i < num {
|
||||
cb = 2 * float32(i-2*num/3) / float32(num/3)
|
||||
}
|
||||
if 0 <= i && i < num/3 {
|
||||
cb = 2 - 2*float32(i)/float32(num/3)
|
||||
}
|
||||
vertices = append(vertices, ebiten.Vertex{
|
||||
DstX: float32(r*math.Cos(theta)) + centerX,
|
||||
DstY: float32(r*math.Sin(theta)) + centerY,
|
||||
SrcX: 0,
|
||||
SrcY: 0,
|
||||
ColorR: cr,
|
||||
ColorG: cg,
|
||||
ColorB: cb,
|
||||
ColorA: 1,
|
||||
})
|
||||
}
|
||||
|
||||
vertices = append(vertices, ebiten.Vertex{
|
||||
DstX: centerX,
|
||||
DstY: centerY,
|
||||
SrcX: 0,
|
||||
SrcY: 0,
|
||||
ColorR: 1,
|
||||
ColorG: 1,
|
||||
ColorB: 1,
|
||||
ColorA: 1,
|
||||
})
|
||||
for i := 0; i < num; i++ {
|
||||
indices = append(indices, uint16(i), uint16(i+1)%num, num)
|
||||
}
|
||||
}
|
||||
|
||||
func update(screen *ebiten.Image) error {
|
||||
if ebiten.IsDrawingSkipped() {
|
||||
return nil
|
||||
}
|
||||
|
||||
op := &ebiten.DrawTrianglesOptions{}
|
||||
screen.DrawTriangles(vertices, indices, emptyImage, op)
|
||||
ebitenutil.DebugPrint(screen, fmt.Sprintf("TPS: %0.2f", ebiten.CurrentTPS()))
|
||||
return nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
if err := ebiten.Run(update, screenWidth, screenHeight, 1, "Triangle (Ebiten Demo)"); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
78
image.go
78
image.go
@ -338,6 +338,84 @@ func (i *Image) drawImage(img *Image, options *DrawImageOptions) {
|
||||
i.disposeMipmaps()
|
||||
}
|
||||
|
||||
// Vertex represents a vertex passed to DrawTriangles.
|
||||
//
|
||||
// Note that this API is experimental.
|
||||
type Vertex struct {
|
||||
// DstX and DstY represents a point on a destination image.
|
||||
DstX float32
|
||||
DstY float32
|
||||
|
||||
// SrcX and SrcY represents a point on a source image.
|
||||
SrcX float32
|
||||
SrcY float32
|
||||
|
||||
// ColorR/ColorG/ColorB/ColorA represents color scaling values.
|
||||
// 1 means the original source image color is used.
|
||||
// 0 means a transparent color is used.
|
||||
ColorR float32
|
||||
ColorG float32
|
||||
ColorB float32
|
||||
ColorA float32
|
||||
}
|
||||
|
||||
// DrawTrianglesOptions represents options to render triangles on an image.
|
||||
//
|
||||
// Note that this API is experimental.
|
||||
type DrawTrianglesOptions struct {
|
||||
// ColorM is a color matrix to draw.
|
||||
// The default (zero) value is identity, which doesn't change any color.
|
||||
// ColorM is applied before vertex color scale is applied.
|
||||
ColorM ColorM
|
||||
|
||||
// CompositeMode is a composite mode to draw.
|
||||
// The default (zero) value is regular alpha blending.
|
||||
CompositeMode CompositeMode
|
||||
|
||||
// Filter is a type of texture filter.
|
||||
// The default (zero) value is FilterDefault.
|
||||
Filter Filter
|
||||
}
|
||||
|
||||
// DrawTriangles draws a triangle with the specified vertices and their indices.
|
||||
//
|
||||
// If len(indices) is not multiple of 3, DrawTriangles panics.
|
||||
//
|
||||
// The rule in which DrawTriangles works effectively is same as DrawImage's.
|
||||
//
|
||||
// In contrast to DrawImage, DrawTriangles doesn't care source image edges.
|
||||
// This means that you might need to add 1px gap on a source region when you render an image by DrawTriangles.
|
||||
// Note that Ebiten creates texture atlases internally, so you still have to care this even when
|
||||
// you render a single image.
|
||||
//
|
||||
// Note that this API is experimental.
|
||||
func (i *Image) DrawTriangles(vertices []Vertex, indices []uint16, img *Image, options *DrawTrianglesOptions) {
|
||||
if len(indices)%3 != 0 {
|
||||
panic("ebiten: len(indices) % 3 must be 0")
|
||||
}
|
||||
// TODO: Check the maximum value of indices and len(vertices)?
|
||||
|
||||
if options == nil {
|
||||
options = &DrawTrianglesOptions{}
|
||||
}
|
||||
|
||||
mode := opengl.CompositeMode(options.CompositeMode)
|
||||
|
||||
filter := graphics.FilterNearest
|
||||
if options.Filter != FilterDefault {
|
||||
filter = graphics.Filter(options.Filter)
|
||||
} else if img.filter != FilterDefault {
|
||||
filter = graphics.Filter(img.filter)
|
||||
}
|
||||
|
||||
vs := []float32{}
|
||||
src := img.shareableImages[0]
|
||||
for _, v := range vertices {
|
||||
vs = append(vs, src.Vertex(float32(v.DstX), float32(v.DstY), v.SrcX, v.SrcY, v.ColorR, v.ColorG, v.ColorB, v.ColorA)...)
|
||||
}
|
||||
i.shareableImages[0].DrawImage(img.shareableImages[0], vs, indices, options.ColorM.impl, mode, filter)
|
||||
}
|
||||
|
||||
// Bounds returns the bounds of the image.
|
||||
func (i *Image) Bounds() image.Rectangle {
|
||||
w, h := i.Size()
|
||||
|
@ -56,10 +56,19 @@ varying vec2 varying_tex_coord_min;
|
||||
varying vec2 varying_tex_coord_max;
|
||||
varying vec4 varying_color_scale;
|
||||
|
||||
bool isNaN(float x) {
|
||||
return x != x;
|
||||
}
|
||||
|
||||
void main(void) {
|
||||
varying_tex_coord = vec2(tex_coord[0], tex_coord[1]);
|
||||
varying_tex_coord_min = vec2(min(tex_coord[0], tex_coord[2]), min(tex_coord[1], tex_coord[3]));
|
||||
varying_tex_coord_max = vec2(max(tex_coord[0], tex_coord[2]), max(tex_coord[1], tex_coord[3]));
|
||||
if (!isNaN(tex_coord[2]) && !isNaN(tex_coord[3])) {
|
||||
varying_tex_coord_min = vec2(min(tex_coord[0], tex_coord[2]), min(tex_coord[1], tex_coord[3]));
|
||||
varying_tex_coord_max = vec2(max(tex_coord[0], tex_coord[2]), max(tex_coord[1], tex_coord[3]));
|
||||
} else {
|
||||
varying_tex_coord_min = vec2(0, 0);
|
||||
varying_tex_coord_max = vec2(1, 1);
|
||||
}
|
||||
varying_color_scale = color_scale;
|
||||
gl_Position = projection_matrix * vec4(vertex, 0, 1);
|
||||
}
|
||||
|
@ -15,6 +15,8 @@
|
||||
package graphicsutil
|
||||
|
||||
import (
|
||||
"math"
|
||||
|
||||
"github.com/hajimehoshi/ebiten/internal/graphics"
|
||||
"github.com/hajimehoshi/ebiten/internal/opengl"
|
||||
)
|
||||
@ -135,3 +137,35 @@ var (
|
||||
func QuadIndices() []uint16 {
|
||||
return quadIndices
|
||||
}
|
||||
|
||||
var (
|
||||
nan32 = float32(math.NaN())
|
||||
)
|
||||
|
||||
func Vertex(width, height int, dx, dy, sx, sy float32, cr, cg, cb, ca float32) []float32 {
|
||||
if !isPowerOf2(width) {
|
||||
panic("not reached")
|
||||
}
|
||||
if !isPowerOf2(height) {
|
||||
panic("not reached")
|
||||
}
|
||||
|
||||
wf := float32(width)
|
||||
hf := float32(height)
|
||||
|
||||
// Specifying a range explicitly here is redundant but this helps optimization
|
||||
// to eliminate boundry checks.
|
||||
vs := theVerticesBackend.sliceForOneQuad()[0:10]
|
||||
vs[0] = dx
|
||||
vs[1] = dy
|
||||
vs[2] = sx / wf
|
||||
vs[3] = sy / hf
|
||||
vs[4] = nan32
|
||||
vs[5] = nan32
|
||||
vs[6] = cr
|
||||
vs[7] = cg
|
||||
vs[8] = cb
|
||||
vs[9] = ca
|
||||
|
||||
return vs
|
||||
}
|
||||
|
@ -193,6 +193,15 @@ func (i *Image) QuadVertices(sx0, sy0, sx1, sy1 int, a, b, c, d, tx, ty float32,
|
||||
return graphicsutil.QuadVertices(w, h, sx0+ox, sy0+oy, sx1+ox, sy1+oy, a, b, c, d, tx, ty, cr, cg, cb, ca)
|
||||
}
|
||||
|
||||
func (i *Image) Vertex(dx, dy, sx, sy float32, cr, cg, cb, ca float32) []float32 {
|
||||
if i.backend == nil {
|
||||
i.allocate(true)
|
||||
}
|
||||
ox, oy, _, _ := i.region()
|
||||
w, h := i.backend.restorable.SizePowerOf2()
|
||||
return graphicsutil.Vertex(w, h, dx, dy, sx+float32(ox), sy+float32(oy), cr, cg, cb, ca)
|
||||
}
|
||||
|
||||
const MaxCountForShare = 10
|
||||
|
||||
func (i *Image) DrawImage(img *Image, vertices []float32, indices []uint16, colorm *affine.ColorM, mode opengl.CompositeMode, filter graphics.Filter) {
|
||||
|
Loading…
Reference in New Issue
Block a user