1 /* 2 Copyright (c) 2022 Timur Gafarov 3 4 Boost Software License - Version 1.0 - August 17th, 2003 5 Permission is hereby granted, free of charge, to any person or organization 6 obtaining a copy of the software and accompanying documentation covered by 7 this license (the "Software") to use, reproduce, display, distribute, 8 execute, and transmit the Software, and to prepare derivative works of the 9 Software, and to permit third-parties to whom the Software is furnished to 10 do so, all subject to the following: 11 12 The copyright notices in the Software and this entire statement, including 13 the above license grant, this restriction and the following disclaimer, 14 must be included in all copies of the Software, in whole or in part, and 15 all derivative works of the Software, unless such copies or derivative 16 works are solely in the form of machine-executable object code generated by 17 a source language processor. 18 19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 22 SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 23 FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 24 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 DEALINGS IN THE SOFTWARE. 26 */ 27 module dagon.graphics.texproc; 28 29 import std.stdio; 30 31 import dlib.core.memory; 32 import dlib.core.ownership; 33 import dlib.math.vector; 34 import dlib.math.matrix; 35 import dlib.math.transformation; 36 import dlib.image.color; 37 import dlib.text.str; 38 39 import dagon.core.bindings; 40 import dagon.graphics.texture; 41 import dagon.graphics.shader; 42 import dagon.graphics.state; 43 import dagon.graphics.screensurface; 44 45 class TextureCombinerShader: Shader 46 { 47 String vs, fs; 48 Texture[4] channels; 49 50 this(Texture[4] channels, Owner owner) 51 { 52 vs = Shader.load("data/__internal/shaders/TextureCombiner/TextureCombiner.vert.glsl"); 53 fs = Shader.load("data/__internal/shaders/TextureCombiner/TextureCombiner.frag.glsl"); 54 55 auto myProgram = New!ShaderProgram(vs, fs, this); 56 super(myProgram, owner); 57 58 this.channels[] = channels[]; 59 } 60 61 ~this() 62 { 63 vs.free(); 64 fs.free(); 65 } 66 67 override void bindParameters(GraphicsState* state) 68 { 69 // Channel0 70 glActiveTexture(GL_TEXTURE0); 71 setParameter("texChannel0", cast(int)0); 72 setParameter("valueChannel0", 0.0f); 73 if (channels[0]) 74 { 75 channels[0].bind(); 76 setParameterSubroutine("channel0", ShaderType.Fragment, "channel0Texture"); 77 } 78 else 79 { 80 glBindTexture(GL_TEXTURE_2D, 0); 81 setParameterSubroutine("channel0", ShaderType.Fragment, "channel0Value"); 82 } 83 84 // Channel1 85 glActiveTexture(GL_TEXTURE1); 86 setParameter("texChannel1", cast(int)1); 87 setParameter("valueChannel1", 0.0f); 88 if (channels[1]) 89 { 90 channels[1].bind(); 91 setParameterSubroutine("channel1", ShaderType.Fragment, "channel1Texture"); 92 } 93 else 94 { 95 glBindTexture(GL_TEXTURE_2D, 0); 96 setParameterSubroutine("channel1", ShaderType.Fragment, "channel1Value"); 97 } 98 99 // Channel2 100 glActiveTexture(GL_TEXTURE2); 101 setParameter("texChannel2", cast(int)2); 102 setParameter("valueChannel2", 0.0f); 103 if (channels[2]) 104 { 105 channels[2].bind(); 106 setParameterSubroutine("channel2", ShaderType.Fragment, "channel2Texture"); 107 } 108 else 109 { 110 glBindTexture(GL_TEXTURE_2D, 0); 111 setParameterSubroutine("channel2", ShaderType.Fragment, "channel2Value"); 112 } 113 114 // Channel3 115 glActiveTexture(GL_TEXTURE3); 116 setParameter("texChannel3", cast(int)3); 117 setParameter("valueChannel3", 0.0f); 118 if (channels[3]) 119 { 120 channels[3].bind(); 121 setParameterSubroutine("channel3", ShaderType.Fragment, "channel3Texture"); 122 } 123 else 124 { 125 glBindTexture(GL_TEXTURE_2D, 0); 126 setParameterSubroutine("channel3", ShaderType.Fragment, "channel3Value"); 127 } 128 129 glActiveTexture(GL_TEXTURE0); 130 131 super.bindParameters(state); 132 } 133 134 override void unbindParameters(GraphicsState* state) 135 { 136 super.unbindParameters(state); 137 138 glActiveTexture(GL_TEXTURE0); 139 glBindTexture(GL_TEXTURE_2D, 0); 140 141 glActiveTexture(GL_TEXTURE1); 142 glBindTexture(GL_TEXTURE_2D, 0); 143 144 glActiveTexture(GL_TEXTURE2); 145 glBindTexture(GL_TEXTURE_2D, 0); 146 147 glActiveTexture(GL_TEXTURE3); 148 glBindTexture(GL_TEXTURE_2D, 0); 149 150 glActiveTexture(GL_TEXTURE0); 151 } 152 } 153 154 /// Combine up to 4 textures to one 155 void combineTextures(Texture[4] channels, Texture output) 156 { 157 GLuint framebuffer; 158 glGenFramebuffers(1, &framebuffer); 159 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); 160 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, output.texture, 0); 161 GLenum[1] drawBuffers = [GL_COLOR_ATTACHMENT0]; 162 glDrawBuffers(drawBuffers.length, drawBuffers.ptr); 163 GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); 164 if (status != GL_FRAMEBUFFER_COMPLETE) 165 { 166 writeln(status); 167 } 168 169 ScreenSurface screenSurface = New!ScreenSurface(null); 170 TextureCombinerShader shader = New!TextureCombinerShader(channels, null); 171 172 GraphicsState state; 173 state.reset(); 174 state.resolution = Vector2f(output.size.width, output.size.height); 175 176 glScissor(0, 0, output.size.width, output.size.height); 177 glViewport(0, 0, output.size.width, output.size.height); 178 179 glDisable(GL_DEPTH_TEST); 180 glDepthMask(GL_FALSE); 181 shader.bind(); 182 shader.bindParameters(&state); 183 screenSurface.render(&state); 184 shader.unbindParameters(&state); 185 shader.unbind(); 186 glDepthMask(GL_TRUE); 187 glEnable(GL_DEPTH_TEST); 188 189 Delete(shader); 190 Delete(screenSurface); 191 192 glBindFramebuffer(GL_FRAMEBUFFER, 0); 193 glDeleteFramebuffers(1, &framebuffer); 194 } 195 196 /// ditto 197 Texture combineTextures(uint w, uint h, Texture[4] channels, Owner owner) 198 { 199 Texture output = New!Texture(owner); 200 output.createBlank(w, h, 4, 8, false, Color4f(0.0f, 0.0f, 0.0f, 1.0f)); 201 combineTextures(channels, output); 202 output.generateMipmap(); 203 return output; 204 }