From 189f9f84fad4f7b22b90e679a91d4263f9ad3c13 Mon Sep 17 00:00:00 2001 From: Stefan Dresselhaus Date: Sat, 5 Apr 2014 15:53:49 +0200 Subject: [PATCH] Textures work now. Scene gets rendered and alpha-overlayed with HUD-Texture. fixes #472 @2h --- shaders/ui/fragment.shader | 7 ++- src/Main.hs | 111 +++++++++++++++++++++++++++++++++---- src/Render/Render.hs | 10 +++- src/Types.hs | 8 ++- 4 files changed, 117 insertions(+), 19 deletions(-) diff --git a/shaders/ui/fragment.shader b/shaders/ui/fragment.shader index bcc5b9f..9153586 100644 --- a/shaders/ui/fragment.shader +++ b/shaders/ui/fragment.shader @@ -1,10 +1,11 @@ #version 110 -uniform sampler2D tex; +uniform sampler2D tex[2]; varying vec2 texcoord; void main() { - - gl_FragColor = texture2D(tex, texcoord); + vec4 map = texture2D(tex[0], texcoord); + vec4 hud = texture2D(tex[1], texcoord); + gl_FragColor = vec4(mix(map.rgb,hud.rgb,hud.a),1.0); } \ No newline at end of file diff --git a/src/Main.hs b/src/Main.hs index fee5917..6083381 100644 --- a/src/Main.hs +++ b/src/Main.hs @@ -87,11 +87,18 @@ main = do withOpenGL window $ do --TTF.withInit $ do + --Create Renderbuffer & Framebuffer + -- We will render to this buffer to copy the result into textures + renderBuffer <- GL.genObjectName + frameBuffer <- GL.genObjectName + GL.bindFramebuffer GL.Framebuffer GL.$= frameBuffer + GL.bindRenderbuffer GL.Renderbuffer GL.$= renderBuffer + (Size fbWidth fbHeight) <- glGetDrawableSize window initRendering --generate map vertices (mapBuffer, vert) <- getMapBufferObject - (mapprog, ci, ni, vi, pri, vii, mi, nmi, tli, tlo) <- initMapShader + (mapprog, ci, ni, vi, pri, vii, mi, nmi, tli, tlo, mapTex) <- initMapShader putStrLn $ show window eventQueue <- newTQueueIO :: IO (TQueue Event) putStrLn "foo" @@ -130,6 +137,7 @@ main = do , _stateMap = mapBuffer , _mapVert = vert , _mapProgram = mapprog + , _mapTexture = mapTex } env = Env { _eventsChan = eventQueue @@ -176,6 +184,8 @@ main = do , _gl = GLState { _glMap = glMap , _glHud = glHud + , _glRenderbuffer = renderBuffer + , _glFramebuffer = frameBuffer } , _game = GameState { @@ -216,14 +226,52 @@ draw = do zDist' = state ^. camera.zDist tessFac = state ^. gl.glMap.stateTessellationFactor window = env ^. windowObject + rb = state ^. gl.glRenderbuffer prepareGUI liftIO $ do + --bind renderbuffer and set sample 0 as target + --GL.bindRenderbuffer GL.Renderbuffer GL.$= rb + --GL.bindFramebuffer GL.Framebuffer GL.$= GL.defaultFramebufferObject + --checkError "bind renderbuffer" + + --checkError "clear renderbuffer" + {-GL.framebufferRenderbuffer + GL.Framebuffer --framebuffer + (GL.ColorAttachment 1) --sample 1 + GL.Renderbuffer --const + rb --buffer + checkError "setup renderbuffer"-} + + -- draw map --(vi,GL.UniformLocation proj) <- initShader + + GL.bindFramebuffer GL.Framebuffer GL.$= (state ^. gl.glFramebuffer) + GL.bindRenderbuffer GL.Renderbuffer GL.$= (state ^. gl.glRenderbuffer) + GL.framebufferRenderbuffer + GL.Framebuffer + GL.DepthAttachment + GL.Renderbuffer + (state ^. gl.glRenderbuffer) + textureBinding GL.Texture2D GL.$= Just (state ^. gl.glMap.mapTexture) + + GL.framebufferTexture2D + GL.Framebuffer + (GL.ColorAttachment 0) + GL.Texture2D + (state ^. gl.glMap.mapTexture) + 0 + + -- Render to FrameBufferObject + GL.drawBuffers GL.$= [GL.FBOColorAttachment 0] + checkError "setup Render-Target" + GL.clear [GL.ColorBuffer, GL.DepthBuffer] + checkError "clear buffer" + GL.currentProgram GL.$= Just (state ^. gl.glMap.mapProgram) - checkError "clearing buffer" + checkError "setting up buffer" --set up projection (= copy from state) with (distribute frust) $ \ptr -> glUniformMatrix4fv proj 1 0 (castPtr (ptr :: Ptr (M44 CFloat))) @@ -264,13 +312,32 @@ draw = do glDrawArrays gl_PATCHES 0 (fromIntegral numVert) checkError "draw map" + -- set sample 1 as target in renderbuffer + {-GL.framebufferRenderbuffer + GL.DrawFramebuffer --write-only + (GL.ColorAttachment 1) --sample 1 + GL.Renderbuffer --const + rb --buffer-} + + -- Render to BackBuffer (=Screen) + GL.bindFramebuffer GL.Framebuffer GL.$= GL.defaultFramebufferObject + GL.drawBuffer GL.$= GL.BackBuffers -- Drawing HUD + GL.clear [GL.ColorBuffer, GL.DepthBuffer] + checkError "clear buffer" + let hud = state ^. gl.glHud stride = fromIntegral $ sizeOf (undefined::GLfloat) * 2 vad = GL.VertexArrayDescriptor 2 GL.Float stride offset0 GL.currentProgram GL.$= Just (hud ^. hudProgram) + GL.activeTexture GL.$= GL.TextureUnit 0 textureBinding GL.Texture2D GL.$= Just (hud ^. hudTexture) + GL.uniform (hud ^. hudTexIndex) GL.$= GL.Index1 (0::GL.GLint) + + GL.activeTexture GL.$= GL.TextureUnit 1 + textureBinding GL.Texture2D GL.$= Just (state ^. gl.glMap.mapTexture) + GL.uniform (hud ^. hudBackIndex) GL.$= GL.Index1 (1::GL.GLint) GL.bindBuffer GL.ArrayBuffer GL.$= Just (hud ^. hudVBO) GL.vertexAttribPointer (hud ^. hudVertexIndex) GL.$= (GL.ToFloat, vad) @@ -331,7 +398,7 @@ run = do mults = sin $ state ^. camera.yAngle modx x' = x' - 0.2 * kxrot * multc - 0.2 * kyrot * mults - mody y' = y' - 0.2 * kxrot * mults + mody y' = y' + 0.2 * kxrot * mults - 0.2 * kyrot * multc modify $ (camera.camPosition.x %~ modx) . (camera.camPosition.y %~ mody) @@ -383,20 +450,40 @@ adjustWindow = do frust = createFrustum fov near far ratio liftIO $ glViewport 0 0 (fromIntegral fbWidth) (fromIntegral fbHeight) modify $ camera.frustum .~ frust - liftIO $ do - let texid = state ^. gl.glHud.hudTexture - int = fromInteger . toInteger - textureBinding Texture2D GL.$= Just texid - checkError "bind HUD-Tex" - textureFilter Texture2D GL.$= ((Linear', Nothing), Linear') - checkError "filter HUD-Tex" + rb <- liftIO $ do + -- bind ints to CInt for lateron. + let fbCWidth = (fromInteger.toInteger) fbWidth + fbCHeight = (fromInteger.toInteger) fbHeight + -- free old renderbuffer & create new (reuse is NOT advised!) + GL.deleteObjectName (state ^. gl.glRenderbuffer) + renderBuffer <- GL.genObjectName + GL.bindRenderbuffer GL.Renderbuffer GL.$= renderBuffer + GL.renderbufferStorage + GL.Renderbuffer -- use the only available renderbuffer + -- - must be this constant. + GL.DepthComponent' -- 32-bit float-rgba-color + (GL.RenderbufferSize fbCWidth fbCHeight) -- size of buffer + + + let hudtexid = state ^. gl.glHud.hudTexture + maptexid = state ^. gl.glMap.mapTexture allocaBytes (fbWidth*fbHeight*4) $ \ptr -> do - let imData = take (fbWidth*fbHeight*4) (cycle [255,0,0,128] :: [Int8]) + let imData = take (fbWidth*fbHeight*4) (cycle [255,0,0,64] :: [Int8]) --putStrLn $ show imData pokeArray ptr imData - texImage2D Texture2D GL.NoProxy 0 RGBA8 (GL.TextureSize2D (int fbWidth) (int fbHeight)) 0 + -- HUD + textureBinding Texture2D GL.$= Just hudtexid + textureFilter Texture2D GL.$= ((Linear', Nothing), Linear') + texImage2D Texture2D GL.NoProxy 0 RGBA8 (GL.TextureSize2D fbCWidth fbCHeight) 0 + (GL.PixelData GL.RGBA GL.UnsignedByte ptr) + -- MAP + textureBinding Texture2D GL.$= Just maptexid + textureFilter Texture2D GL.$= ((Linear', Nothing), Linear') + texImage2D Texture2D GL.NoProxy 0 RGBA8 (GL.TextureSize2D fbCWidth fbCHeight) 0 (GL.PixelData GL.RGBA GL.UnsignedByte ptr) checkError "setting up HUD-Tex" + return renderBuffer + modify $ gl.glRenderbuffer .~ rb processEvents :: Pioneers () processEvents = do diff --git a/src/Render/Render.hs b/src/Render/Render.hs index 3b1aaf8..d45a9c4 100644 --- a/src/Render/Render.hs +++ b/src/Render/Render.hs @@ -12,6 +12,7 @@ import Graphics.Rendering.OpenGL.GL.ObjectName import Graphics.Rendering.OpenGL.GL.PerFragment import Graphics.Rendering.OpenGL.GL.Shaders import Graphics.Rendering.OpenGL.GL.StateVar +import Graphics.Rendering.OpenGL.GL.Texturing.Objects (TextureObject) import Graphics.Rendering.OpenGL.GL.VertexArrays (Capability (..), vertexAttribArray, VertexArrayDescriptor, @@ -62,6 +63,7 @@ initMapShader :: IO ( , UniformLocation -- ^ NormalMat , UniformLocation -- ^ TessLevelInner , UniformLocation -- ^ TessLevelOuter + , TextureObject -- ^ Texture where to draw into ) initMapShader = do ! vertexSource <- B.readFile mapVertexShaderFile @@ -117,8 +119,10 @@ initMapShader = do putStrLn $ unlines $ "Attributes: ":map show att putStrLn $ unlines $ ["Indices: ", show (colorIndex, normalIndex, vertexIndex)] + tex <- genObjectName + checkError "initShader" - return (program, colorIndex, normalIndex, vertexIndex, projectionMatrixIndex, viewMatrixIndex, modelMatrixIndex, normalMatrixIndex, tessLevelInner, tessLevelOuter) + return (program, colorIndex, normalIndex, vertexIndex, projectionMatrixIndex, viewMatrixIndex, modelMatrixIndex, normalMatrixIndex, tessLevelInner, tessLevelOuter, tex) initHud :: IO GLHud initHud = do @@ -135,7 +139,8 @@ initHud = do currentProgram $= Just program - texIndex <- get (uniformLocation program "tex") + backIndex <- get (uniformLocation program "tex[0]") + texIndex <- get (uniformLocation program "tex[1]") checkError "ui-tex" -- | simple triangle over the whole screen. @@ -157,6 +162,7 @@ initHud = do return GLHud { _hudTexture = tex , _hudTexIndex = texIndex + , _hudBackIndex = backIndex , _hudVertexIndex = vertexIndex , _hudVert = 4 , _hudVBO = vbo diff --git a/src/Types.hs b/src/Types.hs index c48351d..d3811ea 100644 --- a/src/Types.hs +++ b/src/Types.hs @@ -87,11 +87,13 @@ data GLMapState = GLMapState , _stateMap :: !GL.BufferObject , _mapVert :: !GL.NumArrayIndices , _mapProgram :: !GL.Program + , _mapTexture :: !TextureObject } data GLHud = GLHud - { _hudTexture :: !TextureObject -- ^ Texture itself - , _hudTexIndex :: !GL.UniformLocation -- ^ Position of Texture in Shader + { _hudTexture :: !TextureObject -- ^ HUD-Texture itself + , _hudTexIndex :: !GL.UniformLocation -- ^ Position of Overlay-Texture in Shader + , _hudBackIndex :: !GL.UniformLocation -- ^ Position of Background-Texture in Shader , _hudVertexIndex :: !GL.AttribLocation -- ^ Position of Vertices in Shader , _hudVert :: !GL.NumArrayIndices -- ^ Number of Vertices to draw , _hudVBO :: !GL.BufferObject -- ^ Vertex-Buffer-Object @@ -102,6 +104,8 @@ data GLHud = GLHud data GLState = GLState { _glMap :: !GLMapState , _glHud :: !GLHud + , _glRenderbuffer :: !GL.RenderbufferObject + , _glFramebuffer :: !GL.FramebufferObject } data UIState = UIState