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/graphicsdriver/opengl/gl"
"github.com/hajimehoshi/ebiten/internal/shaderir"
)
type (
@ -411,7 +412,7 @@ func (c *context) uniformFloat(p program, location string, v float32) bool {
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
_ = c.t.Call(func() error {
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
}
r = true
switch len(v) {
case 2:
gl.Uniform2fv(l, 1, (*float32)(gl.Ptr(v)))
case 4:
gl.Uniform4fv(l, 1, (*float32)(gl.Ptr(v)))
case 16:
gl.UniformMatrix4fv(l, 1, false, (*float32)(gl.Ptr(v)))
base := typ.Main
len := int32(1)
if base == shaderir.Array {
base = typ.Sub[0].Main
len = int32(typ.Length)
}
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:
panic(fmt.Sprintf("opengl: invalid uniform floats num: %d", len(v)))
panic(fmt.Sprintf("opengl: unexpected type: %s", typ.String()))
}
return nil
})

View File

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

View File

@ -23,6 +23,7 @@ import (
mgl "golang.org/x/mobile/gl"
"github.com/hajimehoshi/ebiten/internal/driver"
"github.com/hajimehoshi/ebiten/internal/shaderir"
)
type (
@ -311,21 +312,35 @@ func (c *context) uniformFloat(p program, location string, v float32) bool {
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
l := c.locationCache.GetUniformLocation(c, p, location)
if l == invalidUniform {
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)
case 4:
case shaderir.Vec3:
gl.Uniform3fv(mgl.Uniform(l), v)
case shaderir.Vec4:
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)
default:
panic(fmt.Sprintf("opengl: invalid uniform floats num: %d", len(v)))
panic(fmt.Sprintf("opengl: unexpected type: %s", typ.String()))
}
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 GPUNIFORM1F)(GLint location, GLfloat 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 GPUNIFORM3FV)(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 GPUSEPROGRAM)(GLuint program);
// 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) {
// (*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) {
// (*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) {
// (*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) {
// (*fnptr)(location, count, transpose, value);
// }
@ -414,8 +430,12 @@ var (
gpTexSubImage2D C.GPTEXSUBIMAGE2D
gpUniform1f C.GPUNIFORM1F
gpUniform1i C.GPUNIFORM1I
gpUniform1fv C.GPUNIFORM1FV
gpUniform2fv C.GPUNIFORM2FV
gpUniform3fv C.GPUNIFORM3FV
gpUniform4fv C.GPUNIFORM4FV
gpUniformMatrix2fv C.GPUNIFORMMATRIX2FV
gpUniformMatrix3fv C.GPUNIFORMMATRIX3FV
gpUniformMatrix4fv C.GPUNIFORMMATRIX4FV
gpUseProgram C.GPUSEPROGRAM
gpVertexAttribPointer C.GPVERTEXATTRIBPOINTER
@ -657,14 +677,30 @@ func Uniform1i(location int32, v0 int32) {
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) {
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) {
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) {
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 {
return errors.New("glUniform1i")
}
gpUniform1fv = (C.GPUNIFORM1FV)(getProcAddr("glUniform1fv"))
if gpUniform1fv == nil {
return errors.New("glUniform1fv")
}
gpUniform2fv = (C.GPUNIFORM2FV)(getProcAddr("glUniform2fv"))
if gpUniform2fv == nil {
return errors.New("glUniform2fv")
}
gpUniform3fv = (C.GPUNIFORM3FV)(getProcAddr("glUniform3fv"))
if gpUniform3fv == nil {
return errors.New("glUniform3fv")
}
gpUniform4fv = (C.GPUNIFORM4FV)(getProcAddr("glUniform4fv"))
if gpUniform4fv == nil {
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"))
if gpUniformMatrix4fv == nil {
return errors.New("glUniformMatrix4fv")

View File

@ -67,8 +67,12 @@ var (
gpTexSubImage2D uintptr
gpUniform1f uintptr
gpUniform1i uintptr
gpUniform1fv uintptr
gpUniform2fv uintptr
gpUniform3fv uintptr
gpUniform4fv uintptr
gpUniformMatrix2fv uintptr
gpUniformMatrix3fv uintptr
gpUniformMatrix4fv uintptr
gpUseProgram uintptr
gpVertexAttribPointer uintptr
@ -310,14 +314,30 @@ func Uniform1i(location int32, v0 int32) {
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) {
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) {
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) {
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 {
return errors.New("glUniform1i")
}
gpUniform1fv = getProcAddr("glUniform1fv")
if gpUniform1fv == 0 {
return errors.New("glUniform1fv")
}
gpUniform2fv = getProcAddr("glUniform2fv")
if gpUniform2fv == 0 {
return errors.New("glUniform2fv")
}
gpUniform3fv = getProcAddr("glUniform3fv")
if gpUniform3fv == 0 {
return errors.New("glUniform3fv")
}
gpUniform4fv = getProcAddr("glUniform4fv")
if gpUniform4fv == 0 {
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")
if gpUniformMatrix4fv == 0 {
return errors.New("glUniformMatrix4fv")

View File

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