mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-25 11:18:54 +01:00
parent
bff760af01
commit
2cc809516f
11
image.go
11
image.go
@ -295,6 +295,13 @@ type Vertex struct {
|
|||||||
ColorG float32
|
ColorG float32
|
||||||
ColorB float32
|
ColorB float32
|
||||||
ColorA float32
|
ColorA float32
|
||||||
|
|
||||||
|
// Custom0/Custom1/Custom2/Custom3 represents general-purpose values passed to the shader.
|
||||||
|
// In order to use them, Fragment must have an additional vec4 argument.
|
||||||
|
Custom0 float32
|
||||||
|
Custom1 float32
|
||||||
|
Custom2 float32
|
||||||
|
Custom3 float32
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ [0]byte = [unsafe.Sizeof(Vertex{}) - unsafe.Sizeof(float32(0))*graphics.VertexFloatCount]byte{}
|
var _ [0]byte = [unsafe.Sizeof(Vertex{}) - unsafe.Sizeof(float32(0))*graphics.VertexFloatCount]byte{}
|
||||||
@ -668,6 +675,10 @@ func (i *Image) DrawTrianglesShader(vertices []Vertex, indices []uint16, shader
|
|||||||
vs[i*graphics.VertexFloatCount+5] = v.ColorG
|
vs[i*graphics.VertexFloatCount+5] = v.ColorG
|
||||||
vs[i*graphics.VertexFloatCount+6] = v.ColorB
|
vs[i*graphics.VertexFloatCount+6] = v.ColorB
|
||||||
vs[i*graphics.VertexFloatCount+7] = v.ColorA
|
vs[i*graphics.VertexFloatCount+7] = v.ColorA
|
||||||
|
vs[i*graphics.VertexFloatCount+8] = v.Custom0
|
||||||
|
vs[i*graphics.VertexFloatCount+9] = v.Custom1
|
||||||
|
vs[i*graphics.VertexFloatCount+10] = v.Custom2
|
||||||
|
vs[i*graphics.VertexFloatCount+11] = v.Custom3
|
||||||
}
|
}
|
||||||
|
|
||||||
is := i.ensureTmpIndices(len(indices))
|
is := i.ensureTmpIndices(len(indices))
|
||||||
|
@ -154,8 +154,8 @@ func imageSrc%[1]dAt(pos vec2) vec4 {
|
|||||||
shaderSuffix += `
|
shaderSuffix += `
|
||||||
var __projectionMatrix mat4
|
var __projectionMatrix mat4
|
||||||
|
|
||||||
func __vertex(dstPos vec2, srcPos vec2, color vec4) (vec4, vec2, vec4) {
|
func __vertex(dstPos vec2, srcPos vec2, color vec4, custom vec4) (vec4, vec2, vec4, vec4) {
|
||||||
return __projectionMatrix * vec4(dstPos, 0, 1), srcPos, color
|
return __projectionMatrix * vec4(dstPos, 0, 1), srcPos, color, custom
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
return shaderSuffix, nil
|
return shaderSuffix, nil
|
||||||
|
@ -39,7 +39,7 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
VertexFloatCount = 8
|
VertexFloatCount = 12
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -345,10 +345,10 @@ func (cs *compileState) parse(f *ast.File) {
|
|||||||
// Check varying variables.
|
// Check varying variables.
|
||||||
// In testings, there might not be vertex and fragment entry points.
|
// In testings, there might not be vertex and fragment entry points.
|
||||||
if len(vertexOutParams) > 0 && len(fragmentInParams) > 0 {
|
if len(vertexOutParams) > 0 && len(fragmentInParams) > 0 {
|
||||||
if len(vertexOutParams) != len(fragmentInParams) {
|
|
||||||
cs.addError(0, "the number of vertex entry point's returning values and the number of fragment entry point's params must be the same")
|
|
||||||
}
|
|
||||||
for i, t := range vertexOutParams {
|
for i, t := range vertexOutParams {
|
||||||
|
if len(fragmentInParams) <= i {
|
||||||
|
break
|
||||||
|
}
|
||||||
if !t.Equal(&fragmentInParams[i]) {
|
if !t.Equal(&fragmentInParams[i]) {
|
||||||
cs.addError(0, "vertex entry point's returning value types and fragment entry point's param types must match")
|
cs.addError(0, "vertex entry point's returning value types and fragment entry point's param types must match")
|
||||||
}
|
}
|
||||||
@ -373,7 +373,7 @@ func (cs *compileState) parse(f *ast.File) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set attribute varying veraibles.
|
// Set attribute and varying veraibles.
|
||||||
cs.ir.Attributes = append(cs.ir.Attributes, vertexInParams...)
|
cs.ir.Attributes = append(cs.ir.Attributes, vertexInParams...)
|
||||||
if len(vertexOutParams) > 0 {
|
if len(vertexOutParams) > 0 {
|
||||||
// TODO: Check that these params are not arrays or structs
|
// TODO: Check that these params are not arrays or structs
|
||||||
@ -820,6 +820,18 @@ func (cs *compileState) parseFunc(block *block, d *ast.FuncDecl) (function, bool
|
|||||||
}
|
}
|
||||||
|
|
||||||
inParams, outParams, returnType := cs.parseFuncParams(block, d.Name.Name, d)
|
inParams, outParams, returnType := cs.parseFuncParams(block, d.Name.Name, d)
|
||||||
|
if d.Name.Name == cs.fragmentEntry {
|
||||||
|
// The 0th inParams is a special variable for position and is not included in varying variables.
|
||||||
|
if diff := len(cs.ir.Varyings) - (len(inParams) - 1); diff > 0 {
|
||||||
|
// inParams is not enough when the vertex shader has more returning values than the fragment shader's arguments.
|
||||||
|
for i := 0; i < diff; i++ {
|
||||||
|
inParams = append(inParams, variable{
|
||||||
|
name: "_",
|
||||||
|
typ: cs.ir.Varyings[len(inParams)-1+i],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
b, ok := cs.parseBlock(block, d.Name.Name, d.Body.List, inParams, outParams, returnType, true)
|
b, ok := cs.parseBlock(block, d.Name.Name, d.Body.List, inParams, outParams, returnType, true)
|
||||||
if !ok {
|
if !ok {
|
||||||
return function{}, false
|
return function{}, false
|
||||||
|
@ -2595,3 +2595,90 @@ func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestShaderCustomValues(t *testing.T) {
|
||||||
|
const w, h = 16, 16
|
||||||
|
|
||||||
|
dst := ebiten.NewImage(w, h)
|
||||||
|
s, err := ebiten.NewShader([]byte(`//kage:unit pixels
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
func Fragment(dstPos vec4, srcPos vec2, color vec4, custom vec4) vec4 {
|
||||||
|
return custom
|
||||||
|
}
|
||||||
|
`))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
clr := color.RGBA{R: 0x10, G: 0x20, B: 0x30, A: 0x40}
|
||||||
|
dst.DrawTrianglesShader([]ebiten.Vertex{
|
||||||
|
{
|
||||||
|
DstX: 0,
|
||||||
|
DstY: 0,
|
||||||
|
SrcX: 0,
|
||||||
|
SrcY: 0,
|
||||||
|
ColorR: 1,
|
||||||
|
ColorG: 1,
|
||||||
|
ColorB: 1,
|
||||||
|
ColorA: 1,
|
||||||
|
Custom0: float32(clr.R) / 0xff,
|
||||||
|
Custom1: float32(clr.G) / 0xff,
|
||||||
|
Custom2: float32(clr.B) / 0xff,
|
||||||
|
Custom3: float32(clr.A) / 0xff,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
DstX: w,
|
||||||
|
DstY: 0,
|
||||||
|
SrcX: w,
|
||||||
|
SrcY: 0,
|
||||||
|
ColorR: 1,
|
||||||
|
ColorG: 1,
|
||||||
|
ColorB: 1,
|
||||||
|
ColorA: 1,
|
||||||
|
Custom0: float32(clr.R) / 0xff,
|
||||||
|
Custom1: float32(clr.G) / 0xff,
|
||||||
|
Custom2: float32(clr.B) / 0xff,
|
||||||
|
Custom3: float32(clr.A) / 0xff,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
DstX: 0,
|
||||||
|
DstY: h,
|
||||||
|
SrcX: 0,
|
||||||
|
SrcY: h,
|
||||||
|
ColorR: 1,
|
||||||
|
ColorG: 1,
|
||||||
|
ColorB: 1,
|
||||||
|
ColorA: 1,
|
||||||
|
Custom0: float32(clr.R) / 0xff,
|
||||||
|
Custom1: float32(clr.G) / 0xff,
|
||||||
|
Custom2: float32(clr.B) / 0xff,
|
||||||
|
Custom3: float32(clr.A) / 0xff,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
DstX: w,
|
||||||
|
DstY: h,
|
||||||
|
SrcX: w,
|
||||||
|
SrcY: h,
|
||||||
|
ColorR: 1,
|
||||||
|
ColorG: 1,
|
||||||
|
ColorB: 1,
|
||||||
|
ColorA: 1,
|
||||||
|
Custom0: float32(clr.R) / 0xff,
|
||||||
|
Custom1: float32(clr.G) / 0xff,
|
||||||
|
Custom2: float32(clr.B) / 0xff,
|
||||||
|
Custom3: float32(clr.A) / 0xff,
|
||||||
|
},
|
||||||
|
}, []uint16{0, 1, 2, 1, 2, 3}, s, nil)
|
||||||
|
|
||||||
|
for j := 0; j < h; j++ {
|
||||||
|
for i := 0; i < w; i++ {
|
||||||
|
got := dst.At(i, j).(color.RGBA)
|
||||||
|
want := clr
|
||||||
|
if !sameColors(got, want, 2) {
|
||||||
|
t.Errorf("dst.At(%d, %d): got: %v, want: %v", i, j, got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user