graphicsdriver/opengl: Enable to pass any type of uniform variables

Updates #1274
This commit is contained in:
Hajime Hoshi 2020-07-31 02:52:25 +09:00
parent 2208046382
commit 073fd329f2
6 changed files with 164 additions and 27 deletions

View File

@ -25,6 +25,7 @@ import (
"github.com/hajimehoshi/ebiten/internal/driver" "github.com/hajimehoshi/ebiten/internal/driver"
"github.com/hajimehoshi/ebiten/internal/graphicsdriver/opengl/gl" "github.com/hajimehoshi/ebiten/internal/graphicsdriver/opengl/gl"
"github.com/hajimehoshi/ebiten/internal/shaderir"
) )
type ( type (
@ -411,7 +412,7 @@ func (c *context) uniformFloat(p program, location string, v float32) bool {
return r return r
} }
func (c *context) uniformFloats(p program, location string, v []float32) bool { func (c *context) uniformFloats(p program, location string, v []float32, typ shaderir.Type) bool {
var r bool var r bool
_ = c.t.Call(func() error { _ = c.t.Call(func() error {
l := int32(c.locationCache.GetUniformLocation(c, p, location)) l := int32(c.locationCache.GetUniformLocation(c, p, location))
@ -419,15 +420,31 @@ func (c *context) uniformFloats(p program, location string, v []float32) bool {
return nil return nil
} }
r = true r = true
switch len(v) {
case 2: base := typ.Main
gl.Uniform2fv(l, 1, (*float32)(gl.Ptr(v))) len := int32(1)
case 4: if base == shaderir.Array {
gl.Uniform4fv(l, 1, (*float32)(gl.Ptr(v))) base = typ.Sub[0].Main
case 16: len = int32(typ.Length)
gl.UniformMatrix4fv(l, 1, false, (*float32)(gl.Ptr(v))) }
switch base {
case shaderir.Float:
gl.Uniform1fv(l, len, (*float32)(gl.Ptr(v)))
case shaderir.Vec2:
gl.Uniform2fv(l, len, (*float32)(gl.Ptr(v)))
case shaderir.Vec3:
gl.Uniform3fv(l, len, (*float32)(gl.Ptr(v)))
case shaderir.Vec4:
gl.Uniform4fv(l, len, (*float32)(gl.Ptr(v)))
case shaderir.Mat2:
gl.UniformMatrix2fv(l, len, false, (*float32)(gl.Ptr(v)))
case shaderir.Mat3:
gl.UniformMatrix3fv(l, len, false, (*float32)(gl.Ptr(v)))
case shaderir.Mat4:
gl.UniformMatrix4fv(l, len, false, (*float32)(gl.Ptr(v)))
default: default:
panic(fmt.Sprintf("opengl: invalid uniform floats num: %d", len(v))) panic(fmt.Sprintf("opengl: unexpected type: %s", typ.String()))
} }
return nil return nil
}) })

View File

@ -23,6 +23,7 @@ import (
"github.com/hajimehoshi/ebiten/internal/driver" "github.com/hajimehoshi/ebiten/internal/driver"
"github.com/hajimehoshi/ebiten/internal/jsutil" "github.com/hajimehoshi/ebiten/internal/jsutil"
"github.com/hajimehoshi/ebiten/internal/shaderir"
"github.com/hajimehoshi/ebiten/internal/web" "github.com/hajimehoshi/ebiten/internal/web"
) )
@ -448,26 +449,42 @@ func (c *context) uniformFloat(p program, location string, v float32) bool {
return true return true
} }
func (c *context) uniformFloats(p program, location string, v []float32) bool { func (c *context) uniformFloats(p program, location string, v []float32, typ shaderir.Type) bool {
c.ensureGL() c.ensureGL()
gl := c.gl gl := c.gl
l := c.locationCache.GetUniformLocation(c, p, location) l := c.locationCache.GetUniformLocation(c, p, location)
if l.equal(invalidUniform) { if l.equal(invalidUniform) {
return false return false
} }
switch len(v) {
case 2: base := typ.Main
gl.Call("uniform2f", js.Value(l), v[0], v[1]) if base == shaderir.Array {
case 4: base = typ.Sub[0].Main
gl.Call("uniform4f", js.Value(l), v[0], v[1], v[2], v[3]) }
case 16:
arr8 := jsutil.TemporaryUint8Array(len(v) * 4) arr8 := jsutil.TemporaryUint8Array(len(v) * 4)
arr := js.Global().Get("Float32Array").New(arr8.Get("buffer"), arr8.Get("byteOffset"), len(v)) arr := js.Global().Get("Float32Array").New(arr8.Get("buffer"), arr8.Get("byteOffset"), len(v))
jsutil.CopySliceToJS(arr, v) jsutil.CopySliceToJS(arr, v)
switch base {
case shaderir.Float:
gl.Call("uniform1fv", js.Value(l), arr)
case shaderir.Vec2:
gl.Call("uniform2fv", js.Value(l), arr)
case shaderir.Vec3:
gl.Call("uniform3fv", js.Value(l), arr)
case shaderir.Vec4:
gl.Call("uniform4fv", js.Value(l), arr)
case shaderir.Mat2:
gl.Call("uniformMatrix2fv", js.Value(l), false, arr)
case shaderir.Mat3:
gl.Call("uniformMatrix3fv", js.Value(l), false, arr)
case shaderir.Mat4:
gl.Call("uniformMatrix4fv", js.Value(l), false, arr) gl.Call("uniformMatrix4fv", js.Value(l), false, arr)
default: default:
panic(fmt.Sprintf("opengl: invalid uniform floats num: %d", len(v))) panic(fmt.Sprintf("opengl: unexpected type: %s", typ.String()))
} }
return true return true
} }

