1
0
mirror of https://github.com/rwengine/openrw.git synced 2024-11-25 20:02:40 +01:00

Initial rendering refactor

This commit is contained in:
Daniel Evans 2014-08-22 14:29:46 +01:00
parent 4d78cacd84
commit 668848952b
13 changed files with 638 additions and 361 deletions

View File

@ -203,7 +203,7 @@ public:
/** /**
* The vehicle colour palettes * The vehicle colour palettes
*/ */
std::vector<glm::vec3> vehicleColours; std::vector<glm::u8vec3> vehicleColours;
/** /**
* The vehicle colours for each vehicle type * The vehicle colours for each vehicle type

View File

@ -21,8 +21,8 @@ public:
VehicleDataHandle vehicle; VehicleDataHandle vehicle;
VehicleInfoHandle info; VehicleInfoHandle info;
glm::vec3 colourPrimary; glm::u8vec3 colourPrimary;
glm::vec3 colourSecondary; glm::u8vec3 colourSecondary;
std::map<size_t, GameObject*> seatOccupants; std::map<size_t, GameObject*> seatOccupants;
@ -44,8 +44,8 @@ public:
ModelHandle* model, ModelHandle* model,
VehicleDataHandle data, VehicleDataHandle data,
VehicleInfoHandle info, VehicleInfoHandle info,
const glm::vec3& prim, const glm::u8vec3& prim,
const glm::vec3& sec); const glm::u8vec3& sec);
virtual ~VehicleObject(); virtual ~VehicleObject();

View File

@ -8,6 +8,8 @@
#include <render/ViewCamera.hpp> #include <render/ViewCamera.hpp>
#include <render/OpenGLRenderer.hpp>
class Model; class Model;
class ModelFrame; class ModelFrame;
class GameWorld; class GameWorld;
@ -24,6 +26,8 @@ class CutsceneObject;
class Animator; class Animator;
class InventoryItem; class InventoryItem;
class Renderer;
/** /**
* @brief Implements high level drawing logic and low level draw commands * @brief Implements high level drawing logic and low level draw commands
* *
@ -35,13 +39,16 @@ class GameRenderer
/** Pointer to the world instance */ /** Pointer to the world instance */
GameWorld* engine; GameWorld* engine;
/** Data required to queue transparent objects for delayed rendering */ /** The low-level drawing interface to use */
Renderer* renderer;
/** Stores data for deferring transparent objects */
struct RQueueEntry { struct RQueueEntry {
Model* model; Model* model;
size_t g; size_t g;
size_t sg; size_t sg;
glm::mat4 matrix; glm::mat4 matrix;
float opacity; Renderer::DrawParameters dp;
GameObject* object; GameObject* object;
}; };
@ -56,18 +63,6 @@ class GameRenderer
*/ */
bool renderFrame(Model* m, ModelFrame* f, const glm::mat4& matrix, GameObject* object, float opacity, bool queueTransparent = true); bool renderFrame(Model* m, ModelFrame* f, const glm::mat4& matrix, GameObject* object, float opacity, bool queueTransparent = true);
/**
* @brief renders a model's subgeometry
* @param model
* @param g
* @param sg
* @param matrix
* @param object
* @param queueTransparent
* @return @see renderFrame(
*/
bool renderSubgeometry(Model* model, size_t g, size_t sg, const glm::mat4& matrix, float opacity, GameObject* object, bool queueTransparent = true);
/** Transparent objects are queued into this list */ /** Transparent objects are queued into this list */
std::vector<RQueueEntry> transparentDrawQueue; std::vector<RQueueEntry> transparentDrawQueue;
@ -149,14 +144,10 @@ public:
size_t geoms; size_t geoms;
/** @todo Clean up all these shader program and location variables */ /** @todo Clean up all these shader program and location variables */
GLuint worldProgram; Renderer::ShaderProgram* worldProg;
GLint uniTexture; Renderer::ShaderProgram* skyProg;
GLuint ubiScene, ubiObject; Renderer::ShaderProgram* waterProg;
GLuint uboScene, uboObject;
GLuint skyProgram;
GLuint waterProgram, waterMVP, waterHeight, waterTexture, waterSize, waterTime, waterPosition, waterWave;
GLint skyUniView, skyUniProj, skyUniTop, skyUniBottom;
GLuint particleProgram; GLuint particleProgram;
GLuint ssRectProgram; GLuint ssRectProgram;
@ -165,6 +156,9 @@ public:
GLuint skydomeVBO, skydomeIBO, debugVBO; GLuint skydomeVBO, skydomeIBO, debugVBO;
GLuint debugTex; GLuint debugTex;
DrawBuffer skyDbuff;
GeometryBuffer skyGbuff;
/** /**
* Renders the world using the parameters of the passed Camera. * Renders the world using the parameters of the passed Camera.
* Note: The camera's near and far planes are overriden by weather effects. * Note: The camera's near and far planes are overriden by weather effects.
@ -233,38 +227,6 @@ public:
/** Adds a particle to the rendering */ /** Adds a particle to the rendering */
void addParticle(const FXParticle& particle); void addParticle(const FXParticle& particle);
static GLuint currentUBO;
/**
* Uploads data from T into the specified UBO
*/
template<class T> void uploadUBO(GLuint buffer, const T& data)
{
if( currentUBO != buffer ) {
glBindBuffer(GL_UNIFORM_BUFFER, buffer);
currentUBO = buffer;
}
glBufferData(GL_UNIFORM_BUFFER, sizeof(T), &data, GL_DYNAMIC_DRAW);
}
};
struct SceneUniformData {
glm::mat4 projection;
glm::mat4 view;
glm::vec4 ambient;
glm::vec4 dynamic;
glm::vec4 fogColour;
glm::vec4 campos;
float fogStart;
float fogEnd;
};
struct ObjectUniformData {
glm::mat4 model;
glm::vec4 colour;
float diffuse;
float ambient;
float visibility;
}; };
#endif #endif

View File

