mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-11-10 04:57:26 +01:00
all: allow integer uniform variables for Kage shaders
Closes #2305 Updates #2448
This commit is contained in:
parent
4ff9a12930
commit
1ecac8d834
4
image.go
4
image.go
@ -505,7 +505,7 @@ type DrawTrianglesShaderOptions struct {
|
|||||||
|
|
||||||
// Uniforms is a set of uniform variables for the shader.
|
// Uniforms is a set of uniform variables for the shader.
|
||||||
// The keys are the names of the uniform variables.
|
// The keys are the names of the uniform variables.
|
||||||
// The values must be float or []float.
|
// The values must be a numeric type or a slice of a numeric type.
|
||||||
// If the uniform variable type is an array, a vector or a matrix,
|
// If the uniform variable type is an array, a vector or a matrix,
|
||||||
// you have to specify linearly flattened values as a slice.
|
// you have to specify linearly flattened values as a slice.
|
||||||
// For example, if the uniform variable type is [4]vec4, the number of the slice values will be 16.
|
// For example, if the uniform variable type is [4]vec4, the number of the slice values will be 16.
|
||||||
@ -665,7 +665,7 @@ type DrawRectShaderOptions struct {
|
|||||||
|
|
||||||
// Uniforms is a set of uniform variables for the shader.
|
// Uniforms is a set of uniform variables for the shader.
|
||||||
// The keys are the names of the uniform variables.
|
// The keys are the names of the uniform variables.
|
||||||
// The values must be float or []float.
|
// The values must be a numeric type or a slice of a numeric type.
|
||||||
// If the uniform variable type is an array, a vector or a matrix,
|
// If the uniform variable type is an array, a vector or a matrix,
|
||||||
// you have to specify linearly flattened values as a slice.
|
// you have to specify linearly flattened values as a slice.
|
||||||
// For example, if the uniform variable type is [4]vec4, the number of the slice values will be 16.
|
// For example, if the uniform variable type is [4]vec4, the number of the slice values will be 16.
|
||||||
|
@ -1732,6 +1732,12 @@ func (s *Shader) flattenUniforms(uniforms [][]uint32) []uint32 {
|
|||||||
} else {
|
} else {
|
||||||
fs = append(fs, 0)
|
fs = append(fs, 0)
|
||||||
}
|
}
|
||||||
|
case shaderir.Int:
|
||||||
|
if u != nil {
|
||||||
|
fs = append(fs, u...)
|
||||||
|
} else {
|
||||||
|
fs = append(fs, 0)
|
||||||
|
}
|
||||||
case shaderir.Vec2:
|
case shaderir.Vec2:
|
||||||
if u != nil {
|
if u != nil {
|
||||||
fs = append(fs, u...)
|
fs = append(fs, u...)
|
||||||
@ -1806,6 +1812,17 @@ func (s *Shader) flattenUniforms(uniforms [][]uint32) []uint32 {
|
|||||||
} else {
|
} else {
|
||||||
fs = append(fs, make([]uint32, (t.Length-1)*4+1)...)
|
fs = append(fs, make([]uint32, (t.Length-1)*4+1)...)
|
||||||
}
|
}
|
||||||
|
case shaderir.Int:
|
||||||
|
if u != nil {
|
||||||
|
for j := 0; j < t.Length; j++ {
|
||||||
|
fs = append(fs, u[j])
|
||||||
|
if j < t.Length-1 {
|
||||||
|
fs = append(fs, 0, 0, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fs = append(fs, make([]uint32, (t.Length-1)*4+1)...)
|
||||||
|
}
|
||||||
case shaderir.Vec2:
|
case shaderir.Vec2:
|
||||||
if u != nil {
|
if u != nil {
|
||||||
for j := 0; j < t.Length; j++ {
|
for j := 0; j < t.Length; j++ {
|
||||||
|
@ -375,7 +375,7 @@ func (c *context) uniformInt(p program, location string, v int) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *context) uniformFloats(p program, location string, v []float32, typ shaderir.Type) bool {
|
func (c *context) uniforms(p program, location string, v []uint32, typ shaderir.Type) bool {
|
||||||
l := int32(c.locationCache.GetUniformLocation(c, p, location))
|
l := int32(c.locationCache.GetUniformLocation(c, p, location))
|
||||||
if l == invalidUniform {
|
if l == invalidUniform {
|
||||||
return false
|
return false
|
||||||
@ -391,6 +391,8 @@ func (c *context) uniformFloats(p program, location string, v []float32, typ sha
|
|||||||
switch base {
|
switch base {
|
||||||
case shaderir.Float:
|
case shaderir.Float:
|
||||||
gl.Uniform1fv(l, len, (*float32)(gl.Ptr(v)))
|
gl.Uniform1fv(l, len, (*float32)(gl.Ptr(v)))
|
||||||
|
case shaderir.Int:
|
||||||
|
gl.Uniform1iv(l, len, (*int32)(gl.Ptr(v)))
|
||||||
case shaderir.Vec2:
|
case shaderir.Vec2:
|
||||||
gl.Uniform2fv(l, len, (*float32)(gl.Ptr(v)))
|
gl.Uniform2fv(l, len, (*float32)(gl.Ptr(v)))
|
||||||
case shaderir.Vec3:
|
case shaderir.Vec3:
|
||||||
|
@ -344,7 +344,7 @@ func (c *context) uniformInt(p program, location string, v int) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *context) uniformFloats(p program, location string, v []float32, typ shaderir.Type) bool {
|
func (c *context) uniforms(p program, location string, v []uint32, typ shaderir.Type) bool {
|
||||||
l := c.locationCache.GetUniformLocation(c, p, location)
|
l := c.locationCache.GetUniformLocation(c, p, location)
|
||||||
if l == invalidUniform {
|
if l == invalidUniform {
|
||||||
return false
|
return false
|
||||||
@ -357,19 +357,21 @@ func (c *context) uniformFloats(p program, location string, v []float32, typ sha
|
|||||||
|
|
||||||
switch base {
|
switch base {
|
||||||
case shaderir.Float:
|
case shaderir.Float:
|
||||||
c.ctx.Uniform1fv(int32(l), v)
|
c.ctx.Uniform1fv(int32(l), uint32sToFloat32s(v))
|
||||||
|
case shaderir.Int:
|
||||||
|
c.ctx.Uniform1iv(int32(l), uint32sToInt32s(v))
|
||||||
case shaderir.Vec2:
|
case shaderir.Vec2:
|
||||||
c.ctx.Uniform2fv(int32(l), v)
|
c.ctx.Uniform2fv(int32(l), uint32sToFloat32s(v))
|
||||||
case shaderir.Vec3:
|
case shaderir.Vec3:
|
||||||
c.ctx.Uniform3fv(int32(l), v)
|
c.ctx.Uniform3fv(int32(l), uint32sToFloat32s(v))
|
||||||
case shaderir.Vec4:
|
case shaderir.Vec4:
|
||||||
c.ctx.Uniform4fv(int32(l), v)
|
c.ctx.Uniform4fv(int32(l), uint32sToFloat32s(v))
|
||||||
case shaderir.Mat2:
|
case shaderir.Mat2:
|
||||||
c.ctx.UniformMatrix2fv(int32(l), false, v)
|
c.ctx.UniformMatrix2fv(int32(l), false, uint32sToFloat32s(v))
|
||||||
case shaderir.Mat3:
|
case shaderir.Mat3:
|
||||||
c.ctx.UniformMatrix3fv(int32(l), false, v)
|
c.ctx.UniformMatrix3fv(int32(l), false, uint32sToFloat32s(v))
|
||||||
case shaderir.Mat4:
|
case shaderir.Mat4:
|
||||||
c.ctx.UniformMatrix4fv(int32(l), false, v)
|
c.ctx.UniformMatrix4fv(int32(l), false, uint32sToFloat32s(v))
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("opengl: unexpected type: %s", typ.String()))
|
panic(fmt.Sprintf("opengl: unexpected type: %s", typ.String()))
|
||||||
}
|
}
|
||||||
|
@ -451,7 +451,7 @@ func (c *context) uniformInt(p program, location string, v int) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *context) uniformFloats(p program, location string, v []float32, typ shaderir.Type) bool {
|
func (c *context) uniforms(p program, location string, v []uint32, 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.equal(invalidUniform) {
|
if l.equal(invalidUniform) {
|
||||||
@ -463,46 +463,58 @@ func (c *context) uniformFloats(p program, location string, v []float32, typ sha
|
|||||||
base = typ.Sub[0].Main
|
base = typ.Sub[0].Main
|
||||||
}
|
}
|
||||||
|
|
||||||
arr := jsutil.TemporaryFloat32Array(len(v), v)
|
|
||||||
|
|
||||||
switch base {
|
switch base {
|
||||||
case shaderir.Float:
|
case shaderir.Float:
|
||||||
|
arr := jsutil.TemporaryFloat32Array(len(v), uint32sToFloat32s(v))
|
||||||
if c.usesWebGL2() {
|
if c.usesWebGL2() {
|
||||||
gl.uniform1fv.Invoke(js.Value(l), arr, 0, len(v))
|
gl.uniform1fv.Invoke(js.Value(l), arr, 0, len(v))
|
||||||
} else {
|
} else {
|
||||||
gl.uniform1fv.Invoke(js.Value(l), arr.Call("subarray", 0, len(v)))
|
gl.uniform1fv.Invoke(js.Value(l), arr.Call("subarray", 0, len(v)))
|
||||||
}
|
}
|
||||||
|
case shaderir.Int:
|
||||||
|
arr := jsutil.TemporaryInt32Array(len(v), uint32sToInt32s(v))
|
||||||
|
if c.usesWebGL2() {
|
||||||
|
gl.uniform1iv.Invoke(js.Value(l), arr, 0, len(v))
|
||||||
|
} else {
|
||||||
|
gl.uniform1iv.Invoke(js.Value(l), arr.Call("subarray", 0, len(v)))
|
||||||
|
}
|
||||||
case shaderir.Vec2:
|
case shaderir.Vec2:
|
||||||
|
arr := jsutil.TemporaryFloat32Array(len(v), uint32sToFloat32s(v))
|
||||||
if c.usesWebGL2() {
|
if c.usesWebGL2() {
|
||||||
gl.uniform2fv.Invoke(js.Value(l), arr, 0, len(v))
|
gl.uniform2fv.Invoke(js.Value(l), arr, 0, len(v))
|
||||||
} else {
|
} else {
|
||||||
gl.uniform2fv.Invoke(js.Value(l), arr.Call("subarray", 0, len(v)))
|
gl.uniform2fv.Invoke(js.Value(l), arr.Call("subarray", 0, len(v)))
|
||||||
}
|
}
|
||||||
case shaderir.Vec3:
|
case shaderir.Vec3:
|
||||||
|
arr := jsutil.TemporaryFloat32Array(len(v), uint32sToFloat32s(v))
|
||||||
if c.usesWebGL2() {
|
if c.usesWebGL2() {
|
||||||
gl.uniform3fv.Invoke(js.Value(l), arr, 0, len(v))
|
gl.uniform3fv.Invoke(js.Value(l), arr, 0, len(v))
|
||||||
} else {
|
} else {
|
||||||
gl.uniform3fv.Invoke(js.Value(l), arr.Call("subarray", 0, len(v)))
|
gl.uniform3fv.Invoke(js.Value(l), arr.Call("subarray", 0, len(v)))
|
||||||
}
|
}
|
||||||
case shaderir.Vec4:
|
case shaderir.Vec4:
|
||||||
|
arr := jsutil.TemporaryFloat32Array(len(v), uint32sToFloat32s(v))
|
||||||
if c.usesWebGL2() {
|
if c.usesWebGL2() {
|
||||||
gl.uniform4fv.Invoke(js.Value(l), arr, 0, len(v))
|
gl.uniform4fv.Invoke(js.Value(l), arr, 0, len(v))
|
||||||
} else {
|
} else {
|
||||||
gl.uniform4fv.Invoke(js.Value(l), arr.Call("subarray", 0, len(v)))
|
gl.uniform4fv.Invoke(js.Value(l), arr.Call("subarray", 0, len(v)))
|
||||||
}
|
}
|
||||||
case shaderir.Mat2:
|
case shaderir.Mat2:
|
||||||
|
arr := jsutil.TemporaryFloat32Array(len(v), uint32sToFloat32s(v))
|
||||||
if c.usesWebGL2() {
|
if c.usesWebGL2() {
|
||||||
gl.uniformMatrix2fv.Invoke(js.Value(l), false, arr, 0, len(v))
|
gl.uniformMatrix2fv.Invoke(js.Value(l), false, arr, 0, len(v))
|
||||||
} else {
|
} else {
|
||||||
gl.uniformMatrix2fv.Invoke(js.Value(l), false, arr.Call("subarray", 0, len(v)))
|
gl.uniformMatrix2fv.Invoke(js.Value(l), false, arr.Call("subarray", 0, len(v)))
|
||||||
}
|
}
|
||||||
case shaderir.Mat3:
|
case shaderir.Mat3:
|
||||||
|
arr := jsutil.TemporaryFloat32Array(len(v), uint32sToFloat32s(v))
|
||||||
if c.usesWebGL2() {
|
if c.usesWebGL2() {
|
||||||
gl.uniformMatrix3fv.Invoke(js.Value(l), false, arr, 0, len(v))
|
gl.uniformMatrix3fv.Invoke(js.Value(l), false, arr, 0, len(v))
|
||||||
} else {
|
} else {
|
||||||
gl.uniformMatrix3fv.Invoke(js.Value(l), false, arr.Call("subarray", 0, len(v)))
|
gl.uniformMatrix3fv.Invoke(js.Value(l), false, arr.Call("subarray", 0, len(v)))
|
||||||
}
|
}
|
||||||
case shaderir.Mat4:
|
case shaderir.Mat4:
|
||||||
|
arr := jsutil.TemporaryFloat32Array(len(v), uint32sToFloat32s(v))
|
||||||
if c.usesWebGL2() {
|
if c.usesWebGL2() {
|
||||||
gl.uniformMatrix4fv.Invoke(js.Value(l), false, arr, 0, len(v))
|
gl.uniformMatrix4fv.Invoke(js.Value(l), false, arr, 0, len(v))
|
||||||
} else {
|
} else {
|
||||||
|
@ -31,6 +31,8 @@ func Ptr(data any) unsafe.Pointer {
|
|||||||
addr = unsafe.Pointer(&v[0])
|
addr = unsafe.Pointer(&v[0])
|
||||||
case []uint16:
|
case []uint16:
|
||||||
addr = unsafe.Pointer(&v[0])
|
addr = unsafe.Pointer(&v[0])
|
||||||
|
case []uint32:
|
||||||
|
addr = unsafe.Pointer(&v[0])
|
||||||
case []float32:
|
case []float32:
|
||||||
addr = unsafe.Pointer(&v[0])
|
addr = unsafe.Pointer(&v[0])
|
||||||
default:
|
default:
|
||||||
|
@ -163,8 +163,9 @@ package gl
|
|||||||
// typedef void (APIENTRYP GPTEXIMAGE2D)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void * pixels);
|
// typedef void (APIENTRYP GPTEXIMAGE2D)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void * pixels);
|
||||||
// typedef void (APIENTRYP GPTEXPARAMETERI)(GLenum target, GLenum pname, GLint param);
|
// typedef void (APIENTRYP GPTEXPARAMETERI)(GLenum target, GLenum pname, GLint param);
|
||||||
// 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 GPUNIFORM1I)(GLint location, GLint v0);
|
|
||||||
// typedef void (APIENTRYP GPUNIFORM1FV)(GLint location, GLsizei count, const GLfloat * value);
|
// typedef void (APIENTRYP GPUNIFORM1FV)(GLint location, GLsizei count, const GLfloat * value);
|
||||||
|
// typedef void (APIENTRYP GPUNIFORM1I)(GLint location, GLint v0);
|
||||||
|
// typedef void (APIENTRYP GPUNIFORM1IV)(GLint location, GLsizei count, const GLint * 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 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);
|
||||||
@ -382,10 +383,13 @@ package gl
|
|||||||
// static void glowTexSubImage2D(GPTEXSUBIMAGE2D fnptr, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void * pixels) {
|
// static void glowTexSubImage2D(GPTEXSUBIMAGE2D fnptr, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void * pixels) {
|
||||||
// (*fnptr)(target, level, xoffset, yoffset, width, height, format, type, pixels);
|
// (*fnptr)(target, level, xoffset, yoffset, width, height, format, type, pixels);
|
||||||
// }
|
// }
|
||||||
|
// static void glowUniform1fv(GPUNIFORM1FV fnptr, GLint location, GLsizei count, const GLfloat * value) {
|
||||||
|
// (*fnptr)(location, count, value);
|
||||||
|
// }
|
||||||
// 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) {
|
// static void glowUniform1iv(GPUNIFORM1IV fnptr, GLint location, GLsizei count, const GLint * value) {
|
||||||
// (*fnptr)(location, count, 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) {
|
||||||
@ -494,8 +498,9 @@ var (
|
|||||||
gpTexImage2D C.GPTEXIMAGE2D
|
gpTexImage2D C.GPTEXIMAGE2D
|
||||||
gpTexParameteri C.GPTEXPARAMETERI
|
gpTexParameteri C.GPTEXPARAMETERI
|
||||||
gpTexSubImage2D C.GPTEXSUBIMAGE2D
|
gpTexSubImage2D C.GPTEXSUBIMAGE2D
|
||||||
gpUniform1i C.GPUNIFORM1I
|
|
||||||
gpUniform1fv C.GPUNIFORM1FV
|
gpUniform1fv C.GPUNIFORM1FV
|
||||||
|
gpUniform1i C.GPUNIFORM1I
|
||||||
|
gpUniform1iv C.GPUNIFORM1IV
|
||||||
gpUniform2fv C.GPUNIFORM2FV
|
gpUniform2fv C.GPUNIFORM2FV
|
||||||
gpUniform3fv C.GPUNIFORM3FV
|
gpUniform3fv C.GPUNIFORM3FV
|
||||||
gpUniform4fv C.GPUNIFORM4FV
|
gpUniform4fv C.GPUNIFORM4FV
|
||||||
@ -791,12 +796,16 @@ func TexSubImage2D(target uint32, level int32, xoffset int32, yoffset int32, wid
|
|||||||
C.glowTexSubImage2D(gpTexSubImage2D, (C.GLenum)(target), (C.GLint)(level), (C.GLint)(xoffset), (C.GLint)(yoffset), (C.GLsizei)(width), (C.GLsizei)(height), (C.GLenum)(format), (C.GLenum)(xtype), pixels)
|
C.glowTexSubImage2D(gpTexSubImage2D, (C.GLenum)(target), (C.GLint)(level), (C.GLint)(xoffset), (C.GLint)(yoffset), (C.GLsizei)(width), (C.GLsizei)(height), (C.GLenum)(format), (C.GLenum)(xtype), pixels)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Uniform1fv(location int32, count int32, value *float32) {
|
||||||
|
C.glowUniform1fv(gpUniform1fv, (C.GLint)(location), (C.GLsizei)(count), (*C.GLfloat)(unsafe.Pointer(value)))
|
||||||
|
}
|
||||||
|
|
||||||
func Uniform1i(location int32, v0 int32) {
|
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) {
|
func Uniform1iv(location int32, count int32, value *int32) {
|
||||||
C.glowUniform1fv(gpUniform1fv, (C.GLint)(location), (C.GLsizei)(count), (*C.GLfloat)(unsafe.Pointer(value)))
|
C.glowUniform1iv(gpUniform1iv, (C.GLint)(location), (C.GLsizei)(count), (*C.GLint)(unsafe.Pointer(value)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func Uniform2fv(location int32, count int32, value *float32) {
|
func Uniform2fv(location int32, count int32, value *float32) {
|
||||||
@ -1044,13 +1053,17 @@ func InitWithProcAddrFunc(getProcAddr func(name string) unsafe.Pointer) error {
|
|||||||
if gpTexSubImage2D == nil {
|
if gpTexSubImage2D == nil {
|
||||||
return errors.New("gl: glTexSubImage2D is missing")
|
return errors.New("gl: glTexSubImage2D is missing")
|
||||||
}
|
}
|
||||||
|
gpUniform1fv = (C.GPUNIFORM1FV)(getProcAddr("glUniform1fv"))
|
||||||
|
if gpUniform1fv == nil {
|
||||||
|
return errors.New("gl: glUniform1fv is missing")
|
||||||
|
}
|
||||||
gpUniform1i = (C.GPUNIFORM1I)(getProcAddr("glUniform1i"))
|
gpUniform1i = (C.GPUNIFORM1I)(getProcAddr("glUniform1i"))
|
||||||
if gpUniform1i == nil {
|
if gpUniform1i == nil {
|
||||||
return errors.New("gl: glUniform1i is missing")
|
return errors.New("gl: glUniform1i is missing")
|
||||||
}
|
}
|
||||||
gpUniform1fv = (C.GPUNIFORM1FV)(getProcAddr("glUniform1fv"))
|
gpUniform1iv = (C.GPUNIFORM1IV)(getProcAddr("glUniform1iv"))
|
||||||
if gpUniform1fv == nil {
|
if gpUniform1iv == nil {
|
||||||
return errors.New("gl: glUniform1fv is missing")
|
return errors.New("gl: glUniform1iv is missing")
|
||||||
}
|
}
|
||||||
gpUniform2fv = (C.GPUNIFORM2FV)(getProcAddr("glUniform2fv"))
|
gpUniform2fv = (C.GPUNIFORM2FV)(getProcAddr("glUniform2fv"))
|
||||||
if gpUniform2fv == nil {
|
if gpUniform2fv == nil {
|
||||||
|
@ -81,8 +81,9 @@ var (
|
|||||||
gpTexImage2D uintptr
|
gpTexImage2D uintptr
|
||||||
gpTexParameteri uintptr
|
gpTexParameteri uintptr
|
||||||
gpTexSubImage2D uintptr
|
gpTexSubImage2D uintptr
|
||||||
gpUniform1i uintptr
|
|
||||||
gpUniform1fv uintptr
|
gpUniform1fv uintptr
|
||||||
|
gpUniform1i uintptr
|
||||||
|
gpUniform1iv uintptr
|
||||||
gpUniform2fv uintptr
|
gpUniform2fv uintptr
|
||||||
gpUniform3fv uintptr
|
gpUniform3fv uintptr
|
||||||
gpUniform4fv uintptr
|
gpUniform4fv uintptr
|
||||||
@ -378,12 +379,16 @@ func TexSubImage2D(target uint32, level int32, xoffset int32, yoffset int32, wid
|
|||||||
purego.SyscallN(gpTexSubImage2D, uintptr(target), uintptr(level), uintptr(xoffset), uintptr(yoffset), uintptr(width), uintptr(height), uintptr(format), uintptr(xtype), uintptr(pixels))
|
purego.SyscallN(gpTexSubImage2D, uintptr(target), uintptr(level), uintptr(xoffset), uintptr(yoffset), uintptr(width), uintptr(height), uintptr(format), uintptr(xtype), uintptr(pixels))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Uniform1fv(location int32, count int32, value *float32) {
|
||||||
|
purego.SyscallN(gpUniform1fv, uintptr(location), uintptr(count), uintptr(unsafe.Pointer(value)))
|
||||||
|
}
|
||||||
|
|
||||||
func Uniform1i(location int32, v0 int32) {
|
func Uniform1i(location int32, v0 int32) {
|
||||||
purego.SyscallN(gpUniform1i, uintptr(location), uintptr(v0))
|
purego.SyscallN(gpUniform1i, uintptr(location), uintptr(v0))
|
||||||
}
|
}
|
||||||
|
|
||||||
func Uniform1fv(location int32, count int32, value *float32) {
|
func Uniform1iv(location int32, count int32, value *int32) {
|
||||||
purego.SyscallN(gpUniform1fv, uintptr(location), uintptr(count), uintptr(unsafe.Pointer(value)))
|
purego.SyscallN(gpUniform1iv, uintptr(location), uintptr(count), uintptr(unsafe.Pointer(value)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func Uniform2fv(location int32, count int32, value *float32) {
|
func Uniform2fv(location int32, count int32, value *float32) {
|
||||||
@ -631,13 +636,17 @@ func InitWithProcAddrFunc(getProcAddr func(name string) uintptr) error {
|
|||||||
if gpTexSubImage2D == 0 {
|
if gpTexSubImage2D == 0 {
|
||||||
return errors.New("gl: glTexSubImage2D is missing")
|
return errors.New("gl: glTexSubImage2D is missing")
|
||||||
}
|
}
|
||||||
|
gpUniform1fv = getProcAddr("glUniform1fv")
|
||||||
|
if gpUniform1fv == 0 {
|
||||||
|
return errors.New("gl: glUniform1fv is missing")
|
||||||
|
}
|
||||||
gpUniform1i = getProcAddr("glUniform1i")
|
gpUniform1i = getProcAddr("glUniform1i")
|
||||||
if gpUniform1i == 0 {
|
if gpUniform1i == 0 {
|
||||||
return errors.New("gl: glUniform1i is missing")
|
return errors.New("gl: glUniform1i is missing")
|
||||||
}
|
}
|
||||||
gpUniform1fv = getProcAddr("glUniform1fv")
|
gpUniform1iv = getProcAddr("glUniform1iv")
|
||||||
if gpUniform1fv == 0 {
|
if gpUniform1iv == 0 {
|
||||||
return errors.New("gl: glUniform1fv is missing")
|
return errors.New("gl: glUniform1iv is missing")
|
||||||
}
|
}
|
||||||
gpUniform2fv = getProcAddr("glUniform2fv")
|
gpUniform2fv = getProcAddr("glUniform2fv")
|
||||||
if gpUniform2fv == 0 {
|
if gpUniform2fv == 0 {
|
||||||
|
@ -80,10 +80,11 @@ type gl struct {
|
|||||||
texSubImage2D js.Value
|
texSubImage2D js.Value
|
||||||
texParameteri js.Value
|
texParameteri js.Value
|
||||||
uniform1fv js.Value
|
uniform1fv js.Value
|
||||||
|
uniform1i js.Value
|
||||||
|
uniform1iv js.Value
|
||||||
uniform2fv js.Value
|
uniform2fv js.Value
|
||||||
uniform3fv js.Value
|
uniform3fv js.Value
|
||||||
uniform4fv js.Value
|
uniform4fv js.Value
|
||||||
uniform1i js.Value
|
|
||||||
uniformMatrix2fv js.Value
|
uniformMatrix2fv js.Value
|
||||||
uniformMatrix3fv js.Value
|
uniformMatrix3fv js.Value
|
||||||
uniformMatrix4fv js.Value
|
uniformMatrix4fv js.Value
|
||||||
@ -156,10 +157,11 @@ func (c *context) newGL(v js.Value) *gl {
|
|||||||
texSubImage2D: v.Get("texSubImage2D").Call("bind", v),
|
texSubImage2D: v.Get("texSubImage2D").Call("bind", v),
|
||||||
texParameteri: v.Get("texParameteri").Call("bind", v),
|
texParameteri: v.Get("texParameteri").Call("bind", v),
|
||||||
uniform1fv: v.Get("uniform1fv").Call("bind", v),
|
uniform1fv: v.Get("uniform1fv").Call("bind", v),
|
||||||
|
uniform1i: v.Get("uniform1i").Call("bind", v),
|
||||||
|
uniform1iv: v.Get("uniform1iv").Call("bind", v),
|
||||||
uniform2fv: v.Get("uniform2fv").Call("bind", v),
|
uniform2fv: v.Get("uniform2fv").Call("bind", v),
|
||||||
uniform3fv: v.Get("uniform3fv").Call("bind", v),
|
uniform3fv: v.Get("uniform3fv").Call("bind", v),
|
||||||
uniform4fv: v.Get("uniform4fv").Call("bind", v),
|
uniform4fv: v.Get("uniform4fv").Call("bind", v),
|
||||||
uniform1i: v.Get("uniform1i").Call("bind", v),
|
|
||||||
uniformMatrix2fv: v.Get("uniformMatrix2fv").Call("bind", v),
|
uniformMatrix2fv: v.Get("uniformMatrix2fv").Call("bind", v),
|
||||||
uniformMatrix3fv: v.Get("uniformMatrix3fv").Call("bind", v),
|
uniformMatrix3fv: v.Get("uniformMatrix3fv").Call("bind", v),
|
||||||
uniformMatrix4fv: v.Get("uniformMatrix4fv").Call("bind", v),
|
uniformMatrix4fv: v.Get("uniformMatrix4fv").Call("bind", v),
|
||||||
|
@ -332,6 +332,10 @@ func (DefaultContext) Uniform1i(location int32, v0 int32) {
|
|||||||
C.glUniform1i(C.GLint(location), C.GLint(v0))
|
C.glUniform1i(C.GLint(location), C.GLint(v0))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (DefaultContext) Uniform1iv(location int32, value []int32) {
|
||||||
|
C.glUniform1iv(C.GLint(location), C.GLsizei(len(value)), (*C.GLint)(unsafe.Pointer(&value[0])))
|
||||||
|
}
|
||||||
|
|
||||||
func (DefaultContext) Uniform2fv(location int32, value []float32) {
|
func (DefaultContext) Uniform2fv(location int32, value []float32) {
|
||||||
C.glUniform2fv(C.GLint(location), C.GLsizei(len(value)/2), (*C.GLfloat)(unsafe.Pointer(&value[0])))
|
C.glUniform2fv(C.GLint(location), C.GLsizei(len(value)/2), (*C.GLfloat)(unsafe.Pointer(&value[0])))
|
||||||
}
|
}
|
||||||
|
@ -306,6 +306,10 @@ func (g *GomobileContext) Uniform1i(location int32, v0 int32) {
|
|||||||
g.ctx.Uniform1i(gl.Uniform{Value: location}, int(v0))
|
g.ctx.Uniform1i(gl.Uniform{Value: location}, int(v0))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (g *GomobileContext) Uniform1iv(location int32, value []int32) {
|
||||||
|
g.ctx.Uniform1iv(gl.Uniform{Value: location}, value)
|
||||||
|
}
|
||||||
|
|
||||||
func (g *GomobileContext) Uniform2fv(location int32, value []float32) {
|
func (g *GomobileContext) Uniform2fv(location int32, value []float32) {
|
||||||
g.ctx.Uniform2fv(gl.Uniform{Value: location}, value)
|
g.ctx.Uniform2fv(gl.Uniform{Value: location}, value)
|
||||||
}
|
}
|
||||||
|
@ -76,6 +76,7 @@ type Context interface {
|
|||||||
TexSubImage2D(target uint32, level int32, xoffset int32, yoffset int32, width int32, height int32, format uint32, xtype uint32, pixels []byte)
|
TexSubImage2D(target uint32, level int32, xoffset int32, yoffset int32, width int32, height int32, format uint32, xtype uint32, pixels []byte)
|
||||||
Uniform1fv(location int32, value []float32)
|
Uniform1fv(location int32, value []float32)
|
||||||
Uniform1i(location int32, v0 int32)
|
Uniform1i(location int32, v0 int32)
|
||||||
|
Uniform1iv(location int32, value []int32)
|
||||||
Uniform2fv(location int32, value []float32)
|
Uniform2fv(location int32, value []float32)
|
||||||
Uniform3fv(location int32, value []float32)
|
Uniform3fv(location int32, value []float32)
|
||||||
Uniform4fv(location int32, value []float32)
|
Uniform4fv(location int32, value []float32)
|
||||||
|
@ -223,7 +223,7 @@ func (g *Graphics) useProgram(program program, uniforms []uniformVariable, textu
|
|||||||
if u.value == nil {
|
if u.value == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if got, expected := len(u.value), u.typ.FloatCount(); got != expected {
|
if got, expected := len(u.value), u.typ.Uint32Count(); got != expected {
|
||||||
// Copy a shaderir.Type value once. Do not pass u.typ directly to fmt.Errorf arguments, or
|
// Copy a shaderir.Type value once. Do not pass u.typ directly to fmt.Errorf arguments, or
|
||||||
// the value u would be allocated on heap.
|
// the value u would be allocated on heap.
|
||||||
typ := u.typ
|
typ := u.typ
|
||||||
@ -234,7 +234,7 @@ func (g *Graphics) useProgram(program program, uniforms []uniformVariable, textu
|
|||||||
if ok && areSameUint32Array(cached, u.value) {
|
if ok && areSameUint32Array(cached, u.value) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
g.context.uniformFloats(program, u.name, uint32sToFloat32s(u.value), u.typ)
|
g.context.uniforms(program, u.name, u.value, u.typ)
|
||||||
if g.state.lastUniforms == nil {
|
if g.state.lastUniforms == nil {
|
||||||
g.state.lastUniforms = map[string][]uint32{}
|
g.state.lastUniforms = map[string][]uint32{}
|
||||||
}
|
}
|
||||||
@ -284,3 +284,7 @@ loop:
|
|||||||
func uint32sToFloat32s(s []uint32) []float32 {
|
func uint32sToFloat32s(s []uint32) []float32 {
|
||||||
return unsafe.Slice((*float32)(unsafe.Pointer(&s[0])), len(s))
|
return unsafe.Slice((*float32)(unsafe.Pointer(&s[0])), len(s))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func uint32sToInt32s(s []uint32) []int32 {
|
||||||
|
return unsafe.Slice((*int32)(unsafe.Pointer(&s[0])), len(s))
|
||||||
|
}
|
||||||
|
@ -23,6 +23,7 @@ var (
|
|||||||
arrayBuffer = js.Global().Get("ArrayBuffer")
|
arrayBuffer = js.Global().Get("ArrayBuffer")
|
||||||
uint8Array = js.Global().Get("Uint8Array")
|
uint8Array = js.Global().Get("Uint8Array")
|
||||||
float32Array = js.Global().Get("Float32Array")
|
float32Array = js.Global().Get("Float32Array")
|
||||||
|
int32Array = js.Global().Get("Int32Array")
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -38,6 +39,9 @@ var (
|
|||||||
|
|
||||||
// temporaryFloat32Array is a Float32ArrayBuffer whose underlying buffer is always temporaryArrayBuffer.
|
// temporaryFloat32Array is a Float32ArrayBuffer whose underlying buffer is always temporaryArrayBuffer.
|
||||||
temporaryFloat32Array = float32Array.New(temporaryArrayBuffer)
|
temporaryFloat32Array = float32Array.New(temporaryArrayBuffer)
|
||||||
|
|
||||||
|
// temporaryInt32Array is a Float32ArrayBuffer whose underlying buffer is always temporaryArrayBuffer.
|
||||||
|
temporaryInt32Array = int32Array.New(temporaryArrayBuffer)
|
||||||
)
|
)
|
||||||
|
|
||||||
func ensureTemporaryArrayBufferSize(byteLength int) {
|
func ensureTemporaryArrayBufferSize(byteLength int) {
|
||||||
@ -49,6 +53,7 @@ func ensureTemporaryArrayBufferSize(byteLength int) {
|
|||||||
temporaryArrayBuffer = arrayBuffer.New(bufl)
|
temporaryArrayBuffer = arrayBuffer.New(bufl)
|
||||||
temporaryUint8Array = uint8Array.New(temporaryArrayBuffer)
|
temporaryUint8Array = uint8Array.New(temporaryArrayBuffer)
|
||||||
temporaryFloat32Array = float32Array.New(temporaryArrayBuffer)
|
temporaryFloat32Array = float32Array.New(temporaryArrayBuffer)
|
||||||
|
temporaryInt32Array = int32Array.New(temporaryArrayBuffer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,7 +71,7 @@ func TemporaryUint8ArrayFromUint8Slice(minLength int, data []uint8) js.Value {
|
|||||||
// data must be a slice of a numeric type for initialization, or nil if you don't need initialization.
|
// data must be a slice of a numeric type for initialization, or nil if you don't need initialization.
|
||||||
func TemporaryUint8ArrayFromUint16Slice(minLength int, data []uint16) js.Value {
|
func TemporaryUint8ArrayFromUint16Slice(minLength int, data []uint16) js.Value {
|
||||||
ensureTemporaryArrayBufferSize(minLength * 2)
|
ensureTemporaryArrayBufferSize(minLength * 2)
|
||||||
copyUint16SliceToTemporaryArrayBuffer(data)
|
copySliceToTemporaryArrayBuffer(data)
|
||||||
return temporaryUint8Array
|
return temporaryUint8Array
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,7 +80,7 @@ func TemporaryUint8ArrayFromUint16Slice(minLength int, data []uint16) js.Value {
|
|||||||
// data must be a slice of a numeric type for initialization, or nil if you don't need initialization.
|
// data must be a slice of a numeric type for initialization, or nil if you don't need initialization.
|
||||||
func TemporaryUint8ArrayFromFloat32Slice(minLength int, data []float32) js.Value {
|
func TemporaryUint8ArrayFromFloat32Slice(minLength int, data []float32) js.Value {
|
||||||
ensureTemporaryArrayBufferSize(minLength * 4)
|
ensureTemporaryArrayBufferSize(minLength * 4)
|
||||||
copyFloat32SliceToTemporaryArrayBuffer(data)
|
copySliceToTemporaryArrayBuffer(data)
|
||||||
return temporaryUint8Array
|
return temporaryUint8Array
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,6 +89,15 @@ func TemporaryUint8ArrayFromFloat32Slice(minLength int, data []float32) js.Value
|
|||||||
// data must be a slice of a numeric type for initialization, or nil if you don't need initialization.
|
// data must be a slice of a numeric type for initialization, or nil if you don't need initialization.
|
||||||
func TemporaryFloat32Array(minLength int, data []float32) js.Value {
|
func TemporaryFloat32Array(minLength int, data []float32) js.Value {
|
||||||
ensureTemporaryArrayBufferSize(minLength * 4)
|
ensureTemporaryArrayBufferSize(minLength * 4)
|
||||||
copyFloat32SliceToTemporaryArrayBuffer(data)
|
copySliceToTemporaryArrayBuffer(data)
|
||||||
return temporaryFloat32Array
|
return temporaryFloat32Array
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TemporaryInt32Array returns a Int32Array whose length is at least minLength.
|
||||||
|
// Be careful that the length can exceed the given minLength.
|
||||||
|
// data must be a slice of a numeric type for initialization, or nil if you don't need initialization.
|
||||||
|
func TemporaryInt32Array(minLength int, data []int32) js.Value {
|
||||||
|
ensureTemporaryArrayBufferSize(minLength * 4)
|
||||||
|
copySliceToTemporaryArrayBuffer(data)
|
||||||
|
return temporaryInt32Array
|
||||||
|
}
|
||||||
|
@ -27,18 +27,14 @@ func copyUint8SliceToTemporaryArrayBuffer(src []uint8) {
|
|||||||
js.CopyBytesToJS(temporaryUint8Array, src)
|
js.CopyBytesToJS(temporaryUint8Array, src)
|
||||||
}
|
}
|
||||||
|
|
||||||
func copyUint16SliceToTemporaryArrayBuffer(src []uint16) {
|
type numeric interface {
|
||||||
if len(src) == 0 {
|
~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | ~float32 | ~float64
|
||||||
return
|
|
||||||
}
|
|
||||||
js.CopyBytesToJS(temporaryUint8Array, unsafe.Slice((*byte)(unsafe.Pointer(&src[0])), len(src)*2))
|
|
||||||
runtime.KeepAlive(src)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func copyFloat32SliceToTemporaryArrayBuffer(src []float32) {
|
func copySliceToTemporaryArrayBuffer[T numeric](src []T) {
|
||||||
if len(src) == 0 {
|
if len(src) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
js.CopyBytesToJS(temporaryUint8Array, unsafe.Slice((*byte)(unsafe.Pointer(&src[0])), len(src)*4))
|
js.CopyBytesToJS(temporaryUint8Array, unsafe.Slice((*byte)(unsafe.Pointer(&src[0])), len(src)*int(unsafe.Sizeof(T(0)))))
|
||||||
runtime.KeepAlive(src)
|
runtime.KeepAlive(src)
|
||||||
}
|
}
|
||||||
|
@ -59,6 +59,7 @@ func FragmentPrelude(version GLSLVersion) string {
|
|||||||
}
|
}
|
||||||
prelude := prefix + `#if defined(GL_ES)
|
prelude := prefix + `#if defined(GL_ES)
|
||||||
precision highp float;
|
precision highp float;
|
||||||
|
precision highp int;
|
||||||
#else
|
#else
|
||||||
#define lowp
|
#define lowp
|
||||||
#define mediump
|
#define mediump
|
||||||
|
@ -43,6 +43,9 @@ func calculateMemoryOffsets(uniforms []shaderir.Type) []int {
|
|||||||
case shaderir.Float:
|
case shaderir.Float:
|
||||||
offsets = append(offsets, head)
|
offsets = append(offsets, head)
|
||||||
head += 4
|
head += 4
|
||||||
|
case shaderir.Int:
|
||||||
|
offsets = append(offsets, head)
|
||||||
|
head += 4
|
||||||
case shaderir.Vec2:
|
case shaderir.Vec2:
|
||||||
if head%boundaryInBytes >= 4*3 {
|
if head%boundaryInBytes >= 4*3 {
|
||||||
head = align(head)
|
head = align(head)
|
||||||
@ -79,7 +82,7 @@ func calculateMemoryOffsets(uniforms []shaderir.Type) []int {
|
|||||||
// TODO: What if the array has 2 or more dimensions?
|
// TODO: What if the array has 2 or more dimensions?
|
||||||
head = align(head)
|
head = align(head)
|
||||||
offsets = append(offsets, head)
|
offsets = append(offsets, head)
|
||||||
n := u.Sub[0].FloatCount()
|
n := u.Sub[0].Uint32Count()
|
||||||
switch u.Sub[0].Main {
|
switch u.Sub[0].Main {
|
||||||
case shaderir.Mat2:
|
case shaderir.Mat2:
|
||||||
n = 6
|
n = 6
|
||||||
@ -95,7 +98,7 @@ func calculateMemoryOffsets(uniforms []shaderir.Type) []int {
|
|||||||
// TODO: Implement this
|
// TODO: Implement this
|
||||||
panic("hlsl: offset for a struct is not implemented yet")
|
panic("hlsl: offset for a struct is not implemented yet")
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("hlsl: unexpected type: %d", u.Main))
|
panic(fmt.Sprintf("hlsl: unexpected type: %s", u.String()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ func (t *Type) String() string {
|
|||||||
case Mat4:
|
case Mat4:
|
||||||
return "mat4"
|
return "mat4"
|
||||||
case Array:
|
case Array:
|
||||||
return fmt.Sprintf("%s[%d]", t.Sub[0].String(), t.Length)
|
return fmt.Sprintf("[%d]%s", t.Length, t.Sub[0].String())
|
||||||
case Struct:
|
case Struct:
|
||||||
str := "struct{"
|
str := "struct{"
|
||||||
sub := make([]string, 0, len(t.Sub))
|
sub := make([]string, 0, len(t.Sub))
|
||||||
@ -81,8 +81,10 @@ func (t *Type) String() string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Type) FloatCount() int {
|
func (t *Type) Uint32Count() int {
|
||||||
switch t.Main {
|
switch t.Main {
|
||||||
|
case Int:
|
||||||
|
return 1
|
||||||
case Float:
|
case Float:
|
||||||
return 1
|
return 1
|
||||||
case Vec2:
|
case Vec2:
|
||||||
@ -98,7 +100,7 @@ func (t *Type) FloatCount() int {
|
|||||||
case Mat4:
|
case Mat4:
|
||||||
return 16
|
return 16
|
||||||
case Array:
|
case Array:
|
||||||
return t.Length * t.Sub[0].FloatCount()
|
return t.Length * t.Sub[0].Uint32Count()
|
||||||
default: // TODO: Parse a struct correctly
|
default: // TODO: Parse a struct correctly
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ package ui
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten/v2/internal/mipmap"
|
"github.com/hajimehoshi/ebiten/v2/internal/mipmap"
|
||||||
@ -48,17 +49,37 @@ func (s *Shader) MarkDisposed() {
|
|||||||
func (s *Shader) ConvertUniforms(uniforms map[string]any) [][]uint32 {
|
func (s *Shader) ConvertUniforms(uniforms map[string]any) [][]uint32 {
|
||||||
nameToU32s := map[string][]uint32{}
|
nameToU32s := map[string][]uint32{}
|
||||||
for name, v := range uniforms {
|
for name, v := range uniforms {
|
||||||
switch v := v.(type) {
|
v := reflect.ValueOf(v)
|
||||||
case float32:
|
t := v.Type()
|
||||||
nameToU32s[name] = []uint32{math.Float32bits(v)}
|
switch t.Kind() {
|
||||||
case []float32:
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
u32s := make([]uint32, len(v))
|
nameToU32s[name] = []uint32{uint32(v.Int())}
|
||||||
for i := range v {
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||||
u32s[i] = math.Float32bits(v[i])
|
nameToU32s[name] = []uint32{uint32(v.Uint())}
|
||||||
|
case reflect.Float32, reflect.Float64:
|
||||||
|
nameToU32s[name] = []uint32{math.Float32bits(float32(v.Float()))}
|
||||||
|
case reflect.Slice:
|
||||||
|
// TODO: Allow reflect.Array (#2448)
|
||||||
|
u32s := make([]uint32, v.Len())
|
||||||
|
switch t.Elem().Kind() {
|
||||||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
|
for i := range u32s {
|
||||||
|
u32s[i] = uint32(v.Index(i).Int())
|
||||||
|
}
|
||||||
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||||
|
for i := range u32s {
|
||||||
|
u32s[i] = uint32(v.Index(i).Uint())
|
||||||
|
}
|
||||||
|
case reflect.Float32, reflect.Float64:
|
||||||
|
for i := range u32s {
|
||||||
|
u32s[i] = math.Float32bits(float32(v.Index(i).Float()))
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("ebiten: unexpected uniform value type: %s (%s)", name, v.Kind().String()))
|
||||||
}
|
}
|
||||||
nameToU32s[name] = u32s
|
nameToU32s[name] = u32s
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("ebiten: unexpected uniform value type: %s, %T", name, v))
|
panic(fmt.Sprintf("ebiten: unexpected uniform value type: %s (%s)", name, v.Kind().String()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,7 +105,7 @@ func (s *Shader) ConvertUniforms(uniforms map[string]any) [][]uint32 {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
t := s.uniformNameToType[name]
|
t := s.uniformNameToType[name]
|
||||||
us[idx] = make([]uint32, t.FloatCount())
|
us[idx] = make([]uint32, t.Uint32Count())
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Panic if uniforms include an invalid name
|
// TODO: Panic if uniforms include an invalid name
|
||||||
|
113
shader_test.go
113
shader_test.go
@ -548,10 +548,13 @@ func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
|
|||||||
const w, h = 1, 1
|
const w, h = 1, 1
|
||||||
|
|
||||||
dst := ebiten.NewImage(w, h)
|
dst := ebiten.NewImage(w, h)
|
||||||
|
defer dst.Dispose()
|
||||||
|
|
||||||
s, err := ebiten.NewShader([]byte(shader.Shader))
|
s, err := ebiten.NewShader([]byte(shader.Shader))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
defer s.Dispose()
|
||||||
|
|
||||||
op := &ebiten.DrawRectShaderOptions{}
|
op := &ebiten.DrawRectShaderOptions{}
|
||||||
op.Uniforms = shader.Uniforms
|
op.Uniforms = shader.Uniforms
|
||||||
@ -1269,3 +1272,113 @@ func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestShaderUniformInt(t *testing.T) {
|
||||||
|
const ints = `package main
|
||||||
|
|
||||||
|
var U0 int
|
||||||
|
var U1 int
|
||||||
|
var U2 int
|
||||||
|
var U3 int
|
||||||
|
|
||||||
|
func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
|
||||||
|
return vec4(float(U0)/255.0, float(U1)/255.0, float(U2)/255.0, float(U3)/255.0)
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
const intArray = `package main
|
||||||
|
|
||||||
|
var U [4]int
|
||||||
|
|
||||||
|
func Fragment(position vec4, texCoord vec2, color vec4) vec4 {
|
||||||
|
return vec4(float(U[0])/255.0, float(U[1])/255.0, float(U[2])/255.0, float(U[3])/255.0)
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
Name string
|
||||||
|
Uniforms map[string]any
|
||||||
|
Shader string
|
||||||
|
Want color.RGBA
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
Name: "0xff",
|
||||||
|
Uniforms: map[string]any{
|
||||||
|
"U0": 0xff,
|
||||||
|
"U1": 0xff,
|
||||||
|
"U2": 0xff,
|
||||||
|
"U3": 0xff,
|
||||||
|
},
|
||||||
|
Shader: ints,
|
||||||
|
Want: color.RGBA{0xff, 0xff, 0xff, 0xff},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "int",
|
||||||
|
Uniforms: map[string]any{
|
||||||
|
"U0": int8(0x24),
|
||||||
|
"U1": int16(0x3f),
|
||||||
|
"U2": int32(0x6a),
|
||||||
|
"U3": int64(0x88),
|
||||||
|
},
|
||||||
|
Shader: ints,
|
||||||
|
Want: color.RGBA{0x24, 0x3f, 0x6a, 0x88},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "uint",
|
||||||
|
Uniforms: map[string]any{
|
||||||
|
"U0": uint8(0x85),
|
||||||
|
"U1": uint16(0xa3),
|
||||||
|
"U2": uint32(0x08),
|
||||||
|
"U3": uint64(0xd3),
|
||||||
|
},
|
||||||
|
Shader: ints,
|
||||||
|
Want: color.RGBA{0x85, 0xa3, 0x08, 0xd3},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "0xff,array",
|
||||||
|
Uniforms: map[string]any{
|
||||||
|
"U": []int{0xff, 0xff, 0xff, 0xff},
|
||||||
|
},
|
||||||
|
Shader: intArray,
|
||||||
|
Want: color.RGBA{0xff, 0xff, 0xff, 0xff},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "int,array",
|
||||||
|
Uniforms: map[string]any{
|
||||||
|
"U": []int16{0x24, 0x3f, 0x6a, 0x88},
|
||||||
|
},
|
||||||
|
Shader: intArray,
|
||||||
|
Want: color.RGBA{0x24, 0x3f, 0x6a, 0x88},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "uint,array",
|
||||||
|
Uniforms: map[string]any{
|
||||||
|
"U": []uint8{0x85, 0xa3, 0x08, 0xd3},
|
||||||
|
},
|
||||||
|
Shader: intArray,
|
||||||
|
Want: color.RGBA{0x85, 0xa3, 0x08, 0xd3},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tc := range testCases {
|
||||||
|
tc := tc
|
||||||
|
t.Run(tc.Name, func(t *testing.T) {
|
||||||
|
const w, h = 1, 1
|
||||||
|
|
||||||
|
dst := ebiten.NewImage(w, h)
|
||||||
|
defer dst.Dispose()
|
||||||
|
|
||||||
|
s, err := ebiten.NewShader([]byte(tc.Shader))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer s.Dispose()
|
||||||
|
|
||||||
|
op := &ebiten.DrawRectShaderOptions{}
|
||||||
|
op.Uniforms = tc.Uniforms
|
||||||
|
dst.DrawRectShader(w, h, s, op)
|
||||||
|
if got, want := dst.At(0, 0).(color.RGBA), tc.Want; !sameColors(got, want, 1) {
|
||||||
|
t.Errorf("got: %v, want: %v", got, want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user