From 7a94cbbd62f9b210959146570b483382cfe0a36c Mon Sep 17 00:00:00 2001 From: Hajime Hoshi Date: Fri, 19 Aug 2022 01:43:40 +0900 Subject: [PATCH] internal/shader: add refract Closes #2255 --- internal/shader/expr.go | 11 +++++++- internal/shader/syntax_test.go | 51 ++++++++++++++++++++++++++++++++++ internal/shaderir/program.go | 2 ++ 3 files changed, 63 insertions(+), 1 deletion(-) diff --git a/internal/shader/expr.go b/internal/shader/expr.go index e6ec076f3..258895ca0 100644 --- a/internal/shader/expr.go +++ b/internal/shader/expr.go @@ -447,7 +447,7 @@ func (cs *compileState) parseExpr(block *block, fname string, expr ast.Expr, mar }) return nil, nil, stmts, true - case shaderir.Clamp, shaderir.Mix, shaderir.Smoothstep, shaderir.Faceforward: + case shaderir.Clamp, shaderir.Mix, shaderir.Smoothstep, shaderir.Faceforward, shaderir.Refract: // 3 arguments if len(args) != 3 { cs.addError(e.Pos(), fmt.Sprintf("number of %s's arguments must be 3 but %d", callee.BuiltinFunc, len(args))) @@ -485,6 +485,15 @@ func (cs *compileState) parseExpr(block *block, fname string, expr ast.Expr, mar cs.addError(e.Pos(), fmt.Sprintf("the first and the second arguments for %s must equal to the third argument %s or float but %s and %s", callee.BuiltinFunc, argts[2].String(), argts[0].String(), argts[1].String())) return nil, nil, nil, false } + case shaderir.Refract: + if !argts[0].Equal(&argts[1]) { + cs.addError(e.Pos(), fmt.Sprintf("%s and %s don't match in argument to %s", argts[0].String(), argts[1].String(), callee.BuiltinFunc)) + return nil, nil, nil, false + } + if argts[2].Main != shaderir.Float { + cs.addError(e.Pos(), fmt.Sprintf("cannot use %s as float value in argument to %s", argts[2].String(), callee.BuiltinFunc)) + return nil, nil, nil, false + } default: if !argts[0].Equal(&argts[1]) || !argts[0].Equal(&argts[2]) { cs.addError(e.Pos(), fmt.Sprintf("all the argument types for %s must be the same but %s, %s, and %s", callee.BuiltinFunc, argts[0].String(), argts[1].String(), argts[2].String())) diff --git a/internal/shader/syntax_test.go b/internal/shader/syntax_test.go index f8fd7c49c..8f7c52728 100644 --- a/internal/shader/syntax_test.go +++ b/internal/shader/syntax_test.go @@ -2053,6 +2053,57 @@ func Fragment(position vec4, texCoord vec2, color vec4) vec4 { } } +// Issue #2184 +func TestSyntaxBuiltinFuncRefractType(t *testing.T) { + cases := []struct { + stmt string + err bool + }{ + {stmt: "a := refract(); _ = a", err: true}, + {stmt: "a := refract(1); _ = a", err: true}, + {stmt: "a := refract(false, false); _ = a", err: true}, + {stmt: "a := refract(1, 1); _ = a", err: true}, + {stmt: "a := refract(false, false, false); _ = a", err: true}, + {stmt: "a := refract(1, 1, 1); _ = a", err: false}, + {stmt: "a := refract(1.0, 1, 1); _ = a", err: false}, + {stmt: "a := refract(1, 1.0, 1); _ = a", err: false}, + {stmt: "a := refract(1, 1, 1.0); _ = a", err: false}, + {stmt: "a := refract(1, vec2(1), 1); _ = a", err: true}, + {stmt: "a := refract(1, 1, vec2(1)); _ = a", err: true}, + {stmt: "a := refract(1, vec2(1), vec2(1)); _ = a", err: true}, + {stmt: "a := refract(vec2(1), 1, 1); _ = a", err: true}, + {stmt: "a := refract(vec2(1), 1, vec2(1)); _ = a", err: true}, + {stmt: "a := refract(vec2(1), vec2(1), 1); _ = a", err: false}, // The third argument must be a float. + {stmt: "a := refract(vec2(1), vec2(1), vec2(1)); _ = a", err: true}, + {stmt: "a := refract(vec2(1), vec2(1), vec3(1)); _ = a", err: true}, + {stmt: "a := refract(vec3(1), 1, 1); _ = a", err: true}, + {stmt: "a := refract(vec3(1), 1, vec3(1)); _ = a", err: true}, + {stmt: "a := refract(vec3(1), vec3(1), 1); _ = a", err: false}, // The third argument must be a float. + {stmt: "a := refract(vec3(1), vec3(1), vec3(1)); _ = a", err: true}, + {stmt: "a := refract(vec4(1), 1, 1); _ = a", err: true}, + {stmt: "a := refract(vec4(1), 1, vec4(1)); _ = a", err: true}, + {stmt: "a := refract(vec4(1), vec4(1), 1); _ = a", err: false}, // The third argument must be a float. + {stmt: "a := refract(vec4(1), vec4(1), vec4(1)); _ = a", err: true}, + {stmt: "a := refract(1, 1, 1, 1); _ = a", err: true}, + } + + for _, c := range cases { + stmt := c.stmt + src := fmt.Sprintf(`package main + +func Fragment(position vec4, texCoord vec2, color vec4) vec4 { + %s + return position +}`, stmt) + _, err := compileToIR([]byte(src)) + if err == nil && c.err { + t.Errorf("%s must return an error but does not", stmt) + } else if err != nil && !c.err { + t.Errorf("%s must not return nil but returned %v", stmt, err) + } + } +} + // Issue #2184 func TestSyntaxBuiltinFuncCrossType(t *testing.T) { cases := []struct { diff --git a/internal/shaderir/program.go b/internal/shaderir/program.go index 8380d9102..60e97b32a 100644 --- a/internal/shaderir/program.go +++ b/internal/shaderir/program.go @@ -259,6 +259,7 @@ const ( Normalize BuiltinFunc = "normalize" Faceforward BuiltinFunc = "faceforward" Reflect BuiltinFunc = "reflect" + Refract BuiltinFunc = "refract" Transpose BuiltinFunc = "transpose" Texture2DF BuiltinFunc = "texture2D" Dfdx BuiltinFunc = "dfdx" @@ -313,6 +314,7 @@ func ParseBuiltinFunc(str string) (BuiltinFunc, bool) { Normalize, Faceforward, Reflect, + Refract, Transpose, Texture2DF, Dfdx,