From 014e6070b886a739f2fe5ed1e6c8da0e7e97e03e Mon Sep 17 00:00:00 2001 From: "C. J. Howard" Date: Thu, 18 Jan 2018 08:44:58 +0800 Subject: [PATCH] Revise shader-material system --- data | 2 +- lib/emergent | 2 +- src/application.cpp | 199 +++---- src/application.hpp | 66 ++- src/configuration.hpp.in | 2 +- src/debug.cpp | 4 +- src/debug.hpp | 3 +- src/game/biome.cpp | 14 +- src/game/biome.hpp | 12 +- src/game/terrain.cpp | 8 +- src/game/terrain.hpp | 5 +- src/material-loader.cpp | 377 ++++++++++-- src/material-loader.hpp | 30 +- src/materials.hpp | 89 --- src/render-passes.cpp | 1109 +++++++++++------------------------- src/render-passes.hpp | 178 +++--- src/states/game-state.cpp | 1 + src/states/title-state.cpp | 17 - src/ui/pie-menu.cpp | 2 +- src/ui/pie-menu.hpp | 2 +- src/ui/toolbar.cpp | 12 +- src/ui/toolbar.hpp | 22 +- src/ui/ui.cpp | 17 +- src/ui/ui.hpp | 23 +- 24 files changed, 970 insertions(+), 1226 deletions(-) delete mode 100644 src/materials.hpp diff --git a/data b/data index bf5d69d..41b7c54 160000 --- a/data +++ b/data @@ -1 +1 @@ -Subproject commit bf5d69d87ef22cf3660e8d59d4c338995411e51d +Subproject commit 41b7c54fb2819da830a47d0e5a5756eed5a0310d diff --git a/lib/emergent b/lib/emergent index a452354..ce417f4 160000 --- a/lib/emergent +++ b/lib/emergent @@ -1 +1 @@ -Subproject commit a452354a06253cc1f6b79e5646c6fd7c704448b4 +Subproject commit ce417f4eafa15035b3a7613363e23157b8e59900 diff --git a/src/application.cpp b/src/application.cpp index 886c0b5..6d8216d 100644 --- a/src/application.cpp +++ b/src/application.cpp @@ -120,13 +120,17 @@ Application::Application(int argc, char* argv[]): SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, OPENGL_VERSION_MAJOR); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, OPENGL_VERSION_MINOR); + //SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG); + SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1); + //SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); + //SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4); // Set OpenGL buffer attributes SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16); - SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); + SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 0); // Get all possible display modes for the default display int displayModeCount = SDL_GetNumDisplayModes(0); @@ -701,7 +705,7 @@ void Application::saveUserSettings() bool Application::loadModels() { - antModel = modelLoader->load("data/models/debug-worker.mdl"); + antModel = modelLoader->load("data/models/common-worker-ant.mdl"); antHillModel = modelLoader->load("data/models/ant-hill.mdl"); nestModel = modelLoader->load("data/models/nest.mdl"); forcepsModel = modelLoader->load("data/models/forceps.mdl"); @@ -742,29 +746,9 @@ bool Application::loadModels() bool Application::loadScene() { // Create scene layers - backgroundLayer = scene.addLayer(); defaultLayer = scene.addLayer(); uiLayer = scene.addLayer(); - // BG - bgBatch.resize(1); - BillboardBatch::Range* bgRange = bgBatch.addRange(); - bgRange->start = 0; - bgRange->length = 1; - Billboard* bgBillboard = bgBatch.getBillboard(0); - bgBillboard->setDimensions(Vector2(1.0f, 1.0f)); - bgBillboard->setTranslation(Vector3(0.5f, 0.5f, 0.0f)); - bgBillboard->setTintColor(Vector4(1, 1, 1, 1)); - bgBatch.update(); - - vignettePass.setRenderTarget(&defaultRenderTarget); - //bgCompositor.addPass(&vignettePass); - bgCompositor.load(nullptr); - bgCamera.setOrthographic(0, 1.0f, 1.0f, 0, -1.0f, 1.0f); - bgCamera.lookAt(glm::vec3(0), glm::vec3(0, 0, -1), glm::vec3(0, 1, 0)); - bgCamera.setCompositor(&bgCompositor); - bgCamera.setCompositeIndex(0); - // Set shadow map resolution shadowMapResolution = 4096; @@ -773,9 +757,9 @@ bool Application::loadScene() glBindFramebuffer(GL_FRAMEBUFFER, shadowMapFramebuffer); // Generate shadow map depth texture - glGenTextures(1, &shadowMapDepthTexture); - glBindTexture(GL_TEXTURE_2D, shadowMapDepthTexture); - glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, shadowMapResolution, shadowMapResolution, 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr); + glGenTextures(1, &shadowMapDepthTextureID); + glBindTexture(GL_TEXTURE_2D, shadowMapDepthTextureID); + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, shadowMapResolution, shadowMapResolution, 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); @@ -784,7 +768,7 @@ bool Application::loadScene() glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE); // Attach depth texture to framebuffer - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, shadowMapDepthTexture, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, shadowMapDepthTextureID, 0); glDrawBuffer(GL_NONE); glReadBuffer(GL_NONE); @@ -797,6 +781,11 @@ bool Application::loadScene() shadowMapRenderTarget.height = shadowMapResolution; shadowMapRenderTarget.framebuffer = shadowMapFramebuffer; + // Setup texture class + shadowMapDepthTexture.setTextureID(shadowMapDepthTextureID); + shadowMapDepthTexture.setWidth(shadowMapResolution); + shadowMapDepthTexture.setHeight(shadowMapResolution); + // Setup shadow map render pass shadowMapPass.setRenderTarget(&shadowMapRenderTarget); shadowMapPass.setViewCamera(&camera); @@ -809,8 +798,8 @@ bool Application::loadScene() // Post-processing framebuffers { // Generate color texture - glGenTextures(1, &framebufferAColorTexture); - glBindTexture(GL_TEXTURE_2D, framebufferAColorTexture); + glGenTextures(1, &framebufferAColorTextureID); + glBindTexture(GL_TEXTURE_2D, framebufferAColorTextureID); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, static_cast(resolution.x), static_cast(resolution.y), 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); @@ -818,8 +807,8 @@ bool Application::loadScene() glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); // Generate depth texture - glGenTextures(1, &framebufferADepthTexture); - glBindTexture(GL_TEXTURE_2D, framebufferADepthTexture); + glGenTextures(1, &framebufferADepthTextureID); + glBindTexture(GL_TEXTURE_2D, framebufferADepthTextureID); glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, static_cast(resolution.x), static_cast(resolution.y), 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); @@ -833,8 +822,8 @@ bool Application::loadScene() glBindFramebuffer(GL_FRAMEBUFFER, framebufferA); // Attach textures to framebuffer - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, framebufferAColorTexture, 0); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, framebufferADepthTexture, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, framebufferAColorTextureID, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, framebufferADepthTextureID, 0); glDrawBuffer(GL_COLOR_ATTACHMENT0); //glReadBuffer(GL_COLOR_ATTACHMENT0); @@ -846,12 +835,17 @@ bool Application::loadScene() framebufferARenderTarget.width = static_cast(resolution.x); framebufferARenderTarget.height = static_cast(resolution.y); framebufferARenderTarget.framebuffer = framebufferA; + + // Setup texture class + framebufferAColorTexture.setTextureID(framebufferAColorTextureID); + framebufferAColorTexture.setWidth(static_cast(resolution.x)); + framebufferAColorTexture.setHeight(static_cast(resolution.y)); } { // Generate color texture - glGenTextures(1, &framebufferBColorTexture); - glBindTexture(GL_TEXTURE_2D, framebufferBColorTexture); + glGenTextures(1, &framebufferBColorTextureID); + glBindTexture(GL_TEXTURE_2D, framebufferBColorTextureID); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, static_cast(resolution.x), static_cast(resolution.y), 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); @@ -859,11 +853,11 @@ bool Application::loadScene() glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); // Generate framebuffer - glGenFramebuffers(1, &framebufferA); - glBindFramebuffer(GL_FRAMEBUFFER, framebufferA); + glGenFramebuffers(1, &framebufferB); + glBindFramebuffer(GL_FRAMEBUFFER, framebufferB); // Attach textures to framebuffer - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, framebufferBColorTexture, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, framebufferBColorTextureID, 0); glDrawBuffer(GL_COLOR_ATTACHMENT0); //glReadBuffer(GL_COLOR_ATTACHMENT0); @@ -874,7 +868,12 @@ bool Application::loadScene() // Setup render target framebufferBRenderTarget.width = static_cast(resolution.x); framebufferBRenderTarget.height = static_cast(resolution.y); - framebufferBRenderTarget.framebuffer = framebufferA; + framebufferBRenderTarget.framebuffer = framebufferB; + + // Setup texture class + framebufferBColorTexture.setTextureID(framebufferBColorTextureID); + framebufferBColorTexture.setWidth(static_cast(resolution.x)); + framebufferBColorTexture.setHeight(static_cast(resolution.y)); } // Pheromone PBO @@ -887,12 +886,13 @@ bool Application::loadScene() glGenTextures(1, &pheromoneTextureID); glBindTexture(GL_TEXTURE_2D, pheromoneTextureID); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, PHEROMONE_MATRIX_COLUMNS, PHEROMONE_MATRIX_ROWS, 0, GL_BGRA, GL_UNSIGNED_BYTE, nullptr); glBindTexture(GL_TEXTURE_2D, 0); + // Setup texture class pheromoneTexture.setWidth(PHEROMONE_MATRIX_COLUMNS); pheromoneTexture.setHeight(PHEROMONE_MATRIX_ROWS); pheromoneTexture.setTextureID(pheromoneTextureID); @@ -902,32 +902,36 @@ bool Application::loadScene() glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); // Setup skybox pass - skyboxPass.setRenderTarget(&framebufferARenderTarget); + //skyboxPass.setRenderTarget(&framebufferARenderTarget); + skyboxPass.setRenderTarget(&defaultRenderTarget); // Setup clear depth pass - clearDepthPass.setRenderTarget(&framebufferARenderTarget); + //clearDepthPass.setRenderTarget(&framebufferARenderTarget); + clearDepthPass.setRenderTarget(&defaultRenderTarget); clearDepthPass.setClear(false, true, false); clearDepthPass.setClearDepth(1.0f); // Setup lighting pass - lightingPass.setRenderTarget(&framebufferARenderTarget); - lightingPass.setShadowMap(shadowMapDepthTexture); + //lightingPass.setRenderTarget(&framebufferARenderTarget); + lightingPass.setRenderTarget(&defaultRenderTarget); + lightingPass.setShadowMap(&shadowMapDepthTexture); lightingPass.setShadowCamera(&sunlightCamera); lightingPass.setShadowMapPass(&shadowMapPass); // Setup blur passes horizontalBlurPass.setRenderTarget(&framebufferBRenderTarget); - horizontalBlurPass.setTexture(framebufferAColorTexture); + horizontalBlurPass.setTexture(&framebufferAColorTexture); horizontalBlurPass.setDirection(Vector2(0.0f, 0.0f)); verticalBlurPass.setRenderTarget(&framebufferARenderTarget); - verticalBlurPass.setTexture(framebufferBColorTexture); + verticalBlurPass.setTexture(&framebufferBColorTexture); verticalBlurPass.setDirection(Vector2(0.0f, 0.0f)); horizontalBlurPass2.setRenderTarget(&framebufferBRenderTarget); - horizontalBlurPass2.setTexture(framebufferAColorTexture); + horizontalBlurPass2.setTexture(&framebufferAColorTexture); horizontalBlurPass2.setDirection(Vector2(0.0f, 0.0f)); verticalBlurPass2.setRenderTarget(&defaultRenderTarget); - verticalBlurPass2.setTexture(framebufferBColorTexture); + verticalBlurPass2.setTexture(&framebufferBColorTexture); verticalBlurPass2.setDirection(Vector2(0.0f, 0.0f)); + verticalBlurPass2.setGammaCorrect(true); // Setup debug pass @@ -936,10 +940,10 @@ bool Application::loadScene() defaultCompositor.addPass(&clearDepthPass); defaultCompositor.addPass(&skyboxPass); defaultCompositor.addPass(&lightingPass); - defaultCompositor.addPass(&horizontalBlurPass); - defaultCompositor.addPass(&verticalBlurPass); - defaultCompositor.addPass(&horizontalBlurPass2); - defaultCompositor.addPass(&verticalBlurPass2); + //defaultCompositor.addPass(&horizontalBlurPass); + //defaultCompositor.addPass(&verticalBlurPass); + //defaultCompositor.addPass(&horizontalBlurPass2); + //defaultCompositor.addPass(&verticalBlurPass2); //defaultCompositor.addPass(&debugPass); defaultCompositor.load(nullptr); @@ -994,39 +998,33 @@ bool Application::loadUI() // Load UI textures textureLoader->setGamma(1.0f); - textureLoader->setCubemap(false); textureLoader->setMipmapChain(false); textureLoader->setMaxAnisotropy(1.0f); textureLoader->setWrapS(false); textureLoader->setWrapT(false); - splashTexture = textureLoader->load("data/textures/ui-splash.png"); - titleTexture = textureLoader->load("data/textures/ui-title.png"); - rectangularPaletteTexture = textureLoader->load("data/textures/rectangular-palette.png"); - foodIndicatorTexture = textureLoader->load("data/textures/food-indicator.png"); - toolBrushTexture = textureLoader->load("data/textures/tool-brush.png"); - toolLensTexture = textureLoader->load("data/textures/tool-lens.png"); - toolForcepsTexture = textureLoader->load("data/textures/tool-forceps.png"); - toolTrowelTexture = textureLoader->load("data/textures/tool-trowel.png"); - - toolbarTopTexture = textureLoader->load("data/textures/toolbar-top.png"); - toolbarBottomTexture = textureLoader->load("data/textures/toolbar-bottom.png"); - toolbarMiddleTexture = textureLoader->load("data/textures/toolbar-middle.png"); - toolbarButtonRaisedTexture = textureLoader->load("data/textures/toolbar-button-raised.png"); - toolbarButtonDepressedTexture = textureLoader->load("data/textures/toolbar-button-depressed.png"); - - arcNorthTexture = textureLoader->load("data/textures/pie-menu-arc-north.png"); - arcEastTexture = textureLoader->load("data/textures/pie-menu-arc-east.png"); - arcSouthTexture = textureLoader->load("data/textures/pie-menu-arc-south.png"); - arcWestTexture = textureLoader->load("data/textures/pie-menu-arc-west.png"); - - mouseLeftTexture = textureLoader->load("data/textures/mouse-left.png"); - mouseRightTexture = textureLoader->load("data/textures/mouse-right.png"); - - depthTexture = new Texture(); - depthTexture->setTextureID(shadowMapDepthTexture); - depthTexture->setWidth(shadowMapResolution); - depthTexture->setHeight(shadowMapResolution); + splashTexture = textureLoader->load2D("data/textures/ui-splash.png"); + titleTexture = textureLoader->load2D("data/textures/ui-title.png"); + rectangularPaletteTexture = textureLoader->load2D("data/textures/rectangular-palette.png"); + foodIndicatorTexture = textureLoader->load2D("data/textures/food-indicator.png"); + toolBrushTexture = textureLoader->load2D("data/textures/tool-brush.png"); + toolLensTexture = textureLoader->load2D("data/textures/tool-lens.png"); + toolForcepsTexture = textureLoader->load2D("data/textures/tool-forceps.png"); + toolTrowelTexture = textureLoader->load2D("data/textures/tool-trowel.png"); + + toolbarTopTexture = textureLoader->load2D("data/textures/toolbar-top.png"); + toolbarBottomTexture = textureLoader->load2D("data/textures/toolbar-bottom.png"); + toolbarMiddleTexture = textureLoader->load2D("data/textures/toolbar-middle.png"); + toolbarButtonRaisedTexture = textureLoader->load2D("data/textures/toolbar-button-raised.png"); + toolbarButtonDepressedTexture = textureLoader->load2D("data/textures/toolbar-button-depressed.png"); + + arcNorthTexture = textureLoader->load2D("data/textures/pie-menu-arc-north.png"); + arcEastTexture = textureLoader->load2D("data/textures/pie-menu-arc-east.png"); + arcSouthTexture = textureLoader->load2D("data/textures/pie-menu-arc-south.png"); + arcWestTexture = textureLoader->load2D("data/textures/pie-menu-arc-west.png"); + + mouseLeftTexture = textureLoader->load2D("data/textures/mouse-left.png"); + mouseRightTexture = textureLoader->load2D("data/textures/mouse-right.png"); // Set colors selectedColor = Vector4(1.0f, 1.0f, 1.0f, 1.0f); @@ -1114,9 +1112,9 @@ bool Application::loadUI() //uiRootElement->addChild(foodIndicatorImage); depthTextureImage = new UIImage(); - depthTextureImage->setTexture(depthTexture); + depthTextureImage->setTexture(&shadowMapDepthTexture); depthTextureImage->setVisible(false); - uiRootElement->addChild(depthTextureImage); + //uiRootElement->addChild(depthTextureImage); // Create level name label levelNameLabel = new UILabel(); @@ -2071,40 +2069,17 @@ void Application::loadLevel(std::size_t index) const LevelParameterSet* levelParams = campaign.getLevelParams(currentWorldIndex, currentLevelIndex); currentLevel->load(*levelParams); - PhysicalMaterial* material = materialLoader->load("data/materials/debug-terrain-surface.mtl"); - material->albedoOpacityMap = &pheromoneTexture; - material->shadowCaster = false; - material->flags |= (unsigned int)PhysicalMaterial::Flags::TRANSLUCENT; - - currentLevel->terrain.getSurfaceModel()->getGroup(0)->material = material; -} - -/* -void Application::loadLevel() -{ - if (currentLevel < 1 || currentLevel >= campaign.levels[currentWorld].size()) + Material* material = materialLoader->load("data/materials/debug-terrain-surface.mtl"); + ShaderTexture2D* albedoOpacityMap = static_cast(material->getVariable("albedoOpacityMap")); + if (albedoOpacityMap != nullptr) { - std::cout << "Attempted to load invalid level" << std::endl; - return; + albedoOpacityMap->setValue(&pheromoneTexture); } + //material->shadowCaster = false; + //material->flags |= (unsigned int)PhysicalMaterial::Flags::TRANSLUCENT; - const LevelParameterSet* levelParams = campaign.getLevelParams(currentWorld, currentLevel); - const Biome* biome = &biosphere.biomes[levelParams->biome]; - - soilPass.setHorizonOTexture(biome->soilHorizonO); - soilPass.setHorizonATexture(biome->soilHorizonA); - soilPass.setHorizonBTexture(biome->soilHorizonB); - soilPass.setHorizonCTexture(biome->soilHorizonC); - - std::string heightmap = std::string("data/textures/") + level->heightmap; - currentLevelTerrain->load(heightmap); - - // Set skybox - skyboxPass.setCubemap(biome->specularCubemap); - - //changeState(playState); + currentLevel->terrain.getSurfaceModel()->getGroup(0)->material = material; } -*/ void Application::pauseSimulation() { diff --git a/src/application.hpp b/src/application.hpp index 6ef9aab..cbf4594 100644 --- a/src/application.hpp +++ b/src/application.hpp @@ -154,13 +154,11 @@ public: // Scene Scene scene; - SceneLayer* backgroundLayer; SceneLayer* defaultLayer; SceneLayer* uiLayer; Camera camera; Camera sunlightCamera; Camera uiCamera; - Camera bgCamera; DirectionalLight sunlight; ModelInstance forcepsModelInstance; ModelInstance navigatorObject; @@ -179,25 +177,28 @@ public: RenderTarget defaultRenderTarget; int shadowMapResolution; - GLuint shadowMapDepthTexture; + GLuint shadowMapDepthTextureID; GLuint shadowMapFramebuffer; RenderTarget shadowMapRenderTarget; ShadowMapRenderPass shadowMapPass; Compositor shadowMapCompositor; + Texture2D shadowMapDepthTexture; - GLuint framebufferAColorTexture; - GLuint framebufferADepthTexture; + GLuint framebufferAColorTextureID; + GLuint framebufferADepthTextureID; GLuint framebufferA; RenderTarget framebufferARenderTarget; + Texture2D framebufferAColorTexture; - GLuint framebufferBColorTexture; - GLuint framebufferBDepthTexture; + GLuint framebufferBColorTextureID; + GLuint framebufferBDepthTextureID; GLuint framebufferB; RenderTarget framebufferBRenderTarget; + Texture2D framebufferBColorTexture; GLuint pheromonePBO; GLuint pheromoneTextureID; - Texture pheromoneTexture; + Texture2D pheromoneTexture; ClearRenderPass clearDepthPass; LightingRenderPass lightingPass; @@ -207,9 +208,6 @@ public: UIBatcher* uiBatcher; UIRenderPass uiPass; Compositor uiCompositor; - BillboardBatch bgBatch; - Compositor bgCompositor; - VignetteRenderPass vignettePass; SkyboxRenderPass skyboxPass; TextureLoader* textureLoader; MaterialLoader* materialLoader; @@ -270,29 +268,29 @@ public: Font* levelNameFont; // UI textures - Texture* splashTexture; - Texture* titleTexture; - Texture* rectangularPaletteTexture; - Texture* foodIndicatorTexture; - Texture* toolBrushTexture; - Texture* toolLensTexture; - Texture* toolForcepsTexture; - Texture* toolTrowelTexture; - - Texture* toolbarTopTexture; - Texture* toolbarBottomTexture; - Texture* toolbarMiddleTexture; - Texture* toolbarButtonRaisedTexture; - Texture* toolbarButtonDepressedTexture; - - Texture* arcNorthTexture; - Texture* arcEastTexture; - Texture* arcSouthTexture; - Texture* arcWestTexture; - Texture* mouseLeftTexture; - Texture* mouseRightTexture; - - Texture* depthTexture; + Texture2D* splashTexture; + Texture2D* titleTexture; + Texture2D* rectangularPaletteTexture; + Texture2D* foodIndicatorTexture; + Texture2D* toolBrushTexture; + Texture2D* toolLensTexture; + Texture2D* toolForcepsTexture; + Texture2D* toolTrowelTexture; + + Texture2D* toolbarTopTexture; + Texture2D* toolbarBottomTexture; + Texture2D* toolbarMiddleTexture; + Texture2D* toolbarButtonRaisedTexture; + Texture2D* toolbarButtonDepressedTexture; + + Texture2D* arcNorthTexture; + Texture2D* arcEastTexture; + Texture2D* arcSouthTexture; + Texture2D* arcWestTexture; + Texture2D* mouseLeftTexture; + Texture2D* mouseRightTexture; + + Texture2D* depthTexture; // UI elements Vector4 selectedColor; diff --git a/src/configuration.hpp.in b/src/configuration.hpp.in index 837231d..905935e 100644 --- a/src/configuration.hpp.in +++ b/src/configuration.hpp.in @@ -46,7 +46,7 @@ const float WORLD_WIDTH = 100.0f; // cm const float WORLD_HEIGHT = 100.0f; // cm const float FRAMES_PER_SECOND = 60.0f; const float TIMESTEP = 1.0f / FRAMES_PER_SECOND; -const float PHEROMONE_MATRIX_RESOLUTION = 4.0f; +const float PHEROMONE_MATRIX_RESOLUTION = 5.12f; const int PHEROMONE_MATRIX_COLUMNS = (int)(WORLD_WIDTH * PHEROMONE_MATRIX_RESOLUTION); const int PHEROMONE_MATRIX_ROWS = (int)(WORLD_HEIGHT * PHEROMONE_MATRIX_RESOLUTION); const Vector2 WORLD_BOUNDS_MIN = Vector2(-WORLD_WIDTH * 0.5f, -WORLD_HEIGHT * 0.5f); diff --git a/src/debug.cpp b/src/debug.cpp index b87e465..d3f18e8 100644 --- a/src/debug.cpp +++ b/src/debug.cpp @@ -28,9 +28,9 @@ LineBatcher::LineBatcher(std::size_t lineCount): { batch.resize(lineCount); range = batch.addRange(); - range->material = &material; + range->material = nullptr;//&material; - material.albedo = Vector3(1.0f); + //material.albedo = Vector3(1.0f); } void LineBatcher::begin() diff --git a/src/debug.hpp b/src/debug.hpp index dfac8dc..c0ce801 100644 --- a/src/debug.hpp +++ b/src/debug.hpp @@ -21,7 +21,6 @@ #define DEBUG_HPP #include -#include "materials.hpp" using namespace Emergent; @@ -49,7 +48,7 @@ private: BillboardBatch::Range* range; float width; Vector4 color; - PhysicalMaterial material; + //PhysicalMaterial material; }; inline const BillboardBatch* LineBatcher::getBatch() const diff --git a/src/game/biome.cpp b/src/game/biome.cpp index 7a6dee4..d0126b9 100644 --- a/src/game/biome.cpp +++ b/src/game/biome.cpp @@ -26,26 +26,24 @@ bool Biome::load() parameters.get("cubemap", &cubemapName); TextureLoader textureLoader; - textureLoader.setCubemap(false); textureLoader.setMipmapChain(false); textureLoader.setWrapS(true); textureLoader.setWrapT(true); // Load soil horizon textures - soilHorizonO = textureLoader.load(std::string("data/textures/") + soilHorizonOFilename); - soilHorizonA = textureLoader.load(std::string("data/textures/") + soilHorizonAFilename); - soilHorizonB = textureLoader.load(std::string("data/textures/") + soilHorizonBFilename); - soilHorizonC = textureLoader.load(std::string("data/textures/") + soilHorizonCFilename); + soilHorizonO = textureLoader.load2D(std::string("data/textures/") + soilHorizonOFilename); + soilHorizonA = textureLoader.load2D(std::string("data/textures/") + soilHorizonAFilename); + soilHorizonB = textureLoader.load2D(std::string("data/textures/") + soilHorizonBFilename); + soilHorizonC = textureLoader.load2D(std::string("data/textures/") + soilHorizonCFilename); // Load diffuse cubemap - textureLoader.setCubemap(true); textureLoader.setMipmapChain(true); textureLoader.setWrapS(false); textureLoader.setWrapT(false); textureLoader.setWrapR(false); std::string diffuseCubemapFilename = std::string("data/textures/") + cubemapName + std::string("-irradiance-m%02d.hdr"); - diffuseCubemap = textureLoader.load(diffuseCubemapFilename); + diffuseCubemap = textureLoader.loadCube(diffuseCubemapFilename); if (!diffuseCubemap) { std::cerr << "Failed to load diffuse cubemap \"" << diffuseCubemapFilename << "\"" << std::endl; @@ -53,7 +51,7 @@ bool Biome::load() // Load specular cubemap std::string specularCubemapFilename = std::string("data/textures/") + cubemapName + std::string("-radiance-m%02d.hdr"); - specularCubemap = textureLoader.load(specularCubemapFilename); + specularCubemap = textureLoader.loadCube(specularCubemapFilename); if (!specularCubemap) { std::cerr << "Failed to load specular cubemap \"" << specularCubemapFilename << "\"" << std::endl; diff --git a/src/game/biome.hpp b/src/game/biome.hpp index c85d0b0..4cd72f8 100644 --- a/src/game/biome.hpp +++ b/src/game/biome.hpp @@ -23,12 +23,12 @@ public: std::string soilHorizonCFilename; std::string cubemapName; - Texture* soilHorizonO; - Texture* soilHorizonA; - Texture* soilHorizonB; - Texture* soilHorizonC; - Texture* diffuseCubemap; - Texture* specularCubemap; + Texture2D* soilHorizonO; + Texture2D* soilHorizonA; + Texture2D* soilHorizonB; + Texture2D* soilHorizonC; + TextureCube* diffuseCubemap; + TextureCube* specularCubemap; }; class Biosphere diff --git a/src/game/terrain.cpp b/src/game/terrain.cpp index c88d6b0..d3808ab 100644 --- a/src/game/terrain.cpp +++ b/src/game/terrain.cpp @@ -108,7 +108,7 @@ void Terrain::createSurface() glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(std::uint32_t) * surfaceIndexCount, surfaceIndexData, GL_STATIC_DRAW); // Setup material - surfaceMaterial.flags = static_cast(PhysicalMaterial::Flags::OBJECT); + //surfaceMaterial.flags = static_cast(PhysicalMaterial::Flags::OBJECT); // Setup buffers surfaceModel.setVAO(surfaceVAO); @@ -118,7 +118,7 @@ void Terrain::createSurface() // Create model group Model::Group* group = new Model::Group(); group->name = "default"; - group->material = &surfaceMaterial; + group->material = nullptr;//&surfaceMaterial; group->indexOffset = 0; group->triangleCount = surfaceTriangleCount; @@ -366,7 +366,7 @@ void Terrain::createSubsurface() glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(std::uint32_t) * subsurfaceIndexCount, subsurfaceIndexData, GL_STATIC_DRAW); // Setup material - subsurfaceMaterial.flags = static_cast(PhysicalMaterial::Flags::SOIL); + //subsurfaceMaterial.flags = static_cast(PhysicalMaterial::Flags::SOIL); // Setup buffers subsurfaceModel.setVAO(subsurfaceVAO); @@ -376,7 +376,7 @@ void Terrain::createSubsurface() // Create model group Model::Group* group = new Model::Group(); group->name = "default"; - group->material = &subsurfaceMaterial; + group->material = nullptr;//&subsurfaceMaterial; group->indexOffset = 0; group->triangleCount = subsurfaceTriangleCount; diff --git a/src/game/terrain.hpp b/src/game/terrain.hpp index 9e08dcc..52b3a18 100644 --- a/src/game/terrain.hpp +++ b/src/game/terrain.hpp @@ -21,7 +21,6 @@ #define TERRAIN_HPP #include "navmesh.hpp" -#include "../materials.hpp" #include using namespace Emergent; @@ -92,7 +91,7 @@ private: GLuint surfaceVAO; GLuint surfaceVBO; GLuint surfaceIBO; - PhysicalMaterial surfaceMaterial; + //PhysicalMaterial surfaceMaterial; Model surfaceModel; Navmesh surfaceNavmesh; Octree* surfaceOctree; @@ -109,7 +108,7 @@ private: GLuint subsurfaceVAO; GLuint subsurfaceVBO; GLuint subsurfaceIBO; - PhysicalMaterial subsurfaceMaterial; + //PhysicalMaterial subsurfaceMaterial; Model subsurfaceModel; Navmesh subsurfaceNavmesh; }; diff --git a/src/material-loader.cpp b/src/material-loader.cpp index 4b987de..66fef64 100644 --- a/src/material-loader.cpp +++ b/src/material-loader.cpp @@ -18,16 +18,17 @@ */ #include "material-loader.hpp" +#include #include +#include #include #include MaterialLoader::MaterialLoader() { textureLoader.setGamma(1.0f); - textureLoader.setCubemap(false); textureLoader.setMipmapChain(false); - textureLoader.setMaxAnisotropy(16.0f); + textureLoader.setMaxAnisotropy(1.0f); } MaterialLoader::~MaterialLoader() @@ -43,14 +44,20 @@ void MaterialLoader::unload() } materialCache.clear(); - for (auto it = textureCache.begin(); it != textureCache.end(); ++it) + for (auto it = texture2DCache.begin(); it != texture2DCache.end(); ++it) { delete it->second; } - textureCache.clear(); + texture2DCache.clear(); + + for (auto it = textureCubeCache.begin(); it != textureCubeCache.end(); ++it) + { + delete it->second; + } + textureCubeCache.clear(); } -PhysicalMaterial* MaterialLoader::load(const std::string& filename) +Material* MaterialLoader::load(const std::string& filename) { // Check if material exists in cache auto it = materialCache.find(filename); @@ -60,7 +67,7 @@ PhysicalMaterial* MaterialLoader::load(const std::string& filename) } // Allocate new material - PhysicalMaterial* material = new PhysicalMaterial(); + Material* material = new Material(); // Open file std::ifstream file(filename.c_str(), std::ifstream::in); @@ -83,83 +90,139 @@ PhysicalMaterial* MaterialLoader::load(const std::string& filename) continue; } - // Find position of first character in command string - std::size_t firstCommand = line.find_first_not_of(whitespace, 0); - if (firstCommand == std::string::npos) + // Find position of first character in variable name + std::size_t variableNamePosition = line.find_first_not_of(whitespace, 0); + if (variableNamePosition == std::string::npos) { + // Skip whitespace-only lines continue; } - // Find position of first character in delimeter string - std::size_t firstDelimeter = line.find_first_of(whitespace, firstCommand); - if (firstDelimeter == std::string::npos) + // Find position of equals sign + std::size_t equalsSignPosition = line.find_first_of("=", variableNamePosition); + if (equalsSignPosition == std::string::npos) { + // Skip lines with no equals sign continue; } - // Find position of first character in arguments string - std::size_t firstArgument = line.find_first_not_of(whitespace, firstDelimeter); - if (firstArgument == std::string::npos) + // Find position of first character in variable type + std::size_t variableTypePosition = line.find_first_not_of(whitespace, equalsSignPosition + 1); + if (variableTypePosition == std::string::npos) { - firstArgument = firstDelimeter + 1; + // Skip lines with no variable type definition + continue; + } + + // Count parentheses + std::size_t leftParenthesisCount = std::count(line.begin() + variableNamePosition, line.end(), '('); + std::size_t rightParenthesisCount = std::count(line.begin() + variableNamePosition, line.end(), ')'); + if (leftParenthesisCount != rightParenthesisCount || leftParenthesisCount == 0) + { + // Skip lines with invalid number of parentheses + continue; } - // Form command string and argument list string - std::string command = line.substr(firstCommand, firstDelimeter - firstCommand); - std::string argumentList = line.substr(firstArgument); + std::string variableName = line.substr(variableNamePosition, line.find_first_of(" \t=", variableNamePosition) - variableNamePosition); + std::string variableType = line.substr(variableTypePosition, line.find_first_of(" \t[(", variableTypePosition) - variableTypePosition); + std::size_t elementCount = leftParenthesisCount; + + std::size_t currentPosition = variableTypePosition; + std::vector> elements; + bool invalid = false; + for (std::size_t i = 0; i < elementCount; ++i) + { + std::size_t leftParenthesisPosition = line.find_first_of("(", currentPosition); + std::size_t rightParenthesisPosition = line.find_first_of(")", leftParenthesisPosition + 1); + + if (leftParenthesisPosition == std::string::npos || rightParenthesisPosition == std::string::npos) + { + invalid = true; + break; + } + + currentPosition = leftParenthesisPosition + 1; + std::size_t argumentCount = std::count(line.begin() + leftParenthesisPosition + 1, line.begin() + rightParenthesisPosition, ',') + 1; + std::vector arguments; + for (std::size_t j = 0; j < argumentCount; ++j) + { + std::size_t argumentStart = line.find_first_not_of(whitespace, currentPosition); + std::size_t argumentEnd = line.find_first_of(" \t,)", argumentStart + 1); + + if (argumentStart == std::string::npos || argumentEnd == std::string::npos) + { + // Unable to parse argument + invalid = true; + break; + } + + std::string argument = line.substr(argumentStart, argumentEnd - argumentStart); + arguments.push_back(argument); + + currentPosition = argumentEnd + 1; + } + + if (invalid) + { + // Unable to parse element + break; + } + + elements.push_back(arguments); + + currentPosition = rightParenthesisPosition + 1; + } - // Form vector of argument strings - std::vector arguments; - std::istringstream argumentStream(argumentList); - std::string argument; - while (argumentStream >> argument) + if (invalid) { - arguments.push_back(argument); + // Unable to parse line + continue; } - if (command == "albedo" && arguments.size() == 3) + if (variableType == "int") { - std::stringstream(arguments[0]) >> material->albedo.x; - std::stringstream(arguments[1]) >> material->albedo.y; - std::stringstream(arguments[2]) >> material->albedo.z; + ShaderInt* variable = material->addVariable(variableName, elements.size()); + loadShaderInt(variable, elements); } - else if (command == "opacity" && arguments.size() == 1) + else if (variableType == "float") { - std::stringstream(arguments[0]) >> material->opacity; + ShaderFloat* variable = material->addVariable(variableName, elements.size()); + loadShaderFloat(variable, elements); } - else if (command == "metalness" && arguments.size() == 1) + else if (variableType == "vec2") { - std::stringstream(arguments[0]) >> material->metalness; + ShaderVector2* variable = material->addVariable(variableName, elements.size()); + loadShaderVector2(variable, elements); } - else if (command == "roughness" && arguments.size() == 1) + else if (variableType == "vec3") { - std::stringstream(arguments[0]) >> material->roughness; + ShaderVector3* variable = material->addVariable(variableName, elements.size()); + loadShaderVector3(variable, elements); } - else if (command == "translucent" && arguments.size() == 1) + else if (variableType == "vec4") { - int translucent = 0; - std::stringstream(arguments[0]) >> translucent; - - if (translucent) - { - material->flags |= static_cast(PhysicalMaterial::Flags::TRANSLUCENT); - } + ShaderVector4* variable = material->addVariable(variableName, elements.size()); + loadShaderVector4(variable, elements); } - else if (command == "albedo-opacity-map") + else if (variableType == "mat3") { - material->albedoOpacityMap = loadTexture(argumentList); + ShaderMatrix3* variable = material->addVariable(variableName, elements.size()); + loadShaderMatrix3(variable, elements); } - else if (command == "metalness-roughness-map") + else if (variableType == "mat4") { - material->metalnessRoughnessMap = loadTexture(argumentList); + ShaderMatrix4* variable = material->addVariable(variableName, elements.size()); + loadShaderMatrix4(variable, elements); } - else if (command == "normal-occlusion-map") + else if (variableType == "texture") { - material->normalOcclusionMap = loadTexture(argumentList); + ShaderTexture2D* variable = material->addVariable(variableName, elements.size()); + loadShaderTexture2D(variable, elements); } - else if (command[0] != '#') + else if (variableType == "textureCube") { - std::cerr << "MaterialLoader::load(): Invalid line \"" << line << "\" in file \"" << filename << "\"" << std::endl; + ShaderTextureCube* variable = material->addVariable(variableName, elements.size()); + loadShaderTextureCube(variable, elements); } } @@ -172,11 +235,11 @@ PhysicalMaterial* MaterialLoader::load(const std::string& filename) return material; } -Texture* MaterialLoader::loadTexture(const std::string& filename) +Texture2D* MaterialLoader::loadTexture2D(const std::string& filename) { // Check if texture exists in cache - auto it = textureCache.find(filename); - if (it != textureCache.end()) + auto it = texture2DCache.find(filename); + if (it != texture2DCache.end()) { return it->second; } @@ -184,15 +247,215 @@ Texture* MaterialLoader::loadTexture(const std::string& filename) std::string fullFilename = std::string("data/textures/") + filename; // Load texture - Texture* texture = textureLoader.load(fullFilename); + Texture2D* texture = textureLoader.load2D(fullFilename); if (!texture) { - std::cerr << "MaterialLoader::loadTexture(): Failed to load texture file \"" << fullFilename << "\"" << std::endl; + std::cerr << "MaterialLoader::loadTexture2D(): Failed to load texture file \"" << fullFilename << "\"" << std::endl; return nullptr; } // Add texture to cache - textureCache[filename] = texture; + texture2DCache[filename] = texture; return texture; } + +TextureCube* MaterialLoader::loadTextureCube(const std::string& filename) +{ + // Check if texture exists in cache + auto it = textureCubeCache.find(filename); + if (it != textureCubeCache.end()) + { + return it->second; + } + + std::string fullFilename = std::string("data/textures/") + filename; + + // Load texture + TextureCube* texture = textureLoader.loadCube(fullFilename); + if (!texture) + { + std::cerr << "MaterialLoader::loadTextureCube(): Failed to load texture file \"" << fullFilename << "\"" << std::endl; + return nullptr; + } + + // Add texture to cache + textureCubeCache[filename] = texture; + + return texture; +} + +bool MaterialLoader::loadShaderInt(ShaderInt* variable, const std::vector>& elements) +{ + for (int i = 0; i < elements.size(); ++i) + { + int value; + std::stringstream stream; + stream << elements[i][0]; + stream >> value; + + variable->setValue(i, value); + } + + return true; +} + +bool MaterialLoader::loadShaderFloat(ShaderFloat* variable, const std::vector>& elements) +{ + for (int i = 0; i < elements.size(); ++i) + { + float value; + std::stringstream stream; + stream << elements[i][0]; + stream >> value; + + variable->setValue(i, value); + } + + return true; +} + +bool MaterialLoader::loadShaderVector2(ShaderVector2* variable, const std::vector>& elements) +{ + for (int i = 0; i < elements.size(); ++i) + { + Vector2 value; + + for (int j = 0; j < 2; ++j) + { + std::stringstream stream; + stream << elements[i][j]; + stream >> value[j]; + } + + variable->setValue(i, value); + } + + return true; +} + +bool MaterialLoader::loadShaderVector3(ShaderVector3* variable, const std::vector>& elements) +{ + for (int i = 0; i < elements.size(); ++i) + { + Vector3 value; + + for (int j = 0; j < 3; ++j) + { + std::stringstream stream; + stream << elements[i][j]; + stream >> value[j]; + } + + variable->setValue(i, value); + } + + return true; +} + +bool MaterialLoader::loadShaderVector4(ShaderVector4* variable, const std::vector>& elements) +{ + for (int i = 0; i < elements.size(); ++i) + { + Vector4 value; + + for (int j = 0; j < 4; ++j) + { + std::stringstream stream; + stream << elements[i][j]; + stream >> value[j]; + } + + variable->setValue(i, value); + } + + return true; +} + +bool MaterialLoader::loadShaderMatrix3(ShaderMatrix3* variable, const std::vector>& elements) +{ + for (int i = 0; i < elements.size(); ++i) + { + Matrix3 value; + + for (int j = 0; j < 3; ++j) + { + for (int k = 0; k < 3; ++k) + { + std::stringstream stream; + stream << elements[i][k * 3 + j]; + stream >> value[j][k]; + } + } + + variable->setValue(i, value); + } + + return true; +} + +bool MaterialLoader::loadShaderMatrix4(ShaderMatrix4* variable, const std::vector>& elements) +{ + for (int i = 0; i < elements.size(); ++i) + { + Matrix4 value; + + for (int j = 0; j < 4; ++j) + { + for (int k = 0; k < 4; ++k) + { + std::stringstream stream; + stream << elements[i][k * 4 + j]; + stream >> value[j][k]; + } + } + + variable->setValue(i, value); + } + + return true; +} + +bool MaterialLoader::loadShaderTexture2D(ShaderTexture2D* variable, const std::vector>& elements) +{ + for (int i = 0; i < elements.size(); ++i) + { + std::string filename; + std::stringstream stream; + stream << elements[i][0]; + stream >> filename; + + Texture2D* value = loadTexture2D(filename); + if (!value) + { + std::cerr << "MaterialLoader::loadShaderTexture2D(): Failed to load 2D texture \"" << filename << "\"" << std::endl; + return false; + } + + variable->setValue(i, value); + } + + return true; +} + +bool MaterialLoader::loadShaderTextureCube(ShaderTextureCube* variable, const std::vector>& elements) +{ + for (int i = 0; i < elements.size(); ++i) + { + std::string filename; + std::stringstream stream; + stream << elements[i][0]; + stream >> filename; + + TextureCube* value = loadTextureCube(filename); + if (!value) + { + std::cerr << "MaterialLoader::loadShaderTextureCube(): Failed to load cube texture \"" << filename << "\"" << std::endl; + return false; + } + + variable->setValue(i, value); + } + + return true; +} diff --git a/src/material-loader.hpp b/src/material-loader.hpp index 9bdfe07..ef596d7 100644 --- a/src/material-loader.hpp +++ b/src/material-loader.hpp @@ -20,8 +20,11 @@ #ifndef MATERIAL_LOADER_HPP #define MATERIAL_LOADER_HPP +#include +using namespace Emergent; + +#include #include -#include "materials.hpp" class MaterialLoader { @@ -30,12 +33,29 @@ public: ~MaterialLoader(); void unload(); - PhysicalMaterial* load(const std::string& filename); + + Material* load(const std::string& filename); private: - Texture* loadTexture(const std::string& filename); - std::map textureCache; - std::map materialCache; + Shader* loadShader(const std::string& filename); + Texture2D* loadTexture2D(const std::string& filename); + TextureCube* loadTextureCube(const std::string& filename); + + bool loadShaderInt(ShaderInt* variable, const std::vector>& elements); + bool loadShaderFloat(ShaderFloat* variable, const std::vector>& elements); + bool loadShaderVector2(ShaderVector2* variable, const std::vector>& elements); + bool loadShaderVector3(ShaderVector3* variable, const std::vector>& elements); + bool loadShaderVector4(ShaderVector4* variable, const std::vector>& elements); + bool loadShaderMatrix3(ShaderMatrix3* variable, const std::vector>& elements); + bool loadShaderMatrix4(ShaderMatrix4* variable, const std::vector>& elements); + bool loadShaderTexture2D(ShaderTexture2D* variable, const std::vector>& elements); + bool loadShaderTextureCube(ShaderTextureCube* variable, const std::vector>& elements); + + std::map shaderCache; + std::map texture2DCache; + std::map textureCubeCache; + std::map materialCache; + TextureLoader textureLoader; }; diff --git a/src/materials.hpp b/src/materials.hpp deleted file mode 100644 index 50ec213..0000000 --- a/src/materials.hpp +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (C) 2017 Christopher J. Howard - * - * This file is part of Antkeeper Source Code. - * - * Antkeeper Source Code is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Antkeeper Source Code is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Antkeeper Source Code. If not, see . - */ - -#ifndef MATERIALS -#define MATERIALS - -#include - -using namespace Emergent; - -enum class MaterialFormat -{ - UI, - PHYSICAL -}; - -class UIMaterial: public Material -{ -public: - UIMaterial(): texture(nullptr) {} - virtual ~UIMaterial() {} - - virtual unsigned int getMaterialFormatID() const; - - Texture* texture; -}; - -inline unsigned int UIMaterial::getMaterialFormatID() const -{ - return static_cast(MaterialFormat::UI); -} - -/// @see https://www.marmoset.co/posts/physically-based-rendering-and-you-can-too/ -class PhysicalMaterial: public Material -{ -public: - enum class Flags - { - OBJECT = 0x01, - TERRAIN = 0x02, - SOIL = 0x04, - TRANSLUCENT = 0x08 - }; - - PhysicalMaterial(): - albedoOpacityMap(nullptr), - metalnessRoughnessMap(nullptr), - normalOcclusionMap(nullptr), - flags((unsigned int)Flags::OBJECT), - shadowCaster(true), - shadowReceiver(true) - {}; - virtual ~PhysicalMaterial() {}; - virtual unsigned int getMaterialFormatID() const; - - unsigned int flags; - Vector3 albedo; - float opacity; - float metalness; - float roughness; - Texture* albedoOpacityMap; - Texture* metalnessRoughnessMap; - Texture* normalOcclusionMap; - bool shadowCaster; - bool shadowReceiver; -}; - -inline unsigned int PhysicalMaterial::getMaterialFormatID() const -{ - return static_cast(MaterialFormat::PHYSICAL); -} - -#endif // MATERIALS diff --git a/src/render-passes.cpp b/src/render-passes.cpp index 71f75a3..e26ac9f 100644 --- a/src/render-passes.cpp +++ b/src/render-passes.cpp @@ -18,7 +18,7 @@ */ #include "render-passes.hpp" -#include "materials.hpp" +#include "ui/ui.hpp" #include #include @@ -88,24 +88,42 @@ void ClearRenderPass::setClearStencil(int index) } BlurRenderPass::BlurRenderPass(): - textureID(0) -{ - textureParam = parameterSet.addParameter("blurTexture", ShaderParameter::Type::INT, 1); - resolutionParam = parameterSet.addParameter("resolution", ShaderParameter::Type::VECTOR_2, 1); - directionParam = parameterSet.addParameter("direction", ShaderParameter::Type::VECTOR_2, 1); -} + gammaCorrect(false) +{} bool BlurRenderPass::load(const RenderContext* renderContext) { - // Load shader - shaderLoader.undefine(); - shaderLoader.define("VERTEX_POSITION", EMERGENT_VERTEX_POSITION); - shader = shaderLoader.load("data/shaders/blur.glsl", ¶meterSet); - if (!shader) + permutation = (gammaCorrect) ? 1 : 0; + + // Load shader source + if (!shader.loadSource("data/shaders/blur.glsl")) + { + std::cerr << "BlurRenderPass: failed to load shader source." << std::endl; + return false; + } + + // Generate permutation + if (!shader.generatePermutation(permutation)) + { + std::cerr << "BlurRenderPass: failed to generate shader permutation." << std::endl; + return false; + } + + // Connect shader variables + textureParam.connect(shader.getInput("blurTexture")); + resolutionParam.connect(shader.getInput("resolution")); + directionParam.connect(shader.getInput("direction")); + if (!textureParam.isConnected() || + !resolutionParam.isConnected() || + !directionParam.isConnected()) { + std::cerr << "BlurRenderPass: one or more shader variables were not connected to shader inputs." << std::endl; return false; } + // Initialize shader variables + resolutionParam.setValue(Vector2(renderTarget->width, renderTarget->height)); + const float quadVertexData[] = { -1.0f, 1.0f, 0.0f, @@ -140,55 +158,45 @@ bool BlurRenderPass::load(const RenderContext* renderContext) void BlurRenderPass::unload() { - delete shader; - shader = nullptr; + textureParam.disconnect(); + resolutionParam.disconnect(); + directionParam.disconnect(); + shader.deleteAllPermutations(); glDeleteBuffers(1, &quadIBO); glDeleteBuffers(1, &quadVBO); glDeleteVertexArrays(1, &quadVAO); - - parameterSet.removeParameters(); } void BlurRenderPass::render(RenderContext* renderContext) { - // Bind framebuffer and setup viewport + // Bind framebuffer and set up viewport glBindFramebuffer(GL_FRAMEBUFFER, renderTarget->framebuffer); glViewport(0, 0, renderTarget->width, renderTarget->height); - // Clear the framebuffer - glClear(GL_COLOR_BUFFER_BIT); - - // Disable depth testing + // Set up OpenGL state glDisable(GL_DEPTH_TEST); glDepthMask(GL_FALSE); - - // Disable culling + glDisable(GL_BLEND); glDisable(GL_CULL_FACE); - // Bind shader - shader->bind(); - - // Bind texture - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, textureID); + // Activate shader permutation + shader.activate(permutation); - // Pass texture unit to shader - shader->setParameter(textureParam, 0); - shader->setParameter(resolutionParam, Vector2(renderTarget->width, renderTarget->height)); - shader->setParameter(directionParam, direction); + // Upload shader variables to shader permutation + textureParam.upload(); + resolutionParam.upload(); + directionParam.upload(); // Render quad glBindVertexArray(quadVAO); glDrawElementsBaseVertex(GL_TRIANGLES, quadIndexCount, GL_UNSIGNED_INT, (void*)0, 0); // Unbind texture - glBindTexture(GL_TEXTURE_2D, 0); + //glBindTexture(GL_TEXTURE_2D, 0); } ShadowMapRenderPass::ShadowMapRenderPass(): - unskinnedShader(nullptr), - skinnedShader(nullptr), croppedShadowMapViewports(nullptr), viewCamera(nullptr), splitViewFrustum(nullptr), @@ -238,27 +246,34 @@ bool ShadowMapRenderPass::load(const RenderContext* renderContext) tileMatrices[i] = glm::translate(Vector3(x, y, 0.0f)) * tileScale; } - // Setup shader parameters - modelViewProjectionParam = parameterSet.addParameter("modelViewProjectionMatrix", ShaderParameter::Type::MATRIX_4, 1); - matrixPaletteParam = parameterSet.addParameter("matrixPalette", ShaderParameter::Type::MATRIX_4, maxBoneCount); + // Setup permutation values + unskinnedPermutation = 0; + skinnedPermutation = 1; - // Load unskinned shader - shaderLoader.undefine(); - shaderLoader.define("VERTEX_POSITION", EMERGENT_VERTEX_POSITION); - unskinnedShader = shaderLoader.load("data/shaders/depth-pass.glsl", ¶meterSet); - if (!unskinnedShader) + // Load shader source + if (!shader.loadSource("data/shaders/depth-pass.glsl")) { + std::cerr << "ShadowMapRenderPass: failed to load shader source." << std::endl; return false; } - // Load skinned shader - shaderLoader.define("SKINNED"); - shaderLoader.define("VERTEX_BONE_INDICES", EMERGENT_VERTEX_BONE_INDICES); - shaderLoader.define("VERTEX_BONE_WEIGHTS", EMERGENT_VERTEX_BONE_WEIGHTS); - shaderLoader.define("MAX_BONE_COUNT", maxBoneCount); - skinnedShader = shaderLoader.load("data/shaders/depth-pass.glsl", ¶meterSet); - if (!skinnedShader) + // Generate unskinned and skinned permutations + if (!shader.generatePermutation(unskinnedPermutation) || !shader.generatePermutation(skinnedPermutation)) { + std::cerr << "ShadowMapRenderPass: failed to generate shader permutation." << std::endl; + return false; + } + + // Allocate bone palette parameter + matrixPaletteParam = new ShaderMatrix4(maxBoneCount); + + // Connect shader variables + modelViewProjectionParam.connect(shader.getInput("modelViewProjectionMatrix")); + matrixPaletteParam->connect(shader.getInput("matrixPalette")); + if (!modelViewProjectionParam.isConnected() || + !matrixPaletteParam->isConnected()) + { + std::cerr << "ShadowMapRenderPass: one or more shader variables were not connected to shader inputs." << std::endl; return false; } @@ -267,11 +282,10 @@ bool ShadowMapRenderPass::load(const RenderContext* renderContext) void ShadowMapRenderPass::unload() { - delete unskinnedShader; - unskinnedShader = nullptr; - - delete skinnedShader; - skinnedShader = nullptr; + modelViewProjectionParam.disconnect(); + matrixPaletteParam->disconnect(); + delete matrixPaletteParam; + shader.deleteAllPermutations(); delete[] croppedShadowMapViewports; croppedShadowMapViewports = nullptr; @@ -284,8 +298,6 @@ void ShadowMapRenderPass::unload() delete[] tileMatrices; tileMatrices = nullptr; - - parameterSet.removeParameters(); } void ShadowMapRenderPass::render(RenderContext* renderContext) @@ -312,7 +324,6 @@ void ShadowMapRenderPass::render(RenderContext* renderContext) //const Camera& lightCamera = *(renderContext->camera); std::list* operations = renderContext->queue->getOperations(); - Shader* shader = nullptr; GLuint boundVAO = 0; splitViewFrustum->setMatrices(viewCamera->getView(), viewCamera->getProjection()); @@ -320,6 +331,8 @@ void ShadowMapRenderPass::render(RenderContext* renderContext) // Sort operations operations->sort(RenderOpCompare()); + std::uint32_t permutation = 0xDEADBEEF; + // For each frustum split for (int i = 0; i < splitViewFrustum->getSubfrustumCount(); ++i) { @@ -374,47 +387,45 @@ void ShadowMapRenderPass::render(RenderContext* renderContext) for (const RenderOperation& operation: *operations) { // Skip render operations with unsupported materials + /* if (operation.material->getMaterialFormatID() != static_cast(MaterialFormat::PHYSICAL)) { continue; } + */ // Skip non shadow casters + /* const PhysicalMaterial* material = static_cast(operation.material); if (!material->shadowCaster) { continue; } + */ - // Select shader - Shader* targetShader = nullptr; - if (operation.pose != nullptr) - { - targetShader = skinnedShader; - } - else - { - targetShader = unskinnedShader; - } - // Switch shader if necessary - if (shader != targetShader) + // TODO: Perform culling for subfrustums + + + // Select permutation + std::uint32_t targetPermutation = (operation.pose != nullptr) ? skinnedPermutation : unskinnedPermutation; + if (permutation != targetPermutation) { - shader = targetShader; - - // Bind shader - shader->bind(); + permutation = targetPermutation; + shader.activate(permutation); } - + // Pass matrix palette if (operation.pose != nullptr) { - shader->setParameter(matrixPaletteParam, 0, operation.pose->getMatrixPalette(), operation.pose->getSkeleton()->getBoneCount()); + matrixPaletteParam->getConnectedInput()->upload(0, operation.pose->getMatrixPalette(), operation.pose->getSkeleton()->getBoneCount()); } const Matrix4& modelMatrix = operation.transform; Matrix4 modelViewProjectionMatrix = croppedViewProjection * modelMatrix; - shader->setParameter(modelViewProjectionParam, modelViewProjectionMatrix); + + modelViewProjectionParam.setValue(modelViewProjectionMatrix); + modelViewProjectionParam.upload(); if (boundVAO != operation.vao) { @@ -454,7 +465,6 @@ bool ShadowMapRenderPass::RenderOpCompare::operator()(const RenderOperation& opA LightingRenderPass::LightingRenderPass(): shadowMap(0), shadowCamera(nullptr), - treeShadow(nullptr), diffuseCubemap(nullptr), specularCubemap(nullptr), shadowMapPass(nullptr) @@ -465,484 +475,98 @@ LightingRenderPass::LightingRenderPass(): maxBoneCount = 64; maxDirectionalLightCount = 1; maxSpotlightCount = 1; - - matrixPaletteParam = parameterSet.addParameter("matrixPalette", ShaderParameter::Type::MATRIX_4, maxBoneCount); - modelParam = parameterSet.addParameter("modelMatrix", ShaderParameter::Type::MATRIX_4, 1); - modelViewParam = parameterSet.addParameter("modelViewMatrix", ShaderParameter::Type::MATRIX_4, 1); - modelViewProjectionParam = parameterSet.addParameter("modelViewProjectionMatrix", ShaderParameter::Type::MATRIX_4, 1); - normalModelViewParam = parameterSet.addParameter("normalModelViewMatrix", ShaderParameter::Type::MATRIX_3, 1); - normalModelParam = parameterSet.addParameter("normalModelMatrix", ShaderParameter::Type::MATRIX_3, 1); - lightViewProjectionsParam = parameterSet.addParameter("lightViewProjectionMatrices", ShaderParameter::Type::MATRIX_4, 4); - splitDistancesParam = parameterSet.addParameter("splitDistances", ShaderParameter::Type::VECTOR_4, 1); - shadowMapParam = parameterSet.addParameter("shadowMap", ShaderParameter::Type::INT, 1); - cameraPositionParam = parameterSet.addParameter("cameraPosition", ShaderParameter::Type::VECTOR_3, 1); - directionalLightCountParam = parameterSet.addParameter("directionalLightCount", ShaderParameter::Type::INT, 1); - directionalLightColorsParam = parameterSet.addParameter("directionalLightColors", ShaderParameter::Type::VECTOR_3, maxDirectionalLightCount); - directionalLightDirectionsParam = parameterSet.addParameter("directionalLightDirections", ShaderParameter::Type::VECTOR_3, maxDirectionalLightCount); - - spotlightCountParam = parameterSet.addParameter("spotlightCount", ShaderParameter::Type::INT, 1); - spotlightColorsParam = parameterSet.addParameter("spotlightColors", ShaderParameter::Type::VECTOR_3, maxSpotlightCount); - spotlightPositionsParam = parameterSet.addParameter("spotlightPositions", ShaderParameter::Type::VECTOR_3, maxSpotlightCount); - spotlightAttenuationsParam = parameterSet.addParameter("spotlightAttenuations", ShaderParameter::Type::VECTOR_3, maxSpotlightCount); - spotlightDirectionsParam = parameterSet.addParameter("spotlightDirections", ShaderParameter::Type::VECTOR_3, maxSpotlightCount); - spotlightCutoffsParam = parameterSet.addParameter("spotlightCutoffs", ShaderParameter::Type::FLOAT, maxSpotlightCount); - spotlightExponentsParam = parameterSet.addParameter("spotlightExponents", ShaderParameter::Type::FLOAT, maxSpotlightCount); - - albedoOpacityMapParam = parameterSet.addParameter("albedoOpacityMap", ShaderParameter::Type::INT, 1); - metalnessRoughnessMapParam = parameterSet.addParameter("metalnessRoughnessMap", ShaderParameter::Type::INT, 1); - normalOcclusionMapParam = parameterSet.addParameter("normalOcclusionMap", ShaderParameter::Type::INT, 1); - diffuseCubemapParam = parameterSet.addParameter("diffuseCubemap", ShaderParameter::Type::INT, 1); - specularCubemapParam = parameterSet.addParameter("specularCubemap", ShaderParameter::Type::INT, 1); } bool LightingRenderPass::load(const RenderContext* renderContext) { - // Load tree shadow - TextureLoader textureLoader; - treeShadow = textureLoader.load("data/textures/tree-shadow-0.png"); - if (!treeShadow) - { - std::cerr << "Failed to load tree shadow" << std::endl; - } + // Load shaders for each material - shaderLoader.undefine(); - shaderLoader.define("MAX_DIRECTIONAL_LIGHT_COUNT", maxDirectionalLightCount); - shaderLoader.define("MAX_SPOTLIGHT_COUNT", maxSpotlightCount); + // Register parameter sets for each unique shader - // Load unskinned shader - shaderLoader.define("TEXTURE_COUNT", 0); - shaderLoader.define("VERTEX_POSITION", EMERGENT_VERTEX_POSITION); - shaderLoader.define("VERTEX_NORMAL", EMERGENT_VERTEX_NORMAL); - shaderLoader.define("VERTEX_TEXCOORD", EMERGENT_VERTEX_TEXCOORD); - unskinnedShader = shaderLoader.load("data/shaders/lit-object.glsl", ¶meterSet); - - // Load skinned shader - shaderLoader.define("SKINNED"); - shaderLoader.define("MAX_BONE_COUNT", maxBoneCount); - shaderLoader.define("VERTEX_BONE_INDICES", EMERGENT_VERTEX_BONE_INDICES); - shaderLoader.define("VERTEX_BONE_WEIGHTS", EMERGENT_VERTEX_BONE_WEIGHTS); - skinnedShader = shaderLoader.load("data/shaders/lit-object.glsl", ¶meterSet); - - if (!unskinnedShader || !skinnedShader) + if (!shader.loadSource("data/shaders/standard.glsl")) { + std::cerr << "LightingRenderPass: Failed to load shader source." << std::endl; return false; } - time = 0.0f; - - return true; -} - -void LightingRenderPass::unload() -{ - delete unskinnedShader; - delete skinnedShader; - - unskinnedShader = nullptr; - skinnedShader = nullptr; - - for (auto it = shaderCache.begin(); it != shaderCache.end(); ++it) - { - delete it->second; - } - shaderCache.clear(); - - delete treeShadow; - treeShadow = nullptr; - - delete diffuseCubemap; - diffuseCubemap = nullptr; - - delete specularCubemap; - specularCubemap = nullptr; -} - -void LightingRenderPass::render(RenderContext* renderContext) -{ /* - time += 1.0f / 60.f; - - // Bind framebuffer and setup viewport - glBindFramebuffer(GL_FRAMEBUFFER, renderTarget->framebuffer); - glViewport(0, 0, renderTarget->width, renderTarget->height); - - // Clear the framebuffer depth - //glClearColor(0.0f, 0.0f, 0.0f, 1.0f); - //glClearDepth(1.0); - //glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - // Enable clipping - if (renderContext->layer->getIndex() == 0) + if (renderContext != nullptr) { - // Clipping pass - cappingRenderContext.camera = renderContext->camera; - cappingRenderContext.layer = renderContext->layer; - for (int i = 0; i < 5; ++i) + std::list* operations = renderContext->queue->getOperations(); + + for (RenderOperation& op: *operations) { - clippingRenderPass.setClippingPlane(clippingPlanes[i]); - clippingRenderPass.render(renderContext); - - Transform transform = Transform::getIdentity(); - transform.translation = clippingPlanes[i].getNormal() * -clippingPlanes[i].getDistance(); - transform.scale = Vector3(150.0f); - transform.rotation = glm::normalize(glm::rotation(Vector3(0, 0, -1), clippingPlanes[i].getNormal())); - - ModelInstance* cappingPlaneInstance = &cappingPlaneInstances[i]; - cappingPlaneInstance->setTransform(transform); - cappingRenderQueue.clear(); - cappingRenderQueue.queue(cappingPlaneInstance); - - cappingRenderPass.render(&cappingRenderContext); - } - - glEnable(GL_CLIP_DISTANCE0); } - else - { - glDisable(GL_CLIP_DISTANCE0); - } - - // Enable depth testing - glEnable(GL_DEPTH_TEST); - glDepthMask(GL_TRUE); - glDepthFunc(GL_LEQUAL); + */ - // Enable backface culling - glEnable(GL_CULL_FACE); - glCullFace(GL_BACK); - - // Enable alpha blending - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - const Camera& camera = *(renderContext->camera); - const std::list* operations = renderContext->queue->getOperations(); + // Set permutation values + std::uint32_t IS_SKINNED = 1; + std::uint32_t HAS_AMBIENT_CUBE = 1 << 7; + unskinnedPermutation = HAS_AMBIENT_CUBE; + skinnedPermutation = IS_SKINNED | HAS_AMBIENT_CUBE; - // Calculate camera direction - const Vector3& cameraDirection = camera.getForward(); - - // Textures - const std::size_t maxTextures = 8; - int materialTexture[maxTextures]; - Vector2 texcoordOffset[maxTextures]; - Vector2 texcoordScale[maxTextures]; - float textureDiffuseInfluence[maxTextures]; - float textureSpecularInfluence[maxTextures]; - float textureEmissiveInfluence[maxTextures]; - float textureRoughnessInfluence[maxTextures]; - float textureOpacityInfluence[maxTextures]; - float textureNormalInfluence[maxTextures]; - - for (std::size_t i = 0; i < maxTextures; ++i) + // Generate shader permutations + if (!shader.generatePermutation(unskinnedPermutation) || !shader.generatePermutation(skinnedPermutation)) { - materialTexture[i] = i + 2; + std::cerr << "LightingRenderPass: failed to generate shader permutation." << std::endl; + return false; } - // Lights - // Point lights - const std::size_t maxPointLightCount = 4; - std::size_t pointLightCount = 0; - Vector3 pointLightColor[maxPointLightCount]; - Vector3 pointLightPosition[maxPointLightCount]; - Vector3 pointLightAttenuation[maxPointLightCount]; - for (std::size_t i = 0; i < maxPointLightCount; ++i) - pointLightColor[i] = Vector3(0.0f); - - // Directional lights - const std::size_t maxDirectionalLightCount = 4; - std::size_t directionalLightCount = 0; - Vector3 directionalLightColor[maxDirectionalLightCount]; - Vector3 directionalLightDirection[maxDirectionalLightCount]; - for (std::size_t i = 0; i < maxDirectionalLightCount; ++i) - directionalLightColor[i] = Vector3(0.0f); - - // Spotlights - const std::size_t maxSpotlightCount = 4; - std::size_t spotlightCount = 0; - Vector3 spotlightColor[maxSpotlightCount]; - Vector3 spotlightPosition[maxSpotlightCount]; - Vector3 spotlightAttenuation[maxSpotlightCount]; - Vector3 spotlightDirection[maxSpotlightCount]; - float spotlightCutoff[maxSpotlightCount]; - float spotlightExponent[maxSpotlightCount]; - for (std::size_t i = 0; i < maxSpotlightCount; ++i) - spotlightColor[i] = Vector3(0.0f); - - const std::list* lights = renderContext->layer->getObjects(SceneObjectType::LIGHT); - if (lights != nullptr) + // Allocate shader array parameters + parameters.matrixPalette = new ShaderMatrix4(maxBoneCount); + parameters.lightViewProjectionMatrices = new ShaderMatrix4(4); + + // Connect shader parameters + parameters.matrixPalette->connect(shader.getInput("matrixPalette")); + parameters.modelMatrix.connect(shader.getInput("modelMatrix")); + parameters.modelViewMatrix.connect(shader.getInput("modelViewMatrix")); + parameters.modelViewProjectionMatrix.connect(shader.getInput("modelViewProjectionMatrix")); + parameters.normalModelViewMatrix.connect(shader.getInput("normalModelViewMatrix")); + parameters.normalModelMatrix.connect(shader.getInput("normalModelMatrix")); + parameters.lightViewProjectionMatrices->connect(shader.getInput("lightViewProjectionMatrices")); + parameters.splitDistances.connect(shader.getInput("splitDistances")); + parameters.shadowMap.connect(shader.getInput("shadowMap")); + parameters.cameraPosition.connect(shader.getInput("cameraPosition")); + parameters.diffuseCubemap.connect(shader.getInput("diffuseCubemap")); + parameters.specularCubemap.connect(shader.getInput("specularCubemap")); + + parameters.albedoOpacityMap.connect(shader.getInput("albedoOpacityMap")); + parameters.metalnessRoughnessMap.connect(shader.getInput("metalnessRoughnessMap")); + parameters.normalOcclusionMap.connect(shader.getInput("normalOcclusionMap")); + + if (!parameters.matrixPalette->isConnected() || + !parameters.modelMatrix.isConnected() || + !parameters.modelViewMatrix.isConnected() || + !parameters.modelViewProjectionMatrix.isConnected() || + !parameters.normalModelViewMatrix.isConnected() || + !parameters.normalModelMatrix.isConnected() || + !parameters.lightViewProjectionMatrices->isConnected() || + !parameters.splitDistances.isConnected() || + !parameters.shadowMap.isConnected() || + !parameters.cameraPosition.isConnected() || + !parameters.diffuseCubemap.isConnected() || + !parameters.specularCubemap.isConnected()) { - for (auto object: *lights) - { - const Light* light = static_cast(object); - LightType lightType = light->getLightType(); - - if (lightType == LightType::POINT) - { - const PointLight* pointLight = static_cast(light); - - pointLightColor[pointLightCount] = pointLight->getScaledColor(); - pointLightPosition[pointLightCount] = Vector3(camera.getView() * Vector4(pointLight->getTranslation(), 1.0f)); - pointLightAttenuation[pointLightCount] = pointLight->getAttenuation(); - - ++pointLightCount; - } - else if (lightType == LightType::DIRECTIONAL) - { - const DirectionalLight* directionalLight = static_cast(light); - - directionalLightColor[directionalLightCount] = directionalLight->getScaledColor(); - directionalLightDirection[directionalLightCount] = glm::normalize(Vector3(camera.getView() * Vector4(-directionalLight->getDirection(), 0.0f))); - - ++directionalLightCount; - } - else if (lightType == LightType::SPOTLIGHT) - { - const Spotlight* spotlight = static_cast(light); - - spotlightColor[spotlightCount] = spotlight->getScaledColor(); - spotlightPosition[spotlightCount] = Vector3(camera.getView() * Vector4(spotlight->getTranslation(), 1.0f)); - spotlightAttenuation[spotlightCount] = spotlight->getAttenuation(); - spotlightDirection[spotlightCount] = glm::normalize(Vector3(camera.getView() * Vector4(-spotlight->getDirection(), 0.0f))); - spotlightCutoff[spotlightCount] = spotlight->getCutoff(); - spotlightExponent[spotlightCount] = spotlight->getExponent(); - - ++spotlightCount; - } - } + std::cerr << "LightingRenderPass: one or more shader variables were not connected to shader inputs." << std::endl; } - // Calculate the (light-space) view-projection-bias matrix - Matrix4 viewProjectionBiasMatrix = biasMatrix * shadowCamera->getViewProjection(); + return true; +} - // Bind shader - Shader* boundShader = nullptr; - - // Bind shadow map - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, shadowMap); - - // Bind tree shadow - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, treeShadow.getTextureID()); - - // For each clipping plane - - for (int clippingPlaneIndex = 0; clippingPlaneIndex < 5; ++clippingPlaneIndex) - { - // Render operations - for (const RenderOperation& operation: *operations) - { - const Material* material = operation.material; - - // Find shader - std::size_t hashValue = material->getHashValue(); - auto it = shaderCache.find(hashValue); - if (it == shaderCache.end()) - { - std::cerr << "Warning: material requires unloaded shader" << std::endl; - continue; - } - - // Bind shader - Shader* shader = it->second; - if (shader != boundShader) - { - shader->bind(); - boundShader = shader; - } - - // Get shader parameters - ShaderParameterSet* parameters = shader->getParameters(); - - const Matrix4& modelMatrix = operation.transform; - Matrix4 modelViewMatrix = camera.getView() * modelMatrix; - Matrix4 modelViewProjectionMatrix = camera.getViewProjection() * modelMatrix; - - // Pass matrix parameters - if (parameters->hasParameter(ShaderParameter::MODEL_MATRIX)) - { - parameters->setValue(ShaderParameter::MODEL_MATRIX, modelMatrix); - } - - if (parameters->hasParameter(ShaderParameter::MODEL_VIEW_MATRIX)) - { - parameters->setValue(ShaderParameter::MODEL_VIEW_MATRIX, modelViewMatrix); - } - if (parameters->hasParameter(ShaderParameter::MODEL_VIEW_PROJECTION_MATRIX)) - { - parameters->setValue(ShaderParameter::MODEL_VIEW_PROJECTION_MATRIX, modelViewProjectionMatrix); - } - if (parameters->hasParameter(ShaderParameter::NORMAL_MODEL_MATRIX)) - { - Matrix3 normalModelMatrix = glm::transpose(glm::inverse(Matrix3(modelMatrix))); - parameters->setValue(ShaderParameter::NORMAL_MODEL_MATRIX, normalModelMatrix); - } - if (parameters->hasParameter(ShaderParameter::NORMAL_MODEL_VIEW_MATRIX)) - { - Matrix3 normalModelViewMatrix = glm::transpose(glm::inverse(Matrix3(modelViewMatrix))); - parameters->setValue(ShaderParameter::NORMAL_MODEL_VIEW_MATRIX, normalModelViewMatrix); - } - if (parameters->hasParameter(ShaderParameter::CAMERA_DIRECTION)) - { - parameters->setValue(ShaderParameter::CAMERA_DIRECTION, cameraDirection); - } - - // Pass material parameters - if (parameters->hasParameter(ShaderParameter::MATERIAL_DIFFUSE_COLOR)) - { - parameters->setValue(ShaderParameter::MATERIAL_DIFFUSE_COLOR, material->getDiffuseColor()); - } - if (parameters->hasParameter(ShaderParameter::MATERIAL_SPECULAR_COLOR)) - { - parameters->setValue(ShaderParameter::MATERIAL_SPECULAR_COLOR, material->getSpecularColor()); - } - if (parameters->hasParameter(ShaderParameter::MATERIAL_EMISSIVE_COLOR)) - { - parameters->setValue(ShaderParameter::MATERIAL_EMISSIVE_COLOR, material->getEmissiveColor()); - } - if (parameters->hasParameter(ShaderParameter::MATERIAL_ROUGHNESS)) - { - parameters->setValue(ShaderParameter::MATERIAL_ROUGHNESS, material->getRoughness()); - } - if (parameters->hasParameter(ShaderParameter::MATERIAL_OPACITY)) - { - parameters->setValue(ShaderParameter::MATERIAL_OPACITY, material->getOpacity()); - } - - // Pass texture parameters - if (parameters->hasParameter(ShaderParameter::MATERIAL_TEXTURE)) - { - std::size_t textureCount = material->getTextureCount(); - - for (std::size_t i = 0; i < textureCount; ++i) - { - const Texture* texture = material->getTexture(i); - texcoordOffset[i] = Vector2(texture->getCoordinateOffset()); - texcoordScale[i] = Vector2(texture->getCoordinateScale()); - textureDiffuseInfluence[i] = texture->getDiffuseInfluence(); - textureSpecularInfluence[i] = texture->getSpecularInfluence(); - textureEmissiveInfluence[i] = texture->getEmissiveInfluence(); - textureRoughnessInfluence[i] = texture->getRoughnessInfluence(); - textureOpacityInfluence[i] = texture->getOpacityInfluence(); - textureNormalInfluence[i] = texture->getNormalInfluence(); - - // Bind texture - glActiveTexture(GL_TEXTURE2 + i); - glBindTexture(GL_TEXTURE_2D, texture->getTextureID()); - } - - parameters->setValue(ShaderParameter::MATERIAL_TEXTURE, 0, &materialTexture[0], textureCount); - if (parameters->hasParameter(ShaderParameter::TEXCOORD_OFFSET)) - parameters->setValue(ShaderParameter::TEXCOORD_OFFSET, 0, &texcoordOffset[0], textureCount); - if (parameters->hasParameter(ShaderParameter::TEXCOORD_SCALE)) - parameters->setValue(ShaderParameter::TEXCOORD_SCALE, 0, &texcoordScale[0], textureCount); - - if (parameters->hasParameter(ShaderParameter::TEXTURE_DIFFUSE_INFLUENCE)) - parameters->setValue(ShaderParameter::TEXTURE_DIFFUSE_INFLUENCE, 0, &textureDiffuseInfluence[0], textureCount); - if (parameters->hasParameter(ShaderParameter::TEXTURE_SPECULAR_INFLUENCE)) - parameters->setValue(ShaderParameter::TEXTURE_SPECULAR_INFLUENCE, 0, &textureSpecularInfluence[0], textureCount); - if (parameters->hasParameter(ShaderParameter::TEXTURE_EMISSIVE_INFLUENCE)) - parameters->setValue(ShaderParameter::TEXTURE_EMISSIVE_INFLUENCE, 0, &textureEmissiveInfluence[0], textureCount); - if (parameters->hasParameter(ShaderParameter::TEXTURE_ROUGHNESS_INFLUENCE)) - parameters->setValue(ShaderParameter::TEXTURE_ROUGHNESS_INFLUENCE, 0, &textureRoughnessInfluence[0], textureCount); - if (parameters->hasParameter(ShaderParameter::TEXTURE_OPACITY_INFLUENCE)) - parameters->setValue(ShaderParameter::TEXTURE_OPACITY_INFLUENCE, 0, &textureOpacityInfluence[0], textureCount); - if (parameters->hasParameter(ShaderParameter::TEXTURE_NORMAL_INFLUENCE)) - parameters->setValue(ShaderParameter::TEXTURE_NORMAL_INFLUENCE, 0, &textureNormalInfluence[0], textureCount); - } - - // Pass lighting parameters - if (parameters->hasParameter(ShaderParameter::POINT_LIGHT_COLOR)) - { - parameters->setValue(ShaderParameter::POINT_LIGHT_COLOR, 0, &pointLightColor[0], spotlightCount); - parameters->setValue(ShaderParameter::POINT_LIGHT_POSITION, 0, &pointLightPosition[0], spotlightCount); - parameters->setValue(ShaderParameter::POINT_LIGHT_ATTENUATION, 0, &pointLightAttenuation[0], spotlightCount); - } - if (parameters->hasParameter(ShaderParameter::DIRECTIONAL_LIGHT_COLOR)) - { - parameters->setValue(ShaderParameter::DIRECTIONAL_LIGHT_COLOR, 0, &directionalLightColor[0], directionalLightCount); - parameters->setValue(ShaderParameter::DIRECTIONAL_LIGHT_DIRECTION, 0, &directionalLightDirection[0], directionalLightCount); - } - if (parameters->hasParameter(ShaderParameter::SPOTLIGHT_COLOR)) - { - parameters->setValue(ShaderParameter::SPOTLIGHT_COLOR, 0, &spotlightColor[0], spotlightCount); - parameters->setValue(ShaderParameter::SPOTLIGHT_POSITION, 0, &spotlightPosition[0], spotlightCount); - parameters->setValue(ShaderParameter::SPOTLIGHT_ATTENUATION, 0, &spotlightAttenuation[0], spotlightCount); - parameters->setValue(ShaderParameter::SPOTLIGHT_DIRECTION, 0, &spotlightDirection[0], spotlightCount); - parameters->setValue(ShaderParameter::SPOTLIGHT_CUTOFF, 0, &spotlightCutoff[0], spotlightCount); - parameters->setValue(ShaderParameter::SPOTLIGHT_EXPONENT, 0, &spotlightExponent[0], spotlightCount); - } - if (parameters->hasParameter(ShaderParameter::DIFFUSE_ENVIRONMENT_MAP)) - { - parameters->setValue(ShaderParameter::DIFFUSE_ENVIRONMENT_MAP, 1); - } - if (parameters->hasParameter(ShaderParameter::SPECULAR_ENVIRONMENT_MAP)) - { - parameters->setValue(ShaderParameter::SPECULAR_ENVIRONMENT_MAP, 2); - } - - // Pass shadow parameters - if (parameters->hasParameter(ShaderParameter::MODEL_VIEW_PROJECTION_BIAS_MATRIX)) - { - Matrix4 modelViewProjectionBiasMatrix = viewProjectionBiasMatrix * modelMatrix; - parameters->setValue(ShaderParameter::MODEL_VIEW_PROJECTION_BIAS_MATRIX, modelViewProjectionBiasMatrix); - } - if (parameters->hasParameter(ShaderParameter::SHADOW_MAP)) - { - parameters->setValue(ShaderParameter::SHADOW_MAP, 0); - } - if (parameters->hasParameter(ShaderParameter::TREE_SHADOW)) - { - parameters->setValue(ShaderParameter::TREE_SHADOW, 1); - } - if (parameters->hasParameter(ShaderParameter::TIME)) - { - parameters->setValue(ShaderParameter::TIME, time); - } - - // Pass clipping parameters - if (parameters->hasParameter(ShaderParameter::CLIPPING_PLANES)) - { - const Plane& clippingPlane = clippingPlanes[clippingPlaneIndex]; - parameters->setValue(ShaderParameter::CLIPPING_PLANES, Vector4(clippingPlane.getNormal(), clippingPlane.getDistance())); - } - - // Draw geometry - glBindVertexArray(operation.vao); - if (!material->isOpaque()) - { - - //glBlendFunc(GL_ZERO, GL_SRC_COLOR); - //glBlendFunc(GL_ONE, GL_ONE); - //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - //glBlendFunc(GL_ZERO, GL_SRC_COLOR); - //glDepthMask(GL_FALSE); - glFrontFace(GL_CW); - +void LightingRenderPass::unload() +{ + // Free shader array parameters + delete parameters.matrixPalette; + delete parameters.lightViewProjectionMatrices; + parameters.matrixPalette = nullptr; + parameters.lightViewProjectionMatrices = nullptr; + shader.deleteAllPermutations(); +} - glDrawElementsBaseVertex(GL_TRIANGLES, operation.triangleCount * 3, GL_UNSIGNED_INT, (void*)0, operation.indexOffset); - - parameters->setValue(ShaderParameter::MATERIAL_DIFFUSE_COLOR, material->getDiffuseColor() * 0.05f); - glFrontFace(GL_CCW); - //glDepthMask(GL_TRUE); - glDrawElementsBaseVertex(GL_TRIANGLES, operation.triangleCount * 3, GL_UNSIGNED_INT, (void*)0, operation.indexOffset); - //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } - else - { - glDrawElementsBaseVertex(GL_TRIANGLES, operation.triangleCount * 3, GL_UNSIGNED_INT, (void*)0, operation.indexOffset); - } - - - } - } - - // Disable clipping - glDisable(GL_CLIP_DISTANCE0); - */ - +void LightingRenderPass::render(RenderContext* renderContext) +{ const Camera& camera = *(renderContext->camera); std::list* operations = renderContext->queue->getOperations(); @@ -960,8 +584,9 @@ void LightingRenderPass::render(RenderContext* renderContext) glCullFace(GL_BACK); // Enable alpha blending - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glDisable(GL_BLEND); + Vector4 splitDistances; @@ -1011,80 +636,60 @@ void LightingRenderPass::render(RenderContext* renderContext) } } - // Calculate the (light-space) view-projection matrix - + // Calculate the (light-space) view-projection matrices Matrix4 lightViewProjectionMatrices[4]; for (int i = 0; i < 4; ++i) { lightViewProjectionMatrices[i] = shadowMapPass->getTileMatrix(i) * biasMatrix * shadowMapPass->getCropMatrix(i) * shadowCamera->getViewProjection(); } - //Matrix4 lightViewProjectionMatrix = biasMatrix * shadowCamera->getViewProjection(); - - glActiveTexture(GL_TEXTURE3); - glBindTexture(GL_TEXTURE_CUBE_MAP, diffuseCubemap->getTextureID()); - - glActiveTexture(GL_TEXTURE4); - glBindTexture(GL_TEXTURE_CUBE_MAP, specularCubemap->getTextureID()); - - glActiveTexture(GL_TEXTURE5); - glBindTexture(GL_TEXTURE_2D, shadowMap); - - Shader* shader = nullptr; + // Set shader parameter values + parameters.lightViewProjectionMatrices->setValues(0, &lightViewProjectionMatrices[0], 4); + parameters.splitDistances.setValue(splitDistances); + parameters.cameraPosition.setValue(camera.getTranslation()); + parameters.diffuseCubemap.setValue(diffuseCubemap); + parameters.specularCubemap.setValue(specularCubemap); + parameters.shadowMap.setValue(shadowMap); + parameters.directionalLightCount.setValue(0); + parameters.spotlightCount.setValue(0); + + std::uint32_t permutation = 0xDEADBEEF; + bool blending = false; GLuint boundVAO = 0; - Texture* albedoOpacityMap = nullptr; - Texture* metalnessRoughnessMap = nullptr; - Texture* normalOcclusionMap = nullptr; // Sort operations - operations->sort(RenderOpCompare()); - - int switches = 0; + //operations->sort(RenderOpCompare()); // Render operations for (const RenderOperation& operation: *operations) { - // Skip render operations with unsupported materials - if (operation.material->getMaterialFormatID() != static_cast(MaterialFormat::PHYSICAL)) - { - continue; - } - const PhysicalMaterial* material = static_cast(operation.material); - if (!(material->flags & (unsigned int)PhysicalMaterial::Flags::OBJECT)) + /* + bool hasTranslucency = material->flags & (unsigned int)PhysicalMaterial::Flags::TRANSLUCENT; + if (hasTranslucency && !blending) { - continue; + glEnable(GL_BLEND); + blending = true; } + */ - // Skip render operations with unsupported vertex formats - - // Select shader - Shader* targetShader = nullptr; - if (operation.pose != nullptr) - { - targetShader = skinnedShader; - } - else + // Select permutation + std::uint32_t targetPermutation = (operation.pose != nullptr) ? skinnedPermutation : unskinnedPermutation; + if (permutation != targetPermutation) { - targetShader = unskinnedShader; - } + permutation = targetPermutation; + shader.activate(permutation); - // Switch shader if necessary - if (shader != targetShader) - { - shader = targetShader; - - // Bind shader - shader->bind(); - // Pass static params - shader->setParameter(lightViewProjectionsParam, 0, &lightViewProjectionMatrices[0], 4); - shader->setParameter(splitDistancesParam, splitDistances); - shader->setParameter(albedoOpacityMapParam, 0); - shader->setParameter(metalnessRoughnessMapParam, 1); - shader->setParameter(normalOcclusionMapParam, 2); - shader->setParameter(diffuseCubemapParam, 3); - shader->setParameter(specularCubemapParam, 4); - shader->setParameter(shadowMapParam, 5); + parameters.lightViewProjectionMatrices->upload(); + parameters.splitDistances.upload(); + parameters.cameraPosition.upload(); + parameters.diffuseCubemap.upload(); + parameters.specularCubemap.upload(); + parameters.shadowMap.upload(); + parameters.directionalLightCount.upload(); + parameters.spotlightCount.upload(); + + /* shader->setParameter(directionalLightCountParam, directionalLightCount); shader->setParameter(directionalLightColorsParam, 0, &directionalLightColors[0], directionalLightCount); shader->setParameter(directionalLightDirectionsParam, 0, &directionalLightDirections[0], directionalLightCount); @@ -1096,64 +701,48 @@ void LightingRenderPass::render(RenderContext* renderContext) shader->setParameter(spotlightDirectionsParam, 0, &spotlightDirections[0], spotlightCount); shader->setParameter(spotlightCutoffsParam, 0, &spotlightCutoffs[0], spotlightCount); shader->setParameter(spotlightExponentsParam, 0, &spotlightExponents[0], spotlightCount); - - shader->setParameter(cameraPositionParam, camera.getTranslation()); + */ } - // Pass matrix palette - if (operation.pose != nullptr) - { - shader->setParameter(matrixPaletteParam, 0, operation.pose->getMatrixPalette(), operation.pose->getSkeleton()->getBoneCount()); - } + const Matrix4& modelMatrix = operation.transform; + Matrix4 modelViewMatrix = camera.getView() * modelMatrix; + Matrix4 modelViewProjectionMatrix = camera.getViewProjection() * modelMatrix; + Matrix3 normalModelViewMatrix = glm::transpose(glm::inverse(Matrix3(modelViewMatrix))); + Matrix3 normalModelMatrix = glm::transpose(glm::inverse(Matrix3(modelMatrix))); + + parameters.modelMatrix.setValue(modelMatrix); + parameters.modelViewMatrix.setValue(modelViewMatrix); + parameters.modelViewProjectionMatrix.setValue(modelViewProjectionMatrix); + parameters.normalModelViewMatrix.setValue(normalModelViewMatrix); + parameters.normalModelMatrix.setValue(normalModelMatrix); - // Bind albedo-opacity map - if (material->albedoOpacityMap != albedoOpacityMap) + // Upload matrix parameters + parameters.modelMatrix.upload(); + parameters.modelViewMatrix.upload(); + parameters.modelViewProjectionMatrix.upload(); + parameters.normalModelViewMatrix.upload(); + parameters.normalModelMatrix.upload(); + + // Upload pose matrix palette + if (operation.pose != nullptr && parameters.matrixPalette->isConnected()) { - albedoOpacityMap = material->albedoOpacityMap; - - if (albedoOpacityMap != nullptr) - { - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, albedoOpacityMap->getTextureID()); - } + parameters.matrixPalette->getConnectedInput()->upload(0, operation.pose->getMatrixPalette(), operation.pose->getSkeleton()->getBoneCount()); } - // Bind metalness-roughness map - if (material->metalnessRoughnessMap != metalnessRoughnessMap) + // Upload material parameters + if (operation.material != nullptr) { - metalnessRoughnessMap = material->metalnessRoughnessMap; - - if (metalnessRoughnessMap != nullptr) + if (operation.material->getShader() != &shader) { - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, metalnessRoughnessMap->getTextureID()); + ((Material*)operation.material)->setShader(&shader); } + operation.material->upload(); } - - // Bind normal-occlusion map - if (material->normalOcclusionMap != normalOcclusionMap) + else { - normalOcclusionMap = material->normalOcclusionMap; - - if (normalOcclusionMap != nullptr) - { - glActiveTexture(GL_TEXTURE2); - glBindTexture(GL_TEXTURE_2D, normalOcclusionMap->getTextureID()); - } + //std::cerr << "NULL MATERIAL!!!" << std::endl; } - const Matrix4& modelMatrix = operation.transform; - Matrix4 modelViewMatrix = camera.getView() * modelMatrix; - Matrix4 modelViewProjectionMatrix = camera.getViewProjection() * modelMatrix; - Matrix3 normalModelViewMatrix = glm::transpose(glm::inverse(Matrix3(modelViewMatrix))); - Matrix3 normalModelMatrix = glm::transpose(glm::inverse(Matrix3(modelMatrix))); - - shader->setParameter(modelParam, modelMatrix); - shader->setParameter(modelViewParam, modelViewMatrix); - shader->setParameter(modelViewProjectionParam, modelViewProjectionMatrix); - shader->setParameter(normalModelViewParam, normalModelViewMatrix); - shader->setParameter(normalModelParam, normalModelMatrix); - if (boundVAO != operation.vao) { glBindVertexArray(operation.vao); @@ -1164,77 +753,12 @@ void LightingRenderPass::render(RenderContext* renderContext) } glActiveTexture(GL_TEXTURE5); - glBindTexture(GL_TEXTURE_2D, 0); -} - -bool LightingRenderPass::loadShader(const RenderOperation& operation) -{ - /* - const std::string shaderFilename = "data/shaders/main.glsl"; - - // Get material and its hash value - const Material* material = operation.material; - std::size_t hashValue = material->getHashValue(); - - // Check if shader has already been loaded - auto it = shaderCache.find(hashValue); - if (it != shaderCache.end()) - return true; - - // Define shader preprocessor macros - - // Undefine previous definitions - shaderLoader.undefine(); - - // Clipping - shaderLoader.define("CLIPPING_PLANE_COUNT", 1); - - // Vertex format - shaderLoader.define("VERTEX_POSITION", EMERGENT_VERTEX_POSITION); - shaderLoader.define("VERTEX_NORMAL", EMERGENT_VERTEX_NORMAL); - //shaderLoader.define("VERTEX_COLOR", EMERGENT_VERTEX_COLOR); - - // Lighting - - - // Material - if (material->isShadeless()) - { - shaderLoader.define("SHADELESS"); - } - else - { - // Lighting - //shaderLoader.define("POINT_LIGHT_COUNT", 1); - shaderLoader.define("DIRECTIONAL_LIGHT_COUNT", 2); - //shaderLoader.define("SPOTLIGHT_COUNT", 2); - //shaderLoader.define("ENVIRONMENT_MAP"); - } - - if (material->isShadowReceiver()) - shaderLoader.define("SHADOWED"); - - // Final - shaderLoader.define("GAMMA_CORRECT"); - - // Load shader - Shader* shader = shaderLoader.load(shaderFilename); - if (!shader) - { - std::cerr << "Failed to load shader \"" << shaderFilename << "\"" << std::endl; - return false; - } - - // Store shader in cache - shaderCache[hashValue] = shader; - - return true; - */ - return false; + glBindTexture(GL_TEXTURE_2D, 0); } bool LightingRenderPass::RenderOpCompare::operator()(const RenderOperation& opA, const RenderOperation& opB) const { + /* // Skip render operations with unsupported materials if (opA.material->getMaterialFormatID() != static_cast(MaterialFormat::PHYSICAL)) { @@ -1257,7 +781,7 @@ bool LightingRenderPass::RenderOpCompare::operator()(const RenderOperation& opA, { if (transparentB) { - // A and B are both transparent, sort by depth + // A and B are both transparent, render back to front return (opA.depth <= opB.depth); } else @@ -1277,20 +801,42 @@ bool LightingRenderPass::RenderOpCompare::operator()(const RenderOperation& opA, { // A and B are both opaque, sort by material return (opA.material < opB.material); + + // A and B are both opaque, render front to back + //return (opA.depth > opB.depth); } } + */ + + return (opA.material->getShader() < opB.material->getShader()); } DebugRenderPass::DebugRenderPass() -{ - modelViewProjectionParam = parameterSet.addParameter("modelViewProjectionMatrix", ShaderParameter::Type::MATRIX_4, 1); -} +{} bool DebugRenderPass::load(const RenderContext* renderContext) { - unlitSolidShader = shaderLoader.load("data/shaders/unlit-solid.glsl", ¶meterSet); - if (!unlitSolidShader) + if (!shader.loadSource("data/shaders/unlit-solid.glsl")) { + std::cerr << "DebugRenderPass: Failed to load shader source." << std::endl; + return false; + } + + // Set permutation values + permutation = 0; + + // Generate shader permutations + if (!shader.generatePermutation(permutation)) + { + std::cerr << "DebugRenderPass: failed to generate shader permutation." << std::endl; + return false; + } + + // Connect shader variables + modelViewProjectionMatrixParam.connect(shader.getInput("modelViewProjectionMatrix")); + if (!modelViewProjectionMatrixParam.isConnected()) + { + std::cerr << "DebugRenderPass: one or more shader variables were not connected to shader inputs." << std::endl; return false; } @@ -1333,8 +879,8 @@ bool DebugRenderPass::load(const RenderContext* renderContext) void DebugRenderPass::unload() { - delete unlitSolidShader; - unlitSolidShader = nullptr; + modelViewProjectionMatrixParam.disconnect(); + shader.deleteAllPermutations(); glDeleteBuffers(1, &aabbIBO); glDeleteBuffers(1, &aabbVBO); @@ -1372,7 +918,7 @@ void DebugRenderPass::render(RenderContext* renderContext) glDisable(GL_BLEND); // Bind unlit solid shader - unlitSolidShader->bind(); + shader.activate(permutation); // Bind AABB geometry glBindVertexArray(aabbVAO); @@ -1393,39 +939,46 @@ void DebugRenderPass::render(RenderContext* renderContext) Matrix4 modelMatrix = glm::translate(translation) * glm::scale(scale); Matrix4 modelViewProjectionMatrix = camera.getViewProjection() * modelMatrix; - unlitSolidShader->setParameter(modelViewProjectionParam, modelViewProjectionMatrix); + modelViewProjectionMatrixParam.setValue(modelViewProjectionMatrix); + modelViewProjectionMatrixParam.upload(); glDrawElements(GL_LINES, aabbIndexCount, GL_UNSIGNED_INT, (void*)0); } } UIRenderPass::UIRenderPass() -{ - modelViewProjectionParam = parameterSet.addParameter("modelViewProjectionMatrix", ShaderParameter::Type::MATRIX_4, 1); - textureParam = parameterSet.addParameter("tex", ShaderParameter::Type::INT, 1); - texcoordOffsetParam = parameterSet.addParameter("texcoordOffset", ShaderParameter::Type::VECTOR_2, 1); - texcoordScaleParam = parameterSet.addParameter("texcoordScale", ShaderParameter::Type::VECTOR_2, 1); -} +{} bool UIRenderPass::load(const RenderContext* renderContext) { - shaderLoader.define("VERTEX_POSITION", EMERGENT_VERTEX_POSITION); - shaderLoader.define("VERTEX_TEXCOORD", EMERGENT_VERTEX_TEXCOORD); - shaderLoader.define("VERTEX_COLOR", EMERGENT_VERTEX_COLOR); - shaderLoader.define("GAMMA_CORRECT"); - shaderLoader.define("TEXTURE_COUNT", 1); - - texturedUIShader = shaderLoader.load("data/shaders/ui.glsl", ¶meterSet); + if (!shader.loadSource("data/shaders/ui.glsl")) + { + std::cerr << "UIRenderPass: Failed to load shader source." << std::endl; + return false; + } - shaderLoader.undefine(); - shaderLoader.define("VERTEX_POSITION", EMERGENT_VERTEX_POSITION); - shaderLoader.define("VERTEX_COLOR", EMERGENT_VERTEX_COLOR); - shaderLoader.define("GAMMA_CORRECT"); + // Set permutation values + untexturedPermutation = 0; + texturedPermutation = 1; - untexturedUIShader = shaderLoader.load("data/shaders/ui.glsl", ¶meterSet); + // Generate shader permutations + if (!shader.generatePermutation(untexturedPermutation) || !shader.generatePermutation(texturedPermutation)) + { + std::cerr << "UIRenderPass: failed to generate shader permutation." << std::endl; + return false; + } - if (!texturedUIShader || !untexturedUIShader) + // Connect shader variables + modelViewProjectionMatrixParam.connect(shader.getInput("modelViewProjectionMatrix")); + textureParam.connect(shader.getInput("tex")); + textureOffsetParam.connect(shader.getInput("texcoordOffset")); + textureScaleParam.connect(shader.getInput("texcoordScale")); + if (!modelViewProjectionMatrixParam.isConnected() || + !textureParam.isConnected() || + !textureOffsetParam.isConnected() || + !textureScaleParam.isConnected()) { + std::cerr << "UIRenderPass: one or more shader variables were not connected to shader inputs." << std::endl; return false; } @@ -1434,11 +987,11 @@ bool UIRenderPass::load(const RenderContext* renderContext) void UIRenderPass::unload() { - delete texturedUIShader; - delete untexturedUIShader; - - texturedUIShader = nullptr; - untexturedUIShader = nullptr; + modelViewProjectionMatrixParam.disconnect(); + textureParam.disconnect(); + textureOffsetParam.disconnect(); + textureScaleParam.disconnect(); + shader.deleteAllPermutations(); } void UIRenderPass::render(RenderContext* renderContext) @@ -1462,43 +1015,46 @@ void UIRenderPass::render(RenderContext* renderContext) glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glActiveTexture(GL_TEXTURE0); - - Shader* shader = nullptr; - // Render operations const std::list* operations = renderContext->queue->getOperations(); for (const RenderOperation& operation: *operations) { // Skip render operations with unsupported materials + /* if (operation.material->getMaterialFormatID() != static_cast(MaterialFormat::UI)) { continue; } - const UIMaterial* material = static_cast(operation.material); + */ + const UIMaterial* material = static_cast(operation.material); - if (material->texture != nullptr) + if (material->texture->getValue() != nullptr) { - shader = texturedUIShader; - shader->bind(); - shader->setParameter(textureParam, 0); - shader->setParameter(texcoordOffsetParam, Vector2(0.0f)); - shader->setParameter(texcoordScaleParam, Vector2(1.0f)); + shader.activate(texturedPermutation); - glBindTexture(GL_TEXTURE_2D, material->texture->getTextureID()); + textureParam.setValue(material->texture->getValue()); + textureOffsetParam.setValue(material->textureOffset->getValue()); + textureScaleParam.setValue(material->textureScale->getValue()); + + textureParam.upload(); + textureOffsetParam.upload(); + textureScaleParam.upload(); } else { - shader = untexturedUIShader; - shader->bind(); + shader.activate(untexturedPermutation); } - + const Matrix4& modelMatrix = operation.transform; Matrix4 modelViewProjectionMatrix = camera.getViewProjection() * modelMatrix; - // Pass matrix parameters - shader->setParameter(modelViewProjectionParam, modelViewProjectionMatrix); + // Upload matrix parameters + modelViewProjectionMatrixParam.setValue(modelViewProjectionMatrix); + modelViewProjectionMatrixParam.upload(); + + // Upload material parameters + //operation.material->upload(); // Draw geometry glBindVertexArray(operation.vao); @@ -1506,6 +1062,7 @@ void UIRenderPass::render(RenderContext* renderContext) } } +/* VignetteRenderPass::VignetteRenderPass(): shader(nullptr) { @@ -1589,23 +1146,36 @@ void VignetteRenderPass::render(RenderContext* renderContext) glDrawElementsBaseVertex(GL_TRIANGLES, operation.triangleCount * 3, GL_UNSIGNED_INT, (void*)0, operation.indexOffset); } } +*/ SkyboxRenderPass::SkyboxRenderPass(): - shader(nullptr), cubemap(nullptr) -{ - matrixParam = parameterSet.addParameter("matrix", ShaderParameter::Type::MATRIX_4, 1); - cubemapParam = parameterSet.addParameter("cubemap", ShaderParameter::Type::INT, 1); -} +{} bool SkyboxRenderPass::load(const RenderContext* renderContext) { - shaderLoader.undefine(); - shaderLoader.define("VERTEX_POSITION", EMERGENT_VERTEX_POSITION); + if (!shader.loadSource("data/shaders/skybox.glsl")) + { + std::cerr << "SkyboxRenderPass: Failed to load shader source." << std::endl; + return false; + } - shader = shaderLoader.load("data/shaders/skybox.glsl", ¶meterSet); - if (!shader) + // Set permutation values + permutation = 0; + + // Generate shader permutations + if (!shader.generatePermutation(permutation)) + { + std::cerr << "SkyboxRenderPass: failed to generate shader permutation." << std::endl; + return false; + } + + // Connect shader variables + matrixParam.connect(shader.getInput("matrix")); + cubemapParam.connect(shader.getInput("cubemap")); + if (!matrixParam.isConnected() || !cubemapParam.isConnected()) { + std::cerr << "SkyboxRenderPass: one or more shader variables were not connected to shader inputs." << std::endl; return false; } @@ -1644,8 +1214,9 @@ bool SkyboxRenderPass::load(const RenderContext* renderContext) void SkyboxRenderPass::unload() { - delete shader; - shader = nullptr; + matrixParam.disconnect(); + cubemapParam.disconnect(); + shader.deleteAllPermutations(); glDeleteBuffers(1, &quadIBO); glDeleteBuffers(1, &quadVBO); @@ -1669,22 +1240,20 @@ void SkyboxRenderPass::render(RenderContext* renderContext) //glCullFace(GL_BACK); // Bind shader - shader->bind(); + shader.activate(permutation); // Bind cubemap texture - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_CUBE_MAP, cubemap->getTextureID()); - - // Pass texture unit to shader - shader->setParameter(cubemapParam, 0); + cubemapParam.setValue(cubemap); + cubemapParam.upload(); // Calculate matrix const Camera& camera = *(renderContext->camera); Matrix4 modelView = Matrix4(Matrix3(camera.getView())); Matrix4 matrix = glm::inverse(modelView) * glm::inverse(camera.getProjection()); - // Pass matrix to shader - shader->setParameter(matrixParam, matrix); + // Upload matrix to shader + matrixParam.setValue(matrix); + matrixParam.upload(); // Render quad glBindVertexArray(quadVAO); diff --git a/src/render-passes.hpp b/src/render-passes.hpp index 5cd3b1d..50c935f 100644 --- a/src/render-passes.hpp +++ b/src/render-passes.hpp @@ -25,6 +25,7 @@ using namespace Emergent; #include "material-loader.hpp" #include "model-loader.hpp" +#include /** * Clears framebuffers @@ -62,19 +63,26 @@ public: virtual void unload(); virtual void render(RenderContext* renderContext); - inline void setTexture(GLuint textureID) { this->textureID = textureID; } - inline void setDirection(Vector2 direction) { this->direction = direction; } + inline void setGammaCorrect(bool gammaCorrect) { this->gammaCorrect = gammaCorrect; } + + /** + * Sets the texture to blur. + */ + inline void setTexture(const Texture2D* texture) { textureParam.setValue(texture); } + + /** + * Sets the direction of the blur. + */ + inline void setDirection(const Vector2& direction) { directionParam.setValue(direction); } private: - ShaderParameterSet parameterSet; - const ShaderParameter* textureParam; - const ShaderParameter* resolutionParam; - const ShaderParameter* directionParam; - ShaderLoader shaderLoader; - Shader* shader; + bool gammaCorrect; - GLuint textureID; - Vector2 direction; + Shader shader; + std::uint32_t permutation; + ShaderTexture2D textureParam; + ShaderVector2 resolutionParam; + ShaderVector2 directionParam; int quadVertexCount; int quadIndexCount; @@ -110,16 +118,13 @@ private: bool operator()(const RenderOperation& opA, const RenderOperation& opB) const; }; - ShaderParameterSet parameterSet; - const ShaderParameter* modelViewProjectionParam; - const ShaderParameter* matrixPaletteParam; - - ShaderLoader shaderLoader; + Shader shader; + std::uint32_t unskinnedPermutation; + std::uint32_t skinnedPermutation; + ShaderMatrix4 modelViewProjectionParam; + ShaderMatrix4* matrixPaletteParam; // data not used, just getConnectedInput() then pass pose matrix palette pointer directly - Shader* unskinnedShader; - Shader* skinnedShader; int maxBoneCount; - int shadowMapResolution; int croppedShadowMapResolution; Vector4* croppedShadowMapViewports; @@ -142,11 +147,11 @@ public: virtual void unload(); virtual void render(RenderContext* renderContext); - inline void setShadowMap(GLuint shadowMap) { this->shadowMap = shadowMap; } + inline void setShadowMap(const Texture2D* shadowMap) { this->shadowMap = shadowMap; } inline void setShadowCamera(const Camera* camera) { this->shadowCamera = camera; } inline void setShadowMapPass(const ShadowMapRenderPass* shadowMapPass) { this->shadowMapPass = shadowMapPass; } - inline void setDiffuseCubemap(const Texture* cubemap) { this->diffuseCubemap = cubemap; } - inline void setSpecularCubemap(const Texture* cubemap) { this->specularCubemap = cubemap; } + inline void setDiffuseCubemap(const TextureCube* cubemap) { this->diffuseCubemap = cubemap; } + inline void setSpecularCubemap(const TextureCube* cubemap) { this->specularCubemap = cubemap; } private: class RenderOpCompare @@ -155,53 +160,61 @@ private: // Sort render opations bool operator()(const RenderOperation& opA, const RenderOperation& opB) const; }; - - bool loadShader(const RenderOperation& operation); - ShaderParameterSet parameterSet; - const ShaderParameter* matrixPaletteParam; - const ShaderParameter* modelParam; - const ShaderParameter* modelViewParam; - const ShaderParameter* modelViewProjectionParam; - const ShaderParameter* normalModelViewParam; - const ShaderParameter* normalModelParam; - const ShaderParameter* lightViewProjectionsParam; - const ShaderParameter* splitDistancesParam; - const ShaderParameter* shadowMapParam; - const ShaderParameter* cameraPositionParam; - const ShaderParameter* directionalLightCountParam; - const ShaderParameter* directionalLightColorsParam; - const ShaderParameter* directionalLightDirectionsParam; - - const ShaderParameter* spotlightCountParam; - const ShaderParameter* spotlightColorsParam; - const ShaderParameter* spotlightPositionsParam; - const ShaderParameter* spotlightAttenuationsParam; - const ShaderParameter* spotlightDirectionsParam; - const ShaderParameter* spotlightCutoffsParam; - const ShaderParameter* spotlightExponentsParam; - - const ShaderParameter* albedoOpacityMapParam; - const ShaderParameter* metalnessRoughnessMapParam; - const ShaderParameter* normalOcclusionMapParam; - const ShaderParameter* diffuseCubemapParam; - const ShaderParameter* specularCubemapParam; - - Shader* unskinnedShader; - Shader* skinnedShader; + struct ParameterSet + { + ShaderMatrix4* matrixPalette; + ShaderMatrix4 modelMatrix; + ShaderMatrix4 modelViewMatrix; + ShaderMatrix4 modelViewProjectionMatrix; + ShaderMatrix3 normalModelViewMatrix; + ShaderMatrix3 normalModelMatrix; + ShaderMatrix4* lightViewProjectionMatrices; + ShaderVector4 splitDistances; + ShaderTexture2D shadowMap; + ShaderVector3 cameraPosition; + + ShaderTextureCube diffuseCubemap; + ShaderTextureCube specularCubemap; + + ShaderInt directionalLightCount; + ShaderVector3* directionalLightColors; + ShaderVector3* directionalLightDirections; + + ShaderInt spotlightCount; + ShaderVector3 spotlightColors; + ShaderVector3 spotlightPositions; + ShaderVector3 spotlightAttenuations; + ShaderVector3 spotlightDirections; + ShaderFloat spotlightCutoffs; + ShaderFloat spotlightExponents; + + ShaderTexture2D albedoOpacityMap; + ShaderTexture2D metalnessRoughnessMap; + ShaderTexture2D normalOcclusionMap; + + // Material shader parameters (uploaded by material directly) + //ShaderTexture2D albedoOpacityMap; + //ShaderTexture2D metalnessRoughnessMap; + //ShaderTexture2D normalOcclusionMap; + }; + + //std::map parameterSets; + + Shader shader; + ParameterSet parameters; + std::uint32_t unskinnedPermutation; + std::uint32_t skinnedPermutation; int maxBoneCount; int maxDirectionalLightCount; int maxSpotlightCount; - ShaderLoader shaderLoader; - std::map shaderCache; - //Shader* lightingShader; + Matrix4 biasMatrix; - GLuint shadowMap; - Texture* treeShadow; - const Texture* diffuseCubemap; - const Texture* specularCubemap; + const Texture2D* shadowMap; + const TextureCube* diffuseCubemap; + const TextureCube* specularCubemap; const Camera* shadowCamera; float time; const ShadowMapRenderPass* shadowMapPass; @@ -224,11 +237,9 @@ public: //void setDrawLights(bool enabled); private: - ShaderParameterSet parameterSet; - const ShaderParameter* modelViewProjectionParam; - - ShaderLoader shaderLoader; - Shader* unlitSolidShader; + Shader shader; + std::uint32_t permutation; + ShaderMatrix4 modelViewProjectionMatrixParam; int aabbVertexCount; int aabbIndexCount; @@ -249,20 +260,20 @@ public: virtual void render(RenderContext* renderContext); private: - ShaderParameterSet parameterSet; - const ShaderParameter* modelViewProjectionParam; - const ShaderParameter* textureParam; - const ShaderParameter* texcoordOffsetParam; - const ShaderParameter* texcoordScaleParam; - - ShaderLoader shaderLoader; - Shader* texturedUIShader; - Shader* untexturedUIShader; + Shader shader; + std::uint32_t texturedPermutation; + std::uint32_t untexturedPermutation; + + ShaderMatrix4 modelViewProjectionMatrixParam; + ShaderTexture2D textureParam; + ShaderVector2 textureOffsetParam; + ShaderVector2 textureScaleParam; }; /** * Renders a vignette */ +/* class VignetteRenderPass: public RenderPass { public: @@ -280,6 +291,7 @@ private: Shader* shader; GLuint bayerTextureID; }; +*/ /** * Renders a skybox @@ -289,19 +301,17 @@ class SkyboxRenderPass: public RenderPass public: SkyboxRenderPass(); - inline void setCubemap(Texture* cubemap) { this->cubemap = cubemap; } + inline void setCubemap(TextureCube* cubemap) { this->cubemap = cubemap; } virtual bool load(const RenderContext* renderContext); virtual void unload(); virtual void render(RenderContext* renderContext); private: - ShaderParameterSet parameterSet; - const ShaderParameter* matrixParam; - const ShaderParameter* cubemapParam; - - ShaderLoader shaderLoader; - Shader* shader; - Texture* cubemap; + Shader shader; + std::uint32_t permutation; + ShaderMatrix4 matrixParam; + ShaderTextureCube cubemapParam; + TextureCube* cubemap; int quadVertexCount; int quadIndexCount; @@ -310,6 +320,4 @@ private: GLuint quadIBO; }; - - #endif // RENDER_PASSES_HPP diff --git a/src/states/game-state.cpp b/src/states/game-state.cpp index 0c58888..0e7af28 100644 --- a/src/states/game-state.cpp +++ b/src/states/game-state.cpp @@ -410,6 +410,7 @@ void GameState::execute() glBindTexture(GL_TEXTURE_2D, application->pheromoneTextureID); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, application->pheromoneTexture.getWidth(), application->pheromoneTexture.getHeight(), GL_BGRA, GL_UNSIGNED_BYTE, nullptr); glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + //glGenerateMipmap(GL_TEXTURE_2D); } } } diff --git a/src/states/title-state.cpp b/src/states/title-state.cpp index f6feee3..76aaa7d 100644 --- a/src/states/title-state.cpp +++ b/src/states/title-state.cpp @@ -33,9 +33,6 @@ TitleState::~TitleState() void TitleState::enter() { - application->backgroundLayer->addObject(&application->bgCamera); - application->backgroundLayer->addObject(&application->bgBatch); - application->inputManager->addWindowObserver(this); windowResized(application->resolution.x, application->resolution.y); @@ -163,16 +160,6 @@ void TitleState::execute() { application->close(EXIT_SUCCESS); } - - - // Set selector icon position - /* - float lineHeight = application->menuFont->getMetrics().getHeight(); - const UIContainer* container = application->menuContainers[application->currentMenuIndex]; - application->menuSelectorLabel->setTranslation( - Vector2(container->getPosition().x - application->menuSelectorLabel->getDimensions().x * 1.5f, - container->getPosition().y + lineHeight * 0.5f - application->menuSelectorLabel->getDimensions().y * 0.5f + lineHeight * application->selectedMenuItemIndex)); - */ } void TitleState::exit() @@ -185,10 +172,6 @@ void TitleState::exit() application->copyrightLabel->setVisible(false); application->anyKeyLabel->setVisible(false); application->darkenImage->setVisible(false); - - // Remove clear scene - application->backgroundLayer->removeObject(&application->bgCamera); - application->backgroundLayer->removeObject(&application->bgBatch); } void TitleState::windowClosed() diff --git a/src/ui/pie-menu.cpp b/src/ui/pie-menu.cpp index 5c6551e..019e336 100644 --- a/src/ui/pie-menu.cpp +++ b/src/ui/pie-menu.cpp @@ -70,7 +70,7 @@ void PieMenu::setScale(float scale) } } -void PieMenu::addOption(Texture* backgroundTexture, Texture* iconTexture, std::function selectedCallback, std::function deselectedCallback) +void PieMenu::addOption(Texture2D* backgroundTexture, Texture2D* iconTexture, std::function selectedCallback, std::function deselectedCallback) { // Allocate new option UIImage* option = new UIImage(); diff --git a/src/ui/pie-menu.hpp b/src/ui/pie-menu.hpp index 4aeacf0..da11eba 100644 --- a/src/ui/pie-menu.hpp +++ b/src/ui/pie-menu.hpp @@ -16,7 +16,7 @@ public: void resize(); - void addOption(Texture* backgroundTexture, Texture* iconTexture, std::function selectedCallback, std::function deselectedCallback); + void addOption(Texture2D* backgroundTexture, Texture2D* iconTexture, std::function selectedCallback, std::function deselectedCallback); void select(std::size_t index); void deselect(std::size_t index); diff --git a/src/ui/toolbar.cpp b/src/ui/toolbar.cpp index 747b426..aabe1fd 100644 --- a/src/ui/toolbar.cpp +++ b/src/ui/toolbar.cpp @@ -14,30 +14,30 @@ Toolbar::Toolbar(): toolbarContainer.addChild(&toolbarMiddleImage); } -void Toolbar::setToolbarTopTexture(Texture* texture) +void Toolbar::setToolbarTopTexture(Texture2D* texture) { toolbarTopTexture = texture; toolbarTopImage.setTexture(toolbarTopTexture); } -void Toolbar::setToolbarBottomTexture(Texture* texture) +void Toolbar::setToolbarBottomTexture(Texture2D* texture) { toolbarBottomTexture = texture; toolbarBottomImage.setTexture(toolbarBottomTexture); } -void Toolbar::setToolbarMiddleTexture(Texture* texture) +void Toolbar::setToolbarMiddleTexture(Texture2D* texture) { toolbarMiddleTexture = texture; toolbarMiddleImage.setTexture(toolbarMiddleTexture); } -void Toolbar::setButtonRaisedTexture(Texture* texture) +void Toolbar::setButtonRaisedTexture(Texture2D* texture) { buttonRaisedTexture = texture; } -void Toolbar::setButtonDepressedTexture(Texture* texture) +void Toolbar::setButtonDepressedTexture(Texture2D* texture) { buttonDepressedTexture = texture; } @@ -81,7 +81,7 @@ void Toolbar::resize() } } -void Toolbar::addButton(Texture* iconTexture, std::function pressCallback, std::function releaseCallback) +void Toolbar::addButton(Texture2D* iconTexture, std::function pressCallback, std::function releaseCallback) { if (depressedButtonIndex == buttons.size()) { diff --git a/src/ui/toolbar.hpp b/src/ui/toolbar.hpp index 53caf1b..4985a41 100644 --- a/src/ui/toolbar.hpp +++ b/src/ui/toolbar.hpp @@ -13,15 +13,15 @@ class Toolbar public: Toolbar(); - void setToolbarTopTexture(Texture* texture); - void setToolbarBottomTexture(Texture* texture); - void setToolbarMiddleTexture(Texture* texture); - void setButtonRaisedTexture(Texture* texture); - void setButtonDepressedTexture(Texture* texture); + void setToolbarTopTexture(Texture2D* texture); + void setToolbarBottomTexture(Texture2D* texture); + void setToolbarMiddleTexture(Texture2D* texture); + void setButtonRaisedTexture(Texture2D* texture); + void setButtonDepressedTexture(Texture2D* texture); void resize(); - void addButton(Texture* iconTexture, std::function pressCallback, std::function releaseCallback); + void addButton(Texture2D* iconTexture, std::function pressCallback, std::function releaseCallback); void pressButton(std::size_t index); void releaseButton(std::size_t index); @@ -30,11 +30,11 @@ public: UIContainer* getContainer(); private: - Texture* toolbarTopTexture; - Texture* toolbarBottomTexture; - Texture* toolbarMiddleTexture; - Texture* buttonRaisedTexture; - Texture* buttonDepressedTexture; + Texture2D* toolbarTopTexture; + Texture2D* toolbarBottomTexture; + Texture2D* toolbarMiddleTexture; + Texture2D* buttonRaisedTexture; + Texture2D* buttonDepressedTexture; UIContainer toolbarContainer; UIImage toolbarTopImage; diff --git a/src/ui/ui.cpp b/src/ui/ui.cpp index 5c3dd48..213b733 100644 --- a/src/ui/ui.cpp +++ b/src/ui/ui.cpp @@ -26,6 +26,17 @@ void menuPrint(Application* application, const std::string& string) std::cout << string << std::endl; } +UIMaterial::UIMaterial() +{ + texture = addVariable("texture"); + textureOffset = addVariable("offset"); + textureScale = addVariable("scale"); + + texture->setValue(nullptr); + textureOffset->setValue(Vector2(0.0f)); + textureScale->setValue(Vector2(1.0f)); +} + UIElement::UIElement(): parent(nullptr), anchor(Anchor::TOP_LEFT), @@ -218,7 +229,7 @@ UILabel::~UILabel() void UILabel::setFont(Font* font) { this->font = font; - material.texture = font->getTexture(); + material.texture->setValue(font->getTexture()); calculateDimensions(); } @@ -267,7 +278,7 @@ void UIBatcher::batch(BillboardBatch* result, const UIElement* ui) return false; } - return (a->getMaterial()->texture < b->getMaterial()->texture); + return (a->getMaterial()->texture->getValue() < b->getMaterial()->texture->getValue()); }); // Clear previous ranges @@ -315,7 +326,7 @@ BillboardBatch::Range* UIBatcher::getRange(BillboardBatch* result, const UIEleme const UIMaterial* material = static_cast(range->material); - if (material->texture != element->getMaterial()->texture) + if (material->texture->getValue() != element->getMaterial()->texture->getValue()) { // Create new range for the element range = result->addRange(); diff --git a/src/ui/ui.hpp b/src/ui/ui.hpp index e1e7bf6..5ee9751 100644 --- a/src/ui/ui.hpp +++ b/src/ui/ui.hpp @@ -21,7 +21,6 @@ #define UI_HPP #include "../input.hpp" -#include "../materials.hpp" #include #include @@ -37,6 +36,16 @@ namespace Anchor static const Vector2& CENTER = Vector2(0.5f, 0.5f); } +class UIMaterial: public Material +{ +public: + UIMaterial(); + + ShaderTexture2D* texture; + ShaderVector2* textureOffset; + ShaderVector2* textureScale; +}; + class UIElement: public MouseMotionObserver, public MouseButtonObserver { public: @@ -391,9 +400,9 @@ public: virtual ~UIImage(); virtual UIElement::Type getElementType() const; - virtual const Texture* getTexture() const; + virtual const Texture2D* getTexture() const; - void setTexture(Texture* texture); + void setTexture(Texture2D* texture); void setTextureBounds(const Rect& bounds); const Rect& getTextureBounds() const; @@ -407,14 +416,14 @@ inline UIElement::Type UIImage::getElementType() const return UIElement::Type::IMAGE; } -inline const Texture* UIImage::getTexture() const +inline const Texture2D* UIImage::getTexture() const { - return material.texture; + return material.texture->getValue(); } -inline void UIImage::setTexture(Texture* texture) +inline void UIImage::setTexture(Texture2D* texture) { - material.texture = texture; + material.texture->setValue(texture); } inline void UIImage::setTextureBounds(const Rect& bounds)