I'm using two textures on two different objects that each have their own shader program. However, the second object renders with both textures applied and with some strange distortion.
I will focus on the second object's code as the first object and texture renders correctly.
The first texture is loaded like this:
-- Icosahedron texture
dice_textureP <- malloc
glGenTextures 1 dice_textureP
diceText <- peek dice_textureP
glBindTexture GL_TEXTURE_2D diceText
glEnable GL_BLEND
glBlendFunc GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA
glGenerateMipmap GL_TEXTURE_2D
glTexParameteri GL_TEXTURE_2D GL_TEXTURE_MAG_FILTER GL_LINEAR
glTexParameteri GL_TEXTURE_2D GL_TEXTURE_MIN_FILTER GL_LINEAR
glTexParameteri GL_TEXTURE_2D GL_TEXTURE_WRAP_S GL_REPEAT
glTexParameteri GL_TEXTURE_2D GL_TEXTURE_WRAP_T GL_REPEAT
eErrDI0 <- readImage "app/numbers.png"
dyImage0 <- case eErrDI0 of
Left e -> do
putStrLn e
return $ ImageRGBA8 $ generateImage (\x y ->
let x' = fromIntegral x in (PixelRGBA8 x' x' x' x')) 500 400
Right di -> return di
let ipixelrgba80 = convertRGBA8 dyImage0
iWidth0 = fromIntegral $ imageWidth ipixelrgba80
iHeight0 = fromIntegral $ imageHeight ipixelrgba80
iData0 = imageData ipixelrgba80
VS.unsafeWith iData0 $ \dataP ->
glTexImage2D GL_TEXTURE_2D 0 GL_RGBA iWidth0 iHeight0 0 GL_RGBA GL_UNSIGNED_BYTE (castPtr dataP)
glGenerateMipmap GL_TEXTURE_2D
glBindTexture GL_TEXTURE_2D 0
The second texture is loaded like this:
card_oneP <- malloc
glGenTextures 1 card_oneP
card_oneTexture <- peek card_oneP
glBindTexture GL_TEXTURE_2D card_oneTexture
glDisable GL_BLEND
glTexParameteri GL_TEXTURE_2D GL_TEXTURE_MAG_FILTER GL_NEAREST_MIPMAP_NEAREST
glTexParameteri GL_TEXTURE_2D GL_TEXTURE_MIN_FILTER GL_NEAREST_MIPMAP_NEAREST
glTexParameteri GL_TEXTURE_2D GL_TEXTURE_WRAP_S GL_CLAMP_TO_EDGE
glTexParameteri GL_TEXTURE_2D GL_TEXTURE_WRAP_T GL_CLAMP_TO_EDGE
eErrDI1 <- readImage "app/card_one.jpg"
dyImage1 <- case eErrDI1 of
Left e -> do
putStrLn e
return $ ImageRGBA8 $ generateImage (\x y ->
let x' = fromIntegral x in (PixelRGBA8 x' x' x' x')) 312 445
Right di -> return di
let ipixelrgb81 = convertRGBA8 dyImage1
iWidth1 = fromIntegral $ imageWidth ipixelrgb81
iHeight1 = fromIntegral $ imageHeight ipixelrgb81
iData1 = imageData ipixelrgb81
VS.unsafeWith iData1 $ \dataP ->
glTexImage2D GL_TEXTURE_2D 0 GL_RGBA iWidth0 iHeight0 0 GL_RGBA GL_UNSIGNED_BYTE (castPtr dataP)
glGenerateMipmap GL_TEXTURE_2D
glBindTexture GL_TEXTURE_2D 0
I bind the first texture before drawing the first object like this:
-- first vao and shader program
glUseProgram ico_shaderProgram
glBindVertexArray ico_vao
-- bind first texture
glActiveTexture GL_TEXTURE0
glBindTexture GL_TEXTURE_2D diceText
diceTextureLocation <- glGetUniformLocation ico_shaderProgram diceTexture
glUniform1i diceTextureLocation 0
After calling glDrawArrays
on the first object, I unbind the first texture using glBindTexture_2D 0
.
The second texture is bound in a similar fashion:
-- second vao and shader
glUseProgram card_shaderProgram
glBindVertexArray card_vao
-- bind second texture
glActiveTexture GL_TEXTURE0
glBindTexture GL_TEXTURE_2D card_oneTexture
cardTextureLocation <- glGetUniformLocation card_shaderProgram cardTexture
glUniform1i cardTextureLocation 0
I call glBindTexture_2D 0
after the draw before re-entering the render loop.
The result looks like this:
As you can see, the object on the right has a few artifacts... The second texture is rendering on top of the first texture (which should only be on the first object). Moreover, the second texture is all distorted.
The verticies and uv coords for the second object can be found here (gist).
The shader used for this object is here (gist).
The attributes for the second object are set up like so:
-- second object attribs
glVertexAttribPointer 0 3 GL_FLOAT GL_FALSE (5*floatSize) nullPtr
glEnableVertexAttribArray 0
let threeFloatOffset = castPtr $ plusPtr nullPtr (fromIntegral $ 3*floatSize)
glVertexAttribPointer 1 2 GL_FLOAT GL_FALSE (5*floatSize) threeFloatOffset
glEnableVertexAttribArray 1
glBindVertexArray 0
I've tried to include the most relevant code. I would be very grateful if someone can spot my error. I am 100% willing to post more code if needed.
UPDATE:
Someone in the comments kindly pointed out that my code was using incorrect width and height values for the second texture. I am using this function to load in images now:
loadImageTexture :: [Char] -> Int -> Int -> IO (Image PixelRGBA8)
loadImageTexture filePath w h = do
errorOrDyImage <- readImage filePath
dyImage <- case errorOrDyImage of
Left e -> do
putStrLn e
return $ ImageRGBA8 $ generateImage (\x y ->
let x' = fromIntegral x in (PixelRGBA8 x' x' x' x')) w h
Right di -> return di
return $ convertRGBA8 dyImage