mirror of
https://github.com/rwengine/openrw.git
synced 2024-11-07 03:12:36 +01:00
clang-format files in rwengine/src/render
This commit is contained in:
parent
1e4d7ea133
commit
e888d04303
@ -6,9 +6,7 @@
|
||||
|
||||
#include <iostream>
|
||||
|
||||
DebugDraw::DebugDraw()
|
||||
: shaderProgram(nullptr)
|
||||
{
|
||||
DebugDraw::DebugDraw() : shaderProgram(nullptr) {
|
||||
lineBuff = new GeometryBuffer;
|
||||
dbuff = new DrawBuffer;
|
||||
dbuff->setFaceType(GL_LINES);
|
||||
@ -18,41 +16,33 @@ DebugDraw::DebugDraw()
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
int img = 0xFFFFFFFF;
|
||||
glTexImage2D(
|
||||
GL_TEXTURE_2D, 0, GL_RGBA, 1, 1,
|
||||
0, GL_RGBA, GL_UNSIGNED_BYTE, &img
|
||||
);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
&img);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
maxlines = 0;
|
||||
}
|
||||
|
||||
DebugDraw::~DebugDraw()
|
||||
{
|
||||
DebugDraw::~DebugDraw() {
|
||||
delete dbuff;
|
||||
delete lineBuff;
|
||||
}
|
||||
|
||||
void DebugDraw::drawLine(const btVector3 &from, const btVector3 &to, const btVector3 &color)
|
||||
{
|
||||
void DebugDraw::drawLine(const btVector3 &from, const btVector3 &to,
|
||||
const btVector3 &color) {
|
||||
btVector3 c = color * 255;
|
||||
lines.push_back({
|
||||
glm::vec3(from.getX(), from.getY(), from.getZ()),
|
||||
glm::vec3(0.f),
|
||||
lines.push_back({glm::vec3(from.getX(), from.getY(), from.getZ()),
|
||||
glm::vec3(0.f), glm::vec2(0.f),
|
||||
glm::u8vec4(c.getX(), c.getY(), c.getZ(), 255)});
|
||||
lines.push_back({glm::vec3(to.getX(), to.getY(), to.getZ()), glm::vec3(0.f),
|
||||
glm::vec2(0.f),
|
||||
glm::u8vec4(c.getX(), c.getY(), c.getZ(), 255)
|
||||
});
|
||||
lines.push_back({
|
||||
glm::vec3(to.getX(), to.getY(), to.getZ()),
|
||||
glm::vec3(0.f),
|
||||
glm::vec2(0.f),
|
||||
glm::u8vec4(c.getX(), c.getY(), c.getZ(), 255)
|
||||
});
|
||||
glm::u8vec4(c.getX(), c.getY(), c.getZ(), 255)});
|
||||
}
|
||||
|
||||
void DebugDraw::drawContactPoint(const btVector3 &pointOnB, const btVector3 &normalOnB, btScalar distance, int lifeTime, const btVector3 &color)
|
||||
{
|
||||
void DebugDraw::drawContactPoint(const btVector3 &pointOnB,
|
||||
const btVector3 &normalOnB, btScalar distance,
|
||||
int lifeTime, const btVector3 &color) {
|
||||
RW_UNUSED(pointOnB);
|
||||
RW_UNUSED(normalOnB);
|
||||
RW_UNUSED(distance);
|
||||
@ -60,8 +50,7 @@ void DebugDraw::drawContactPoint(const btVector3 &pointOnB, const btVector3 &nor
|
||||
RW_UNUSED(color);
|
||||
}
|
||||
|
||||
void DebugDraw::flush(GameRenderer* renderer)
|
||||
{
|
||||
void DebugDraw::flush(GameRenderer *renderer) {
|
||||
if (lines.size() == 0) {
|
||||
return;
|
||||
}
|
||||
@ -91,23 +80,19 @@ void DebugDraw::flush(GameRenderer* renderer)
|
||||
lines.clear();
|
||||
}
|
||||
|
||||
void DebugDraw::reportErrorWarning(const char *warningString)
|
||||
{
|
||||
void DebugDraw::reportErrorWarning(const char *warningString) {
|
||||
std::cerr << warningString << std::endl;
|
||||
}
|
||||
|
||||
void DebugDraw::draw3dText(const btVector3 &location, const char *textString)
|
||||
{
|
||||
void DebugDraw::draw3dText(const btVector3 &location, const char *textString) {
|
||||
RW_UNUSED(location);
|
||||
std::cout << textString << std::endl;
|
||||
}
|
||||
|
||||
void DebugDraw::setDebugMode(int debugMode)
|
||||
{
|
||||
void DebugDraw::setDebugMode(int debugMode) {
|
||||
this->debugMode = debugMode;
|
||||
}
|
||||
|
||||
int DebugDraw::getDebugMode() const
|
||||
{
|
||||
int DebugDraw::getDebugMode() const {
|
||||
return debugMode;
|
||||
}
|
||||
|
@ -1,17 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include <LinearMath/btIDebugDraw.h>
|
||||
#include <render/GameRenderer.hpp>
|
||||
#include <data/Model.hpp>
|
||||
#include <render/GameRenderer.hpp>
|
||||
|
||||
class DebugDraw : public btIDebugDraw
|
||||
{
|
||||
class DebugDraw : public btIDebugDraw {
|
||||
public:
|
||||
DebugDraw();
|
||||
~DebugDraw();
|
||||
|
||||
void drawLine(const btVector3 &from, const btVector3 &to, const btVector3 &color);
|
||||
void drawContactPoint(const btVector3 &pointOnB, const btVector3 &normalOnB, btScalar distance, int lifeTime, const btVector3 &color);
|
||||
void drawLine(const btVector3 &from, const btVector3 &to,
|
||||
const btVector3 &color);
|
||||
void drawContactPoint(const btVector3 &pointOnB, const btVector3 &normalOnB,
|
||||
btScalar distance, int lifeTime,
|
||||
const btVector3 &color);
|
||||
void reportErrorWarning(const char *warningString);
|
||||
void draw3dText(const btVector3 &location, const char *textString);
|
||||
void setDebugMode(int debugMode);
|
||||
|
@ -1,14 +1,14 @@
|
||||
#include <render/GameRenderer.hpp>
|
||||
#include <engine/GameWorld.hpp>
|
||||
#include <data/Model.hpp>
|
||||
#include <engine/Animator.hpp>
|
||||
#include <engine/GameState.hpp>
|
||||
#include <data/Model.hpp>
|
||||
#include <engine/GameWorld.hpp>
|
||||
#include <render/GameRenderer.hpp>
|
||||
|
||||
#include <objects/CharacterObject.hpp>
|
||||
#include <objects/InstanceObject.hpp>
|
||||
#include <objects/VehicleObject.hpp>
|
||||
#include <objects/PickupObject.hpp>
|
||||
#include <objects/ProjectileObject.hpp>
|
||||
#include <objects/VehicleObject.hpp>
|
||||
|
||||
#include <ai/CharacterController.hpp>
|
||||
#include <data/ObjectData.hpp>
|
||||
@ -19,8 +19,8 @@
|
||||
#include <objects/CutsceneObject.hpp>
|
||||
#include <render/ObjectRenderer.hpp>
|
||||
|
||||
#include <render/GameShaders.hpp>
|
||||
#include <core/Logger.hpp>
|
||||
#include <render/GameShaders.hpp>
|
||||
|
||||
#include <deque>
|
||||
#include <glm/gtc/constants.hpp>
|
||||
@ -31,17 +31,14 @@
|
||||
|
||||
const size_t skydomeSegments = 8, skydomeRows = 10;
|
||||
constexpr uint32_t kMissingTextureBytes[] = {
|
||||
0xFF0000FF, 0xFFFF00FF, 0xFF0000FF, 0xFFFF00FF,
|
||||
0xFFFF00FF, 0xFF0000FF, 0xFFFF00FF, 0xFF0000FF,
|
||||
0xFF0000FF, 0xFFFF00FF, 0xFF0000FF, 0xFFFF00FF,
|
||||
0xFF0000FF, 0xFFFF00FF, 0xFF0000FF, 0xFFFF00FF, 0xFFFF00FF, 0xFF0000FF,
|
||||
0xFFFF00FF, 0xFF0000FF, 0xFF0000FF, 0xFFFF00FF, 0xFF0000FF, 0xFFFF00FF,
|
||||
0xFFFF00FF, 0xFF0000FF, 0xFFFF00FF, 0xFF0000FF,
|
||||
};
|
||||
|
||||
struct WaterVertex {
|
||||
static const AttributeList vertex_attributes() {
|
||||
return {
|
||||
{ATRS_Position, 2, sizeof(WaterVertex), 0ul}
|
||||
};
|
||||
return {{ATRS_Position, 2, sizeof(WaterVertex), 0ul}};
|
||||
}
|
||||
|
||||
float x, y;
|
||||
@ -50,11 +47,9 @@ struct WaterVertex {
|
||||
/// @todo collapse all of these into "VertPNC" etc.
|
||||
struct ParticleVert {
|
||||
static const AttributeList vertex_attributes() {
|
||||
return {
|
||||
{ATRS_Position, 2, sizeof(ParticleVert), 0ul},
|
||||
return {{ATRS_Position, 2, sizeof(ParticleVert), 0ul},
|
||||
{ATRS_TexCoord, 2, sizeof(ParticleVert), 2ul * sizeof(float)},
|
||||
{ATRS_Colour, 3, sizeof(ParticleVert), 4ul * sizeof(float)}
|
||||
};
|
||||
{ATRS_Colour, 3, sizeof(ParticleVert), 4ul * sizeof(float)}};
|
||||
}
|
||||
|
||||
float x, y;
|
||||
@ -66,10 +61,7 @@ GeometryBuffer particleGeom;
|
||||
DrawBuffer particleDraw;
|
||||
|
||||
std::vector<VertexP2> sspaceRect = {
|
||||
{-1.f, -1.f},
|
||||
{ 1.f, -1.f},
|
||||
{-1.f, 1.f},
|
||||
{ 1.f, 1.f},
|
||||
{-1.f, -1.f}, {1.f, -1.f}, {-1.f, 1.f}, {1.f, 1.f},
|
||||
};
|
||||
|
||||
GeometryBuffer ssRectGeom;
|
||||
@ -84,41 +76,40 @@ GameRenderer::GameRenderer(Logger* log, GameData* _data)
|
||||
, cullOverride(false)
|
||||
, map(renderer, _data)
|
||||
, water(this)
|
||||
, text(this)
|
||||
{
|
||||
, text(this) {
|
||||
logger->info("Renderer", renderer->getIDString());
|
||||
|
||||
worldProg = renderer->createShader(
|
||||
GameShaders::WorldObject::VertexShader,
|
||||
worldProg =
|
||||
renderer->createShader(GameShaders::WorldObject::VertexShader,
|
||||
GameShaders::WorldObject::FragmentShader);
|
||||
|
||||
renderer->setUniformTexture(worldProg, "texture", 0);
|
||||
renderer->setProgramBlockBinding(worldProg, "SceneData", 1);
|
||||
renderer->setProgramBlockBinding(worldProg, "ObjectData", 2);
|
||||
|
||||
particleProg = renderer->createShader(
|
||||
GameShaders::WorldObject::VertexShader,
|
||||
particleProg =
|
||||
renderer->createShader(GameShaders::WorldObject::VertexShader,
|
||||
GameShaders::Particle::FragmentShader);
|
||||
|
||||
renderer->setUniformTexture(particleProg, "texture", 0);
|
||||
renderer->setProgramBlockBinding(particleProg, "SceneData", 1);
|
||||
renderer->setProgramBlockBinding(particleProg, "ObjectData", 2);
|
||||
|
||||
skyProg = renderer->createShader(
|
||||
GameShaders::Sky::VertexShader,
|
||||
skyProg = renderer->createShader(GameShaders::Sky::VertexShader,
|
||||
GameShaders::Sky::FragmentShader);
|
||||
|
||||
renderer->setProgramBlockBinding(skyProg, "SceneData", 1);
|
||||
|
||||
postProg = renderer->createShader(
|
||||
GameShaders::DefaultPostProcess::VertexShader,
|
||||
postProg =
|
||||
renderer->createShader(GameShaders::DefaultPostProcess::VertexShader,
|
||||
GameShaders::DefaultPostProcess::FragmentShader);
|
||||
|
||||
glGenVertexArrays(1, &vao);
|
||||
|
||||
glGenTextures(1, &m_missingTexture);
|
||||
glBindTexture(GL_TEXTURE_2D, m_missingTexture);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, kMissingTextureBytes);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
kMissingTextureBytes);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
|
||||
@ -127,17 +118,21 @@ GameRenderer::GameRenderer(Logger* log, GameData* _data)
|
||||
glGenTextures(2, fbTextures);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, fbTextures[0]);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 128, 128, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 128, 128, 0, GL_RGBA,
|
||||
GL_UNSIGNED_BYTE, NULL);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, fbTextures[1]);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_R16F, 128, 128, 0, GL_RED, GL_FLOAT, NULL);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_R16F, 128, 128, 0, GL_RED, GL_FLOAT,
|
||||
NULL);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbTextures[0], 0);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, fbTextures[1], 0);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
|
||||
fbTextures[0], 0);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D,
|
||||
fbTextures[1], 0);
|
||||
|
||||
// Give water renderer the data texture
|
||||
water.setDataTexture(1, fbTextures[1]);
|
||||
@ -145,9 +140,8 @@ GameRenderer::GameRenderer(Logger* log, GameData* _data)
|
||||
glGenRenderbuffers(1, fbRenderBuffers);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, fbRenderBuffers[0]);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 128, 128);
|
||||
glFramebufferRenderbuffer(
|
||||
GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fbRenderBuffers[0]
|
||||
);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
|
||||
GL_RENDERBUFFER, fbRenderBuffers[0]);
|
||||
|
||||
// Create the skydome
|
||||
|
||||
@ -159,11 +153,12 @@ GameRenderer::GameRenderer(Logger* log, GameData* _data)
|
||||
skydomeVerts.resize(rows * segments);
|
||||
for (size_t r = 0, i = 0; r < rows; ++r) {
|
||||
for (size_t s = 0; s < segments; ++s) {
|
||||
skydomeVerts[i++].position = glm::vec3(
|
||||
cos(2.f * glm::pi<float>() * s * S) * cos(glm::half_pi<float>() * r * R),
|
||||
sin(2.f * glm::pi<float>() * s * S) * cos(glm::half_pi<float>() * r * R),
|
||||
sin(glm::half_pi<float>() * r * R)
|
||||
);
|
||||
skydomeVerts[i++].position =
|
||||
glm::vec3(cos(2.f * glm::pi<float>() * s * S) *
|
||||
cos(glm::half_pi<float>() * r * R),
|
||||
sin(2.f * glm::pi<float>() * s * S) *
|
||||
cos(glm::half_pi<float>() * r * R),
|
||||
sin(glm::half_pi<float>() * r * R));
|
||||
}
|
||||
}
|
||||
skyGbuff.uploadVertices(skydomeVerts);
|
||||
@ -184,7 +179,9 @@ GameRenderer::GameRenderer(Logger* log, GameData* _data)
|
||||
}
|
||||
}
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, skydomeIBO);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * skydomeIndBuff.size(), skydomeIndBuff.data(), GL_STATIC_DRAW);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER,
|
||||
sizeof(GLuint) * skydomeIndBuff.size(), skydomeIndBuff.data(),
|
||||
GL_STATIC_DRAW);
|
||||
|
||||
glBindVertexArray(0);
|
||||
|
||||
@ -193,12 +190,10 @@ GameRenderer::GameRenderer(Logger* log, GameData* _data)
|
||||
glGenVertexArrays(1, &debugVAO);
|
||||
|
||||
particleGeom.uploadVertices<ParticleVert>(
|
||||
{
|
||||
{ 0.5f, 0.5f, 1.f, 1.f, 1.f, 1.f, 1.f},
|
||||
{{0.5f, 0.5f, 1.f, 1.f, 1.f, 1.f, 1.f},
|
||||
{-0.5f, 0.5f, 0.f, 1.f, 1.f, 1.f, 1.f},
|
||||
{0.5f, -0.5f, 1.f, 0.f, 1.f, 1.f, 1.f},
|
||||
{-0.5f,-0.5f, 0.f, 0.f, 1.f, 1.f, 1.f}
|
||||
});
|
||||
{-0.5f, -0.5f, 0.f, 0.f, 1.f, 1.f, 1.f}});
|
||||
particleDraw.addGeometry(&particleGeom);
|
||||
particleDraw.setFaceType(GL_TRIANGLE_STRIP);
|
||||
|
||||
@ -206,7 +201,8 @@ GameRenderer::GameRenderer(Logger* log, GameData* _data)
|
||||
ssRectDraw.addGeometry(&ssRectGeom);
|
||||
ssRectDraw.setFaceType(GL_TRIANGLE_STRIP);
|
||||
|
||||
ssRectProgram = compileProgram(GameShaders::ScreenSpaceRect::VertexShader,
|
||||
ssRectProgram =
|
||||
compileProgram(GameShaders::ScreenSpaceRect::VertexShader,
|
||||
GameShaders::ScreenSpaceRect::FragmentShader);
|
||||
|
||||
ssRectTexture = glGetUniformLocation(ssRectProgram, "texture");
|
||||
@ -216,8 +212,7 @@ GameRenderer::GameRenderer(Logger* log, GameData* _data)
|
||||
|
||||
const static int cylsegments = 16;
|
||||
std::vector<Model::GeometryVertex> cylverts;
|
||||
for(int s = 0; s < cylsegments; ++s)
|
||||
{
|
||||
for (int s = 0; s < cylsegments; ++s) {
|
||||
float theta = (2.f * glm::pi<float>() / cylsegments) * (s + 0);
|
||||
float gamma = (2.f * glm::pi<float>() / cylsegments) * (s + 1);
|
||||
glm::vec2 p0(glm::sin(theta), glm::cos(theta));
|
||||
@ -226,31 +221,40 @@ GameRenderer::GameRenderer(Logger* log, GameData* _data)
|
||||
p0 *= 0.5f;
|
||||
p1 *= 0.5f;
|
||||
|
||||
cylverts.push_back({glm::vec3(p0, 2.f), glm::vec3(), glm::vec2(0.45f,0.6f), glm::u8vec4(255, 255, 255, 50)});
|
||||
cylverts.push_back({glm::vec3(p0,-1.f), glm::vec3(), glm::vec2(0.45f,0.4f), glm::u8vec4(255, 255, 255, 150)});
|
||||
cylverts.push_back({glm::vec3(p1, 2.f), glm::vec3(), glm::vec2(0.55f,0.6f), glm::u8vec4(255, 255, 255, 50)});
|
||||
cylverts.push_back({glm::vec3(p0, 2.f), glm::vec3(),
|
||||
glm::vec2(0.45f, 0.6f),
|
||||
glm::u8vec4(255, 255, 255, 50)});
|
||||
cylverts.push_back({glm::vec3(p0, -1.f), glm::vec3(),
|
||||
glm::vec2(0.45f, 0.4f),
|
||||
glm::u8vec4(255, 255, 255, 150)});
|
||||
cylverts.push_back({glm::vec3(p1, 2.f), glm::vec3(),
|
||||
glm::vec2(0.55f, 0.6f),
|
||||
glm::u8vec4(255, 255, 255, 50)});
|
||||
|
||||
cylverts.push_back({glm::vec3(p0,-1.f), glm::vec3(), glm::vec2(0.45f,0.4f), glm::u8vec4(255, 255, 255, 150)});
|
||||
cylverts.push_back({glm::vec3(p1,-1.f), glm::vec3(), glm::vec2(0.55f,0.4f), glm::u8vec4(255, 255, 255, 150)});
|
||||
cylverts.push_back({glm::vec3(p1, 2.f), glm::vec3(), glm::vec2(0.55f,0.6f), glm::u8vec4(255, 255, 255, 50)});
|
||||
cylverts.push_back({glm::vec3(p0, -1.f), glm::vec3(),
|
||||
glm::vec2(0.45f, 0.4f),
|
||||
glm::u8vec4(255, 255, 255, 150)});
|
||||
cylverts.push_back({glm::vec3(p1, -1.f), glm::vec3(),
|
||||
glm::vec2(0.55f, 0.4f),
|
||||
glm::u8vec4(255, 255, 255, 150)});
|
||||
cylverts.push_back({glm::vec3(p1, 2.f), glm::vec3(),
|
||||
glm::vec2(0.55f, 0.6f),
|
||||
glm::u8vec4(255, 255, 255, 50)});
|
||||
}
|
||||
cylinderGeometry.uploadVertices<Model::GeometryVertex>(cylverts);
|
||||
cylinderBuffer.addGeometry(&cylinderGeometry);
|
||||
cylinderBuffer.setFaceType(GL_TRIANGLES);
|
||||
}
|
||||
|
||||
GameRenderer::~GameRenderer()
|
||||
{
|
||||
GameRenderer::~GameRenderer() {
|
||||
glDeleteFramebuffers(1, &framebufferName);
|
||||
}
|
||||
|
||||
float mix(uint8_t a, uint8_t b, float num)
|
||||
{
|
||||
float mix(uint8_t a, uint8_t b, float num) {
|
||||
return a + (b - a) * num;
|
||||
}
|
||||
|
||||
void GameRenderer::setupRender()
|
||||
{
|
||||
void GameRenderer::setupRender() {
|
||||
// Set the viewport
|
||||
const glm::ivec2& vp = getRenderer()->getViewport();
|
||||
glViewport(0, 0, vp.x, vp.y);
|
||||
@ -258,8 +262,8 @@ void GameRenderer::setupRender()
|
||||
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
|
||||
}
|
||||
|
||||
void GameRenderer::renderWorld(GameWorld* world, const ViewCamera &camera, float alpha)
|
||||
{
|
||||
void GameRenderer::renderWorld(GameWorld* world, const ViewCamera& camera,
|
||||
float alpha) {
|
||||
_renderAlpha = alpha;
|
||||
_renderWorld = world;
|
||||
|
||||
@ -273,7 +277,8 @@ void GameRenderer::renderWorld(GameWorld* world, const ViewCamera &camera, float
|
||||
float tod = world->getHour() + world->getMinute() / 60.f;
|
||||
|
||||
// Requires a float 0-24
|
||||
auto weatherID = static_cast<WeatherLoader::WeatherCondition>(world->state->basic.nextWeather * 24);
|
||||
auto weatherID = static_cast<WeatherLoader::WeatherCondition>(
|
||||
world->state->basic.nextWeather * 24);
|
||||
auto weather = world->data->weatherLoader.getWeatherData(weatherID, tod);
|
||||
|
||||
glm::vec3 skyTop = weather.skyTopColor;
|
||||
@ -283,9 +288,7 @@ void GameRenderer::renderWorld(GameWorld* world, const ViewCamera &camera, float
|
||||
|
||||
float theta = (tod / (60.f * 24.f) - 0.5f) * 2 * 3.14159265;
|
||||
glm::vec3 sunDirection{
|
||||
sin(theta),
|
||||
0.0,
|
||||
cos(theta),
|
||||
sin(theta), 0.0, cos(theta),
|
||||
};
|
||||
sunDirection = glm::normalize(sunDirection);
|
||||
|
||||
@ -295,26 +298,23 @@ void GameRenderer::renderWorld(GameWorld* world, const ViewCamera &camera, float
|
||||
auto view = _camera.getView();
|
||||
auto proj = _camera.frustum.projection();
|
||||
|
||||
Renderer::SceneUniformData sceneParams {
|
||||
proj,
|
||||
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
|
||||
};
|
||||
_camera.frustum.far};
|
||||
|
||||
renderer->setSceneParameters(sceneParams);
|
||||
|
||||
renderer->clear(glm::vec4(skyBottom, 1.f));
|
||||
|
||||
_camera.frustum.update(proj * view);
|
||||
if (cullOverride)
|
||||
{
|
||||
cullingCamera.frustum.update(
|
||||
cullingCamera.frustum.projection() * cullingCamera.getView());
|
||||
if (cullOverride) {
|
||||
cullingCamera.frustum.update(cullingCamera.frustum.projection() *
|
||||
cullingCamera.getView());
|
||||
}
|
||||
|
||||
culled = 0;
|
||||
@ -337,8 +337,7 @@ void GameRenderer::renderWorld(GameWorld* world, const ViewCamera &camera, float
|
||||
|
||||
ObjectRenderer objectRenderer(_renderWorld,
|
||||
(cullOverride ? cullingCamera : _camera),
|
||||
_renderAlpha,
|
||||
getMissingTexture());
|
||||
_renderAlpha, getMissingTexture());
|
||||
|
||||
// World Objects
|
||||
for (auto object : world->allObjects) {
|
||||
@ -369,12 +368,10 @@ void GameRenderer::renderWorld(GameWorld* world, const ViewCamera &camera, float
|
||||
|
||||
// Render arrows above anything that isn't radar only (or hidden)
|
||||
ModelRef& arrowModel = world->data->models["arrow"];
|
||||
if( arrowModel && arrowModel->resource )
|
||||
{
|
||||
if (arrowModel && arrowModel->resource) {
|
||||
auto arrowTex = world->data->textures[{"copblue", ""}];
|
||||
auto arrowFrame = arrowModel->resource->findFrame("arrow");
|
||||
for( auto& blip : world->state->radarBlips )
|
||||
{
|
||||
for (auto& blip : world->state->radarBlips) {
|
||||
auto dm = blip.second.display;
|
||||
if (dm == BlipData::Hide || dm == BlipData::RadarOnly) {
|
||||
continue;
|
||||
@ -382,21 +379,18 @@ void GameRenderer::renderWorld(GameWorld* world, const ViewCamera &camera, float
|
||||
|
||||
glm::mat4 model;
|
||||
|
||||
if( blip.second.target > 0 )
|
||||
{
|
||||
if (blip.second.target > 0) {
|
||||
auto object = world->getBlipTarget(blip.second);
|
||||
if( object )
|
||||
{
|
||||
if (object) {
|
||||
model = object->getTimeAdjustedTransform(_renderAlpha);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
model = glm::translate(model, blip.second.coord);
|
||||
}
|
||||
|
||||
float a = world->getGameTime() * glm::pi<float>();
|
||||
model = glm::translate( model, glm::vec3(0.f, 0.f, 2.5f + glm::sin( a ) * 0.5f) );
|
||||
model = glm::translate(
|
||||
model, glm::vec3(0.f, 0.f, 2.5f + glm::sin(a) * 0.5f));
|
||||
model = glm::rotate(model, a, glm::vec3(0.f, 0.f, 1.f));
|
||||
model = glm::scale(model, glm::vec3(1.5f, 1.5f, 1.5f));
|
||||
|
||||
@ -405,7 +399,8 @@ void GameRenderer::renderWorld(GameWorld* world, const ViewCamera &camera, float
|
||||
dp.ambient = 1.f;
|
||||
dp.colour = glm::u8vec4(255, 255, 255, 255);
|
||||
|
||||
auto geom = arrowModel->resource->geometries[arrowFrame->getGeometries()[0]];
|
||||
auto geom = arrowModel->resource
|
||||
->geometries[arrowFrame->getGeometries()[0]];
|
||||
Model::SubGeometry& sg = geom->subgeom[0];
|
||||
|
||||
dp.start = sg.start;
|
||||
@ -419,8 +414,7 @@ void GameRenderer::renderWorld(GameWorld* world, const ViewCamera &camera, float
|
||||
// Draw goal indicators
|
||||
glDepthMask(GL_FALSE);
|
||||
renderer->useProgram(particleProg);
|
||||
for(auto& i : world->getAreaIndicators())
|
||||
{
|
||||
for (auto& i : world->getAreaIndicators()) {
|
||||
renderAreaIndicator(&i);
|
||||
}
|
||||
glDepthMask(GL_TRUE);
|
||||
@ -457,13 +451,13 @@ void GameRenderer::renderWorld(GameWorld* world, const ViewCamera &camera, float
|
||||
auto fc = world->state->fadeColour;
|
||||
if ((fc.r + fc.g + fc.b) == 0 && world->state->currentSplash.size() > 0) {
|
||||
auto splash = world->data->findTexture(world->state->currentSplash);
|
||||
if ( splash )
|
||||
{
|
||||
if (splash) {
|
||||
splashTexName = splash->getName();
|
||||
}
|
||||
}
|
||||
|
||||
if( (world->state->isCinematic || world->state->currentCutscene ) && splashTexName != 0 ) {
|
||||
if ((world->state->isCinematic || world->state->currentCutscene) &&
|
||||
splashTexName != 0) {
|
||||
renderLetterbox();
|
||||
}
|
||||
|
||||
@ -478,8 +472,7 @@ void GameRenderer::renderWorld(GameWorld* world, const ViewCamera &camera, float
|
||||
if (splashTexName != 0) {
|
||||
glBindTexture(GL_TEXTURE_2D, splashTexName);
|
||||
fc = glm::u16vec3(0, 0, 0);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
@ -498,7 +491,8 @@ void GameRenderer::renderWorld(GameWorld* world, const ViewCamera &camera, float
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
}
|
||||
|
||||
if( (world->state->isCinematic || world->state->currentCutscene ) && splashTexName == 0 ) {
|
||||
if ((world->state->isCinematic || world->state->currentCutscene) &&
|
||||
splashTexName == 0) {
|
||||
renderLetterbox();
|
||||
}
|
||||
|
||||
@ -510,12 +504,12 @@ void GameRenderer::renderWorld(GameWorld* world, const ViewCamera &camera, float
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
void GameRenderer::renderPostProcess()
|
||||
{
|
||||
void GameRenderer::renderPostProcess() {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
glStencilMask(0xFF);
|
||||
glClearStencil(0x00);
|
||||
glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT |
|
||||
GL_STENCIL_BUFFER_BIT);
|
||||
|
||||
renderer->useProgram(postProg);
|
||||
|
||||
@ -527,10 +521,10 @@ void GameRenderer::renderPostProcess()
|
||||
renderer->drawArrays(glm::mat4(), &ssRectDraw, wdp);
|
||||
}
|
||||
|
||||
void GameRenderer::renderGeometry(Model* model, size_t g, const glm::mat4& modelMatrix, float opacity, GameObject* object)
|
||||
{
|
||||
for(size_t sg = 0; sg < model->geometries[g]->subgeom.size(); ++sg)
|
||||
{
|
||||
void GameRenderer::renderGeometry(Model* model, size_t g,
|
||||
const glm::mat4& modelMatrix, float opacity,
|
||||
GameObject* object) {
|
||||
for (size_t sg = 0; sg < model->geometries[g]->subgeom.size(); ++sg) {
|
||||
Model::SubGeometry& subgeom = model->geometries[g]->subgeom[sg];
|
||||
|
||||
Renderer::DrawParameters dp;
|
||||
@ -541,36 +535,38 @@ void GameRenderer::renderGeometry(Model* model, size_t g, const glm::mat4& model
|
||||
dp.textures = {0};
|
||||
|
||||
if (model->geometries[g]->materials.size() > subgeom.material) {
|
||||
Model::Material& mat = model->geometries[g]->materials[subgeom.material];
|
||||
Model::Material& mat =
|
||||
model->geometries[g]->materials[subgeom.material];
|
||||
|
||||
if (mat.textures.size() > 0) {
|
||||
auto tex = mat.textures[0].texture;
|
||||
if( ! tex )
|
||||
{
|
||||
if (!tex) {
|
||||
auto& tC = mat.textures[0].name;
|
||||
auto& tA = mat.textures[0].alphaName;
|
||||
tex = data->findTexture(tC, tA);
|
||||
if( ! tex )
|
||||
{
|
||||
//logger->warning("Renderer", "Missing texture: " + tC + " " + tA);
|
||||
if (!tex) {
|
||||
// logger->warning("Renderer", "Missing texture: " + tC
|
||||
// + " " + tA);
|
||||
}
|
||||
mat.textures[0].texture = tex;
|
||||
}
|
||||
if( tex )
|
||||
{
|
||||
if (tex) {
|
||||
dp.textures = {tex->getName()};
|
||||
}
|
||||
}
|
||||
|
||||
if( (model->geometries[g]->flags & RW::BSGeometry::ModuleMaterialColor) == RW::BSGeometry::ModuleMaterialColor) {
|
||||
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 ) {
|
||||
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 ) {
|
||||
} else if (dp.colour.r == 255 && dp.colour.g == 0 &&
|
||||
dp.colour.b == 175) {
|
||||
dp.colour = glm::u8vec4(vehicle->colourSecondary, 255);
|
||||
}
|
||||
}
|
||||
@ -587,11 +583,11 @@ void GameRenderer::renderGeometry(Model* model, size_t g, const glm::mat4& model
|
||||
}
|
||||
|
||||
#define GOAL_RINGS 3
|
||||
void GameRenderer::renderAreaIndicator(const AreaIndicatorInfo* info)
|
||||
{
|
||||
void GameRenderer::renderAreaIndicator(const AreaIndicatorInfo* info) {
|
||||
glm::mat4 m(1.f);
|
||||
m = glm::translate(m, info->position);
|
||||
glm::vec3 scale = info->radius + 0.15f * glm::sin(_renderWorld->getGameTime() * 5.f);
|
||||
glm::vec3 scale =
|
||||
info->radius + 0.15f * glm::sin(_renderWorld->getGameTime() * 5.f);
|
||||
|
||||
Renderer::DrawParameters dp;
|
||||
dp.textures = {data->findTexture("cloud1")->getName()};
|
||||
@ -601,30 +597,31 @@ void GameRenderer::renderAreaIndicator(const AreaIndicatorInfo* info)
|
||||
dp.count = cylinderGeometry.getCount();
|
||||
dp.diffuse = 1.f;
|
||||
|
||||
for(int i = 0; i < GOAL_RINGS; i++)
|
||||
{
|
||||
for (int i = 0; i < GOAL_RINGS; i++) {
|
||||
glm::mat4 mt = m;
|
||||
glm::vec3 final = scale * glm::pow(0.9f, i + 1.0f);
|
||||
mt = glm::scale(mt, glm::vec3(final.x, final.y, 1.0f + i * 0.1f));
|
||||
int reverse = (i % 2 ? 1 : -1);
|
||||
mt = glm::rotate(mt, reverse * _renderWorld->getGameTime() * 0.5f, glm::vec3(0.f, 0.f, 1.f) );
|
||||
mt = glm::rotate(mt, reverse * _renderWorld->getGameTime() * 0.5f,
|
||||
glm::vec3(0.f, 0.f, 1.f));
|
||||
|
||||
renderer->drawArrays(mt, &cylinderBuffer, dp);
|
||||
}
|
||||
}
|
||||
|
||||
void GameRenderer::renderEffects(GameWorld* world)
|
||||
{
|
||||
void GameRenderer::renderEffects(GameWorld* world) {
|
||||
renderer->useProgram(particleProg);
|
||||
|
||||
auto cpos = _camera.position;
|
||||
auto cfwd = glm::normalize(glm::inverse(_camera.rotation) * glm::vec3(0.f, 1.f, 0.f));
|
||||
auto cfwd = glm::normalize(glm::inverse(_camera.rotation) *
|
||||
glm::vec3(0.f, 1.f, 0.f));
|
||||
|
||||
auto& effects = world->effects;
|
||||
|
||||
std::sort(effects.begin(), effects.end(),
|
||||
[&](const VisualFX* a, const VisualFX* b) {
|
||||
return glm::distance( a->getPosition(), cpos ) > glm::distance( b->getPosition(), cpos );
|
||||
return glm::distance(a->getPosition(), cpos) >
|
||||
glm::distance(b->getPosition(), cpos);
|
||||
});
|
||||
|
||||
for (VisualFX* fx : effects) {
|
||||
@ -643,8 +640,7 @@ void GameRenderer::renderEffects(GameWorld* world)
|
||||
|
||||
if (particle.orientation == VisualFX::ParticleData::UpCamera) {
|
||||
ptc = glm::normalize(amp - (glm::dot(amp, cfwd)) * cfwd);
|
||||
}
|
||||
else if( particle.orientation == VisualFX::ParticleData::Camera ) {
|
||||
} else if (particle.orientation == VisualFX::ParticleData::Camera) {
|
||||
ptc = amp;
|
||||
}
|
||||
|
||||
@ -679,13 +675,11 @@ void GameRenderer::renderEffects(GameWorld* world)
|
||||
}
|
||||
}
|
||||
|
||||
void GameRenderer::drawOnScreenText()
|
||||
{
|
||||
void GameRenderer::drawOnScreenText() {
|
||||
/// @ TODO
|
||||
}
|
||||
|
||||
void GameRenderer::drawTexture(TextureData* texture, glm::vec4 extents)
|
||||
{
|
||||
void GameRenderer::drawTexture(TextureData* texture, glm::vec4 extents) {
|
||||
glUseProgram(ssRectProgram);
|
||||
|
||||
// Move into NDC
|
||||
@ -715,8 +709,7 @@ void GameRenderer::drawTexture(TextureData* texture, glm::vec4 extents)
|
||||
renderer->invalidate();
|
||||
}
|
||||
|
||||
void GameRenderer::drawColour(const glm::vec4& colour, glm::vec4 extents)
|
||||
{
|
||||
void GameRenderer::drawColour(const glm::vec4& colour, glm::vec4 extents) {
|
||||
glUseProgram(ssRectProgram);
|
||||
|
||||
// Move into NDC
|
||||
@ -746,8 +739,9 @@ void GameRenderer::drawColour(const glm::vec4& colour, glm::vec4 extents)
|
||||
renderer->invalidate();
|
||||
}
|
||||
|
||||
bool GameRenderer::renderFrame(Model* m, ModelFrame* f, const glm::mat4& matrix, GameObject* object, float opacity, bool queueTransparent)
|
||||
{
|
||||
bool GameRenderer::renderFrame(Model* m, ModelFrame* f, const glm::mat4& matrix,
|
||||
GameObject* object, float opacity,
|
||||
bool queueTransparent) {
|
||||
auto localmatrix = matrix;
|
||||
bool vis = true;
|
||||
|
||||
@ -756,15 +750,13 @@ bool GameRenderer::renderFrame(Model* m, ModelFrame* f, const glm::mat4& matrix,
|
||||
localmatrix *= object->skeleton->getMatrix(f);
|
||||
|
||||
vis = object->skeleton->getData(f->getIndex()).enabled;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
localmatrix *= f->getTransform();
|
||||
}
|
||||
|
||||
if (vis) {
|
||||
for (size_t g : f->getGeometries()) {
|
||||
if( !object || !object->animator )
|
||||
{
|
||||
if (!object || !object->animator) {
|
||||
RW::BSGeometryBounds& bounds = m->geometries[g]->geometryBounds;
|
||||
|
||||
glm::vec3 boundpos = bounds.center + glm::vec3(localmatrix[3]);
|
||||
@ -784,13 +776,13 @@ bool GameRenderer::renderFrame(Model* m, ModelFrame* f, const glm::mat4& matrix,
|
||||
return true;
|
||||
}
|
||||
|
||||
void GameRenderer::renderModel(Model* model, const glm::mat4& modelMatrix, GameObject* object)
|
||||
{
|
||||
renderFrame(model, model->frames[model->rootFrameIdx], modelMatrix, object, 1.f);
|
||||
void GameRenderer::renderModel(Model* model, const glm::mat4& modelMatrix,
|
||||
GameObject* object) {
|
||||
renderFrame(model, model->frames[model->rootFrameIdx], modelMatrix, object,
|
||||
1.f);
|
||||
}
|
||||
|
||||
void GameRenderer::renderPaths()
|
||||
{
|
||||
void GameRenderer::renderPaths() {
|
||||
/*glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, debugTex);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
@ -819,8 +811,10 @@ void GameRenderer::renderPaths()
|
||||
}
|
||||
}
|
||||
else {
|
||||
carlines.push_back(start->position-glm::vec3(start->size / 2.f, 0.f, 0.f));
|
||||
carlines.push_back(start->position+glm::vec3(start->size / 2.f, 0.f, 0.f));
|
||||
carlines.push_back(start->position-glm::vec3(start->size / 2.f, 0.f,
|
||||
0.f));
|
||||
carlines.push_back(start->position+glm::vec3(start->size / 2.f, 0.f,
|
||||
0.f));
|
||||
}
|
||||
|
||||
for( size_t c = 0; c < start->connections.size(); ++c ) {
|
||||
@ -842,7 +836,8 @@ void GameRenderer::renderPaths()
|
||||
glEnableVertexAttribArray(posAttrib);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, debugVBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * carlines.size(), &(carlines[0]), GL_STREAM_DRAW);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * carlines.size(),
|
||||
&(carlines[0]), GL_STREAM_DRAW);
|
||||
glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE, 0, 0);
|
||||
|
||||
float img[] = {1.f, 0.f, 0.f};
|
||||
@ -853,7 +848,8 @@ void GameRenderer::renderPaths()
|
||||
|
||||
glDrawArrays(GL_LINES, 0, carlines.size());
|
||||
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * pedlines.size(), &(pedlines[0]), GL_STREAM_DRAW);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * pedlines.size(),
|
||||
&(pedlines[0]), GL_STREAM_DRAW);
|
||||
glVertexAttribPointer(posAttrib, 3, GL_FLOAT, GL_FALSE, 0, 0);
|
||||
|
||||
float img2[] = {0.f, 1.f, 0.f};
|
||||
@ -869,8 +865,7 @@ void GameRenderer::renderPaths()
|
||||
glBindVertexArray( 0 );*/
|
||||
}
|
||||
|
||||
void GameRenderer::renderLetterbox()
|
||||
{
|
||||
void GameRenderer::renderLetterbox() {
|
||||
glUseProgram(ssRectProgram);
|
||||
const float cinematicExperienceSize = 0.15f;
|
||||
glUniform2f(ssRectOffset, 0.f, -1.f * (1.f - cinematicExperienceSize));
|
||||
@ -889,17 +884,17 @@ void GameRenderer::renderLetterbox()
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
}
|
||||
|
||||
void GameRenderer::setViewport(int w, int h)
|
||||
{
|
||||
void GameRenderer::setViewport(int w, int h) {
|
||||
auto& lastViewport = renderer->getViewport();
|
||||
if( lastViewport.x != w || lastViewport.y != h)
|
||||
{
|
||||
if (lastViewport.x != w || lastViewport.y != h) {
|
||||
renderer->setViewport({w, h});
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, fbTextures[0]);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB,
|
||||
GL_UNSIGNED_BYTE, NULL);
|
||||
glBindTexture(GL_TEXTURE_2D, fbTextures[1]);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_R16F, w, h, 0, GL_RED, GL_FLOAT, NULL);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_R16F, w, h, 0, GL_RED, GL_FLOAT,
|
||||
NULL);
|
||||
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, fbRenderBuffers[0]);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, w, h);
|
||||
|
@ -42,8 +42,7 @@ class Renderer;
|
||||
* Rendering of object types is handled by drawWorld, calling the respective
|
||||
* render function for each object.
|
||||
*/
|
||||
class GameRenderer
|
||||
{
|
||||
class GameRenderer {
|
||||
/** Game data to use for rendering */
|
||||
GameData* data;
|
||||
|
||||
@ -69,10 +68,13 @@ class GameRenderer
|
||||
* @param f
|
||||
* @param matrix
|
||||
* @param object
|
||||
* @param queueTransparent abort the draw if the frame contains transparent materials
|
||||
* @param queueTransparent abort the draw if the frame contains transparent
|
||||
* materials
|
||||
* @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);
|
||||
bool renderFrame(Model* m, ModelFrame* f, const glm::mat4& matrix,
|
||||
GameObject* object, float opacity,
|
||||
bool queueTransparent = true);
|
||||
|
||||
// Temporary variables used during rendering
|
||||
float _renderAlpha;
|
||||
@ -95,7 +97,6 @@ class GameRenderer
|
||||
GLuint m_missingTexture;
|
||||
|
||||
public:
|
||||
|
||||
GameRenderer(Logger* log, GameData* data);
|
||||
~GameRenderer();
|
||||
|
||||
@ -119,9 +120,13 @@ public:
|
||||
DrawBuffer cylinderBuffer;
|
||||
GeometryBuffer cylinderGeometry;
|
||||
|
||||
GameData* getData() const { return data; }
|
||||
GameData* getData() const {
|
||||
return data;
|
||||
}
|
||||
|
||||
GLuint getMissingTexture() const { return m_missingTexture; }
|
||||
GLuint getMissingTexture() const {
|
||||
return m_missingTexture;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the world using the parameters of the passed Camera.
|
||||
@ -153,9 +158,11 @@ public:
|
||||
/**
|
||||
* Renders a model (who'd have thought)
|
||||
*/
|
||||
void renderModel(Model*, const glm::mat4& modelMatrix, GameObject* = nullptr);
|
||||
void renderModel(Model*, const glm::mat4& modelMatrix,
|
||||
GameObject* = nullptr);
|
||||
|
||||
void renderGeometry(Model*, size_t geom, const glm::mat4& modelMatrix, float opacity, GameObject* = nullptr);
|
||||
void renderGeometry(Model*, size_t geom, const glm::mat4& modelMatrix,
|
||||
float opacity, GameObject* = nullptr);
|
||||
|
||||
/** Renders the area indicator */
|
||||
void renderAreaIndicator(const AreaIndicatorInfo* info);
|
||||
@ -169,15 +176,13 @@ public:
|
||||
void setupRender();
|
||||
void renderPostProcess();
|
||||
|
||||
Renderer* getRenderer()
|
||||
{
|
||||
Renderer* getRenderer() {
|
||||
return renderer;
|
||||
}
|
||||
|
||||
void setViewport(int w, int h);
|
||||
|
||||
void setCullOverride(bool override, const ViewCamera& cullCamera)
|
||||
{
|
||||
void setCullOverride(bool override, const ViewCamera& cullCamera) {
|
||||
cullingCamera = cullCamera;
|
||||
cullOverride = override;
|
||||
}
|
||||
|
@ -268,7 +268,6 @@ void main()
|
||||
outColour = c * tint;
|
||||
})";
|
||||
|
||||
|
||||
const char* ScreenSpaceRect::VertexShader = R"(
|
||||
#version 330
|
||||
|
||||
@ -325,5 +324,4 @@ void main()
|
||||
vec4 c = texture(colour, TexCoords);
|
||||
outColour = c;
|
||||
})";
|
||||
|
||||
}
|
||||
|
@ -49,7 +49,6 @@ struct ScreenSpaceRect {
|
||||
};
|
||||
|
||||
SHADER_VF(DefaultPostProcess);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,10 +1,10 @@
|
||||
#include <render/MapRenderer.hpp>
|
||||
#include <render/GameShaders.hpp>
|
||||
#include <engine/GameWorld.hpp>
|
||||
#include <ai/PlayerController.hpp>
|
||||
#include <engine/GameData.hpp>
|
||||
#include <engine/GameState.hpp>
|
||||
#include <ai/PlayerController.hpp>
|
||||
#include <engine/GameWorld.hpp>
|
||||
#include <objects/CharacterObject.hpp>
|
||||
#include <render/GameShaders.hpp>
|
||||
#include <render/MapRenderer.hpp>
|
||||
|
||||
const char* MapVertexShader = R"(
|
||||
#version 330
|
||||
@ -37,43 +37,32 @@ void main()
|
||||
outColour = vec4(colour.rgb + c.rgb, colour.a * c.a);
|
||||
})";
|
||||
|
||||
|
||||
MapRenderer::MapRenderer(Renderer* renderer, GameData* _data)
|
||||
: data(_data), renderer(renderer)
|
||||
{
|
||||
rectGeom.uploadVertices<VertexP2>({
|
||||
{-.5f, -.5f},
|
||||
{ .5f, -.5f},
|
||||
{ .5f, .5f},
|
||||
{-.5f, .5f}
|
||||
});
|
||||
: data(_data), renderer(renderer) {
|
||||
rectGeom.uploadVertices<VertexP2>(
|
||||
{{-.5f, -.5f}, {.5f, -.5f}, {.5f, .5f}, {-.5f, .5f}});
|
||||
rect.addGeometry(&rectGeom);
|
||||
rect.setFaceType(GL_TRIANGLE_FAN);
|
||||
|
||||
std::vector<VertexP2> circleVerts;
|
||||
circleVerts.push_back({0.f, 0.f});
|
||||
for (int v = 0; v < 181; ++v) {
|
||||
circleVerts.push_back({
|
||||
0.5f * glm::cos(2*(v/180.f)*glm::pi<float>()),
|
||||
0.5f * glm::sin(2*(v/180.f)*glm::pi<float>())
|
||||
});
|
||||
circleVerts.push_back(
|
||||
{0.5f * glm::cos(2 * (v / 180.f) * glm::pi<float>()),
|
||||
0.5f * glm::sin(2 * (v / 180.f) * glm::pi<float>())});
|
||||
}
|
||||
circleGeom.uploadVertices(circleVerts);
|
||||
circle.addGeometry(&circleGeom);
|
||||
circle.setFaceType(GL_TRIANGLE_FAN);
|
||||
|
||||
rectProg = renderer->createShader(
|
||||
MapVertexShader,
|
||||
MapFragmentShader
|
||||
);
|
||||
rectProg = renderer->createShader(MapVertexShader, MapFragmentShader);
|
||||
|
||||
renderer->setUniform(rectProg, "colour", glm::vec4(1.f));
|
||||
}
|
||||
|
||||
#define GAME_MAP_SIZE 4000
|
||||
|
||||
void MapRenderer::draw(GameWorld* world, const MapInfo& mi)
|
||||
{
|
||||
void MapRenderer::draw(GameWorld* world, const MapInfo& mi) {
|
||||
renderer->pushDebugGroup("Map");
|
||||
renderer->useProgram(rectProg);
|
||||
|
||||
@ -92,8 +81,7 @@ void MapRenderer::draw(GameWorld* world, const MapInfo& mi)
|
||||
|
||||
view = glm::translate(view, glm::vec3(mi.screenPosition, 0.f));
|
||||
|
||||
if (mi.clipToSize)
|
||||
{
|
||||
if (mi.clipToSize) {
|
||||
glBindVertexArray(circle.getVAOName());
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glm::mat4 circleView = glm::scale(view, glm::vec3(mi.screenSize));
|
||||
@ -110,7 +98,8 @@ void MapRenderer::draw(GameWorld* world, const MapInfo& mi)
|
||||
|
||||
view = glm::scale(view, glm::vec3(worldScale));
|
||||
view = glm::rotate(view, mi.rotation, glm::vec3(0.f, 0.f, 1.f));
|
||||
view = glm::translate(view, glm::vec3(glm::vec2(-1.f, 1.f) * mi.worldCenter, 0.f));
|
||||
view = glm::translate(
|
||||
view, glm::vec3(glm::vec2(-1.f, 1.f) * mi.worldCenter, 0.f));
|
||||
renderer->setUniform(rectProg, "view", view);
|
||||
|
||||
glBindVertexArray(rect.getVAOName());
|
||||
@ -123,8 +112,7 @@ void MapRenderer::draw(GameWorld* world, const MapInfo& mi)
|
||||
int initX = -(mapBlockLine / 2);
|
||||
int initY = -(mapBlockLine / 2);
|
||||
|
||||
for( int m = 0; m < MAP_BLOCK_SIZE; ++m )
|
||||
{
|
||||
for (int m = 0; m < MAP_BLOCK_SIZE; ++m) {
|
||||
std::string num = (m < 10 ? "0" : "");
|
||||
std::string name = "radar" + num + std::to_string(m);
|
||||
auto texture = world->data->textures[{name, ""}];
|
||||
@ -160,28 +148,23 @@ void MapRenderer::draw(GameWorld* world, const MapInfo& mi)
|
||||
renderer->setUniform(rectProg, "model", model);
|
||||
glBindTexture(GL_TEXTURE_2D, radarDisc->getName());
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);
|
||||
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE,
|
||||
GL_ZERO);
|
||||
}
|
||||
|
||||
// Draw the player blip
|
||||
auto player = world->pedestrianPool.find(world->state->playerObject);
|
||||
if( player )
|
||||
{
|
||||
if (player) {
|
||||
glm::vec2 plyblip(player->getPosition());
|
||||
float hdg = glm::roll(player->getRotation());
|
||||
drawBlip(
|
||||
plyblip, view, mi,
|
||||
"radar_centre", glm::vec4(0.0f, 0.0f, 0.0f, 1.0f), 18.0f, mi.rotation - hdg
|
||||
);
|
||||
drawBlip(plyblip, view, mi, "radar_centre",
|
||||
glm::vec4(0.0f, 0.0f, 0.0f, 1.0f), 18.0f, mi.rotation - hdg);
|
||||
}
|
||||
|
||||
drawBlip(
|
||||
mi.worldCenter + glm::vec2(0.f, mi.worldSize), view, mi,
|
||||
"radar_north", glm::vec4(0.0f, 0.0f, 0.0f, 1.0f), 24.f
|
||||
);
|
||||
drawBlip(mi.worldCenter + glm::vec2(0.f, mi.worldSize), view, mi,
|
||||
"radar_north", glm::vec4(0.0f, 0.0f, 0.0f, 1.0f), 24.f);
|
||||
|
||||
for(auto& radarBlip : world->state->radarBlips)
|
||||
{
|
||||
for (auto& radarBlip : world->state->radarBlips) {
|
||||
const auto& blip = radarBlip.second;
|
||||
|
||||
auto dm = blip.display;
|
||||
@ -190,20 +173,20 @@ void MapRenderer::draw(GameWorld* world, const MapInfo& mi)
|
||||
}
|
||||
|
||||
glm::vec2 blippos(blip.coord);
|
||||
if( blip.target > 0 )
|
||||
{
|
||||
if (blip.target > 0) {
|
||||
GameObject* object = world->getBlipTarget(blip);
|
||||
if( object )
|
||||
{
|
||||
if (object) {
|
||||
blippos = glm::vec2(object->getPosition());
|
||||
}
|
||||
}
|
||||
|
||||
const auto& texture = blip.texture;
|
||||
if (!texture.empty()) {
|
||||
drawBlip(blippos, view, mi, texture, glm::vec4(0.0f, 0.0f, 0.0f, 1.0f), 18.0f);
|
||||
drawBlip(blippos, view, mi, texture,
|
||||
glm::vec4(0.0f, 0.0f, 0.0f, 1.0f), 18.0f);
|
||||
} else {
|
||||
// Colours from http://www.gtamodding.com/wiki/0165 (colors not specific to that opcode!)
|
||||
// Colours from http://www.gtamodding.com/wiki/0165 (colors not
|
||||
// specific to that opcode!)
|
||||
uint32_t rgbaValue;
|
||||
switch (blip.colour) {
|
||||
case 0: // RED
|
||||
@ -232,8 +215,7 @@ void MapRenderer::draw(GameWorld* world, const MapInfo& mi)
|
||||
break;
|
||||
}
|
||||
|
||||
glm::vec4 colour(
|
||||
(rgbaValue >> 24) / 255.0f,
|
||||
glm::vec4 colour((rgbaValue >> 24) / 255.0f,
|
||||
((rgbaValue >> 16) & 0xFF) / 255.0f,
|
||||
((rgbaValue >> 8) & 0xFF) / 255.0f,
|
||||
1.0f // Note: Alpha is not controlled by blip
|
||||
@ -252,19 +234,21 @@ void MapRenderer::draw(GameWorld* world, const MapInfo& mi)
|
||||
renderer->popDebugGroup();
|
||||
}
|
||||
|
||||
void MapRenderer::prepareBlip(const glm::vec2& coord, const glm::mat4& view, const MapInfo& mi, const std::string& texture, glm::vec4 colour, float size, float heading)
|
||||
{
|
||||
void MapRenderer::prepareBlip(const glm::vec2& coord, const glm::mat4& view,
|
||||
const MapInfo& mi, const std::string& texture,
|
||||
glm::vec4 colour, float size, float heading) {
|
||||
glm::vec2 adjustedCoord = coord;
|
||||
if (mi.clipToSize)
|
||||
{
|
||||
if (mi.clipToSize) {
|
||||
float maxDist = mi.worldSize / 2.f;
|
||||
float centerDist = glm::distance(coord, mi.worldCenter);
|
||||
if (centerDist > maxDist) {
|
||||
adjustedCoord = mi.worldCenter + ((coord - mi.worldCenter)/centerDist)*maxDist;
|
||||
adjustedCoord = mi.worldCenter +
|
||||
((coord - mi.worldCenter) / centerDist) * maxDist;
|
||||
}
|
||||
}
|
||||
|
||||
glm::vec3 viewPos(view * glm::vec4(glm::vec2(1.f,-1.f)*adjustedCoord, 0.f, 1.f));
|
||||
glm::vec3 viewPos(
|
||||
view * glm::vec4(glm::vec2(1.f, -1.f) * adjustedCoord, 0.f, 1.f));
|
||||
glm::mat4 model;
|
||||
model = glm::translate(model, viewPos);
|
||||
model = glm::scale(model, glm::vec3(size));
|
||||
@ -272,8 +256,7 @@ void MapRenderer::prepareBlip(const glm::vec2& coord, const glm::mat4& view, con
|
||||
renderer->setUniform(rectProg, "model", model);
|
||||
|
||||
GLuint tex = 0;
|
||||
if ( !texture.empty() )
|
||||
{
|
||||
if (!texture.empty()) {
|
||||
auto sprite = data->findTexture(texture);
|
||||
tex = sprite->getName();
|
||||
}
|
||||
@ -284,13 +267,16 @@ void MapRenderer::prepareBlip(const glm::vec2& coord, const glm::mat4& view, con
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
}
|
||||
|
||||
void MapRenderer::drawBlip(const glm::vec2& coord, const glm::mat4& view, const MapInfo& mi, const std::string& texture, glm::vec4 colour, float size, float heading) {
|
||||
void MapRenderer::drawBlip(const glm::vec2& coord, const glm::mat4& view,
|
||||
const MapInfo& mi, const std::string& texture,
|
||||
glm::vec4 colour, float size, float heading) {
|
||||
prepareBlip(coord, view, mi, texture, colour, size, heading);
|
||||
glBindVertexArray(rect.getVAOName());
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
}
|
||||
|
||||
void MapRenderer::drawBlip(const glm::vec2& coord, const glm::mat4& view, const MapInfo& mi, glm::vec4 colour, float size) {
|
||||
void MapRenderer::drawBlip(const glm::vec2& coord, const glm::mat4& view,
|
||||
const MapInfo& mi, glm::vec4 colour, float size) {
|
||||
drawBlip(coord, view, mi, "", colour, size);
|
||||
// Draw outline
|
||||
renderer->setUniform(rectProg, "colour", glm::vec4(0.0f, 0.0f, 0.0f, 1.0f));
|
||||
|
@ -9,12 +9,9 @@ class GameWorld;
|
||||
/**
|
||||
* Utility class for rendering the world map, in the menu and radar.
|
||||
*/
|
||||
class MapRenderer
|
||||
{
|
||||
class MapRenderer {
|
||||
public:
|
||||
|
||||
struct MapInfo
|
||||
{
|
||||
struct MapInfo {
|
||||
/// World coordinate center
|
||||
glm::vec2 worldCenter;
|
||||
/// World units to fit on the map
|
||||
@ -45,7 +42,12 @@ private:
|
||||
|
||||
Renderer::ShaderProgram* rectProg;
|
||||
|
||||
void prepareBlip(const glm::vec2& coord, const glm::mat4& view, const MapInfo& mi, const std::string& texture, glm::vec4 colour, float size, float heading);
|
||||
void drawBlip(const glm::vec2& coord, const glm::mat4& view, const MapInfo& mi, const std::string& texture, glm::vec4 colour, float size, float heading = 0.0f);
|
||||
void drawBlip(const glm::vec2& coord, const glm::mat4& view, const MapInfo& mi, glm::vec4 colour, float size);
|
||||
void prepareBlip(const glm::vec2& coord, const glm::mat4& view,
|
||||
const MapInfo& mi, const std::string& texture,
|
||||
glm::vec4 colour, float size, float heading);
|
||||
void drawBlip(const glm::vec2& coord, const glm::mat4& view,
|
||||
const MapInfo& mi, const std::string& texture,
|
||||
glm::vec4 colour, float size, float heading = 0.0f);
|
||||
void drawBlip(const glm::vec2& coord, const glm::mat4& view,
|
||||
const MapInfo& mi, glm::vec4 colour, float size);
|
||||
};
|
||||
|
@ -1,19 +1,19 @@
|
||||
#include <render/ObjectRenderer.hpp>
|
||||
#include <data/Skeleton.hpp>
|
||||
#include <data/CutsceneData.hpp>
|
||||
#include <data/Model.hpp>
|
||||
#include <data/Skeleton.hpp>
|
||||
#include <engine/GameData.hpp>
|
||||
#include <engine/GameState.hpp>
|
||||
#include <data/CutsceneData.hpp>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
#include <render/ObjectRenderer.hpp>
|
||||
|
||||
// Objects that we know how to turn into renderlist entries
|
||||
#include <objects/InstanceObject.hpp>
|
||||
#include <objects/VehicleObject.hpp>
|
||||
#include <objects/CharacterObject.hpp>
|
||||
#include <objects/ProjectileObject.hpp>
|
||||
#include <objects/PickupObject.hpp>
|
||||
#include <objects/CutsceneObject.hpp>
|
||||
#include <items/InventoryItem.hpp>
|
||||
#include <objects/CharacterObject.hpp>
|
||||
#include <objects/CutsceneObject.hpp>
|
||||
#include <objects/InstanceObject.hpp>
|
||||
#include <objects/PickupObject.hpp>
|
||||
#include <objects/ProjectileObject.hpp>
|
||||
#include <objects/VehicleObject.hpp>
|
||||
#ifdef RW_WINDOWS
|
||||
#include <rw_mingw.hpp>
|
||||
#endif
|
||||
@ -25,22 +25,19 @@ constexpr float kVehicleDrawDistanceFactor = kDrawDistanceFactor;
|
||||
constexpr float kPedestrianDrawDistanceFactor = kDrawDistanceFactor;
|
||||
#endif
|
||||
|
||||
RenderKey createKey(bool transparent, float normalizedDepth, Renderer::Textures& textures)
|
||||
{
|
||||
return ((transparent?0x1:0x0) << 31)
|
||||
| uint32_t(0x7FFFFF * (transparent? 1.f - normalizedDepth : normalizedDepth)) << 8
|
||||
| uint8_t(0xFF & (textures.size() > 0 ? textures[0] : 0)) << 0;
|
||||
RenderKey createKey(bool transparent, float normalizedDepth,
|
||||
Renderer::Textures& textures) {
|
||||
return ((transparent ? 0x1 : 0x0) << 31) |
|
||||
uint32_t(0x7FFFFF *
|
||||
(transparent ? 1.f - normalizedDepth : normalizedDepth))
|
||||
<< 8 |
|
||||
uint8_t(0xFF & (textures.size() > 0 ? textures[0] : 0)) << 0;
|
||||
}
|
||||
|
||||
void ObjectRenderer::renderGeometry(Model* model,
|
||||
size_t g,
|
||||
const glm::mat4& modelMatrix,
|
||||
float opacity,
|
||||
GameObject* object,
|
||||
RenderList& outList)
|
||||
{
|
||||
for(size_t sg = 0; sg < model->geometries[g]->subgeom.size(); ++sg)
|
||||
{
|
||||
void ObjectRenderer::renderGeometry(Model* model, size_t g,
|
||||
const glm::mat4& modelMatrix, float opacity,
|
||||
GameObject* object, RenderList& outList) {
|
||||
for (size_t sg = 0; sg < model->geometries[g]->subgeom.size(); ++sg) {
|
||||
Model::SubGeometry& subgeom = model->geometries[g]->subgeom[sg];
|
||||
|
||||
bool isTransparent = false;
|
||||
@ -55,28 +52,28 @@ void ObjectRenderer::renderGeometry(Model* model,
|
||||
|
||||
if (object && object->type() == GameObject::Instance) {
|
||||
auto instance = static_cast<InstanceObject*>(object);
|
||||
dp.depthWrite = !(instance->object->flags & ObjectData::NO_ZBUFFER_WRITE);
|
||||
dp.depthWrite =
|
||||
!(instance->object->flags & ObjectData::NO_ZBUFFER_WRITE);
|
||||
}
|
||||
|
||||
if (model->geometries[g]->materials.size() > subgeom.material) {
|
||||
Model::Material& mat = model->geometries[g]->materials[subgeom.material];
|
||||
Model::Material& mat =
|
||||
model->geometries[g]->materials[subgeom.material];
|
||||
|
||||
if (mat.textures.size() > 0) {
|
||||
auto tex = mat.textures[0].texture;
|
||||
if( ! tex )
|
||||
{
|
||||
if (!tex) {
|
||||
auto& tC = mat.textures[0].name;
|
||||
auto& tA = mat.textures[0].alphaName;
|
||||
tex = m_world->data->findTexture(tC, tA);
|
||||
if( ! tex )
|
||||
{
|
||||
//logger->warning("Renderer", "Missing texture: " + tC + " " + tA);
|
||||
if (!tex) {
|
||||
// logger->warning("Renderer", "Missing texture: " + tC
|
||||
// + " " + tA);
|
||||
dp.textures = {m_errorTexture};
|
||||
}
|
||||
mat.textures[0].texture = tex;
|
||||
}
|
||||
if( tex )
|
||||
{
|
||||
if (tex) {
|
||||
if (tex->isTransparent()) {
|
||||
isTransparent = true;
|
||||
}
|
||||
@ -84,15 +81,18 @@ void ObjectRenderer::renderGeometry(Model* model,
|
||||
}
|
||||
}
|
||||
|
||||
if( (model->geometries[g]->flags & RW::BSGeometry::ModuleMaterialColor) == RW::BSGeometry::ModuleMaterialColor) {
|
||||
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 ) {
|
||||
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 ) {
|
||||
} else if (dp.colour.r == 255 && dp.colour.g == 0 &&
|
||||
dp.colour.b == 175) {
|
||||
dp.colour = glm::u8vec4(vehicle->colourSecondary, 255);
|
||||
}
|
||||
}
|
||||
@ -112,22 +112,16 @@ void ObjectRenderer::renderGeometry(Model* model,
|
||||
|
||||
glm::vec3 position(modelMatrix[3]);
|
||||
float distance = glm::length(m_camera.position - position);
|
||||
float depth = (distance - m_camera.frustum.near) / (m_camera.frustum.far - m_camera.frustum.near);
|
||||
float depth = (distance - m_camera.frustum.near) /
|
||||
(m_camera.frustum.far - m_camera.frustum.near);
|
||||
outList.emplace_back(
|
||||
createKey(isTransparent, depth * depth, dp.textures),
|
||||
modelMatrix,
|
||||
&model->geometries[g]->dbuff,
|
||||
dp
|
||||
);
|
||||
createKey(isTransparent, depth * depth, dp.textures), modelMatrix,
|
||||
&model->geometries[g]->dbuff, dp);
|
||||
}
|
||||
}
|
||||
bool ObjectRenderer::renderFrame(Model* m,
|
||||
ModelFrame* f,
|
||||
const glm::mat4& matrix,
|
||||
GameObject* object,
|
||||
float opacity,
|
||||
RenderList& outList)
|
||||
{
|
||||
bool ObjectRenderer::renderFrame(Model* m, ModelFrame* f,
|
||||
const glm::mat4& matrix, GameObject* object,
|
||||
float opacity, RenderList& outList) {
|
||||
auto localmatrix = matrix;
|
||||
bool vis = true;
|
||||
|
||||
@ -136,15 +130,13 @@ bool ObjectRenderer::renderFrame(Model* m,
|
||||
localmatrix *= object->skeleton->getMatrix(f);
|
||||
|
||||
vis = object->skeleton->getData(f->getIndex()).enabled;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
localmatrix *= f->getTransform();
|
||||
}
|
||||
|
||||
if (vis) {
|
||||
for (size_t g : f->getGeometries()) {
|
||||
if( !object || !object->animator )
|
||||
{
|
||||
if (!object || !object->animator) {
|
||||
RW::BSGeometryBounds& bounds = m->geometries[g]->geometryBounds;
|
||||
|
||||
glm::vec3 boundpos = bounds.center + glm::vec3(localmatrix[3]);
|
||||
@ -165,32 +157,27 @@ bool ObjectRenderer::renderFrame(Model* m,
|
||||
|
||||
void ObjectRenderer::renderItem(InventoryItem* item,
|
||||
const glm::mat4& modelMatrix,
|
||||
RenderList& outList)
|
||||
{
|
||||
RenderList& outList) {
|
||||
// srhand
|
||||
if (item->getModelID() == -1) {
|
||||
return; // No model for this item
|
||||
}
|
||||
|
||||
std::shared_ptr<ObjectData> odata = m_world->data->findObjectType<ObjectData>(item->getModelID());
|
||||
std::shared_ptr<ObjectData> odata =
|
||||
m_world->data->findObjectType<ObjectData>(item->getModelID());
|
||||
auto weapons = m_world->data->models["weapons"];
|
||||
if (weapons && weapons->resource) {
|
||||
auto itemModel = weapons->resource->findFrame(odata->modelName + "_l0");
|
||||
auto matrix = glm::inverse(itemModel->getTransform());
|
||||
if (itemModel) {
|
||||
renderFrame(weapons->resource,
|
||||
itemModel,
|
||||
modelMatrix * matrix,
|
||||
nullptr,
|
||||
1.f,
|
||||
outList);
|
||||
renderFrame(weapons->resource, itemModel, modelMatrix * matrix,
|
||||
nullptr, 1.f, outList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectRenderer::renderInstance(InstanceObject* instance,
|
||||
RenderList& outList)
|
||||
{
|
||||
RenderList& outList) {
|
||||
if (!instance->model->resource) {
|
||||
return;
|
||||
}
|
||||
@ -200,28 +187,29 @@ void ObjectRenderer::renderInstance(InstanceObject *instance,
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Handles times provided by TOBJ data
|
||||
const auto currentHour = m_world->getHour();
|
||||
if (instance->object->timeOff < instance->object->timeOn)
|
||||
{
|
||||
if ( currentHour >= instance->object->timeOff && currentHour < instance->object->timeOn )
|
||||
if (instance->object->timeOff < instance->object->timeOn) {
|
||||
if (currentHour >= instance->object->timeOff &&
|
||||
currentHour < instance->object->timeOn)
|
||||
return;
|
||||
} else {
|
||||
if ( currentHour >= instance->object->timeOff || currentHour < instance->object->timeOn )
|
||||
if (currentHour >= instance->object->timeOff ||
|
||||
currentHour < instance->object->timeOn)
|
||||
return;
|
||||
}
|
||||
|
||||
auto matrixModel = instance->getTimeAdjustedTransform(m_renderAlpha);
|
||||
|
||||
float mindist = glm::length(instance->getPosition()-m_camera.position)
|
||||
- instance->model->resource->getBoundingRadius();
|
||||
float mindist = glm::length(instance->getPosition() - m_camera.position) -
|
||||
instance->model->resource->getBoundingRadius();
|
||||
mindist *= 1.f / kDrawDistanceFactor;
|
||||
|
||||
Model* model = nullptr;
|
||||
ModelFrame* frame = nullptr;
|
||||
|
||||
// These are used to gracefully fade out things that are just out of view distance.
|
||||
// These are used to gracefully fade out things that are just out of view
|
||||
// distance.
|
||||
Model* fadingModel = nullptr;
|
||||
ModelFrame* fadingFrame = nullptr;
|
||||
auto fadingMatrix = matrixModel;
|
||||
@ -238,20 +226,18 @@ void ObjectRenderer::renderInstance(InstanceObject *instance,
|
||||
// Is the closest point greater than the *LOD* draw distance
|
||||
float LODrange = instance->LODinstance->object->drawDistance[0];
|
||||
if (mindist > LODrange) {
|
||||
}
|
||||
else if (instance->LODinstance->model->resource) {
|
||||
} else if (instance->LODinstance->model->resource) {
|
||||
// The model matrix needs to be for the LOD instead
|
||||
matrixModel = instance->LODinstance->getTimeAdjustedTransform(m_renderAlpha);
|
||||
matrixModel =
|
||||
instance->LODinstance->getTimeAdjustedTransform(
|
||||
m_renderAlpha);
|
||||
// If the object is only just out of range, keep
|
||||
// rendering it and screen-door the LOD.
|
||||
if (overlap < fadeRange)
|
||||
{
|
||||
if (overlap < fadeRange) {
|
||||
model = instance->LODinstance->model->resource;
|
||||
fadingModel = instance->model->resource;
|
||||
opacity = 1.f - (overlap / fadeRange);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
model = instance->LODinstance->model->resource;
|
||||
}
|
||||
}
|
||||
@ -266,8 +252,7 @@ void ObjectRenderer::renderInstance(InstanceObject *instance,
|
||||
else if (!instance->object->LOD) {
|
||||
model = instance->model->resource;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
auto root = instance->model->resource->frames[0];
|
||||
auto objectModel = instance->model->resource;
|
||||
fadingFrame = nullptr;
|
||||
@ -275,17 +260,14 @@ void ObjectRenderer::renderInstance(InstanceObject *instance,
|
||||
|
||||
matrixModel *= root->getTransform();
|
||||
|
||||
for (int i = 0; i < instance->object->numClumps-1; ++i)
|
||||
{
|
||||
for (int i = 0; i < instance->object->numClumps - 1; ++i) {
|
||||
auto ind = (instance->object->numClumps - 1) - i;
|
||||
float lodDistance = instance->object->drawDistance[i];
|
||||
if (mindist > lodDistance) {
|
||||
fadingFrame = root->getChildren()[ind];
|
||||
fadingModel = objectModel;
|
||||
opacity = 1.f - ((mindist - lodDistance) / fadeRange);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
model = objectModel;
|
||||
frame = root->getChildren()[ind];
|
||||
}
|
||||
@ -294,49 +276,39 @@ void ObjectRenderer::renderInstance(InstanceObject *instance,
|
||||
|
||||
if (model) {
|
||||
frame = frame ? frame : model->frames[0];
|
||||
renderFrame(model,
|
||||
frame,
|
||||
matrixModel * glm::inverse(frame->getTransform()),
|
||||
instance,
|
||||
1.f,
|
||||
outList);
|
||||
renderFrame(model, frame,
|
||||
matrixModel * glm::inverse(frame->getTransform()), instance,
|
||||
1.f, outList);
|
||||
}
|
||||
if (fadingModel) {
|
||||
if (opacity >= 0.01f) {
|
||||
fadingFrame = fadingFrame ? fadingFrame : fadingModel->frames[0];
|
||||
renderFrame(fadingModel,
|
||||
fadingFrame,
|
||||
renderFrame(
|
||||
fadingModel, fadingFrame,
|
||||
fadingMatrix * glm::inverse(fadingFrame->getTransform()),
|
||||
instance,
|
||||
opacity,
|
||||
outList);
|
||||
instance, opacity, outList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectRenderer::renderCharacter(CharacterObject* pedestrian,
|
||||
RenderList& outList)
|
||||
{
|
||||
RenderList& outList) {
|
||||
glm::mat4 matrixModel;
|
||||
|
||||
if (pedestrian->getCurrentVehicle())
|
||||
{
|
||||
if (pedestrian->getCurrentVehicle()) {
|
||||
auto vehicle = pedestrian->getCurrentVehicle();
|
||||
auto seat = pedestrian->getCurrentSeat();
|
||||
matrixModel = vehicle->getTimeAdjustedTransform(m_renderAlpha);
|
||||
if (pedestrian->isEnteringOrExitingVehicle())
|
||||
{
|
||||
matrixModel = glm::translate(matrixModel, vehicle->getSeatEntryPosition(seat));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pedestrian->isEnteringOrExitingVehicle()) {
|
||||
matrixModel = glm::translate(matrixModel,
|
||||
vehicle->getSeatEntryPosition(seat));
|
||||
} else {
|
||||
if (seat < vehicle->info->seats.size()) {
|
||||
matrixModel = glm::translate(matrixModel, vehicle->info->seats[seat].offset);
|
||||
matrixModel = glm::translate(matrixModel,
|
||||
vehicle->info->seats[seat].offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
matrixModel = pedestrian->getTimeAdjustedTransform(m_renderAlpha);
|
||||
}
|
||||
|
||||
@ -344,37 +316,29 @@ void ObjectRenderer::renderCharacter(CharacterObject *pedestrian,
|
||||
|
||||
auto root = pedestrian->model->resource->frames[0];
|
||||
|
||||
renderFrame(pedestrian->model->resource,
|
||||
root->getChildren()[0],
|
||||
matrixModel,
|
||||
pedestrian,
|
||||
1.f,
|
||||
outList);
|
||||
renderFrame(pedestrian->model->resource, root->getChildren()[0],
|
||||
matrixModel, pedestrian, 1.f, outList);
|
||||
|
||||
if (pedestrian->getActiveItem()) {
|
||||
auto handFrame = pedestrian->model->resource->findFrame("srhand");
|
||||
glm::mat4 localMatrix;
|
||||
if (handFrame) {
|
||||
while (handFrame->getParent()) {
|
||||
localMatrix = pedestrian->skeleton->getMatrix(handFrame->getIndex()) * localMatrix;
|
||||
localMatrix =
|
||||
pedestrian->skeleton->getMatrix(handFrame->getIndex()) *
|
||||
localMatrix;
|
||||
handFrame = handFrame->getParent();
|
||||
}
|
||||
}
|
||||
renderItem(pedestrian->getActiveItem(),
|
||||
matrixModel * localMatrix,
|
||||
renderItem(pedestrian->getActiveItem(), matrixModel * localMatrix,
|
||||
outList);
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectRenderer::renderWheel(
|
||||
VehicleObject* vehicle,
|
||||
Model* model,
|
||||
void ObjectRenderer::renderWheel(VehicleObject* vehicle, Model* model,
|
||||
const glm::mat4& matrix,
|
||||
const std::string& name,
|
||||
RenderList& outList)
|
||||
{
|
||||
for (const ModelFrame* f : model->frames)
|
||||
{
|
||||
const std::string& name, RenderList& outList) {
|
||||
for (const ModelFrame* f : model->frames) {
|
||||
const std::string& fname = f->getName();
|
||||
if (fname != name) {
|
||||
continue;
|
||||
@ -384,7 +348,8 @@ void ObjectRenderer::renderWheel(
|
||||
|
||||
for (auto& g : firstLod->getGeometries()) {
|
||||
RW::BSGeometryBounds& bounds = model->geometries[g]->geometryBounds;
|
||||
if(! m_camera.frustum.intersects(bounds.center + glm::vec3(matrix[3]), bounds.radius)) {
|
||||
if (!m_camera.frustum.intersects(
|
||||
bounds.center + glm::vec3(matrix[3]), bounds.radius)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -395,8 +360,7 @@ void ObjectRenderer::renderWheel(
|
||||
}
|
||||
|
||||
void ObjectRenderer::renderVehicle(VehicleObject* vehicle,
|
||||
RenderList& outList)
|
||||
{
|
||||
RenderList& outList) {
|
||||
RW_CHECK(vehicle->model, "Vehicle model is null");
|
||||
|
||||
if (!vehicle->model) {
|
||||
@ -405,23 +369,21 @@ void ObjectRenderer::renderVehicle(VehicleObject *vehicle,
|
||||
|
||||
glm::mat4 matrixModel = vehicle->getTimeAdjustedTransform(m_renderAlpha);
|
||||
|
||||
renderFrame(vehicle->model->resource,
|
||||
vehicle->model->resource->frames[0],
|
||||
matrixModel,
|
||||
vehicle,
|
||||
1.f,
|
||||
outList);
|
||||
renderFrame(vehicle->model->resource, vehicle->model->resource->frames[0],
|
||||
matrixModel, vehicle, 1.f, outList);
|
||||
|
||||
// Draw wheels n' stuff
|
||||
for (size_t w = 0; w < vehicle->info->wheels.size(); ++w) {
|
||||
auto woi = m_world->data->findObjectType<ObjectData>(vehicle->vehicle->wheelModelID);
|
||||
auto woi = m_world->data->findObjectType<ObjectData>(
|
||||
vehicle->vehicle->wheelModelID);
|
||||
if (woi) {
|
||||
Model* wheelModel = m_world->data->models["wheels"]->resource;
|
||||
auto& wi = vehicle->physVehicle->getWheelInfo(w);
|
||||
if (wheelModel) {
|
||||
// Construct our own matrix so we can use the local transform
|
||||
vehicle->physVehicle->updateWheelTransform(w, false);
|
||||
/// @todo migrate this into Vehicle physics tick so we can interpolate old -> new
|
||||
/// @todo migrate this into Vehicle physics tick so we can
|
||||
/// interpolate old -> new
|
||||
|
||||
glm::mat4 wheelM(matrixModel);
|
||||
|
||||
@ -431,68 +393,59 @@ void ObjectRenderer::renderVehicle(VehicleObject *vehicle,
|
||||
btQuaternion steerQ(up, wi.m_steering);
|
||||
btQuaternion rollQ(right, -wi.m_rotation);
|
||||
|
||||
btMatrix3x3 basis(
|
||||
right[0], fwd[0], up[0],
|
||||
right[1], fwd[1], up[1],
|
||||
right[2], fwd[2], up[2]
|
||||
);
|
||||
|
||||
btMatrix3x3 basis(right[0], fwd[0], up[0], right[1], fwd[1],
|
||||
up[1], right[2], fwd[2], up[2]);
|
||||
|
||||
btTransform t;
|
||||
t.setBasis(btMatrix3x3(steerQ) * btMatrix3x3(rollQ) * basis);
|
||||
t.setOrigin(wi.m_chassisConnectionPointCS + wi.m_wheelDirectionCS * wi.m_raycastInfo.m_suspensionLength);
|
||||
t.setOrigin(wi.m_chassisConnectionPointCS +
|
||||
wi.m_wheelDirectionCS *
|
||||
wi.m_raycastInfo.m_suspensionLength);
|
||||
|
||||
t.getOpenGLMatrix(glm::value_ptr(wheelM));
|
||||
wheelM = matrixModel * wheelM;
|
||||
|
||||
wheelM = glm::scale(wheelM, glm::vec3(vehicle->vehicle->wheelScale));
|
||||
wheelM =
|
||||
glm::scale(wheelM, glm::vec3(vehicle->vehicle->wheelScale));
|
||||
if (wi.m_chassisConnectionPointCS.x() < 0.f) {
|
||||
wheelM = glm::scale(wheelM, glm::vec3(-1.f, 1.f, 1.f));
|
||||
}
|
||||
|
||||
renderWheel(vehicle,
|
||||
wheelModel,
|
||||
wheelM,
|
||||
woi->modelName,
|
||||
renderWheel(vehicle, wheelModel, wheelM, woi->modelName,
|
||||
outList);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectRenderer::renderPickup(PickupObject *pickup,
|
||||
RenderList& outList)
|
||||
{
|
||||
void ObjectRenderer::renderPickup(PickupObject* pickup, RenderList& outList) {
|
||||
if (!pickup->isEnabled()) return;
|
||||
|
||||
glm::mat4 modelMatrix = glm::translate(glm::mat4(), pickup->getPosition());
|
||||
modelMatrix = glm::rotate(modelMatrix, m_world->getGameTime(), glm::vec3(0.f, 0.f, 1.f));
|
||||
modelMatrix = glm::rotate(modelMatrix, m_world->getGameTime(),
|
||||
glm::vec3(0.f, 0.f, 1.f));
|
||||
|
||||
auto odata = m_world->data->findObjectType<ObjectData>(pickup->getModelID());
|
||||
auto odata =
|
||||
m_world->data->findObjectType<ObjectData>(pickup->getModelID());
|
||||
|
||||
Model* model = nullptr;
|
||||
ModelFrame* itemModel = nullptr;
|
||||
|
||||
/// @todo Better determination of is this object a weapon.
|
||||
if( odata->ID >= 170 && odata->ID <= 184 )
|
||||
{
|
||||
if (odata->ID >= 170 && odata->ID <= 184) {
|
||||
auto weapons = m_world->data->models["weapons"];
|
||||
if (weapons && weapons->resource && odata) {
|
||||
model = weapons->resource;
|
||||
itemModel = weapons->resource->findFrame(odata->modelName + "_l0");
|
||||
RW_CHECK(itemModel, "Weapon Frame not present int weapon model");
|
||||
if ( ! itemModel )
|
||||
{
|
||||
if (!itemModel) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
auto handle = m_world->data->models[odata->modelName];
|
||||
RW_CHECK(handle && handle->resource, "Pickup has no model");
|
||||
if ( handle && handle->resource )
|
||||
{
|
||||
if (handle && handle->resource) {
|
||||
model = handle->resource;
|
||||
itemModel = model->frames[model->rootFrameIdx];
|
||||
}
|
||||
@ -500,41 +453,38 @@ void ObjectRenderer::renderPickup(PickupObject *pickup,
|
||||
|
||||
if (itemModel) {
|
||||
auto matrix = glm::inverse(itemModel->getTransform());
|
||||
renderFrame(model,
|
||||
itemModel,
|
||||
modelMatrix * matrix,
|
||||
pickup,
|
||||
1.f,
|
||||
renderFrame(model, itemModel, modelMatrix * matrix, pickup, 1.f,
|
||||
outList);
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectRenderer::renderCutsceneObject(CutsceneObject* cutscene,
|
||||
RenderList& outList)
|
||||
{
|
||||
RenderList& outList) {
|
||||
if (!m_world->state->currentCutscene) return;
|
||||
|
||||
if(!cutscene->model->resource)
|
||||
{
|
||||
if (!cutscene->model->resource) {
|
||||
return;
|
||||
}
|
||||
|
||||
glm::mat4 matrixModel;
|
||||
auto cutsceneOffset = m_world->state->currentCutscene->meta.sceneOffset + glm::vec3(0.f, 0.f, 1.f);
|
||||
auto cutsceneOffset = m_world->state->currentCutscene->meta.sceneOffset +
|
||||
glm::vec3(0.f, 0.f, 1.f);
|
||||
|
||||
if (cutscene->getParentActor()) {
|
||||
matrixModel = glm::translate(matrixModel, cutsceneOffset);
|
||||
//matrixModel = cutscene->getParentActor()->getTimeAdjustedTransform(_renderAlpha);
|
||||
// matrixModel =
|
||||
// cutscene->getParentActor()->getTimeAdjustedTransform(_renderAlpha);
|
||||
// matrixModel = glm::translate(matrixModel, glm::vec3(0.f, 0.f, 1.f));
|
||||
glm::mat4 localMatrix;
|
||||
auto boneframe = cutscene->getParentFrame();
|
||||
while (boneframe) {
|
||||
localMatrix = cutscene->getParentActor()->skeleton->getMatrix(boneframe->getIndex()) * localMatrix;
|
||||
localMatrix = cutscene->getParentActor()->skeleton->getMatrix(
|
||||
boneframe->getIndex()) *
|
||||
localMatrix;
|
||||
boneframe = boneframe->getParent();
|
||||
}
|
||||
matrixModel = matrixModel * localMatrix;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
matrixModel = glm::translate(matrixModel, cutsceneOffset);
|
||||
}
|
||||
|
||||
@ -543,29 +493,20 @@ void ObjectRenderer::renderCutsceneObject(CutsceneObject *cutscene,
|
||||
glm::mat4 align;
|
||||
/// @todo figure out where this 90 degree offset is coming from.
|
||||
align = glm::rotate(align, glm::half_pi<float>(), {0.f, 1.f, 0.f});
|
||||
renderFrame(model,
|
||||
model->frames[0],
|
||||
matrixModel * align,
|
||||
cutscene,
|
||||
1.f,
|
||||
renderFrame(model, model->frames[0], matrixModel * align, cutscene, 1.f,
|
||||
outList);
|
||||
}
|
||||
else {
|
||||
renderFrame(model,
|
||||
model->frames[0],
|
||||
matrixModel,
|
||||
cutscene,
|
||||
1.f,
|
||||
} else {
|
||||
renderFrame(model, model->frames[0], matrixModel, cutscene, 1.f,
|
||||
outList);
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectRenderer::renderProjectile(ProjectileObject* projectile,
|
||||
RenderList& outList)
|
||||
{
|
||||
RenderList& outList) {
|
||||
glm::mat4 modelMatrix = projectile->getTimeAdjustedTransform(m_renderAlpha);
|
||||
|
||||
auto odata = m_world->data->findObjectType<ObjectData>(projectile->getProjectileInfo().weapon->modelID);
|
||||
auto odata = m_world->data->findObjectType<ObjectData>(
|
||||
projectile->getProjectileInfo().weapon->modelID);
|
||||
auto weapons = m_world->data->models["weapons"];
|
||||
|
||||
RW_CHECK(weapons, "Weapons model not loaded");
|
||||
@ -575,48 +516,38 @@ void ObjectRenderer::renderProjectile(ProjectileObject *projectile,
|
||||
auto matrix = glm::inverse(itemModel->getTransform());
|
||||
RW_CHECK(itemModel, "Weapon frame not in model");
|
||||
if (itemModel) {
|
||||
renderFrame(weapons->resource,
|
||||
itemModel,
|
||||
modelMatrix * matrix,
|
||||
projectile,
|
||||
1.f,
|
||||
outList);
|
||||
renderFrame(weapons->resource, itemModel, modelMatrix * matrix,
|
||||
projectile, 1.f, outList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectRenderer::buildRenderList(GameObject* object, RenderList& outList)
|
||||
{
|
||||
if( object->skeleton )
|
||||
{
|
||||
void ObjectRenderer::buildRenderList(GameObject* object, RenderList& outList) {
|
||||
if (object->skeleton) {
|
||||
object->skeleton->interpolate(m_renderAlpha);
|
||||
}
|
||||
|
||||
// Right now specialized on each object type
|
||||
switch (object->type()) {
|
||||
case GameObject::Instance:
|
||||
renderInstance(static_cast<InstanceObject*>(object),
|
||||
outList);
|
||||
renderInstance(static_cast<InstanceObject*>(object), outList);
|
||||
break;
|
||||
case GameObject::Character:
|
||||
renderCharacter(static_cast<CharacterObject*>(object),
|
||||
outList);
|
||||
break;;
|
||||
renderCharacter(static_cast<CharacterObject*>(object), outList);
|
||||
break;
|
||||
;
|
||||
case GameObject::Vehicle:
|
||||
renderVehicle(static_cast<VehicleObject*>(object),
|
||||
outList);
|
||||
break;;
|
||||
renderVehicle(static_cast<VehicleObject*>(object), outList);
|
||||
break;
|
||||
;
|
||||
case GameObject::Pickup:
|
||||
renderPickup(static_cast<PickupObject*>(object),
|
||||
outList);
|
||||
renderPickup(static_cast<PickupObject*>(object), outList);
|
||||
break;
|
||||
case GameObject::Projectile:
|
||||
renderProjectile(static_cast<ProjectileObject*>(object),
|
||||
outList);
|
||||
renderProjectile(static_cast<ProjectileObject*>(object), outList);
|
||||
break;
|
||||
case GameObject::Cutscene:
|
||||
renderCutsceneObject(static_cast<CutsceneObject*>(object),
|
||||
outList);
|
||||
renderCutsceneObject(static_cast<CutsceneObject*>(object), outList);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -1,13 +1,13 @@
|
||||
#ifndef _RWENGINE_OBJECTRENDERER_HPP_
|
||||
#define _RWENGINE_OBJECTRENDERER_HPP_
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <rw/types.hpp>
|
||||
#include <render/ViewCamera.hpp>
|
||||
#include <render/OpenGLRenderer.hpp>
|
||||
#include <objects/GameObject.hpp>
|
||||
#include <engine/GameWorld.hpp>
|
||||
#include <gl/DrawBuffer.hpp>
|
||||
#include <glm/glm.hpp>
|
||||
#include <objects/GameObject.hpp>
|
||||
#include <render/OpenGLRenderer.hpp>
|
||||
#include <render/ViewCamera.hpp>
|
||||
#include <rw/types.hpp>
|
||||
|
||||
class ProjectileObject;
|
||||
class PickupObject;
|
||||
@ -18,18 +18,15 @@ class PickupObject;
|
||||
* Determines what parts of an object are within a camera frustum and exports
|
||||
* a list of things to render for the object.
|
||||
*/
|
||||
class ObjectRenderer
|
||||
{
|
||||
class ObjectRenderer {
|
||||
public:
|
||||
ObjectRenderer(GameWorld* world,
|
||||
const ViewCamera& camera,
|
||||
float renderAlpha,
|
||||
GLuint errorTexture)
|
||||
ObjectRenderer(GameWorld* world, const ViewCamera& camera,
|
||||
float renderAlpha, GLuint errorTexture)
|
||||
: m_world(world)
|
||||
, m_camera(camera)
|
||||
, m_renderAlpha(renderAlpha)
|
||||
, m_errorTexture(errorTexture)
|
||||
{ }
|
||||
, m_errorTexture(errorTexture) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief buildRenderList
|
||||
@ -51,28 +48,17 @@ private:
|
||||
void renderCutsceneObject(CutsceneObject* cutscene, RenderList& outList);
|
||||
void renderProjectile(ProjectileObject* projectile, RenderList& outList);
|
||||
|
||||
void renderItem(InventoryItem *item,
|
||||
const glm::mat4 &modelMatrix,
|
||||
void renderItem(InventoryItem* item, const glm::mat4& modelMatrix,
|
||||
RenderList& outList);
|
||||
void renderWheel(VehicleObject* vehicle,
|
||||
Model* model,
|
||||
const glm::mat4 &matrix,
|
||||
const std::string& name,
|
||||
void renderWheel(VehicleObject* vehicle, Model* model,
|
||||
const glm::mat4& matrix, const std::string& name,
|
||||
RenderList& outList);
|
||||
|
||||
bool renderFrame(Model* m,
|
||||
ModelFrame* f,
|
||||
const glm::mat4& matrix,
|
||||
GameObject* object,
|
||||
float opacity,
|
||||
RenderList& outList);
|
||||
bool renderFrame(Model* m, ModelFrame* f, const glm::mat4& matrix,
|
||||
GameObject* object, float opacity, RenderList& outList);
|
||||
|
||||
void renderGeometry(Model* model,
|
||||
size_t g,
|
||||
const glm::mat4& modelMatrix,
|
||||
float opacity,
|
||||
GameObject* object,
|
||||
RenderList& outList);
|
||||
void renderGeometry(Model* model, size_t g, const glm::mat4& modelMatrix,
|
||||
float opacity, GameObject* object, RenderList& outList);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -1,12 +1,11 @@
|
||||
#include <render/OpenGLRenderer.hpp>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
#include <render/OpenGLRenderer.hpp>
|
||||
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
GLuint compileShader(GLenum type, const char *source)
|
||||
{
|
||||
GLuint compileShader(GLenum type, const char* source) {
|
||||
GLuint shader = glCreateShader(type);
|
||||
glShaderSource(shader, 1, &source, NULL);
|
||||
glCompileShader(shader);
|
||||
@ -29,7 +28,9 @@ GLuint compileShader(GLenum type, const char *source)
|
||||
GLchar* sourceBuff = new GLchar[sourceLen];
|
||||
glGetShaderSource(shader, sourceLen, nullptr, sourceBuff);
|
||||
|
||||
std::cerr << "[OGL] Shader InfoLog(" << shader << "):\n" << buffer << "\nSource:\n" << sourceBuff << std::endl;
|
||||
std::cerr << "[OGL] Shader InfoLog(" << shader << "):\n"
|
||||
<< buffer << "\nSource:\n"
|
||||
<< sourceBuff << std::endl;
|
||||
|
||||
delete[] buffer;
|
||||
delete[] sourceBuff;
|
||||
@ -42,8 +43,7 @@ GLuint compileShader(GLenum type, const char *source)
|
||||
return shader;
|
||||
}
|
||||
|
||||
GLuint compileProgram(const char* vertex, const char* fragment)
|
||||
{
|
||||
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();
|
||||
@ -64,7 +64,8 @@ GLuint compileProgram(const char* vertex, const char* fragment)
|
||||
GLchar* buffer = new GLchar[len];
|
||||
glGetProgramInfoLog(prog, len, NULL, buffer);
|
||||
|
||||
std::cerr << "[OGL] Program InfoLog(" << prog << "):\n" << buffer << std::endl;
|
||||
std::cerr << "[OGL] Program InfoLog(" << prog << "):\n"
|
||||
<< buffer << std::endl;
|
||||
|
||||
delete[] buffer;
|
||||
}
|
||||
@ -79,78 +80,64 @@ GLuint compileProgram(const char* vertex, const char* fragment)
|
||||
return prog;
|
||||
}
|
||||
|
||||
void Renderer::setViewport(const glm::ivec2& vp)
|
||||
{
|
||||
void Renderer::setViewport(const glm::ivec2& vp) {
|
||||
viewport = vp;
|
||||
|
||||
projection2D = glm::ortho(0.f, (float)viewport.x, (float)viewport.y, 0.f, -1.f, 1.f);
|
||||
projection2D =
|
||||
glm::ortho(0.f, (float)viewport.x, (float)viewport.y, 0.f, -1.f, 1.f);
|
||||
}
|
||||
|
||||
void Renderer::swap()
|
||||
{
|
||||
void Renderer::swap() {
|
||||
drawCounter = 0;
|
||||
textureCounter = 0;
|
||||
bufferCounter = 0;
|
||||
}
|
||||
|
||||
int Renderer::getDrawCount()
|
||||
{
|
||||
int Renderer::getDrawCount() {
|
||||
return drawCounter;
|
||||
}
|
||||
|
||||
int Renderer::getBufferCount()
|
||||
{
|
||||
int Renderer::getBufferCount() {
|
||||
return bufferCounter;
|
||||
}
|
||||
|
||||
int Renderer::getTextureCount()
|
||||
{
|
||||
int Renderer::getTextureCount() {
|
||||
return textureCounter;
|
||||
}
|
||||
|
||||
const Renderer::SceneUniformData& Renderer::getSceneData() const
|
||||
{
|
||||
const Renderer::SceneUniformData& Renderer::getSceneData() const {
|
||||
return lastSceneData;
|
||||
}
|
||||
|
||||
void OpenGLRenderer::useDrawBuffer(DrawBuffer* dbuff)
|
||||
{
|
||||
if( dbuff != currentDbuff )
|
||||
{
|
||||
void OpenGLRenderer::useDrawBuffer(DrawBuffer* dbuff) {
|
||||
if (dbuff != currentDbuff) {
|
||||
glBindVertexArray(dbuff->getVAOName());
|
||||
currentDbuff = dbuff;
|
||||
bufferCounter++;
|
||||
#if RW_PROFILER
|
||||
if( currentDebugDepth > 0 )
|
||||
{
|
||||
if (currentDebugDepth > 0) {
|
||||
profileInfo[currentDebugDepth - 1].buffers++;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLRenderer::useTexture(GLuint unit, GLuint tex)
|
||||
{
|
||||
if( currentTextures[unit] != tex )
|
||||
{
|
||||
void OpenGLRenderer::useTexture(GLuint unit, GLuint tex) {
|
||||
if (currentTextures[unit] != tex) {
|
||||
glActiveTexture(GL_TEXTURE0 + unit);
|
||||
glBindTexture(GL_TEXTURE_2D, tex);
|
||||
currentTextures[unit] = tex;
|
||||
textureCounter++;
|
||||
#if RW_PROFILER
|
||||
if( currentDebugDepth > 0 )
|
||||
{
|
||||
if (currentDebugDepth > 0) {
|
||||
profileInfo[currentDebugDepth - 1].textures++;
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLRenderer::useProgram(Renderer::ShaderProgram* p)
|
||||
{
|
||||
if( p != currentProgram )
|
||||
{
|
||||
void OpenGLRenderer::useProgram(Renderer::ShaderProgram* p) {
|
||||
if (p != currentProgram) {
|
||||
currentProgram = static_cast<OpenGLShaderProgram*>(p);
|
||||
glUseProgram(currentProgram->getName());
|
||||
}
|
||||
@ -191,8 +178,7 @@ OpenGLRenderer::OpenGLRenderer()
|
||||
, entryAlignment(0)
|
||||
, blendEnabled(false)
|
||||
, depthWriteEnabled(true)
|
||||
, currentDebugDepth(0)
|
||||
{
|
||||
, currentDebugDepth(0) {
|
||||
// We need to query for some profiling exts.
|
||||
ogl_CheckExtensions();
|
||||
|
||||
@ -214,16 +200,13 @@ OpenGLRenderer::OpenGLRenderer()
|
||||
std::cout << "Max batch size: " << maxObjectEntries << std::endl;
|
||||
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, UBOObject);
|
||||
glBufferData(GL_UNIFORM_BUFFER,
|
||||
entryAlignment * maxObjectEntries,
|
||||
NULL,
|
||||
glBufferData(GL_UNIFORM_BUFFER, entryAlignment * maxObjectEntries, NULL,
|
||||
GL_STREAM_DRAW);
|
||||
|
||||
glGenQueries(1, &debugQuery);
|
||||
}
|
||||
|
||||
std::string OpenGLRenderer::getIDString() const
|
||||
{
|
||||
std::string OpenGLRenderer::getIDString() const {
|
||||
std::stringstream ss;
|
||||
ss << "OpenGL Renderer";
|
||||
ss << " Version: " << glGetString(GL_VERSION);
|
||||
@ -232,64 +215,68 @@ std::string OpenGLRenderer::getIDString() const
|
||||
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()));
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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::mat4& m)
|
||||
{
|
||||
void OpenGLRenderer::setUniform(Renderer::ShaderProgram* p,
|
||||
const std::string& name, const glm::mat4& m) {
|
||||
useProgram(p);
|
||||
|
||||
glUniformMatrix4fv(currentProgram->getUniformLocation(name.c_str()), 1, GL_FALSE, glm::value_ptr(m));
|
||||
glUniformMatrix4fv(currentProgram->getUniformLocation(name.c_str()), 1,
|
||||
GL_FALSE, glm::value_ptr(m));
|
||||
}
|
||||
|
||||
void OpenGLRenderer::setUniform(Renderer::ShaderProgram* p, const std::string& name, const glm::vec4& m)
|
||||
{
|
||||
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));
|
||||
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)
|
||||
{
|
||||
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));
|
||||
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)
|
||||
{
|
||||
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));
|
||||
glUniform2fv(currentProgram->getUniformLocation(name.c_str()), 1,
|
||||
glm::value_ptr(m));
|
||||
}
|
||||
|
||||
void OpenGLRenderer::setUniform(Renderer::ShaderProgram* p, const std::string& name, float f)
|
||||
{
|
||||
void OpenGLRenderer::setUniform(Renderer::ShaderProgram* p,
|
||||
const std::string& name, float f) {
|
||||
useProgram(p);
|
||||
|
||||
glUniform1fv(currentProgram->getUniformLocation(name.c_str()), 1, &f);
|
||||
}
|
||||
|
||||
void OpenGLRenderer::clear(const glm::vec4& colour, bool clearColour, bool clearDepth)
|
||||
{
|
||||
void OpenGLRenderer::clear(const glm::vec4& colour, bool clearColour,
|
||||
bool clearDepth) {
|
||||
auto flags = 0;
|
||||
if (clearColour) {
|
||||
flags |= GL_COLOR_BUFFER_BIT;
|
||||
@ -308,60 +295,54 @@ void OpenGLRenderer::clear(const glm::vec4& colour, bool clearColour, bool clear
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLRenderer::setSceneParameters(const Renderer::SceneUniformData& data)
|
||||
{
|
||||
void OpenGLRenderer::setSceneParameters(
|
||||
const Renderer::SceneUniformData& data) {
|
||||
uploadUBO(UBOScene, data);
|
||||
lastSceneData = data;
|
||||
}
|
||||
|
||||
void OpenGLRenderer::setDrawState(const glm::mat4& model, DrawBuffer* draw, const Renderer::DrawParameters& p)
|
||||
{
|
||||
void OpenGLRenderer::setDrawState(const glm::mat4& model, DrawBuffer* draw,
|
||||
const Renderer::DrawParameters& p) {
|
||||
useDrawBuffer(draw);
|
||||
|
||||
for( GLuint u = 0; u < p.textures.size(); ++u )
|
||||
{
|
||||
for (GLuint u = 0; u < p.textures.size(); ++u) {
|
||||
useTexture(u, p.textures[u]);
|
||||
}
|
||||
|
||||
setBlend(p.blend);
|
||||
setDepthWrite(p.depthWrite);
|
||||
|
||||
ObjectUniformData oudata {
|
||||
model,
|
||||
glm::vec4(p.colour.r/255.f, p.colour.g/255.f, p.colour.b/255.f, p.colour.a/255.f),
|
||||
1.f,
|
||||
1.f,
|
||||
p.visibility
|
||||
};
|
||||
ObjectUniformData oudata{model,
|
||||
glm::vec4(p.colour.r / 255.f, p.colour.g / 255.f,
|
||||
p.colour.b / 255.f, p.colour.a / 255.f),
|
||||
1.f, 1.f, p.visibility};
|
||||
uploadUBO(UBOObject, oudata);
|
||||
|
||||
drawCounter++;
|
||||
#if RW_PROFILER
|
||||
if( currentDebugDepth > 0 )
|
||||
{
|
||||
if (currentDebugDepth > 0) {
|
||||
profileInfo[currentDebugDepth - 1].draws++;
|
||||
profileInfo[currentDebugDepth - 1].primitives += p.count;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void OpenGLRenderer::draw(const glm::mat4& model, DrawBuffer* draw, const Renderer::DrawParameters& p)
|
||||
{
|
||||
void OpenGLRenderer::draw(const glm::mat4& model, DrawBuffer* draw,
|
||||
const Renderer::DrawParameters& p) {
|
||||
setDrawState(model, draw, p);
|
||||
|
||||
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)
|
||||
{
|
||||
void OpenGLRenderer::drawArrays(const glm::mat4& model, DrawBuffer* draw,
|
||||
const Renderer::DrawParameters& p) {
|
||||
setDrawState(model, draw, p);
|
||||
|
||||
glDrawArrays(draw->getFaceType(), p.start, p.count);
|
||||
}
|
||||
|
||||
void OpenGLRenderer::drawBatched(const RenderList& list)
|
||||
{
|
||||
void OpenGLRenderer::drawBatched(const RenderList& list) {
|
||||
#if 0 // Needs shader changes
|
||||
// Determine how many batches we need to process the entire list
|
||||
auto entries = list.size();
|
||||
@ -405,29 +386,26 @@ void OpenGLRenderer::drawBatched(const RenderList& list)
|
||||
}
|
||||
}
|
||||
#else
|
||||
for(auto& ri : list)
|
||||
{
|
||||
for (auto& ri : list) {
|
||||
draw(ri.model, ri.dbuff, ri.drawInfo);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void OpenGLRenderer::invalidate()
|
||||
{
|
||||
void OpenGLRenderer::invalidate() {
|
||||
currentDbuff = nullptr;
|
||||
currentProgram = nullptr;
|
||||
currentTextures.clear();
|
||||
currentUBO = 0;
|
||||
}
|
||||
|
||||
void OpenGLRenderer::pushDebugGroup(const std::string& title)
|
||||
{
|
||||
void OpenGLRenderer::pushDebugGroup(const std::string& title) {
|
||||
#if RW_PROFILER
|
||||
if( ogl_ext_KHR_debug )
|
||||
{
|
||||
if (ogl_ext_KHR_debug) {
|
||||
glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0, -1, title.c_str());
|
||||
ProfileInfo& prof = profileInfo[currentDebugDepth];
|
||||
prof.buffers = prof.draws = prof.textures = prof.uploads = prof.primitives = 0;
|
||||
prof.buffers = prof.draws = prof.textures = prof.uploads =
|
||||
prof.primitives = 0;
|
||||
|
||||
glQueryCounter(debugQuery, GL_TIMESTAMP);
|
||||
glGetQueryObjectui64v(debugQuery, GL_QUERY_RESULT, &prof.timerStart);
|
||||
@ -440,11 +418,9 @@ void OpenGLRenderer::pushDebugGroup(const std::string& title)
|
||||
#endif
|
||||
}
|
||||
|
||||
const Renderer::ProfileInfo& OpenGLRenderer::popDebugGroup()
|
||||
{
|
||||
const Renderer::ProfileInfo& OpenGLRenderer::popDebugGroup() {
|
||||
#if RW_PROFILER
|
||||
if( ogl_ext_KHR_debug )
|
||||
{
|
||||
if (ogl_ext_KHR_debug) {
|
||||
glPopDebugGroup();
|
||||
currentDebugDepth--;
|
||||
assert(currentDebugDepth >= 0);
|
||||
@ -458,8 +434,7 @@ const Renderer::ProfileInfo& OpenGLRenderer::popDebugGroup()
|
||||
prof.duration = current_time - prof.timerStart;
|
||||
|
||||
// Add counters to the parent group
|
||||
if( currentDebugDepth > 0 )
|
||||
{
|
||||
if (currentDebugDepth > 0) {
|
||||
ProfileInfo& p = profileInfo[currentDebugDepth - 1];
|
||||
p.draws += prof.draws;
|
||||
p.buffers += prof.buffers;
|
||||
|
@ -2,10 +2,10 @@
|
||||
#ifndef _OPENGLRENDERER_HPP_
|
||||
#define _OPENGLRENDERER_HPP_
|
||||
|
||||
#include <rw/types.hpp>
|
||||
#include <gl/DrawBuffer.hpp>
|
||||
#include <gl/GeometryBuffer.hpp>
|
||||
#include <glm/vec2.hpp>
|
||||
#include <rw/types.hpp>
|
||||
|
||||
typedef uint64_t RenderKey;
|
||||
|
||||
@ -14,8 +14,7 @@ typedef uint64_t RenderKey;
|
||||
|
||||
typedef std::uint32_t RenderIndex;
|
||||
|
||||
struct VertexP3
|
||||
{
|
||||
struct VertexP3 {
|
||||
glm::vec3 position;
|
||||
|
||||
static const AttributeList vertex_attributes() {
|
||||
@ -28,18 +27,14 @@ struct VertexP3
|
||||
/// @todo normalize this to have the same interface as VertexP3
|
||||
struct VertexP2 {
|
||||
static const AttributeList vertex_attributes() {
|
||||
return {
|
||||
{ATRS_Position, 2, sizeof(VertexP2), 0ul}
|
||||
};
|
||||
return {{ATRS_Position, 2, sizeof(VertexP2), 0ul}};
|
||||
}
|
||||
|
||||
float x, y;
|
||||
};
|
||||
|
||||
class Renderer
|
||||
{
|
||||
class Renderer {
|
||||
public:
|
||||
|
||||
typedef std::vector<GLuint> Textures;
|
||||
|
||||
/**
|
||||
@ -51,8 +46,7 @@ public:
|
||||
* Since not all draws use the same shaders, material properties
|
||||
* should be controlled via a different mechanism.
|
||||
*/
|
||||
struct DrawParameters
|
||||
{
|
||||
struct DrawParameters {
|
||||
/// Number of indicies
|
||||
size_t count;
|
||||
/// Start index.
|
||||
@ -78,8 +72,8 @@ public:
|
||||
, depthWrite(true)
|
||||
, ambient(1.f)
|
||||
, diffuse(1.f)
|
||||
, visibility(1.f)
|
||||
{ }
|
||||
, visibility(1.f) {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@ -88,30 +82,21 @@ public:
|
||||
* These are generated by the ObjectRenderer, and passed in to the
|
||||
* OpenGLRenderer by GameRenderer.
|
||||
*/
|
||||
struct RenderInstruction
|
||||
{
|
||||
struct RenderInstruction {
|
||||
RenderKey sortKey;
|
||||
// Ideally, this would just be an index into a buffer that contains the matrix
|
||||
// Ideally, this would just be an index into a buffer that contains the
|
||||
// matrix
|
||||
glm::mat4 model;
|
||||
DrawBuffer* dbuff;
|
||||
Renderer::DrawParameters drawInfo;
|
||||
|
||||
RenderInstruction(
|
||||
RenderKey key,
|
||||
const glm::mat4& model,
|
||||
DrawBuffer* dbuff,
|
||||
const Renderer::DrawParameters& dp)
|
||||
: sortKey(key)
|
||||
, model(model)
|
||||
, dbuff(dbuff)
|
||||
, drawInfo(dp)
|
||||
{
|
||||
|
||||
RenderInstruction(RenderKey key, const glm::mat4& model,
|
||||
DrawBuffer* dbuff, const Renderer::DrawParameters& dp)
|
||||
: sortKey(key), model(model), dbuff(dbuff), drawInfo(dp) {
|
||||
}
|
||||
};
|
||||
typedef std::vector<RenderInstruction> RenderList;
|
||||
|
||||
|
||||
struct ObjectUniformData {
|
||||
glm::mat4 model;
|
||||
glm::vec4 colour;
|
||||
@ -137,32 +122,48 @@ public:
|
||||
|
||||
virtual std::string getIDString() const = 0;
|
||||
|
||||
virtual ShaderProgram* createShader(const std::string& vert, const std::string& frag) = 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::mat4& m) = 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 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::mat4& m) = 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 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;
|
||||
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;
|
||||
|
||||
virtual void drawBatched(const RenderList& list) = 0;
|
||||
|
||||
void setViewport(const glm::ivec2& vp);
|
||||
const glm::ivec2& getViewport() const { return viewport; }
|
||||
const glm::ivec2& getViewport() const {
|
||||
return viewport;
|
||||
}
|
||||
|
||||
const glm::mat4& get2DProjection() const { return projection2D; }
|
||||
const glm::mat4& get2DProjection() const {
|
||||
return projection2D;
|
||||
}
|
||||
|
||||
virtual void invalidate() = 0;
|
||||
|
||||
@ -185,8 +186,7 @@ public:
|
||||
* Not all fields will be populated, depending on
|
||||
* USING(RENDER_PROFILER)
|
||||
*/
|
||||
struct ProfileInfo
|
||||
{
|
||||
struct ProfileInfo {
|
||||
GLuint64 timerStart;
|
||||
GLuint64 duration;
|
||||
unsigned int primitives;
|
||||
@ -210,6 +210,7 @@ public:
|
||||
private:
|
||||
glm::ivec2 viewport;
|
||||
glm::mat4 projection2D;
|
||||
|
||||
protected:
|
||||
int drawCounter;
|
||||
int textureCounter;
|
||||
@ -217,19 +218,19 @@ protected:
|
||||
SceneUniformData lastSceneData;
|
||||
};
|
||||
|
||||
class OpenGLRenderer : public Renderer
|
||||
{
|
||||
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; }
|
||||
public:
|
||||
OpenGLShaderProgram(GLuint p) : program(p) {
|
||||
}
|
||||
|
||||
GLuint getName() const {
|
||||
return program;
|
||||
}
|
||||
|
||||
GLint getUniformLocation(const std::string& name) {
|
||||
auto c = uniforms.find(name.c_str());
|
||||
@ -237,8 +238,7 @@ public:
|
||||
if (c == uniforms.end()) {
|
||||
loc = glGetUniformLocation(program, name.c_str());
|
||||
uniforms[name] = loc;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
loc = c->second;
|
||||
}
|
||||
return loc;
|
||||
@ -249,24 +249,36 @@ public:
|
||||
|
||||
std::string getIDString() const override;
|
||||
|
||||
ShaderProgram* createShader(const std::string &vert, const std::string &frag) override;
|
||||
void setProgramBlockBinding(ShaderProgram* p, const std::string &name, GLint point) override;
|
||||
void setUniformTexture(ShaderProgram* p, const std::string &name, GLint tex) override;
|
||||
void setUniform(ShaderProgram* p, const std::string& name, const glm::mat4& m) override;
|
||||
void setUniform(ShaderProgram* p, const std::string& name, const glm::vec4& m) override;
|
||||
void setUniform(ShaderProgram* p, const std::string& name, const glm::vec3& m) override;
|
||||
void setUniform(ShaderProgram* p, const std::string& name, const glm::vec2& m) override;
|
||||
void setUniform(ShaderProgram* p, const std::string& name, float f) override;
|
||||
ShaderProgram* createShader(const std::string& vert,
|
||||
const std::string& frag) override;
|
||||
void setProgramBlockBinding(ShaderProgram* p, const std::string& name,
|
||||
GLint point) override;
|
||||
void setUniformTexture(ShaderProgram* p, const std::string& name,
|
||||
GLint tex) override;
|
||||
void setUniform(ShaderProgram* p, const std::string& name,
|
||||
const glm::mat4& m) override;
|
||||
void setUniform(ShaderProgram* p, const std::string& name,
|
||||
const glm::vec4& m) override;
|
||||
void setUniform(ShaderProgram* p, const std::string& name,
|
||||
const glm::vec3& m) override;
|
||||
void setUniform(ShaderProgram* p, const std::string& name,
|
||||
const glm::vec2& m) override;
|
||||
void setUniform(ShaderProgram* p, const std::string& name,
|
||||
float f) override;
|
||||
void useProgram(ShaderProgram* p) override;
|
||||
|
||||
void clear(const glm::vec4 &colour, bool clearColour, bool clearDepth) override;
|
||||
void clear(const glm::vec4& colour, bool clearColour,
|
||||
bool clearDepth) override;
|
||||
|
||||
void setSceneParameters(const SceneUniformData& data) override;
|
||||
|
||||
void setDrawState(const glm::mat4& model, DrawBuffer* draw, const DrawParameters& p);
|
||||
void setDrawState(const glm::mat4& model, DrawBuffer* draw,
|
||||
const DrawParameters& p);
|
||||
|
||||
void draw(const glm::mat4& model, DrawBuffer* draw, const DrawParameters& p) override;
|
||||
void drawArrays(const glm::mat4& model, DrawBuffer* draw, const DrawParameters& p) override;
|
||||
void draw(const glm::mat4& model, DrawBuffer* draw,
|
||||
const DrawParameters& p) override;
|
||||
void drawArrays(const glm::mat4& model, DrawBuffer* draw,
|
||||
const DrawParameters& p) override;
|
||||
|
||||
void drawBatched(const RenderList& list) override;
|
||||
|
||||
@ -286,16 +298,15 @@ private:
|
||||
OpenGLShaderProgram* currentProgram;
|
||||
|
||||
GLuint currentUBO;
|
||||
template<class T> void uploadUBO(GLuint buffer, const T& data)
|
||||
{
|
||||
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);
|
||||
#if RW_PROFILER
|
||||
if( currentDebugDepth > 0 )
|
||||
{
|
||||
if (currentDebugDepth > 0) {
|
||||
profileInfo[currentDebugDepth - 1].uploads++;
|
||||
}
|
||||
#endif
|
||||
@ -312,11 +323,11 @@ private:
|
||||
bool depthWriteEnabled;
|
||||
|
||||
// Set state
|
||||
void setBlend(bool enable)
|
||||
{
|
||||
void setBlend(bool enable) {
|
||||
RW_UNUSED(enable);
|
||||
|
||||
/// @todo set blendEnabled, currently not possible because other functions keep trashing the state
|
||||
/// @todo set blendEnabled, currently not possible because other functions keep
|
||||
/// trashing the state
|
||||
#if 0
|
||||
if (enable && !blendEnabled) {
|
||||
glEnable(GL_BLEND);
|
||||
@ -330,8 +341,7 @@ private:
|
||||
#endif
|
||||
}
|
||||
|
||||
void setDepthWrite(bool enable)
|
||||
{
|
||||
void setDepthWrite(bool enable) {
|
||||
if (enable != depthWriteEnabled) {
|
||||
glDepthMask(enable ? GL_TRUE : GL_FALSE);
|
||||
depthWriteEnabled = enable;
|
||||
@ -348,7 +358,6 @@ private:
|
||||
GLuint compileShader(GLenum type, const char* source);
|
||||
GLuint compileProgram(const char* vertex, const char* fragment);
|
||||
|
||||
|
||||
typedef Renderer::RenderList RenderList;
|
||||
|
||||
#endif
|
||||
|
@ -1,28 +1,24 @@
|
||||
#include "render/TextRenderer.hpp"
|
||||
#include <render/GameRenderer.hpp>
|
||||
#include <engine/GameWorld.hpp>
|
||||
#include <render/GameRenderer.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
|
||||
int charToIndex(uint16_t g)
|
||||
{
|
||||
int charToIndex(uint16_t g) {
|
||||
// Correct for the default font maps
|
||||
/// @todo confirm for JA / RU font maps
|
||||
return g - 32;
|
||||
}
|
||||
|
||||
glm::vec4 indexToCoord(int font, int index)
|
||||
{
|
||||
glm::vec4 indexToCoord(int font, int index) {
|
||||
float x = int(index % 16);
|
||||
float y = int(index / 16) + 0.01f;
|
||||
float fontHeight = ((font == 0) ? 16.f : 13.f);
|
||||
glm::vec2 gsize(1.f / 16.f, 1.f / fontHeight);
|
||||
return glm::vec4( x, y, x + 1, y + 0.98f ) *
|
||||
glm::vec4( gsize, gsize );
|
||||
return glm::vec4(x, y, x + 1, y + 0.98f) * glm::vec4(gsize, gsize);
|
||||
}
|
||||
|
||||
|
||||
const char* TextVertexShader = R"(
|
||||
#version 330
|
||||
|
||||
@ -57,8 +53,7 @@ void main()
|
||||
outColour = vec4(Colour, a);
|
||||
})";
|
||||
|
||||
struct TextVertex
|
||||
{
|
||||
struct TextVertex {
|
||||
glm::vec2 position;
|
||||
glm::vec2 texcoord;
|
||||
glm::vec3 colour;
|
||||
@ -73,19 +68,14 @@ struct TextVertex
|
||||
};
|
||||
|
||||
TextRenderer::TextInfo::TextInfo()
|
||||
: font(0), size(1.f), baseColour({1.f, 1.f, 1.f}), align(Left), wrapX(0)
|
||||
{
|
||||
|
||||
: font(0), size(1.f), baseColour({1.f, 1.f, 1.f}), align(Left), wrapX(0) {
|
||||
}
|
||||
|
||||
TextRenderer::TextRenderer(GameRenderer* renderer)
|
||||
: renderer(renderer)
|
||||
{
|
||||
textShader = renderer->getRenderer()->createShader(
|
||||
TextVertexShader, TextFragmentShader );
|
||||
TextRenderer::TextRenderer(GameRenderer* renderer) : renderer(renderer) {
|
||||
textShader = renderer->getRenderer()->createShader(TextVertexShader,
|
||||
TextFragmentShader);
|
||||
|
||||
for( int g = 0; g < GAME_GLYPHS; g++ )
|
||||
{
|
||||
for (int g = 0; g < GAME_GLYPHS; g++) {
|
||||
glyphData[g] = {.9f};
|
||||
}
|
||||
|
||||
@ -102,10 +92,8 @@ TextRenderer::TextRenderer(GameRenderer* renderer)
|
||||
}
|
||||
|
||||
// Assumes contigious a-z character encoding
|
||||
for(char g = 0; g <= ('z'-'a'); g++)
|
||||
{
|
||||
switch( ('a' + g) )
|
||||
{
|
||||
for (char g = 0; g <= ('z' - 'a'); g++) {
|
||||
switch (('a' + g)) {
|
||||
case 'i':
|
||||
glyphData[charToIndex('a' + g)].widthFrac = 0.4f;
|
||||
glyphData[charToIndex('A' + g)].widthFrac = 0.4f;
|
||||
@ -130,21 +118,17 @@ TextRenderer::TextRenderer(GameRenderer* renderer)
|
||||
}
|
||||
}
|
||||
|
||||
TextRenderer::~TextRenderer()
|
||||
{
|
||||
|
||||
TextRenderer::~TextRenderer() {
|
||||
}
|
||||
|
||||
void TextRenderer::setFontTexture(int index, const std::string& texture)
|
||||
{
|
||||
if( index < GAME_FONTS )
|
||||
{
|
||||
void TextRenderer::setFontTexture(int index, const std::string& texture) {
|
||||
if (index < GAME_FONTS) {
|
||||
fonts[index] = texture;
|
||||
}
|
||||
}
|
||||
|
||||
void TextRenderer::renderText(const TextRenderer::TextInfo& ti, bool forceColour)
|
||||
{
|
||||
void TextRenderer::renderText(const TextRenderer::TextInfo& ti,
|
||||
bool forceColour) {
|
||||
renderer->getRenderer()->pushDebugGroup("Text");
|
||||
renderer->getRenderer()->useProgram(textShader);
|
||||
|
||||
@ -168,48 +152,51 @@ void TextRenderer::renderText(const TextRenderer::TextInfo& ti, bool forceColour
|
||||
|
||||
auto text = ti.text;
|
||||
|
||||
for (size_t i = 0; i < text.length(); ++i)
|
||||
{
|
||||
for (size_t i = 0; i < text.length(); ++i) {
|
||||
char16_t c = text[i];
|
||||
|
||||
// Handle any markup changes.
|
||||
if( c == '~' && text.length() > i + 1 )
|
||||
{
|
||||
switch( text[i+1] )
|
||||
{
|
||||
if (c == '~' && text.length() > i + 1) {
|
||||
switch (text[i + 1]) {
|
||||
case 'g': // Green
|
||||
text.erase(text.begin() + i, text.begin() + i + 3);
|
||||
colour = glm::vec3(glm::u8vec3(90, 157, 102)) * (1 / 255.f);
|
||||
break;
|
||||
case 'h': // White
|
||||
text.erase(text.begin() + i, text.begin() + i + 3);
|
||||
colour = glm::vec3(1.f); /// @todo FIXME! Use proper colour!
|
||||
colour =
|
||||
glm::vec3(1.f); /// @todo FIXME! Use proper colour!
|
||||
break;
|
||||
case 'k': { // Key
|
||||
text.erase(text.begin() + i, text.begin() + i + 3);
|
||||
// Extract the key name from the /next/ markup
|
||||
auto keyend = text.find('~', i + 1);
|
||||
auto keyname = text.substr(i + 1, keyend - i - 1);
|
||||
// Since we don't have a key map yet, just print out the name
|
||||
// Since we don't have a key map yet, just print out the
|
||||
// name
|
||||
text.erase(text.begin() + i, text.begin() + keyend);
|
||||
text.insert(i, keyname);
|
||||
break;
|
||||
}
|
||||
case 'l': // Black
|
||||
text.erase(text.begin() + i, text.begin() + i + 3);
|
||||
colour = glm::vec3(0.f); /// @todo FIXME! Use proper colour!
|
||||
colour =
|
||||
glm::vec3(0.f); /// @todo FIXME! Use proper colour!
|
||||
break;
|
||||
case 'r': // Red
|
||||
text.erase(text.begin() + i, text.begin() + i + 3);
|
||||
colour = glm::vec3(1.f, 0.0f, 0.0f); /// @todo FIXME! Use proper colour!
|
||||
colour = glm::vec3(
|
||||
1.f, 0.0f, 0.0f); /// @todo FIXME! Use proper colour!
|
||||
break;
|
||||
case 'w': // Gray
|
||||
text.erase(text.begin() + i, text.begin() + i + 3);
|
||||
colour = glm::vec3(0.5f); /// @todo FIXME! Use proper colour!
|
||||
colour =
|
||||
glm::vec3(0.5f); /// @todo FIXME! Use proper colour!
|
||||
break;
|
||||
case 'y': // Yellow
|
||||
text.erase(text.begin() + i, text.begin() + i + 3);
|
||||
colour = glm::vec3(1.0f, 1.0f, 0.0f); /// @todo FIXME! Use proper colour!
|
||||
colour = glm::vec3(
|
||||
1.0f, 1.0f, 0.0f); /// @todo FIXME! Use proper colour!
|
||||
break;
|
||||
}
|
||||
|
||||
@ -221,23 +208,18 @@ void TextRenderer::renderText(const TextRenderer::TextInfo& ti, bool forceColour
|
||||
}
|
||||
|
||||
int glyph = charToIndex(c);
|
||||
if( glyph >= GAME_GLYPHS )
|
||||
{
|
||||
if (glyph >= GAME_GLYPHS) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// If we're not at the start of the column, check if the current word
|
||||
// will need to be wrapped
|
||||
if (ti.wrapX > 0 && coord.x > 0.f && !std::isspace(c))
|
||||
{
|
||||
auto wend = std::find_if(std::begin(text)+i,
|
||||
std::end(text),
|
||||
if (ti.wrapX > 0 && coord.x > 0.f && !std::isspace(c)) {
|
||||
auto wend = std::find_if(std::begin(text) + i, std::end(text),
|
||||
[](char x) { return std::isspace(x); });
|
||||
if (wend != std::end(text))
|
||||
{
|
||||
if (wend != std::end(text)) {
|
||||
auto word = std::distance(std::begin(text) + i, wend);
|
||||
if (lineLength + word >= ti.wrapX)
|
||||
{
|
||||
if (lineLength + word >= ti.wrapX) {
|
||||
coord.x = 0;
|
||||
coord.y += ss.y;
|
||||
maxHeight = coord.y + ss.y;
|
||||
@ -253,8 +235,7 @@ void TextRenderer::renderText(const TextRenderer::TextInfo& ti, bool forceColour
|
||||
tex.z = tex.x + (tex.z - tex.x) * data.widthFrac;
|
||||
|
||||
// Handle special chars.
|
||||
if( c == '\n' )
|
||||
{
|
||||
if (c == '\n') {
|
||||
coord.x = 0.f;
|
||||
coord.y += ss.y;
|
||||
maxHeight = coord.y + ss.y;
|
||||
@ -271,35 +252,28 @@ void TextRenderer::renderText(const TextRenderer::TextInfo& ti, bool forceColour
|
||||
geo.push_back({{p.x + ss.x, p.y + ss.y}, {tex.z, tex.w}, colour});
|
||||
geo.push_back({{p.x, p.y}, {tex.x, tex.y}, colour});
|
||||
|
||||
|
||||
geo.push_back({{p.x + ss.x, p.y}, {tex.z, tex.y}, colour});
|
||||
geo.push_back({{p.x, p.y}, {tex.x, tex.y}, colour});
|
||||
geo.push_back({{p.x + ss.x, p.y + ss.y}, {tex.z, tex.w}, colour});
|
||||
}
|
||||
|
||||
if ( ti.align == TextInfo::Right )
|
||||
{
|
||||
if (ti.align == TextInfo::Right) {
|
||||
alignment.x -= maxWidth;
|
||||
}
|
||||
else if ( ti.align == TextInfo::Center )
|
||||
{
|
||||
} else if (ti.align == TextInfo::Center) {
|
||||
alignment.x -= (maxWidth / 2.f);
|
||||
}
|
||||
|
||||
alignment.y -= ti.size * 0.2f;
|
||||
|
||||
// If we need to, draw the background.
|
||||
if (colourBG.a > 0.f)
|
||||
{
|
||||
if (colourBG.a > 0.f) {
|
||||
renderer->drawColour(
|
||||
colourBG,
|
||||
glm::vec4(
|
||||
ti.screenPosition - (ss/3.f),
|
||||
colourBG, glm::vec4(ti.screenPosition - (ss / 3.f),
|
||||
glm::vec2(maxWidth, maxHeight) + (ss / 2.f)));
|
||||
|
||||
}
|
||||
|
||||
renderer->getRenderer()->setUniform(textShader, "proj", renderer->getRenderer()->get2DProjection());
|
||||
renderer->getRenderer()->setUniform(
|
||||
textShader, "proj", renderer->getRenderer()->get2DProjection());
|
||||
renderer->getRenderer()->setUniformTexture(textShader, "fontTexture", 0);
|
||||
renderer->getRenderer()->setUniform(textShader, "alignment", alignment);
|
||||
|
||||
|
@ -13,21 +13,13 @@ class GameRenderer;
|
||||
* In future, strings textures might be cached to improve performance, but
|
||||
* for now, we just render each glyph on it's own quad
|
||||
*/
|
||||
class TextRenderer
|
||||
{
|
||||
class TextRenderer {
|
||||
public:
|
||||
|
||||
/**
|
||||
* @todo Can this be merged with the gamestate text entries?
|
||||
*/
|
||||
struct TextInfo
|
||||
{
|
||||
enum TextAlignemnt
|
||||
{
|
||||
Left = 0,
|
||||
Right = 1,
|
||||
Center = 2
|
||||
};
|
||||
struct TextInfo {
|
||||
enum TextAlignemnt { Left = 0, Right = 1, Center = 2 };
|
||||
|
||||
/// Font index @see TextRenderer::setFontTexture
|
||||
int font;
|
||||
@ -52,8 +44,7 @@ public:
|
||||
/**
|
||||
* Stores the information for kerning a glyph
|
||||
*/
|
||||
struct GlyphInfo
|
||||
{
|
||||
struct GlyphInfo {
|
||||
float widthFrac;
|
||||
};
|
||||
|
||||
|
@ -1,30 +1,25 @@
|
||||
#ifndef _VIEWCAMERA_HPP_
|
||||
#define _VIEWCAMERA_HPP_
|
||||
#include "ViewFrustum.hpp"
|
||||
#include <glm/gtc/quaternion.hpp>
|
||||
#include "ViewFrustum.hpp"
|
||||
|
||||
class ViewCamera
|
||||
{
|
||||
class ViewCamera {
|
||||
public:
|
||||
|
||||
ViewFrustum frustum;
|
||||
|
||||
glm::vec3 position;
|
||||
glm::quat rotation;
|
||||
|
||||
ViewCamera(const glm::vec3& pos = {}, const glm::quat& rot = {})
|
||||
: frustum({0.1f, 5000.f, glm::radians(45.f), 1.f}),
|
||||
position(pos), rotation(rot)
|
||||
{
|
||||
|
||||
: frustum({0.1f, 5000.f, glm::radians(45.f), 1.f})
|
||||
, position(pos)
|
||||
, rotation(rot) {
|
||||
}
|
||||
|
||||
glm::mat4 getView()
|
||||
{
|
||||
glm::mat4 getView() {
|
||||
auto up = rotation * glm::vec3(0.f, 0.f, 1.f);
|
||||
return glm::lookAt(position,
|
||||
position + rotation * glm::vec3(1.f, 0.f, 0.f),
|
||||
up);
|
||||
position + rotation * glm::vec3(1.f, 0.f, 0.f), up);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -6,12 +6,9 @@
|
||||
#include <rw_mingw.hpp>
|
||||
#endif
|
||||
|
||||
class ViewFrustum
|
||||
{
|
||||
class ViewFrustum {
|
||||
public:
|
||||
|
||||
class ViewPlane
|
||||
{
|
||||
class ViewPlane {
|
||||
public:
|
||||
glm::vec3 normal;
|
||||
float distance;
|
||||
@ -25,20 +22,15 @@ public:
|
||||
ViewPlane planes[6];
|
||||
|
||||
ViewFrustum(float near, float far, float fov, float aspect)
|
||||
: near(near), far(far), fov(fov), aspectRatio(aspect)
|
||||
{
|
||||
|
||||
: near(near), far(far), fov(fov), aspectRatio(aspect) {
|
||||
}
|
||||
|
||||
glm::mat4 projection()
|
||||
{
|
||||
glm::mat4 projection() {
|
||||
return glm::perspective(fov / aspectRatio, aspectRatio, near, far);
|
||||
}
|
||||
|
||||
void update(const glm::mat4& proj)
|
||||
{
|
||||
for(size_t i = 0; i < 6; ++i)
|
||||
{
|
||||
void update(const glm::mat4& proj) {
|
||||
for (size_t i = 0; i < 6; ++i) {
|
||||
float sign = (i % 2 == 0) ? 1.f : -1.f;
|
||||
int r = i / 2;
|
||||
planes[i].normal.x = proj[0][3] + proj[0][r] * sign;
|
||||
@ -52,13 +44,11 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
bool intersects(glm::vec3 center, float radius) const
|
||||
{
|
||||
bool intersects(glm::vec3 center, float radius) const {
|
||||
float d;
|
||||
bool result = true;
|
||||
|
||||
for(size_t i = 0; i < 6; ++i)
|
||||
{
|
||||
for (size_t i = 0; i < 6; ++i) {
|
||||
d = glm::dot(planes[i].normal, center) + planes[i].distance;
|
||||
if (d < -radius) result = false;
|
||||
}
|
||||
|
@ -2,26 +2,17 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
VisualFX::LightData::~LightData()
|
||||
{
|
||||
|
||||
VisualFX::LightData::~LightData() {
|
||||
}
|
||||
|
||||
VisualFX::ParticleData::~ParticleData()
|
||||
{
|
||||
|
||||
VisualFX::ParticleData::~ParticleData() {
|
||||
}
|
||||
|
||||
VisualFX::TrailData::~TrailData()
|
||||
{
|
||||
|
||||
VisualFX::TrailData::~TrailData() {
|
||||
}
|
||||
|
||||
VisualFX::VisualFX(VisualFX::EffectType type)
|
||||
: type(type)
|
||||
{
|
||||
switch( type )
|
||||
{
|
||||
VisualFX::VisualFX(VisualFX::EffectType type) : type(type) {
|
||||
switch (type) {
|
||||
case VisualFX::Light:
|
||||
new (&light) LightData;
|
||||
break;
|
||||
@ -34,10 +25,8 @@ VisualFX::VisualFX(VisualFX::EffectType type)
|
||||
}
|
||||
}
|
||||
|
||||
VisualFX::~VisualFX()
|
||||
{
|
||||
switch( type )
|
||||
{
|
||||
VisualFX::~VisualFX() {
|
||||
switch (type) {
|
||||
case VisualFX::Light:
|
||||
light.~LightData();
|
||||
break;
|
||||
@ -50,15 +39,12 @@ VisualFX::~VisualFX()
|
||||
}
|
||||
}
|
||||
|
||||
const glm::vec3& VisualFX::getPosition() const
|
||||
{
|
||||
const glm::vec3& VisualFX::getPosition() const {
|
||||
static glm::vec3 errorRef;
|
||||
switch( type )
|
||||
{
|
||||
switch (type) {
|
||||
case VisualFX::Particle:
|
||||
return particle.position;
|
||||
default:
|
||||
return errorRef;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,27 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <gl/TextureData.hpp>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
/**
|
||||
* Represents a scene effect: lighting, particles etc.
|
||||
*/
|
||||
class VisualFX
|
||||
{
|
||||
class VisualFX {
|
||||
public:
|
||||
enum EffectType
|
||||
{
|
||||
Light,
|
||||
Particle,
|
||||
Trail
|
||||
};
|
||||
enum EffectType { Light, Particle, Trail };
|
||||
|
||||
struct LightData
|
||||
{
|
||||
struct LightData {
|
||||
~LightData();
|
||||
};
|
||||
struct ParticleData
|
||||
{
|
||||
struct ParticleData {
|
||||
/** Initial world position */
|
||||
glm::vec3 position;
|
||||
|
||||
@ -38,7 +30,8 @@ public:
|
||||
|
||||
/** Game time at particle instantiation */
|
||||
float starttime;
|
||||
/** Number of seconds particle should exist for, negative values = forever */
|
||||
/** Number of seconds particle should exist for, negative values =
|
||||
* forever */
|
||||
float lifetime;
|
||||
|
||||
/** Texture name */
|
||||
@ -55,12 +48,16 @@ public:
|
||||
|
||||
/** Constructs a particle */
|
||||
ParticleData()
|
||||
: orientation(Free), starttime(0.f), lifetime(-1.f), size(1.f, 1.f),
|
||||
up(0.f, 0.f, 1.f), colour(1.f, 1.f, 1.f, 1.f) { }
|
||||
: orientation(Free)
|
||||
, starttime(0.f)
|
||||
, lifetime(-1.f)
|
||||
, size(1.f, 1.f)
|
||||
, up(0.f, 0.f, 1.f)
|
||||
, colour(1.f, 1.f, 1.f, 1.f) {
|
||||
}
|
||||
~ParticleData();
|
||||
};
|
||||
struct TrailData
|
||||
{
|
||||
struct TrailData {
|
||||
~TrailData();
|
||||
};
|
||||
|
||||
@ -74,7 +71,9 @@ public:
|
||||
VisualFX(EffectType type);
|
||||
~VisualFX();
|
||||
|
||||
EffectType getType() const { return type; }
|
||||
EffectType getType() const {
|
||||
return type;
|
||||
}
|
||||
|
||||
const glm::vec3& getPosition() const;
|
||||
|
||||
|
@ -1,22 +1,19 @@
|
||||
#include <render/WaterRenderer.hpp>
|
||||
#include <engine/GameWorld.hpp>
|
||||
#include <render/GameRenderer.hpp>
|
||||
#include <render/GameShaders.hpp>
|
||||
#include <engine/GameWorld.hpp>
|
||||
#include <render/WaterRenderer.hpp>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
WaterRenderer::WaterRenderer(GameRenderer* renderer)
|
||||
: waterProg(nullptr)
|
||||
{
|
||||
WaterRenderer::WaterRenderer(GameRenderer* renderer) : waterProg(nullptr) {
|
||||
maskDraw.setFaceType(GL_TRIANGLES);
|
||||
gridDraw.setFaceType(GL_TRIANGLES);
|
||||
|
||||
waterProg = renderer->getRenderer()->createShader(
|
||||
GameShaders::WaterHQ::VertexShader, GameShaders::WaterHQ::FragmentShader
|
||||
);
|
||||
GameShaders::WaterHQ::VertexShader,
|
||||
GameShaders::WaterHQ::FragmentShader);
|
||||
maskProg = renderer->getRenderer()->createShader(
|
||||
GameShaders::Mask3D::VertexShader, GameShaders::Mask3D::FragmentShader
|
||||
);
|
||||
GameShaders::Mask3D::VertexShader, GameShaders::Mask3D::FragmentShader);
|
||||
|
||||
renderer->getRenderer()->setProgramBlockBinding(waterProg, "SceneData", 1);
|
||||
renderer->getRenderer()->setProgramBlockBinding(maskProg, "SceneData", 1);
|
||||
@ -28,10 +25,8 @@ WaterRenderer::WaterRenderer(GameRenderer* renderer)
|
||||
std::vector<glm::vec2> grid;
|
||||
float gridresinv = 1.f / (gridres * 0.5f);
|
||||
glm::vec2 b(-1.f, -1.f);
|
||||
for( int x = 0; x < gridres; x++ )
|
||||
{
|
||||
for( int y = 0; y < gridres; y++ )
|
||||
{
|
||||
for (int x = 0; x < gridres; x++) {
|
||||
for (int y = 0; y < gridres; y++) {
|
||||
glm::vec2 tMin(b + glm::vec2(x, y) * gridresinv);
|
||||
glm::vec2 tMax(b + glm::vec2(x + 1, y + 1) * gridresinv);
|
||||
|
||||
@ -46,20 +41,17 @@ WaterRenderer::WaterRenderer(GameRenderer* renderer)
|
||||
}
|
||||
}
|
||||
|
||||
gridGeom.uploadVertices(grid.size(), sizeof(glm::vec2)*grid.size(), grid.data());
|
||||
gridGeom.getDataAttributes().push_back(
|
||||
{ATRS_Position, 2, 0, 0, GL_FLOAT}
|
||||
);
|
||||
gridGeom.uploadVertices(grid.size(), sizeof(glm::vec2) * grid.size(),
|
||||
grid.data());
|
||||
gridGeom.getDataAttributes().push_back({ATRS_Position, 2, 0, 0, GL_FLOAT});
|
||||
gridDraw.addGeometry(&gridGeom);
|
||||
}
|
||||
|
||||
WaterRenderer::~WaterRenderer()
|
||||
{
|
||||
|
||||
WaterRenderer::~WaterRenderer() {
|
||||
}
|
||||
|
||||
void WaterRenderer::setWaterTable(float* waterHeights, unsigned int nHeights, uint8_t* tiles, unsigned int nTiles)
|
||||
{
|
||||
void WaterRenderer::setWaterTable(float* waterHeights, unsigned int nHeights,
|
||||
uint8_t* tiles, unsigned int nTiles) {
|
||||
// Determine the dimensions of the input tiles
|
||||
int edgeNum = sqrt(nTiles);
|
||||
float tileSize = WATER_WORLD_SIZE / edgeNum;
|
||||
@ -67,11 +59,9 @@ void WaterRenderer::setWaterTable(float* waterHeights, unsigned int nHeights, ui
|
||||
|
||||
std::vector<glm::vec3> vertexData;
|
||||
|
||||
for( int x = 0; x < edgeNum; x++ )
|
||||
{
|
||||
for (int x = 0; x < edgeNum; x++) {
|
||||
int xi = x * WATER_HQ_DATA_SIZE;
|
||||
for( int y = 0; y < edgeNum; y++ )
|
||||
{
|
||||
for (int y = 0; y < edgeNum; y++) {
|
||||
RW_CHECK(tiles[xi + y] < nHeights, "Tile index out of bounds");
|
||||
if (tiles[xi + y] >= nHeights) continue;
|
||||
|
||||
@ -93,21 +83,19 @@ void WaterRenderer::setWaterTable(float* waterHeights, unsigned int nHeights, ui
|
||||
}
|
||||
}
|
||||
|
||||
maskGeom.uploadVertices(vertexData.size(), sizeof(glm::vec3)*vertexData.size(), vertexData.data());
|
||||
maskGeom.getDataAttributes().push_back(
|
||||
{ATRS_Position, 3, 0, 0, GL_FLOAT}
|
||||
);
|
||||
maskGeom.uploadVertices(vertexData.size(),
|
||||
sizeof(glm::vec3) * vertexData.size(),
|
||||
vertexData.data());
|
||||
maskGeom.getDataAttributes().push_back({ATRS_Position, 3, 0, 0, GL_FLOAT});
|
||||
maskDraw.addGeometry(&maskGeom);
|
||||
}
|
||||
|
||||
void WaterRenderer::setDataTexture(GLuint fbBinding, GLuint dataTex)
|
||||
{
|
||||
void WaterRenderer::setDataTexture(GLuint fbBinding, GLuint dataTex) {
|
||||
fbOutput = fbBinding;
|
||||
dataTexture = dataTex;
|
||||
}
|
||||
|
||||
void WaterRenderer::render(GameRenderer* renderer, GameWorld* world)
|
||||
{
|
||||
void WaterRenderer::render(GameRenderer* renderer, GameWorld* world) {
|
||||
auto r = renderer->getRenderer();
|
||||
|
||||
auto waterTex = world->data->findTexture("water_old");
|
||||
@ -136,7 +124,6 @@ void WaterRenderer::render(GameRenderer* renderer, GameWorld* world)
|
||||
|
||||
r->useProgram(maskProg);
|
||||
|
||||
|
||||
r->drawArrays(m, &maskDraw, wdp);
|
||||
|
||||
glStencilFunc(GL_EQUAL, 1, 0xFF);
|
||||
@ -149,8 +136,10 @@ void WaterRenderer::render(GameRenderer* renderer, GameWorld* world)
|
||||
glDrawBuffers(1, buffers);
|
||||
|
||||
r->setUniform(waterProg, "time", world->getGameTime());
|
||||
r->setUniform(waterProg, "waveParams", glm::vec2(WATER_SCALE, WATER_HEIGHT));
|
||||
auto ivp = glm::inverse(r->getSceneData().projection * r->getSceneData().view);
|
||||
r->setUniform(waterProg, "waveParams",
|
||||
glm::vec2(WATER_SCALE, WATER_HEIGHT));
|
||||
auto ivp =
|
||||
glm::inverse(r->getSceneData().projection * r->getSceneData().view);
|
||||
r->setUniform(waterProg, "inverseVP", ivp);
|
||||
|
||||
wdp.count = gridGeom.getCount();
|
||||
|
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <rw/types.hpp>
|
||||
#include <render/OpenGLRenderer.hpp>
|
||||
#include <rw/types.hpp>
|
||||
|
||||
class GameRenderer;
|
||||
class GameWorld;
|
||||
@ -9,8 +9,7 @@ class GameWorld;
|
||||
/**
|
||||
* Implements the rendering routines for drawing the sea water.
|
||||
*/
|
||||
class WaterRenderer
|
||||
{
|
||||
class WaterRenderer {
|
||||
public:
|
||||
WaterRenderer(GameRenderer* renderer);
|
||||
~WaterRenderer();
|
||||
@ -23,7 +22,8 @@ public:
|
||||
* This data is used to create the internal stencil mask for clipping
|
||||
* the water rendering.
|
||||
*/
|
||||
void setWaterTable(float* waterHeights, unsigned int nHeights, uint8_t* tiles, unsigned int nTiles);
|
||||
void setWaterTable(float* waterHeights, unsigned int nHeights,
|
||||
uint8_t* tiles, unsigned int nTiles);
|
||||
|
||||
void setDataTexture(GLuint fbBinding, GLuint dataTexture);
|
||||
|
||||
@ -31,6 +31,7 @@ public:
|
||||
* Render the water using the currently active render state
|
||||
*/
|
||||
void render(GameRenderer* renderer, GameWorld* world);
|
||||
|
||||
private:
|
||||
Renderer::ShaderProgram* waterProg;
|
||||
Renderer::ShaderProgram* maskProg;
|
||||
|
Loading…
Reference in New Issue
Block a user