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

View File

@ -396,7 +396,7 @@ func (c *context) newShader(shaderType uint32, source string) (shader, error) {
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()
if p == 0 {
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)
}
for i, name := range fragData {
c.ctx.BindFragDataLocation(p, uint32(i), name)
}
c.ctx.LinkProgram(p)
if c.ctx.GetProgrami(p, gl.LINK_STATUS) == gl.FALSE {
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) {
d.Context.BindFramebuffer(arg0, arg1)
fmt.Fprintln(os.Stderr, "BindFramebuffer")

View File

@ -28,6 +28,7 @@ type defaultContext struct {
gpAttachShader uintptr
gpBindAttribLocation uintptr
gpBindBuffer uintptr
gpBindFragDataLocation uintptr
gpBindFramebuffer uintptr
gpBindRenderbuffer uintptr
gpBindTexture uintptr
@ -140,6 +141,12 @@ func (c *defaultContext) BindBuffer(target uint32, buffer uint32) {
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) {
purego.SyscallN(c.gpBindFramebuffer, uintptr(target), uintptr(framebuffer))
}
@ -483,6 +490,7 @@ func (c *defaultContext) LoadFunctions() error {
c.gpAttachShader = g.get("glAttachShader")
c.gpBindAttribLocation = g.get("glBindAttribLocation")
c.gpBindBuffer = g.get("glBindBuffer")
c.gpBindFragDataLocation = g.get("glBindFragDataLocation")
c.gpBindFramebuffer = g.get("glBindFramebuffer")
c.gpBindRenderbuffer = g.get("glBindRenderbuffer")
c.gpBindTexture = g.get("glBindTexture")

View File

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

View File

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

View File

@ -69,7 +69,11 @@ func (s *Shader) compile() error {
}
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 {
return err
}

View File

@ -822,7 +822,7 @@ func (cs *compileState) parseFunc(block *block, d *ast.FuncDecl) (function, bool
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 {
if outParams[i].typ.Main != shaderir.Vec4 {
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 mediump
#define highp
#endif
`
#endif`
if version == GLSLVersionDefault {
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))))
}
}
for i := 0; i < p.ColorsOutCount; i++ {
fslines = append(fslines, fmt.Sprintf("out vec4 fragColor%d;", i))
}
var funcs []*shaderir.Func
if p.VertexFunc.Block != nil {
@ -291,6 +293,8 @@ func Compile(p *shaderir.Program, version GLSLVersion) (vertexShader, fragmentSh
vs = strings.TrimSpace(vs) + "\n"
fs = strings.TrimSpace(fs) + "\n"
fmt.Println("FS:", fs)
return vs, fs
}
@ -419,7 +423,7 @@ func (c *compileContext) localVariableName(p *shaderir.Program, topBlock *shader
case idx < nv+1:
return fmt.Sprintf("V%d", idx-1)
default:
return fmt.Sprintf("gl_FragData[%d]", idx-(nv+1))
return fmt.Sprintf("fragColor%d", idx-(nv+1))
}
default:
return fmt.Sprintf("l%d", idx)

View File

@ -607,11 +607,6 @@ func adjustProgram(p *shaderir.Program) *shaderir.Program {
copy(newP.Funcs, p.Funcs)
// 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.
var funcIdx int
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.
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,
Exprs: []shaderir.Expr{
// The function call