This commit is contained in:
Zyko 2024-04-09 01:00:26 +02:00
parent 4536fadebe
commit c7eeae7189
10 changed files with 44 additions and 16 deletions

View File

@ -15,11 +15,13 @@
package main package main
import ( import (
"fmt"
"image" "image"
_ "image/jpeg" _ "image/jpeg"
"log" "log"
"github.com/hajimehoshi/ebiten/v2" "github.com/hajimehoshi/ebiten/v2"
"github.com/hajimehoshi/ebiten/v2/ebitenutil"
) )
const ( const (
@ -71,11 +73,9 @@ func init() {
} }
type Game struct { type Game struct {
count int
} }
func (g *Game) Update() error { func (g *Game) Update() error {
g.count++
return nil return nil
} }
@ -114,6 +114,8 @@ func (g *Game) Draw(screen *ebiten.Image) {
opts.GeoM.Reset() opts.GeoM.Reset()
opts.GeoM.Translate(dstSize, dstSize) opts.GeoM.Translate(dstSize, dstSize)
screen.DrawImage(dsts[3], opts) screen.DrawImage(dsts[3], opts)
ebitenutil.DebugPrint(screen, fmt.Sprintf("FPS: %.2f", ebiten.ActualFPS()))
} }
func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) { func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) {
@ -122,9 +124,10 @@ func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) {
func main() { func main() {
ebiten.SetWindowSize(screenWidth, screenHeight) ebiten.SetWindowSize(screenWidth, screenHeight)
ebiten.SetVsyncEnabled(false)
ebiten.SetWindowTitle("MRT (Ebitengine Demo)") ebiten.SetWindowTitle("MRT (Ebitengine Demo)")
if err := ebiten.RunGameWithOptions(&Game{}, &ebiten.RunGameOptions{ if err := ebiten.RunGameWithOptions(&Game{}, &ebiten.RunGameOptions{
GraphicsLibrary: ebiten.GraphicsLibraryDirectX, GraphicsLibrary: ebiten.GraphicsLibraryOpenGL,
}); err != nil { }); err != nil {
log.Fatal(err) log.Fatal(err)
} }

View File

@ -396,7 +396,7 @@ func (c *context) newShader(shaderType uint32, source string) (shader, error) {
return shader(s), nil return shader(s), nil
} }
func (c *context) newProgram(shaders []shader, attributes []string) (program, error) { func (c *context) newProgram(shaders []shader, attributes, fragData []string) (program, error) {
p := c.ctx.CreateProgram() p := c.ctx.CreateProgram()
if p == 0 { if p == 0 {
return 0, errors.New("opengl: glCreateProgram failed") return 0, errors.New("opengl: glCreateProgram failed")
@ -410,6 +410,10 @@ func (c *context) newProgram(shaders []shader, attributes []string) (program, er
c.ctx.BindAttribLocation(p, uint32(i), name) c.ctx.BindAttribLocation(p, uint32(i), name)
} }
for i, name := range fragData {
c.ctx.BindFragDataLocation(p, uint32(i), name)
}
c.ctx.LinkProgram(p) c.ctx.LinkProgram(p)
if c.ctx.GetProgrami(p, gl.LINK_STATUS) == gl.FALSE { if c.ctx.GetProgrami(p, gl.LINK_STATUS) == gl.FALSE {
info := c.ctx.GetProgramInfoLog(p) info := c.ctx.GetProgramInfoLog(p)

View File

@ -61,6 +61,14 @@ func (d *DebugContext) BindBuffer(arg0 uint32, arg1 uint32) {
} }
} }
func (d *DebugContext) BindFragDataLocation(arg0 uint32, arg1 uint32, arg2 string) {
d.Context.BindFragDataLocation(arg0, arg1, arg2)
fmt.Fprintln(os.Stderr, "BindFragDataLocation")
if e := d.Context.GetError(); e != NO_ERROR {
panic(fmt.Sprintf("gl: GetError() returned %d at BindFragDataLocation", e))
}
}
func (d *DebugContext) BindFramebuffer(arg0 uint32, arg1 uint32) { func (d *DebugContext) BindFramebuffer(arg0 uint32, arg1 uint32) {
d.Context.BindFramebuffer(arg0, arg1) d.Context.BindFramebuffer(arg0, arg1)
fmt.Fprintln(os.Stderr, "BindFramebuffer") fmt.Fprintln(os.Stderr, "BindFramebuffer")

View File

@ -28,6 +28,7 @@ type defaultContext struct {
gpAttachShader uintptr gpAttachShader uintptr
gpBindAttribLocation uintptr gpBindAttribLocation uintptr
gpBindBuffer uintptr gpBindBuffer uintptr
gpBindFragDataLocation uintptr
gpBindFramebuffer uintptr gpBindFramebuffer uintptr
gpBindRenderbuffer uintptr gpBindRenderbuffer uintptr
gpBindTexture uintptr gpBindTexture uintptr
@ -140,6 +141,12 @@ func (c *defaultContext) BindBuffer(target uint32, buffer uint32) {
purego.SyscallN(c.gpBindBuffer, uintptr(target), uintptr(buffer)) purego.SyscallN(c.gpBindBuffer, uintptr(target), uintptr(buffer))
} }
func (c *defaultContext) BindFragDataLocation(program uint32, index uint32, name string) {
cname, free := cStr(name)
defer free()
purego.SyscallN(c.gpBindFragDataLocation, uintptr(program), uintptr(index), uintptr(unsafe.Pointer(cname)))
}
func (c *defaultContext) BindFramebuffer(target uint32, framebuffer uint32) { func (c *defaultContext) BindFramebuffer(target uint32, framebuffer uint32) {
purego.SyscallN(c.gpBindFramebuffer, uintptr(target), uintptr(framebuffer)) purego.SyscallN(c.gpBindFramebuffer, uintptr(target), uintptr(framebuffer))
} }
@ -483,6 +490,7 @@ func (c *defaultContext) LoadFunctions() error {
c.gpAttachShader = g.get("glAttachShader") c.gpAttachShader = g.get("glAttachShader")
c.gpBindAttribLocation = g.get("glBindAttribLocation") c.gpBindAttribLocation = g.get("glBindAttribLocation")
c.gpBindBuffer = g.get("glBindBuffer") c.gpBindBuffer = g.get("glBindBuffer")
c.gpBindFragDataLocation = g.get("glBindFragDataLocation")
c.gpBindFramebuffer = g.get("glBindFramebuffer") c.gpBindFramebuffer = g.get("glBindFramebuffer")
c.gpBindRenderbuffer = g.get("glBindRenderbuffer") c.gpBindRenderbuffer = g.get("glBindRenderbuffer")
c.gpBindTexture = g.get("glBindTexture") c.gpBindTexture = g.get("glBindTexture")

View File

@ -31,6 +31,7 @@ type Context interface {
AttachShader(program uint32, shader uint32) AttachShader(program uint32, shader uint32)
BindAttribLocation(program uint32, index uint32, name string) BindAttribLocation(program uint32, index uint32, name string)
BindBuffer(target uint32, buffer uint32) BindBuffer(target uint32, buffer uint32)
BindFragDataLocation(program uint32, index uint32, name string)
BindFramebuffer(target uint32, framebuffer uint32) BindFramebuffer(target uint32, framebuffer uint32)
BindRenderbuffer(target uint32, renderbuffer uint32) BindRenderbuffer(target uint32, renderbuffer uint32)
BindTexture(target uint32, texture uint32) BindTexture(target uint32, texture uint32)

View File

@ -265,7 +265,7 @@ func (g *Graphics) colorBufferVariableName(idx int) string {
if g.colorBufferVariableNameCache == nil { if g.colorBufferVariableNameCache == nil {
g.colorBufferVariableNameCache = map[int]string{} g.colorBufferVariableNameCache = map[int]string{}
} }
name := fmt.Sprintf("gl_FragData[%d]", idx) name := fmt.Sprintf("fragColor%d", idx)
g.colorBufferVariableNameCache[idx] = name g.colorBufferVariableNameCache[idx] = name
return name return name
} }

View File

@ -69,7 +69,11 @@ func (s *Shader) compile() error {
} }
defer s.graphics.context.ctx.DeleteShader(uint32(fs)) defer s.graphics.context.ctx.DeleteShader(uint32(fs))
p, err := s.graphics.context.newProgram([]shader{vs, fs}, theArrayBufferLayout.names()) colorNames := make([]string, s.ir.ColorsOutCount)
for i := range colorNames {
colorNames[i] = s.graphics.colorBufferVariableName(i)
}
p, err := s.graphics.context.newProgram([]shader{vs, fs}, theArrayBufferLayout.names(), colorNames)
if err != nil { if err != nil {
return err return err
} }

View File

@ -822,7 +822,7 @@ func (cs *compileState) parseFunc(block *block, d *ast.FuncDecl) (function, bool
return function{}, false return function{}, false
} }
// The first out-param is treated as gl_FragColor in GLSL. // The first out-param is treated as fragColor0 in GLSL.
for i := range outParams { for i := range outParams {
if outParams[i].typ.Main != shaderir.Vec4 { if outParams[i].typ.Main != shaderir.Vec4 {
cs.addError(d.Pos(), "fragment entry point must only have vec4 return values for colors") cs.addError(d.Pos(), "fragment entry point must only have vec4 return values for colors")

View File

@ -86,8 +86,7 @@ precision highp int;
#define lowp #define lowp
#define mediump #define mediump
#define highp #define highp
#endif #endif`
`
if version == GLSLVersionDefault { if version == GLSLVersionDefault {
prelude += "\n\n" + utilFunctions prelude += "\n\n" + utilFunctions
} }
@ -230,6 +229,9 @@ func Compile(p *shaderir.Program, version GLSLVersion) (vertexShader, fragmentSh
fslines = append(fslines, fmt.Sprintf("in %s;", c.varDecl(p, &t, fmt.Sprintf("V%d", i)))) fslines = append(fslines, fmt.Sprintf("in %s;", c.varDecl(p, &t, fmt.Sprintf("V%d", i))))
} }
} }
for i := 0; i < p.ColorsOutCount; i++ {
fslines = append(fslines, fmt.Sprintf("out vec4 fragColor%d;", i))
}
var funcs []*shaderir.Func var funcs []*shaderir.Func
if p.VertexFunc.Block != nil { if p.VertexFunc.Block != nil {
@ -291,6 +293,8 @@ func Compile(p *shaderir.Program, version GLSLVersion) (vertexShader, fragmentSh
vs = strings.TrimSpace(vs) + "\n" vs = strings.TrimSpace(vs) + "\n"
fs = strings.TrimSpace(fs) + "\n" fs = strings.TrimSpace(fs) + "\n"
fmt.Println("FS:", fs)
return vs, fs return vs, fs
} }
@ -419,7 +423,7 @@ func (c *compileContext) localVariableName(p *shaderir.Program, topBlock *shader
case idx < nv+1: case idx < nv+1:
return fmt.Sprintf("V%d", idx-1) return fmt.Sprintf("V%d", idx-1)
default: default:
return fmt.Sprintf("gl_FragData[%d]", idx-(nv+1)) return fmt.Sprintf("fragColor%d", idx-(nv+1))
} }
default: default:
return fmt.Sprintf("l%d", idx) return fmt.Sprintf("l%d", idx)

View File

@ -607,11 +607,6 @@ func adjustProgram(p *shaderir.Program) *shaderir.Program {
copy(newP.Funcs, p.Funcs) copy(newP.Funcs, p.Funcs)
// Create a new function whose body is the same is the fragment shader's entry point. // Create a new function whose body is the same is the fragment shader's entry point.
// The entry point will call this.
// This indirect call is needed for these issues:
// - Assignment to gl_FragColor doesn't work (#2245)
// - There are some odd compilers that don't work with early returns and gl_FragColor (#2247)
// Determine a unique index of the new function. // Determine a unique index of the new function.
var funcIdx int var funcIdx int
for _, f := range newP.Funcs { for _, f := range newP.Funcs {
@ -659,7 +654,8 @@ func adjustProgram(p *shaderir.Program) *shaderir.Program {
// Replace the entry point with just calling the new function. // Replace the entry point with just calling the new function.
stmts := []shaderir.Stmt{ stmts := []shaderir.Stmt{
{ {
// Return: This will be replaced with assignment to gl_FragColor. // Return: This will be replaced with a call to the new function.
// Then the output structure containing colors will be returned.
Type: shaderir.Return, Type: shaderir.Return,
Exprs: []shaderir.Expr{ Exprs: []shaderir.Expr{
// The function call // The function call