get textures halfway working

This commit is contained in:
nek0 2020-05-22 16:16:06 +02:00
parent 1714facb11
commit e3be56ab6c
8 changed files with 136 additions and 31 deletions

View file

@ -24,8 +24,11 @@ executable renderer-tutorial
, OpenGLRaw , OpenGLRaw
, sdl2 >= 2.5.0.0 , sdl2 >= 2.5.0.0
, bytestring , bytestring
, vector
, linear
, monad-loops , monad-loops
, random , random
, JuicyPixels
other-modules: BindableClass other-modules: BindableClass
, BufferClass , BufferClass
, VertexBuffer , VertexBuffer
@ -33,5 +36,6 @@ executable renderer-tutorial
, IndexBuffer , IndexBuffer
, Shader , Shader
, Renderer , Renderer
, Texture
hs-source-dirs: src hs-source-dirs: src
default-language: Haskell2010 default-language: Haskell2010

View file

@ -1,10 +1,14 @@
#version 330 core #version 330 core
out vec4 color; layout(location = 0) out vec4 color;
in vec2 v_texCoord;
uniform vec4 u_color; uniform vec4 u_color;
uniform sampler2D u_texture;
void main() void main()
{ {
color = u_color; vec4 texColor = texture(u_texture, v_texCoord);
color = texColor;
} }

View file

@ -1,8 +1,12 @@
#version 330 core #version 330 core
layout(location = 0) in vec4 position; layout(location = 0) in vec3 position;
layout(location = 1) in vec2 texCoord;
out vec2 v_texCoord;
void main() void main()
{ {
gl_Position = position; gl_Position = position;
v_texCoord = texCoord;
} }

BIN
res/textures/lynx.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 KiB

View file

@ -4,17 +4,18 @@ let
inherit (nixpkgs) pkgs; inherit (nixpkgs) pkgs;
f = { mkDerivation, base, bytestring, monad-loops, OpenGL f = { mkDerivation, base, bytestring, JuicyPixels, linear
, OpenGLRaw, random, sdl2, stdenv , monad-loops, OpenGL, OpenGLRaw, random, sdl2, stdenv, vector
}: }:
mkDerivation { mkDerivation {
pname = "renderer"; pname = "renderer-tutorial";
version = "0.0.0.0"; version = "0.0.0.0";
src = ./.; src = ./.;
isLibrary = false; isLibrary = false;
isExecutable = true; isExecutable = true;
executableHaskellDepends = [ executableHaskellDepends = [
base bytestring monad-loops OpenGL OpenGLRaw random sdl2 base bytestring JuicyPixels linear monad-loops OpenGL OpenGLRaw
random sdl2 vector
]; ];
license = stdenv.lib.licenses.gpl3; license = stdenv.lib.licenses.gpl3;
}; };

View file

@ -38,6 +38,7 @@ import VertexBuffer
import IndexBuffer import IndexBuffer
import Shader import Shader
import Renderer import Renderer
import Texture
main :: IO () main :: IO ()
main = do main = do
@ -80,12 +81,14 @@ main = do
vao <- GL.genObjectName vao <- GL.genObjectName
GL.bindVertexArrayObject $= Just vao GL.bindVertexArrayObject $= Just vao
-- define vertices (positions of the triangle corners) as List of Floats -- define vertices (positions of the rectangle corners) as List of Floats
-- with added in texture coordinates
let vertexPositions = let vertexPositions =
[ (-0.5), (-0.5) -- 0 -- 3D positions | texture coordinates
, 0.5 , (-0.5) -- 1 [ (-0.5), (-0.5), 0, 0, 0 -- 0
, 0.5 , 0.5 -- 2 , 0.5 , (-0.5), 0, 1, 0 -- 1
, (-0.5), 0.5 -- 3 , 0.5 , 0.5 , 0, 1, 1 -- 2
, (-0.5), 0.5 , 0, 0, 1 -- 3
] :: [GL.GLfloat] ] :: [GL.GLfloat]
-- create draw order indices -- create draw order indices
@ -100,23 +103,18 @@ main = do
-- enable and specify data layout of the in-memory vertices -- enable and specify data layout of the in-memory vertices
layout <- newVertexBufferLayout layout <- newVertexBufferLayout
-- push vertex positions
pushElements layout GL.Float 3
-- pusht texture coordinates
pushElements layout GL.Float 2 pushElements layout GL.Float 2
addBuffer vao vbo layout addBuffer vao vbo layout
-- GL.vertexAttribPointer (GL.AttribLocation 0) $= -- -- TEXTURE
-- ( GL.ToFloat
-- , GL.VertexArrayDescriptor -- generate and bind texture
-- -- There are 2 components (Floats) to our attribute tex <- newTexture "res/textures/lynx.jpg" 0
-- 2 bind tex
-- -- They are Floats
-- GL.Float
-- -- ???
-- 0
-- -- our attribute is directly at the beginning of each vertex
-- (plusPtr nullPtr 0)
-- )
-- GL.vertexAttribArray (GL.AttribLocation 0) $= GL.Enabled
-- construct new IndexBuffer and fill it with data -- construct new IndexBuffer and fill it with data
ibo <- newIndexBuffer indices ibo <- newIndexBuffer indices
@ -128,8 +126,13 @@ main = do
, ShaderSource GL.FragmentShader "./res/shaders/frag.shader" , ShaderSource GL.FragmentShader "./res/shaders/frag.shader"
] ]
[ "u_color" [ "u_color"
, "u_texture"
] ]
-- -- tell the shader where to find the texture
bind sp
setUniform sp "u_texture" (texSlot tex)
-- -- UNIFORMS -- -- UNIFORMS
-- create MVars for pulsating red channel -- create MVars for pulsating red channel
@ -143,7 +146,7 @@ main = do
-- -- UNBINDING ALL BUFFERS AND VERTEX ARRAYS -- -- UNBINDING ALL BUFFERS AND VERTEX ARRAYS
GL.bindVertexArrayObject $= Nothing unbind vao
unbind vbo unbind vbo
unbind ibo unbind ibo
unbind sp unbind sp

