From 073fd329f2bd1233ba2b73d182d8caeb326a88ef Mon Sep 17 00:00:00 2001 From: Hajime Hoshi Date: Fri, 31 Jul 2020 02:52:25 +0900 Subject: [PATCH] graphicsdriver/opengl: Enable to pass any type of uniform variables Updates #1274 --- .../graphicsdriver/opengl/context_desktop.go | 35 +++++++++---- internal/graphicsdriver/opengl/context_js.go | 39 ++++++++++---- .../graphicsdriver/opengl/context_mobile.go | 27 +++++++--- .../opengl/gl/package_notwindows.go | 52 +++++++++++++++++++ .../opengl/gl/package_windows.go | 36 +++++++++++++ internal/graphicsdriver/opengl/program.go | 2 +- 6 files changed, 164 insertions(+), 27 deletions(-) diff --git a/internal/graphicsdriver/opengl/context_desktop.go b/internal/graphicsdriver/opengl/context_desktop.go index 08b23d9e0..7743703a1 100644 --- a/internal/graphicsdriver/opengl/context_desktop.go +++ b/internal/graphicsdriver/opengl/context_desktop.go @@ -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 }) diff --git a/internal/graphicsdriver/opengl/context_js.go b/internal/graphicsdriver/opengl/context_js.go index a99f7f8e3..51bcfd224 100644 --- a/internal/graphicsdriver/opengl/context_js.go +++ b/internal/graphicsdriver/opengl/context_js.go @@ -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 } diff --git a/internal/graphicsdriver/opengl/context_mobile.go b/internal/graphicsdriver/opengl/context_mobile.go index 7cd3d8224..10d47b16a 100644 --- a/internal/graphicsdriver/opengl/context_mobile.go +++ b/internal/graphicsdriver/opengl/context_mobile.go @@ -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 } diff --git a/internal/graphicsdriver/opengl/gl/package_notwindows.go b/internal/graphicsdriver/opengl/gl/package_notwindows.go index a080cfb92..79e95a948 100644 --- a/internal/graphicsdriver/opengl/gl/package_notwindows.go +++ b/internal/graphicsdriver/opengl/gl/package_notwindows.go @@ -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") diff --git a/internal/graphicsdriver/opengl/gl/package_windows.go b/internal/graphicsdriver/opengl/gl/package_windows.go index 8b8afafc6..c6d99dceb 100644 --- a/internal/graphicsdriver/opengl/gl/package_windows.go +++ b/internal/graphicsdriver/opengl/gl/package_windows.go @@ -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") diff --git a/internal/graphicsdriver/opengl/program.go b/internal/graphicsdriver/opengl/program.go index 9418979a8..0b4d2bb88 100644 --- a/internal/graphicsdriver/opengl/program.go +++ b/internal/graphicsdriver/opengl/program.go @@ -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)