From dc6a153c654267de62e3d9ec9defa8eb8125c710 Mon Sep 17 00:00:00 2001 From: Hajime Hoshi Date: Wed, 31 Dec 2014 16:12:13 +0900 Subject: [PATCH] Add opengl.Context.NewShader --- graphicscontext.go | 4 +- image.go | 6 +- internal/graphics/framebuffer.go | 4 +- .../graphics/internal/shader/drawtexture.go | 5 +- internal/graphics/internal/shader/program.go | 25 ++++--- internal/graphics/internal/shader/shader.go | 34 ++------- internal/opengl/context.go | 71 +++++++++++++++++-- 7 files changed, 94 insertions(+), 55 deletions(-) diff --git a/graphicscontext.go b/graphicscontext.go index 816419b3e..bf4b827f1 100644 --- a/graphicscontext.go +++ b/graphicscontext.go @@ -35,6 +35,7 @@ func newGraphicsContext(c *opengl.Context, screenWidth, screenHeight, screenScal } gc := &graphicsContext{ + glContext: c, defaultR: &innerImage{f, nil}, screen: screen, screenScale: screenScale, @@ -43,6 +44,7 @@ func newGraphicsContext(c *opengl.Context, screenWidth, screenHeight, screenScal } type graphicsContext struct { + glContext *opengl.Context screen *innerImage defaultR *innerImage screenScale int @@ -70,7 +72,7 @@ func (c *graphicsContext) postUpdate() error { options := &DrawImageOptions{ GeoM: ScaleGeo(scale, scale), } - if err := c.defaultR.drawImage(c.screen, options); err != nil { + if err := c.defaultR.drawImage(c.glContext, c.screen, options); err != nil { return err } return nil diff --git a/image.go b/image.go index fdc870a4d..13b422e92 100644 --- a/image.go +++ b/image.go @@ -48,7 +48,7 @@ func (i *innerImage) Fill(clr color.Color) error { return i.framebuffer.Fill(r, g, b, a) } -func (i *innerImage) drawImage(img *innerImage, options *DrawImageOptions) error { +func (i *innerImage) drawImage(c *opengl.Context, img *innerImage, options *DrawImageOptions) error { if options == nil { options = &DrawImageOptions{} } @@ -66,7 +66,7 @@ func (i *innerImage) drawImage(img *innerImage, options *DrawImageOptions) error clr := options.ColorM w, h := img.size() quads := &textureQuads{parts, w, h} - return i.framebuffer.DrawTexture(img.texture, quads, geo, clr) + return i.framebuffer.DrawTexture(c, img.texture, quads, geo, clr) } func u(x float64, width int) float32 { @@ -152,7 +152,7 @@ func (i *Image) DrawImage(image *Image, options *DrawImageOptions) (err error) { func (i *Image) drawImage(image *innerImage, option *DrawImageOptions) (err error) { i.pixels = nil i.syncer.Sync(func() { - err = i.inner.drawImage(image, option) + err = i.inner.drawImage(currentUI.glContext, image, option) }) return } diff --git a/internal/graphics/framebuffer.go b/internal/graphics/framebuffer.go index be661c66c..6dbf366b2 100644 --- a/internal/graphics/framebuffer.go +++ b/internal/graphics/framebuffer.go @@ -107,11 +107,11 @@ func (f *Framebuffer) Fill(r, g, b, a float64) error { return f.framebuffer.Fill(r, g, b, a) } -func (f *Framebuffer) DrawTexture(t *Texture, quads TextureQuads, geo, clr Matrix) error { +func (f *Framebuffer) DrawTexture(c *opengl.Context, t *Texture, quads TextureQuads, geo, clr Matrix) error { if err := f.setAsViewport(); err != nil { return err } projectionMatrix := f.projectionMatrix() // TODO: Define texture.Draw() - return shader.DrawTexture(gl.Texture(t.native), projectionMatrix, quads, geo, clr) + return shader.DrawTexture(c, gl.Texture(t.native), projectionMatrix, quads, geo, clr) } diff --git a/internal/graphics/internal/shader/drawtexture.go b/internal/graphics/internal/shader/drawtexture.go index 6ea834597..ca59783e5 100644 --- a/internal/graphics/internal/shader/drawtexture.go +++ b/internal/graphics/internal/shader/drawtexture.go @@ -16,6 +16,7 @@ package shader import ( "github.com/go-gl/gl" + "github.com/hajimehoshi/ebiten/internal/opengl" ) func glMatrix(m [4][4]float64) [16]float32 { @@ -46,11 +47,11 @@ const size = 10000 const uint16Size = 2 const float32Size = 4 -func DrawTexture(native gl.Texture, projectionMatrix [4][4]float64, quads TextureQuads, geo Matrix, color Matrix) error { +func DrawTexture(c *opengl.Context, native gl.Texture, projectionMatrix [4][4]float64, quads TextureQuads, geo Matrix, color Matrix) error { // TODO: Check len(quads) and gl.MAX_ELEMENTS_INDICES? const stride = 4 * 4 if !initialized { - if err := initialize(); err != nil { + if err := initialize(c); err != nil { return err } diff --git a/internal/graphics/internal/shader/program.go b/internal/graphics/internal/shader/program.go index 33ebff3bc..b7b3931fb 100644 --- a/internal/graphics/internal/shader/program.go +++ b/internal/graphics/internal/shader/program.go @@ -17,6 +17,7 @@ package shader import ( "errors" "github.com/go-gl/gl" + "github.com/hajimehoshi/ebiten/internal/opengl" ) type program struct { @@ -35,7 +36,7 @@ func (p *program) create() error { } for _, shaderId := range p.shaderIds { - p.native.AttachShader(shaders[shaderId].native) + p.native.AttachShader(gl.Shader(shaders[shaderId].native)) } p.native.Link() if p.native.Get(gl.LINK_STATUS) == gl.FALSE { @@ -44,17 +45,19 @@ func (p *program) create() error { return nil } -func initialize() error { - for _, shader := range shaders { - if err := shader.compile(); err != nil { - return err - } +func initialize(c *opengl.Context) error { + var err error + shaders[shaderVertex].native, err = c.NewShader(c.VertexShader, shaders[shaderVertex].source) + if err != nil { + return err } - defer func() { - for _, shader := range shaders { - shader.delete() - } - }() + defer shaders[shaderVertex].delete() + + shaders[shaderColorMatrix].native, err = c.NewShader(c.FragmentShader, shaders[shaderColorMatrix].source) + if err != nil { + return err + } + defer shaders[shaderColorMatrix].delete() return programColorMatrix.create() } diff --git a/internal/graphics/internal/shader/shader.go b/internal/graphics/internal/shader/shader.go index 8c2d86b56..797f6b27f 100644 --- a/internal/graphics/internal/shader/shader.go +++ b/internal/graphics/internal/shader/shader.go @@ -15,15 +15,13 @@ package shader import ( - "errors" - "fmt" "github.com/go-gl/gl" + "github.com/hajimehoshi/ebiten/internal/opengl" ) type shader struct { - native gl.Shader - shaderType gl.GLenum - source string + native opengl.Shader + source string } type shaderId int @@ -35,7 +33,6 @@ const ( var shaders = map[shaderId]*shader{ shaderVertex: { - shaderType: gl.VERTEX_SHADER, source: ` uniform mat4 projection_matrix; uniform mat4 modelview_matrix; @@ -50,7 +47,6 @@ void main(void) { `, }, shaderColorMatrix: { - shaderType: gl.FRAGMENT_SHADER, source: ` uniform sampler2D texture; uniform mat4 color_matrix; @@ -76,28 +72,6 @@ void main(void) { }, } -func (s *shader) compile() error { - s.native = gl.CreateShader(s.shaderType) - if s.native == 0 { - return errors.New("glCreateShader failed") - } - - s.native.Source(s.source) - s.native.Compile() - - if s.native.Get(gl.COMPILE_STATUS) == gl.FALSE { - return errors.New(fmt.Sprintf("shader compile failed: %s", s.shaderLog())) - } - return nil -} - -func (s *shader) shaderLog() string { - if s.native.Get(gl.INFO_LOG_LENGTH) == 0 { - return "" - } - return s.native.GetInfoLog() -} - func (s *shader) delete() { - s.native.Delete() + gl.Shader(s.native).Delete() } diff --git a/internal/opengl/context.go b/internal/opengl/context.go index 6c86254b5..5b4bc4659 100644 --- a/internal/opengl/context.go +++ b/internal/opengl/context.go @@ -27,10 +27,12 @@ const ( filterLinear = gl.LINEAR ) -type Context struct { - Nearest Filter - Linear Filter -} +type ShaderType int + +const ( + shaderTypeVertex ShaderType = gl.VERTEX_SHADER + shaderTypeFragment = gl.FRAGMENT_SHADER +) type Texture gl.Texture @@ -76,10 +78,31 @@ func (f Framebuffer) Delete() { gl.Framebuffer(f).Delete() } +type Shader gl.Shader + +type Program gl.Program + +func (p Program) GetAttribLocation(name string) int { + return int(p.GetAttribLocation(name)) +} + +func (p Program) GetUniformLocation(name string) int { + return int(p.GetUniformLocation(name)) +} + +type Context struct { + Nearest Filter + Linear Filter + VertexShader ShaderType + FragmentShader ShaderType +} + func NewContext() *Context { c := &Context{ - Nearest: filterNearest, - Linear: filterLinear, + Nearest: filterNearest, + Linear: filterLinear, + VertexShader: shaderTypeVertex, + FragmentShader: shaderTypeFragment, } c.init() return c @@ -121,3 +144,39 @@ func (c *Context) NewFramebuffer(texture Texture) (Framebuffer, error) { return Framebuffer(f), nil } + +func (c *Context) NewShader(shaderType ShaderType, source string) (Shader, error) { + s := gl.CreateShader(gl.GLenum(shaderType)) + if s == 0 { + println(gl.GetError()) + return 0, errors.New("glCreateShader failed") + } + + s.Source(source) + s.Compile() + + if s.Get(gl.COMPILE_STATUS) == gl.FALSE { + log := "" + if s.Get(gl.INFO_LOG_LENGTH) != 0 { + log = s.GetInfoLog() + } + return 0, errors.New(fmt.Sprintf("shader compile failed: %s", log)) + } + return Shader(s), nil +} + +func (c *Context) NewProgram() (Program, error) { + p := gl.CreateProgram() + if p == 0 { + return 0, errors.New("glCreateProgram failed") + } + + /*for _, shaderId := range p.shaderIds { + p.native.AttachShader(shaders[shaderId].native) + } + p.native.Link() + if p.native.Get(gl.LINK_STATUS) == gl.FALSE { + return errors.New("program error") + }*/ + return Program(p), nil +}