View File

@ -23,6 +23,7 @@ import (
mgl "golang.org/x/mobile/gl" mgl "golang.org/x/mobile/gl"
"github.com/hajimehoshi/ebiten/internal/driver" "github.com/hajimehoshi/ebiten/internal/driver"
"github.com/hajimehoshi/ebiten/internal/shaderir"
) )
type ( type (
@ -311,21 +312,35 @@ func (c *context) uniformFloat(p program, location string, v float32) bool {
return true return true
} }
func (c *context) uniformFloats(p program, location string, v []float32) bool { func (c *context) uniformFloats(p program, location string, v []float32, typ shaderir.Type) bool {
gl := c.gl gl := c.gl
l := c.locationCache.GetUniformLocation(c, p, location) l := c.locationCache.GetUniformLocation(c, p, location)
if l == invalidUniform { if l == invalidUniform {
return false return false
} }
switch len(v) {
case 2: base := typ.Main
if base == shaderir.Array {
base = typ.Sub[0].Main
}
switch base {
case shaderir.Float:
gl.Uniform1fv(mgl.Uniform(l), v)
case shaderir.Vec2:
gl.Uniform2fv(mgl.Uniform(l), v) gl.Uniform2fv(mgl.Uniform(l), v)
case 4: case shaderir.Vec3:
gl.Uniform3fv(mgl.Uniform(l), v)
case shaderir.Vec4:
gl.Uniform4fv(mgl.Uniform(l), v) gl.Uniform4fv(mgl.Uniform(l), v)
case 16: case shaderir.Mat2:
gl.UniformMatrix2fv(mgl.Uniform(l), v)
case shaderir.Mat3:
gl.UniformMatrix3fv(mgl.Uniform(l), v)
case shaderir.Mat4:
gl.UniformMatrix4fv(mgl.Uniform(l), v) gl.UniformMatrix4fv(mgl.Uniform(l), v)
default: default:
panic(fmt.Sprintf("opengl: invalid uniform floats num: %d", len(v))) panic(fmt.Sprintf("opengl: unexpected type: %s", typ.String()))
} }
return true return true
} }

View File

@ -153,8 +153,12 @@ package gl
// typedef void (APIENTRYP GPTEXSUBIMAGE2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void * pixels); // typedef void (APIENTRYP GPTEXSUBIMAGE2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void * pixels);
// typedef void (APIENTRYP GPUNIFORM1F)(GLint location, GLfloat v0); // typedef void (APIENTRYP GPUNIFORM1F)(GLint location, GLfloat v0);
// typedef void (APIENTRYP GPUNIFORM1I)(GLint location, GLint v0); // typedef void (APIENTRYP GPUNIFORM1I)(GLint location, GLint v0);
// typedef void (APIENTRYP GPUNIFORM1FV)(GLint location, GLsizei count, const GLfloat * value);
// typedef void (APIENTRYP GPUNIFORM2FV)(GLint location, GLsizei count, const GLfloat * value); // typedef void (APIENTRYP GPUNIFORM2FV)(GLint location, GLsizei count, const GLfloat * value);
// typedef void (APIENTRYP GPUNIFORM3FV)(GLint location, GLsizei count, const GLfloat * value);
// typedef void (APIENTRYP GPUNIFORM4FV)(GLint location, GLsizei count, const GLfloat * value); // typedef void (APIENTRYP GPUNIFORM4FV)(GLint location, GLsizei count, const GLfloat * value);
// typedef void (APIENTRYP GPUNIFORMMATRIX2FV)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
// typedef void (APIENTRYP GPUNIFORMMATRIX3FV)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
// typedef void (APIENTRYP GPUNIFORMMATRIX4FV)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); // typedef void (APIENTRYP GPUNIFORMMATRIX4FV)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
// typedef void (APIENTRYP GPUSEPROGRAM)(GLuint program); // typedef void (APIENTRYP GPUSEPROGRAM)(GLuint program);
// 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);
@ -331,12 +335,24 @@ package gl
// static void glowUniform1i(GPUNIFORM1I fnptr, GLint location, GLint v0) { // static void glowUniform1i(GPUNIFORM1I fnptr, GLint location, GLint v0) {
// (*fnptr)(location, v0); // (*fnptr)(location, v0);
// } // }
// static void glowUniform1fv(GPUNIFORM1FV fnptr, GLint location, GLsizei count, const GLfloat * value) {
// (*fnptr)(location, count, value);
// }
// static void glowUniform2fv(GPUNIFORM2FV fnptr, GLint location, GLsizei count, const GLfloat * value) { // static void glowUniform2fv(GPUNIFORM2FV fnptr, GLint location, GLsizei count, const GLfloat * value) {
// (*fnptr)(location, count, value); // (*fnptr)(location, count, value);
// } // }
// static void glowUniform3fv(GPUNIFORM3FV fnptr, GLint location, GLsizei count, const GLfloat * value) {
// (*fnptr)(location, count, value);
// }
// static void glowUniform4fv(GPUNIFORM4FV fnptr, GLint location, GLsizei count, const GLfloat * value) { // static void glowUniform4fv(GPUNIFORM4FV fnptr, GLint location, GLsizei count, const GLfloat * value) {
// (*fnptr)(location, count, value); // (*fnptr)(location, count, value);
// } // }
// static void glowUniformMatrix2fv(GPUNIFORMMATRIX2FV fnptr, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
// (*fnptr)(location, count, transpose, value);
// }
// static void glowUniformMatrix3fv(GPUNIFORMMATRIX3FV fnptr, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
// (*fnptr)(location, count, transpose, value);
// }
// static void glowUniformMatrix4fv(GPUNIFORMMATRIX4FV fnptr, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) { // static void glowUniformMatrix4fv(GPUNIFORMMATRIX4FV fnptr, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
// (*fnptr)(location, count, transpose, value); // (*fnptr)(location, count, transpose, value);
// } // }
@ -414,8 +430,12 @@ var (
gpTexSubImage2D C.GPTEXSUBIMAGE2D gpTexSubImage2D C.GPTEXSUBIMAGE2D
gpUniform1f C.GPUNIFORM1F gpUniform1f C.GPUNIFORM1F
gpUniform1i C.GPUNIFORM1I gpUniform1i C.GPUNIFORM1I
gpUniform1fv C.GPUNIFORM1FV
gpUniform2fv C.GPUNIFORM2FV gpUniform2fv C.GPUNIFORM2FV
gpUniform3fv C.GPUNIFORM3FV
gpUniform4fv C.GPUNIFORM4FV gpUniform4fv C.GPUNIFORM4FV
gpUniformMatrix2fv C.GPUNIFORMMATRIX2FV
gpUniformMatrix3fv C.GPUNIFORMMATRIX3FV
gpUniformMatrix4fv C.GPUNIFORMMATRIX4FV gpUniformMatrix4fv C.GPUNIFORMMATRIX4FV
gpUseProgram C.GPUSEPROGRAM gpUseProgram C.GPUSEPROGRAM
gpVertexAttribPointer C.GPVERTEXATTRIBPOINTER gpVertexAttribPointer C.GPVERTEXATTRIBPOINTER
@ -657,14 +677,30 @@ func Uniform1i(location int32, v0 int32) {
C.glowUniform1i(gpUniform1i, (C.GLint)(location), (C.GLint)(v0)) C.glowUniform1i(gpUniform1i, (C.GLint)(location), (C.GLint)(v0))
} }
func Uniform1fv(location int32, count int32, value *float32) {
C.glowUniform1fv(gpUniform1fv, (C.GLint)(location), (C.GLsizei)(count), (*C.GLfloat)(unsafe.Pointer(value)))
}
func Uniform2fv(location int32, count int32, value *float32) { func Uniform2fv(location int32, count int32, value *float32) {
C.glowUniform2fv(gpUniform2fv, (C.GLint)(location), (C.GLsizei)(count), (*C.GLfloat)(unsafe.Pointer(value))) C.glowUniform2fv(gpUniform2fv, (C.GLint)(location), (C.GLsizei)(count), (*C.GLfloat)(unsafe.Pointer(value)))
} }
func Uniform3fv(location int32, count int32, value *float32) {
C.glowUniform3fv(gpUniform3fv, (C.GLint)(location), (C.GLsizei)(count), (*C.GLfloat)(unsafe.Pointer(value)))
}
func Uniform4fv(location int32, count int32, value *float32) { func Uniform4fv(location int32, count int32, value *float32) {
C.glowUniform4fv(gpUniform4fv, (C.GLint)(location), (C.GLsizei)(count), (*C.GLfloat)(unsafe.Pointer(value))) C.glowUniform4fv(gpUniform4fv, (C.GLint)(location), (C.GLsizei)(count), (*C.GLfloat)(unsafe.Pointer(value)))
} }
func UniformMatrix2fv(location int32, count int32, transpose bool, value *float32) {
C.glowUniformMatrix2fv(gpUniformMatrix2fv, (C.GLint)(location), (C.GLsizei)(count), (C.GLboolean)(boolToInt(transpose)), (*C.GLfloat)(unsafe.Pointer(value)))
}
func UniformMatrix3fv(location int32, count int32, transpose bool, value *float32) {
C.glowUniformMatrix3fv(gpUniformMatrix3fv, (C.GLint)(location), (C.GLsizei)(count), (C.GLboolean)(boolToInt(transpose)), (*C.GLfloat)(unsafe.Pointer(value)))
}
func UniformMatrix4fv(location int32, count int32, transpose bool, value *float32) { func UniformMatrix4fv(location int32, count int32, transpose bool, value *float32) {
C.glowUniformMatrix4fv(gpUniformMatrix4fv, (C.GLint)(location), (C.GLsizei)(count), (C.GLboolean)(boolToInt(transpose)), (*C.GLfloat)(unsafe.Pointer(value))) C.glowUniformMatrix4fv(gpUniformMatrix4fv, (C.GLint)(location), (C.GLsizei)(count), (C.GLboolean)(boolToInt(transpose)), (*C.GLfloat)(unsafe.Pointer(value)))
} }
@ -858,14 +894,30 @@ func InitWithProcAddrFunc(getProcAddr func(name string) unsafe.Pointer) error {
if gpUniform1i == nil { if gpUniform1i == nil {
return errors.New("glUniform1i") return errors.New("glUniform1i")
} }
gpUniform1fv = (C.GPUNIFORM1FV)(getProcAddr("glUniform1fv"))
if gpUniform1fv == nil {
return errors.New("glUniform1fv")
}
gpUniform2fv = (C.GPUNIFORM2FV)(getProcAddr("glUniform2fv")) gpUniform2fv = (C.GPUNIFORM2FV)(getProcAddr("glUniform2fv"))
if gpUniform2fv == nil { if gpUniform2fv == nil {
return errors.New("glUniform2fv") return errors.New("glUniform2fv")
} }
gpUniform3fv = (C.GPUNIFORM3FV)(getProcAddr("glUniform3fv"))
if gpUniform3fv == nil {
return errors.New("glUniform3fv")
}
gpUniform4fv = (C.GPUNIFORM4FV)(getProcAddr("glUniform4fv")) gpUniform4fv = (C.GPUNIFORM4FV)(getProcAddr("glUniform4fv"))
if gpUniform4fv == nil { if gpUniform4fv == nil {
return errors.New("glUniform4fv") return errors.New("glUniform4fv")
} }
gpUniformMatrix2fv = (C.GPUNIFORMMATRIX2FV)(getProcAddr("glUniformMatrix2fv"))
if gpUniformMatrix2fv == nil {
return errors.New("glUniformMatrix2fv")
}
gpUniformMatrix3fv = (C.GPUNIFORMMATRIX3FV)(getProcAddr("glUniformMatrix3fv"))
if gpUniformMatrix3fv == nil {
return errors.New("glUniformMatrix3fv")
}
gpUniformMatrix4fv = (C.GPUNIFORMMATRIX4FV)(getProcAddr("glUniformMatrix4fv")) gpUniformMatrix4fv = (C.GPUNIFORMMATRIX4FV)(getProcAddr("glUniformMatrix4fv"))
if gpUniformMatrix4fv == nil { if gpUniformMatrix4fv == nil {
return errors.New("glUniformMatrix4fv") return errors.New("glUniformMatrix4fv")

View File

@ -67,8 +67,12 @@ var (
gpTexSubImage2D uintptr gpTexSubImage2D uintptr
gpUniform1f uintptr gpUniform1f uintptr
gpUniform1i uintptr gpUniform1i uintptr
gpUniform1fv uintptr
gpUniform2fv uintptr gpUniform2fv uintptr
gpUniform3fv uintptr
gpUniform4fv uintptr gpUniform4fv uintptr
gpUniformMatrix2fv uintptr
gpUniformMatrix3fv uintptr
gpUniformMatrix4fv uintptr gpUniformMatrix4fv uintptr
gpUseProgram uintptr gpUseProgram uintptr
gpVertexAttribPointer uintptr gpVertexAttribPointer uintptr
@ -310,14 +314,30 @@ func Uniform1i(location int32, v0 int32) {
syscall.Syscall(gpUniform1i, 2, uintptr(location), uintptr(v0), 0) syscall.Syscall(gpUniform1i, 2, uintptr(location), uintptr(v0), 0)
} }
func Uniform1fv(location int32, count int32, value *float32) {
syscall.Syscall(gpUniform1fv, 3, uintptr(location), uintptr(count), uintptr(unsafe.Pointer(value)))
}
func Uniform2fv(location int32, count int32, value *float32) { func Uniform2fv(location int32, count int32, value *float32) {
syscall.Syscall(gpUniform2fv, 3, uintptr(location), uintptr(count), uintptr(unsafe.Pointer(value))) syscall.Syscall(gpUniform2fv, 3, uintptr(location), uintptr(count), uintptr(unsafe.Pointer(value)))
} }
func Uniform3fv(location int32, count int32, value *float32) {
syscall.Syscall(gpUniform3fv, 3, uintptr(location), uintptr(count), uintptr(unsafe.Pointer(value)))
}
func Uniform4fv(location int32, count int32, value *float32) { func Uniform4fv(location int32, count int32, value *float32) {
syscall.Syscall(gpUniform4fv, 3, uintptr(location), uintptr(count), uintptr(unsafe.Pointer(value))) syscall.Syscall(gpUniform4fv, 3, uintptr(location), uintptr(count), uintptr(unsafe.Pointer(value)))
} }
func UniformMatrix2fv(location int32, count int32, transpose bool, value *float32) {
syscall.Syscall6(gpUniformMatrix2fv, 4, uintptr(location), uintptr(count), boolToUintptr(transpose), uintptr(unsafe.Pointer(value)), 0, 0)
}
func UniformMatrix3fv(location int32, count int32, transpose bool, value *float32) {
syscall.Syscall6(gpUniformMatrix3fv, 4, uintptr(location), uintptr(count), boolToUintptr(transpose), uintptr(unsafe.Pointer(value)), 0, 0)
}
func UniformMatrix4fv(location int32, count int32, transpose bool, value *float32) { func UniformMatrix4fv(location int32, count int32, transpose bool, value *float32) {
syscall.Syscall6(gpUniformMatrix4fv, 4, uintptr(location), uintptr(count), boolToUintptr(transpose), uintptr(unsafe.Pointer(value)), 0, 0) syscall.Syscall6(gpUniformMatrix4fv, 4, uintptr(location), uintptr(count), boolToUintptr(transpose), uintptr(unsafe.Pointer(value)), 0, 0)
} }
@ -511,14 +531,30 @@ func InitWithProcAddrFunc(getProcAddr func(name string) uintptr) error {
if gpUniform1i == 0 { if gpUniform1i == 0 {
return errors.New("glUniform1i") return errors.New("glUniform1i")
} }
gpUniform1fv = getProcAddr("glUniform1fv")
if gpUniform1fv == 0 {
return errors.New("glUniform1fv")
}
gpUniform2fv = getProcAddr("glUniform2fv") gpUniform2fv = getProcAddr("glUniform2fv")
if gpUniform2fv == 0 { if gpUniform2fv == 0 {
return errors.New("glUniform2fv") return errors.New("glUniform2fv")
} }
gpUniform3fv = getProcAddr("glUniform3fv")
if gpUniform3fv == 0 {
return errors.New("glUniform3fv")
}
gpUniform4fv = getProcAddr("glUniform4fv") gpUniform4fv = getProcAddr("glUniform4fv")
if gpUniform4fv == 0 { if gpUniform4fv == 0 {
return errors.New("glUniform4fv") return errors.New("glUniform4fv")
} }
gpUniformMatrix2fv = getProcAddr("glUniformMatrix2fv")
if gpUniformMatrix2fv == 0 {
return errors.New("glUniformMatrix2fv")
}
gpUniformMatrix3fv = getProcAddr("glUniformMatrix3fv")
if gpUniformMatrix3fv == 0 {
return errors.New("glUniformMatrix3fv")
}
gpUniformMatrix4fv = getProcAddr("glUniformMatrix4fv") gpUniformMatrix4fv = getProcAddr("glUniformMatrix4fv")
if gpUniformMatrix4fv == 0 { if gpUniformMatrix4fv == 0 {
return errors.New("glUniformMatrix4fv") return errors.New("glUniformMatrix4fv")

View File

@ -285,7 +285,7 @@ func (g *Graphics) useProgram(program program, uniforms []uniformVariable, textu
if ok && areSameFloat32Array(cached, v) { if ok && areSameFloat32Array(cached, v) {
continue continue
} }
g.context.uniformFloats(program, u.name, v) g.context.uniformFloats(program, u.name, v, u.typ)
g.state.lastUniforms[u.name] = v g.state.lastUniforms[u.name] = v
default: default:
return fmt.Errorf("opengl: unexpected uniform value: %v (type: %T)", u.value, u.value) return fmt.Errorf("opengl: unexpected uniform value: %v (type: %T)", u.value, u.value)