mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-25 19:28:57 +01:00
parent
85730b433e
commit
8738d182fb
@ -15,7 +15,6 @@
|
|||||||
package restorable_test
|
package restorable_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"image"
|
|
||||||
"image/color"
|
"image/color"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@ -31,16 +30,15 @@ func TestShader(t *testing.T) {
|
|||||||
t.Skip("shader is not available on this environment")
|
t.Skip("shader is not available on this environment")
|
||||||
}
|
}
|
||||||
|
|
||||||
img := newImageFromImage(image.NewRGBA(image.Rect(0, 0, 1, 1)))
|
img := NewImage(1, 1, false)
|
||||||
defer img.Dispose()
|
defer img.Dispose()
|
||||||
|
|
||||||
ir := etesting.ShaderProgramFill(0xff, 0, 0, 0xff)
|
ir := etesting.ShaderProgramFill(0xff, 0, 0, 0xff)
|
||||||
s := NewShader(&ir)
|
s := NewShader(&ir)
|
||||||
is := graphics.QuadIndices()
|
|
||||||
us := map[int]interface{}{
|
us := map[int]interface{}{
|
||||||
0: []float32{1, 1},
|
0: []float32{1, 1},
|
||||||
}
|
}
|
||||||
img.DrawTriangles(nil, quadVertices(1, 1, 0, 0), is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressClampToZero, s, us)
|
img.DrawTriangles(nil, quadVertices(1, 1, 0, 0), graphics.QuadIndices(), nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressClampToZero, s, us)
|
||||||
|
|
||||||
if err := ResolveStaleImages(); err != nil {
|
if err := ResolveStaleImages(); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -55,3 +53,44 @@ func TestShader(t *testing.T) {
|
|||||||
t.Errorf("got %v, want %v", got, want)
|
t.Errorf("got %v, want %v", got, want)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestShaderChain(t *testing.T) {
|
||||||
|
if !graphicscommand.IsShaderAvailable() {
|
||||||
|
t.Skip("shader is not available on this environment")
|
||||||
|
}
|
||||||
|
|
||||||
|
const num = 10
|
||||||
|
imgs := []*Image{}
|
||||||
|
for i := 0; i < num; i++ {
|
||||||
|
img := NewImage(1, 1, false)
|
||||||
|
defer img.Dispose()
|
||||||
|
imgs = append(imgs, img)
|
||||||
|
}
|
||||||
|
|
||||||
|
imgs[0].ReplacePixels([]byte{0xff, 0, 0, 0xff}, 0, 0, 1, 1)
|
||||||
|
|
||||||
|
ir := etesting.ShaderProgramImages(1)
|
||||||
|
s := NewShader(&ir)
|
||||||
|
for i := 0; i < num-1; i++ {
|
||||||
|
us := map[int]interface{}{
|
||||||
|
0: []float32{1, 1},
|
||||||
|
1: imgs[i],
|
||||||
|
}
|
||||||
|
imgs[i+1].DrawTriangles(nil, quadVertices(1, 1, 0, 0), graphics.QuadIndices(), nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressClampToZero, s, us)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ResolveStaleImages(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := RestoreIfNeeded(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, img := range imgs {
|
||||||
|
want := color.RGBA{0xff, 0, 0, 0xff}
|
||||||
|
got := pixelsToColor(img.BasePixelsForTesting(), 0, 0)
|
||||||
|
if !sameColors(got, want, 1) {
|
||||||
|
t.Errorf("%d: got %v, want %v", i, got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -45,7 +45,7 @@ type VertexFunc struct {
|
|||||||
Block Block
|
Block Block
|
||||||
}
|
}
|
||||||
|
|
||||||
// FragmentFunc takes pseudo in-params, and the number is len(varyings) + 2.
|
// FragmentFunc takes pseudo params, and the number is len(varyings) + 2.
|
||||||
// If index == len(varyings), the param represents the coordinate of the fragment (gl_FragCoord in GLSL).
|
// If index == len(varyings), the param represents the coordinate of the fragment (gl_FragCoord in GLSL).
|
||||||
// If index == len(varyings)+1, the param is an out-param representing the color of the pixel (gl_FragColor in GLSL).
|
// If index == len(varyings)+1, the param is an out-param representing the color of the pixel (gl_FragColor in GLSL).
|
||||||
type FragmentFunc struct {
|
type FragmentFunc struct {
|
||||||
|
@ -159,7 +159,20 @@ var (
|
|||||||
Exprs: []shaderir.Expr{
|
Exprs: []shaderir.Expr{
|
||||||
{
|
{
|
||||||
Type: shaderir.LocalVariable,
|
Type: shaderir.LocalVariable,
|
||||||
Index: 4,
|
Index: 4, // the varying variable
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Type: shaderir.LocalVariable,
|
||||||
|
Index: 1, // the 2nd attribute variable
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Type: shaderir.Assign,
|
||||||
|
Exprs: []shaderir.Expr{
|
||||||
|
{
|
||||||
|
Type: shaderir.LocalVariable,
|
||||||
|
Index: 5, // gl_Position in GLSL
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Type: shaderir.Binary,
|
Type: shaderir.Binary,
|
||||||
@ -174,25 +187,31 @@ var (
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
defaultProgram = shaderir.Program{
|
)
|
||||||
|
|
||||||
|
func defaultProgram() shaderir.Program {
|
||||||
|
return shaderir.Program{
|
||||||
Uniforms: []shaderir.Type{
|
Uniforms: []shaderir.Type{
|
||||||
{Main: shaderir.Vec2},
|
{Main: shaderir.Vec2},
|
||||||
},
|
},
|
||||||
Attributes: []shaderir.Type{
|
Attributes: []shaderir.Type{
|
||||||
{Main: shaderir.Vec2},
|
{Main: shaderir.Vec2}, // Local var (0) in the vertex shader
|
||||||
{Main: shaderir.Vec2},
|
{Main: shaderir.Vec2}, // Local var (1) in the vertex shader
|
||||||
{Main: shaderir.Vec4},
|
{Main: shaderir.Vec4}, // Local var (2) in the vertex shader
|
||||||
{Main: shaderir.Vec4},
|
{Main: shaderir.Vec4}, // Local var (3) in the vertex shader
|
||||||
|
},
|
||||||
|
Varyings: []shaderir.Type{
|
||||||
|
{Main: shaderir.Vec2}, // Local var (4) in the vertex shader, (0) in the fragment shader
|
||||||
},
|
},
|
||||||
VertexFunc: defaultVertexFunc,
|
VertexFunc: defaultVertexFunc,
|
||||||
}
|
}
|
||||||
)
|
}
|
||||||
|
|
||||||
// ShaderProgramFill returns a shader intermediate representation to fill the frambuffer.
|
// ShaderProgramFill returns a shader intermediate representation to fill the frambuffer.
|
||||||
//
|
//
|
||||||
// Uniform variables:
|
// Uniform variables:
|
||||||
//
|
//
|
||||||
// 0. the framebuffer size (vec2)
|
// 0: the framebuffer size (Vec2)
|
||||||
func ShaderProgramFill(r, g, b, a byte) shaderir.Program {
|
func ShaderProgramFill(r, g, b, a byte) shaderir.Program {
|
||||||
clr := shaderir.Expr{
|
clr := shaderir.Expr{
|
||||||
Type: shaderir.Call,
|
Type: shaderir.Call,
|
||||||
@ -220,7 +239,7 @@ func ShaderProgramFill(r, g, b, a byte) shaderir.Program {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
p := defaultProgram
|
p := defaultProgram()
|
||||||
p.FragmentFunc = shaderir.FragmentFunc{
|
p.FragmentFunc = shaderir.FragmentFunc{
|
||||||
Block: shaderir.Block{
|
Block: shaderir.Block{
|
||||||
Stmts: []shaderir.Stmt{
|
Stmts: []shaderir.Stmt{
|
||||||
@ -229,7 +248,7 @@ func ShaderProgramFill(r, g, b, a byte) shaderir.Program {
|
|||||||
Exprs: []shaderir.Expr{
|
Exprs: []shaderir.Expr{
|
||||||
{
|
{
|
||||||
Type: shaderir.LocalVariable,
|
Type: shaderir.LocalVariable,
|
||||||
Index: 1,
|
Index: 2,
|
||||||
},
|
},
|
||||||
clr,
|
clr,
|
||||||
},
|
},
|
||||||
@ -240,3 +259,121 @@ func ShaderProgramFill(r, g, b, a byte) shaderir.Program {
|
|||||||
|
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ShaderProgramImages returns a shader intermediate representation to render the frambuffer with the given images.
|
||||||
|
//
|
||||||
|
// Uniform variables:
|
||||||
|
//
|
||||||
|
// 0: the framebuffer size (Vec2)
|
||||||
|
// 1: the first images (Sampler2D)
|
||||||
|
// 3n-1: the (n+1)th image (Sampler2D)
|
||||||
|
// 3n: the (n+1)th image's size (Vec2)
|
||||||
|
// 3n+1: the (n+1)th image's region (Vec4)
|
||||||
|
//
|
||||||
|
// The first image's size and region are represented in attribute variables.
|
||||||
|
//
|
||||||
|
// The size and region values are actually not used in this shader so far.
|
||||||
|
func ShaderProgramImages(imageNum int) shaderir.Program {
|
||||||
|
if imageNum <= 0 {
|
||||||
|
panic("testing: imageNum must be >= 1")
|
||||||
|
}
|
||||||
|
|
||||||
|
p := defaultProgram()
|
||||||
|
|
||||||
|
for i := 0; i < imageNum; i++ {
|
||||||
|
p.Uniforms = append(p.Uniforms, shaderir.Type{Main: shaderir.Sampler2D})
|
||||||
|
if i > 0 {
|
||||||
|
p.Uniforms = append(p.Uniforms, shaderir.Type{Main: shaderir.Vec2})
|
||||||
|
p.Uniforms = append(p.Uniforms, shaderir.Type{Main: shaderir.Vec4})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// In the fragment shader, local variables are:
|
||||||
|
//
|
||||||
|
// 0: Varying variables (vec2)
|
||||||
|
// 1: gl_FragCoord
|
||||||
|
// 2: gl_FragColor
|
||||||
|
// 3: Actual local variables in the main function
|
||||||
|
|
||||||
|
local := shaderir.Expr{
|
||||||
|
Type: shaderir.LocalVariable,
|
||||||
|
Index: 3,
|
||||||
|
}
|
||||||
|
fragColor := shaderir.Expr{
|
||||||
|
Type: shaderir.LocalVariable,
|
||||||
|
Index: 2,
|
||||||
|
}
|
||||||
|
texPos := shaderir.Expr{
|
||||||
|
Type: shaderir.LocalVariable,
|
||||||
|
Index: 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
var stmts []shaderir.Stmt
|
||||||
|
for i := 0; i < imageNum; i++ {
|
||||||
|
var rhs shaderir.Expr
|
||||||
|
if i == 0 {
|
||||||
|
rhs = shaderir.Expr{
|
||||||
|
Type: shaderir.Call,
|
||||||
|
Exprs: []shaderir.Expr{
|
||||||
|
{
|
||||||
|
Type: shaderir.BuiltinFuncExpr,
|
||||||
|
BuiltinFunc: shaderir.Texture2D,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Type: shaderir.UniformVariable,
|
||||||
|
Index: 1,
|
||||||
|
},
|
||||||
|
texPos,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rhs = shaderir.Expr{
|
||||||
|
Type: shaderir.Binary,
|
||||||
|
Op: shaderir.Add,
|
||||||
|
Exprs: []shaderir.Expr{
|
||||||
|
local,
|
||||||
|
{
|
||||||
|
Type: shaderir.Call,
|
||||||
|
Exprs: []shaderir.Expr{
|
||||||
|
{
|
||||||
|
Type: shaderir.BuiltinFuncExpr,
|
||||||
|
BuiltinFunc: shaderir.Texture2D,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Type: shaderir.UniformVariable,
|
||||||
|
Index: 3*i - 1,
|
||||||
|
},
|
||||||
|
texPos,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stmts = append(stmts, shaderir.Stmt{
|
||||||
|
Type: shaderir.Assign,
|
||||||
|
Exprs: []shaderir.Expr{
|
||||||
|
local,
|
||||||
|
rhs,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
stmts = append(stmts, shaderir.Stmt{
|
||||||
|
Type: shaderir.Assign,
|
||||||
|
Exprs: []shaderir.Expr{
|
||||||
|
fragColor,
|
||||||
|
local,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
p.FragmentFunc = shaderir.FragmentFunc{
|
||||||
|
Block: shaderir.Block{
|
||||||
|
LocalVars: []shaderir.Type{
|
||||||
|
{Main: shaderir.Vec4},
|
||||||
|
},
|
||||||
|
Stmts: stmts,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user