shaderir: Implement vertex function

This commit is contained in:
Hajime Hoshi 2020-05-16 22:18:58 +09:00
parent eb5a2efad8
commit ddaed674dd
3 changed files with 96 additions and 21 deletions

View File

@ -51,6 +51,13 @@ func (p *Program) Glsl() string {
lines = append(lines, p.glslFunc(&f)...)
}
// Vertex func
if len(p.VertexFunc.Block.Stmts) > 0 {
lines = append(lines, "void main(void) {")
lines = append(lines, p.glslBlock(&p.VertexFunc.Block, 0, 0)...)
lines = append(lines, "}")
}
var stLines []string
for i, t := range p.structTypes {
stLines = append(stLines, fmt.Sprintf("struct S%d {", i))
@ -116,13 +123,13 @@ func (p *Program) glslFunc(f *Func) []string {
var lines []string
lines = append(lines, fmt.Sprintf("%s %s(%s) {", p.glslType(&f.Return), f.Name, argsstr))
lines = append(lines, p.glslBlock(&f.Block, f, 0, idx)...)
lines = append(lines, p.glslBlock(&f.Block, 0, idx)...)
lines = append(lines, "}")
return lines
}
func (p *Program) glslBlock(b *Block, f *Func, level int, localVarIndex int) []string {
func (p *Program) glslBlock(b *Block, level int, localVarIndex int) []string {
idt := strings.Repeat("\t", level+1)
var lines []string
@ -142,12 +149,24 @@ func (p *Program) glslBlock(b *Block, f *Func, level int, localVarIndex int) []s
switch e.Variable.Type {
case Uniform:
return fmt.Sprintf("U%d", e.Variable.Index)
case Attribute:
return fmt.Sprintf("A%d", e.Variable.Index)
case Varying:
return fmt.Sprintf("V%d", e.Variable.Index)
case Local:
return fmt.Sprintf("l%d", e.Variable.Index)
idx := e.Variable.Index
if b == &p.VertexFunc.Block {
na := len(p.Attributes)
nv := len(p.Varyings)
switch {
case idx < na:
return fmt.Sprintf("A%d", idx)
case idx < na+nv:
return fmt.Sprintf("V%d", idx-na)
case idx == na+nv:
return "gl_Position"
default:
return fmt.Sprintf("l%d", idx-(na+nv))
}
} else {
return fmt.Sprintf("l%d", idx)
}
default:
return fmt.Sprintf("?(unexpected variable type: %d)", e.Variable.Type)
}
@ -187,16 +206,16 @@ func (p *Program) glslBlock(b *Block, f *Func, level int, localVarIndex int) []s
lines = append(lines, fmt.Sprintf("%s%s;", idt, glslExpr(&s.Exprs[0])))
case BlockStmt:
lines = append(lines, idt+"{")
lines = append(lines, p.glslBlock(&s.Blocks[0], f, level+1, localVarIndex)...)
lines = append(lines, p.glslBlock(&s.Blocks[0], level+1, localVarIndex)...)
lines = append(lines, idt+"}")
case Assign:
lines = append(lines, fmt.Sprintf("%s%s = %s;", idt, glslExpr(&s.Exprs[0]), glslExpr(&s.Exprs[1])))
case If:
lines = append(lines, fmt.Sprintf("%sif (%s) {", idt, glslExpr(&s.Exprs[0])))
lines = append(lines, p.glslBlock(&s.Blocks[0], f, level+1, localVarIndex)...)
lines = append(lines, p.glslBlock(&s.Blocks[0], level+1, localVarIndex)...)
if len(s.Blocks) > 1 {
lines = append(lines, fmt.Sprintf("%s} else {", idt))
lines = append(lines, p.glslBlock(&s.Blocks[1], f, level+1, localVarIndex)...)
lines = append(lines, p.glslBlock(&s.Blocks[1], level+1, localVarIndex)...)
}
lines = append(lines, fmt.Sprintf("%s}", idt))
case For:
@ -225,7 +244,7 @@ func (p *Program) glslBlock(b *Block, f *Func, level int, localVarIndex int) []s
op = fmt.Sprintf("?(unexpected op: %s)", string(s.ForOp))
}
lines = append(lines, fmt.Sprintf("%sfor (int l%d = %d; l%d %s %d; %s) {", idt, v, s.ForInit, v, op, s.ForEnd, delta))
lines = append(lines, p.glslBlock(&s.Blocks[0], f, level+1, localVarIndex)...)
lines = append(lines, p.glslBlock(&s.Blocks[0], level+1, localVarIndex)...)
lines = append(lines, fmt.Sprintf("%s}", idt))
case Continue:
lines = append(lines, idt+"continue;")
@ -246,5 +265,3 @@ func (p *Program) glslBlock(b *Block, f *Func, level int, localVarIndex int) []s
return lines
}
// TODO: Distinguish regular functions, vertex functions and fragment functions. e.g., Treat gl_Position correctly.

View File

@ -521,6 +521,51 @@ varying vec3 V0;`,
for (int l3 = 0; l3 < 100; l3++) {
l2 = l0;
}
}`,
},
{
Name: "VertexFunc",
Program: Program{
Uniforms: []Type{
{Main: Float},
},
Attributes: []Type{
{Main: Vec4},
{Main: Float},
{Main: Vec2},
},
Varyings: []Type{
{Main: Float},
{Main: Vec2},
},
VertexFunc: VertexFunc{
Block: block(
nil,
assignStmt(
varNameExpr(Local, 5),
varNameExpr(Local, 0),
),
assignStmt(
varNameExpr(Local, 3),
varNameExpr(Local, 1),
),
assignStmt(
varNameExpr(Local, 4),
varNameExpr(Local, 2),
),
),
},
},
Glsl: `uniform float U0;
attribute vec4 A0;
attribute float A1;
attribute vec2 A2;
varying float V0;
varying vec2 V1;
void main(void) {
gl_Position = A0;
V0 = A1;
V1 = A2;
}`,
},
}

View File

@ -15,12 +15,12 @@
package shaderir
type Program struct {
Uniforms []Type
Attributes []Type
Varyings []Type
Funcs []Func
VertexEntry string
FragmentEntry string
Uniforms []Type
Attributes []Type
Varyings []Type
Funcs []Func
VertexFunc VertexFunc
FragmentFunc FragmentFunc
structNames map[string]string
structTypes []Type
@ -37,6 +37,21 @@ type Func struct {
Block Block
}
// VertexFunc takes pseudo params, and the number if len(attributes) + len(varyings) + 1.
// If 0 <= index < len(attributes), the params are in-params and treated as attribute variables.
// If len(attributes) <= index < len(attributes) + len(varyings), the params are out-params and treated as varying
// variables.
// The last param represents the position in vec4 (gl_Position in GLSL).
type VertexFunc struct {
Block Block
}
// FragmentFunc takes pseudo in-params, and the number is len(varyings) + 1.
// The last param represents the coordinate of the fragment (gl_FragCoord in GLSL)
type FragmentFunc struct {
Block Block
}
type Block struct {
LocalVars []Type
Stmts []Stmt
@ -100,8 +115,6 @@ type VariableType int
const (
Uniform VariableType = iota
Attribute
Varying
Local
)