mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-24 18:58:54 +01:00
graphicsdriver/opengl: Enable to bind multiple textures (in theory)
This commit is contained in:
parent
733c463e26
commit
7f2092f964
@ -198,6 +198,13 @@ func (c *context) framebufferPixels(f *framebuffer, width, height int) ([]byte,
|
|||||||
return pixels, nil
|
return pixels, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *context) activeTexture(idx int) {
|
||||||
|
_ = c.t.Call(func() error {
|
||||||
|
gl.ActiveTexture(gl.TEXTURE0 + uint32(idx))
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func (c *context) bindTextureImpl(t textureNative) {
|
func (c *context) bindTextureImpl(t textureNative) {
|
||||||
_ = c.t.Call(func() error {
|
_ = c.t.Call(func() error {
|
||||||
gl.BindTexture(gl.TEXTURE_2D, uint32(t))
|
gl.BindTexture(gl.TEXTURE_2D, uint32(t))
|
||||||
|
@ -112,6 +112,8 @@ var (
|
|||||||
unsignedByte js.Value
|
unsignedByte js.Value
|
||||||
unsignedShort js.Value
|
unsignedShort js.Value
|
||||||
|
|
||||||
|
texture0 int
|
||||||
|
|
||||||
isWebGL2Available bool
|
isWebGL2Available bool
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -154,6 +156,7 @@ func init() {
|
|||||||
nearest = contextPrototype.Get("NEAREST")
|
nearest = contextPrototype.Get("NEAREST")
|
||||||
noError = contextPrototype.Get("NO_ERROR")
|
noError = contextPrototype.Get("NO_ERROR")
|
||||||
rgba = contextPrototype.Get("RGBA")
|
rgba = contextPrototype.Get("RGBA")
|
||||||
|
texture0 = contextPrototype.Get("TEXTURE0").Int()
|
||||||
texture2d = contextPrototype.Get("TEXTURE_2D")
|
texture2d = contextPrototype.Get("TEXTURE_2D")
|
||||||
textureMagFilter = contextPrototype.Get("TEXTURE_MAG_FILTER")
|
textureMagFilter = contextPrototype.Get("TEXTURE_MAG_FILTER")
|
||||||
textureMinFilter = contextPrototype.Get("TEXTURE_MIN_FILTER")
|
textureMinFilter = contextPrototype.Get("TEXTURE_MIN_FILTER")
|
||||||
@ -279,6 +282,12 @@ func (c *context) framebufferPixels(f *framebuffer, width, height int) ([]byte,
|
|||||||
return jsutil.Uint8ArrayToSlice(p), nil
|
return jsutil.Uint8ArrayToSlice(p), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *context) activeTexture(idx int) {
|
||||||
|
c.ensureGL()
|
||||||
|
gl := c.gl
|
||||||
|
gl.Call("activeTexture", texture0+idx)
|
||||||
|
}
|
||||||
|
|
||||||
func (c *context) bindTextureImpl(t textureNative) {
|
func (c *context) bindTextureImpl(t textureNative) {
|
||||||
c.ensureGL()
|
c.ensureGL()
|
||||||
gl := c.gl
|
gl := c.gl
|
||||||
|
@ -156,6 +156,11 @@ func (c *context) framebufferPixels(f *framebuffer, width, height int) ([]byte,
|
|||||||
return pixels, nil
|
return pixels, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *context) activeTexture(idx int) {
|
||||||
|
gl := c.gl
|
||||||
|
gl.ActiveTexture(mgl.Enum(mgl.TEXTURE0 + idx))
|
||||||
|
}
|
||||||
|
|
||||||
func (c *context) bindTextureImpl(t textureNative) {
|
func (c *context) bindTextureImpl(t textureNative) {
|
||||||
gl := c.gl
|
gl := c.gl
|
||||||
gl.BindTexture(mgl.TEXTURE_2D, mgl.Texture(t))
|
gl.BindTexture(mgl.TEXTURE_2D, mgl.Texture(t))
|
||||||
|
@ -49,6 +49,7 @@ const (
|
|||||||
NO_ERROR = 0
|
NO_ERROR = 0
|
||||||
READ_WRITE = 0x88BA
|
READ_WRITE = 0x88BA
|
||||||
RGBA = 0x1908
|
RGBA = 0x1908
|
||||||
|
TEXTURE0 = 0x84C0
|
||||||
TEXTURE_2D = 0x0DE1
|
TEXTURE_2D = 0x0DE1
|
||||||
TEXTURE_MAG_FILTER = 0x2800
|
TEXTURE_MAG_FILTER = 0x2800
|
||||||
TEXTURE_MIN_FILTER = 0x2801
|
TEXTURE_MIN_FILTER = 0x2801
|
||||||
|
@ -95,7 +95,8 @@ package gl
|
|||||||
// typedef void (APIENTRY *GLDEBUGPROCAMD)(GLuint id,GLenum category,GLenum severity,GLsizei length,const GLchar *message,void *userParam);
|
// typedef void (APIENTRY *GLDEBUGPROCAMD)(GLuint id,GLenum category,GLenum severity,GLsizei length,const GLchar *message,void *userParam);
|
||||||
// typedef unsigned short GLhalfNV;
|
// typedef unsigned short GLhalfNV;
|
||||||
// typedef GLintptr GLvdpauSurfaceNV;
|
// typedef GLintptr GLvdpauSurfaceNV;
|
||||||
// typedef void (APIENTRY *GLVULKANPROCNV)(void);
|
//
|
||||||
|
// typedef void (APIENTRYP GPACTIVETEXTURE)(GLenum texture);
|
||||||
// typedef void (APIENTRYP GPATTACHSHADER)(GLuint program, GLuint shader);
|
// typedef void (APIENTRYP GPATTACHSHADER)(GLuint program, GLuint shader);
|
||||||
// typedef void (APIENTRYP GPBINDATTRIBLOCATION)(GLuint program, GLuint index, const GLchar * name);
|
// typedef void (APIENTRYP GPBINDATTRIBLOCATION)(GLuint program, GLuint index, const GLchar * name);
|
||||||
// typedef void (APIENTRYP GPBINDBUFFER)(GLenum target, GLuint buffer);
|
// typedef void (APIENTRYP GPBINDBUFFER)(GLenum target, GLuint buffer);
|
||||||
@ -159,6 +160,9 @@ package gl
|
|||||||
// typedef void (APIENTRYP GPVERTEXATTRIBPOINTER)(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const uintptr_t pointer);
|
// typedef void (APIENTRYP GPVERTEXATTRIBPOINTER)(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const uintptr_t pointer);
|
||||||
// typedef void (APIENTRYP GPVIEWPORT)(GLint x, GLint y, GLsizei width, GLsizei height);
|
// typedef void (APIENTRYP GPVIEWPORT)(GLint x, GLint y, GLsizei width, GLsizei height);
|
||||||
//
|
//
|
||||||
|
// static void glowActiveTexture(GPACTIVETEXTURE fnptr, GLenum texture) {
|
||||||
|
// (*fnptr)(texture);
|
||||||
|
// }
|
||||||
// static void glowAttachShader(GPATTACHSHADER fnptr, GLuint program, GLuint shader) {
|
// static void glowAttachShader(GPATTACHSHADER fnptr, GLuint program, GLuint shader) {
|
||||||
// (*fnptr)(program, shader);
|
// (*fnptr)(program, shader);
|
||||||
// }
|
// }
|
||||||
@ -353,6 +357,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
gpActiveTexture C.GPACTIVETEXTURE
|
||||||
gpAttachShader C.GPATTACHSHADER
|
gpAttachShader C.GPATTACHSHADER
|
||||||
gpBindAttribLocation C.GPBINDATTRIBLOCATION
|
gpBindAttribLocation C.GPBINDATTRIBLOCATION
|
||||||
gpBindBuffer C.GPBINDBUFFER
|
gpBindBuffer C.GPBINDBUFFER
|
||||||
@ -424,6 +429,10 @@ func boolToInt(b bool) int {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ActiveTexture(texture uint32) {
|
||||||
|
C.glowActiveTexture(gpActiveTexture, (C.GLenum)(texture))
|
||||||
|
}
|
||||||
|
|
||||||
func AttachShader(program uint32, shader uint32) {
|
func AttachShader(program uint32, shader uint32) {
|
||||||
C.glowAttachShader(gpAttachShader, (C.GLuint)(program), (C.GLuint)(shader))
|
C.glowAttachShader(gpAttachShader, (C.GLuint)(program), (C.GLuint)(shader))
|
||||||
}
|
}
|
||||||
@ -675,6 +684,10 @@ func Viewport(x int32, y int32, width int32, height int32) {
|
|||||||
// InitWithProcAddrFunc intializes the package using the specified OpenGL
|
// InitWithProcAddrFunc intializes the package using the specified OpenGL
|
||||||
// function pointer loading function. For more cases Init should be used
|
// function pointer loading function. For more cases Init should be used
|
||||||
func InitWithProcAddrFunc(getProcAddr func(name string) unsafe.Pointer) error {
|
func InitWithProcAddrFunc(getProcAddr func(name string) unsafe.Pointer) error {
|
||||||
|
gpActiveTexture = (C.GPACTIVETEXTURE)(getProcAddr("glActiveTexture"))
|
||||||
|
if gpActiveTexture == nil {
|
||||||
|
return errors.New("glActiveTexture")
|
||||||
|
}
|
||||||
gpAttachShader = (C.GPATTACHSHADER)(getProcAddr("glAttachShader"))
|
gpAttachShader = (C.GPATTACHSHADER)(getProcAddr("glAttachShader"))
|
||||||
if gpAttachShader == nil {
|
if gpAttachShader == nil {
|
||||||
return errors.New("glAttachShader")
|
return errors.New("glAttachShader")
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
gpActiveTexture uintptr
|
||||||
gpAttachShader uintptr
|
gpAttachShader uintptr
|
||||||
gpBindAttribLocation uintptr
|
gpBindAttribLocation uintptr
|
||||||
gpBindBuffer uintptr
|
gpBindBuffer uintptr
|
||||||
@ -81,6 +82,10 @@ func boolToUintptr(b bool) uintptr {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ActiveTexture(texture uint32) {
|
||||||
|
syscall.Syscall(gpActiveTexture, 1, uintptr(texture), 0, 0)
|
||||||
|
}
|
||||||
|
|
||||||
func AttachShader(program uint32, shader uint32) {
|
func AttachShader(program uint32, shader uint32) {
|
||||||
syscall.Syscall(gpAttachShader, 2, uintptr(program), uintptr(shader), 0)
|
syscall.Syscall(gpAttachShader, 2, uintptr(program), uintptr(shader), 0)
|
||||||
}
|
}
|
||||||
@ -332,6 +337,10 @@ func Viewport(x int32, y int32, width int32, height int32) {
|
|||||||
// InitWithProcAddrFunc intializes the package using the specified OpenGL
|
// InitWithProcAddrFunc intializes the package using the specified OpenGL
|
||||||
// function pointer loading function. For more cases Init should be used
|
// function pointer loading function. For more cases Init should be used
|
||||||
func InitWithProcAddrFunc(getProcAddr func(name string) uintptr) error {
|
func InitWithProcAddrFunc(getProcAddr func(name string) uintptr) error {
|
||||||
|
gpActiveTexture = getProcAddr("glActiveTexture")
|
||||||
|
if gpActiveTexture == 0 {
|
||||||
|
return errors.New("glActiveTexture")
|
||||||
|
}
|
||||||
gpAttachShader = getProcAddr("glAttachShader")
|
gpAttachShader = getProcAddr("glAttachShader")
|
||||||
if gpAttachShader == 0 {
|
if gpAttachShader == 0 {
|
||||||
return errors.New("glAttachShader")
|
return errors.New("glAttachShader")
|
||||||
|
@ -160,7 +160,7 @@ func (g *Graphics) Draw(indexLen int, indexOffset int, mode driver.CompositeMode
|
|||||||
uniforms["scale"] = scale
|
uniforms["scale"] = scale
|
||||||
}
|
}
|
||||||
|
|
||||||
uniforms["texture"] = source.textureNative
|
uniforms["texture/0"] = source.textureNative
|
||||||
|
|
||||||
if err := g.useProgram(program, uniforms); err != nil {
|
if err := g.useProgram(program, uniforms); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -16,6 +16,8 @@ package opengl
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten/internal/driver"
|
"github.com/hajimehoshi/ebiten/internal/driver"
|
||||||
"github.com/hajimehoshi/ebiten/internal/graphics"
|
"github.com/hajimehoshi/ebiten/internal/graphics"
|
||||||
@ -132,8 +134,9 @@ type openGLState struct {
|
|||||||
// programs is OpenGL's program for rendering a texture.
|
// programs is OpenGL's program for rendering a texture.
|
||||||
programs map[programKey]program
|
programs map[programKey]program
|
||||||
|
|
||||||
lastProgram program
|
lastProgram program
|
||||||
lastUniforms map[string]interface{}
|
lastUniforms map[string]interface{}
|
||||||
|
lastActiveTexture int
|
||||||
|
|
||||||
source *Image
|
source *Image
|
||||||
destination *Image
|
destination *Image
|
||||||
@ -251,6 +254,8 @@ func (g *Graphics) useProgram(program program, uniforms map[string]interface{})
|
|||||||
|
|
||||||
g.state.lastProgram = program
|
g.state.lastProgram = program
|
||||||
g.state.lastUniforms = map[string]interface{}{}
|
g.state.lastUniforms = map[string]interface{}{}
|
||||||
|
g.state.lastActiveTexture = 0
|
||||||
|
g.context.activeTexture(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
for key, u := range uniforms {
|
for key, u := range uniforms {
|
||||||
@ -271,10 +276,19 @@ func (g *Graphics) useProgram(program program, uniforms map[string]interface{})
|
|||||||
g.state.lastUniforms[key] = u
|
g.state.lastUniforms[key] = u
|
||||||
case textureNative:
|
case textureNative:
|
||||||
// Apparently, a texture must be bound every time. The cache is not used here.
|
// Apparently, a texture must be bound every time. The cache is not used here.
|
||||||
// TODO: Use another value than 0 when binding multiple textures.
|
tokens := strings.SplitN(key, "/", 2)
|
||||||
g.context.uniformInt(program, key, 0)
|
if len(tokens) != 2 {
|
||||||
// We don't have to call gl.ActiveTexture here: GL_TEXTURE0 is the default active texture
|
return fmt.Errorf("opengl: a uniform variable name for textures must be '[name]/[index]' but %s", key)
|
||||||
// See also: https://www.opengl.org/sdk/docs/man2/xhtml/glActiveTexture.xml
|
}
|
||||||
|
idx, err := strconv.Atoi(tokens[1])
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("opengl: a uniform variable name for textures must be '[name]/[index]' but %s", key)
|
||||||
|
}
|
||||||
|
g.context.uniformInt(program, tokens[0], idx)
|
||||||
|
if g.state.lastActiveTexture != idx {
|
||||||
|
g.context.activeTexture(idx)
|
||||||
|
g.state.lastActiveTexture = idx
|
||||||
|
}
|
||||||
g.context.bindTexture(u)
|
g.context.bindTexture(u)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user