1 /* This file is part of Dilay 2 * Copyright © 2015-2018 Alexander Bau 3 * Use and redistribute under the terms of the GNU General Public License 4 */ 5 #include <glm/glm.hpp> 6 #include "color.hpp" 7 #include "config.hpp" 8 #include "opengl.hpp" 9 #include "render-mode.hpp" 10 #include "renderer.hpp" 11 #include "util.hpp" 12 13 namespace 14 { 15 const unsigned int numLights = 2; 16 17 struct LightIds 18 { 19 int directionId; 20 int colorId; 21 int irradianceId; 22 LightIds__anonf3ef77560111::LightIds23 LightIds () 24 : directionId (0) 25 , colorId (0) 26 , irradianceId (0) 27 { 28 } 29 }; 30 31 struct ShaderIds 32 { 33 unsigned int programId; 34 int modelId; 35 int modelNormalId; 36 int viewId; 37 int projectionId; 38 int colorId; 39 int wireframeColorId; 40 int eyePointId; 41 int barycentricId; 42 LightIds lightIds[numLights]; 43 ShaderIds__anonf3ef77560111::ShaderIds44 ShaderIds () 45 : programId (0) 46 , modelId (0) 47 , modelNormalId (0) 48 , viewId (0) 49 , projectionId (0) 50 , colorId (0) 51 , wireframeColorId (0) 52 , eyePointId (0) 53 , barycentricId (0) 54 { 55 } 56 }; 57 58 struct GlobalLightUniforms 59 { 60 glm::vec3 direction; 61 Color color; 62 float irradiance; 63 }; 64 65 struct GlobalUniforms 66 { 67 GlobalLightUniforms lightUniforms[numLights]; 68 glm::vec3 eyePoint; 69 }; 70 }; 71 72 struct Renderer::Impl 73 { 74 static const unsigned int numShaders = 6; 75 76 ShaderIds shaderIds[Impl::numShaders]; 77 ShaderIds* activeShaderIndex; 78 GlobalUniforms globalUniforms; 79 Color clearColor; 80 ImplRenderer::Impl81 Impl (const Config& config) 82 : activeShaderIndex (nullptr) 83 { 84 this->runFromConfig (config); 85 } 86 ~ImplRenderer::Impl87 ~Impl () 88 { 89 for (unsigned int i = 0; i < Impl::numShaders; i++) 90 { 91 OpenGL::safeDeleteProgram (this->shaderIds[i].programId); 92 } 93 } 94 setupRenderingRenderer::Impl95 void setupRendering () 96 { 97 OpenGL::glClearColor (this->clearColor.r (), this->clearColor.g (), this->clearColor.b (), 98 0.0f); 99 OpenGL::glClearStencil (0); 100 OpenGL::glFrontFace (OpenGL::CCW ()); 101 OpenGL::glEnable (OpenGL::CullFace ()); 102 OpenGL::glCullFace (OpenGL::Back ()); 103 OpenGL::glEnable (OpenGL::DepthTest ()); 104 OpenGL::glDepthFunc (OpenGL::LEqual ()); 105 OpenGL::glClear (OpenGL::ColorBufferBit () | OpenGL::DepthBufferBit ()); 106 } 107 shutdownRenderingRenderer::Impl108 void shutdownRendering () 109 { 110 OpenGL::glDisable (OpenGL::DepthTest ()); 111 OpenGL::glDisable (OpenGL::CullFace ()); 112 } 113 shaderIndexRenderer::Impl114 unsigned int shaderIndex (const RenderMode& renderMode) 115 { 116 if (renderMode.smoothShading ()) 117 { 118 return renderMode.renderWireframe () ? 0 : 1; 119 } 120 else if (renderMode.flatShading ()) 121 { 122 return renderMode.renderWireframe () ? 2 : 3; 123 } 124 else if (renderMode.constantShading ()) 125 { 126 return renderMode.renderWireframe () ? 4 : 5; 127 } 128 else 129 { 130 DILAY_IMPOSSIBLE 131 } 132 } 133 initalizeProgramRenderer::Impl134 void initalizeProgram (const RenderMode& renderMode) 135 { 136 assert (renderMode.renderWireframe () == false || OpenGL::hasGeometryShader ()); 137 138 const unsigned int id = OpenGL::loadProgram ( 139 renderMode.vertexShader (), renderMode.fragmentShader (), renderMode.renderWireframe ()); 140 141 unsigned int index = this->shaderIndex (renderMode); 142 assert (this->shaderIds[index].programId == 0); 143 144 ShaderIds* s = &this->shaderIds[index]; 145 146 s->programId = id; 147 s->modelId = OpenGL::glGetUniformLocation (id, "model"); 148 s->modelNormalId = OpenGL::glGetUniformLocation (id, "modelNormal"); 149 s->viewId = OpenGL::glGetUniformLocation (id, "view"); 150 s->projectionId = OpenGL::glGetUniformLocation (id, "projection"); 151 s->colorId = OpenGL::glGetUniformLocation (id, "color"); 152 s->wireframeColorId = OpenGL::glGetUniformLocation (id, "wireframeColor"); 153 s->eyePointId = OpenGL::glGetUniformLocation (id, "eyePoint"); 154 s->barycentricId = OpenGL::glGetUniformLocation (id, "barycentric"); 155 s->lightIds[0].directionId = OpenGL::glGetUniformLocation (id, "light1Direction"); 156 s->lightIds[0].colorId = OpenGL::glGetUniformLocation (id, "light1Color"); 157 s->lightIds[0].irradianceId = OpenGL::glGetUniformLocation (id, "light1Irradiance"); 158 s->lightIds[1].directionId = OpenGL::glGetUniformLocation (id, "light2Direction"); 159 s->lightIds[1].colorId = OpenGL::glGetUniformLocation (id, "light2Color"); 160 s->lightIds[1].irradianceId = OpenGL::glGetUniformLocation (id, "light2Irradiance"); 161 } 162 setProgramRenderer::Impl163 void setProgram (const RenderMode& renderMode) 164 { 165 const unsigned int index = this->shaderIndex (renderMode); 166 167 if (this->shaderIds[index].programId == 0) 168 { 169 this->initalizeProgram (renderMode); 170 } 171 assert (this->shaderIds[index].programId); 172 173 this->activeShaderIndex = &this->shaderIds[index]; 174 OpenGL::glUseProgram (this->activeShaderIndex->programId); 175 176 OpenGL::glUniformVec3 (this->activeShaderIndex->eyePointId, this->globalUniforms.eyePoint); 177 178 for (unsigned int i = 0; i < numLights; i++) 179 { 180 OpenGL::glUniformVec3 (this->activeShaderIndex->lightIds[i].directionId, 181 this->globalUniforms.lightUniforms[i].direction); 182 OpenGL::glUniformVec3 (this->activeShaderIndex->lightIds[i].colorId, 183 this->globalUniforms.lightUniforms[i].color.vec3 ()); 184 OpenGL::glUniform1f (this->activeShaderIndex->lightIds[i].irradianceId, 185 this->globalUniforms.lightUniforms[i].irradiance); 186 } 187 } 188 setModelRenderer::Impl189 void setModel (const float* model, const float* modelNormal) 190 { 191 assert (this->activeShaderIndex); 192 OpenGL::glUniformMatrix4fv (this->activeShaderIndex->modelId, 1, false, model); 193 OpenGL::glUniformMatrix3fv (this->activeShaderIndex->modelNormalId, 1, false, modelNormal); 194 } 195 setViewRenderer::Impl196 void setView (const float* view) 197 { 198 assert (this->activeShaderIndex); 199 OpenGL::glUniformMatrix4fv (this->activeShaderIndex->viewId, 1, false, view); 200 } 201 setProjectionRenderer::Impl202 void setProjection (const float* projection) 203 { 204 assert (this->activeShaderIndex); 205 OpenGL::glUniformMatrix4fv (this->activeShaderIndex->projectionId, 1, false, projection); 206 } 207 setColorRenderer::Impl208 void setColor (const Color& c, bool withOpacity) 209 { 210 assert (this->activeShaderIndex); 211 212 if (withOpacity) 213 { 214 OpenGL::glUniformVec4 (this->activeShaderIndex->colorId, c.vec4 ()); 215 } 216 else 217 { 218 OpenGL::glUniformVec3 (this->activeShaderIndex->colorId, c.vec3 ()); 219 } 220 } 221 setWireframeColorRenderer::Impl222 void setWireframeColor (const Color& c, bool withOpacity) 223 { 224 assert (this->activeShaderIndex); 225 226 if (withOpacity) 227 { 228 OpenGL::glUniformVec4 (this->activeShaderIndex->wireframeColorId, c.vec4 ()); 229 } 230 else 231 { 232 OpenGL::glUniformVec3 (this->activeShaderIndex->wireframeColorId, c.vec3 ()); 233 } 234 } 235 setEyePointRenderer::Impl236 void setEyePoint (const glm::vec3& e) { this->globalUniforms.eyePoint = e; } 237 setLightDirectionRenderer::Impl238 void setLightDirection (unsigned int i, const glm::vec3& d) 239 { 240 assert (i < numLights); 241 this->globalUniforms.lightUniforms[i].direction = d; 242 } 243 setLightColorRenderer::Impl244 void setLightColor (unsigned int i, const Color& c) 245 { 246 assert (i < numLights); 247 this->globalUniforms.lightUniforms[i].color = c; 248 } 249 setLightIrradianceRenderer::Impl250 void setLightIrradiance (unsigned int i, float irr) 251 { 252 assert (i < numLights); 253 this->globalUniforms.lightUniforms[i].irradiance = irr; 254 } 255 runFromConfigRenderer::Impl256 void runFromConfig (const Config& config) 257 { 258 this->clearColor = config.get<Color> ("editor/background"); 259 260 for (unsigned int i = 0; i < numLights; i++) 261 { 262 const std::string key = "editor/light/light" + std::to_string (i + 1) + "/"; 263 264 const glm::vec3 dir = config.get<glm::vec3> (key + "direction"); 265 this->setLightDirection (i, glm::normalize (dir)); 266 this->setLightColor (i, config.get<Color> (key + "color")); 267 this->setLightIrradiance (i, config.get<float> (key + "irradiance")); 268 } 269 } 270 }; 271 272 DELEGATE1_BIG3 (Renderer, const Config&) 273 274 DELEGATE (void, Renderer, setupRendering) 275 DELEGATE (void, Renderer, shutdownRendering) 276 DELEGATE1 (void, Renderer, setProgram, const RenderMode&) 277 DELEGATE2 (void, Renderer, setModel, const float*, const float*) 278 DELEGATE1 (void, Renderer, setView, const float*) 279 DELEGATE1 (void, Renderer, setProjection, const float*) 280 DELEGATE2 (void, Renderer, setColor, const Color&, bool) 281 DELEGATE2 (void, Renderer, setWireframeColor, const Color&, bool) 282 DELEGATE1 (void, Renderer, setEyePoint, const glm::vec3&) 283 DELEGATE2 (void, Renderer, setLightDirection, unsigned int, const glm::vec3&) 284 DELEGATE2 (void, Renderer, setLightColor, unsigned int, const Color&) 285 DELEGATE2 (void, Renderer, setLightIrradiance, unsigned int, float) 286 DELEGATE1 (void, Renderer, runFromConfig, const Config&) 287