Add support for transparent mesh sorting
This commit is contained in:
parent
2ade6919d1
commit
97adb2fd3b
|
@ -25,8 +25,8 @@ void runProgram(GLFWwindow* window, CommandLineOptions options)
|
|||
glEnable(GL_CULL_FACE);
|
||||
|
||||
//enable alpha
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glEnable(GL_BLEND);
|
||||
|
||||
// Set default colour after clearing the colour buffer
|
||||
glClearColor(0.3f, 0.5f, 0.8f, 1.0f);
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include <glm/vec3.hpp>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <utilities/glfont.h>
|
||||
#include <utilities/shader.hpp>
|
||||
#include <utilities/timeutils.h>
|
||||
|
@ -119,7 +120,14 @@ void updateFrame(GLFWwindow* window, int windowWidth, int windowHeight) {
|
|||
}
|
||||
|
||||
// traverses and renders one and one node
|
||||
void renderNode(SceneNode* node, Gloom::Shader* parent_shader) {
|
||||
struct NodeDistShader{
|
||||
SceneNode* node;
|
||||
Gloom::Shader* s;
|
||||
float dist;
|
||||
NodeDistShader(SceneNode* node, Gloom::Shader* s, float dist)
|
||||
: node(node), s(s), dist(dist) {}
|
||||
};
|
||||
void renderNode(SceneNode* node, Gloom::Shader* parent_shader, vector<NodeDistShader>* transparent_nodes=nullptr, bool do_recursive=true) {
|
||||
struct Light { // lights as stored in the shader
|
||||
// coordinates in MV space
|
||||
vec3 position; // MV
|
||||
|
@ -158,7 +166,11 @@ void renderNode(SceneNode* node, Gloom::Shader* parent_shader) {
|
|||
|
||||
switch(node->nodeType) {
|
||||
case GEOMETRY:
|
||||
if(node->vertexArrayObjectID != -1) {
|
||||
if (transparent_nodes!=nullptr && node->has_transparancy()) {
|
||||
// defer to sorted pass later on
|
||||
transparent_nodes->emplace_back(node, node_shader, (float)glm::length(vec3(node->MVP*vec4(0,0,0,1))));
|
||||
}
|
||||
else if(node->vertexArrayObjectID != -1) {
|
||||
// load uniforms
|
||||
glUniformMatrix4fv(s->location("MVP") , 1, GL_FALSE, glm::value_ptr(node->MVP));
|
||||
glUniformMatrix4fv(s->location("MV") , 1, GL_FALSE, glm::value_ptr(node->MV));
|
||||
|
@ -203,16 +215,37 @@ void renderNode(SceneNode* node, Gloom::Shader* parent_shader) {
|
|||
break;
|
||||
}
|
||||
|
||||
if (do_recursive)
|
||||
for(SceneNode* child : node->children) {
|
||||
renderNode(child, node_shader);
|
||||
renderNode(child, node_shader, transparent_nodes, true);
|
||||
}
|
||||
}
|
||||
|
||||
// draw
|
||||
void renderFrame(GLFWwindow* window, int windowWidth, int windowHeight) {
|
||||
glViewport(0, 0, windowWidth, windowHeight);
|
||||
|
||||
|
||||
static vector<NodeDistShader> transparent_nodes;
|
||||
transparent_nodes.clear();
|
||||
|
||||
// externs from scene.hpp, they must have shaders set
|
||||
renderNode(rootNode, nullptr);
|
||||
renderNode(rootNode, nullptr, &transparent_nodes);
|
||||
|
||||
// sort and render transparent node, sorted by distance from camera
|
||||
std::sort(
|
||||
transparent_nodes.begin(),
|
||||
transparent_nodes.end(),
|
||||
[](NodeDistShader a, NodeDistShader b) {
|
||||
return a.dist > b.dist;
|
||||
});
|
||||
glDepthMask(GL_FALSE);
|
||||
//glDisable(GL_DEPTH_TEST);
|
||||
for (NodeDistShader a : transparent_nodes)
|
||||
renderNode(a.node, a.s, nullptr, false);
|
||||
std::cout << transparent_nodes.size() << std::endl;
|
||||
glDepthMask(GL_TRUE);
|
||||
//glEnable(GL_DEPTH_TEST);
|
||||
|
||||
|
||||
renderNode(hudNode, nullptr);
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <chrono>
|
||||
#include <glad/glad.h>
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
#include <utilities/imageLoader.hpp>
|
||||
#include <utilities/modelLoader.hpp>
|
||||
#include <utilities/mesh.h>
|
||||
|
@ -73,11 +74,31 @@ void init_scene(CommandLineOptions options) {
|
|||
rootNode->children.push_back(lightNode[i]);
|
||||
}
|
||||
|
||||
//treeNode = loadModelScene("../res/models/fur_tree/scene.gltf");
|
||||
//treeNode = loadModelScene("../res/models/fur_tree", "scene.gltf");
|
||||
//treeNode->position = {300, 800, 10};
|
||||
//rootNode->children.push_back(treeNode);
|
||||
|
||||
carNode = loadModelScene("../res/models/beetle/scene.gltf", {
|
||||
//uint i = 30;
|
||||
//while (i--) {
|
||||
// SceneNode* asd = treeNode->clone();
|
||||
// asd->position.x = (std::rand() % 10000) / 10;
|
||||
// asd->position.y = (std::rand() % 10000) / 10;
|
||||
// rootNode->children.push_back(asd);
|
||||
//}
|
||||
|
||||
grassNode = loadModelScene("../res/models/single_grass", "scene.gltf");
|
||||
grassNode->position = {400, 400, 15};
|
||||
rootNode->children.push_back(grassNode);
|
||||
for (uint i = 100; i--;) {
|
||||
SceneNode* asd = grassNode->clone();
|
||||
asd->position.x = (std::rand() % 10000) / 10;
|
||||
asd->position.y = (std::rand() % 10000) / 10;
|
||||
rootNode->children.push_back(asd);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
carNode = loadModelScene("../res/models/beetle", "scene.gltf", {
|
||||
{ 0, Material().diffuse({0.0, 0.0, 1.0}).diffuse_only().reflection_mapped(&t_reflection, 0.15)},// Blue_Metal
|
||||
{ 1, Material().diffuse(vec3(0.85)).emissive(vec3(0.1)).reflection_mapped(&t_reflection, -1.0)},// Metal (decals)
|
||||
//{ 2, Material().diffuse({1.0, 1.0, 1.0})},// Front_Light_Glass
|
||||
|
@ -85,20 +106,18 @@ void init_scene(CommandLineOptions options) {
|
|||
{ 4, Material().no_colors().reflection_mapped(&t_reflection, 1.0)},// Mirror
|
||||
//{ 5, Material().diffuse({1.0, 1.0, 1.0})},// Black_Metal
|
||||
//{ 6, Material().diffuse({1.0, 1.0, 1.0})},// Plastic
|
||||
// { 7, Material().diffuse(vec3(0.2)).emissive(vec3(0.25)).specular(vec3(1.0), 70).reflection_mapped(&t_reflection, -0.8)},// Window_Glass
|
||||
{ 7, Material().diffuse(vec3(0.2)).emissive(vec3(0.25)).specular(vec3(1.0), 70).reflection_mapped(&t_reflection, -0.8)},// Window_Glass
|
||||
//{ 8, Material().diffuse({1.0, 1.0, 1.0})},// Material
|
||||
{ 9, Material().diffuse(vec3(1.0)).emissive(vec3(0.2)).specular(vec3(0.4), 70).reflection_mapped(&t_reflection, -1.0)},// Glossy_metal
|
||||
//{10, Material().diffuse({1.0, 1.0, 1.0})},// Rogh_Metal
|
||||
// {11, Material().no_colors().reflection_mapped(&t_reflection, 1.0)},// License_Plate_Metal
|
||||
{11, Material().no_colors().reflection_mapped(&t_reflection, 1.0)},// License_Plate_Metal
|
||||
//{12, Material().diffuse({1.0, 1.0, 1.0})},// License_Plate_Frame
|
||||
//{13, Material().diffuse({1.0, 1.0, 1.0})},//
|
||||
});
|
||||
//carNode->setMaterial(Material().reflection_mapped(&t_reflection, 0.0).no_colors().no_texture_reset(), true);
|
||||
carNode->position = {500, 500, 100};
|
||||
carNode->scale *= 100;
|
||||
rootNode->children.push_back(carNode);
|
||||
*/
|
||||
|
||||
//create the scene:
|
||||
plainNode = createSceneNode();
|
||||
|
|
|
@ -14,6 +14,7 @@ void SceneNode::setMesh(const Mesh* mesh) {
|
|||
vertexArrayObjectID = cache[mesh];
|
||||
VAOIndexCount = mesh->indices.size();
|
||||
isVertexColored = ! mesh->colors.empty();
|
||||
m_gemoetry = mesh;
|
||||
}
|
||||
void SceneNode::setTexture(
|
||||
const PNGImage* diffuse,
|
||||
|
@ -27,6 +28,7 @@ void SceneNode::setTexture(
|
|||
isNormalMapped = false;
|
||||
isDisplacementMapped = false;
|
||||
isReflectionMapped = false;
|
||||
t_diffuse = nullptr;
|
||||
}
|
||||
|
||||
if (diffuse) {
|
||||
|
@ -34,6 +36,7 @@ void SceneNode::setTexture(
|
|||
cache[diffuse] = generateTexture(*diffuse);
|
||||
diffuseTextureID = cache[diffuse];
|
||||
isTextured = true;
|
||||
t_diffuse = diffuse;
|
||||
}
|
||||
|
||||
if (normal) {
|
||||
|
@ -74,6 +77,22 @@ void SceneNode::setMaterial(const Material& mat, bool recursive) {
|
|||
child->setMaterial(mat, true);
|
||||
}
|
||||
|
||||
bool SceneNode::has_transparancy() const {
|
||||
return opacity < 1.0
|
||||
|| t_diffuse && t_diffuse->has_transparancy
|
||||
|| m_gemoetry && m_gemoetry->has_transparancy;
|
||||
}
|
||||
|
||||
SceneNode* SceneNode::clone() const {
|
||||
SceneNode* out = new SceneNode();
|
||||
*out = *this;
|
||||
out->children.clear();
|
||||
for (SceneNode* child : children) {
|
||||
out->children.push_back(child->clone());
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
SceneNode* createSceneNode() {
|
||||
return new SceneNode();
|
||||
|
|
|
@ -42,6 +42,8 @@ struct SceneNode {
|
|||
const PNGImage* reflection=nullptr,
|
||||
bool texture_reset=true);
|
||||
void setMaterial(const Material& mat, bool recursive=false);
|
||||
bool has_transparancy() const;
|
||||
SceneNode* clone() const;
|
||||
|
||||
// this node
|
||||
SceneNodeType nodeType;
|
||||
|
@ -57,7 +59,7 @@ struct SceneNode {
|
|||
|
||||
// The node's position and rotation relative to its parent
|
||||
vec3 position = vec3(0, 0, 0);
|
||||
vec3 rotation = vec3(0, 0, 0); // also used as spot-target
|
||||
vec3 rotation = vec3(0, 0, 0);
|
||||
vec3 scale = vec3(1, 1, 1);
|
||||
vec3 referencePoint = vec3(0, 0, 0); // center of rotation, in model space
|
||||
|
||||
|
@ -78,7 +80,11 @@ struct SceneNode {
|
|||
uint displacementTextureID;
|
||||
float displacementCoefficient = 0.1; // in units
|
||||
uint reflectionTextureID;
|
||||
|
||||
|
||||
// has_transparancy
|
||||
const Mesh* m_gemoetry = nullptr;
|
||||
const PNGImage* t_diffuse = nullptr;
|
||||
|
||||
// shader flags
|
||||
bool isTextured = false;
|
||||
bool isVertexColored = false;
|
||||
|
|
|
@ -58,7 +58,14 @@ PNGImage loadPNGFile(string filename, bool flip_handedness) {
|
|||
image.width = width;
|
||||
image.height = height;
|
||||
image.pixels = pixels;
|
||||
|
||||
|
||||
for (uint i = 3; i < pixels.size(); i+=4) {
|
||||
if (pixels[i] < 255) {
|
||||
image.has_transparancy = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ struct PNGImage {
|
|||
uint width, height;
|
||||
bool repeat_mirrored = false;
|
||||
std::vector<unsigned char> pixels; // RGBA
|
||||
bool has_transparancy = false;
|
||||
};
|
||||
|
||||
PNGImage loadPNGFile(std::string filename, bool flip_handedness=false);
|
||||
|
|
|
@ -10,4 +10,6 @@ struct Mesh {
|
|||
std::vector<glm::vec4> colors;
|
||||
|
||||
std::vector<unsigned int> indices;
|
||||
|
||||
bool has_transparancy = false; // if any of the colors are transparent
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue