/ fbo_example.lua
fbo_example.lua
1 -- File: fbo_example.lua 2 3 --[[ 4 Copyright (C) 2024 chmod777 5 6 This program is free software: you can redistribute it and/or modify it under 7 the terms of the GNU Affero General Public License version 3 as published by the 8 Free Software Foundation. 9 10 This program is distributed in the hope that it will be useful, but WITHOUT ANY 11 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 12 PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. 13 14 You should have received a copy of the GNU Affero General Public License along 15 with this program. If not, see <https://www.gnu.org/licenses/>. 16 ]] 17 18 function widget:GetInfo() 19 return { 20 name = 'FBO example', 21 desc = 'A minimal FBO example. Requires chmod777_includes/utilites_GL4.lua', 22 author = 'chmod777', 23 date = 'May 2024', 24 license = 'GNU AGPL v3', 25 layer = 0, 26 enabled = true, 27 } 28 end 29 30 local luaWidgetDir = 'LuaUI/Widgets/' 31 local luaIncludeDir = luaWidgetDir..'Include/' 32 local LuaShader = VFS.Include(luaIncludeDir..'LuaShader.lua') 33 local Quad, FBO = VFS.Include(luaWidgetDir..'chmod777_includes/utilities_GL4.lua') 34 35 local quadVsSrc = [[ 36 #version 420 37 38 layout (location = 0) in vec2 coords; 39 layout (location = 1) in vec2 uv; 40 41 uniform vec2 viewGeometry; 42 uniform vec2 screenPos; 43 uniform float imgSize; 44 45 out DataVS { 46 vec2 uv; 47 } vs_out; 48 49 void main() { 50 vs_out.uv = uv; 51 52 vec2 coord = coords; 53 54 coord = fma(coord, vec2(imgSize*0.5), screenPos) / viewGeometry; 55 coord = fma(coord, vec2(2.0), vec2(-1.0)); 56 57 gl_Position = vec4(coord, 0.0, 1.0); 58 } 59 ]] 60 local quadFsSrc = [[ 61 #version 420 62 63 #extension GL_ARB_uniform_buffer_object : require 64 #extension GL_ARB_shading_language_420pack: require 65 66 layout (binding = 0) uniform sampler2D img; 67 68 in DataVS { 69 vec2 uv; 70 } vs_in; 71 72 out vec4 fragColor; 73 74 void main() { 75 fragColor = texture(img, vs_in.uv); 76 } 77 ]] 78 79 local vsSrc = [[ 80 #version 420 81 82 layout (location = 0) in vec2 coords; 83 layout (location = 1) in vec2 uv; 84 85 out DataVS { 86 vec2 uv; 87 } vs_out; 88 89 void main() { 90 vs_out.uv = uv; 91 gl_Position = vec4(coords, 0.0, 1.0); 92 } 93 ]] 94 95 local fsSrc = [[ 96 #version 420 97 98 #extension GL_ARB_uniform_buffer_object : require 99 #extension GL_ARB_shading_language_420pack: require 100 101 layout (binding = 0) uniform sampler2D imgTop; 102 layout (binding = 1) uniform sampler2D imgLeft; 103 layout (binding = 2) uniform sampler2D imgRight; 104 105 const vec2 OFFSET_TOP = vec2(0.0, 0.0); 106 const vec2 OFFSET_LEFT = vec2(0.4, 0.0); 107 const vec2 OFFSET_RIGHT = vec2(-0.3, 0.0); 108 109 in DataVS { 110 vec2 uv; 111 } vs_in; 112 113 out vec4 fragColor; 114 115 void main() { 116 vec2 uv = vs_in.uv; 117 vec4 top = texture(imgTop, uv + OFFSET_TOP); 118 vec4 left = texture(imgLeft, uv + OFFSET_LEFT); 119 vec4 right = texture(imgRight, uv + OFFSET_RIGHT); 120 121 if (uv.y < 0.5) { 122 fragColor = top; 123 if (1 - uv.x < uv.y) { 124 fragColor = right; 125 } 126 if (uv.x < uv.y) { 127 fragColor = left; 128 } 129 } else if (uv.x > 0.5) { 130 fragColor = right; 131 } else { 132 fragColor = left; 133 } 134 } 135 ]] 136 137 local fbo 138 139 local combiningShader 140 local combiningQuad 141 local imgSize = 256 142 143 local screenQuadShader 144 local screenQuadUniformLocs = {} 145 local screenQuad 146 147 local glViewport = gl.Viewport 148 local glClear = gl.Clear 149 local glTexture = gl.Texture 150 local glUniform = gl.Uniform 151 local GL_COLOR_BUFFER_BIT = GL.COLOR_BUFFER_BIT 152 153 function widget:Initialize() 154 combiningShader = LuaShader({ 155 vertex = vsSrc, 156 fragment = fsSrc, 157 }, 'Combining Shader') 158 local combiningShaderCompiled = combiningShader:Initialize() 159 if not combiningShaderCompiled then 160 Spring.Echo('Img Shader: compilation failed') 161 widgetHandler:RemoveWidget() 162 end 163 combiningQuad = Quad:new(-1,-1, 1, 1, true) 164 165 screenQuadShader = LuaShader({ 166 vertex = quadVsSrc, 167 fragment = quadFsSrc, 168 }, 'Quad Shader') 169 local quadShaderCompiled = screenQuadShader:Initialize() 170 if not quadShaderCompiled then 171 Spring.Echo('Quad Shader: compilation failed') 172 widgetHandler:RemoveWidget() 173 end 174 175 local shader = screenQuadShader.shaderObj; 176 screenQuadUniformLocs['screenPos'] = gl.GetUniformLocation(shader, 'screenPos') 177 screenQuadUniformLocs['imgSize'] = gl.GetUniformLocation(shader, 'imgSize') 178 screenQuadUniformLocs['viewGeometry'] = gl.GetUniformLocation(shader, 'viewGeometry') 179 180 screenQuad = Quad:new() 181 182 fbo = FBO:new(imgSize, imgSize, false) 183 end 184 185 function widget:Shutdown() 186 if fbo ~= nil then fbo:Delete() end 187 188 if screenQuadShader ~= nil then screenQuadShader:Delete() end 189 if combineShader ~= nil then combineShader:Delete() end 190 191 if screenQuad ~= nil then screenQuad:Delete() end 192 if combiningQuad ~= nil then combiningQuad:Delete() end 193 end 194 195 function DrawCombined() 196 combiningShader:Activate() 197 glTexture(0, "unitpics/armcom.dds") 198 glTexture(1, "unitpics/corcom.dds") 199 glTexture(2, "unitpics/armgeo.dds") 200 combiningQuad:draw() 201 glTexture(0, false) 202 glTexture(1, false) 203 glTexture(2, false) 204 combiningShader:Deactivate() 205 end 206 207 function widget:DrawScreen() 208 local viewGeometryX,viewGeometryY = Spring.GetViewGeometry() 209 210 glViewport(0, 0, imgSize, imgSize) 211 -- Show preview in bottom of screen 212 DrawCombined() 213 214 -- render to a texture(fbo.tex) 215 fbo:bind() 216 glClear(GL_COLOR_BUFFER_BIT, 0,0,0,0) 217 DrawCombined() 218 fbo:unbind() 219 glViewport(0, 0, viewGeometryX, viewGeometryY) 220 221 -- display the texture on a quad in the center of the screen 222 screenQuadShader:Activate() 223 glTexture(0, fbo.tex) 224 glUniform(screenQuadUniformLocs['imgSize'], imgSize) 225 glUniform(screenQuadUniformLocs['screenPos'], viewGeometryX/2, viewGeometryY/2) 226 glUniform(screenQuadUniformLocs['viewGeometry'], viewGeometryX, viewGeometryY) 227 screenQuad:draw() 228 glTexture(0, false) 229 screenQuadShader:Deactivate() 230 end