The fruits of my labor

This commit is contained in:
2023-01-20 00:00:36 -08:00
parent 97fd59f28d
commit 3ee07af4db
55 changed files with 563 additions and 459 deletions

View File

@ -73,6 +73,8 @@ void RenderPipeline::renderScene(Scene *scene) {
}
void RenderPipeline::renderSceneCamera(Scene *scene, Camera *camera) {
std::vector<struct ShaderPassItem>::iterator itPassItem;
assertNotNull(scene);
assertNotNull(camera);
@ -80,8 +82,12 @@ void RenderPipeline::renderSceneCamera(Scene *scene, Camera *camera) {
// not sending parameters to shaders more than we need.
this->renderId--;
// Get the render target.
auto renderTarget = camera->getRenderTarget();
assertNotNull(renderTarget);
// Get the list of things to render first.
std::vector<struct RenderPipelineItem> pipelineItems;
std::vector<struct ShaderPassItem> shaderPassItems;
// Meshes
auto meshes = scene->findComponents<MeshRenderer>();
@ -89,6 +95,7 @@ void RenderPipeline::renderSceneCamera(Scene *scene, Camera *camera) {
while(itMesh != meshes.end()) {
// Get Mesh
auto mesh = *itMesh;
assertNotNull(mesh);
assertNotNull(mesh->mesh);
// Make sure this mesh has a material
@ -98,62 +105,76 @@ void RenderPipeline::renderSceneCamera(Scene *scene, Camera *camera) {
auto shader = mat->getShader();
assertNotNull(shader);
// Now do each pass.
auto passes = shader->getItemPasses(mesh, mat);
auto itPass = passes.begin();
while(itPass != passes.end()) {
struct RenderPipelineItem item;
item.mesh = mesh;
item.pass = *itPass;
// Now get and validate the pass items for this material/shader
auto materialPassItems = shader->getPassItems(mesh->mesh, mat, camera);
itPassItem = materialPassItems.begin();
while(itPassItem != materialPassItems.end()) {
auto item = *itPassItem;
// Validate the pass
assertNotNull(item.pass.shaderProgram);
// Do we need to get the W Vector?
if(item.pass.needsW) {
assertUnreachable();// TODO: Add distance from camera for W vector.
} else {
item.w = 0;
}
assertNotNull(item.mesh);
assertTrue(item.start >= 0);
assertTrue(item.count > 0 || item.count == -1);
assertNotNull(item.shaderProgram);
// Queue
pipelineItems.push_back(item);
++itPass;
shaderPassItems.push_back(item);
++itPassItem;
}
// Now, for optimization, we bind the global parameters here, once for each
// shader.
if(shader->renderId != this->renderId) {
shader->setGlobalParameters(
camera->projection,
camera->transform->getWorldTransform()
);
shader->renderId = this->renderId;
}
++itMesh;
}
// UI Elements
auto canvases = scene->findComponents<UICanvas>();
auto itCanvas = canvases.begin();
while(itCanvas != canvases.end()) {
auto canvas = *itCanvas;
glm::mat4 model;
glm::mat4 projection;
glm::mat4 view;
// TODO: Get UI stuff here.
switch(canvas->drawType) {
case UI_DRAW_TYPE_WORLD_ABSOLUTE:
projection = camera->projection;
view = camera->transform->getWorldTransform();
model = canvas->transform->getWorldTransform();
break;
case UI_DRAW_TYPE_WORLD_CAMERA_RELATIVE:
projection = glm::ortho(0.0f, renderTarget->getWidth(), renderTarget->getHeight(), 0.0f);
view = glm::mat4(1.0f);
model = canvas->transform->getWorldTransform();
break;
default:
assertUnreachable();
}
auto itChild = canvas->children.begin();
while(itChild != canvas->children.end()) {
vectorAppend(&shaderPassItems, (*itChild)->getPassItems(
projection, view, model
));
++itChild;
}
++itCanvas;
}
// Now we've queued everything, let's sort the rendering queue by the priority
std::sort(
pipelineItems.begin(),
pipelineItems.end(),
[](struct RenderPipelineItem &a, struct RenderPipelineItem &b){
if(a.pass.orderShader == b.pass.orderShader) {
shaderPassItems.begin(),
shaderPassItems.end(),
[](struct ShaderPassItem &a, struct ShaderPassItem &b){
if(a.priority == b.priority) {
return a.w < b.w;
}
return a.pass.orderShader < b.pass.orderShader;
return a.priority < b.priority;
}
);
// Now we've sorted everything! Let's actually start rendering.
ShaderProgram *boundProgram = nullptr;
std::map<textureslot_t, Texture*> boundTextures;
auto renderTarget = camera->getRenderTarget();
assertNotNull(renderTarget);
// TODO: This will be editable!
renderTarget->bind();
@ -161,24 +182,20 @@ void RenderPipeline::renderSceneCamera(Scene *scene, Camera *camera) {
RENDER_TARGET_CLEAR_FLAG_DEPTH |
RENDER_TARGET_CLEAR_FLAG_COLOR
);
this->renderManager->setRenderFlags(
RENDER_MANAGER_RENDER_FLAG_DEPTH_TEST |
RENDER_MANAGER_RENDER_FLAG_BLEND
);
auto itItems = pipelineItems.begin();
while(itItems != pipelineItems.end()) {
auto item = *itItems;
itPassItem = shaderPassItems.begin();
while(itPassItem != shaderPassItems.end()) {
auto item = *itPassItem;
// Bind the program.
if(boundProgram != item.pass.shaderProgram) {
boundProgram = item.pass.shaderProgram;
if(boundProgram != item.shaderProgram) {
boundProgram = item.shaderProgram;
boundProgram->bind();
}
// Bind the textures to the slots
auto itTextureSlot = item.pass.textureSlots.begin();
while(itTextureSlot != item.pass.textureSlots.end()) {
auto itTextureSlot = item.textureSlots.begin();
while(itTextureSlot != item.textureSlots.end()) {
// Assert texture isn't null, just don't include it.
assertNotNull(itTextureSlot->second);
@ -190,45 +207,52 @@ void RenderPipeline::renderSceneCamera(Scene *scene, Camera *camera) {
}
// Now set each of the parameters. Nothing exciting here.
auto itColors = item.pass.colorValues.begin();
while(itColors != item.pass.colorValues.end()) {
item.pass.shaderProgram->setColor(itColors->first, itColors->second);
auto itColors = item.colorValues.begin();
while(itColors != item.colorValues.end()) {
item.shaderProgram->setColor(itColors->first, itColors->second);
++itColors;
}
auto itBool = item.pass.boolValues.begin();
while(itBool != item.pass.boolValues.end()) {
item.pass.shaderProgram->setBoolean(itBool->first, itBool->second);
auto itBool = item.boolValues.begin();
while(itBool != item.boolValues.end()) {
item.shaderProgram->setBoolean(itBool->first, itBool->second);
++itBool;
}
auto itMat = item.pass.matrixValues.begin();
while(itMat != item.pass.matrixValues.end()) {
item.pass.shaderProgram->setMatrix(itMat->first, itMat->second);
auto itMat = item.matrixValues.begin();
while(itMat != item.matrixValues.end()) {
item.shaderProgram->setMatrix(itMat->first, itMat->second);
++itMat;
}
auto itVec3 = item.pass.vec3Values.begin();
while(itVec3 != item.pass.vec3Values.end()) {
item.pass.shaderProgram->setVector3(itVec3->first, itVec3->second);
auto itVec3 = item.vec3Values.begin();
while(itVec3 != item.vec3Values.end()) {
item.shaderProgram->setVector3(itVec3->first, itVec3->second);
++itVec3;
}
auto itText = item.pass.textureValues.begin();
while(itText != item.pass.textureValues.end()) {
item.pass.shaderProgram->setTexture(itText->first, itText->second);
auto itText = item.textureValues.begin();
while(itText != item.textureValues.end()) {
item.shaderProgram->setTexture(itText->first, itText->second);
++itText;
}
auto itFloat = item.pass.floatValues.begin();
while(itFloat != item.pass.floatValues.end()) {
item.pass.shaderProgram->setFloat(itFloat->first, itFloat->second);
auto itFloat = item.floatValues.begin();
while(itFloat != item.floatValues.end()) {
item.shaderProgram->setFloat(itFloat->first, itFloat->second);
++itFloat;
}
// Set Render flags
this->renderManager->setRenderFlags(item.renderFlags);
// Thank god that's done, now just draw the damn mesh.
item.mesh->mesh->draw(MESH_DRAW_MODE_TRIANGLES, 0, -1);
++itItems;
item.mesh->draw(
MESH_DRAW_MODE_TRIANGLES,
item.start,
item.count
);
++itPassItem;
}
}

View File

@ -10,16 +10,11 @@
#include "scene/components/display/Material.hpp"
#include "scene/components/display/MeshRenderer.hpp"
#include "scene/components/display/Camera.hpp"
#include "ui/UIComponent.hpp"
namespace Dawn {
class RenderManager;
struct RenderPipelineItem {
MeshRenderer *mesh;
struct ShaderPass pass;
float_t w;
};
class RenderPipeline {
private:
int_fast16_t renderId = -1;

View File

@ -5,13 +5,10 @@
#pragma once
#include "RenderTarget.hpp"
#include "display/shader/Shader.hpp"
#include "display/shader/UIShader.hpp"
#include "util/flag.hpp"
#define RENDER_MANAGER_RENDER_FLAG_DEPTH_TEST FLAG_DEFINE(0)
#define RENDER_MANAGER_RENDER_FLAG_BLEND FLAG_DEFINE(1)
typedef flag_t renderflag_t;
namespace Dawn {
@ -51,13 +48,6 @@ namespace Dawn {
* @return Reference to the currently active main scene render pipeline.
*/
virtual RenderPipeline * getRenderPipeline() = 0;
/**
* Returns the UI Shader used by the game's UI engine.
*
* @return Pointer to the UI Shader.
*/
virtual UIShader * getUIShader() = 0;
/**
* Sets the render flags for the render manager to use.

View File

@ -6,14 +6,21 @@
#pragma once
#include "display/shader/ShaderProgram.hpp"
#include "scene/components/display/MeshRenderer.hpp"
#include "scene/components/display/Camera.hpp"
#include "display/_RenderManager.hpp"
namespace Dawn {
class Material;
struct ShaderPass {
struct ShaderPassItem {
ShaderProgram *shaderProgram = nullptr;
int32_t orderShader = 0;
bool_t needsW = false;
int32_t priority = 0;
Mesh *mesh;
int32_t start = 0;
int32_t count = -1;
float_t w = 0;
renderflag_t renderFlags = RENDER_MANAGER_RENDER_FLAG_DEPTH_TEST;
// Parameters
std::map<shaderparameter_t, struct Color> colorValues;
@ -39,27 +46,17 @@ namespace Dawn {
virtual void compile() = 0;
/**
* Returns the list of passes to render for the given scene item.
* Returns the list of pass items to render for the given scene item.
*
* @param mesh Mesh Renderer for the scene item.
* @param material Material for the scene item.
* @param camera Camera for the scene.
* @return List of passes to render.
*/
virtual std::vector<struct ShaderPass> getItemPasses(
MeshRenderer *mesh,
Material *material
) = 0;
/**
* Called once per frame, set the global shader parameters that is used by
* every item in the scene.
*
* @param cameraProjection Projection matrix of the camera.
* @param cameraView View matrix of the camera.
*/
virtual void setGlobalParameters(
glm::mat4 cameraProjection,
glm::mat4 cameraView
virtual std::vector<struct ShaderPassItem> getPassItems(
Mesh *mesh,
Material *material,
Camera *camera
) = 0;
};
}