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