@ -0,0 +1,169 @@
#pragma once
#ifndef _OPENGLRENDERER_HPP_
#define _OPENGLRENDERER_HPP_
#include <engine/RWTypes.hpp>
#include <render/DrawBuffer.hpp>
#include <render/GeometryBuffer.hpp>
typedef std::uint32_t RenderIndex;
struct VertexP3
{
glm::vec3 position;
static const AttributeList vertex_attributes() {
return {
{ATRS_Position, 3, sizeof(VertexP3), 0ul},
};
}
};
/// @todo normalize this to have the same interface as VertexP3
struct VertexP2 {
static const AttributeList vertex_attributes() {
return {
{ATRS_Position, 2, sizeof(VertexP2), 0ul}
};
}
float x, y;
};
class Renderer
{
public:
struct DrawParameters
{
GLuint texture; /// @todo replace with texture handle.
glm::u8vec4 colour;
float ambient;
float diffuse;
size_t count; /// The number of indicies to draw
unsigned int start; /// Start index.
};
struct ObjectUniformData {
glm::mat4 model;
glm::vec4 colour;
float diffuse;
float ambient;
float visibility;
};
struct SceneUniformData {
glm::mat4 projection;
glm::mat4 view;
glm::vec4 ambient;
glm::vec4 dynamic;
glm::vec4 fogColour;
glm::vec4 campos;
float fogStart;
float fogEnd;
};
class ShaderProgram {
// This just provides an opaque handle for external users.
};
virtual std::string getIDString() const = 0;
virtual ShaderProgram* createShader(const std::string& vert, const std::string& frag) = 0;
virtual void useProgram(ShaderProgram* p) = 0;
/// @todo dont use GLint in the interface.
virtual void setProgramBlockBinding(ShaderProgram* p, const std::string& name, GLint point) = 0;
virtual void setUniformTexture(ShaderProgram*p, const std::string& name, GLint tex) = 0;
virtual void setUniform(ShaderProgram*p, const std::string& name, const glm::vec4& v) = 0;
virtual void setUniform(ShaderProgram*p, const std::string& name, const glm::vec3& v) = 0;
virtual void setUniform(ShaderProgram*p, const std::string& name, const glm::vec2& v) = 0;
virtual void setUniform(ShaderProgram*p, const std::string& name, float f) = 0;
virtual void clear(const glm::vec4& colour, bool clearColour = true, bool clearDepth = true) = 0;
virtual void setSceneParameters(const SceneUniformData& data) = 0;
virtual void draw(const glm::mat4& model, DrawBuffer* draw, const DrawParameters& p) = 0;
virtual void drawArrays(const glm::mat4& model, DrawBuffer* draw, const DrawParameters& p) = 0;
};
class OpenGLRenderer : public Renderer
{
public:
class OpenGLShaderProgram : public ShaderProgram {
GLuint program;
std::map<std::string, GLint> uniforms;
public:
OpenGLShaderProgram(GLuint p)
: program(p)
{ }
GLuint getName() const { return program; }
GLint getUniformLocation(const std::string& name) {
auto c = uniforms.find(name.c_str());
GLint loc = -1;
if( c == uniforms.end() ) {
loc = glGetUniformLocation(program, name.c_str());
uniforms[name] = loc;
}
else {
loc = c->second;
}
return loc;
}
};
OpenGLRenderer();
std::string getIDString() const;
ShaderProgram* createShader(const std::string &vert, const std::string &frag);
void setProgramBlockBinding(ShaderProgram* p, const std::string &name, GLint point);
void setUniformTexture(ShaderProgram* p, const std::string &name, GLint tex);
void setUniform(ShaderProgram* p, const std::string& name, const glm::vec4& m);
void setUniform(ShaderProgram* p, const std::string& name, const glm::vec3& m);
void setUniform(ShaderProgram* p, const std::string& name, const glm::vec2& m);
void setUniform(ShaderProgram* p, const std::string& name, float f);
void useProgram(ShaderProgram* p);
void clear(const glm::vec4 &colour, bool clearColour, bool clearDepth);
void setSceneParameters(const SceneUniformData &data);
void draw(const glm::mat4& model, DrawBuffer* draw, const DrawParameters& p);
void drawArrays(const glm::mat4& model, DrawBuffer* draw, const DrawParameters& p);
private:
DrawBuffer* currentDbuff;
void useDrawBuffer(DrawBuffer* dbuff);
GLuint currentTexture;
void useTexture(GLuint tex);
OpenGLShaderProgram* currentProgram;
GLuint currentUBO;
template<class T> void uploadUBO(GLuint buffer, const T& data)
{
if( currentUBO != buffer ) {
glBindBuffer(GL_UNIFORM_BUFFER, buffer);
currentUBO = buffer;
}
glBufferData(GL_UNIFORM_BUFFER, sizeof(T), &data, GL_DYNAMIC_DRAW);
}
GLuint UBOObject;
GLuint UBOScene;
};
/// @todo remove these from here
GLuint compileShader(GLenum type, const char *source);
GLuint compileProgram(const char* vertex, const char* fragment);
#endif

View File

@ -280,10 +280,10 @@ void GameData::loadCarcols(const std::string& path)
std::stringstream ss(line); std::stringstream ss(line);
if( std::getline(ss, r, ',') && std::getline(ss, g, ',') && std::getline(ss, b)) { if( std::getline(ss, r, ',') && std::getline(ss, g, ',') && std::getline(ss, b)) {
vehicleColours.push_back(glm::vec3( vehicleColours.push_back(glm::u8vec3(
atoi(r.c_str())/255.f, atoi(r.c_str()),
atoi(g.c_str())/255.f, atoi(g.c_str()),
atoi(b.c_str())/255.f atoi(b.c_str())
)); ));
} }
} }

View File

@ -116,6 +116,7 @@ bool GameWorld::load()
void GameWorld::logInfo(const std::string& info) void GameWorld::logInfo(const std::string& info)
{ {
log.push_back({LogEntry::Info, gameTime, info}); log.push_back({LogEntry::Info, gameTime, info});
std::cout << info << std::endl;
} }
void GameWorld::logError(const std::string& error) void GameWorld::logError(const std::string& error)
@ -418,7 +419,7 @@ VehicleObject *GameWorld::createVehicle(const uint16_t id, const glm::vec3& pos,
gameData.loadTXD(vti->second->textureName + ".txd"); gameData.loadTXD(vti->second->textureName + ".txd");
} }
glm::vec3 prim = glm::vec3(1.f), sec = glm::vec3(0.5f); glm::u8vec3 prim(255), sec(128);
auto palit = gameData.vehiclePalettes.find(vti->second->modelName); // modelname is conveniently lowercase (usually) auto palit = gameData.vehiclePalettes.find(vti->second->modelName); // modelname is conveniently lowercase (usually)
if(palit != gameData.vehiclePalettes.end() && palit->second.size() > 0 ) { if(palit != gameData.vehiclePalettes.end() && palit->second.size() > 0 ) {
std::uniform_int_distribution<int> uniform(0, palit->second.size()-1); std::uniform_int_distribution<int> uniform(0, palit->second.size()-1);

View File

@ -246,6 +246,7 @@ void LoaderDFF::readGeometry(Model *model, const RWBStream &stream)
sizeof(uint32_t) * sg.numIndices, sizeof(uint32_t) * sg.numIndices,
sg.indices.data()); sg.indices.data());
} }
} }
void LoaderDFF::readMaterialList(Model *model, const RWBStream &stream) void LoaderDFF::readMaterialList(Model *model, const RWBStream &stream)

View File

