1 /* 2 Copyright (c) 2019-2020 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 28 module dagon.render.shaders.decal; 29 30 import std.stdio; 31 import std.math; 32 33 import dlib.core.memory; 34 import dlib.core.ownership; 35 import dlib.math.vector; 36 import dlib.math.matrix; 37 import dlib.math.transformation; 38 import dlib.math.interpolation; 39 import dlib.image.color; 40 import dlib.text.str; 41 42 import dagon.core.bindings; 43 import dagon.graphics.material; 44 import dagon.graphics.shader; 45 import dagon.graphics.state; 46 import dagon.render.gbuffer; 47 48 class DecalShader: Shader 49 { 50 String vs, fs; 51 52 GBuffer gbuffer; 53 54 this(GBuffer gbuffer, Owner owner) 55 { 56 vs = Shader.load("data/__internal/shaders/Decal/Decal.vert.glsl"); 57 fs = Shader.load("data/__internal/shaders/Decal/Decal.frag.glsl"); 58 59 auto prog = New!ShaderProgram(vs, fs, this); 60 super(prog, owner); 61 62 this.gbuffer = gbuffer; 63 } 64 65 ~this() 66 { 67 vs.free(); 68 fs.free(); 69 } 70 71 override void bindParameters(GraphicsState* state) 72 { 73 auto idiffuse = "diffuse" in state.material.inputs; 74 auto inormal = "normal" in state.material.inputs; 75 auto iheight = "height" in state.material.inputs; 76 auto iparallax = "parallax" in state.material.inputs; 77 auto iroughnessMetallic = "roughnessMetallic" in state.material.inputs; 78 auto iroughness = "roughness" in state.material.inputs; 79 auto imetallic = "metallic" in state.material.inputs; 80 auto ispecularity = "specularity" in state.material.inputs; 81 auto itextureScale = "textureScale" in state.material.inputs; 82 auto iemission = "emission" in state.material.inputs; 83 auto ienergy = "energy" in state.material.inputs; 84 auto ioutputColor = "outputColor" in state.material.inputs; 85 auto ioutputNormal = "outputNormal" in state.material.inputs; 86 auto ioutputPBR = "outputPBR" in state.material.inputs; 87 auto ioutputEmission = "outputEmission" in state.material.inputs; 88 89 int parallaxMethod = iparallax.asInteger; 90 if (parallaxMethod > ParallaxOcclusionMapping) 91 parallaxMethod = ParallaxOcclusionMapping; 92 if (parallaxMethod < 0) 93 parallaxMethod = 0; 94 95 setParameter("modelViewMatrix", state.modelViewMatrix); 96 setParameter("projectionMatrix", state.projectionMatrix); 97 setParameter("invProjectionMatrix", state.invProjectionMatrix); 98 setParameter("normalMatrix", state.normalMatrix); 99 setParameter("viewMatrix", state.viewMatrix); 100 setParameter("invViewMatrix", state.invViewMatrix); 101 setParameter("invModelMatrix", state.invModelMatrix); 102 setParameter("resolution", state.resolution); 103 104 setParameter("opacity", state.opacity); 105 setParameter("textureScale", itextureScale.asVector2f); 106 107 glActiveTexture(GL_TEXTURE0); 108 glBindTexture(GL_TEXTURE_2D, gbuffer.depthTexture); 109 setParameter("depthTexture", cast(int)0); 110 111 // Diffuse 112 if (idiffuse.texture) 113 { 114 glActiveTexture(GL_TEXTURE1); 115 idiffuse.texture.bind(); 116 setParameter("diffuseTexture", cast(int)1); 117 setParameterSubroutine("diffuse", ShaderType.Fragment, "diffuseColorTexture"); 118 } 119 else 120 { 121 setParameter("diffuseVector", idiffuse.asVector4f); 122 setParameterSubroutine("diffuse", ShaderType.Fragment, "diffuseColorValue"); 123 } 124 125 if (!ioutputColor.asBool) 126 { 127 glColorMaski(0, 0, 0, 0, 0); 128 } 129 130 // Normal/height 131 bool haveHeightMap = inormal.texture !is null; 132 if (haveHeightMap) 133 haveHeightMap = inormal.texture.image.channels == 4; 134 135 if (!haveHeightMap) 136 { 137 if (inormal.texture is null) 138 { 139 if (iheight.texture !is null) // we have height map, but no normal map 140 { 141 Color4f color = Color4f(0.5f, 0.5f, 1.0f, 0.0f); // default normal pointing upwards 142 inormal.texture = state.material.makeTexture(color, iheight.texture); 143 haveHeightMap = true; 144 } 145 } 146 else 147 { 148 if (iheight.texture !is null) // we have both normal and height maps 149 { 150 inormal.texture = state.material.makeTexture(inormal.texture, iheight.texture); 151 haveHeightMap = true; 152 } 153 } 154 } 155 156 if (inormal.texture) 157 { 158 setParameter("normalTexture", 2); 159 setParameterSubroutine("normal", ShaderType.Fragment, "normalMap"); 160 161 glActiveTexture(GL_TEXTURE2); 162 inormal.texture.bind(); 163 } 164 else 165 { 166 setParameter("normalVector", state.material.normal.asVector3f); 167 setParameterSubroutine("normal", ShaderType.Fragment, "normalValue"); 168 } 169 170 if (!ioutputNormal.asBool) 171 { 172 glColorMaski(1, 0, 0, 0, 0); 173 } 174 175 // Height and parallax 176 // TODO: make these material properties 177 float parallaxScale = 0.03f; 178 float parallaxBias = -0.01f; 179 setParameter("parallaxScale", parallaxScale); 180 setParameter("parallaxBias", parallaxBias); 181 182 if (haveHeightMap) 183 { 184 setParameterSubroutine("height", ShaderType.Fragment, "heightMap"); 185 } 186 else 187 { 188 float h = 0.0f; //-parallaxBias / parallaxScale; 189 setParameter("heightScalar", h); 190 setParameterSubroutine("height", ShaderType.Fragment, "heightValue"); 191 parallaxMethod = ParallaxNone; 192 } 193 194 if (parallaxMethod == ParallaxSimple) 195 setParameterSubroutine("parallax", ShaderType.Fragment, "parallaxSimple"); 196 else if (parallaxMethod == ParallaxOcclusionMapping) 197 setParameterSubroutine("parallax", ShaderType.Fragment, "parallaxOcclusionMapping"); 198 else 199 setParameterSubroutine("parallax", ShaderType.Fragment, "parallaxNone"); 200 201 // PBR 202 if (iroughnessMetallic is null) 203 { 204 state.material.setInput("roughnessMetallic", 0.0f); 205 iroughnessMetallic = "roughnessMetallic" in state.material.inputs; 206 } 207 if (iroughnessMetallic.texture is null) 208 { 209 iroughnessMetallic.texture = state.material.makeTexture(*ispecularity, *iroughness, *imetallic, materialInput(0.0f)); 210 } 211 glActiveTexture(GL_TEXTURE3); 212 iroughnessMetallic.texture.bind(); 213 setParameter("pbrTexture", 3); 214 215 setParameterSubroutine("specularity", ShaderType.Fragment, "specularityMap"); 216 setParameterSubroutine("metallic", ShaderType.Fragment, "metallicMap"); 217 setParameterSubroutine("roughness", ShaderType.Fragment, "roughnessMap"); 218 219 if (!ioutputPBR.asBool) 220 { 221 glColorMaski(2, 0, 0, 0, 0); 222 } 223 224 // Emission 225 if (iemission.texture) 226 { 227 glActiveTexture(GL_TEXTURE4); 228 iemission.texture.bind(); 229 setParameter("emissionTexture", cast(int)4); 230 setParameterSubroutine("emission", ShaderType.Fragment, "emissionMap"); 231 } 232 else 233 { 234 setParameter("emissionVector", iemission.asVector4f); 235 setParameterSubroutine("emission", ShaderType.Fragment, "emissionValue"); 236 } 237 setParameter("energy", ienergy.asFloat); 238 239 if (!ioutputEmission.asBool) 240 { 241 glColorMaski(3, 0, 0, 0, 0); 242 } 243 244 glActiveTexture(GL_TEXTURE0); 245 246 super.bindParameters(state); 247 } 248 249 override void unbindParameters(GraphicsState* state) 250 { 251 super.unbindParameters(state); 252 253 glColorMaski(0, 1, 1, 1, 1); 254 glColorMaski(1, 1, 1, 1, 1); 255 glColorMaski(2, 1, 1, 1, 1); 256 glColorMaski(3, 1, 1, 1, 1); 257 258 glActiveTexture(GL_TEXTURE0); 259 glBindTexture(GL_TEXTURE_2D, 0); 260 261 glActiveTexture(GL_TEXTURE1); 262 glBindTexture(GL_TEXTURE_2D, 0); 263 264 glActiveTexture(GL_TEXTURE2); 265 glBindTexture(GL_TEXTURE_2D, 0); 266 267 glActiveTexture(GL_TEXTURE3); 268 glBindTexture(GL_TEXTURE_2D, 0); 269 270 glActiveTexture(GL_TEXTURE4); 271 glBindTexture(GL_TEXTURE_2D, 0); 272 273 glActiveTexture(GL_TEXTURE0); 274 } 275 }