88
src/Texture.hs Normal file
View file

@ -0,0 +1,88 @@
module Texture where
import SDL (($=), get)
import qualified Graphics.Rendering.OpenGL as GL
import Codec.Picture
import Data.Either
import Data.Vector.Storable as VS
import Foreign.Ptr
import Foreign.Marshal.Alloc (free)
import Linear
-- internal imports
import BindableClass
data Texture = Texture
{ texId :: GL.TextureObject
, texSlot :: GL.TextureUnit
, texPath :: FilePath
, texDimensions :: V2 GL.GLsizei
, texBPP :: Int
, texData :: Ptr ()
}
instance Bindable Texture where
bind t = do
GL.activeTexture $= texSlot t
GL.textureBinding GL.Texture2D $= Just (texId t)
unbind _ = GL.textureBinding GL.Texture2D $= Nothing
newTexture :: FilePath -> GL.GLuint -> IO Texture
newTexture fp slot = do
-- read in image from filesystem
img <- convertRGBA8 <$>
either (error $ "reading image file " <> fp <> " failed!") id <$>
readImage fp
-- extract the raw pointer from vector
unsafeWith (imageData img) $ \ptr -> do
-- create texture object
tex <- Texture
<$> GL.genObjectName
<*> (pure $ GL.TextureUnit slot)
<*> (pure fp)
<*> (pure $ fmap fromIntegral $ V2 (imageWidth img) (imageHeight img))
<*> (pure $ componentCount (VS.head $ imageData img))
<*> (pure $ castPtr ptr)
-- bind texture
bind tex
-- set texture parameters
GL.textureFilter GL.Texture2D $= ((GL.Linear', Nothing), GL.Linear')
GL.textureWrapMode GL.Texture2D GL.S $= (GL.Repeated, GL.Clamp)
GL.textureWrapMode GL.Texture2D GL.T $= (GL.Repeated, GL.Clamp)
-- put data into GPU memory
loadTexture tex
-- unbind texture
unbind tex
-- -- throw away the data on the CPU side
-- free (texData tex)
-- pass texture object out
return tex
loadTexture :: Texture -> IO ()
loadTexture tex =
let (V2 w h) = texDimensions tex
in GL.texImage2D
GL.Texture2D
GL.NoProxy
0
GL.RGBA'
(GL.TextureSize2D w h)
0
(GL.PixelData GL.RGBA GL.UnsignedByte (texData tex))

View file

@ -60,11 +60,12 @@ addBuffer va vb layout = do
(\(index, elem) -> do (\(index, elem) -> do
let offset = fromIntegral $ let offset = fromIntegral $
foldl foldl
(\acc (index, _) -> acc + index ) (\acc (index, elem) -> acc + vbleCount elem)
0 0
(filter ((<= index) . fst) indexed) :: Int (filter ((< index) . fst) indexed) :: Int
GL.vertexAttribArray (GL.AttribLocation index) $= GL.Enabled GL.vertexAttribArray (GL.AttribLocation $ fromIntegral index) $=
GL.vertexAttribPointer (GL.AttribLocation index) $= GL.Enabled
GL.vertexAttribPointer (GL.AttribLocation $ fromIntegral index) $=
( vbleHandling elem ( vbleHandling elem
, GL.VertexArrayDescriptor , GL.VertexArrayDescriptor
-- number of components to our attribute -- number of components to our attribute
@ -72,7 +73,7 @@ addBuffer va vb layout = do
-- datatype of elements -- datatype of elements
(vbleType elem) (vbleType elem)
-- ??? -- ???
0 (sum (map vbleCount list) * fromIntegral (dataElementSize (vbleType elem)))
-- offset from beginnning of vertex -- offset from beginnning of vertex
(plusPtr nullPtr (offset * dataElementSize (vbleType elem))) (plusPtr nullPtr (offset * dataElementSize (vbleType elem)))
) )