mirror of
https://github.com/rwengine/openrw.git
synced 2024-11-25 11:52:40 +01:00
Improving handling game shaders (#302)
* move delete to earlier stage * lines for better readability * Added detach shader * Addition forgotten glDeleteProgram https://github.com/rwengine/openrw/search?utf8=%E2%9C%93&q=glDeleteProgram&type= In project there's no necessary clearing call of glDeleteProgram. * Removing/Closing shader programs Each shader program should be taken care by glDeleteProgram. To make it works/usefull, each shader's raw ptr will convertet to unique_ptr in next commit. * Converting ShaderProgram's ptr to unique Actually deleting isn't handled, so this commit removes memory leak.
This commit is contained in:
parent
c54cfa0ae8
commit
b9d306ae70
@ -33,6 +33,7 @@ protected:
|
||||
GeometryBuffer *lineBuff;
|
||||
DrawBuffer *dbuff;
|
||||
|
||||
//Ownership is handled by worldProg in renderer
|
||||
Renderer::ShaderProgram *shaderProgram;
|
||||
|
||||
GLuint texture;
|
||||
|
@ -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<glm::vec3> carlines;
|
||||
static std::vector<glm::vec3> 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 );
|
||||
|
||||
|
@ -69,7 +69,7 @@ class GameRenderer {
|
||||
GLuint framebufferName;
|
||||
GLuint fbTextures[2];
|
||||
GLuint fbRenderBuffers[1];
|
||||
Renderer::ShaderProgram* postProg;
|
||||
std::unique_ptr<Renderer::ShaderProgram> 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<Renderer::ShaderProgram> worldProg;
|
||||
std::unique_ptr<Renderer::ShaderProgram> skyProg;
|
||||
std::unique_ptr<Renderer::ShaderProgram> particleProg;
|
||||
|
||||
GLuint ssRectProgram;
|
||||
GLint ssRectTexture, ssRectColour, ssRectSize, ssRectOffset;
|
||||
|
@ -57,14 +57,14 @@ MapRenderer::MapRenderer(std::shared_ptr<Renderer> 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);
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ private:
|
||||
GeometryBuffer circleGeom;
|
||||
DrawBuffer circle;
|
||||
|
||||
Renderer::ShaderProgram* rectProg;
|
||||
std::unique_ptr<Renderer::ShaderProgram> rectProg;
|
||||
|
||||
void prepareBlip(const glm::vec2& coord, const glm::mat4& view,
|
||||
const MapInfo& mi, const std::string& texture,
|
||||
|
@ -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<Renderer::ShaderProgram> OpenGLRenderer::createShader(const std::string& vert,
|
||||
const std::string& frag) {
|
||||
return new OpenGLShaderProgram(compileProgram(vert.c_str(), frag.c_str()));
|
||||
return std::make_unique<OpenGLShaderProgram>(compileProgram(vert.c_str(), frag.c_str()));
|
||||
}
|
||||
|
||||
void OpenGLRenderer::setProgramBlockBinding(Renderer::ShaderProgram* p,
|
||||
|
@ -136,7 +136,7 @@ public:
|
||||
|
||||
virtual std::string getIDString() const = 0;
|
||||
|
||||
virtual ShaderProgram* createShader(const std::string& vert,
|
||||
virtual std::unique_ptr<ShaderProgram> 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<ShaderProgram> createShader(const std::string& vert,
|
||||
const std::string& frag) override;
|
||||
void setProgramBlockBinding(ShaderProgram* p, const std::string& name,
|
||||
GLint point) override;
|
||||
|
@ -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);
|
||||
|
@ -60,7 +60,7 @@ private:
|
||||
GlyphInfo glyphData[GAME_GLYPHS];
|
||||
|
||||
GameRenderer* renderer;
|
||||
Renderer::ShaderProgram* textShader;
|
||||
std::unique_ptr<Renderer::ShaderProgram> textShader;
|
||||
|
||||
GeometryBuffer gb;
|
||||
DrawBuffer db;
|
||||
|
@ -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};
|
||||
|
@ -33,8 +33,8 @@ public:
|
||||
void render(GameRenderer* renderer, GameWorld* world);
|
||||
|
||||
private:
|
||||
Renderer::ShaderProgram* waterProg;
|
||||
Renderer::ShaderProgram* maskProg;
|
||||
std::unique_ptr<Renderer::ShaderProgram> waterProg;
|
||||
std::unique_ptr<Renderer::ShaderProgram> maskProg;
|
||||
|
||||
DrawBuffer maskDraw;
|
||||
GeometryBuffer maskGeom;
|
||||
|
@ -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");
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user