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);
|
glEnable(GL_CULL_FACE);
|
||||||
|
|
||||||
//enable alpha
|
//enable alpha
|
||||||
glEnable(GL_BLEND);
|
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
|
||||||
// Set default colour after clearing the colour buffer
|
// Set default colour after clearing the colour buffer
|
||||||
glClearColor(0.3f, 0.5f, 0.8f, 1.0f);
|
glClearColor(0.3f, 0.5f, 0.8f, 1.0f);
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include <glm/vec3.hpp>
|
#include <glm/vec3.hpp>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <algorithm>
|
||||||
#include <utilities/glfont.h>
|
#include <utilities/glfont.h>
|
||||||
#include <utilities/shader.hpp>
|
#include <utilities/shader.hpp>
|
||||||
#include <utilities/timeutils.h>
|
#include <utilities/timeutils.h>
|
||||||
|
@ -119,7 +120,14 @@ void updateFrame(GLFWwindow* window, int windowWidth, int windowHeight) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// traverses and renders one and one node
|
// 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
|
struct Light { // lights as stored in the shader
|
||||||
// coordinates in MV space
|
// coordinates in MV space
|
||||||
vec3 position; // MV
|
vec3 position; // MV
|
||||||
|
@ -158,7 +166,11 @@ void renderNode(SceneNode* node, Gloom::Shader* parent_shader) {
|
||||||
|
|
||||||
switch(node->nodeType) {
|
switch(node->nodeType) {
|
||||||
case GEOMETRY:
|
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
|
// load uniforms
|
||||||
glUniformMatrix4fv(s->location("MVP") , 1, GL_FALSE, glm::value_ptr(node->MVP));
|
glUniformMatrix4fv(s->location("MVP") , 1, GL_FALSE, glm::value_ptr(node->MVP));
|
||||||
glUniformMatrix4fv(s->location("MV") , 1, GL_FALSE, glm::value_ptr(node->MV));
|
glUniformMatrix4fv(s->location("MV") , 1, GL_FALSE, glm::value_ptr(node->MV));
|
||||||
|
@ -203,8 +215,9 @@ void renderNode(SceneNode* node, Gloom::Shader* parent_shader) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (do_recursive)
|
||||||
for(SceneNode* child : node->children) {
|
for(SceneNode* child : node->children) {
|
||||||
renderNode(child, node_shader);
|
renderNode(child, node_shader, transparent_nodes, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -212,7 +225,27 @@ void renderNode(SceneNode* node, Gloom::Shader* parent_shader) {
|
||||||
void renderFrame(GLFWwindow* window, int windowWidth, int windowHeight) {
|
void renderFrame(GLFWwindow* window, int windowWidth, int windowHeight) {
|
||||||
glViewport(0, 0, windowWidth, windowHeight);
|
glViewport(0, 0, windowWidth, windowHeight);
|
||||||
|
|
||||||
|
static vector<NodeDistShader> transparent_nodes;
|
||||||
|
transparent_nodes.clear();
|
||||||
|
|
||||||
// externs from scene.hpp, they must have shaders set
|
// 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);
|
renderNode(hudNode, nullptr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <glad/glad.h>
|
#include <glad/glad.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <cstdlib>
|
||||||
#include <utilities/imageLoader.hpp>
|
#include <utilities/imageLoader.hpp>
|
||||||
#include <utilities/modelLoader.hpp>
|
#include <utilities/modelLoader.hpp>
|
||||||
#include <utilities/mesh.h>
|
#include <utilities/mesh.h>
|
||||||
|
@ -73,11 +74,31 @@ void init_scene(CommandLineOptions options) {
|
||||||
rootNode->children.push_back(lightNode[i]);
|
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};
|
//treeNode->position = {300, 800, 10};
|
||||||
//rootNode->children.push_back(treeNode);
|
//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
|
{ 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)
|
{ 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
|
//{ 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
|
{ 4, Material().no_colors().reflection_mapped(&t_reflection, 1.0)},// Mirror
|
||||||
//{ 5, Material().diffuse({1.0, 1.0, 1.0})},// Black_Metal
|
//{ 5, Material().diffuse({1.0, 1.0, 1.0})},// Black_Metal
|
||||||
//{ 6, Material().diffuse({1.0, 1.0, 1.0})},// Plastic
|
//{ 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
|
{ 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
|
//{ 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
|
{ 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
|
//{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
|
{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
|
//{12, Material().diffuse({1.0, 1.0, 1.0})},// License_Plate_Frame
|
||||||
//{13, Material().diffuse({1.0, 1.0, 1.0})},//
|
//{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->position = {500, 500, 100};
|
||||||
carNode->scale *= 100;
|
carNode->scale *= 100;
|
||||||
rootNode->children.push_back(carNode);
|
rootNode->children.push_back(carNode);
|
||||||
|
*/
|
||||||
|
|
||||||
//create the scene:
|
//create the scene:
|
||||||
plainNode = createSceneNode();
|
plainNode = createSceneNode();
|
||||||
|
|
|
@ -14,6 +14,7 @@ void SceneNode::setMesh(const Mesh* mesh) {
|
||||||
vertexArrayObjectID = cache[mesh];
|
vertexArrayObjectID = cache[mesh];
|
||||||
VAOIndexCount = mesh->indices.size();
|
VAOIndexCount = mesh->indices.size();
|
||||||
isVertexColored = ! mesh->colors.empty();
|
isVertexColored = ! mesh->colors.empty();
|
||||||
|
m_gemoetry = mesh;
|
||||||
}
|
}
|
||||||
void SceneNode::setTexture(
|
void SceneNode::setTexture(
|
||||||
const PNGImage* diffuse,
|
const PNGImage* diffuse,
|
||||||
|
@ -27,6 +28,7 @@ void SceneNode::setTexture(
|
||||||
isNormalMapped = false;
|
isNormalMapped = false;
|
||||||
isDisplacementMapped = false;
|
isDisplacementMapped = false;
|
||||||
isReflectionMapped = false;
|
isReflectionMapped = false;
|
||||||
|
t_diffuse = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (diffuse) {
|
if (diffuse) {
|
||||||
|
@ -34,6 +36,7 @@ void SceneNode::setTexture(
|
||||||
cache[diffuse] = generateTexture(*diffuse);
|
cache[diffuse] = generateTexture(*diffuse);
|
||||||
diffuseTextureID = cache[diffuse];
|
diffuseTextureID = cache[diffuse];
|
||||||
isTextured = true;
|
isTextured = true;
|
||||||
|
t_diffuse = diffuse;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (normal) {
|
if (normal) {
|
||||||
|
@ -74,6 +77,22 @@ void SceneNode::setMaterial(const Material& mat, bool recursive) {
|
||||||
child->setMaterial(mat, true);
|
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() {
|
SceneNode* createSceneNode() {
|
||||||
return new SceneNode();
|
return new SceneNode();
|
||||||
|
|
|
@ -42,6 +42,8 @@ struct SceneNode {
|
||||||
const PNGImage* reflection=nullptr,
|
const PNGImage* reflection=nullptr,
|
||||||
bool texture_reset=true);
|
bool texture_reset=true);
|
||||||
void setMaterial(const Material& mat, bool recursive=false);
|
void setMaterial(const Material& mat, bool recursive=false);
|
||||||
|
bool has_transparancy() const;
|
||||||
|
SceneNode* clone() const;
|
||||||
|
|
||||||
// this node
|
// this node
|
||||||
SceneNodeType nodeType;
|
SceneNodeType nodeType;
|
||||||
|
@ -57,7 +59,7 @@ struct SceneNode {
|
||||||
|
|
||||||
// The node's position and rotation relative to its parent
|
// The node's position and rotation relative to its parent
|
||||||
vec3 position = vec3(0, 0, 0);
|
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 scale = vec3(1, 1, 1);
|
||||||
vec3 referencePoint = vec3(0, 0, 0); // center of rotation, in model space
|
vec3 referencePoint = vec3(0, 0, 0); // center of rotation, in model space
|
||||||
|
|
||||||
|
@ -79,6 +81,10 @@ struct SceneNode {
|
||||||
float displacementCoefficient = 0.1; // in units
|
float displacementCoefficient = 0.1; // in units
|
||||||
uint reflectionTextureID;
|
uint reflectionTextureID;
|
||||||
|
|
||||||
|
// has_transparancy
|
||||||
|
const Mesh* m_gemoetry = nullptr;
|
||||||
|
const PNGImage* t_diffuse = nullptr;
|
||||||
|
|
||||||
// shader flags
|
// shader flags
|
||||||
bool isTextured = false;
|
bool isTextured = false;
|
||||||
bool isVertexColored = false;
|
bool isVertexColored = false;
|
||||||
|
|
|
@ -59,6 +59,13 @@ PNGImage loadPNGFile(string filename, bool flip_handedness) {
|
||||||
image.height = height;
|
image.height = height;
|
||||||
image.pixels = pixels;
|
image.pixels = pixels;
|
||||||
|
|
||||||
|
for (uint i = 3; i < pixels.size(); i+=4) {
|
||||||
|
if (pixels[i] < 255) {
|
||||||
|
image.has_transparancy = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ struct PNGImage {
|
||||||
uint width, height;
|
uint width, height;
|
||||||
bool repeat_mirrored = false;
|
bool repeat_mirrored = false;
|
||||||
std::vector<unsigned char> pixels; // RGBA
|
std::vector<unsigned char> pixels; // RGBA
|
||||||
|
bool has_transparancy = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
PNGImage loadPNGFile(std::string filename, bool flip_handedness=false);
|
PNGImage loadPNGFile(std::string filename, bool flip_handedness=false);
|
||||||
|
|
|
@ -10,4 +10,6 @@ struct Mesh {
|
||||||
std::vector<glm::vec4> colors;
|
std::vector<glm::vec4> colors;
|
||||||
|
|
||||||
std::vector<unsigned int> indices;
|
std::vector<unsigned int> indices;
|
||||||
|
|
||||||
|
bool has_transparancy = false; // if any of the colors are transparent
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue