1 /* 2 Copyright (c) 2019 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 ipbr = "pbr" 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 itranslucency = "translucency" in state.material.inputs; 76 auto itextureScale = "textureScale" in state.material.inputs; 77 auto iparallax = "parallax" in state.material.inputs; 78 auto iemission = "emission" in state.material.inputs; 79 auto ienergy = "energy" in state.material.inputs; 80 auto isphericalNormal = "sphericalNormal" in state.material.inputs; 81 82 setParameter("modelViewMatrix", state.modelViewMatrix); 83 setParameter("projectionMatrix", state.projectionMatrix); 84 setParameter("normalMatrix", state.normalMatrix); 85 setParameter("viewMatrix", state.viewMatrix); 86 setParameter("invViewMatrix", state.invViewMatrix); 87 setParameter("prevModelViewMatrix", state.prevModelViewMatrix); 88 89 setParameter("layer", cast(float)(state.layer)); 90 setParameter("opacity", state.opacity); 91 setParameter("textureScale", itextureScale.asVector2f); 92 93 int parallaxMethod = iparallax.asInteger; 94 if (parallaxMethod > ParallaxOcclusionMapping) 95 parallaxMethod = ParallaxOcclusionMapping; 96 if (parallaxMethod < 0) 97 parallaxMethod = 0; 98 99 setParameter("sphericalNormal", cast(int)isphericalNormal.asBool); 100 101 // Diffuse 102 if (idiffuse.texture) 103 { 104 glActiveTexture(GL_TEXTURE0); 105 idiffuse.texture.bind(); 106 setParameter("diffuseTexture", cast(int)0); 107 setParameterSubroutine("diffuse", ShaderType.Fragment, "diffuseColorTexture"); 108 } 109 else 110 { 111 setParameter("diffuseVector", idiffuse.asVector4f); 112 setParameterSubroutine("diffuse", ShaderType.Fragment, "diffuseColorValue"); 113 } 114 115 // Normal/height 116 bool haveHeightMap = inormal.texture !is null; 117 if (haveHeightMap) 118 haveHeightMap = inormal.texture.image.channels == 4; 119 120 if (!haveHeightMap) 121 { 122 if (inormal.texture is null) 123 { 124 if (iheight.texture !is null) // we have height map, but no normal map 125 { 126 Color4f color = Color4f(0.5f, 0.5f, 1.0f, 0.0f); // default normal pointing upwards 127 inormal.texture = state.material.makeTexture(color, iheight.texture); 128 haveHeightMap = true; 129 } 130 else 131 { 132 Color4f color = Color4f(0.5f, 0.5f, 1.0f, 0.0f); // default normal pointing upwards 133 inormal.texture = state.material.makeTexture(color); 134 } 135 } 136 else 137 { 138 if (iheight.texture !is null) // we have both normal and height maps 139 { 140 inormal.texture = state.material.makeTexture(inormal.texture, iheight.texture); 141 haveHeightMap = true; 142 } 143 } 144 } 145 146 if (inormal.texture) 147 { 148 setParameter("normalTexture", 1); 149 setParameterSubroutine("normal", ShaderType.Fragment, "normalMap"); 150 151 glActiveTexture(GL_TEXTURE1); 152 inormal.texture.bind(); 153 } 154 else 155 { 156 setParameter("normalVector", state.material.normal.asVector3f); 157 setParameterSubroutine("normal", ShaderType.Fragment, "normalValue"); 158 } 159 160 // Height and parallax 161 // TODO: make these material properties 162 float parallaxScale = 0.03f; 163 float parallaxBias = -0.01f; 164 setParameter("parallaxScale", parallaxScale); 165 setParameter("parallaxBias", parallaxBias); 166 167 if (haveHeightMap) 168 { 169 setParameterSubroutine("height", ShaderType.Fragment, "heightMap"); 170 } 171 else 172 { 173 float h = 0.0f; //-parallaxBias / parallaxScale; 174 setParameter("heightScalar", h); 175 setParameterSubroutine("height", ShaderType.Fragment, "heightValue"); 176 parallaxMethod = ParallaxNone; 177 } 178 179 if (parallaxMethod == ParallaxSimple) 180 setParameterSubroutine("parallax", ShaderType.Fragment, "parallaxSimple"); 181 else if (parallaxMethod == ParallaxOcclusionMapping) 182 setParameterSubroutine("parallax", ShaderType.Fragment, "parallaxOcclusionMapping"); 183 else 184 setParameterSubroutine("parallax", ShaderType.Fragment, "parallaxNone"); 185 186 // PBR 187 if (ipbr is null) 188 { 189 state.material.setInput("pbr", 0.0f); 190 ipbr = "pbr" in state.material.inputs; 191 } 192 if (ipbr.texture is null) 193 { 194 ipbr.texture = state.material.makeTexture(*iroughness, *imetallic, *ispecularity, *itranslucency); 195 } 196 glActiveTexture(GL_TEXTURE2); 197 ipbr.texture.bind(); 198 setParameter("pbrTexture", 2); 199 200 if (iroughness.texture is null) 201 { 202 setParameterSubroutine("roughness", ShaderType.Fragment, "roughnessValue"); 203 204 if (iroughness.type == MaterialInputType.Float) 205 setParameter("roughnessScalar", iroughness.asFloat); 206 else if (iroughness.type == MaterialInputType.Bool) 207 setParameter("roughnessScalar", cast(float)iroughness.asBool); 208 else if (iroughness.type == MaterialInputType.Integer) 209 setParameter("roughnessScalar", cast(float)iroughness.asInteger); 210 else if (iroughness.type == MaterialInputType.Vec2) 211 setParameter("roughnessScalar", iroughness.asVector2f.r); 212 else if (iroughness.type == MaterialInputType.Vec3) 213 setParameter("roughnessScalar", iroughness.asVector3f.r); 214 else if (iroughness.type == MaterialInputType.Vec4) 215 setParameter("roughnessScalar", iroughness.asVector4f.r); 216 } 217 else 218 { 219 setParameterSubroutine("roughness", ShaderType.Fragment, "roughnessMap"); 220 } 221 222 if (imetallic.texture is null) 223 { 224 setParameterSubroutine("metallic", ShaderType.Fragment, "metallicValue"); 225 226 if (imetallic.type == MaterialInputType.Float) 227 setParameter("metallicScalar", imetallic.asFloat); 228 else if (imetallic.type == MaterialInputType.Bool) 229 setParameter("metallicScalar", cast(float)imetallic.asBool); 230 else if (imetallic.type == MaterialInputType.Integer) 231 setParameter("metallicScalar", cast(float)imetallic.asInteger); 232 else if (imetallic.type == MaterialInputType.Vec2) 233 setParameter("metallicScalar", imetallic.asVector2f.r); 234 else if (imetallic.type == MaterialInputType.Vec3) 235 setParameter("metallicScalar", imetallic.asVector3f.r); 236 else if (imetallic.type == MaterialInputType.Vec4) 237 setParameter("metallicScalar", imetallic.asVector4f.r); 238 } 239 else 240 { 241 setParameterSubroutine("metallic", ShaderType.Fragment, "metallicMap"); 242 } 243 244 if (ispecularity.texture is null) 245 { 246 setParameterSubroutine("specularity", ShaderType.Fragment, "specularityValue"); 247 248 if (ispecularity.type == MaterialInputType.Float) 249 setParameter("specularityScalar", ispecularity.asFloat); 250 else if (ispecularity.type == MaterialInputType.Bool) 251 setParameter("specularityScalar", cast(float)ispecularity.asBool); 252 else if (ispecularity.type == MaterialInputType.Integer) 253 setParameter("specularityScalar", cast(float)ispecularity.asInteger); 254 else if (ispecularity.type == MaterialInputType.Vec2) 255 setParameter("specularityScalar", ispecularity.asVector2f.r); 256 else if (ispecularity.type == MaterialInputType.Vec3) 257 setParameter("specularityScalar", ispecularity.asVector3f.r); 258 else if (ispecularity.type == MaterialInputType.Vec4) 259 setParameter("specularityScalar", ispecularity.asVector4f.r); 260 } 261 else 262 { 263 setParameterSubroutine("specularity", ShaderType.Fragment, "specularityMap"); 264 } 265 266 if (itranslucency.texture is null) 267 { 268 setParameterSubroutine("translucency", ShaderType.Fragment, "translucencyValue"); 269 270 if (itranslucency.type == MaterialInputType.Float) 271 setParameter("translucencyScalar", itranslucency.asFloat); 272 else if (itranslucency.type == MaterialInputType.Bool) 273 setParameter("translucencyScalar", cast(float)itranslucency.asBool); 274 else if (itranslucency.type == MaterialInputType.Integer) 275 setParameter("translucencyScalar", cast(float)itranslucency.asInteger); 276 else if (itranslucency.type == MaterialInputType.Vec2) 277 setParameter("translucencyScalar", itranslucency.asVector2f.r); 278 else if (itranslucency.type == MaterialInputType.Vec3) 279 setParameter("translucencyScalar", itranslucency.asVector3f.r); 280 else if (itranslucency.type == MaterialInputType.Vec4) 281 setParameter("translucencyScalar", itranslucency.asVector4f.r); 282 } 283 else 284 { 285 setParameterSubroutine("translucency", ShaderType.Fragment, "translucencyMap"); 286 } 287 288 // Emission 289 if (iemission.texture) 290 { 291 glActiveTexture(GL_TEXTURE3); 292 iemission.texture.bind(); 293 setParameter("emissionTexture", cast(int)3); 294 setParameterSubroutine("emission", ShaderType.Fragment, "emissionColorTexture"); 295 } 296 else 297 { 298 setParameter("emissionVector", iemission.asVector4f); 299 setParameterSubroutine("emission", ShaderType.Fragment, "emissionColorValue"); 300 } 301 setParameter("energy", ienergy.asFloat); 302 303 glActiveTexture(GL_TEXTURE0); 304 305 super.bindParameters(state); 306 } 307 308 override void unbindParameters(GraphicsState* state) 309 { 310 super.unbindParameters(state); 311 312 glActiveTexture(GL_TEXTURE0); 313 glBindTexture(GL_TEXTURE_2D, 0); 314 315 glActiveTexture(GL_TEXTURE1); 316 glBindTexture(GL_TEXTURE_2D, 0); 317 318 glActiveTexture(GL_TEXTURE2); 319 glBindTexture(GL_TEXTURE_2D, 0); 320 321 glActiveTexture(GL_TEXTURE3); 322 glBindTexture(GL_TEXTURE_2D, 0); 323 324 glActiveTexture(GL_TEXTURE0); 325 } 326 }