mirror of
				https://github.com/hajimehoshi/ebiten.git
				synced 2025-10-31 03:36:21 +08:00 
			
		
		
		
	shader: Enable more Go syntax
This commit is contained in:
		| @@ -29,6 +29,8 @@ const ( | |||||||
|  |  | ||||||
| const shaderSrc = `package main | const shaderSrc = `package main | ||||||
|  |  | ||||||
|  | var Time float | ||||||
|  |  | ||||||
| // viewportSize is a predefined function. | // viewportSize is a predefined function. | ||||||
|  |  | ||||||
| func Vertex(position vec2, texCoord vec2, color vec4) vec4 { | func Vertex(position vec2, texCoord vec2, color vec4) vec4 { | ||||||
| @@ -41,14 +43,22 @@ func Vertex(position vec2, texCoord vec2, color vec4) vec4 { | |||||||
| } | } | ||||||
|  |  | ||||||
| func Fragment(position vec4) vec4 { | func Fragment(position vec4) vec4 { | ||||||
| 	return vec4(position.x/viewportSize().x, position.y/viewportSize().y, 0, 1) | 	pos := position.xy / viewportSize() | ||||||
|  | 	color := 0.0 | ||||||
|  | 	color += sin(pos.x * cos(Time / 15.0) * 80.0) + cos(pos.y * cos(Time / 15.0) * 10.0) | ||||||
|  | 	color += sin(pos.y * sin(Time / 10.0) * 40.0) + cos(pos.x * sin(Time / 25.0) * 40.0) | ||||||
|  | 	color += sin(pos.x * sin(Time / 5.0) * 10.0) + sin(pos.y * sin(Time / 35.0) * 80.0) | ||||||
|  | 	color *= sin(Time / 10.0) * 0.5 | ||||||
|  | 	return vec4(color, color * 0.5, sin(color + Time / 3.0 ) * 0.75, 1.0) | ||||||
| }` | }` | ||||||
|  |  | ||||||
| type Game struct { | type Game struct { | ||||||
| 	shader *ebiten.Shader | 	shader *ebiten.Shader | ||||||
|  | 	time   int | ||||||
| } | } | ||||||
|  |  | ||||||
| func (g *Game) Update(screen *ebiten.Image) error { | func (g *Game) Update(screen *ebiten.Image) error { | ||||||
|  | 	g.time++ | ||||||
| 	if g.shader == nil { | 	if g.shader == nil { | ||||||
| 		var err error | 		var err error | ||||||
| 		g.shader, err = ebiten.NewShader([]byte(shaderSrc)) | 		g.shader, err = ebiten.NewShader([]byte(shaderSrc)) | ||||||
| @@ -80,7 +90,12 @@ func (g *Game) Draw(screen *ebiten.Image) { | |||||||
| 		}, | 		}, | ||||||
| 	} | 	} | ||||||
| 	is := []uint16{0, 1, 2, 1, 2, 3} | 	is := []uint16{0, 1, 2, 1, 2, 3} | ||||||
| 	screen.DrawTrianglesWithShader(vs, is, g.shader, nil) |  | ||||||
|  | 	op := &ebiten.DrawTrianglesWithShaderOptions{} | ||||||
|  | 	op.Uniforms = []interface{}{ | ||||||
|  | 		float32(g.time) / 60, // time | ||||||
|  | 	} | ||||||
|  | 	screen.DrawTrianglesWithShader(vs, is, g.shader, op) | ||||||
| } | } | ||||||
|  |  | ||||||
| func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) { | func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) { | ||||||
|   | |||||||
| @@ -285,7 +285,7 @@ func (g *Graphics) useProgram(program program, uniforms []uniformVariable) error | |||||||
| 			} | 			} | ||||||
| 			g.context.bindTexture(v) | 			g.context.bindTexture(v) | ||||||
| 		default: | 		default: | ||||||
| 			return fmt.Errorf("opengl: unexpected uniform value: %v", u.value) | 			return fmt.Errorf("opengl: unexpected uniform value: %v (type: %T)", u.value, u.value) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	return nil | 	return nil | ||||||
|   | |||||||
| @@ -557,7 +557,9 @@ func (cs *compileState) parseBlock(outer *block, b *ast.BlockStmt, inParams, out | |||||||
| 						if len(ts) > 1 { | 						if len(ts) > 1 { | ||||||
| 							cs.addError(l.Pos(), fmt.Sprintf("single-value context and multiple-value context cannot be mixed")) | 							cs.addError(l.Pos(), fmt.Sprintf("single-value context and multiple-value context cannot be mixed")) | ||||||
| 						} | 						} | ||||||
| 						v.typ = ts[0] | 						if len(ts) == 1 { | ||||||
|  | 							v.typ = ts[0] | ||||||
|  | 						} | ||||||
| 					} else { | 					} else { | ||||||
| 						if i == 0 { | 						if i == 0 { | ||||||
| 							rhsTypes = cs.detectType(block, l.Rhs[0]) | 							rhsTypes = cs.detectType(block, l.Rhs[0]) | ||||||
| @@ -578,6 +580,40 @@ func (cs *compileState) parseBlock(outer *block, b *ast.BlockStmt, inParams, out | |||||||
| 					return nil | 					return nil | ||||||
| 				} | 				} | ||||||
| 				cs.assign(block, l.Pos(), l.Lhs, l.Rhs) | 				cs.assign(block, l.Pos(), l.Lhs, l.Rhs) | ||||||
|  | 			case token.ADD_ASSIGN, token.SUB_ASSIGN, token.MUL_ASSIGN, token.QUO_ASSIGN, token.REM_ASSIGN: | ||||||
|  | 				var op shaderir.Op | ||||||
|  | 				switch l.Tok { | ||||||
|  | 				case token.ADD_ASSIGN: | ||||||
|  | 					op = shaderir.Add | ||||||
|  | 				case token.SUB_ASSIGN: | ||||||
|  | 					op = shaderir.Sub | ||||||
|  | 				case token.MUL_ASSIGN: | ||||||
|  | 					op = shaderir.Mul | ||||||
|  | 				case token.QUO_ASSIGN: | ||||||
|  | 					op = shaderir.Div | ||||||
|  | 				case token.REM_ASSIGN: | ||||||
|  | 					op = shaderir.ModOp | ||||||
|  | 				} | ||||||
|  | 				rhs, stmts := cs.parseExpr(block, l.Rhs[0]) | ||||||
|  | 				block.ir.Stmts = append(block.ir.Stmts, stmts...) | ||||||
|  | 				lhs, stmts := cs.parseExpr(block, l.Lhs[0]) | ||||||
|  | 				block.ir.Stmts = append(block.ir.Stmts, stmts...) | ||||||
|  | 				block.ir.Stmts = append(block.ir.Stmts, shaderir.Stmt{ | ||||||
|  | 					Type: shaderir.Assign, | ||||||
|  | 					Exprs: []shaderir.Expr{ | ||||||
|  | 						lhs[0], | ||||||
|  | 						{ | ||||||
|  | 							Type: shaderir.Binary, | ||||||
|  | 							Op:   op, | ||||||
|  | 							Exprs: []shaderir.Expr{ | ||||||
|  | 								lhs[0], | ||||||
|  | 								rhs[0], | ||||||
|  | 							}, | ||||||
|  | 						}, | ||||||
|  | 					}, | ||||||
|  | 				}) | ||||||
|  | 			default: | ||||||
|  | 				cs.addError(l.Pos(), fmt.Sprintf("unexpected token: %s", l.Tok)) | ||||||
| 			} | 			} | ||||||
| 		case *ast.BlockStmt: | 		case *ast.BlockStmt: | ||||||
| 			b := cs.parseBlock(block, l, nil, nil) | 			b := cs.parseBlock(block, l, nil, nil) | ||||||
|   | |||||||
| @@ -72,6 +72,30 @@ func (cs *compileState) detectType(b *block, expr ast.Expr) []shaderir.Type { | |||||||
| 		} | 		} | ||||||
| 		cs.addError(expr.Pos(), fmt.Sprintf("unexpected literal: %s", e.Value)) | 		cs.addError(expr.Pos(), fmt.Sprintf("unexpected literal: %s", e.Value)) | ||||||
| 		return nil | 		return nil | ||||||
|  | 	case *ast.BinaryExpr: | ||||||
|  | 		t1, t2 := cs.detectType(b, e.X), cs.detectType(b, e.Y) | ||||||
|  | 		if len(t1) != 1 || len(t2) != 1 { | ||||||
|  | 			cs.addError(expr.Pos(), fmt.Sprintf("binary operator cannot be used for multiple-value context: %v", expr)) | ||||||
|  | 			return nil | ||||||
|  | 		} | ||||||
|  | 		if !t1[0].Equal(&t2[0]) { | ||||||
|  | 			// TODO: Move this checker to shaderir | ||||||
|  | 			if t1[0].Main == shaderir.Float { | ||||||
|  | 				switch t2[0].Main { | ||||||
|  | 				case shaderir.Vec2, shaderir.Vec3, shaderir.Vec4: | ||||||
|  | 					return t2 | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			if t2[0].Main == shaderir.Float { | ||||||
|  | 				switch t1[0].Main { | ||||||
|  | 				case shaderir.Vec2, shaderir.Vec3, shaderir.Vec4: | ||||||
|  | 					return t1 | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			cs.addError(expr.Pos(), fmt.Sprintf("types between a binary operator don't match")) | ||||||
|  | 			return nil | ||||||
|  | 		} | ||||||
|  | 		return t1 | ||||||
| 	case *ast.CallExpr: | 	case *ast.CallExpr: | ||||||
| 		n := e.Fun.(*ast.Ident).Name | 		n := e.Fun.(*ast.Ident).Name | ||||||
| 		f, ok := shaderir.ParseBuiltinFunc(n) | 		f, ok := shaderir.ParseBuiltinFunc(n) | ||||||
| @@ -127,8 +151,34 @@ func (cs *compileState) detectType(b *block, expr ast.Expr) []shaderir.Type { | |||||||
| 		} | 		} | ||||||
| 		cs.addError(expr.Pos(), fmt.Sprintf("unexpected identifier: %s", n)) | 		cs.addError(expr.Pos(), fmt.Sprintf("unexpected identifier: %s", n)) | ||||||
| 		return nil | 		return nil | ||||||
| 	//case *ast.SelectorExpr: | 	case *ast.SelectorExpr: | ||||||
| 	//return fmt.Sprintf("%cs.%s", dumpExpr(e.X), dumpExpr(e.Sel)) | 		t := cs.detectType(b, e.X) | ||||||
|  | 		if len(t) != 1 { | ||||||
|  | 			cs.addError(expr.Pos(), fmt.Sprintf("selector is not available in multiple-value context: %v", e.X)) | ||||||
|  | 			return nil | ||||||
|  | 		} | ||||||
|  | 		switch t[0].Main { | ||||||
|  | 		case shaderir.Vec2, shaderir.Vec3, shaderir.Vec4: | ||||||
|  | 			switch len(e.Sel.Name) { | ||||||
|  | 			case 1: | ||||||
|  | 				return []shaderir.Type{{Main: shaderir.Float}} | ||||||
|  | 			case 2: | ||||||
|  | 				return []shaderir.Type{{Main: shaderir.Vec2}} | ||||||
|  | 			case 3: | ||||||
|  | 				return []shaderir.Type{{Main: shaderir.Float}} | ||||||
|  | 			case 4: | ||||||
|  | 				return []shaderir.Type{{Main: shaderir.Float}} | ||||||
|  | 			default: | ||||||
|  | 				cs.addError(expr.Pos(), fmt.Sprintf("invalid selector: %s", e.Sel.Name)) | ||||||
|  | 			} | ||||||
|  | 			return nil | ||||||
|  | 		case shaderir.Struct: | ||||||
|  | 			cs.addError(expr.Pos(), fmt.Sprintf("selector for a struct is not implemented yet")) | ||||||
|  | 			return nil | ||||||
|  | 		default: | ||||||
|  | 			cs.addError(expr.Pos(), fmt.Sprintf("selector is not available for: %v", expr)) | ||||||
|  | 			return nil | ||||||
|  | 		} | ||||||
| 	default: | 	default: | ||||||
| 		cs.addError(expr.Pos(), fmt.Sprintf("detecting type not implemented: %#v", expr)) | 		cs.addError(expr.Pos(), fmt.Sprintf("detecting type not implemented: %#v", expr)) | ||||||
| 		return nil | 		return nil | ||||||
|   | |||||||
| @@ -25,6 +25,24 @@ type Type struct { | |||||||
| 	Length int | 	Length int | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (t *Type) Equal(rhs *Type) bool { | ||||||
|  | 	if t.Main != rhs.Main { | ||||||
|  | 		return false | ||||||
|  | 	} | ||||||
|  | 	if t.Length != rhs.Length { | ||||||
|  | 		return false | ||||||
|  | 	} | ||||||
|  | 	if len(t.Sub) != len(rhs.Sub) { | ||||||
|  | 		return false | ||||||
|  | 	} | ||||||
|  | 	for i, s := range t.Sub { | ||||||
|  | 		if !s.Equal(&rhs.Sub[i]) { | ||||||
|  | 			return false | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return true | ||||||
|  | } | ||||||
|  |  | ||||||
| func (t *Type) serialize() string { | func (t *Type) serialize() string { | ||||||
| 	switch t.Main { | 	switch t.Main { | ||||||
| 	case None: | 	case None: | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Hajime Hoshi
					Hajime Hoshi