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