mirror of
https://github.com/rwengine/openrw.git
synced 2024-11-25 11:52:40 +01:00
Initial rendering refactor
This commit is contained in:
parent
4d78cacd84
commit
668848952b
@ -203,7 +203,7 @@ public:
|
||||
/**
|
||||
* The vehicle colour palettes
|
||||
*/
|
||||
std::vector<glm::vec3> vehicleColours;
|
||||
std::vector<glm::u8vec3> vehicleColours;
|
||||
|
||||
/**
|
||||
* The vehicle colours for each vehicle type
|
||||
|
@ -21,8 +21,8 @@ public:
|
||||
|
||||
VehicleDataHandle vehicle;
|
||||
VehicleInfoHandle info;
|
||||
glm::vec3 colourPrimary;
|
||||
glm::vec3 colourSecondary;
|
||||
glm::u8vec3 colourPrimary;
|
||||
glm::u8vec3 colourSecondary;
|
||||
|
||||
std::map<size_t, GameObject*> seatOccupants;
|
||||
|
||||
@ -44,8 +44,8 @@ public:
|
||||
ModelHandle* model,
|
||||
VehicleDataHandle data,
|
||||
VehicleInfoHandle info,
|
||||
const glm::vec3& prim,
|
||||
const glm::vec3& sec);
|
||||
const glm::u8vec3& prim,
|
||||
const glm::u8vec3& sec);
|
||||
|
||||
virtual ~VehicleObject();
|
||||
|
||||
|
@ -8,6 +8,8 @@
|
||||
|
||||
#include <render/ViewCamera.hpp>
|
||||
|
||||
#include <render/OpenGLRenderer.hpp>
|
||||
|
||||
class Model;
|
||||
class ModelFrame;
|
||||
class GameWorld;
|
||||
@ -24,6 +26,8 @@ class CutsceneObject;
|
||||
class Animator;
|
||||
class InventoryItem;
|
||||
|
||||
class Renderer;
|
||||
|
||||
/**
|
||||
* @brief Implements high level drawing logic and low level draw commands
|
||||
*
|
||||
@ -34,14 +38,17 @@ class GameRenderer
|
||||
{
|
||||
/** Pointer to the world instance */
|
||||
GameWorld* engine;
|
||||
|
||||
/** The low-level drawing interface to use */
|
||||
Renderer* renderer;
|
||||
|
||||
/** Data required to queue transparent objects for delayed rendering */
|
||||
/** Stores data for deferring transparent objects */
|
||||
struct RQueueEntry {
|
||||
Model* model;
|
||||
size_t g;
|
||||
size_t sg;
|
||||
glm::mat4 matrix;
|
||||
float opacity;
|
||||
Renderer::DrawParameters dp;
|
||||
GameObject* object;
|
||||
};
|
||||
|
||||
@ -55,19 +62,7 @@ class GameRenderer
|
||||
* @return True if the frame was drawn, false if it should be queued
|
||||
*/
|
||||
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 */
|
||||
std::vector<RQueueEntry> transparentDrawQueue;
|
||||
|
||||
@ -149,14 +144,10 @@ public:
|
||||
size_t geoms;
|
||||
|
||||
/** @todo Clean up all these shader program and location variables */
|
||||
GLuint worldProgram;
|
||||
GLint uniTexture;
|
||||
GLuint ubiScene, ubiObject;
|
||||
GLuint uboScene, uboObject;
|
||||
Renderer::ShaderProgram* worldProg;
|
||||
Renderer::ShaderProgram* skyProg;
|
||||
Renderer::ShaderProgram* waterProg;
|
||||
|
||||
GLuint skyProgram;
|
||||
GLuint waterProgram, waterMVP, waterHeight, waterTexture, waterSize, waterTime, waterPosition, waterWave;
|
||||
GLint skyUniView, skyUniProj, skyUniTop, skyUniBottom;
|
||||
GLuint particleProgram;
|
||||
|
||||
GLuint ssRectProgram;
|
||||
@ -164,6 +155,9 @@ public:
|
||||
|
||||
GLuint skydomeVBO, skydomeIBO, debugVBO;
|
||||
GLuint debugTex;
|
||||
|
||||
DrawBuffer skyDbuff;
|
||||
GeometryBuffer skyGbuff;
|
||||
|
||||
/**
|
||||
* Renders the world using the parameters of the passed Camera.
|
||||
@ -233,38 +227,6 @@ public:
|
||||
|
||||
/** Adds a particle to the rendering */
|
||||
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
|
||||
|
169
rwengine/include/render/OpenGLRenderer.hpp
Normal file
169
rwengine/include/render/OpenGLRenderer.hpp
Normal 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
|
@ -280,10 +280,10 @@ void GameData::loadCarcols(const std::string& path)
|
||||
std::stringstream ss(line);
|
||||
|
||||
if( std::getline(ss, r, ',') && std::getline(ss, g, ',') && std::getline(ss, b)) {
|
||||
vehicleColours.push_back(glm::vec3(
|
||||
atoi(r.c_str())/255.f,
|
||||
atoi(g.c_str())/255.f,
|
||||
atoi(b.c_str())/255.f
|
||||
vehicleColours.push_back(glm::u8vec3(
|
||||
atoi(r.c_str()),
|
||||
atoi(g.c_str()),
|
||||
atoi(b.c_str())
|
||||
));
|
||||
}
|
||||
}
|
||||
|
@ -116,6 +116,7 @@ bool GameWorld::load()
|
||||
void GameWorld::logInfo(const std::string& info)
|
||||
{
|
||||
log.push_back({LogEntry::Info, gameTime, info});
|
||||
std::cout << info << std::endl;
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
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)
|
||||
if(palit != gameData.vehiclePalettes.end() && palit->second.size() > 0 ) {
|
||||
std::uniform_int_distribution<int> uniform(0, palit->second.size()-1);
|
||||
|
@ -246,6 +246,7 @@ void LoaderDFF::readGeometry(Model *model, const RWBStream &stream)
|
||||
sizeof(uint32_t) * sg.numIndices,
|
||||
sg.indices.data());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void LoaderDFF::readMaterialList(Model *model, const RWBStream &stream)
|
||||
|
@ -7,7 +7,7 @@
|
||||
#include <render/Model.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),
|
||||
steerAngle(0.f), throttle(0.f), brake(0.f), handbrake(false),
|
||||
vehicle(data), info(info), colourPrimary(prim),
|
||||
|
@ -23,8 +23,6 @@
|
||||
#include <cmath>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
GLuint GameRenderer::currentUBO = 0;
|
||||
|
||||
const size_t skydomeSegments = 8, skydomeRows = 10;
|
||||
|
||||
struct WaterVertex {
|
||||
@ -69,16 +67,6 @@ struct ParticleVert {
|
||||
GeometryBuffer particleGeom;
|
||||
DrawBuffer particleDraw;
|
||||
|
||||
struct VertexP2 {
|
||||
static const AttributeList vertex_attributes() {
|
||||
return {
|
||||
{ATRS_Position, 2, sizeof(VertexP2), 0ul}
|
||||
};
|
||||
}
|
||||
|
||||
float x, y;
|
||||
};
|
||||
|
||||
std::vector<VertexP2> sspaceRect = {
|
||||
{-1.f, -1.f},
|
||||
{ 1.f, -1.f},
|
||||
@ -89,98 +77,18 @@ std::vector<VertexP2> sspaceRect = {
|
||||
GeometryBuffer ssRectGeom;
|
||||
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)
|
||||
: engine(engine), _renderAlpha(0.f)
|
||||
: engine(engine), renderer(new OpenGLRenderer), _renderAlpha(0.f)
|
||||
{
|
||||
worldProgram = compileProgram(GameShaders::WorldObject::VertexShader,
|
||||
GameShaders::WorldObject::FragmentShader);
|
||||
|
||||
uniTexture = glGetUniformLocation(worldProgram, "texture");
|
||||
ubiScene = glGetUniformBlockIndex(worldProgram, "SceneData");
|
||||
ubiObject = glGetUniformBlockIndex(worldProgram, "ObjectData");
|
||||
engine->logInfo("[DRAW] " + renderer->getIDString());
|
||||
|
||||
glGenBuffers(1, &uboScene);
|
||||
glGenBuffers(1, &uboObject);
|
||||
worldProg = renderer->createShader(
|
||||
GameShaders::WorldObject::VertexShader,
|
||||
GameShaders::WorldObject::FragmentShader);
|
||||
|
||||
glUniformBlockBinding(worldProgram, ubiScene, 1);
|
||||
glUniformBlockBinding(worldProgram, ubiObject, 2);
|
||||
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER, 1, uboScene);
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER, 2, uboObject);
|
||||
renderer->setUniformTexture(worldProg, "texture", 0);
|
||||
renderer->setProgramBlockBinding(worldProg, "SceneData", 1);
|
||||
renderer->setProgramBlockBinding(worldProg, "ObjectData", 2);
|
||||
|
||||
particleProgram = compileProgram(GameShaders::WorldObject::VertexShader,
|
||||
GameShaders::Particle::FragmentShader);
|
||||
@ -189,27 +97,23 @@ GameRenderer::GameRenderer(GameWorld* engine)
|
||||
ubiScene = glGetUniformBlockIndex(particleProgram, "SceneData");
|
||||
ubiObject = glGetUniformBlockIndex(particleProgram, "ObjectData");*/
|
||||
|
||||
glUniformBlockBinding(particleProgram, ubiScene, 1);
|
||||
glUniformBlockBinding(particleProgram, ubiObject, 2);
|
||||
//glUniformBlockBinding(particleProgram, ubiScene, 1);
|
||||
//glUniformBlockBinding(particleProgram, ubiObject, 2);
|
||||
|
||||
skyProgram = compileProgram(GameShaders::Sky::VertexShader,
|
||||
GameShaders::Sky::FragmentShader);
|
||||
skyProg = renderer->createShader(
|
||||
GameShaders::Sky::VertexShader,
|
||||
GameShaders::Sky::FragmentShader);
|
||||
|
||||
skyUniView = glGetUniformLocation(skyProgram, "view");
|
||||
skyUniProj = glGetUniformLocation(skyProgram, "proj");
|
||||
skyUniTop = glGetUniformLocation(skyProgram, "TopColor");
|
||||
skyUniBottom = glGetUniformLocation(skyProgram, "BottomColor");
|
||||
renderer->setProgramBlockBinding(skyProg, "SceneData", 1);
|
||||
|
||||
waterProgram = compileProgram(GameShaders::WaterHQ::VertexShader,
|
||||
GameShaders::WaterHQ::FragmentShader);
|
||||
waterProg = renderer->createShader(
|
||||
GameShaders::WaterHQ::VertexShader,
|
||||
GameShaders::WaterHQ::FragmentShader);
|
||||
|
||||
waterHeight = glGetUniformLocation(waterProgram, "height");
|
||||
waterTexture = glGetUniformLocation(waterProgram, "texture");
|
||||
waterSize = glGetUniformLocation(waterProgram, "size");
|
||||
waterMVP = glGetUniformLocation(waterProgram, "MVP");
|
||||
waterTime = glGetUniformLocation(waterProgram, "time");
|
||||
waterPosition = glGetUniformLocation(waterProgram, "worldP");
|
||||
waterWave = glGetUniformLocation(waterProgram, "waveParams");
|
||||
renderer->setUniformTexture(waterProg, "texture", 0);
|
||||
|
||||
renderer->setProgramBlockBinding(waterProg, "SceneData", 1);
|
||||
renderer->setProgramBlockBinding(waterProg, "ObjectData", 2);
|
||||
|
||||
glGenVertexArrays( 1, &vao );
|
||||
|
||||
@ -240,28 +144,29 @@ GameRenderer::GameRenderer(GameWorld* engine)
|
||||
waterHQDraw.setFaceType(GL_TRIANGLES);
|
||||
|
||||
|
||||
// And our skydome while we're at it.
|
||||
glGenBuffers(1, &skydomeVBO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, skydomeVBO);
|
||||
// Create the skydome
|
||||
|
||||
size_t segments = skydomeSegments, rows = skydomeRows;
|
||||
|
||||
float R = 1.f/(float)(rows-1);
|
||||
float S = 1.f/(float)(segments-1);
|
||||
std::vector<glm::vec3> skydomeBuff;
|
||||
skydomeBuff.resize(rows * segments);
|
||||
std::vector<VertexP3> skydomeVerts;
|
||||
skydomeVerts.resize(rows * segments);
|
||||
for( size_t r = 0, i = 0; r < rows; ++r) {
|
||||
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),
|
||||
sin(2.f * M_PI * s * S) * cos(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);
|
||||
GLushort skydomeIndBuff[rows*segments*6];
|
||||
GLuint skydomeIndBuff[rows*segments*6];
|
||||
for( size_t r = 0, i = 0; r < (rows-1); ++r ) {
|
||||
for( size_t s = 0; s < (segments-1); ++s ) {
|
||||
skydomeIndBuff[i++] = r * segments + s;
|
||||
@ -275,6 +180,8 @@ GameRenderer::GameRenderer(GameWorld* engine)
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, skydomeIBO);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(skydomeIndBuff), skydomeIndBuff, GL_STATIC_DRAW);
|
||||
|
||||
glBindVertexArray(0);
|
||||
|
||||
glGenBuffers(1, &debugVBO);
|
||||
glGenTextures(1, &debugTex);
|
||||
glGenVertexArrays(1, &debugVAO);
|
||||
@ -341,33 +248,31 @@ void GameRenderer::renderWorld(const ViewCamera &camera, float alpha)
|
||||
_camera.frustum.near = engine->state.cameraNear;
|
||||
_camera.frustum.far = weather.farClipping;
|
||||
|
||||
glUseProgram(worldProgram);
|
||||
|
||||
auto view = _camera.getView();
|
||||
auto proj = _camera.frustum.projection();
|
||||
|
||||
uploadUBO<SceneUniformData>(
|
||||
uboScene,
|
||||
{
|
||||
proj,
|
||||
view,
|
||||
glm::vec4{ambient, 0.0f},
|
||||
glm::vec4{dynamic, 0.0f},
|
||||
glm::vec4(skyBottom, 1.f),
|
||||
glm::vec4(camera.position, 0.f),
|
||||
weather.fogStart,
|
||||
camera.frustum.far
|
||||
});
|
||||
Renderer::SceneUniformData sceneParams {
|
||||
proj,
|
||||
view,
|
||||
glm::vec4{ambient, 0.0f},
|
||||
glm::vec4{dynamic, 0.0f},
|
||||
glm::vec4(skyBottom, 1.f),
|
||||
glm::vec4(camera.position, 0.f),
|
||||
weather.fogStart,
|
||||
camera.frustum.far
|
||||
};
|
||||
|
||||
renderer->setSceneParameters(sceneParams);
|
||||
|
||||
glClearColor(skyBottom.r, skyBottom.g, skyBottom.b, 1.f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
renderer->clear(glm::vec4(skyBottom, 1.f));
|
||||
|
||||
_camera.frustum.update(proj * view);
|
||||
|
||||
rendered = culled = geoms = frames = 0;
|
||||
|
||||
renderer->useProgram(worldProg);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glUniform1i(uniTexture, 0);
|
||||
|
||||
for( GameObject* object : engine->objects ) {
|
||||
switch(object->type()) {
|
||||
@ -398,36 +303,36 @@ void GameRenderer::renderWorld(const ViewCamera &camera, float alpha)
|
||||
it != transparentDrawQueue.end();
|
||||
++it)
|
||||
{
|
||||
glBindVertexArray(it->model->geometries[it->g]->dbuff.getVAOName());
|
||||
|
||||
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);
|
||||
renderer->draw(it->matrix, &it->model->geometries[it->g]->dbuff, it->dp);
|
||||
}
|
||||
transparentDrawQueue.clear();
|
||||
|
||||
// Draw the water.
|
||||
glUseProgram( waterProgram );
|
||||
|
||||
// TODO: Add some kind of draw distance
|
||||
renderer->useProgram( waterProg );
|
||||
|
||||
float blockLQSize = WATER_WORLD_SIZE/WATER_LQ_DATA_SIZE;
|
||||
float blockHQSize = WATER_WORLD_SIZE/WATER_HQ_DATA_SIZE;
|
||||
|
||||
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",""}];
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, waterTex.texName);
|
||||
|
||||
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
|
||||
glUniform1f(waterSize, blockHQSize);
|
||||
glUniform1f(waterTime, engine->gameTime);
|
||||
renderer->setUniform(waterProg, "size", blockHQSize);
|
||||
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 y = 0; y < WATER_HQ_DATA_SIZE; 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;
|
||||
float h = engine->gameData.waterHeights[hI];
|
||||
|
||||
glUniform1f(waterHeight, h);
|
||||
auto MVP = proj * view;
|
||||
glUniform2fv(waterPosition, 1, glm::value_ptr(waterWS));
|
||||
glUniformMatrix4fv(waterMVP, 1, GL_FALSE, glm::value_ptr(MVP));
|
||||
glDrawArrays(waterHQDraw.getFaceType(), 0, waterHQVerts.size());
|
||||
glm::mat4 m;
|
||||
m = glm::translate(m, glm::vec3(waterWS, h));
|
||||
|
||||
renderer->drawArrays(m, &waterHQDraw, wdp);
|
||||
}
|
||||
}
|
||||
|
||||
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 y = 0; y < WATER_LQ_DATA_SIZE; 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;
|
||||
float h = engine->gameData.waterHeights[hI];
|
||||
|
||||
glUniform1f(waterHeight, h);
|
||||
auto MVP = proj * view;
|
||||
glUniform2fv(waterPosition, 1, glm::value_ptr(waterWS));
|
||||
glUniformMatrix4fv(waterMVP, 1, GL_FALSE, glm::value_ptr(MVP));
|
||||
glDrawArrays(waterLQDraw.getFaceType(), 0, 4);
|
||||
glm::mat4 m;
|
||||
m = glm::translate(m, glm::vec3(waterWS, h));
|
||||
|
||||
renderer->drawArrays(m, &waterLQDraw, wdp);
|
||||
}
|
||||
}
|
||||
|
||||
glBindVertexArray( vao );
|
||||
|
||||
glUseProgram(skyProgram);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, skydomeVBO);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, skydomeIBO);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
|
||||
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::DrawParameters dp;
|
||||
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->draw(glm::mat4(), &skyDbuff, dp);
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
if(opacity < 1.f || ! renderSubgeometry(model, g, sg, modelMatrix, opacity, object)) {
|
||||
// If rendering was rejected, queue for later.
|
||||
Model::SubGeometry& subgeom = model->geometries[g]->subgeom[sg];
|
||||
|
||||
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(
|
||||
{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 = glm::scale(glm::inverse(m), glm::vec3(part.size, 1.f));
|
||||
uploadUBO<ObjectUniformData>(
|
||||
/*uploadUBO<ObjectUniformData>(
|
||||
uboObject, {
|
||||
m,
|
||||
part.colour,
|
||||
1.f, 1.f, 1.f
|
||||
});
|
||||
});*/
|
||||
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
}
|
||||
@ -963,6 +916,7 @@ bool GameRenderer::renderFrame(Model* m, ModelFrame* f, const glm::mat4& matrix,
|
||||
{
|
||||
frames++;
|
||||
auto localmatrix = matrix;
|
||||
bool vis = true;
|
||||
|
||||
if(object && object->animator) {
|
||||
bool animFixed = false;
|
||||
@ -970,26 +924,26 @@ bool GameRenderer::renderFrame(Model* m, ModelFrame* f, const glm::mat4& matrix,
|
||||
animFixed = static_cast<CharacterObject*>(object)->isAnimationFixed();
|
||||
}
|
||||
localmatrix *= object->animator->getFrameMatrix(f, _renderAlpha, animFixed);
|
||||
|
||||
vis = object->animator->getFrameVisibility(f);
|
||||
}
|
||||
else {
|
||||
localmatrix *= f->getTransform();
|
||||
}
|
||||
|
||||
bool vis = (object == nullptr || object->animator == nullptr) ||
|
||||
object->animator->getFrameVisibility(f);
|
||||
if( vis ) {
|
||||
for(size_t g : f->getGeometries()) {
|
||||
RW::BSGeometryBounds& bounds = m->geometries[g]->geometryBounds;
|
||||
/// @todo fix culling animating objects?
|
||||
|
||||
for(size_t g : f->getGeometries()) {
|
||||
if(!vis ) continue;
|
||||
glm::vec3 boundpos = bounds.center + glm::vec3(matrix[3]);
|
||||
if(! _camera.frustum.intersects(boundpos, bounds.radius)) {
|
||||
culled++;
|
||||
continue;
|
||||
}
|
||||
|
||||
RW::BSGeometryBounds& bounds = m->geometries[g]->geometryBounds;
|
||||
/// @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);
|
||||
}
|
||||
|
||||
renderGeometry(m, g, localmatrix, opacity, object);
|
||||
}
|
||||
|
||||
for(ModelFrame* c : f->getChildren()) {
|
||||
@ -998,78 +952,6 @@ bool GameRenderer::renderFrame(Model* m, ModelFrame* f, const glm::mat4& matrix,
|
||||
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)
|
||||
{
|
||||
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()
|
||||
{
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
/*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);
|
||||
@ -1152,7 +1034,7 @@ void GameRenderer::renderPaths()
|
||||
|
||||
pedlines.clear();
|
||||
carlines.clear();
|
||||
glBindVertexArray( 0 );
|
||||
glBindVertexArray( 0 );*/
|
||||
}
|
||||
|
||||
void GameRenderer::renderLetterbox()
|
||||
|
@ -9,18 +9,38 @@ const char* WaterHQ::VertexShader = R"(
|
||||
|
||||
layout(location = 0) in vec2 position;
|
||||
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 mat4 MVP;
|
||||
|
||||
uniform float time;
|
||||
uniform vec2 worldP;
|
||||
uniform vec2 waveParams;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 p = worldP + position * size;
|
||||
float waveHeight = (1.0+sin(time + (p.x + p.y) * waveParams.x)) * waveParams.y;
|
||||
mat4 MVP = projection * view;
|
||||
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;
|
||||
gl_Position = MVP * vec4(p, height + waveHeight, 1.0);
|
||||
gl_Position = MVP * vp;
|
||||
})";
|
||||
|
||||
const char* WaterHQ::FragmentShader = R"(
|
||||
@ -36,14 +56,26 @@ void main() {
|
||||
|
||||
const char* Sky::VertexShader = R"(
|
||||
#version 130
|
||||
in vec3 position;
|
||||
uniform mat4 view;
|
||||
uniform mat4 proj;
|
||||
#extension GL_ARB_explicit_attrib_location : enable
|
||||
#extension GL_ARB_uniform_buffer_object : enable
|
||||
|
||||
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;
|
||||
uniform float Far;
|
||||
|
||||
void main() {
|
||||
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;
|
||||
gl_Position = viewsp;
|
||||
})";
|
||||
@ -67,7 +99,6 @@ const char* WorldObject::VertexShader = R"(
|
||||
#version 130
|
||||
#extension GL_ARB_explicit_attrib_location : enable
|
||||
#extension GL_ARB_uniform_buffer_object : enable
|
||||
#extension GL_ARB_gpu_shader5 : enable
|
||||
layout(location = 0) in vec3 position;
|
||||
layout(location = 1) in vec3 normal;
|
||||
layout(location = 2) in vec4 _colour;
|
||||
|
231
rwengine/src/render/OpenGLRenderer.cpp
Normal file
231
rwengine/src/render/OpenGLRenderer.cpp
Normal 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);
|
||||
}
|
@ -185,7 +185,7 @@ void init(std::string gtapath)
|
||||
gta->gameTime = 0.f;
|
||||
|
||||
debugDrawer = new DebugDraw;
|
||||
debugDrawer->setShaderProgram(gta->renderer.worldProgram);
|
||||
//debugDrawer->setShaderProgram(gta->renderer.worldProgram);
|
||||
debugDrawer->setDebugMode(btIDebugDraw::DBG_DrawWireframe);
|
||||
gta->dynamicsWorld->setDebugDrawer(debugDrawer);
|
||||
|
||||
@ -302,24 +302,24 @@ void render(float alpha)
|
||||
case 0: break;
|
||||
|
||||
case 1: {
|
||||
glUseProgram(gta->renderer.worldProgram);
|
||||
gta->renderer.uploadUBO<ObjectUniformData>(
|
||||
//glUseProgram(gta->renderer.worldProgram);
|
||||
/*gta->renderer.uploadUBO<ObjectUniformData>(
|
||||
gta->renderer.uboObject, {
|
||||
glm::mat4(),
|
||||
glm::vec4(1.f),
|
||||
1.f, 1.f
|
||||
});
|
||||
});*/
|
||||
gta->renderer.renderPaths();
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
glUseProgram(gta->renderer.worldProgram);
|
||||
gta->renderer.uploadUBO<ObjectUniformData>(
|
||||
//glUseProgram(gta->renderer.worldProgram);
|
||||
/*gta->renderer.uploadUBO<ObjectUniformData>(
|
||||
gta->renderer.uboObject, {
|
||||
glm::mat4(),
|
||||
glm::vec4(1.f),
|
||||
1.f, 1.f
|
||||
});
|
||||
});*/
|
||||
gta->dynamicsWorld->debugDrawWorld();
|
||||
debugDrawer->drawAllLines();
|
||||
|
||||
|
@ -84,7 +84,7 @@ void ViewerWidget::paintGL()
|
||||
|
||||
glm::mat4 m;
|
||||
|
||||
glUseProgram(r.worldProgram);
|
||||
//glUseProgram(r.worldProgram);
|
||||
|
||||
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::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,
|
||||
{ proj, view, glm::vec4(1.f), glm::vec4(1.f), glm::vec4(1.f), glm::vec4(0.f), 90.f, vc.frustum.far });
|
||||
//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 });
|
||||
|
||||
if( dummyObject->model->model ) {
|
||||
gworld->renderer.renderModel(dummyObject->model->model, m, dummyObject);
|
||||
|
Loading…
Reference in New Issue
Block a user