@ -7,7 +7,7 @@
#include <render/Model.hpp> #include <render/Model.hpp>
#include <engine/Animator.hpp> #include <engine/Animator.hpp>
VehicleObject::VehicleObject(GameWorld* engine, const glm::vec3& pos, const glm::quat& rot, ModelHandle* model, VehicleDataHandle data, VehicleInfoHandle info, const glm::vec3& prim, const glm::vec3& sec) VehicleObject::VehicleObject(GameWorld* engine, const glm::vec3& pos, const glm::quat& rot, ModelHandle* model, VehicleDataHandle data, VehicleInfoHandle info, const glm::u8vec3& prim, const glm::u8vec3& sec)
: GameObject(engine, pos, rot, model), : GameObject(engine, pos, rot, model),
steerAngle(0.f), throttle(0.f), brake(0.f), handbrake(false), steerAngle(0.f), throttle(0.f), brake(0.f), handbrake(false),
vehicle(data), info(info), colourPrimary(prim), vehicle(data), info(info), colourPrimary(prim),

View File

@ -23,8 +23,6 @@
#include <cmath> #include <cmath>
#include <glm/gtc/type_ptr.hpp> #include <glm/gtc/type_ptr.hpp>
GLuint GameRenderer::currentUBO = 0;
const size_t skydomeSegments = 8, skydomeRows = 10; const size_t skydomeSegments = 8, skydomeRows = 10;
struct WaterVertex { struct WaterVertex {
@ -69,16 +67,6 @@ struct ParticleVert {
GeometryBuffer particleGeom; GeometryBuffer particleGeom;
DrawBuffer particleDraw; DrawBuffer particleDraw;
struct VertexP2 {
static const AttributeList vertex_attributes() {
return {
{ATRS_Position, 2, sizeof(VertexP2), 0ul}
};
}
float x, y;
};
std::vector<VertexP2> sspaceRect = { std::vector<VertexP2> sspaceRect = {
{-1.f, -1.f}, {-1.f, -1.f},
{ 1.f, -1.f}, { 1.f, -1.f},
@ -89,98 +77,18 @@ std::vector<VertexP2> sspaceRect = {
GeometryBuffer ssRectGeom; GeometryBuffer ssRectGeom;
DrawBuffer ssRectDraw; DrawBuffer ssRectDraw;
GLuint compileShader(GLenum type, const char *source)
{
GLuint shader = glCreateShader(type);
glShaderSource(shader, 1, &source, NULL);
glCompileShader(shader);
GLint status;
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
if( status != GL_TRUE ) {
std::cerr << "[OGL] Shader Compilation Failed" << std::endl;
}
GLint len;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &len);
if( len > 1 ) {
GLchar *buffer = new GLchar[len];
glGetShaderInfoLog(shader, len, NULL, buffer);
GLint sourceLen;
glGetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &sourceLen);
GLchar *sourceBuff = new GLchar[sourceLen];
glGetShaderSource(shader, sourceLen, nullptr, sourceBuff);
std::cerr << "[OGL] Shader InfoLog(" << shader << "):\n" << buffer << "\nSource:\n" << sourceBuff << std::endl;
delete[] buffer;
delete[] sourceBuff;
}
if (status != GL_TRUE) {
exit(1);
}
return shader;
}
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);
GLint status;
glGetProgramiv(prog, GL_LINK_STATUS, &status);
if( status != GL_TRUE ) {
std::cerr << "[OGL] Program Link Failed" << std::endl;
}
GLint len;
glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &len);
if( len > 1 ) {
GLchar *buffer = new GLchar[len];
glGetProgramInfoLog(prog, len, NULL, buffer);
std::cerr << "[OGL] Program InfoLog(" << prog << "):\n" << buffer << std::endl;
delete[] buffer;
}
if (status != GL_TRUE) {
exit(1);
}
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
return prog;
}
GameRenderer::GameRenderer(GameWorld* engine) GameRenderer::GameRenderer(GameWorld* engine)
: engine(engine), _renderAlpha(0.f) : engine(engine), renderer(new OpenGLRenderer), _renderAlpha(0.f)
{ {
worldProgram = compileProgram(GameShaders::WorldObject::VertexShader, engine->logInfo("[DRAW] " + renderer->getIDString());
GameShaders::WorldObject::FragmentShader);
uniTexture = glGetUniformLocation(worldProgram, "texture"); worldProg = renderer->createShader(
ubiScene = glGetUniformBlockIndex(worldProgram, "SceneData"); GameShaders::WorldObject::VertexShader,
ubiObject = glGetUniformBlockIndex(worldProgram, "ObjectData"); GameShaders::WorldObject::FragmentShader);
glGenBuffers(1, &uboScene); renderer->setUniformTexture(worldProg, "texture", 0);
glGenBuffers(1, &uboObject); renderer->setProgramBlockBinding(worldProg, "SceneData", 1);
renderer->setProgramBlockBinding(worldProg, "ObjectData", 2);
glUniformBlockBinding(worldProgram, ubiScene, 1);
glUniformBlockBinding(worldProgram, ubiObject, 2);
glBindBufferBase(GL_UNIFORM_BUFFER, 1, uboScene);
glBindBufferBase(GL_UNIFORM_BUFFER, 2, uboObject);
particleProgram = compileProgram(GameShaders::WorldObject::VertexShader, particleProgram = compileProgram(GameShaders::WorldObject::VertexShader,
GameShaders::Particle::FragmentShader); GameShaders::Particle::FragmentShader);
@ -189,27 +97,23 @@ GameRenderer::GameRenderer(GameWorld* engine)
ubiScene = glGetUniformBlockIndex(particleProgram, "SceneData"); ubiScene = glGetUniformBlockIndex(particleProgram, "SceneData");
ubiObject = glGetUniformBlockIndex(particleProgram, "ObjectData");*/ ubiObject = glGetUniformBlockIndex(particleProgram, "ObjectData");*/
glUniformBlockBinding(particleProgram, ubiScene, 1); //glUniformBlockBinding(particleProgram, ubiScene, 1);
glUniformBlockBinding(particleProgram, ubiObject, 2); //glUniformBlockBinding(particleProgram, ubiObject, 2);
skyProgram = compileProgram(GameShaders::Sky::VertexShader, skyProg = renderer->createShader(
GameShaders::Sky::FragmentShader); GameShaders::Sky::VertexShader,
GameShaders::Sky::FragmentShader);
skyUniView = glGetUniformLocation(skyProgram, "view"); renderer->setProgramBlockBinding(skyProg, "SceneData", 1);
skyUniProj = glGetUniformLocation(skyProgram, "proj");
skyUniTop = glGetUniformLocation(skyProgram, "TopColor");
skyUniBottom = glGetUniformLocation(skyProgram, "BottomColor");
waterProgram = compileProgram(GameShaders::WaterHQ::VertexShader, waterProg = renderer->createShader(
GameShaders::WaterHQ::FragmentShader); GameShaders::WaterHQ::VertexShader,
GameShaders::WaterHQ::FragmentShader);
waterHeight = glGetUniformLocation(waterProgram, "height"); renderer->setUniformTexture(waterProg, "texture", 0);
waterTexture = glGetUniformLocation(waterProgram, "texture");
waterSize = glGetUniformLocation(waterProgram, "size"); renderer->setProgramBlockBinding(waterProg, "SceneData", 1);
waterMVP = glGetUniformLocation(waterProgram, "MVP"); renderer->setProgramBlockBinding(waterProg, "ObjectData", 2);
waterTime = glGetUniformLocation(waterProgram, "time");
waterPosition = glGetUniformLocation(waterProgram, "worldP");
waterWave = glGetUniformLocation(waterProgram, "waveParams");
glGenVertexArrays( 1, &vao ); glGenVertexArrays( 1, &vao );
@ -240,28 +144,29 @@ GameRenderer::GameRenderer(GameWorld* engine)
waterHQDraw.setFaceType(GL_TRIANGLES); waterHQDraw.setFaceType(GL_TRIANGLES);
// And our skydome while we're at it. // Create the skydome
glGenBuffers(1, &skydomeVBO);
glBindBuffer(GL_ARRAY_BUFFER, skydomeVBO);
size_t segments = skydomeSegments, rows = skydomeRows; size_t segments = skydomeSegments, rows = skydomeRows;
float R = 1.f/(float)(rows-1); float R = 1.f/(float)(rows-1);
float S = 1.f/(float)(segments-1); float S = 1.f/(float)(segments-1);
std::vector<glm::vec3> skydomeBuff; std::vector<VertexP3> skydomeVerts;
skydomeBuff.resize(rows * segments); skydomeVerts.resize(rows * segments);
for( size_t r = 0, i = 0; r < rows; ++r) { for( size_t r = 0, i = 0; r < rows; ++r) {
for( size_t s = 0; s < segments; ++s) { for( size_t s = 0; s < segments; ++s) {
skydomeBuff[i++] = glm::vec3( skydomeVerts[i++].position = glm::vec3(
cos(2.f * M_PI * s * S) * cos(M_PI_2 * r * R), cos(2.f * M_PI * s * S) * cos(M_PI_2 * r * R),
sin(2.f * M_PI * s * S) * cos(M_PI_2 * r * R), sin(2.f * M_PI * s * S) * cos(M_PI_2 * r * R),
sin(M_PI_2 * r * R) sin(M_PI_2 * r * R)
); );
} }
} }
glBufferData(GL_ARRAY_BUFFER, sizeof(skydomeBuff), skydomeBuff.data(), GL_STATIC_DRAW); skyGbuff.uploadVertices(skydomeVerts);
skyDbuff.addGeometry(&skyGbuff);
skyDbuff.setFaceType(GL_TRIANGLES);
glGenBuffers(1, &skydomeIBO); glGenBuffers(1, &skydomeIBO);
GLushort skydomeIndBuff[rows*segments*6]; GLuint skydomeIndBuff[rows*segments*6];
for( size_t r = 0, i = 0; r < (rows-1); ++r ) { for( size_t r = 0, i = 0; r < (rows-1); ++r ) {
for( size_t s = 0; s < (segments-1); ++s ) { for( size_t s = 0; s < (segments-1); ++s ) {
skydomeIndBuff[i++] = r * segments + s; skydomeIndBuff[i++] = r * segments + s;
@ -275,6 +180,8 @@ GameRenderer::GameRenderer(GameWorld* engine)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, skydomeIBO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, skydomeIBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(skydomeIndBuff), skydomeIndBuff, GL_STATIC_DRAW); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(skydomeIndBuff), skydomeIndBuff, GL_STATIC_DRAW);
glBindVertexArray(0);
glGenBuffers(1, &debugVBO); glGenBuffers(1, &debugVBO);
glGenTextures(1, &debugTex); glGenTextures(1, &debugTex);
glGenVertexArrays(1, &debugVAO); glGenVertexArrays(1, &debugVAO);
@ -341,33 +248,31 @@ void GameRenderer::renderWorld(const ViewCamera &camera, float alpha)
_camera.frustum.near = engine->state.cameraNear; _camera.frustum.near = engine->state.cameraNear;
_camera.frustum.far = weather.farClipping; _camera.frustum.far = weather.farClipping;
glUseProgram(worldProgram);
auto view = _camera.getView(); auto view = _camera.getView();
auto proj = _camera.frustum.projection(); auto proj = _camera.frustum.projection();
uploadUBO<SceneUniformData>( Renderer::SceneUniformData sceneParams {
uboScene, proj,
{ view,
proj, glm::vec4{ambient, 0.0f},
view, glm::vec4{dynamic, 0.0f},
glm::vec4{ambient, 0.0f}, glm::vec4(skyBottom, 1.f),
glm::vec4{dynamic, 0.0f}, glm::vec4(camera.position, 0.f),
glm::vec4(skyBottom, 1.f), weather.fogStart,
glm::vec4(camera.position, 0.f), camera.frustum.far
weather.fogStart, };
camera.frustum.far
});
glClearColor(skyBottom.r, skyBottom.g, skyBottom.b, 1.f); renderer->setSceneParameters(sceneParams);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
renderer->clear(glm::vec4(skyBottom, 1.f));
_camera.frustum.update(proj * view); _camera.frustum.update(proj * view);
rendered = culled = geoms = frames = 0; rendered = culled = geoms = frames = 0;
renderer->useProgram(worldProg);
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
glUniform1i(uniTexture, 0);
for( GameObject* object : engine->objects ) { for( GameObject* object : engine->objects ) {
switch(object->type()) { switch(object->type()) {
@ -398,36 +303,36 @@ void GameRenderer::renderWorld(const ViewCamera &camera, float alpha)
it != transparentDrawQueue.end(); it != transparentDrawQueue.end();
++it) ++it)
{ {
glBindVertexArray(it->model->geometries[it->g]->dbuff.getVAOName()); renderer->draw(it->matrix, &it->model->geometries[it->g]->dbuff, it->dp);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, it->model->geometries[it->g]->EBO);
renderSubgeometry(it->model, it->g, it->sg, it->matrix, it->opacity, it->object, false);
} }
transparentDrawQueue.clear(); transparentDrawQueue.clear();
// Draw the water. // Draw the water.
glUseProgram( waterProgram ); renderer->useProgram( waterProg );
// TODO: Add some kind of draw distance
float blockLQSize = WATER_WORLD_SIZE/WATER_LQ_DATA_SIZE; float blockLQSize = WATER_WORLD_SIZE/WATER_LQ_DATA_SIZE;
float blockHQSize = WATER_WORLD_SIZE/WATER_HQ_DATA_SIZE; float blockHQSize = WATER_WORLD_SIZE/WATER_HQ_DATA_SIZE;
glm::vec2 waterOffset { -WATER_WORLD_SIZE/2.f, -WATER_WORLD_SIZE/2.f }; glm::vec2 waterOffset { -WATER_WORLD_SIZE/2.f, -WATER_WORLD_SIZE/2.f };
glUniform1i(waterTexture, 0);
glUniform2f(waterWave, WATER_SCALE, WATER_HEIGHT);
auto waterTex = engine->gameData.textures[{"water_old",""}]; auto waterTex = engine->gameData.textures[{"water_old",""}];
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, waterTex.texName); glBindTexture(GL_TEXTURE_2D, waterTex.texName);
auto camposFlat = glm::vec2(camera.position); auto camposFlat = glm::vec2(camera.position);
glBindVertexArray( waterHQDraw.getVAOName() ); Renderer::DrawParameters wdp;
wdp.start = 0;
wdp.count = waterHQVerts.size();
wdp.texture = waterTex.texName;
renderer->useProgram(waterProg);
renderer->setSceneParameters(sceneParams);
// Draw High detail water // Draw High detail water
glUniform1f(waterSize, blockHQSize); renderer->setUniform(waterProg, "size", blockHQSize);
glUniform1f(waterTime, engine->gameTime); renderer->setUniform(waterProg, "time", engine->gameTime);
renderer->setUniform(waterProg, "waveParams", glm::vec2(WATER_SCALE, WATER_HEIGHT));
for( int x = 0; x < WATER_HQ_DATA_SIZE; x++ ) { for( int x = 0; x < WATER_HQ_DATA_SIZE; x++ ) {
for( int y = 0; y < WATER_HQ_DATA_SIZE; y++ ) { for( int y = 0; y < WATER_HQ_DATA_SIZE; y++ ) {
auto waterWS = waterOffset + glm::vec2(blockHQSize) * glm::vec2(x, y); auto waterWS = waterOffset + glm::vec2(blockHQSize) * glm::vec2(x, y);
@ -441,18 +346,18 @@ void GameRenderer::renderWorld(const ViewCamera &camera, float alpha)
if( hI >= NO_WATER_INDEX ) continue; if( hI >= NO_WATER_INDEX ) continue;
float h = engine->gameData.waterHeights[hI]; float h = engine->gameData.waterHeights[hI];
glUniform1f(waterHeight, h); glm::mat4 m;
auto MVP = proj * view; m = glm::translate(m, glm::vec3(waterWS, h));
glUniform2fv(waterPosition, 1, glm::value_ptr(waterWS));
glUniformMatrix4fv(waterMVP, 1, GL_FALSE, glm::value_ptr(MVP)); renderer->drawArrays(m, &waterHQDraw, wdp);
glDrawArrays(waterHQDraw.getFaceType(), 0, waterHQVerts.size());
} }
} }
glBindVertexArray( waterLQDraw.getVAOName() );
glUniform2f(waterWave, 0.0f, 0.0f);
glUniform1f(waterSize, blockLQSize); wdp.count = waterLQVerts.size();
renderer->setUniform(waterProg, "size", blockLQSize);
renderer->setUniform(waterProg, "waveParams", glm::vec2(0.f));
for( int x = 0; x < WATER_LQ_DATA_SIZE; x++ ) { for( int x = 0; x < WATER_LQ_DATA_SIZE; x++ ) {
for( int y = 0; y < WATER_LQ_DATA_SIZE; y++ ) { for( int y = 0; y < WATER_LQ_DATA_SIZE; y++ ) {
auto waterWS = waterOffset + glm::vec2(blockLQSize) * glm::vec2(x, y); auto waterWS = waterOffset + glm::vec2(blockLQSize) * glm::vec2(x, y);
@ -467,28 +372,24 @@ void GameRenderer::renderWorld(const ViewCamera &camera, float alpha)
if( hI >= NO_WATER_INDEX ) continue; if( hI >= NO_WATER_INDEX ) continue;
float h = engine->gameData.waterHeights[hI]; float h = engine->gameData.waterHeights[hI];
glUniform1f(waterHeight, h); glm::mat4 m;
auto MVP = proj * view; m = glm::translate(m, glm::vec3(waterWS, h));
glUniform2fv(waterPosition, 1, glm::value_ptr(waterWS));
glUniformMatrix4fv(waterMVP, 1, GL_FALSE, glm::value_ptr(MVP)); renderer->drawArrays(m, &waterLQDraw, wdp);
glDrawArrays(waterLQDraw.getFaceType(), 0, 4);
} }
} }
glBindVertexArray( vao ); glBindVertexArray( vao );
glUseProgram(skyProgram); Renderer::DrawParameters dp;
dp.start = 0;
dp.count = skydomeSegments * skydomeRows * 6;
glBindBuffer(GL_ARRAY_BUFFER, skydomeVBO); renderer->useProgram(skyProg);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, skydomeIBO); renderer->setUniform(skyProg, "TopColor", glm::vec4(skyTop, 1.f));
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); renderer->setUniform(skyProg, "BottomColor", glm::vec4(skyBottom, 1.f));
glEnableVertexAttribArray(0);
glUniformMatrix4fv(skyUniView, 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(skyUniProj, 1, GL_FALSE, glm::value_ptr(proj));
glUniform4f(skyUniTop, skyTop.r, skyTop.g, skyTop.b, 1.f);
glUniform4f(skyUniBottom, skyBottom.r, skyBottom.g, skyBottom.b, 1.f);
glDrawElements(GL_TRIANGLES, skydomeSegments * skydomeRows * 6, GL_UNSIGNED_SHORT, NULL); renderer->draw(glm::mat4(), &skyDbuff, dp);
renderParticles(); renderParticles();
@ -871,18 +772,70 @@ void GameRenderer::renderItem(InventoryItem *item, const glm::mat4 &modelMatrix)
void GameRenderer::renderGeometry(Model* model, size_t g, const glm::mat4& modelMatrix, float opacity, GameObject* object) void GameRenderer::renderGeometry(Model* model, size_t g, const glm::mat4& modelMatrix, float opacity, GameObject* object)
{ {
geoms++; geoms++;
glBindVertexArray(model->geometries[g]->dbuff.getVAOName());
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, model->geometries[g]->EBO);
for(size_t sg = 0; sg < model->geometries[g]->subgeom.size(); ++sg) for(size_t sg = 0; sg < model->geometries[g]->subgeom.size(); ++sg)
{ {
if(opacity < 1.f || ! renderSubgeometry(model, g, sg, modelMatrix, opacity, object)) { Model::SubGeometry& subgeom = model->geometries[g]->subgeom[sg];
// If rendering was rejected, queue for later.
bool abortTransparent = false;
Renderer::DrawParameters dp;
dp.colour = {255, 255, 255, 255};
dp.count = subgeom.numIndices;
dp.start = subgeom.start;
dp.texture = 0;
if (model->geometries[g]->materials.size() > subgeom.material) {
Model::Material& mat = model->geometries[g]->materials[subgeom.material];
if(mat.textures.size() > 0 ) {
auto& tC = mat.textures[0].name;
auto& tA = mat.textures[0].alphaName;
auto t = engine->gameData.textures.find({tC, tA});
if(t != engine->gameData.textures.end()) {
TextureInfo& tex = t->second;
if(tex.transparent) {
abortTransparent = true;
}
dp.texture = tex.texName;
}
}
if( (model->geometries[g]->flags & RW::BSGeometry::ModuleMaterialColor) == RW::BSGeometry::ModuleMaterialColor) {
dp.colour = mat.colour;
if( object && object->type() == GameObject::Vehicle ) {
auto vehicle = static_cast<VehicleObject*>(object);
if( dp.colour.r == 60 && dp.colour.g == 255 && dp.colour.b == 0 ) {
dp.colour = glm::u8vec4(vehicle->colourPrimary, 255);
}
else if( dp.colour.r == 255 && dp.colour.g == 0 && dp.colour.b == 175 ) {
dp.colour = glm::u8vec4(vehicle->colourSecondary, 255);
}
}
}
dp.colour.a *= opacity;
if( dp.colour.a < 255 ) {
abortTransparent = true;
}
dp.diffuse = mat.diffuseIntensity;
dp.ambient = mat.ambientIntensity;
}
rendered++;
if( abortTransparent ) {
transparentDrawQueue.push_back( transparentDrawQueue.push_back(
{model, g, sg, modelMatrix, opacity, object} {model, g, sg, modelMatrix, dp, object}
); );
} }
else {
renderer->draw(modelMatrix, &model->geometries[g]->dbuff, dp);
}
} }
} }
@ -943,12 +896,12 @@ void GameRenderer::renderParticles()
m[3][2] =-glm::dot(u, p); m[3][2] =-glm::dot(u, p);
m = glm::scale(glm::inverse(m), glm::vec3(part.size, 1.f)); m = glm::scale(glm::inverse(m), glm::vec3(part.size, 1.f));
uploadUBO<ObjectUniformData>( /*uploadUBO<ObjectUniformData>(
uboObject, { uboObject, {
m, m,
part.colour, part.colour,
1.f, 1.f, 1.f 1.f, 1.f, 1.f
}); });*/
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
} }
@ -963,6 +916,7 @@ bool GameRenderer::renderFrame(Model* m, ModelFrame* f, const glm::mat4& matrix,
{ {
frames++; frames++;
auto localmatrix = matrix; auto localmatrix = matrix;
bool vis = true;
if(object && object->animator) { if(object && object->animator) {
bool animFixed = false; bool animFixed = false;
@ -970,26 +924,26 @@ bool GameRenderer::renderFrame(Model* m, ModelFrame* f, const glm::mat4& matrix,
animFixed = static_cast<CharacterObject*>(object)->isAnimationFixed(); animFixed = static_cast<CharacterObject*>(object)->isAnimationFixed();
} }
localmatrix *= object->animator->getFrameMatrix(f, _renderAlpha, animFixed); localmatrix *= object->animator->getFrameMatrix(f, _renderAlpha, animFixed);
vis = object->animator->getFrameVisibility(f);
} }
else { else {
localmatrix *= f->getTransform(); localmatrix *= f->getTransform();
} }
bool vis = (object == nullptr || object->animator == nullptr) || if( vis ) {
object->animator->getFrameVisibility(f); for(size_t g : f->getGeometries()) {
RW::BSGeometryBounds& bounds = m->geometries[g]->geometryBounds;
/// @todo fix culling animating objects?
for(size_t g : f->getGeometries()) { glm::vec3 boundpos = bounds.center + glm::vec3(matrix[3]);
if(!vis ) continue; if(! _camera.frustum.intersects(boundpos, bounds.radius)) {
culled++;
continue;
}
RW::BSGeometryBounds& bounds = m->geometries[g]->geometryBounds; renderGeometry(m, g, localmatrix, opacity, object);
/// @todo fix culling animating objects?
glm::vec3 boundpos = bounds.center + glm::vec3(matrix[3]);
if( (!object || !object->animator) && ! _camera.frustum.intersects(boundpos, bounds.radius)) {
continue;
} }
renderGeometry(m, g, localmatrix, opacity, object);
} }
for(ModelFrame* c : f->getChildren()) { for(ModelFrame* c : f->getChildren()) {
@ -998,78 +952,6 @@ bool GameRenderer::renderFrame(Model* m, ModelFrame* f, const glm::mat4& matrix,
return true; return true;
} }
bool GameRenderer::renderSubgeometry(Model* model, size_t g, size_t sg, const glm::mat4& matrix, float opacity, GameObject* object, bool queueTransparent)
{
auto& subgeom = model->geometries[g]->subgeom[sg];
/*
* model matrix,
* material diffuse
* material ambient
* materialcolour
*/
ObjectUniformData oudata {
matrix,
glm::vec4(1.f),
1.f, 1.f, opacity
};
if (model->geometries[g]->materials.size() > subgeom.material) {
Model::Material& mat = model->geometries[g]->materials[subgeom.material];
if(mat.textures.size() > 0 ) {
auto& tC = mat.textures[0].name;
auto& tA = mat.textures[0].alphaName;
auto t = engine->gameData.textures.find({tC, tA});
if(t != engine->gameData.textures.end()) {
TextureInfo& tex = t->second;
if(tex.transparent && queueTransparent) {
return false;
}
glBindTexture(GL_TEXTURE_2D, tex.texName);
}
else {
// Texture pair is missing?
}
}
else {
glBindTexture(GL_TEXTURE_2D, 0);
}
if( (model->geometries[g]->flags & RW::BSGeometry::ModuleMaterialColor) == RW::BSGeometry::ModuleMaterialColor) {
auto col = mat.colour;
if(col.a < 255 && queueTransparent) return false;
if( object && object->type() == GameObject::Vehicle ) {
auto vehicle = static_cast<VehicleObject*>(object);
if( col.r == 60 && col.g == 255 && col.b == 0 ) {
oudata.colour = glm::vec4(vehicle->colourPrimary, 1.f);
}
else if( col.r == 255 && col.g == 0 && col.b == 175 ) {
oudata.colour = glm::vec4(vehicle->colourSecondary, 1.f);
}
else {
oudata.colour = {col.r/255.f, col.g/255.f, col.b/255.f, col.a/255.f};
}
}
else {
oudata.colour = {col.r/255.f, col.g/255.f, col.b/255.f, col.a/255.f};
}
}
oudata.diffuse = mat.diffuseIntensity;
oudata.ambient = mat.ambientIntensity;
}
uploadUBO(uboObject, oudata);
rendered++;
glDrawElements(model->geometries[g]->dbuff.getFaceType(),
subgeom.numIndices, GL_UNSIGNED_INT, (void*)(sizeof(uint32_t) * subgeom.start));
return true;
}
void GameRenderer::renderModel(Model* model, const glm::mat4& modelMatrix, GameObject* object, Animator *animator) void GameRenderer::renderModel(Model* model, const glm::mat4& modelMatrix, GameObject* object, Animator *animator)
{ {
renderFrame(model, model->frames[model->rootFrameIdx], modelMatrix, object, 1.f); renderFrame(model, model->frames[model->rootFrameIdx], modelMatrix, object, 1.f);
@ -1077,7 +959,7 @@ void GameRenderer::renderModel(Model* model, const glm::mat4& modelMatrix, GameO
void GameRenderer::renderPaths() void GameRenderer::renderPaths()
{ {
glActiveTexture(GL_TEXTURE0); /*glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, debugTex); glBindTexture(GL_TEXTURE_2D, debugTex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 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_WRAP_T, GL_REPEAT);
@ -1152,7 +1034,7 @@ void GameRenderer::renderPaths()
pedlines.clear(); pedlines.clear();
carlines.clear(); carlines.clear();
glBindVertexArray( 0 ); glBindVertexArray( 0 );*/
} }
void GameRenderer::renderLetterbox() void GameRenderer::renderLetterbox()

View File

@ -9,18 +9,38 @@ const char* WaterHQ::VertexShader = R"(
layout(location = 0) in vec2 position; layout(location = 0) in vec2 position;
out vec2 TexCoords; out vec2 TexCoords;
uniform float height;
layout(std140) uniform SceneData {
mat4 projection;
mat4 view;
vec4 ambient;
vec4 dynamic;
vec4 fogColor;
vec4 campos;
float fogStart;
float fogEnd;
};
layout(std140) uniform ObjectData {
mat4 model;
vec4 colour;
float diffusefac;
float ambientfac;
float visibility;
};
uniform float size; uniform float size;
uniform mat4 MVP;
uniform float time; uniform float time;
uniform vec2 worldP;
uniform vec2 waveParams; uniform vec2 waveParams;
void main() void main()
{ {
vec2 p = worldP + position * size; mat4 MVP = projection * view;
float waveHeight = (1.0+sin(time + (p.x + p.y) * waveParams.x)) * waveParams.y; vec4 vp = model * vec4(position * size, 0.0, 1.0);
vp.z = (1.0+sin(time + (vp.x + vp.y) * waveParams.x)) * waveParams.y;
TexCoords = position * 2.0; TexCoords = position * 2.0;
gl_Position = MVP * vec4(p, height + waveHeight, 1.0); gl_Position = MVP * vp;
})"; })";
const char* WaterHQ::FragmentShader = R"( const char* WaterHQ::FragmentShader = R"(
@ -36,14 +56,26 @@ void main() {
const char* Sky::VertexShader = R"( const char* Sky::VertexShader = R"(
#version 130 #version 130
in vec3 position; #extension GL_ARB_explicit_attrib_location : enable
uniform mat4 view; #extension GL_ARB_uniform_buffer_object : enable
uniform mat4 proj;
layout(std140) uniform SceneData {
mat4 projection;
mat4 view;
vec4 ambient;
vec4 dynamic;
vec4 fogColor;
vec4 campos;
float fogStart;
float fogEnd;
};
layout(location = 0) in vec3 position;
out vec3 Position; out vec3 Position;
uniform float Far;
void main() { void main() {
Position = position; Position = position;
vec4 viewsp = proj * mat4(mat3(view)) * vec4(position, 1.0); vec4 viewsp = projection * mat4(mat3(view)) * vec4(position, 1.0);
viewsp.z = viewsp.w - 0.000001; viewsp.z = viewsp.w - 0.000001;
gl_Position = viewsp; gl_Position = viewsp;
})"; })";
@ -67,7 +99,6 @@ const char* WorldObject::VertexShader = R"(
#version 130 #version 130
#extension GL_ARB_explicit_attrib_location : enable #extension GL_ARB_explicit_attrib_location : enable
#extension GL_ARB_uniform_buffer_object : enable #extension GL_ARB_uniform_buffer_object : enable
#extension GL_ARB_gpu_shader5 : enable
layout(location = 0) in vec3 position; layout(location = 0) in vec3 position;
layout(location = 1) in vec3 normal; layout(location = 1) in vec3 normal;
layout(location = 2) in vec4 _colour; layout(location = 2) in vec4 _colour;

View File

@ -0,0 +1,231 @@
#include <render/OpenGLRenderer.hpp>
#include <GL/glew.h>
#include <glm/gtc/type_ptr.hpp>
#include <sstream>
#include <iostream>
GLuint compileShader(GLenum type, const char *source)
{
GLuint shader = glCreateShader(type);
glShaderSource(shader, 1, &source, NULL);
glCompileShader(shader);
GLint status;
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
if( status != GL_TRUE ) {
std::cerr << "[OGL] Shader Compilation Failed" << std::endl;
}
GLint len;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &len);
if( len > 1 ) {
GLchar *buffer = new GLchar[len];
glGetShaderInfoLog(shader, len, NULL, buffer);
GLint sourceLen;
glGetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &sourceLen);
GLchar *sourceBuff = new GLchar[sourceLen];
glGetShaderSource(shader, sourceLen, nullptr, sourceBuff);
std::cerr << "[OGL] Shader InfoLog(" << shader << "):\n" << buffer << "\nSource:\n" << sourceBuff << std::endl;
delete[] buffer;
delete[] sourceBuff;
}
if (status != GL_TRUE) {
exit(1);
}
return shader;
}
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);
GLint status;
glGetProgramiv(prog, GL_LINK_STATUS, &status);
if( status != GL_TRUE ) {
std::cerr << "[OGL] Program Link Failed" << std::endl;
}
GLint len;
glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &len);
if( len > 1 ) {
GLchar *buffer = new GLchar[len];
glGetProgramInfoLog(prog, len, NULL, buffer);
std::cerr << "[OGL] Program InfoLog(" << prog << "):\n" << buffer << std::endl;
delete[] buffer;
}
if (status != GL_TRUE) {
exit(1);
}
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
return prog;
}
void OpenGLRenderer::useDrawBuffer(DrawBuffer* dbuff)
{
if( dbuff != currentDbuff )
{
glBindVertexArray(dbuff->getVAOName());
currentDbuff = dbuff;
}
}
void OpenGLRenderer::useTexture(GLuint tex)
{
if( tex != currentTexture )
{
glBindTexture(GL_TEXTURE_2D, tex);
currentTexture = tex;
}
}
void OpenGLRenderer::useProgram(Renderer::ShaderProgram* p)
{
if( p != currentProgram )
{
currentProgram = static_cast<OpenGLShaderProgram*>(p);
glUseProgram( currentProgram->getName() );
}
}
OpenGLRenderer::OpenGLRenderer()
: currentDbuff(nullptr), currentTexture(0), currentProgram(nullptr)
{
glGenBuffers(1, &UBOScene);
glGenBuffers(1, &UBOObject);
glBindBufferBase(GL_UNIFORM_BUFFER, 1, UBOScene);
glBindBufferBase(GL_UNIFORM_BUFFER, 2, UBOObject);
}
std::string OpenGLRenderer::getIDString() const
{
std::stringstream ss;
ss << "OpenGL Renderer";
ss << " Version: " << glGetString(GL_VERSION);
ss << " (GLSL " << glGetString(GL_SHADING_LANGUAGE_VERSION) << ")";
ss << " Vendor: " << glGetString(GL_VENDOR);
return ss.str();
}
Renderer::ShaderProgram* OpenGLRenderer::createShader(const std::string& vert, const std::string& frag)
{
return new OpenGLShaderProgram(
compileProgram(vert.c_str(), frag.c_str()));
}
void OpenGLRenderer::setProgramBlockBinding(Renderer::ShaderProgram* p, const std::string& name, GLint point)
{
OpenGLShaderProgram* glsh = static_cast<OpenGLShaderProgram*>(p);
auto ubi = glGetUniformBlockIndex(glsh->getName(), name.c_str());
glUniformBlockBinding(glsh->getName(), ubi, point);
}
void OpenGLRenderer::setUniformTexture(Renderer::ShaderProgram* p, const std::string& name, GLint tex)
{
useProgram(p);
glUniform1i(currentProgram->getUniformLocation(name), tex);
}
void OpenGLRenderer::setUniform(Renderer::ShaderProgram* p, const std::string& name, const glm::vec4& m)
{
useProgram(p);
glUniform4fv(currentProgram->getUniformLocation(name.c_str()), 1, glm::value_ptr(m));
}
void OpenGLRenderer::setUniform(Renderer::ShaderProgram* p, const std::string& name, const glm::vec3& m)
{
useProgram(p);
glUniform3fv(currentProgram->getUniformLocation(name.c_str()), 1, glm::value_ptr(m));
}
void OpenGLRenderer::setUniform(Renderer::ShaderProgram* p, const std::string& name, const glm::vec2& m)
{
useProgram(p);
glUniform2fv(currentProgram->getUniformLocation(name.c_str()), 1, glm::value_ptr(m));
}
void OpenGLRenderer::setUniform(Renderer::ShaderProgram* p, const std::string& name, float f)
{
glUniform1fv(currentProgram->getUniformLocation(name.c_str()), 1, &f);
}
void OpenGLRenderer::clear(const glm::vec4& colour, bool clearColour, bool clearDepth)
{
auto flags = 0;
if( clearColour ) {
flags |= GL_COLOR_BUFFER_BIT;
glClearColor(colour.r, colour.g, colour.b, colour.a);
}
if( clearDepth ) {
flags |= GL_DEPTH_BUFFER_BIT;
}
glClear(flags);
}
void OpenGLRenderer::setSceneParameters(const Renderer::SceneUniformData& data)
{
uploadUBO(UBOScene, data);
}
void OpenGLRenderer::draw(const glm::mat4& model, DrawBuffer* draw, const Renderer::DrawParameters& p)
{
useDrawBuffer(draw);
useTexture(p.texture);
ObjectUniformData oudata {
model,
glm::vec4(p.colour.r/255.f, p.colour.g/255.f, p.colour.b/255.f, 1.f),
1.f,
1.f,
p.colour.a/255.f
};
uploadUBO(UBOObject, oudata);
glDrawElements(draw->getFaceType(), p.count, GL_UNSIGNED_INT,
(void*) (sizeof(RenderIndex) * p.start));
}
void OpenGLRenderer::drawArrays(const glm::mat4& model, DrawBuffer* draw, const Renderer::DrawParameters& p)
{
useDrawBuffer(draw);
useTexture(p.texture);
ObjectUniformData oudata {
model,
glm::vec4(p.colour.r/255.f, p.colour.g/255.f, p.colour.b/255.f, 1.f),
1.f,
1.f,
p.colour.a/255.f
};
uploadUBO(UBOObject, oudata);
glDrawArrays(draw->getFaceType(), p.start, p.count);
}

View File

@ -185,7 +185,7 @@ void init(std::string gtapath)
gta->gameTime = 0.f; gta->gameTime = 0.f;
debugDrawer = new DebugDraw; debugDrawer = new DebugDraw;
debugDrawer->setShaderProgram(gta->renderer.worldProgram); //debugDrawer->setShaderProgram(gta->renderer.worldProgram);
debugDrawer->setDebugMode(btIDebugDraw::DBG_DrawWireframe); debugDrawer->setDebugMode(btIDebugDraw::DBG_DrawWireframe);
gta->dynamicsWorld->setDebugDrawer(debugDrawer); gta->dynamicsWorld->setDebugDrawer(debugDrawer);
@ -302,24 +302,24 @@ void render(float alpha)
case 0: break; case 0: break;
case 1: { case 1: {
glUseProgram(gta->renderer.worldProgram); //glUseProgram(gta->renderer.worldProgram);
gta->renderer.uploadUBO<ObjectUniformData>( /*gta->renderer.uploadUBO<ObjectUniformData>(
gta->renderer.uboObject, { gta->renderer.uboObject, {
glm::mat4(), glm::mat4(),
glm::vec4(1.f), glm::vec4(1.f),
1.f, 1.f 1.f, 1.f
}); });*/
gta->renderer.renderPaths(); gta->renderer.renderPaths();
break; break;
} }
case 2: { case 2: {
glUseProgram(gta->renderer.worldProgram); //glUseProgram(gta->renderer.worldProgram);
gta->renderer.uploadUBO<ObjectUniformData>( /*gta->renderer.uploadUBO<ObjectUniformData>(
gta->renderer.uboObject, { gta->renderer.uboObject, {
glm::mat4(), glm::mat4(),
glm::vec4(1.f), glm::vec4(1.f),
1.f, 1.f 1.f, 1.f
}); });*/
gta->dynamicsWorld->debugDrawWorld(); gta->dynamicsWorld->debugDrawWorld();
debugDrawer->drawAllLines(); debugDrawer->drawAllLines();

View File

@ -84,7 +84,7 @@ void ViewerWidget::paintGL()
glm::mat4 m; glm::mat4 m;
glUseProgram(r.worldProgram); //glUseProgram(r.worldProgram);
ViewCamera vc; ViewCamera vc;
@ -97,8 +97,8 @@ void ViewerWidget::paintGL()
glm::vec3 eye(sin(viewAngles.x) * cos(viewAngles.y), cos(viewAngles.x) * cos(viewAngles.y), sin(viewAngles.y)); glm::vec3 eye(sin(viewAngles.x) * cos(viewAngles.y), cos(viewAngles.x) * cos(viewAngles.y), sin(viewAngles.y));
glm::mat4 view = glm::lookAt(eye * viewDistance, glm::vec3(0.f, 0.f, 0.f), glm::vec3(0.f, 0.f, 1.f)); glm::mat4 view = glm::lookAt(eye * viewDistance, glm::vec3(0.f, 0.f, 0.f), glm::vec3(0.f, 0.f, 1.f));
r.uploadUBO<SceneUniformData>(r.uboScene, //r.uploadUBO<SceneUniformData>(r.uboScene,
{ proj, view, glm::vec4(1.f), glm::vec4(1.f), glm::vec4(1.f), glm::vec4(0.f), 90.f, vc.frustum.far }); //{ proj, view, glm::vec4(1.f), glm::vec4(1.f), glm::vec4(1.f), glm::vec4(0.f), 90.f, vc.frustum.far });
if( dummyObject->model->model ) { if( dummyObject->model->model ) {
gworld->renderer.renderModel(dummyObject->model->model, m, dummyObject); gworld->renderer.renderModel(dummyObject->model->model, m, dummyObject);