diff --git a/rwengine/src/render/DebugDraw.hpp b/rwengine/src/render/DebugDraw.hpp index 3c2ad88e..1c2d6882 100644 --- a/rwengine/src/render/DebugDraw.hpp +++ b/rwengine/src/render/DebugDraw.hpp @@ -33,6 +33,7 @@ protected: GeometryBuffer *lineBuff; DrawBuffer *dbuff; + //Ownership is handled by worldProg in renderer Renderer::ShaderProgram *shaderProgram; GLuint texture; diff --git a/rwengine/src/render/GameRenderer.cpp b/rwengine/src/render/GameRenderer.cpp index 8cc46776..33eaa15c 100644 --- a/rwengine/src/render/GameRenderer.cpp +++ b/rwengine/src/render/GameRenderer.cpp @@ -81,22 +81,22 @@ GameRenderer::GameRenderer(Logger* log, GameData* _data) renderer->createShader(GameShaders::WorldObject::VertexShader, GameShaders::WorldObject::FragmentShader); - renderer->setUniformTexture(worldProg, "texture", 0); - renderer->setProgramBlockBinding(worldProg, "SceneData", 1); - renderer->setProgramBlockBinding(worldProg, "ObjectData", 2); + renderer->setUniformTexture(worldProg.get(), "texture", 0); + renderer->setProgramBlockBinding(worldProg.get(), "SceneData", 1); + renderer->setProgramBlockBinding(worldProg.get(), "ObjectData", 2); particleProg = renderer->createShader(GameShaders::WorldObject::VertexShader, GameShaders::Particle::FragmentShader); - renderer->setUniformTexture(particleProg, "texture", 0); - renderer->setProgramBlockBinding(particleProg, "SceneData", 1); - renderer->setProgramBlockBinding(particleProg, "ObjectData", 2); + renderer->setUniformTexture(particleProg.get(), "texture", 0); + renderer->setProgramBlockBinding(particleProg.get(), "SceneData", 1); + renderer->setProgramBlockBinding(particleProg.get(), "ObjectData", 2); skyProg = renderer->createShader(GameShaders::Sky::VertexShader, GameShaders::Sky::FragmentShader); - renderer->setProgramBlockBinding(skyProg, "SceneData", 1); + renderer->setProgramBlockBinding(skyProg.get(), "SceneData", 1); postProg = renderer->createShader(GameShaders::DefaultPostProcess::VertexShader, @@ -212,6 +212,7 @@ GameRenderer::GameRenderer(Logger* log, GameData* _data) GameRenderer::~GameRenderer() { glDeleteFramebuffers(1, &framebufferName); + glDeleteProgram(ssRectProgram); } float mix(uint8_t a, uint8_t b, float num) { @@ -283,7 +284,7 @@ void GameRenderer::renderWorld(GameWorld* world, const ViewCamera& camera, culled = 0; - renderer->useProgram(worldProg); + renderer->useProgram(worldProg.get()); //=============================================================== // Render List Construction @@ -384,9 +385,9 @@ void GameRenderer::renderWorld(GameWorld* world, const ViewCamera& camera, dp.start = 0; dp.count = skydomeSegments * skydomeRows * 6; - renderer->useProgram(skyProg); - renderer->setUniform(skyProg, "TopColor", glm::vec4(skyTop, 1.f)); - renderer->setUniform(skyProg, "BottomColor", glm::vec4(skyBottom, 1.f)); + renderer->useProgram(skyProg.get()); + renderer->setUniform(skyProg.get(), "TopColor", glm::vec4(skyTop, 1.f)); + renderer->setUniform(skyProg.get(), "BottomColor", glm::vec4(skyBottom, 1.f)); renderer->draw(glm::mat4(), &skyDbuff, dp); @@ -462,7 +463,7 @@ void GameRenderer::renderPostProcess() { glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - renderer->useProgram(postProg); + renderer->useProgram(postProg.get()); Renderer::DrawParameters wdp; wdp.start = 0; @@ -473,7 +474,7 @@ void GameRenderer::renderPostProcess() { } void GameRenderer::renderEffects(GameWorld* world) { - renderer->useProgram(particleProg); + renderer->useProgram(particleProg.get()); auto cpos = _camera.position; auto cfwd = glm::normalize(glm::inverse(_camera.rotation) * @@ -614,8 +615,8 @@ void GameRenderer::renderPaths() { static std::vector carlines; static std::vector pedlines; - GLint posAttrib = glGetAttribLocation(worldProgram, "position"); - GLint uniModel = glGetUniformLocation(worldProgram, "model"); + GLint posAttrib = glGetAttribLocation(worldProg.get(), "position"); + GLint uniModel = glGetUniformLocation(worldProg.get(), "model"); glBindVertexArray( vao ); diff --git a/rwengine/src/render/GameRenderer.hpp b/rwengine/src/render/GameRenderer.hpp index 661a39e5..7ce43ace 100644 --- a/rwengine/src/render/GameRenderer.hpp +++ b/rwengine/src/render/GameRenderer.hpp @@ -69,7 +69,7 @@ class GameRenderer { GLuint framebufferName; GLuint fbTextures[2]; GLuint fbRenderBuffers[1]; - Renderer::ShaderProgram* postProg; + std::unique_ptr postProg; /// Texture used to replace textures missing from the data GLuint m_missingTexture; @@ -79,9 +79,9 @@ public: ~GameRenderer(); /** @todo Clean up all these shader program and location variables */ - Renderer::ShaderProgram* worldProg; - Renderer::ShaderProgram* skyProg; - Renderer::ShaderProgram* particleProg; + std::unique_ptr worldProg; + std::unique_ptr skyProg; + std::unique_ptr particleProg; GLuint ssRectProgram; GLint ssRectTexture, ssRectColour, ssRectSize, ssRectOffset; diff --git a/rwengine/src/render/MapRenderer.cpp b/rwengine/src/render/MapRenderer.cpp index 51c01ad3..42fa4f7d 100644 --- a/rwengine/src/render/MapRenderer.cpp +++ b/rwengine/src/render/MapRenderer.cpp @@ -57,14 +57,14 @@ MapRenderer::MapRenderer(std::shared_ptr renderer, GameData* _data) rectProg = renderer->createShader(MapVertexShader, MapFragmentShader); - renderer->setUniform(rectProg, "colour", glm::vec4(1.f)); + renderer->setUniform(rectProg.get(), "colour", glm::vec4(1.f)); } #define GAME_MAP_SIZE 4000 void MapRenderer::draw(GameWorld* world, const MapInfo& mi) { renderer->pushDebugGroup("Map"); - renderer->useProgram(rectProg); + renderer->useProgram(rectProg.get()); Renderer::DrawParameters dp { }; dp.start = 0; @@ -80,15 +80,15 @@ void MapRenderer::draw(GameWorld* world, const MapInfo& mi) { auto proj = renderer->get2DProjection(); glm::mat4 view, model; - renderer->setUniform(rectProg, "proj", proj); - renderer->setUniform(rectProg, "model", glm::mat4()); - renderer->setUniform(rectProg, "colour", glm::vec4(0.f, 0.f, 0.f, 1.f)); + renderer->setUniform(rectProg.get(), "proj", proj); + renderer->setUniform(rectProg.get(), "model", glm::mat4()); + renderer->setUniform(rectProg.get(), "colour", glm::vec4(0.f, 0.f, 0.f, 1.f)); view = glm::translate(view, glm::vec3(mi.screenPosition, 0.f)); if (mi.clipToSize) { glm::mat4 circleView = glm::scale(view, glm::vec3(mi.screenSize)); - renderer->setUniform(rectProg, "view", circleView); + renderer->setUniform(rectProg.get(), "view", circleView); dp.count = 182; glEnable(GL_STENCIL_TEST); glStencilFunc(GL_ALWAYS, 1, 0xFF); @@ -104,7 +104,7 @@ void MapRenderer::draw(GameWorld* world, const MapInfo& mi) { view = glm::rotate(view, mi.rotation, glm::vec3(0.f, 0.f, 1.f)); view = glm::translate( view, glm::vec3(glm::vec2(-1.f, 1.f) * mi.worldCenter, 0.f)); - renderer->setUniform(rectProg, "view", view); + renderer->setUniform(rectProg.get(), "view", view); // radar00 = -x, +y // incrementing in X, then Y @@ -129,13 +129,13 @@ void MapRenderer::draw(GameWorld* world, const MapInfo& mi) { tilemodel = glm::translate(tilemodel, glm::vec3(tc, 0.f)); tilemodel = glm::scale(tilemodel, glm::vec3(tileSize, 1.f)); - renderer->setUniform(rectProg, "model", tilemodel); + renderer->setUniform(rectProg.get(), "model", tilemodel); renderer->drawArrays(glm::mat4(), &rect, dp); } // From here on out we will work in screenspace - renderer->setUniform(rectProg, "view", glm::mat4()); + renderer->setUniform(rectProg.get(), "view", glm::mat4()); if (mi.clipToSize) { glDisable(GL_STENCIL_TEST); @@ -148,7 +148,7 @@ void MapRenderer::draw(GameWorld* world, const MapInfo& mi) { glm::mat4 model; model = glm::translate(model, glm::vec3(mi.screenPosition, 0.0f)); model = glm::scale(model, glm::vec3(mi.screenSize * 1.07f)); - renderer->setUniform(rectProg, "model", model); + renderer->setUniform(rectProg.get(), "model", model); renderer->drawArrays(glm::mat4(), &rect, dp); glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO); @@ -251,14 +251,14 @@ void MapRenderer::prepareBlip(const glm::vec2& coord, const glm::mat4& view, model = glm::translate(model, viewPos); model = glm::scale(model, glm::vec3(size)); model = glm::rotate(model, heading, glm::vec3(0.f, 0.f, 1.f)); - renderer->setUniform(rectProg, "model", model); + renderer->setUniform(rectProg.get(), "model", model); GLuint tex = 0; if (!texture.empty()) { auto sprite = data->findSlotTexture("hud", texture); tex = sprite->getName(); } - renderer->setUniform(rectProg, "colour", colour); + renderer->setUniform(rectProg.get(), "colour", colour); glBindTexture(GL_TEXTURE_2D, tex); @@ -277,6 +277,6 @@ void MapRenderer::drawBlip(const glm::vec2& coord, const glm::mat4& view, const MapInfo& mi, glm::vec4 colour, float size) { drawBlip(coord, view, mi, "", colour, size); // Draw outline - renderer->setUniform(rectProg, "colour", glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)); + renderer->setUniform(rectProg.get(), "colour", glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)); glDrawArrays(GL_LINE_LOOP, 0, 4); } diff --git a/rwengine/src/render/MapRenderer.hpp b/rwengine/src/render/MapRenderer.hpp index bba96d8e..7454668e 100644 --- a/rwengine/src/render/MapRenderer.hpp +++ b/rwengine/src/render/MapRenderer.hpp @@ -40,7 +40,7 @@ private: GeometryBuffer circleGeom; DrawBuffer circle; - Renderer::ShaderProgram* rectProg; + std::unique_ptr rectProg; void prepareBlip(const glm::vec2& coord, const glm::mat4& view, const MapInfo& mi, const std::string& texture, diff --git a/rwengine/src/render/OpenGLRenderer.cpp b/rwengine/src/render/OpenGLRenderer.cpp index f9bd9725..bb81a254 100644 --- a/rwengine/src/render/OpenGLRenderer.cpp +++ b/rwengine/src/render/OpenGLRenderer.cpp @@ -51,11 +51,19 @@ GLuint compileShader(GLenum type, const char* source) { GLuint compileProgram(const char* vertex, const char* fragment) { GLuint vertexShader = compileShader(GL_VERTEX_SHADER, vertex); GLuint fragmentShader = compileShader(GL_FRAGMENT_SHADER, fragment); + GLuint prog = glCreateProgram(); + glAttachShader(prog, vertexShader); glAttachShader(prog, fragmentShader); glLinkProgram(prog); + glDetachShader(prog, vertexShader); + glDetachShader(prog, fragmentShader); + + glDeleteShader(vertexShader); + glDeleteShader(fragmentShader); + GLint status; glGetProgramiv(prog, GL_LINK_STATUS, &status); @@ -79,9 +87,6 @@ GLuint compileProgram(const char* vertex, const char* fragment) { exit(1); } - glDeleteShader(vertexShader); - glDeleteShader(fragmentShader); - return prog; } @@ -177,9 +182,9 @@ std::string OpenGLRenderer::getIDString() const { return ss.str(); } -Renderer::ShaderProgram* OpenGLRenderer::createShader(const std::string& vert, +std::unique_ptr OpenGLRenderer::createShader(const std::string& vert, const std::string& frag) { - return new OpenGLShaderProgram(compileProgram(vert.c_str(), frag.c_str())); + return std::make_unique(compileProgram(vert.c_str(), frag.c_str())); } void OpenGLRenderer::setProgramBlockBinding(Renderer::ShaderProgram* p, diff --git a/rwengine/src/render/OpenGLRenderer.hpp b/rwengine/src/render/OpenGLRenderer.hpp index 508d7712..4f3b28ba 100644 --- a/rwengine/src/render/OpenGLRenderer.hpp +++ b/rwengine/src/render/OpenGLRenderer.hpp @@ -136,7 +136,7 @@ public: virtual std::string getIDString() const = 0; - virtual ShaderProgram* createShader(const std::string& vert, + virtual std::unique_ptr createShader(const std::string& vert, const std::string& frag) = 0; virtual void useProgram(ShaderProgram* p) = 0; @@ -241,6 +241,9 @@ public: public: OpenGLShaderProgram(GLuint p) : program(p) { } + ~OpenGLShaderProgram() { + glDeleteProgram(program); + } GLuint getName() const { return program; @@ -263,7 +266,7 @@ public: std::string getIDString() const override; - ShaderProgram* createShader(const std::string& vert, + std::unique_ptr createShader(const std::string& vert, const std::string& frag) override; void setProgramBlockBinding(ShaderProgram* p, const std::string& name, GLint point) override; diff --git a/rwengine/src/render/TextRenderer.cpp b/rwengine/src/render/TextRenderer.cpp index b510e465..d2231a40 100644 --- a/rwengine/src/render/TextRenderer.cpp +++ b/rwengine/src/render/TextRenderer.cpp @@ -139,7 +139,7 @@ void TextRenderer::setFontTexture(int index, const std::string& texture) { void TextRenderer::renderText(const TextRenderer::TextInfo& ti, bool forceColour) { renderer->getRenderer()->pushDebugGroup("Text"); - renderer->getRenderer()->useProgram(textShader); + renderer->getRenderer()->useProgram(textShader.get()); glm::vec2 coord(0.f, 0.f); glm::vec2 alignment = ti.screenPosition; @@ -281,9 +281,9 @@ void TextRenderer::renderText(const TextRenderer::TextInfo& ti, } renderer->getRenderer()->setUniform( - textShader, "proj", renderer->getRenderer()->get2DProjection()); - renderer->getRenderer()->setUniformTexture(textShader, "fontTexture", 0); - renderer->getRenderer()->setUniform(textShader, "alignment", alignment); + textShader.get(), "proj", renderer->getRenderer()->get2DProjection()); + renderer->getRenderer()->setUniformTexture(textShader.get(), "fontTexture", 0); + renderer->getRenderer()->setUniform(textShader.get(), "alignment", alignment); gb.uploadVertices(geo); db.addGeometry(&gb); diff --git a/rwengine/src/render/TextRenderer.hpp b/rwengine/src/render/TextRenderer.hpp index 4abb1f73..9d2b757b 100644 --- a/rwengine/src/render/TextRenderer.hpp +++ b/rwengine/src/render/TextRenderer.hpp @@ -60,7 +60,7 @@ private: GlyphInfo glyphData[GAME_GLYPHS]; GameRenderer* renderer; - Renderer::ShaderProgram* textShader; + std::unique_ptr textShader; GeometryBuffer gb; DrawBuffer db; diff --git a/rwengine/src/render/WaterRenderer.cpp b/rwengine/src/render/WaterRenderer.cpp index 468cb31e..e3ac7582 100644 --- a/rwengine/src/render/WaterRenderer.cpp +++ b/rwengine/src/render/WaterRenderer.cpp @@ -15,10 +15,10 @@ WaterRenderer::WaterRenderer(GameRenderer* renderer) : waterProg(nullptr) { maskProg = renderer->getRenderer()->createShader( GameShaders::Mask3D::VertexShader, GameShaders::Mask3D::FragmentShader); - renderer->getRenderer()->setProgramBlockBinding(waterProg, "SceneData", 1); - renderer->getRenderer()->setProgramBlockBinding(maskProg, "SceneData", 1); + renderer->getRenderer()->setProgramBlockBinding(waterProg.get(), "SceneData", 1); + renderer->getRenderer()->setProgramBlockBinding(maskProg.get(), "SceneData", 1); - renderer->getRenderer()->setUniformTexture(waterProg, "data", 1); + renderer->getRenderer()->setUniformTexture(waterProg.get(), "data", 1); // Generate grid mesh int gridres = 60; @@ -121,7 +121,7 @@ void WaterRenderer::render(GameRenderer* renderer, GameWorld* world) { glDrawBuffers(1, buffers); glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT); - r->useProgram(maskProg); + r->useProgram(maskProg.get()); r->drawArrays(m, &maskDraw, wdp); @@ -129,17 +129,17 @@ void WaterRenderer::render(GameRenderer* renderer, GameWorld* world) { glStencilMask(0x00); glEnable(GL_DEPTH_TEST); - r->useProgram(waterProg); + r->useProgram(waterProg.get()); buffers[0] = GL_COLOR_ATTACHMENT0; glDrawBuffers(1, buffers); - r->setUniform(waterProg, "time", world->getGameTime()); - r->setUniform(waterProg, "waveParams", + r->setUniform(waterProg.get(), "time", world->getGameTime()); + r->setUniform(waterProg.get(), "waveParams", glm::vec2(WATER_SCALE, WATER_HEIGHT)); auto ivp = glm::inverse(r->getSceneData().projection * r->getSceneData().view); - r->setUniform(waterProg, "inverseVP", ivp); + r->setUniform(waterProg.get(), "inverseVP", ivp); wdp.count = gridGeom.getCount(); wdp.textures = {waterTex->getName(), dataTexture}; diff --git a/rwengine/src/render/WaterRenderer.hpp b/rwengine/src/render/WaterRenderer.hpp index 7f51c515..0b8ecb75 100644 --- a/rwengine/src/render/WaterRenderer.hpp +++ b/rwengine/src/render/WaterRenderer.hpp @@ -33,8 +33,8 @@ public: void render(GameRenderer* renderer, GameWorld* world); private: - Renderer::ShaderProgram* waterProg; - Renderer::ShaderProgram* maskProg; + std::unique_ptr waterProg; + std::unique_ptr maskProg; DrawBuffer maskDraw; GeometryBuffer maskGeom; diff --git a/rwgame/RWGame.cpp b/rwgame/RWGame.cpp index 1d86b03c..73cb05fb 100644 --- a/rwgame/RWGame.cpp +++ b/rwgame/RWGame.cpp @@ -68,7 +68,7 @@ RWGame::RWGame(Logger& log, int argc, char* argv[]) debug.setDebugMode(btIDebugDraw::DBG_DrawWireframe | btIDebugDraw::DBG_DrawConstraints | btIDebugDraw::DBG_DrawConstraintLimits); - debug.setShaderProgram(renderer.worldProg); + debug.setShaderProgram(renderer.worldProg.get()); data.loadDynamicObjects(config.getGameDataPath() + "/data/object.dat"); diff --git a/rwviewer/ViewerWidget.cpp b/rwviewer/ViewerWidget.cpp index 02d3e614..f4f26f6b 100644 --- a/rwviewer/ViewerWidget.cpp +++ b/rwviewer/ViewerWidget.cpp @@ -92,7 +92,7 @@ void ViewerWidget::paintGL() { glm::mat4 m(1.f); - r.getRenderer()->useProgram(r.worldProg); + r.getRenderer()->useProgram(r.worldProg.get()); ViewCamera vc;