From 00ac2ef5b2f518d0455abb5252b4afec7e85eb5a Mon Sep 17 00:00:00 2001 From: nek0 Date: Sat, 17 Oct 2020 16:18:42 +0200 Subject: [PATCH] preparing for graphics --- pituicat.cabal | 7 +- res/maps/00_test/00_test.bmp | Bin 12342 -> 12342 bytes res/maps/00_test/00_test.kra | Bin 31934 -> 31856 bytes src/Classes.hs | 2 +- src/Classes/Graphics.hs | 5 ++ src/Classes/{ => Graphics}/Bindable.hs | 2 +- src/Classes/Graphics/Buffer.hs | 26 ++++++ src/Main.hs | 11 ++- src/Map.hs | 23 +++-- src/State/MainGame/Load.hs | 1 + src/Texture.hs | 2 +- src/Types.hs | 1 + src/Types/Graphics.hs | 6 ++ src/Types/Graphics/IndexBuffer.hs | 70 +++++++++++++++ src/Types/Graphics/VertexArray.hs | 116 +++++++++++++++++++++++++ src/Types/Graphics/VertexBuffer.hs | 93 ++++++++++++++++++++ src/Types/Texture.hs | 2 +- 17 files changed, 351 insertions(+), 16 deletions(-) create mode 100644 src/Classes/Graphics.hs rename src/Classes/{ => Graphics}/Bindable.hs (84%) create mode 100644 src/Classes/Graphics/Buffer.hs create mode 100644 src/Types/Graphics.hs create mode 100644 src/Types/Graphics/IndexBuffer.hs create mode 100644 src/Types/Graphics/VertexArray.hs create mode 100644 src/Types/Graphics/VertexBuffer.hs diff --git a/pituicat.cabal b/pituicat.cabal index 34463d9..88074e6 100644 --- a/pituicat.cabal +++ b/pituicat.cabal @@ -22,8 +22,13 @@ executable pituicat , Types.Subsystems , Types.GameMap , Types.Texture + , Types.Graphics + , Types.Graphics.VertexArray + , Types.Graphics.VertexBuffer , Classes - , Classes.Bindable + , Classes.Graphics + , Classes.Graphics.Bindable + , Classes.Graphics.Buffer , State.Loading , State.Loading.Load , State.Loading.Update diff --git a/res/maps/00_test/00_test.bmp b/res/maps/00_test/00_test.bmp index 565eea85d599d522ea5f55b5145db2b1003ef080..203e49aac3f8625517f7c11417cc224959f632e2 100644 GIT binary patch delta 19 bcmdm%uq|OjwLatDiH5F|%hbFlI%oj^SzZVM delta 17 Ycmdm%uq|Ojwf;myx5;H{-V+_P07q>H1ONa4 diff --git a/res/maps/00_test/00_test.kra b/res/maps/00_test/00_test.kra index 1a28659f2aae993bfa26a12ceb07e6bab35aac4c..2006d1923477340c44a284275938dec443fe6967 100644 GIT binary patch delta 3487 zcmcgvc{tQx7ypi3V@nG0vyQCU3FT+VGBd{5vlWpgg<)hF+aQCAEHn0yz1LorETzc4 z7TGcrlAQ>lgm?75{hsQ1|9R4Ro4a;)Vk+N zryQ-~7u;kUqkDC&4J15xhfMaHY`ZVLjfb$3%(O~US@x(Abq;DLCE^yzOL^yVIOj#* zG=3c|8IGF`pVF{;eV z2GHzTO=nEEqbE|)p$kd2R!rTc(3*cyYyAREtClReCA-{%WO)DcOItk1eX-cc%*;mXTr^MMcxIGC2g58h93IX2D-+1aGf zV-sO5ptR8*-`LrECKfH2EA3{krlH!Xn?}bZU2D4_AC=65vR2As6HmW1T}i9$lVLAc z(aawde;UPZAj05urL5M1kugPDS2Ew)Jpyz77DB8G?S$RxtCv{2bo?wExVa z%DTYEu#Q2`^h(oI$D#G(MJ*yOwJbHxJ(KL_d75L?sMReZdp`aNJm+;>%ue}A^K*V} z5%%%1o2wa+@;jm5u6#W`AW~`Iv303n%SV%yoYewP%`^Z#qbW=~H`m;%pXj+@!2R+% zG3M2A$2gfb+^58VCCBycO4~;hNe2~kcB9KG?^7gV4&#9isqxL0~YXFq~Ip4wwvf31|M`pRpH&aB@?&){s=(0DgnDF}FQny8h;w`mdoXW*oY-*vMmfM(Gt&HO<6wRVE33@T~ZLuI}Z)ld2BsdcL?Soeq zdDbt^&=55^WV_k!XXB30~e*hLld9Grs%%wv%_ zrQj?^W$gX!%f=(uJ0rr>DACUl-8<(ku$VMd#h}dN&1D7KL0_NpH^w}Z58;U&LyGnA zqEVV`L{Nfb@eRwi%r3s#XJU0v&XNUpICs~%Bb3$$xi6nH5o)_pq5dI6!2Pu~7nr__ z{-crPc;I3J&ohnH?7+k9RVeQI3l5Lh_6wUl?mABe)ZO-$0$#oC_ggkvuBy^QaVFkB zpgxM^k9dIqz>E6NNP_=f-nOU2SC#<)zyJVvVw`+ko&2OdJzQ3k7fpvOI3m&PQt1q0 z`mwal;sQh^4jp}FeJhB`czR_-yev+_iEtGVrehXo5-@8EpQ>cQL&uO*TH4T<=y)Mo z9V!mF7B1xkwwBx+xBVK0eV%u$S!oIbq|NEx`nBM--mb0BYB`bLsTcvHSJ=95Ab=V- z-#;J_|DhNcQMvp~&*%cMWO#_O%&KpY28z*M<^8*@4&#>5MIMk`o8x7!xSLhEBlvPJ zg%ZW)Pv)BT^Th}84kzJH)?3HzY=g>iO-%ZG-NK!Uv1%9g%v3LDq)m9&LWXk$9Nnfv zthG7NHn$rV90xB{ZhuGAIgf2?zK6|hwGZIM!D_m?yu6lS3D=NsLWCmy>77j6x=&*_}=2)X~}KwO<`an1`m zRKgP-t>WEY0ITatAgOvn#^mR&8;?kbcKIOg>b$pRzF0*W zUb!lJLnJXiXKv4dekJT*QK7^q_OnEOUkuwMYCD;CC|iOq|G~^ltf9|CowM&tBOR0e znx`!dXt6(kJ{aTeJ>F(5HBg6NM)e0G{aSqDIh;56l0U%1)ZVdGx=l@KgwB{3#-rZ^ zO1f1y9P@Z2pM%I7!l}NUQ!9LZItm#^_dIzau8CoI=k94tOaRpsgGHsx2{+!L@aEB} z{qCSM652_$3+724ylUhXUzsP~pMB;c3*h0QDvBDo6wbkRRr0!x;`gvx#DY1>Jn3Q6 z!Dvm5K8?a(nc0ofcC``bOhsf;l0O*?^e*J5Jiox}+^dxdEaHyeYIsppB$|NaJ9Q78 zS-Ry7Efk6Cc(Ac?*FnBZj6c%~qJ&#bbI)QK!Twybol+X;)EwPuTrjMU`d7|t!DVZKR{5N=K1fZ<5w%mccmF27qyl8KUwlJYw( zx|A+Q<_vg_q&~FmYvF}QCvMNjEuhqq^IwO1L*irQPKkyLcF0TQ(ri1pVs1u0c;9ZB z)r1O3wN&1Grl_WT$yQWrprZKx@Oe9MxB=0y1-Xf;9n4>REx^dnspW{l`tpv?ik<2a z!Kkk3?c#jGPAz31U};@&VS9wanR*He`c?k&h-o(rXbEa=_9wq5tQ}OTRRv-mxkVOLkX_R@AlB8v2?QS`F-;!~& zC#(j5s}#VwAV$#P{xl1)!iONNGuaSAnFOn>nFFb~e>MH>P{JqHOVpI!lyFl)q{@v= zSm+0nC?EWTvMc=9th%WH`>|0~YpyFKdeq8VLzw+-DW$}UGFd7A;_ifTadLEZw|8+m zDjFawP$5CsUkwL_YipYM+peZ)vWG+2S}nhv{C zkDkC>8N~-|TS#4Fl4v5HKLa$7WT@+i>q;t8p>)E@Sp|_9gTf7csZ=#D* zde|IYAW1?LY4Bzp?we+@hvwZIggoN_#f}<1Kb;p_fRfb__bX(Ms`t+U3FD;H^j~WEA7>l?3X3B|{Tz_6$HxfM z0i2S58t_hP3o=r)CNceal`JBvf2Ag`9WydM#m;>s)R2T?B7 zr_euGtG{y+-%89##vpBEz3!by`$=Xv^KHV8YD zJBve09bT|C{cPVSX|6@^80w~FKQPtISdw_brh2oFFrAP!<^0yK$d|YH_Rforb8n znG?@-bd5%8&&8_L-GT@bhsgIn$&AB-%vP6*$ae?NvG*Uye2vv7xe!nbDs4ZP`Fy;C zVPBs1W-ikAm$1_>dj$tf|3{F=ftp-3-t@l4u)P*s?G)c=W&KdZyocD!#=Rw)%wSFo zl6fCKWAeC>jH4Gsnj5Q|i*;qBoRYtNGfp3)FUir)+k7b_!Djm$wi4bj=hAgqaNLop zlh6vP>}=#-X?MFggYDyHWwf3JMT01d^B&n_o^3WK&=0jsY8YONbBcC`C+OdLl$AKB z7-_8U9uJa$Z(*dTs{{=aLz2B&yCXgrmRfX)XT0&}$CcicS`d#e#cxF(;5DGI_A;lW z??#Z>782`tzO&e4f&572DdqPGkl28lh(Yg74W;C~djvLwyLF;}9k@ahgs5t{ByxX~ zj{o`dl?fv}$e21zb2nvJ@~#xf*+l7Q@yZL0gfvD9Gf>O3EiFYG47c|f9=I8RQTwJr z_S3`Qe!hqpDGYoubymo}nl?Vf-$=tMjA9 za?@Ya}JLT_6fcOLxrLmy`g2HZ=h78?6mFe1UQK1T~;2PE=SFeAfYQ zA&Dw?lIhfBrJ|PT2k}J9b{bh72EolA+gE8)Fs)8C%uJqtq`HqmZ(cVOj(y&Nfqj9K zKA^9SZ1@@9f%&cjpZ4YN|9r8tUj9JLs4})MBx@>(gxOkOT+ou$g5bKIKo+!uGvEaF znYk*AY!LOR17y{wE^8Kt==%7*byR8aa~b!nb37<7cQr6LInB7vfB%z0+ikF6qr8M4 ziy=Op>in!Q9W6V5GyYZhg~EwY98h~*5oA76go^^-nZHljGr}a!yg9TXfD`9Sv%XPp zmmW5+zvSC)@?7=BTZDv$X9VJcBBaM8Kw_$TI5?{ZjgRTZ)@tMC8qv+KPq%Rq&8SLQ zms*x}2Ut^em_pxmK1i2+7K&e*mq)tQf5Owp7v=lL8d!Kfa=>U5m2IllHD>Nuf}`0- zynCFd^_fa$>_y8LNqoC+-gfk+*GG&@ea6wA2W8^<5DI&-k4=bV%B~&~z zw;fxs{Nyqox-+=P&CE(nn!(P`mbmOftgHua*Gxsas(ici;|FOMR@$X}oX3-FQ2+oQ zz(4co*C4W8dX!ypIskwH006jq+WTPaeI?yp9hZ%rWuDTr2M<)Z7LK|ow~O`rR4x@I z+fRnpZWcw4N<{s%uTz%9(P!u3T>Y)$h4S*ujSG-j;J74k z;(g?KSlsRX`@tU%+~cKbbc-s>LHA~A6MQ)>=@O-D3WYW;z=-y949n*=VSou~7~M!43d-&;k@X))9mp=R9DIQg z?EHR<8>ic#(DcdM&Fh^#+gFn+McwvUOv@7zgMEpW&?}TZS1UBl{m(vFbrG zH@}p1+k)@VUJo5%sX0)9LoY--#d{qDaM6Sr5{;pimNRxc9H?L*Oj}z=%2ST*H7Za! zySmyeWEIfCDWC|J=7i*_^3@QBgj#(aRG^-0xFr_4QzGsac&#KAwb6+|*&8eDxhOjI zSA`O=LK6n`h`U|siv6U4z84w|q|#WL7(zOERbI6T(TA%0h8UCm7l$Q$hKad5MHjru zwXwdJ=;=@GyR6)ttO|9*!T1@swS`tlpCrV*e z;#-YH9J*Wjl>LIZOo$cmS_Xs}3O+rl8}>G|v9U2})a;^8%BShW^&l5LFRw%xE~ht) z)@;>iZCO#qVH`a=XPjXN@~3D|M2s(PChH`~o;CNpAKL=IVho@oqxeHrK0#$O!Ky zj%XP2kOs)yKby7vcCODa>~L-lH+L^@T~(S*&>Di(LV4V%6xjuFOm`4xT~u$R%!}D? zSWy@zGS`9~HuJU*=r@mNZlW=wWZS(v^S z4X_F)|LhK=wPCzsDsiTphcl*)<+AN_b3O3%9gP1?75%O3HzePbC@2BiVYT)Mj^2;GTu$UyPB#H_8Z z1nG`xW}v})*{CbcLc~lTRWWnXU|Q_D%eI(UGi-PZDb6WXA!}1qR;SEHz1p5Z{q^1A z#b`wpuVwA-{;S@cWLh#dM2*jfsPg$q&|Ol)y=`WyRIOCZ*Hhp*Teny^8Mya z#>MAU06;Po!9be3YzCA`0bF9aMCd^&Xr?JzDk z9qo?`4uu&-4q?z&2?x@>qJj3ivHYZmv00tH)rZwM>u~BC&F-^mJW%R!QY7|MS3w8Z zuJMOs(ITWr`jsQDEeU&V{pEx|Wk}C~bchbUbyy3f)5X8Og1Ax5BcDrXWFfD;s2N43 zo!!lV+z-rZo6EfRTBc{-;JS?{-MtO>fQyoEg+tu9kTtU$1-O~>Djg$r4!E9mQ$Pqe zM=pgSmcm}{|Msc=?{d4_G`C;Ja0lO}u5&$#7eH6b;7Sq9CiFPDzXlV9q@d&j{(I>l z==;n3d+Q+F_rFAc9R0srwq}1h^W)jC+&C`${|x9|j-z(qmp0%J--f@kg5#gRjwJLh zfPsJtIDhuoJMX6}=je~XBZ>h8elwb8J~HAW?$jX1bftjW+OjJiJ`<({>xPIF}E&+H) a=)~sN2p-e%p8>u5odCZhK=Z)=82K-Xh#O%5 diff --git a/src/Classes.hs b/src/Classes.hs index ec1d9be..1668bd5 100644 --- a/src/Classes.hs +++ b/src/Classes.hs @@ -2,4 +2,4 @@ module Classes ( module C ) where -import Classes.Bindable as C +import Classes.Graphics as C diff --git a/src/Classes/Graphics.hs b/src/Classes/Graphics.hs new file mode 100644 index 0000000..baba09c --- /dev/null +++ b/src/Classes/Graphics.hs @@ -0,0 +1,5 @@ +module Classes.Graphics + ( module G + ) where + +import Classes.Graphics.Bindable as G diff --git a/src/Classes/Bindable.hs b/src/Classes/Graphics/Bindable.hs similarity index 84% rename from src/Classes/Bindable.hs rename to src/Classes/Graphics/Bindable.hs index a6c9b1c..e590b21 100644 --- a/src/Classes/Bindable.hs +++ b/src/Classes/Graphics/Bindable.hs @@ -1,4 +1,4 @@ -module Classes.Bindable where +module Classes.Graphics.Bindable where -- | typeclass for bindable objects like buffers, vertex arrays or shaders class Bindable a where diff --git a/src/Classes/Graphics/Buffer.hs b/src/Classes/Graphics/Buffer.hs new file mode 100644 index 0000000..46fe645 --- /dev/null +++ b/src/Classes/Graphics/Buffer.hs @@ -0,0 +1,26 @@ +{-# LANGUAGE TypeFamilies #-} +module Classes.Graphics.Buffer where + +import qualified Graphics.Rendering.OpenGL as GL + +import SDL (($=), get) + +-- internal imports + +import Classes.Graphics.Bindable + +-- this aims to be a typeclass for all used buffer objects throughout the +-- game. +-- think of it as some kind of interface in the object oriented context +class (Bindable a) => Buffer a where + + type ObjName a :: * + + -- what buffer target does te buffer bind to + target :: a -> GL.BufferTarget + + -- what ID does the buffer have + glId :: a -> ObjName a + + -- bind the buffer object and fill it with data + initialize :: a -> IO () diff --git a/src/Main.hs b/src/Main.hs index 622437c..6ab6d7b 100644 --- a/src/Main.hs +++ b/src/Main.hs @@ -48,8 +48,15 @@ main = do withAffection config preLoad :: GameData -> Affection () -preLoad gd = do - liftIO $ atomically $ writeTVar (gameState gd) Loading +preLoad gd = + liftIO $ do + let projection = ortho 0 800 0 600 (-1) 1 :: M44 GL.GLfloat + view = mkTransformationMat (identity :: M33 GL.GLfloat) (V3 0 0 0) + model = mkTransformationMat (identity :: M33 GL.GLfloat) (V3 0 0 0) + + vertexArrayObject <- GL.genObjectName + va <- newVertexArray + atomically $ writeTVar (gameState gd) Loading handle :: GameData -> [SDL.EventPayload] -> Affection () diff --git a/src/Map.hs b/src/Map.hs index 9e6ea53..34fa4d9 100644 --- a/src/Map.hs +++ b/src/Map.hs @@ -50,15 +50,20 @@ readLayer (idx, path) = do img <- either error convertRGBA8 <$> readImage path let width = imageWidth img height = imageHeight img - layer = V.map - (\(py, px) -> case (pixelAt img px py) of - (PixelRGBA8 r g b _) -> Tile - (V2 (255 - fromIntegral g) (255 - fromIntegral b)) - (case r of - 255 -> Solid - 254 -> Platform - _ -> Decoration - ) + layer = V.foldl + (\acc (py, px) -> case (pixelAt img px py) of + (PixelRGBA8 r g b _) -> if r >= 253 + then + acc `V.snoc` Tile + (V2 (255 - fromIntegral g) (255 - fromIntegral b)) + (case r of + 255 -> Solid + 254 -> Platform + _ -> Decoration + ) + else + acc ) + V.empty (V.fromList ((,) <$> [0 .. height - 1] <*> [0 .. width - 1])) return (MapLayer layer, V2 width height) diff --git a/src/State/MainGame/Load.hs b/src/State/MainGame/Load.hs index d92a5f7..b34d595 100644 --- a/src/State/MainGame/Load.hs +++ b/src/State/MainGame/Load.hs @@ -32,6 +32,7 @@ loadFork dataContainer progress = do _ <- takeTMVar progress putTMVar progress (0, "Loading test level...") testData <- TestData <$> constructMap testLevelDesc 0 + print testData atomically $ do _ <- takeTMVar dataContainer putTMVar dataContainer testData diff --git a/src/Texture.hs b/src/Texture.hs index fd14f42..052ab4c 100644 --- a/src/Texture.hs +++ b/src/Texture.hs @@ -16,7 +16,7 @@ import Foreign.Ptr -- internal imports -import Classes.Bindable +import Classes.Graphics.Bindable import Types.Texture newTexture :: FilePath -> GL.GLuint -> IO (V2 Word, Texture) diff --git a/src/Types.hs b/src/Types.hs index b42bb70..6ea5273 100644 --- a/src/Types.hs +++ b/src/Types.hs @@ -6,3 +6,4 @@ import Types.Application as T import Types.Subsystems as T import Types.GameMap as T import Types.Texture as T +import Types.Graphics as T diff --git a/src/Types/Graphics.hs b/src/Types/Graphics.hs new file mode 100644 index 0000000..a703f30 --- /dev/null +++ b/src/Types/Graphics.hs @@ -0,0 +1,6 @@ +module Types.Graphics + ( module G + ) where + +import Types.Graphics.VertexArray as G +import Types.Graphics.VertexBuffer as G diff --git a/src/Types/Graphics/IndexBuffer.hs b/src/Types/Graphics/IndexBuffer.hs new file mode 100644 index 0000000..88c8926 --- /dev/null +++ b/src/Types/Graphics/IndexBuffer.hs @@ -0,0 +1,70 @@ +{-# LANGUAGE TypeFamilies #-} +module Types.Graphics.IndexBuffer where + +import qualified Graphics.Rendering.OpenGL as GL + +import SDL (($=), get) + +import Foreign + +-- internal imports + +import Classes.Graphics.Bindable +import Classes.Graphics.Buffer + +-- layout of the IndexBuffer data object +data IndexBuffer a = IndexBuffer + { iBufId :: GL.BufferObject -- buffer id + , iBufSize :: GL.GLsizeiptr -- size of data + , iBufData :: Ptr a -- pointer to data + , iBufCount :: GL.GLint -- number of data elements + } + +-- instanciate typeclass from BufferClass and fill in missing implementations +instance Buffer (IndexBuffer a) where + + type ObjName (IndexBuffer a) = GL.BufferObject + + target _ = GL.ElementArrayBuffer + + glId = iBufId + + initialize buf = do + -- bind the buffer using the default iplementation of the typeclass + bind buf + -- fill in the data + GL.bufferData (target buf) $= + ( iBufSize buf + , iBufData buf + , GL.DynamicDraw + ) + -- release the buffer using the default implementation of the typeclass + unbind buf + +instance Bindable (IndexBuffer a) where + + -- bind the buffer + bind buf = GL.bindBuffer (target buf) $= Just (glId buf) + + -- unbind the buffer + unbind buf = GL.bindBuffer (target buf) $= Nothing + +newIndexBuffer :: + (Storable a) => -- we have to be able to get a pointer to provided data + [a] -> -- list of data elements + IO (IndexBuffer a) -- newly built IndexBuffer data object +newIndexBuffer list = do + -- create the buffer object in applicative style + buf <- IndexBuffer + -- generate the ID + <$> GL.genObjectName + -- compute buffer size + <*> pure (fromIntegral (length list * sizeOf (head list))) + -- make pointer out of list + <*> newArray list + -- get count + <*> pure (fromIntegral $ length list) + -- fill the data in to the buffer + initialize buf + -- return the data object + return buf diff --git a/src/Types/Graphics/VertexArray.hs b/src/Types/Graphics/VertexArray.hs new file mode 100644 index 0000000..df8dad9 --- /dev/null +++ b/src/Types/Graphics/VertexArray.hs @@ -0,0 +1,116 @@ +{-# LANGUAGE TypeFamilies #-} +module Types.Graphics.VertexArray where + +import qualified Graphics.Rendering.OpenGL as GL + +import SDL (($=), get) + +import Foreign + +import Control.Concurrent.MVar + +-- internal imports + +import Classes.Graphics.Bindable +import Classes.Graphics.Buffer +import Types.Graphics.VertexBuffer + +data VertexArray = VertexArray + { vArrId :: GL.VertexArrayObject + } + deriving (Eq, Show) + +instance Buffer VertexArray where + + type ObjName VertexArray = GL.VertexArrayObject + + target _ = undefined + + glId = vArrId + + initialize va = return () + + +instance Bindable VertexArray where + + bind va = GL.bindVertexArrayObject $= Just (vArrId va) + + unbind va = GL.bindVertexArrayObject $= Nothing + +newVertexArray :: IO VertexArray +newVertexArray = VertexArray + <$> GL.genObjectName + +addBuffer + :: (Buffer buf) + => VertexArray + -> buf + -> VertexBufferLayout + -> IO () +addBuffer va vb layout = do + -- bind the provided vertex buffer + bind va + bind vb + -- enable and fill out the vertex attrib pointer(s) + list <- readMVar (vblElements layout) + let dataElementSize e = case e of + GL.Float -> sizeOf (undefined :: GL.GLfloat) + x -> error ("No size computation implemented fof: " <> show x) + mapM_ + (\(VertexBufferLayoutElement index type_ count offset handling) -> do + GL.vertexAttribArray (GL.AttribLocation index) $= + GL.Enabled + GL.vertexAttribPointer (GL.AttribLocation index) $= + ( handling + , GL.VertexArrayDescriptor + -- number of components to our attribute + count + -- datatype of elements + type_ + -- Stride (How big is one Vertex in bytes) + (vblStride layout) + -- offset from beginnning of vertex in bytes + (plusPtr nullPtr offset) + ) + ) + list + unbind va + unbind vb + +data VertexBufferLayout = VertexBufferLayout + { vblElements :: MVar [VertexBufferLayoutElement] + , vblStride :: GL.GLsizei + } + +data VertexBufferLayoutElement = VertexBufferLayoutElement + { vbleIndex :: GL.GLuint + , vbleType :: GL.DataType + , vbleCount :: GL.GLint + , vbleOffset :: Int + , vbleHandling :: GL.IntegerHandling + } + +newVertexBufferLayout :: GL.GLsizei -> IO VertexBufferLayout +newVertexBufferLayout stride = VertexBufferLayout + <$> newMVar [] + <*> pure stride + +pushElements + :: VertexBufferLayout + -> GL.GLuint + -> GL.DataType + -> GL.GLint + -> Int + -> IO () +pushElements vbl index type_ count offset = do + modifyMVar_ (vblElements vbl) $ \list -> + return + (list ++ + [VertexBufferLayoutElement + index + type_ + count + offset + GL.ToNormalizedFloat + ] + ) diff --git a/src/Types/Graphics/VertexBuffer.hs b/src/Types/Graphics/VertexBuffer.hs new file mode 100644 index 0000000..dd38d69 --- /dev/null +++ b/src/Types/Graphics/VertexBuffer.hs @@ -0,0 +1,93 @@ +{-# LANGUAGE TypeFamilies #-} +module Types.Graphics.VertexBuffer where + +import qualified Graphics.Rendering.OpenGL as GL + +import SDL (($=), get) + +import Linear + +import Foreign +import Foreign.C.Types + +-- internal imports + +import Classes.Graphics.Bindable +import Classes.Graphics.Buffer + +-- layout of the VertexBuffer data object +data VertexBuffer = VertexBuffer + { vBufId :: GL.BufferObject -- buffer id + , vBufSize :: GL.GLsizeiptr -- size of data + -- , vBufData :: Ptr a -- pointer to data + } + +data Vertex = Vertex + { vertPosition :: V3 GL.GLfloat + , vertColor :: V4 GL.GLfloat + , vertTexCoord :: V2 GL.GLfloat + , vertTexID :: GL.GLfloat + , vertSize :: GL.GLsizei + } + +-- | Smart constructor for a new Vertex +newVertex + :: V3 GL.GLfloat + -> V4 GL.GLfloat + -> V2 GL.GLfloat + -> GL.GLfloat + -> Vertex +newVertex pos color texcoord index = + Vertex + pos + color + texcoord + index + (fromIntegral $ 10 * (sizeOf (undefined :: GL.GLfloat))) + +-- instanciate typeclass from BufferClass and fill in missing implementations +instance Buffer VertexBuffer where + + type ObjName VertexBuffer = GL.BufferObject + + target _ = GL.ArrayBuffer + + glId = vBufId + + initialize buf = do + -- bind the buffer using the default iplementation of the typeclass + bind buf + -- fill in the data + GL.bufferData (target buf) $= + ( vBufSize buf + , nullPtr + , GL.DynamicDraw + ) + -- release the buffer using the default implementation of the typeclass + unbind buf + + +instance Bindable VertexBuffer where + + -- bind the buffer + bind buf = GL.bindBuffer (target buf) $= Just (glId buf) + + -- unbind the buffer + unbind buf = GL.bindBuffer (target buf) $= Nothing + +newVertexBuffer + :: IO VertexBuffer -- newly built VertexBuffer data object +newVertexBuffer = do + let dummyVertex = newVertex (V3 0 0 0) (V4 0 0 0 0) (V2 0 0) 0 + -- create the buffer object in applicative style + buf <- VertexBuffer + -- generate the ID + <$> GL.genObjectName + -- compute buffer size + <*> pure (CPtrdiff (fromIntegral $ 1024 * vertSize dummyVertex)) + -- make pointer out of list + -- <*> newArray list + -- fill the data in to the buffer + initialize buf + -- return the data object + return buf diff --git a/src/Types/Texture.hs b/src/Types/Texture.hs index 486fdb0..e819acc 100644 --- a/src/Types/Texture.hs +++ b/src/Types/Texture.hs @@ -6,7 +6,7 @@ import qualified Graphics.Rendering.OpenGL as GL -- internal imports -import Classes.Bindable +import Classes.Graphics.Bindable data Texture = Texture { textureId :: GL.TextureObject