1
0
mirror of https://github.com/rwengine/openrw.git synced 2024-09-15 06:52:34 +02:00

Merge pull request #600 from danhedron/cleanup/game_renderer

Cleanup Game Renderer
This commit is contained in:
Daniel Evans 2018-08-23 10:33:46 +01:00 committed by GitHub
commit 7d894b2da5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 100 additions and 231 deletions

View File

@ -32,14 +32,6 @@ constexpr uint32_t kMissingTextureBytes[] = {
0xFFFF00FF, 0xFF0000FF, 0xFFFF00FF, 0xFF0000FF,
};
struct WaterVertex {
static const AttributeList vertex_attributes() {
return {{ATRS_Position, 2, sizeof(WaterVertex), 0ul}};
}
float x, y;
};
/// @todo collapse all of these into "VertPNC" etc.
struct ParticleVert {
static const AttributeList vertex_attributes() {
@ -167,10 +159,6 @@ GameRenderer::GameRenderer(Logger* log, GameData* _data)
glBindVertexArray(0);
glGenBuffers(1, &debugVBO);
glGenTextures(1, &debugTex);
glGenVertexArrays(1, &debugVAO);
particleGeom.uploadVertices<ParticleVert>(
{{0.5f, 0.5f, 1.f, 1.f, 1.f, 1.f, 1.f},
{-0.5f, 0.5f, 0.f, 1.f, 1.f, 1.f, 1.f},
@ -179,28 +167,18 @@ GameRenderer::GameRenderer(Logger* log, GameData* _data)
particleDraw.addGeometry(&particleGeom);
particleDraw.setFaceType(GL_TRIANGLE_STRIP);
ssRectGeom.uploadVertices(sspaceRect);
ssRectGeom.uploadVertices<VertexP2>({{-1.f, -1.f}, {1.f, -1.f}, {-1.f, 1.f}, {1.f, 1.f}});
ssRectDraw.addGeometry(&ssRectGeom);
ssRectDraw.setFaceType(GL_TRIANGLE_STRIP);
ssRectProgram =
compileProgram(GameShaders::ScreenSpaceRect::VertexShader,
GameShaders::ScreenSpaceRect::FragmentShader);
ssRectTexture = glGetUniformLocation(ssRectProgram, "texture");
ssRectColour = glGetUniformLocation(ssRectProgram, "colour");
ssRectSize = glGetUniformLocation(ssRectProgram, "size");
ssRectOffset = glGetUniformLocation(ssRectProgram, "offset");
ssRectProg =
renderer->createShader(GameShaders::ScreenSpaceRect::VertexShader,
GameShaders::ScreenSpaceRect::FragmentShader);
renderer->setUniform(ssRectProg.get(), "texture", 0);
}
GameRenderer::~GameRenderer() {
glDeleteFramebuffers(1, &framebufferName);
glDeleteProgram(ssRectProgram);
}
float mix(uint8_t a, uint8_t b, float num) {
return a + (b - a) * num;
}
void GameRenderer::setupRender() {
@ -389,7 +367,7 @@ void GameRenderer::renderWorld(GameWorld* world, const ViewCamera& camera,
glDisable(GL_DEPTH_TEST);
GLuint splashTexName = 0;
auto fc = world->state->fadeColour;
const auto fc = world->state->fadeColour;
if ((fc.r + fc.g + fc.b) == 0 && !world->state->currentSplash.empty()) {
auto splash = world->data->findSlotTexture("generic", world->state->currentSplash);
if (splash) {
@ -402,37 +380,8 @@ void GameRenderer::renderWorld(GameWorld* world, const ViewCamera& camera,
renderLetterbox();
}
float fadeTimer = world->getGameTime() - world->state->fadeStart;
if (!world->isPaused()) {
glEnable(GL_BLEND);
/// @todo rewrite this render code to use renderer class
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glUseProgram(ssRectProgram);
glUniform2f(ssRectOffset, 0.f, 0.f);
glUniform2f(ssRectSize, 1.f, 1.f);
glUniform1i(ssRectTexture, 0);
if (splashTexName != 0) {
glBindTexture(GL_TEXTURE_2D, splashTexName);
fc = glm::u16vec3(0, 0, 0);
} else {
glBindTexture(GL_TEXTURE_2D, 0);
}
float fadeFrac = 1.f;
if (world->state->fadeTime > 0.f) {
fadeFrac = std::min(fadeTimer / world->state->fadeTime, 1.f);
}
float a = world->state->fadeIn ? 1.f - fadeFrac : fadeFrac;
glm::vec4 fadeNormed(fc.r / 255.f, fc.g / 255.f, fc.b / 255.f, a);
glUniform4fv(ssRectColour, 1, glm::value_ptr(fadeNormed));
glBindVertexArray(ssRectDraw.getVAOName());
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
renderSplash(world, splashTexName, fc);
}
if ((world->state->isCinematic || world->state->currentCutscene) &&
@ -441,19 +390,46 @@ void GameRenderer::renderWorld(GameWorld* world, const ViewCamera& camera,
}
renderPostProcess();
}
glUseProgram(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindVertexArray(0);
void GameRenderer::renderSplash(GameWorld* world, GLuint splashTexName, glm::u16vec3 fc) {
float fadeTimer = world->getGameTime() - world->state->fadeStart;
if (splashTexName != 0) {
fc = glm::u16vec3(0, 0, 0);
}
float fadeFrac = 1.f;
if (world->state->fadeTime > 0.f) {
fadeFrac = std::min(fadeTimer / world->state->fadeTime, 1.f);
}
float a = world->state->fadeIn ? 1.f - fadeFrac : fadeFrac;
if (a <= 0.f) {
return;
}
glm::vec4 fadeNormed(fc.r / 255.f, fc.g / 255.f, fc.b / 255.f, a);
renderer->useProgram(ssRectProg.get());
renderer->setUniform(ssRectProg.get(), "colour", fadeNormed);
renderer->setUniform(ssRectProg.get(), "size", glm::vec2{1.f, 1.f});
renderer->setUniform(ssRectProg.get(), "offset", glm::vec2{0.f, 0.f});
Renderer::DrawParameters wdp;
wdp.depthMode = DepthMode::OFF;
wdp.blendMode = BlendMode::BLEND_ALPHA;
wdp.count = ssRectGeom.getCount();
wdp.textures = {splashTexName};
renderer->drawArrays(glm::mat4(1.0f), &ssRectDraw, wdp);
}
void GameRenderer::renderPostProcess() {
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glStencilMask(0xFF);
glClearStencil(0x00);
glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT |
GL_STENCIL_BUFFER_BIT);
glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
renderer->useProgram(postProg.get());
@ -461,6 +437,7 @@ void GameRenderer::renderPostProcess() {
wdp.start = 0;
wdp.count = ssRectGeom.getCount();
wdp.textures = {fbTextures[0]};
wdp.depthMode = DepthMode::OFF;
renderer->drawArrays(glm::mat4(1.0f), &ssRectDraw, wdp);
}
@ -523,45 +500,15 @@ void GameRenderer::renderEffects(GameWorld* world) {
}
}
void GameRenderer::drawOnScreenText() {
/// @ TODO
}
void GameRenderer::drawTexture(TextureData* texture, glm::vec4 extents) {
glUseProgram(ssRectProgram);
// Move into NDC
extents.x /= renderer->getViewport().x;
extents.y /= renderer->getViewport().y;
extents.z /= renderer->getViewport().x;
extents.w /= renderer->getViewport().y;
extents.x += extents.z / 2.f;
extents.y += extents.w / 2.f;
extents.x -= .5f;
extents.y -= .5f;
extents *= glm::vec4(2.f, -2.f, 1.f, 1.f);
/// @todo rewrite this render code to use renderer class
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glUniform2f(ssRectOffset, extents.x, extents.y);
glUniform2f(ssRectSize, extents.z, extents.w);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture->getName());
glUniform1i(ssRectTexture, 0);
glUniform4f(ssRectColour, 0.f, 0.f, 0.f, 1.f);
glBindVertexArray(ssRectDraw.getVAOName());
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
// Ooops
renderer->invalidate();
drawRect({0.f, 0.f, 0.f, 1.f}, texture, extents);
}
void GameRenderer::drawColour(const glm::vec4& colour, glm::vec4 extents) {
glUseProgram(ssRectProgram);
drawRect(colour, nullptr, extents);
}
void GameRenderer::drawRect(const glm::vec4& colour, TextureData* texture, glm::vec4& extents) {
// Move into NDC
extents.x /= renderer->getViewport().x;
extents.y /= renderer->getViewport().y;
@ -573,126 +520,35 @@ void GameRenderer::drawColour(const glm::vec4& colour, glm::vec4 extents) {
extents.y -= .5f;
extents *= glm::vec4(2.f, -2.f, 1.f, 1.f);
/// @todo rewrite this render code to use renderer class
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glUniform2f(ssRectOffset, extents.x, extents.y);
glUniform2f(ssRectSize, extents.z, extents.w);
renderer->useProgram(ssRectProg.get());
renderer->setUniform(ssRectProg.get(), "colour", colour);
renderer->setUniform(ssRectProg.get(), "size", glm::vec2{extents.z, extents.w});
renderer->setUniform(ssRectProg.get(), "offset", glm::vec2{extents.x, extents.y});
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, 0);
glUniform1i(ssRectTexture, 0);
glUniform4f(ssRectColour, colour.r, colour.g, colour.b, colour.a);
Renderer::DrawParameters wdp;
wdp.depthMode = DepthMode::OFF;
wdp.blendMode = BlendMode::BLEND_ALPHA;
wdp.count = ssRectGeom.getCount();
wdp.textures = {texture ? texture->getName() : 0};
glBindVertexArray(ssRectDraw.getVAOName());
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
// Ooops
renderer->invalidate();
}
void GameRenderer::renderPaths() {
/*glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, debugTex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
static std::vector<glm::vec3> carlines;
static std::vector<glm::vec3> pedlines;
GLint posAttrib = glGetAttribLocation(worldProg.get(), "position");
GLint uniModel = glGetUniformLocation(worldProg.get(), "model");
glBindVertexArray( vao );
for( size_t n = 0; n < engine->aigraph.nodes.size(); ++n ) {
auto start = engine->aigraph.nodes[n];
if( start->type == AIGraphNode::Pedestrian ) {
pedlines.push_back(start->position);
if( start->external ) {
pedlines.push_back(start->position+glm::vec3(0.f, 0.f, 2.f));
}
else {
pedlines.push_back(start->position+glm::vec3(0.f, 0.f, 1.f));
}
}
else {
carlines.push_back(start->position-glm::vec3(start->size / 2.f, 0.f,
0.f));
carlines.push_back(start->position+glm::vec3(start->size / 2.f, 0.f,
0.f));
}
for( size_t c = 0; c < start->connections.size(); ++c ) {
auto end = start->connections[c];
if( start->type == AIGraphNode::Pedestrian ) {
pedlines.push_back(start->position + glm::vec3(0.f, 0.f, 1.f));
pedlines.push_back(end->position + glm::vec3(0.f, 0.f, 1.f));
}
else {
carlines.push_back(start->position + glm::vec3(0.f, 0.f, 1.f));
carlines.push_back(end->position + glm::vec3(0.f, 0.f, 1.f));
}
}
}
glm::mat4 model;
glUniformMatrix4fv(uniModel, 1, GL_FALSE, glm::value_ptr(model));
glEnableVertexAttribArray(posAttrib);
glBindBuffer(GL_ARRAY_BUFFER, debugVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * carlines.size(),
&(carlines[0]), GL_STREAM_DRAW);
glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE, 0, 0);
float img[] = {1.f, 0.f, 0.f};
glTexImage2D(
GL_TEXTURE_2D, 0, GL_RGB, 1, 1,
0, GL_RGB, GL_FLOAT, img
);
glDrawArrays(GL_LINES, 0, carlines.size());
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * pedlines.size(),
&(pedlines[0]), GL_STREAM_DRAW);
glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE, 0, 0);
float img2[] = {0.f, 1.f, 0.f};
glTexImage2D(
GL_TEXTURE_2D, 0, GL_RGB, 1, 1,
0, GL_RGB, GL_FLOAT, img2
);
glDrawArrays(GL_LINES, 0, pedlines.size());
pedlines.clear();
carlines.clear();
glBindVertexArray( 0 );*/
renderer->drawArrays(glm::mat4(1.0f), &ssRectDraw, wdp);
}
void GameRenderer::renderLetterbox() {
/// @todo rewrite this render code to use renderer class
glUseProgram(ssRectProgram);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
const float cinematicExperienceSize = 0.15f;
glUniform2f(ssRectOffset, 0.f, -1.f * (1.f - cinematicExperienceSize));
glUniform2f(ssRectSize, 1.f, cinematicExperienceSize);
constexpr float cinematicExperienceSize = 0.15f;
renderer->useProgram(ssRectProg.get());
renderer->setUniform(ssRectProg.get(), "colour", glm::vec4{0.f, 0.f, 0.f, 1.f});
renderer->setUniform(ssRectProg.get(), "size", glm::vec2{1.f, cinematicExperienceSize});
renderer->setUniform(ssRectProg.get(), "offset", glm::vec2{0.f,-1.f * (1.f - cinematicExperienceSize)});
Renderer::DrawParameters wdp;
wdp.depthMode = DepthMode::OFF;
wdp.blendMode = BlendMode::BLEND_NONE;
wdp.count = ssRectGeom.getCount();
wdp.textures = {0};
glBindTexture(GL_TEXTURE_2D, 0);
glUniform1i(ssRectTexture, 0);
glUniform4f(ssRectColour, 0.f, 0.f, 0.f, 1.f);
glBindVertexArray(ssRectDraw.getVAOName());
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glUniform2f(ssRectOffset, 0.f, 1.f * (1.f - cinematicExperienceSize));
glUniform2f(ssRectSize, 1.f, cinematicExperienceSize);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
renderer->drawArrays(glm::mat4(1.0f), &ssRectDraw, wdp);
renderer->setUniform(ssRectProg.get(), "offset", glm::vec2{0.f, 1.f * (1.f - cinematicExperienceSize)});
renderer->drawArrays(glm::mat4(1.0f), &ssRectDraw, wdp);
}
void GameRenderer::setViewport(int w, int h) {

View File

@ -44,7 +44,7 @@ class GameRenderer {
GameWorld* _renderWorld = nullptr;
/** Internal non-descript VAOs */
GLuint vao, debugVAO;
GLuint vao;
/** Camera values passed to renderWorld() */
ViewCamera _camera;
@ -65,10 +65,6 @@ class GameRenderer {
GeometryBuffer particleGeom;
DrawBuffer particleDraw;
std::vector<VertexP2> sspaceRect = {
{-1.f, -1.f}, {1.f, -1.f}, {-1.f, 1.f}, {1.f, 1.f},
};
GeometryBuffer ssRectGeom;
DrawBuffer ssRectDraw;
@ -81,11 +77,9 @@ public:
std::unique_ptr<Renderer::ShaderProgram> skyProg;
std::unique_ptr<Renderer::ShaderProgram> particleProg;
GLuint ssRectProgram;
GLint ssRectTexture, ssRectColour, ssRectSize, ssRectOffset;
std::unique_ptr<Renderer::ShaderProgram> ssRectProg;
GLuint skydomeVBO, skydomeIBO, debugVBO;
GLuint debugTex;
GLuint skydomeIBO;
DrawBuffer skyDbuff;
GeometryBuffer skyGbuff;
@ -118,19 +112,14 @@ public:
*/
void renderEffects(GameWorld* world);
/**
* @brief Draws the current on screen text.
*/
void drawOnScreenText();
/**
* @brief Draws a texture on the screen
*/
void drawTexture(TextureData* texture, glm::vec4 extents);
void drawColour(const glm::vec4& colour, glm::vec4 extents);
/** method for rendering AI debug information */
void renderPaths();
/** Render full screen splash / fade */
void renderSplash(GameWorld* world, GLuint tex, glm::u16vec3 fc);
/** Increases cinematic value */
void renderLetterbox();
@ -181,6 +170,8 @@ private:
ClumpPtr getSpecialModel(SpecialModel usage) const {
return specialmodels_[usage];
}
void drawRect(const glm::vec4& colour, TextureData* texture, glm::vec4& extents);
};
#endif

View File

@ -282,6 +282,7 @@ void OpenGLRenderer::setDrawState(const glm::mat4& model, DrawBuffer* draw,
setBlend(p.blendMode);
setDepthWrite(p.depthWrite);
setDepthMode(p.depthMode);
ObjectUniformData objectData{model,
glm::vec4(p.colour.r / 255.f, p.colour.g / 255.f,
@ -369,6 +370,7 @@ void OpenGLRenderer::invalidate() {
currentTextures.clear();
currentUBO = 0;
setBlend(BlendMode::BLEND_NONE);
setDepthMode(DepthMode::OFF);
}
bool OpenGLRenderer::createUBO(Buffer &out, GLsizei size, GLsizei entrySize)

View File

@ -7,6 +7,7 @@
#include <memory>
#include <string>
#include <vector>
#include <array>
#include <glm/glm.hpp>
@ -62,9 +63,14 @@ enum class BlendMode {
BLEND_ADDITIVE
};
enum class DepthMode {
OFF,
LESS,
};
class Renderer {
public:
typedef std::vector<GLuint> Textures;
typedef std::array<GLuint,2> Textures;
/**
* @brief The DrawParameters struct stores drawing state
@ -84,7 +90,9 @@ public:
Textures textures{};
/// Blending mode
BlendMode blendMode = BlendMode::BLEND_NONE;
// Depth writing state
/// Depth
DepthMode depthMode = DepthMode::LESS;
/// Depth writing state
bool depthWrite = true;
/// Material
glm::u8vec4 colour{};
@ -342,6 +350,7 @@ private:
DrawBuffer* currentDbuff = nullptr;
OpenGLShaderProgram* currentProgram = nullptr;
BlendMode blendMode = BlendMode::BLEND_NONE;
DepthMode depthMode = DepthMode::OFF;
bool depthWriteEnabled = false;
GLuint currentUBO = 0;
GLuint currentUnit = 0;
@ -373,6 +382,17 @@ private:
blendMode = mode;
}
void setDepthMode(DepthMode mode) {
if (mode != depthMode) {
if (depthMode == DepthMode::OFF) glEnable(GL_DEPTH_TEST);
switch(mode) {
case DepthMode::OFF: glDisable(GL_DEPTH_TEST); break;
case DepthMode::LESS: glDepthFunc(GL_LESS); break;
}
depthMode = mode;
}
}
void setDepthWrite(bool enable) {
if (enable != depthWriteEnabled) {
glDepthMask(enable ? GL_TRUE : GL_FALSE);

View File

@ -353,7 +353,7 @@ void TextRenderer::renderText(const TextRenderer::TextInfo& ti,
dp.count = gb.getCount();
auto ftexture = renderer->getData()->findSlotTexture("fonts", fontMetaData.textureName);
dp.textures = {ftexture->getName()};
dp.depthWrite = false;
dp.depthMode = DepthMode::OFF;
renderer->getRenderer()->drawArrays(glm::mat4(1.0f), &db, dp);