• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

Go で書き直した Ikemen


Commit MetaInfo

Revisionabf1f49b3c2f7ef567e8db46e36d07a3d193080f (tree)
Time2016-11-08 23:16:36
AuthorSUEHIRO <supersuehiro@user...>
CommiterSUEHIRO

Log Message

画像の表示テスト

Change Summary

Incremental Difference

--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,3 @@
11 /data
22 /go
3-/godoc.txt
43 /sound
--- a/run.sh
+++ b/run.sh
@@ -2,5 +2,5 @@
22 GOPATH=$PWD/go
33 export GOPATH
44 go fmt ./src/*.go
5-godoc -src ./src .* > godoc.txt
6-go generate ./src/*.go && GODEBUG=cgocheck=0 go run ./src/*.go
5+# godoc -src ./src .* > godoc.txt
6+go generate ./src/main.go && GODEBUG=cgocheck=0 go run ./src/*.go
--- a/src/common.go
+++ b/src/common.go
@@ -1,7 +1,17 @@
11 package main
22
3-type Error string
3+import "math"
44
5-func (e Error) Error() string {
6- return string(e)
5+func Abs(f float32) float32 {
6+ if f < 0 {
7+ return -f
8+ }
9+ return f
10+}
11+func IsFinite(f float32) bool {
12+ return math.Abs(float64(f)) <= math.MaxFloat64
713 }
14+
15+type Error string
16+
17+func (e Error) Error() string { return string(e) }
--- a/src/gen/gen.go
+++ b/src/gen/gen.go
@@ -4,6 +4,7 @@ import "os"
44
55 var AppendFunc = [...][2]string{
66 {"I", "int"},
7+ {"U32", "uint32"},
78 {"Pal", "[]uint32"},
89 }
910
--- a/src/generated.go
+++ b/src/generated.go
@@ -11,6 +11,17 @@ func AppendI(slice *[]int, data ...int) {
1111 *slice = (*slice)[:n]
1212 copy((*slice)[m:n], data)
1313 }
14+func AppendU32(slice *[]uint32, data ...uint32) {
15+ m := len(*slice)
16+ n := m + len(data)
17+ if n > cap(*slice) {
18+ newSlice := make([]uint32, n+n/4)
19+ copy(newSlice, *slice)
20+ *slice = newSlice
21+ }
22+ *slice = (*slice)[:n]
23+ copy((*slice)[m:n], data)
24+}
1425 func AppendPal(slice *[][]uint32, data ...[]uint32) {
1526 m := len(*slice)
1627 n := m + len(data)
--- a/src/image.go
+++ b/src/image.go
@@ -5,120 +5,14 @@ package main
55 import "C"
66 import (
77 "encoding/binary"
8+ "fmt"
89 "github.com/go-gl/gl/v2.1/gl"
9- "image"
10- "image/draw"
11- "image/png"
1210 "io"
1311 "os"
1412 "runtime"
15- "strings"
1613 "unsafe"
1714 )
1815
19-func gltest() {
20- vertShader := strings.Join([]string{
21- "void main(void){",
22- "gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;",
23- "gl_Position = ftransform();",
24- "}\x00"}, "")
25- fragShader := strings.Join([]string{
26- "uniform float a;",
27- "uniform sampler2D tex;",
28- "uniform sampler1D pal;",
29- "uniform int msk;",
30- "void main(void){",
31- "float r = texture2D(tex, gl_TexCoord[0].st).r;",
32- "vec4 c;",
33- "gl_FragColor =",
34- "int(255.0*r) == msk ? vec4(0.0)",
35- ": (c = texture1D(pal, r*0.9961), vec4(c.b, c.g, c.r, a));",
36- "}\x00"}, "")
37- fragShaderFc := strings.Join([]string{
38- "uniform float a;",
39- "uniform sampler2D tex;",
40- "uniform bool neg;",
41- "uniform float gray;",
42- "uniform vec3 add;",
43- "uniform vec3 mul;",
44- "void main(void){",
45- "vec4 c = texture2D(tex, gl_TexCoord[0].st);",
46- "if(neg) c.rgb = vec3(1.0) - c.rgb;",
47- "float gcol = (c.r + c.g + c.b) / 3.0;",
48- "c.r += (gcol - c.r) * gray + add.r;",
49- "c.g += (gcol - c.g) * gray + add.g;",
50- "c.b += (gcol - c.b) * gray + add.b;",
51- "c.rgb *= mul;",
52- "c.a *= a;",
53- "gl_FragColor = c;",
54- "}\x00"}, "")
55- fragShaderFcS := strings.Join([]string{
56- "uniform float a;",
57- "uniform sampler2D tex;",
58- "uniform vec3 color;",
59- "void main(void){",
60- "vec4 c = texture2D(tex, gl_TexCoord[0].st);",
61- "c.rgb = color * c.a;",
62- "c.a *= a;",
63- "gl_FragColor = c;",
64- "}\x00"}, "")
65- errLog := func(obl uintptr) error {
66- var size int32
67- gl.GetObjectParameterivARB(obl, gl.INFO_LOG_LENGTH, &size)
68- if size <= 0 {
69- return nil
70- }
71- var l int32
72- str := make([]byte, size+1)
73- gl.GetInfoLogARB(obl, size, &l, &str[0])
74- return Error(str[:l])
75- }
76- compile := func(shaderType uint32, src string) (shader uintptr) {
77- shader = gl.CreateShaderObjectARB(shaderType)
78- s, l := gl.Str(src), int32(len(src)-1)
79- gl.ShaderSourceARB(shader, 1, &s, &l)
80- gl.CompileShaderARB(shader)
81- var ok int32
82- gl.GetObjectParameterivARB(shader, gl.OBJECT_COMPILE_STATUS_ARB, &ok)
83- if ok == 0 {
84- chk(errLog(shader))
85- panic(Error("コンパイルエラー"))
86- }
87- return
88- }
89- link := func(v uintptr, f uintptr) (program uintptr) {
90- program = gl.CreateProgramObjectARB()
91- gl.AttachObjectARB(program, v)
92- gl.AttachObjectARB(program, f)
93- gl.LinkProgramARB(program)
94- var ok int32
95- gl.GetObjectParameterivARB(program, gl.OBJECT_LINK_STATUS_ARB, &ok)
96- if ok == 0 {
97- chk(errLog(program))
98- panic(Error("リンクエラー"))
99- }
100- return
101- }
102- vertObj := compile(gl.VERTEX_SHADER, vertShader)
103- fragObj := compile(gl.FRAGMENT_SHADER, fragShader)
104- shader := link(vertObj, fragObj)
105- gl.GetUniformLocationARB(shader, gl.Str("pal\x00"))
106- gl.GetUniformLocationARB(shader, gl.Str("msk\x00"))
107- gl.DeleteObjectARB(fragObj)
108- fragObj = compile(gl.FRAGMENT_SHADER, fragShaderFc)
109- shaderFc := link(vertObj, fragObj)
110- gl.GetUniformLocationARB(shaderFc, gl.Str("neg\x00"))
111- gl.GetUniformLocationARB(shaderFc, gl.Str("gray\x00"))
112- gl.GetUniformLocationARB(shaderFc, gl.Str("add\x00"))
113- gl.GetUniformLocationARB(shaderFc, gl.Str("mul\x00"))
114- gl.DeleteObjectARB(fragObj)
115- fragObj = compile(gl.FRAGMENT_SHADER, fragShaderFcS)
116- shaderFcS := link(vertObj, fragObj)
117- gl.GetUniformLocationARB(shaderFcS, gl.Str("color\x00"))
118- gl.DeleteObjectARB(fragObj)
119- gl.DeleteObjectARB(vertObj)
120-}
121-
12216 type Texture uint32
12317
12418 func textureFinalizer(t *Texture) {
@@ -128,29 +22,24 @@ func textureFinalizer(t *Texture) {
12822 }
12923 func NewTexture() (t *Texture) {
13024 t = new(Texture)
25+ gl.GenTextures(1, (*uint32)(t))
13126 runtime.SetFinalizer(t, textureFinalizer)
13227 return
13328 }
134-func (t *Texture) FromImageRGBA(rgba *image.RGBA) {
135- gl.BindTexture(gl.TEXTURE_2D, uint32(*t))
136- gl.PixelStorei(gl.UNPACK_ALIGNMENT, 1)
137- gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA,
138- int32(rgba.Bounds().Dx()), int32(rgba.Bounds().Dy()),
139- 0, gl.RGBA, gl.UNSIGNED_BYTE, unsafe.Pointer(&rgba.Pix[0]))
140- gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
141- gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
142- gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP)
143- gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP)
144-}
145-func (t *Texture) FromImage(im image.Image) {
146- switch trueim := im.(type) {
147- case *image.RGBA:
148- t.FromImageRGBA(trueim)
149- default:
150- copy := image.NewRGBA(trueim.Bounds())
151- draw.Draw(copy, trueim.Bounds(), trueim, image.Pt(0, 0), draw.Src)
152- t.FromImageRGBA(copy)
29+
30+type PalFX struct{}
31+
32+func (fx *PalFX) GetFcPalFx(trans int32) (neg bool, color float32,
33+ add, mul [3]float32) {
34+ neg = false
35+ color = 1
36+ for i := range add {
37+ add[i] = 0
38+ }
39+ for i := range mul {
40+ mul[i] = 1
15341 }
42+ return
15443 }
15544
15645 type PalleteList struct {
@@ -159,7 +48,7 @@ type PalleteList struct {
15948 PalTable map[[2]int16]int
16049 }
16150
162-func (pl *PalleteList) Clear() {
51+func (pl *PalleteList) init() {
16352 pl.palletes = nil
16453 pl.palleteMap = nil
16554 pl.PalTable = make(map[[2]int16]int)
@@ -306,6 +195,128 @@ type Sprite struct {
306195 func NewSprite() *Sprite {
307196 return &Sprite{palidx: -1, link: -1}
308197 }
198+func LoadFromSff(filename string, g int16, n int16) (*Sprite, error) {
199+ s := NewSprite()
200+ f, err := os.Open(filename)
201+ if err != nil {
202+ return nil, err
203+ }
204+ defer func() { chk(f.Close()) }()
205+ h := &SffHeader{}
206+ var lofs, tofs uint32
207+ if err := h.Read(f, &lofs, &tofs); err != nil {
208+ return nil, err
209+ }
210+ var shofs, xofs, size uint32 = h.FirstSpriteHeaderOffset, 0, 0
211+ var indexOfPrevious uint16
212+ pl := &PalleteList{}
213+ pl.init()
214+ foo := func() error {
215+ switch h.Ver0 {
216+ case 1:
217+ if err := s.readHeader(f, &xofs, &size, &indexOfPrevious); err != nil {
218+ return err
219+ }
220+ case 2:
221+ if err := s.readHeaderV2(f, &xofs, &size,
222+ lofs, tofs, &indexOfPrevious); err != nil {
223+ return err
224+ }
225+ }
226+ return nil
227+ }
228+ var palletSame bool
229+ var dummy *Sprite
230+ var newSubHeaderOffset []uint32
231+ AppendU32(&newSubHeaderOffset, shofs)
232+ i := 0
233+ for ; i < int(h.NumberOfSprites); i++ {
234+ AppendU32(&newSubHeaderOffset, shofs)
235+ f.Seek(int64(shofs), 0)
236+ if err := foo(); err != nil {
237+ return nil, err
238+ }
239+ if s.palidx < 0 || s.Group == g && s.Number == n {
240+ ip := len(newSubHeaderOffset)
241+ for size == 0 {
242+ if int(indexOfPrevious) >= ip {
243+ return nil, Error("linkが不正です")
244+ }
245+ ip = int(indexOfPrevious)
246+ if h.Ver0 == 1 {
247+ shofs = newSubHeaderOffset[ip]
248+ } else {
249+ shofs = h.FirstSpriteHeaderOffset + uint32(ip)*28
250+ }
251+ f.Seek(int64(shofs), 0)
252+ if err := foo(); err != nil {
253+ return nil, err
254+ }
255+ }
256+ switch h.Ver0 {
257+ case 1:
258+ if err := s.read(f, h, int64(shofs+32), size, xofs, dummy,
259+ &palletSame, pl, false); err != nil {
260+ return nil, err
261+ }
262+ case 2:
263+ if err := s.readV2(f, int64(xofs), size); err != nil {
264+ return nil, err
265+ }
266+ }
267+ if s.Group == g && s.Number == n {
268+ break
269+ }
270+ dummy = &Sprite{palidx: s.palidx}
271+ }
272+ if h.Ver0 == 1 {
273+ shofs = xofs
274+ } else {
275+ shofs += 28
276+ }
277+ }
278+ if i == int(h.NumberOfSprites) {
279+ return nil, Error(fmt.Sprintf("%d, %d のスプライトが見つかりません", g, n))
280+ }
281+ if h.Ver0 == 1 {
282+ s.Pal = pl.Get(s.palidx)
283+ s.palidx = -1
284+ return s, nil
285+ }
286+ read := func(x interface{}) error {
287+ return binary.Read(f, binary.LittleEndian, x)
288+ }
289+ size = 0
290+ indexOfPrevious = uint16(s.palidx)
291+ ip := indexOfPrevious + 1
292+ for size == 0 && ip != indexOfPrevious {
293+ ip = indexOfPrevious
294+ shofs = h.FirstPaletteHeaderOffset + uint32(ip)*16
295+ f.Seek(int64(shofs)+6, 0)
296+ if err := read(&indexOfPrevious); err != nil {
297+ return nil, err
298+ }
299+ if err := read(&xofs); err != nil {
300+ return nil, err
301+ }
302+ if err := read(&size); err != nil {
303+ return nil, err
304+ }
305+ }
306+ if s.rle != -12 {
307+ f.Seek(int64(lofs+xofs), 0)
308+ s.Pal = make([]uint32, 256)
309+ var rgba [4]byte
310+ for i := 0; i < int(size)/4 && i < len(s.Pal); i++ {
311+ if err := read(rgba[:]); err != nil {
312+ return nil, err
313+ }
314+ s.Pal[i] = uint32(rgba[2])<<16 | uint32(rgba[1])<<8 | uint32(rgba[0])
315+ }
316+ }
317+ s.palidx = -1
318+ return s, nil
319+}
309320 func (s *Sprite) shareCopy(src *Sprite) {
310321 s.Pal = src.Pal
311322 s.Tex = src.Tex
@@ -475,7 +486,7 @@ func (s *Sprite) read(f *os.File, sh *SffHeader, offset int64,
475486 if err := read(rgb[:]); err != nil {
476487 return err
477488 }
478- pal[i] = uint32(rgb[0])<<16 | uint32(rgb[1])<<16 | uint32(rgb[2])
489+ pal[i] = uint32(rgb[2])<<16 | uint32(rgb[1])<<8 | uint32(rgb[0])
479490 }
480491 }
481492 s.SetPxl(s.RlePcxDecode(px))
@@ -677,8 +688,7 @@ func (s *Sprite) Lz5Decode(rle []byte) (p []byte) {
677688 }
678689 return
679690 }
680-func (s *Sprite) readV2(f *os.File, sh *SffHeader, offset int64,
681- datasize uint32) error {
691+func (s *Sprite) readV2(f *os.File, offset int64, datasize uint32) error {
682692 f.Seek(offset+4, 0)
683693 if s.rle < 0 {
684694 format := -s.rle
@@ -689,6 +699,36 @@ func (s *Sprite) readV2(f *os.File, sh *SffHeader, offset int64,
689699 return err
690700 }
691701 }
702+ getIHDR := func() (png_ptr C.png_structp, info_ptr C.png_infop,
703+ width, height C.png_uint_32, bit_depth, color_type C.int,
704+ ok bool, err error) {
705+ png_sig := make([]C.png_byte, 8)
706+ if err = binary.Read(f, binary.LittleEndian, png_sig); err != nil {
707+ return
708+ }
709+ if C.png_sig_cmp(&png_sig[0], 0, 8) != 0 {
710+ err = Error("png_sig_cmp failed")
711+ return
712+ }
713+ png_ptr = C.png_create_read_struct(C.CString(C.PNG_LIBPNG_VER_STRING),
714+ nil, nil, nil)
715+ if png_ptr == nil {
716+ err = Error("png_create_read_struct failed")
717+ return
718+ }
719+ info_ptr = C.png_create_info_struct(png_ptr)
720+ if info_ptr == nil {
721+ C.png_destroy_read_struct(&png_ptr, nil, nil)
722+ err = Error("png_create_info_struct failed")
723+ return
724+ }
725+ C.png_init_io(png_ptr, C.fdopen(C.int(f.Fd()), C.CString("rb")))
726+ C.png_set_sig_bytes(png_ptr, 8)
727+ C.png_read_info(png_ptr, info_ptr)
728+ ok = C.png_get_IHDR(png_ptr, info_ptr, &width, &height,
729+ &bit_depth, &color_type, nil, nil, nil) != 0
730+ return
731+ }
692732 switch format {
693733 case 2:
694734 px = s.Rle8Decode(px)
@@ -697,14 +737,75 @@ func (s *Sprite) readV2(f *os.File, sh *SffHeader, offset int64,
697737 case 4:
698738 px = s.Lz5Decode(px)
699739 case 10:
740+ png_ptr, info_ptr, width, height, bit_depth, color_type, ok, err :=
741+ getIHDR()
742+ if err != nil {
743+ return err
744+ }
745+ if ok && color_type == C.PNG_COLOR_TYPE_PALETTE && bit_depth <= 8 {
746+ px = make([]byte, int(width*height))
747+ pp := make([]*C.png_byte, int(height))
748+ for i := range pp {
749+ pp[i] = (*C.png_byte)(&px[i*int(width)])
750+ }
751+ C.png_read_image(png_ptr, &pp[0])
752+ switch bit_depth {
753+ case 1:
754+ for y := range pp {
755+ for i := width - 1; i >= 0; i-- {
756+ p := (*[1 << 30]byte)(unsafe.Pointer(pp[y]))[:width:width]
757+ p[i] = p[i>>3] & (1 << uint(i&7)) >> uint(i&7)
758+ }
759+ }
760+ case 2:
761+ for y := range pp {
762+ for i := width - 1; i >= 0; i-- {
763+ p := (*[1 << 30]byte)(unsafe.Pointer(pp[y]))[:width:width]
764+ p[i] = p[i>>2] & (3 << uint(i&3*2)) >> uint(i&3*2)
765+ }
766+ }
767+ case 4:
768+ for y := range pp {
769+ for i := width - 1; i >= 0; i-- {
770+ p := (*[1 << 30]byte)(unsafe.Pointer(pp[y]))[:width:width]
771+ p[i] = p[i>>1] & (15 << uint(i&1*4)) >> uint(i&1*4)
772+ }
773+ }
774+ }
775+ }
776+ C.png_destroy_read_struct(&png_ptr, &info_ptr, nil)
700777 case 11, 12:
701778 s.rle = -12
702- img, err := png.Decode(f)
779+ png_ptr, info_ptr, width, height, bit_depth, color_type, ok, err :=
780+ getIHDR()
703781 if err != nil {
704782 return err
705783 }
706- s.Tex = NewTexture()
707- s.Tex.FromImage(img)
784+ if ok {
785+ if bit_depth > 8 {
786+ C.png_set_strip_16(png_ptr)
787+ }
788+ C.png_set_expand(png_ptr)
789+ if color_type&C.PNG_COLOR_MASK_ALPHA == 0 {
790+ C.png_set_add_alpha(png_ptr, 0xFF, C.PNG_FILLER_AFTER)
791+ }
792+ px = make([]byte, int(width*height*4))
793+ pp := make([]*C.png_byte, int(height))
794+ for i := range pp {
795+ pp[i] = (*C.png_byte)(&px[i*int(width)*4])
796+ }
797+ C.png_read_image(png_ptr, &pp[0])
798+ s.Tex = NewTexture()
799+ gl.BindTexture(gl.TEXTURE_2D, uint32(*s.Tex))
800+ gl.PixelStorei(gl.UNPACK_ALIGNMENT, 1)
801+ gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, int32(width), int32(height),
802+ 0, gl.RGBA, gl.UNSIGNED_BYTE, unsafe.Pointer(&px[0]))
803+ gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
804+ gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
805+ gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP)
806+ gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP)
807+ }
808+ C.png_destroy_read_struct(&png_ptr, &info_ptr, nil)
708809 return nil
709810 default:
710811 return Error("不明な形式です")
@@ -713,3 +814,31 @@ func (s *Sprite) readV2(f *os.File, sh *SffHeader, offset int64,
713814 }
714815 return nil
715816 }
817+func (s *Sprite) glDraw(pal []uint32, mask int32, x, y float32, tile *[4]int32,
818+ xts, xbs, ys, rxadd, agl float32, trans int32, window *[4]int32,
819+ rcx, rcy float32, fx *PalFX) {
820+ if s.Tex == nil {
821+ return
822+ }
823+ if s.rle == -12 {
824+ neg, color, padd, pmul := fx.GetFcPalFx(trans)
825+ RenderMugenFc(*s.Tex, s.Size, x, y, tile, xts, xbs, ys, 1, rxadd, agl,
826+ trans, window, rcx, rcy, neg, color, &padd, &pmul)
827+ } else {
828+ RenderMugen(*s.Tex, pal, mask, s.Size, x, y, tile, xts, xbs, ys, 1,
829+ rxadd, agl, trans, window, rcx, rcy)
830+ }
831+}
832+func (s *Sprite) Draw(x, y, xscale, yscale float32, pal []uint32) {
833+ x -= xscale*float32(s.Offset[0]) + float32(GameWidth-320)/2
834+ y -= yscale*float32(s.Offset[1]) + float32(GameHeight-240)
835+ if xscale < 0 {
836+ x *= -1
837+ }
838+ if yscale < 0 {
839+ y *= -1
840+ }
841+ s.glDraw(pal, 0, -x*WidthScale, -y*HeightScale, &notiling,
842+ xscale*WidthScale, xscale*WidthScale, yscale*HeightScale, 0, 0, 255,
843+ &scrrect, 0, 0, nil)
844+}
--- a/src/main.go
+++ b/src/main.go
@@ -9,10 +9,14 @@ import (
99 "time"
1010 )
1111
12+var windowWidth, windowHeight int32 = 640, 480
13+var GameWidth, GameHeight int32 = 320, 240
14+var WidthScale = float32(windowWidth) / float32(GameWidth)
15+var HeightScale = float32(windowHeight) / float32(GameHeight)
1216 var window *glfw.Window
13-var windowWidth, windowHeight = 640, 480
1417 var gameEnd, frameSkip = false, false
1518 var redrawWait = struct{ nextTime, lastDraw time.Time }{}
19+var testSprite *Sprite
1620
1721 func init() {
1822 runtime.LockOSThread()
@@ -49,9 +53,9 @@ func await(fps int) {
4953 glfw.PollEvents()
5054 gameEnd = window.ShouldClose()
5155 if !frameSkip {
52- windowWidth, windowHeight = window.GetFramebufferSize()
5356 gl.Viewport(0, 0, int32(windowWidth), int32(windowHeight))
5457 gl.Clear(gl.COLOR_BUFFER_BIT)
58+ testSprite.Draw(160, 120, 1, 1, testSprite.GetPal(nil))
5559 }
5660 }
5761 func main() {
@@ -61,15 +65,18 @@ func main() {
6165 glfw.WindowHint(glfw.ContextVersionMajor, 2)
6266 glfw.WindowHint(glfw.ContextVersionMinor, 1)
6367 var err error
64- window, err =
65- glfw.CreateWindow(windowWidth, windowHeight, "Ikemen GO", nil, nil)
68+ window, err = glfw.CreateWindow(int(windowWidth), int(windowHeight),
69+ "Ikemen GO", nil, nil)
6670 chk(err)
6771 window.MakeContextCurrent()
68- chk(gl.Init())
69- gltest()
7072 glfw.SwapInterval(1)
71- l := lua.NewState()
73+ chk(gl.Init())
74+ RenderInit()
75+ if testSprite, err = LoadFromSff("data/testv2.sff", 0, 0); err != nil {
76+ panic(err)
77+ }
7278 audioOpen()
79+ l := lua.NewState()
7380 lua.OpenLibraries(l)
7481 systemScriptInit(l)
7582 if err := lua.DoFile(l, "script/main.lua"); err != nil {
--- /dev/null
+++ b/src/render.go
@@ -0,0 +1,449 @@
1+package main
2+
3+import (
4+ "github.com/go-gl/gl/v2.1/gl"
5+ "math"
6+ "strings"
7+ "unsafe"
8+)
9+
10+var notiling = [4]int32{0, 0, 0, 0}
11+var scrrect = [4]int32{0, 0, int32(windowWidth), int32(windowHeight)}
12+var mugenShader uintptr
13+var uniformA, uniformPal, uniformMsk int32
14+var mugenShaderFc uintptr
15+var uniformFcA, uniformNeg, uniformGray, uniformAdd, uniformMul int32
16+var mugenShaderFcS uintptr
17+var uniformFcSA, uniformColor int32
18+
19+func RenderInit() {
20+ vertShader := strings.Join([]string{
21+ "void main(void){",
22+ "gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;",
23+ "gl_Position = ftransform();",
24+ "}\x00"}, "")
25+ fragShader := strings.Join([]string{
26+ "uniform float a;",
27+ "uniform sampler2D tex;",
28+ "uniform sampler1D pal;",
29+ "uniform int msk;",
30+ "void main(void){",
31+ "float r = texture2D(tex, gl_TexCoord[0].st).r;",
32+ "vec4 c;",
33+ "gl_FragColor =",
34+ "int(255.0*r) == msk ? vec4(0.0)",
35+ ": (c = texture1D(pal, r*0.9961), vec4(c.rgb, a));",
36+ "}\x00"}, "")
37+ fragShaderFc := strings.Join([]string{
38+ "uniform float a;",
39+ "uniform sampler2D tex;",
40+ "uniform bool neg;",
41+ "uniform float gray;",
42+ "uniform vec3 add;",
43+ "uniform vec3 mul;",
44+ "void main(void){",
45+ "vec4 c = texture2D(tex, gl_TexCoord[0].st);",
46+ "if(neg) c.rgb = vec3(1.0) - c.rgb;",
47+ "float gcol = (c.r + c.g + c.b) / 3.0;",
48+ "c.r += (gcol - c.r) * gray + add.r;",
49+ "c.g += (gcol - c.g) * gray + add.g;",
50+ "c.b += (gcol - c.b) * gray + add.b;",
51+ "c.rgb *= mul;",
52+ "c.a *= a;",
53+ "gl_FragColor = c;",
54+ "}\x00"}, "")
55+ fragShaderFcS := strings.Join([]string{
56+ "uniform float a;",
57+ "uniform sampler2D tex;",
58+ "uniform vec3 color;",
59+ "void main(void){",
60+ "vec4 c = texture2D(tex, gl_TexCoord[0].st);",
61+ "c.rgb = color * c.a;",
62+ "c.a *= a;",
63+ "gl_FragColor = c;",
64+ "}\x00"}, "")
65+ errLog := func(obl uintptr) error {
66+ var size int32
67+ gl.GetObjectParameterivARB(obl, gl.INFO_LOG_LENGTH, &size)
68+ if size <= 0 {
69+ return nil
70+ }
71+ var l int32
72+ str := make([]byte, size+1)
73+ gl.GetInfoLogARB(obl, size, &l, &str[0])
74+ return Error(str[:l])
75+ }
76+ compile := func(shaderType uint32, src string) (shader uintptr) {
77+ shader = gl.CreateShaderObjectARB(shaderType)
78+ s, l := gl.Str(src), int32(len(src)-1)
79+ gl.ShaderSourceARB(shader, 1, &s, &l)
80+ gl.CompileShaderARB(shader)
81+ var ok int32
82+ gl.GetObjectParameterivARB(shader, gl.OBJECT_COMPILE_STATUS_ARB, &ok)
83+ if ok == 0 {
84+ chk(errLog(shader))
85+ panic(Error("コンパイルエラー"))
86+ }
87+ return
88+ }
89+ link := func(v uintptr, f uintptr) (program uintptr) {
90+ program = gl.CreateProgramObjectARB()
91+ gl.AttachObjectARB(program, v)
92+ gl.AttachObjectARB(program, f)
93+ gl.LinkProgramARB(program)
94+ var ok int32
95+ gl.GetObjectParameterivARB(program, gl.OBJECT_LINK_STATUS_ARB, &ok)
96+ if ok == 0 {
97+ chk(errLog(program))
98+ panic(Error("リンクエラー"))
99+ }
100+ return
101+ }
102+ vertObj := compile(gl.VERTEX_SHADER, vertShader)
103+ fragObj := compile(gl.FRAGMENT_SHADER, fragShader)
104+ mugenShader = link(vertObj, fragObj)
105+ uniformA = gl.GetUniformLocationARB(mugenShader, gl.Str("a\x00"))
106+ uniformPal = gl.GetUniformLocationARB(mugenShader, gl.Str("pal\x00"))
107+ uniformMsk = gl.GetUniformLocationARB(mugenShader, gl.Str("msk\x00"))
108+ gl.DeleteObjectARB(fragObj)
109+ fragObj = compile(gl.FRAGMENT_SHADER, fragShaderFc)
110+ mugenShaderFc = link(vertObj, fragObj)
111+ uniformFcA = gl.GetUniformLocationARB(mugenShader, gl.Str("a\x00"))
112+ uniformNeg = gl.GetUniformLocationARB(mugenShaderFc, gl.Str("neg\x00"))
113+ uniformGray = gl.GetUniformLocationARB(mugenShaderFc, gl.Str("gray\x00"))
114+ uniformAdd = gl.GetUniformLocationARB(mugenShaderFc, gl.Str("add\x00"))
115+ uniformMul = gl.GetUniformLocationARB(mugenShaderFc, gl.Str("mul\x00"))
116+ gl.DeleteObjectARB(fragObj)
117+ fragObj = compile(gl.FRAGMENT_SHADER, fragShaderFcS)
118+ mugenShaderFcS = link(vertObj, fragObj)
119+ uniformFcSA = gl.GetUniformLocationARB(mugenShader, gl.Str("a\x00"))
120+ uniformColor = gl.GetUniformLocationARB(mugenShaderFcS, gl.Str("color\x00"))
121+ gl.DeleteObjectARB(fragObj)
122+ gl.DeleteObjectARB(vertObj)
123+ scrrect[2], scrrect[3] = int32(windowWidth), int32(windowHeight)
124+}
125+func kaiten(x *float32, y *float32,
126+ angle float64, rcx float32, rcy float32, vscl float32) {
127+ temp := (*y - rcy) / vscl
128+ length := math.Sqrt(float64((*x-rcx)*(*x-rcx) + temp*temp))
129+ if *x-rcx == 0 {
130+ if *y-rcy > 0 {
131+ angle += math.Pi / 2
132+ } else {
133+ angle -= math.Pi / 2
134+ }
135+ *x = rcx + float32(length*math.Cos(angle))
136+ *y = rcy + float32(length*math.Sin(angle))*vscl
137+ return
138+ }
139+ kakudo := math.Atan(float64(temp/(*x-rcx))) + angle
140+ if *x-rcx < 0 {
141+ kakudo += math.Pi
142+ }
143+ *x = rcx + float32(length*math.Cos(kakudo))
144+ *y = rcy + float32(length*math.Sin(kakudo))*vscl
145+}
146+func drawQuads(x1, y1, x2, y2, x3, y3, x4, y4, r, g, b, a, pers float32) {
147+ gl.Color4f(r, g, b, a)
148+ gl.Begin(gl.TRIANGLE_STRIP)
149+ gl.TexCoord2f(0, 1)
150+ gl.Vertex2f(x1, y1)
151+ gl.TexCoord2f(0, 0)
152+ gl.Vertex2f(x4, y4)
153+ if pers != 1 {
154+ n := int((1 - (pers * pers)) * Abs(x1-x2) *
155+ float32(windowHeight>>5) / (Abs(y1-y4) + float32(windowHeight>>5)))
156+ for i := 1; i < n; i++ {
157+ gl.TexCoord2f(float32(i)/float32(n), 1)
158+ gl.Vertex2f(x1+(x2-x1)*float32(i)/float32(n),
159+ y1+(y2-y1)*float32(i)/float32(n))
160+ gl.TexCoord2f(float32(i)/float32(n), 0)
161+ gl.Vertex2f(x4+(x3-x4)*float32(i)/float32(n),
162+ y4+(y3-y4)*float32(i)/float32(n))
163+ }
164+ }
165+ gl.TexCoord2f(1, 1)
166+ gl.Vertex2f(x2, y2)
167+ gl.TexCoord2f(1, 0)
168+ gl.Vertex2f(x3, y3)
169+ gl.End()
170+}
171+func rmTileHSub(x1, y1, x2, y2, x3, y3, x4, y4, xtw, xbw, xts, xbs float32,
172+ tl *[4]int32, rcx, r, g, b, a, pers float32) {
173+ topdist := xtw + xts*float32((*tl)[0])
174+ if Abs(topdist) >= 0.01 {
175+ botdist := xbw + xbs*float32((*tl)[0])
176+ db := (x4 - rcx) * (botdist - topdist) / Abs(topdist)
177+ x1 += db
178+ x2 += db
179+ if (*tl)[2] == 1 {
180+ x1d, x2d, x3d, x4d := x1, x2, x3, x4
181+ for {
182+ x2d = x1d - xbs*float32((*tl)[0])
183+ x3d = x4d - xts*float32((*tl)[0])
184+ x4d = x3d - xtw
185+ x1d = x2d - xbw
186+ if topdist < 0 {
187+ if x1d >= float32(windowWidth) && x2d >= float32(windowWidth) &&
188+ x3d >= float32(windowWidth) && x4d >= float32(windowWidth) {
189+ break
190+ }
191+ } else if x1d <= 0 && x2d <= 0 && x3d <= 0 && x4d <= 0 {
192+ break
193+ }
194+ if (0 < x1d || 0 < x2d) &&
195+ (x1d < float32(windowWidth) || x2d < float32(windowWidth)) ||
196+ (0 < x3d || 0 < x4d) &&
197+ (x3d < float32(windowWidth) || x4d < float32(windowWidth)) {
198+ drawQuads(x1d, y1, x2d, y2, x3d, y3, x4d, y4, r, g, b, a, pers)
199+ }
200+ }
201+ }
202+ }
203+ n := (*tl)[2]
204+ for {
205+ if topdist > 0 {
206+ if x1 >= float32(windowWidth) && x2 >= float32(windowWidth) &&
207+ x3 >= float32(windowWidth) && x4 >= float32(windowWidth) {
208+ break
209+ }
210+ } else if x1 <= 0 && x2 <= 0 && x3 <= 0 && x4 <= 0 {
211+ break
212+ }
213+ if (0 < x1 || 0 < x2) &&
214+ (x1 < float32(windowWidth) || x2 < float32(windowWidth)) ||
215+ (0 < x3 || 0 < x4) &&
216+ (x3 < float32(windowWidth) || x4 < float32(windowWidth)) {
217+ drawQuads(x1, y1, x2, y2, x3, y3, x4, y4, r, g, b, a, pers)
218+ }
219+ if (*tl)[2] != 1 && n != 0 {
220+ n--
221+ }
222+ if n == 0 || Abs(topdist) < 0.01 {
223+ break
224+ }
225+ x4 = x3 + xts*float32((*tl)[0])
226+ x1 = x2 + xbs*float32((*tl)[0])
227+ x2 = x1 + xbw
228+ x3 = x4 + xtw
229+ }
230+}
231+func rmTileSub(w, h uint16, x, y float32, tl *[4]int32,
232+ xts, xbs, ys, vs, rxadd, agl, rcx, rcy, r, g, b, a float32) {
233+ x1, y1 := x+rxadd*ys*float32(h), rcy+((y-ys*float32(h))-rcy)*vs
234+ x2, y2 := x1+xbs*float32(w), y1
235+ x3, y3 := x+xts*float32(w), rcy+(y-rcy)*vs
236+ x4, y4 := x, y3
237+ var pers float32
238+ if Abs(xts) < Abs(xbs) {
239+ pers = Abs(xts) / Abs(xbs)
240+ } else {
241+ pers = Abs(xbs) / Abs(xts)
242+ }
243+ if agl != 0 {
244+ kaiten(&x1, &y1, float64(agl), rcx, rcy, vs)
245+ kaiten(&x2, &y2, float64(agl), rcx, rcy, vs)
246+ kaiten(&x3, &y3, float64(agl), rcx, rcy, vs)
247+ kaiten(&x4, &y4, float64(agl), rcx, rcy, vs)
248+ drawQuads(x1, y1, x2, y2, x3, y3, x4, y4, r, g, b, a, pers)
249+ return
250+ }
251+ if (*tl)[3] == 1 && xbs != 0 {
252+ x1d, y1d, x2d, y2d, x3d, y3d, x4d, y4d := x1, y1, x2, y2, x3, y3, x4, y4
253+ for {
254+ x1d, y1d = x4d, y4d+ys*vs*float32((*tl)[1])
255+ x2d, y2d = x3d, y1d
256+ x3d = x4d - rxadd*ys*float32(h) + (xts/xbs)*(x3d-x4d)
257+ y3d = y2d + ys*vs*float32(h)
258+ x4d = x4d - rxadd*ys*float32(h)
259+ if Abs(y3d-y4d) < 0.01 {
260+ break
261+ }
262+ y4d = y3d
263+ if ys*(float32(h)+float32((*tl)[1])) < 0 {
264+ if y1d <= float32(-windowHeight) && y4d <= float32(-windowHeight) {
265+ break
266+ }
267+ } else if y1d >= 0 && y4d >= 0 {
268+ break
269+ }
270+ if (0 > y1d || 0 > y4d) &&
271+ (y1d > float32(-windowHeight) || y4d > float32(-windowHeight)) {
272+ rmTileHSub(x1d, y1d, x2d, y2d, x3d, y3d, x4d, y4d, x3d-x4d, x2d-x1d,
273+ (x3d-x4d)/float32(w), (x2d-x1d)/float32(w), tl,
274+ rcx, r, g, b, a, pers)
275+ }
276+ }
277+ }
278+ if (*tl)[3] == 0 || xts != 0 {
279+ n := (*tl)[3]
280+ for {
281+ if ys*(float32(h)+float32((*tl)[1])) > 0 {
282+ if y1 <= float32(-windowHeight) && y4 <= float32(-windowHeight) {
283+ break
284+ }
285+ } else if y1 >= 0 && y4 >= 0 {
286+ break
287+ }
288+ if (0 > y1 || 0 > y4) &&
289+ (y1 > float32(-windowHeight) || y4 > float32(-windowHeight)) {
290+ rmTileHSub(x1, y1, x2, y2, x3, y3, x4, y4, x3-x4, x2-x1,
291+ (x3-x4)/float32(w), (x2-x1)/float32(w), tl, rcx, r, g, b, a, pers)
292+ }
293+ if (*tl)[3] != 1 && n != 0 {
294+ n--
295+ }
296+ if n == 0 {
297+ break
298+ }
299+ x4, y4 = x1, y1-ys*vs*float32((*tl)[1])
300+ x3, y3 = x2, y4
301+ x2 = x1 + rxadd*ys*float32(h) + (xbs/xts)*(x2-x1)
302+ y2 = y3 - ys*vs*float32(h)
303+ x1 = x1 + rxadd*ys*float32(h)
304+ if Abs(y1-y2) < 0.01 {
305+ break
306+ }
307+ y1 = y2
308+ }
309+ }
310+}
311+func rmMainSub(a int32, size [2]uint16, x, y float32, tl *[4]int32,
312+ xts, xbs, ys, vs, rxadd, agl float32, trans int32, rcx, rcy float32) {
313+ gl.MatrixMode(gl.PROJECTION)
314+ gl.PushMatrix()
315+ gl.LoadIdentity()
316+ gl.Ortho(0, float64(windowWidth), 0, float64(windowHeight), -1, 1)
317+ gl.MatrixMode(gl.MODELVIEW)
318+ gl.PushMatrix()
319+ gl.Translated(0, float64(windowHeight), 0)
320+ switch {
321+ case trans == -1:
322+ gl.Uniform1fARB(a, 1)
323+ gl.BlendFunc(gl.SRC_ALPHA, gl.ONE)
324+ rmTileSub(size[0], size[1], x, y, tl, xts, xbs, ys, vs, rxadd,
325+ agl, rcx, rcy, 1, 1, 1, 1)
326+ case trans == -2:
327+ gl.Uniform1fARB(a, 1)
328+ gl.BlendFunc(gl.ZERO, gl.ONE_MINUS_SRC_COLOR)
329+ rmTileSub(size[0], size[1], x, y, tl, xts, xbs, ys, vs, rxadd,
330+ agl, rcx, rcy, 1, 1, 1, 1)
331+ case trans <= 0:
332+ case trans < 255:
333+ gl.Uniform1fARB(a, float32(trans)/255)
334+ gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)
335+ rmTileSub(size[0], size[1], x, y, tl, xts, xbs, ys, vs, rxadd,
336+ agl, rcx, rcy, 1, 1, 1, float32(trans)/255)
337+ case trans < 512:
338+ gl.Uniform1fARB(a, 1)
339+ gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)
340+ rmTileSub(size[0], size[1], x, y, tl, xts, xbs, ys, vs, rxadd,
341+ agl, rcx, rcy, 1, 1, 1, 1)
342+ default:
343+ src, dst := trans&0xff, trans&0x3fc00>>10
344+ if dst < 255 {
345+ gl.Uniform1fARB(a, 1-float32(dst)/255)
346+ gl.BlendFunc(gl.ZERO, gl.ONE_MINUS_SRC_ALPHA)
347+ rmTileSub(size[0], size[1], x, y, tl, xts, xbs, ys, vs, rxadd,
348+ agl, rcx, rcy, 1, 1, 1, 1-float32(trans)/255)
349+ }
350+ if src > 0 {
351+ gl.Uniform1fARB(a, float32(src)/255)
352+ gl.BlendFunc(gl.SRC_ALPHA, gl.ONE)
353+ rmTileSub(size[0], size[1], x, y, tl, xts, xbs, ys, vs, rxadd,
354+ agl, rcx, rcy, 1, 1, 1, float32(trans)/255)
355+ }
356+ }
357+ gl.PopMatrix()
358+ gl.MatrixMode(gl.PROJECTION)
359+ gl.PopMatrix()
360+}
361+func rmInitSub(size [2]uint16, x, y *float32, tile *[4]int32, xts float32,
362+ ys, vs, agl *float32, window *[4]int32, rcx float32, rcy *float32) (
363+ tl [4]int32) {
364+ if *vs < 0 {
365+ *vs *= -1
366+ *ys *= -1
367+ *agl *= -1
368+ }
369+ tl = *tile
370+ if tl[2] == 0 {
371+ tl[0] = 0
372+ } else if tl[0] > 0 {
373+ tl[0] -= int32(size[0])
374+ }
375+ if tl[3] == 0 {
376+ tl[1] = 0
377+ } else if tl[1] > 0 {
378+ tl[1] -= int32(size[1])
379+ }
380+ if xts >= 0 {
381+ *x *= -1
382+ }
383+ *x += rcx
384+ *rcy *= -1
385+ if *ys < 0 {
386+ *y *= -1
387+ }
388+ *y += *rcy
389+ gl.Enable(gl.TEXTURE_2D)
390+ gl.Disable(gl.DEPTH_TEST)
391+ gl.Enable(gl.SCISSOR_TEST)
392+ gl.Scissor((*window)[0], windowHeight-((*window)[1]+(*window)[3]),
393+ (*window)[2], (*window)[3])
394+ return
395+}
396+func RenderMugen(tex Texture, pal []uint32, mask int32, size [2]uint16,
397+ x, y float32, tile *[4]int32, xts, xbs, ys, vs, rxadd, agl float32,
398+ trans int32, window *[4]int32, rcx, rcy float32) {
399+ if tex == 0 || !IsFinite(x+y+xts+xbs+ys+vs+rxadd+agl+rcx+rcy) {
400+ return
401+ }
402+ tl := rmInitSub(size, &x, &y, tile, xts, &ys, &vs, &agl, window, rcx, &rcy)
403+ gl.Enable(gl.TEXTURE_1D)
404+ gl.UseProgramObjectARB(mugenShader)
405+ gl.Uniform1iARB(uniformPal, 1)
406+ gl.Uniform1iARB(uniformMsk, mask)
407+ gl.ActiveTexture(gl.TEXTURE1)
408+ var paltex uint32
409+ gl.GenTextures(1, &paltex)
410+ gl.BindTexture(gl.TEXTURE_1D, paltex)
411+ gl.PixelStorei(gl.UNPACK_ALIGNMENT, 1)
412+ gl.TexImage1D(gl.TEXTURE_1D, 0, gl.RGBA, 256, 0, gl.RGBA, gl.UNSIGNED_BYTE,
413+ unsafe.Pointer(&pal[0]))
414+ gl.TexParameteri(gl.TEXTURE_1D, gl.TEXTURE_MAG_FILTER, gl.NEAREST)
415+ gl.TexParameteri(gl.TEXTURE_1D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)
416+ gl.ActiveTexture(gl.TEXTURE0)
417+ gl.BindTexture(gl.TEXTURE_2D, uint32(tex))
418+ rmMainSub(uniformA, size, x, y, &tl, xts, xbs, ys, vs, rxadd, agl,
419+ trans, rcx, rcy)
420+ gl.DeleteTextures(1, &paltex)
421+ gl.UseProgramObjectARB(0)
422+ gl.Disable(gl.TEXTURE_1D)
423+ gl.Disable(gl.SCISSOR_TEST)
424+ gl.Disable(gl.TEXTURE_2D)
425+}
426+func RenderMugenFc(tex Texture, size [2]uint16, x, y float32,
427+ tile *[4]int32, xts, xbs, ys, vs, rxadd, agl float32, trans int32,
428+ window *[4]int32, rcx, rcy float32, neg bool, color float32,
429+ padd, pmul *[3]float32) {
430+ if tex == 0 || !IsFinite(x+y+xts+xbs+ys+vs+rxadd+agl+rcx+rcy) {
431+ return
432+ }
433+ tl := rmInitSub(size, &x, &y, tile, xts, &ys, &vs, &agl, window, rcx, &rcy)
434+ gl.UseProgramObjectARB(mugenShaderFc)
435+ ineg := int32(0)
436+ if neg {
437+ ineg = 1
438+ }
439+ gl.Uniform1iARB(uniformNeg, ineg)
440+ gl.Uniform1fARB(uniformGray, 1-color)
441+ gl.Uniform3fARB(uniformAdd, (*padd)[0], (*padd)[1], (*padd)[2])
442+ gl.Uniform3fARB(uniformMul, (*pmul)[0], (*pmul)[1], (*pmul)[2])
443+ gl.BindTexture(gl.TEXTURE_2D, uint32(tex))
444+ rmMainSub(uniformFcA, size, x, y, &tl, xts, xbs, ys, vs, rxadd, agl,
445+ trans, rcx, rcy)
446+ gl.UseProgramObjectARB(0)
447+ gl.Disable(gl.SCISSOR_TEST)
448+ gl.Disable(gl.TEXTURE_2D)
449+}