1 /* 2 Copyright (c) 2017-2018 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.graphics.shaders.geometrypass; 29 30 import std.stdio; 31 import std.math; 32 33 import dlib.core.memory; 34 import dlib.math.vector; 35 import dlib.math.matrix; 36 import dlib.math.transformation; 37 import dlib.math.interpolation; 38 import dlib.image.color; 39 40 import dagon.core.libs; 41 import dagon.core.ownership; 42 import dagon.graphics.rc; 43 import dagon.graphics.shadow; 44 import dagon.graphics.texture; 45 import dagon.graphics.material; 46 import dagon.graphics.shader; 47 48 class GeometryPassShader: Shader 49 { 50 string vs = import("GeometryPass.vs"); 51 string fs = import("GeometryPass.fs"); 52 53 this(Owner o) 54 { 55 auto myProgram = New!ShaderProgram(vs, fs, this); 56 super(myProgram, o); 57 } 58 59 override void bind(RenderingContext* rc) 60 { 61 auto idiffuse = "diffuse" in rc.material.inputs; 62 auto inormal = "normal" in rc.material.inputs; 63 auto iheight = "height" in rc.material.inputs; 64 auto ipbr = "pbr" in rc.material.inputs; 65 auto iroughness = "roughness" in rc.material.inputs; 66 auto imetallic = "metallic" in rc.material.inputs; 67 auto iemission = "emission" in rc.material.inputs; 68 auto ienergy = "energy" in rc.material.inputs; 69 auto iparallax = "parallax" in rc.material.inputs; 70 auto itextureScale = "textureScale" in rc.material.inputs; 71 72 int parallaxMethod = iparallax.asInteger; 73 if (parallaxMethod > ParallaxOcclusionMapping) 74 parallaxMethod = ParallaxOcclusionMapping; 75 if (parallaxMethod < 0) 76 parallaxMethod = 0; 77 78 setParameter("layer", rc.layer); 79 setParameter("blurMask", rc.blurMask); 80 81 setParameter("modelViewMatrix", rc.modelViewMatrix); 82 setParameter("projectionMatrix", rc.projectionMatrix); 83 setParameter("normalMatrix", rc.normalMatrix); 84 85 setParameter("prevModelViewProjMatrix", rc.prevModelViewProjMatrix); 86 setParameter("blurModelViewProjMatrix", rc.blurModelViewProjMatrix); 87 88 setParameter("textureScale", itextureScale.asVector2f); 89 90 // Diffuse 91 if (idiffuse.texture) 92 { 93 glActiveTexture(GL_TEXTURE0); 94 idiffuse.texture.bind(); 95 setParameter("diffuseTexture", cast(int)0); 96 setParameterSubroutine("diffuse", ShaderType.Fragment, "diffuseColorTexture"); 97 } 98 else 99 { 100 setParameter("diffuseVector", rc.material.diffuse.asVector4f); 101 setParameterSubroutine("diffuse", ShaderType.Fragment, "diffuseColorValue"); 102 } 103 104 // Normal/height 105 bool haveHeightMap = inormal.texture !is null; 106 if (haveHeightMap) 107 haveHeightMap = inormal.texture.image.channels == 4; 108 109 if (!haveHeightMap) 110 { 111 if (inormal.texture is null) 112 { 113 if (iheight.texture !is null) // we have height map, but no normal map 114 { 115 Color4f color = Color4f(0.5f, 0.5f, 1.0f, 0.0f); // default normal pointing upwards 116 inormal.texture = rc.material.makeTexture(color, iheight.texture); 117 haveHeightMap = true; 118 } 119 } 120 else 121 { 122 if (iheight.texture !is null) // we have both normal and height maps 123 { 124 inormal.texture = rc.material.makeTexture(inormal.texture, iheight.texture); 125 haveHeightMap = true; 126 } 127 } 128 } 129 130 if (inormal.texture) 131 { 132 setParameter("normalTexture", 1); 133 setParameterSubroutine("normal", ShaderType.Fragment, "normalMap"); 134 135 glActiveTexture(GL_TEXTURE1); 136 inormal.texture.bind(); 137 } 138 else 139 { 140 setParameter("normalVector", rc.material.normal.asVector3f); 141 setParameterSubroutine("normal", ShaderType.Fragment, "normalValue"); 142 } 143 144 // Height and parallax 145 146 // TODO: make these material properties 147 float parallaxScale = 0.03f; 148 float parallaxBias = -0.01f; 149 setParameter("parallaxScale", parallaxScale); 150 setParameter("parallaxBias", parallaxBias); 151 152 if (haveHeightMap) 153 { 154 setParameterSubroutine("height", ShaderType.Fragment, "heightMap"); 155 } 156 else 157 { 158 float h = 0.0f; //-parallaxBias / parallaxScale; 159 setParameter("heightScalar", h); 160 setParameterSubroutine("height", ShaderType.Fragment, "heightValue"); 161 parallaxMethod = ParallaxNone; 162 } 163 164 if (parallaxMethod == ParallaxSimple) 165 setParameterSubroutine("parallax", ShaderType.Fragment, "parallaxSimple"); 166 else if (parallaxMethod == ParallaxOcclusionMapping) 167 setParameterSubroutine("parallax", ShaderType.Fragment, "parallaxOcclusionMapping"); 168 else 169 setParameterSubroutine("parallax", ShaderType.Fragment, "parallaxNone"); 170 171 // PBR 172 // TODO: pass solid values as uniforms, make subroutine for each mode 173 if (ipbr is null) 174 { 175 rc.material.setInput("pbr", 0.0f); 176 ipbr = "pbr" in rc.material.inputs; 177 } 178 179 if (ipbr.texture is null) 180 ipbr.texture = rc.material.makeTexture(*iroughness, *imetallic, materialInput(0.0f), materialInput(0.0f)); 181 glActiveTexture(GL_TEXTURE2); 182 ipbr.texture.bind(); 183 setParameter("pbrTexture", 2); 184 185 // Emission 186 if (iemission.texture) 187 { 188 glActiveTexture(GL_TEXTURE3); 189 iemission.texture.bind(); 190 191 setParameter("emissionTexture", 3); 192 setParameterSubroutine("emission", ShaderType.Fragment, "emissionMap"); 193 } 194 else 195 { 196 setParameter("emissionVector", rc.material.emission.asVector4f); 197 setParameterSubroutine("emission", ShaderType.Fragment, "emissionValue"); 198 } 199 200 setParameter("emissionEnergy", ienergy.asFloat); 201 202 glActiveTexture(GL_TEXTURE0); 203 204 super.bind(rc); 205 } 206 207 override void unbind(RenderingContext* rc) 208 { 209 super.unbind(rc); 210 211 glActiveTexture(GL_TEXTURE0); 212 glBindTexture(GL_TEXTURE_2D, 0); 213 214 glActiveTexture(GL_TEXTURE1); 215 glBindTexture(GL_TEXTURE_2D, 0); 216 217 glActiveTexture(GL_TEXTURE2); 218 glBindTexture(GL_TEXTURE_2D, 0); 219 220 glActiveTexture(GL_TEXTURE3); 221 glBindTexture(GL_TEXTURE_2D, 0); 222 223 glActiveTexture(GL_TEXTURE4); 224 glBindTexture(GL_TEXTURE_2D, 0); 225 226 glActiveTexture(GL_TEXTURE5); 227 glBindTexture(GL_TEXTURE_2D_ARRAY, 0); 228 229 glActiveTexture(GL_TEXTURE6); 230 glBindTexture(GL_TEXTURE_2D, 0); 231 232 glActiveTexture(GL_TEXTURE7); 233 glBindTexture(GL_TEXTURE_2D, 0); 234 235 glActiveTexture(GL_TEXTURE8); 236 glBindTexture(GL_TEXTURE_2D, 0); 237 238 glActiveTexture(GL_TEXTURE0); 239 } 240 }