From 511b26ec82e8d9e281ae92518c13770a59c52552 Mon Sep 17 00:00:00 2001 From: Ben Carey Date: Sat, 10 Aug 2019 23:50:07 +0100 Subject: [PATCH] midway through adding the polygon and leaf stuff to the forest class, it's not running atm though :/ --- ForestGenerator/include/Instance.h | 6 + ForestGenerator/include/InstanceCacheMacros.h | 4 +- ForestGenerator/include/LSystem.h | 22 ++-- ForestGenerator/include/NGLScene.h | 12 +- .../shaders/ForestLeafFragment.glsl | 14 +++ .../shaders/ForestLeafGeometry.glsl | 32 +++++ ForestGenerator/shaders/ForestLeafVertex.glsl | 20 ++++ .../shaders/ForestPolygonFragment.glsl | 11 ++ .../shaders/ForestPolygonVertex.glsl | 14 +++ ForestGenerator/shaders/ForestVertex.glsl | 6 +- ForestGenerator/shaders/TerrainFragment.glsl | 2 +- .../src/LSystem_CreateGeometry.cpp | 107 ++++++++++------- .../src/LSystem_InstanceMethods.cpp | 7 ++ ForestGenerator/src/NGLScene.cpp | 46 +++++--- ForestGenerator/src/NGLScene_VAOBuilding.cpp | 109 +++++++++++++++--- 15 files changed, 329 insertions(+), 83 deletions(-) create mode 100644 ForestGenerator/shaders/ForestLeafFragment.glsl create mode 100644 ForestGenerator/shaders/ForestLeafGeometry.glsl create mode 100644 ForestGenerator/shaders/ForestLeafVertex.glsl create mode 100644 ForestGenerator/shaders/ForestPolygonFragment.glsl create mode 100644 ForestGenerator/shaders/ForestPolygonVertex.glsl diff --git a/ForestGenerator/include/Instance.h b/ForestGenerator/include/Instance.h index 4d910f2..b0e9617 100644 --- a/ForestGenerator/include/Instance.h +++ b/ForestGenerator/include/Instance.h @@ -34,6 +34,12 @@ struct Instance size_t m_instanceEnd; //std::vector m_indices; + size_t m_instanceLeafStart; + size_t m_instanceLeafEnd; + + size_t m_instancePolygonStart; + size_t m_instancePolygonEnd; + struct ExitPoint { ExitPoint(size_t _exitId, size_t _exitAge, ngl::Mat4 _transform); diff --git a/ForestGenerator/include/InstanceCacheMacros.h b/ForestGenerator/include/InstanceCacheMacros.h index 8e27900..021f86b 100644 --- a/ForestGenerator/include/InstanceCacheMacros.h +++ b/ForestGenerator/include/InstanceCacheMacros.h @@ -19,8 +19,8 @@ /// of variable, I have created the following macros to reduce repetition and improve readability of the code /// /// (I initially tried to do this with a templated class, but ran into issues when I tried to pass a unique -/// pointer as the template argument, since some of the methods would have required calling the copy constructor -/// of the unique pointer) +/// pointer as the template argument (for the VAOs in the NGLScene class) since some of the methods would have +/// required calling the deleted copy constructor of the unique pointer) //---------------------------------------------------------------------------------------------------------------------- #define CACHE_STRUCTURE(_class) std::vector>> diff --git a/ForestGenerator/include/LSystem.h b/ForestGenerator/include/LSystem.h index 3bd74eb..a8d3c79 100644 --- a/ForestGenerator/include/LSystem.h +++ b/ForestGenerator/include/LSystem.h @@ -159,22 +159,30 @@ class LSystem std::vector m_rightVectors; std::vector m_thicknessValues; - std::vector m_heroVertices = {}; - std::vector m_heroIndices= {}; - std::vector m_heroRightVectors = {}; - std::vector m_heroThicknessValues= {}; - std::vector m_leafVertices = {}; - std::vector m_leafIndices = {}; + std::vector m_leafIndices = {}; std::vector m_leafDirections = {}; std::vector m_leafRightVectors = {}; //polygons will be drawn with gl triangles not triangle strips //to allow for multiple ones in different places std::vector m_polygonVertices = {}; - std::vector m_polygonIndices = {}; + std::vector m_polygonIndices = {}; //std::vector m_polygonRightVectors = {}; + std::vector m_heroVertices = {}; + std::vector m_heroIndices= {}; + std::vector m_heroRightVectors = {}; + std::vector m_heroThicknessValues= {}; + + std::vector m_heroLeafVertices = {}; + std::vector m_heroLeafIndices = {}; + std::vector m_heroLeafDirections = {}; + std::vector m_heroLeafRightVectors = {}; + + std::vector m_heroPolygonVertices = {}; + std::vector m_heroPolygonIndices = {}; + size_t m_maxInstancePerLevel = 10; bool m_forestMode = false; diff --git a/ForestGenerator/include/NGLScene.h b/ForestGenerator/include/NGLScene.h index e742038..090abe9 100644 --- a/ForestGenerator/include/NGLScene.h +++ b/ForestGenerator/include/NGLScene.h @@ -267,6 +267,8 @@ public slots: //third layer separates by age //inner index corresponds to different instances of a given age and id std::vector)> m_forestVAOs; + std::vector)> m_forestLeafVAOs; + std::vector)> m_forestPolygonVAOs; //---------------------------------------------------------------------------------------------------------------------- /// @brief bool to tell paintGL whether or not we need to rebuild the current LSystem VAO @@ -350,9 +352,12 @@ public slots: void buildSimpleIndexVAO(std::unique_ptr &_vao, std::vector &_vertices, std::vector &_indices, GLenum _mode, GLenum _indexType); - void buildInstanceCacheVAO(std::unique_ptr &_vao, +/* void buildInstanceCacheVAO(std::unique_ptr &_vao, LSystem &_treeType, Instance &_instance, - std::vector &_transforms); + std::vector &_transforms);*/ + void buildInstanceCacheVAO(std::unique_ptr &_vao, std::vector &_vertices, + std::vector &_indices, std::vector &_transforms, + Instance &_instance, GLenum _mode); void addBufferToBoundVAO(size_t _bufferSize, const GLvoid * _bufferData); void buildGridVAO(); @@ -361,6 +366,9 @@ public slots: void buildLeafVAO(size_t _treeNum); void buildPolygonVAO(size_t _treeNum); + void buildForestVAO(size_t _treeNum, size_t _id, size_t _age, size_t _index); + void buildForestLeafVAO(size_t _treeNum, size_t _id, size_t _age, size_t _index); + void buildForestPolygonVAO(size_t _treeNum, size_t _id, size_t _age, size_t _index); void buildForestVAOs(); void loadTextures(ngl::ShaderLib *_shader, const std::string &_shaderName, diff --git a/ForestGenerator/shaders/ForestLeafFragment.glsl b/ForestGenerator/shaders/ForestLeafFragment.glsl new file mode 100644 index 0000000..bdf8d44 --- /dev/null +++ b/ForestGenerator/shaders/ForestLeafFragment.glsl @@ -0,0 +1,14 @@ +#version 330 core + +in vec2 UV; + +uniform sampler2D textureMap; + +/// @brief our output fragment colour +layout (location =0)out vec4 fragColour; + +void main () +{ + fragColour = texture(textureMap, UV); + fragColour.a = step(0.0000000000001, fragColour.r+fragColour.g+fragColour.b); +} diff --git a/ForestGenerator/shaders/ForestLeafGeometry.glsl b/ForestGenerator/shaders/ForestLeafGeometry.glsl new file mode 100644 index 0000000..add5c22 --- /dev/null +++ b/ForestGenerator/shaders/ForestLeafGeometry.glsl @@ -0,0 +1,32 @@ +#version 330 core + +layout (points) in; +layout (triangle_strip, max_vertices=4) out; + +in vec4 dir[1]; +in vec4 right[1]; + +uniform mat4 MVP; + +out vec2 UV; + +void main () +{ + gl_Position = gl_in[0].gl_Position + 0.5*right[0]; + UV = vec2(1,0); + EmitVertex(); + + gl_Position = gl_in[0].gl_Position + 0.5*right[0] + dir[0]; + UV = vec2(1,1); + EmitVertex(); + + gl_Position = gl_in[0].gl_Position - 0.5*right[0]; + UV = vec2(0,0); + EmitVertex(); + + gl_Position = gl_in[0].gl_Position - 0.5*right[0] + dir[0]; + UV = vec2(0,1); + EmitVertex(); + + EndPrimitive(); +} diff --git a/ForestGenerator/shaders/ForestLeafVertex.glsl b/ForestGenerator/shaders/ForestLeafVertex.glsl new file mode 100644 index 0000000..1e8ca3e --- /dev/null +++ b/ForestGenerator/shaders/ForestLeafVertex.glsl @@ -0,0 +1,20 @@ +#version 330 core + +/// @brief the vertex passed in +layout(location =0)in vec3 inVert; +layout(location =1)in mat4 inTransform; +layout(location =5)in vec3 inDir; +layout(location =6)in vec3 inRight; + +uniform mat4 MVP; +//out vec3 vertColour; +out vec4 dir; +out vec4 right; + +void main() +{ + gl_Position = MVP * inTransform * vec4(inVert,1.0); + dir = MVP * inTransform * vec4(inDir,0); + right = MVP * inTransform * vec4(inRight,0); + //vertColour = vec3(1,0,0); +} diff --git a/ForestGenerator/shaders/ForestPolygonFragment.glsl b/ForestGenerator/shaders/ForestPolygonFragment.glsl new file mode 100644 index 0000000..7dbe7fc --- /dev/null +++ b/ForestGenerator/shaders/ForestPolygonFragment.glsl @@ -0,0 +1,11 @@ +#version 330 core + +in vec3 vertColour; + +/// @brief our output fragment colour +layout (location =0)out vec4 fragColour; + +void main () +{ + fragColour = vec4(vertColour,1); +} diff --git a/ForestGenerator/shaders/ForestPolygonVertex.glsl b/ForestGenerator/shaders/ForestPolygonVertex.glsl new file mode 100644 index 0000000..d48ba94 --- /dev/null +++ b/ForestGenerator/shaders/ForestPolygonVertex.glsl @@ -0,0 +1,14 @@ +#version 330 core + +/// @brief the vertex passed in +layout(location =0)in vec3 inVert; +layout(location =1)in mat4 inTransform; + +uniform mat4 MVP; +out vec3 vertColour; + +void main() +{ + gl_Position = MVP * inTransform * vec4(inVert,1.0); + vertColour = vec3(0.3,0.3,0.3); +} diff --git a/ForestGenerator/shaders/ForestVertex.glsl b/ForestGenerator/shaders/ForestVertex.glsl index b784ded..fe2edfb 100644 --- a/ForestGenerator/shaders/ForestVertex.glsl +++ b/ForestGenerator/shaders/ForestVertex.glsl @@ -2,7 +2,7 @@ /// @brief the vertex passed in layout(location =0)in vec3 inVert; -layout(location =1)in mat4 transform; +layout(location =1)in mat4 inTransform; layout(location =5)in vec3 inRightVector; layout(location =6)in float inThicknessValues; @@ -17,10 +17,10 @@ void main() { //Note that this is identical to the treeVertex shader except that //we multiply the positions by transform - gl_Position = MVP * transform * vec4(inVert,1.0); + gl_Position = MVP * inTransform * vec4(inVert,1.0); vertCol = vec3(inVert[0]/10,inVert[1]/10,0); - worldSpacePos = vec3(transform * vec4(inVert,1)); + worldSpacePos = vec3(inTransform * vec4(inVert,1)); rightVector = inRightVector; thickness = inThicknessValues; } diff --git a/ForestGenerator/shaders/TerrainFragment.glsl b/ForestGenerator/shaders/TerrainFragment.glsl index 8cab11b..b5ebce8 100644 --- a/ForestGenerator/shaders/TerrainFragment.glsl +++ b/ForestGenerator/shaders/TerrainFragment.glsl @@ -46,7 +46,7 @@ void main () // fragColour = vec4(normal,1); fragColour = lightIntensity * texture(textureMap, UV); - fragColour.a = step(0.0000001, fragColour.r+fragColour.g+fragColour.b); + fragColour.a = 1;// step(0.0000001, fragColour.r+fragColour.g+fragColour.b); //fragColour = vec4(normal,1); //fragColour = vec4(vertColour,1); diff --git a/ForestGenerator/src/LSystem_CreateGeometry.cpp b/ForestGenerator/src/LSystem_CreateGeometry.cpp index 7b97bfc..74c9682 100644 --- a/ForestGenerator/src/LSystem_CreateGeometry.cpp +++ b/ForestGenerator/src/LSystem_CreateGeometry.cpp @@ -59,31 +59,43 @@ void LSystem::createGeometry() std::vector temporaryPolygon = {}; bool makingPolygon = false; - m_leafVertices = {}; - m_leafIndices = {}; - m_leafDirections = {}; - m_leafRightVectors = {}; - - m_polygonVertices = {}; - m_polygonIndices = {}; - //m_polygonRightVectors = {}; - + //set up pointers to buffers std::vector * vertices; std::vector * indices; std::vector * rightVectors; std::vector * thicknessValues; - + std::vector * leafVertices; + std::vector * leafIndices; + std::vector * leafDirections; + std::vector * leafRightVectors; + std::vector * polygonVertices; + std::vector * polygonIndices; + + //switch pointers to either hero buffers or regular buffers + //depending on whether we're building a single tree or a forest if(m_forestMode == false) { m_vertices = {lastVertex}; m_indices = {}; m_thicknessValues = {thickness}; m_rightVectors = {right}; + m_leafVertices = {}; + m_leafIndices = {}; + m_leafDirections = {}; + m_leafRightVectors = {}; + m_polygonVertices = {}; + m_polygonIndices = {}; vertices = &m_vertices; indices = &m_indices; rightVectors = &m_rightVectors; thicknessValues = &m_thicknessValues; + leafVertices = &m_leafVertices; + leafIndices = &m_leafIndices; + leafDirections = &m_leafDirections; + leafRightVectors = &m_leafRightVectors; + polygonVertices = &m_polygonVertices; + polygonIndices = &m_polygonIndices; } else { @@ -96,6 +108,12 @@ void LSystem::createGeometry() indices = &m_heroIndices; rightVectors = &m_heroRightVectors; thicknessValues = &m_heroThicknessValues; + leafVertices = &m_heroLeafVertices; + leafIndices = &m_heroLeafIndices; + leafDirections = &m_heroLeafDirections; + leafRightVectors = &m_heroLeafRightVectors; + polygonVertices = &m_heroPolygonVertices; + polygonIndices = &m_heroPolygonIndices; } for(size_t i=0; i0) { - size_t offset = m_polygonVertices.size(); + size_t offset = polygonVertices->size(); size_t n = temporaryPolygon.size(); - //we want these indices: //but we need to reverse every other one for winding to be correct: + //we want these indices: //but reverse every other one for correct winding: // 0,1,(n-1) 0,1,(n-1) // 1,(n-1),2 (n-1),1,2 // (n-1),2,(n-2) (n-1),2,(n-2) @@ -153,44 +181,34 @@ void LSystem::createGeometry() // (n-2),3,(n-3) (n-2),3,(n-3) // 3,(n-3),4 (n-3),3,4 // ... ... - m_polygonIndices.push_back(GLushort(offset+0)); - m_polygonIndices.push_back(GLushort(offset+1)); - m_polygonIndices.push_back(GLushort(offset+n-1)); + polygonIndices->push_back(GLushort(offset+0)); + polygonIndices->push_back(GLushort(offset+1)); + polygonIndices->push_back(GLushort(offset+n-1)); for(size_t i=1; i<1+temporaryPolygon.size()/2; i++) { - m_polygonIndices.push_back(GLushort(offset+n-i)); - m_polygonIndices.push_back(GLushort(offset+i)); - m_polygonIndices.push_back(GLushort(offset+i+1)); + polygonIndices->push_back(GLushort(offset+n-i)); + polygonIndices->push_back(GLushort(offset+i)); + polygonIndices->push_back(GLushort(offset+i+1)); - m_polygonIndices.push_back(GLushort(offset+n-i)); - m_polygonIndices.push_back(GLushort(offset+i+1)); - m_polygonIndices.push_back(GLushort(offset+n-i-1)); + polygonIndices->push_back(GLushort(offset+n-i)); + polygonIndices->push_back(GLushort(offset+i+1)); + polygonIndices->push_back(GLushort(offset+n-i-1)); } - m_polygonVertices.insert(m_polygonVertices.end(), - temporaryPolygon.begin(), - temporaryPolygon.end()); + polygonVertices->insert(polygonVertices->end(), + temporaryPolygon.begin(), + temporaryPolygon.end()); temporaryPolygon = {}; } break; } - //add point to polygon - case '.': - { - if(makingPolygon) - { - temporaryPolygon.push_back(lastVertex); - } - break; - } - //add default leaf case 'J': { - m_leafVertices.push_back(lastVertex); - m_leafIndices.push_back(GLushort(m_leafVertices.size()-1)); - m_leafDirections.push_back(dir); - m_leafRightVectors.push_back(right); + leafVertices->push_back(lastVertex); + leafIndices->push_back(GLushort(leafVertices->size()-1)); + leafDirections->push_back(dir); + leafRightVectors->push_back(right); break; } @@ -342,6 +360,9 @@ void LSystem::createGeometry() instance = Instance(transform); instance.m_instanceStart = indices->size(); + instance.m_instanceLeafStart = leafIndices->size(); + instance.m_instancePolygonStart = polygonIndices->size(); + //if instance cache isn't already too full at this id, add this instance to it if(m_instanceCache[id][age].size()<=size_t(m_maxInstancePerLevel/(age+1))) { m_instanceCache[id][age].push_back(instance); @@ -360,6 +381,8 @@ void LSystem::createGeometry() case '$': { currentInstance->m_instanceEnd = indices->size(); + currentInstance->m_instanceLeafEnd = leafIndices->size(); + currentInstance->m_instancePolygonEnd = polygonIndices->size(); savedInstance.pop_back(); if(savedInstance.size()>0) { @@ -385,11 +408,13 @@ void LSystem::createGeometry() instance->m_exitPoints.push_back(Instance::ExitPoint(id, age, instance->m_transform.inverse()*transform)); } - //if the instance cachec currently has no entries for this (id,age) pair, add a new instance to it + //if the instance cache currently has no entries for this (id,age) pair, add a new instance to it if(m_instanceCache[id][age].size()==0) { instance = Instance(transform); instance.m_instanceStart = indices->size(); + instance.m_instanceLeafStart = leafIndices->size(); + instance.m_instancePolygonStart = polygonIndices->size(); m_instanceCache[id][age].push_back(instance); currentInstance = &m_instanceCache[id][age].back(); savedInstance.push_back(currentInstance); @@ -408,6 +433,8 @@ void LSystem::createGeometry() //note that assuming > doesn't appear in any rules, we will only reach this //case if we are using the corresponding < to make an instance currentInstance->m_instanceEnd = indices->size(); + currentInstance->m_instanceLeafEnd = leafIndices->size(); + currentInstance->m_instancePolygonEnd = polygonIndices->size(); savedInstance.pop_back(); if(savedInstance.size()>0) { @@ -467,7 +494,7 @@ void LSystem::parseBrackets(const std::string &_treeString, size_t &_i, float &_ void LSystem::parseInstanceBrackets(const std::string &_treeString, size_t &_i, size_t &_id, size_t &_age) { - //don't need the outer if clause that parseBrackets() has because <, { are guaranteed to be followed by ( + //don't need the outer if clause that parseBrackets() has because <, @ are guaranteed to be followed by ( size_t j=_i+2; for( ; j<_treeString.size(); j++) { diff --git a/ForestGenerator/src/LSystem_InstanceMethods.cpp b/ForestGenerator/src/LSystem_InstanceMethods.cpp index 19c7626..edef299 100644 --- a/ForestGenerator/src/LSystem_InstanceMethods.cpp +++ b/ForestGenerator/src/LSystem_InstanceMethods.cpp @@ -127,10 +127,17 @@ void LSystem::fillInstanceCache(int _numHeroTrees) RESIZE_CACHE_BY_VALUES(m_instanceCache, m_branches.size(), size_t(m_generation)+1) m_forestMode = true; + m_heroIndices = {}; m_heroVertices = {}; m_heroRightVectors = {}; m_heroThicknessValues = {}; + m_heroLeafVertices = {}; + m_heroLeafIndices = {}; + m_heroLeafDirections = {}; + m_heroLeafRightVectors = {}; + m_heroPolygonVertices = {}; + m_heroPolygonIndices = {}; for(int i=0; i<_numHeroTrees; i++) { diff --git a/ForestGenerator/src/NGLScene.cpp b/ForestGenerator/src/NGLScene.cpp index 27cfaf7..d922fd4 100644 --- a/ForestGenerator/src/NGLScene.cpp +++ b/ForestGenerator/src/NGLScene.cpp @@ -66,22 +66,18 @@ NGLScene::~NGLScene() std::cout<<"Shutting down NGL, removing VAO's and Shaders\n"; m_gridVAO->removeVAO(); m_terrainVAO->removeVAO(); - for(auto &LSystemVAO : m_treeVAOs) - { - LSystemVAO->removeVAO(); - } - for(auto &LeafVAO : m_leafVAOs) - { - LeafVAO->removeVAO(); - } - for(auto &polygonVAO : m_polygonVAOs) + for(size_t i=0; iremoveVAO(); + m_treeVAOs[i]->removeVAO(); + m_leafVAOs[i]->removeVAO(); + m_polygonVAOs[i]->removeVAO(); } for(size_t t=0; tremoveVAO()) + m_forestVAOs[t][ID][AGE][INDEX]->removeVAO(); + m_forestLeafVAOs[t][ID][AGE][INDEX]->removeVAO(); + m_forestPolygonVAOs[t][ID][AGE][INDEX]->removeVAO()) } } @@ -116,6 +112,7 @@ void NGLScene::initializeGL() // now to load the shaders // grab an instance of shader manager ngl::ShaderLib *shader=ngl::ShaderLib::instance(); + shader->loadShader("SkeletalTreeShader", "shaders/SkeletalTreeVertex.glsl", "shaders/SkeletalTreeFragment.glsl"); shader->loadShader("TreeShader", "shaders/TreeVertex.glsl", @@ -124,12 +121,18 @@ void NGLScene::initializeGL() "shaders/LeafFragment.glsl", "shaders/LeafGeometry.glsl"); shader->loadShader("PolygonShader", "shaders/PolygonVertex.glsl", "shaders/PolygonFragment.glsl"); - shader->loadShader("GridShader", "shaders/GridVertex.glsl", - "shaders/GridFragment.glsl"); + shader->loadShader("SkeletalForestShader", "shaders/SkeletalForestVertex.glsl", "shaders/SkeletalForestFragment.glsl"); shader->loadShader("ForestShader", "shaders/ForestVertex.glsl", "shaders/ForestFragment.glsl", "shaders/ForestGeometry.glsl"); + shader->loadShader("ForestLeafShader", "shaders/ForestLeafVertex.glsl", + "shaders/ForestLeafFragment.glsl", "shaders/ForestLeafGeometry.glsl"); + shader->loadShader("ForestPolygonShader", "shaders/ForestPolygonVertex.glsl", + "shaders/ForestPolygonFragment.glsl"); + + shader->loadShader("GridShader", "shaders/GridVertex.glsl", + "shaders/GridFragment.glsl"); shader->loadShader("TerrainShader", "shaders/TerrainVertex.glsl", "shaders/TerrainFragment.glsl"); @@ -242,7 +245,7 @@ void NGLScene::paintGL() refineTerrain(); loadUniformsToShader(shader, "TerrainShader"); loadTextures(shader, "TerrainShader", - "textures/leaf2.jpg", + "textures/Lawn_grass_pxr128.jpg", "textures/Lawn_grass_pxr128_normal.jpg"); drawVAO(m_terrainVAO); } @@ -289,7 +292,20 @@ void NGLScene::paintGL() for(size_t t=0; t &_vao, std: //------------------------------------------------------------------------------------------------------------------------ -void NGLScene::buildInstanceCacheVAO(std::unique_ptr &_vao, LSystem &_treeType, +/*void NGLScene::buildInstanceCacheVAO(std::unique_ptr &_vao, LSystem &_treeType, Instance &_instance, std::vector &_transforms) { // create a vao using GL_LINES @@ -76,19 +76,34 @@ void NGLScene::buildInstanceCacheVAO(std::unique_ptr &_vao, LS &_transforms[0])); // set number of indices to length of current instance _vao->setNumIndices(_instance.m_instanceEnd-_instance.m_instanceStart); + _vao->unbind(); +}*/ - addBufferToBoundVAO(sizeof(ngl::Vec3)*_treeType.m_heroRightVectors.size(), - &_treeType.m_heroRightVectors[0].m_x); - _vao->setVertexAttributePointer(5,3,GL_FLOAT,12,0); - addBufferToBoundVAO(sizeof(ngl::Vec3)*_treeType.m_heroThicknessValues.size(), - &_treeType.m_heroThicknessValues[0]); - _vao->setVertexAttributePointer(6,1,GL_FLOAT,4,0); - +void NGLScene::buildInstanceCacheVAO(std::unique_ptr &_vao, std::vector &_vertices, + std::vector &_indices, std::vector &_transforms, + Instance &_instance, GLenum _mode) +{ + // create a vao using _mode + _vao=ngl::VAOFactory::createVAO("instanceCacheVAO",_mode); + _vao->bind(); + // set our data for the VAO: + // (1) vertexBufferSize, (2) vertexBufferStart, + // (3) indexBufferSize, (4) indexBufferStart, + // (5) transformBufferSize, (6) transformBufferStart + _vao->setData(ngl::InstanceCacheVAO::VertexData( + sizeof(ngl::Vec3)*_vertices.size(), + _vertices[0].m_x, + uint(_instance.m_instanceEnd-_instance.m_instanceStart), + &_indices[_instance.m_instanceStart], + uint(_transforms.size()), + &_transforms[0])); + // set number of indices to length of current instance + _vao->setNumIndices(_instance.m_instanceEnd-_instance.m_instanceStart); _vao->unbind(); } //------------------------------------------------------------------------------------------------------------------------ -/// Specific methods for each thing we need to draw: grid, tree, leaves, LSystem polygons, terrain and forest +/// Specific methods for each thing we need to draw: grid, tree, leaves, polygons, terrain and forest //------------------------------------------------------------------------------------------------------------------------ void NGLScene::buildGridVAO() @@ -172,6 +187,71 @@ void NGLScene::buildTerrainVAO() //------------------------------------------------------------------------------------------------------------------------ +void NGLScene::buildForestVAO(size_t _treeNum, size_t _id, size_t _age, size_t _index) +{ + LSystem &treeType = m_forest.m_treeTypes[_treeNum]; + CACHE_STRUCTURE(Instance) &instanceCache = treeType.m_instanceCache; + std::unique_ptr &vao = m_forestVAOs[_treeNum][_id][_age][_index]; + + buildInstanceCacheVAO(vao, + treeType.m_heroVertices, + treeType.m_heroIndices, + m_forest.m_transformCache[_treeNum][_id][_age][_index], + instanceCache[_id][_age][_index], + GL_LINES); + + m_forestVAOs[_treeNum][_id][_age][_index]->bind(); + addBufferToBoundVAO(sizeof(ngl::Vec3)*treeType.m_heroRightVectors.size(), + &treeType.m_heroRightVectors[0].m_x); + vao->setVertexAttributePointer(5,3,GL_FLOAT,12,0); + addBufferToBoundVAO(sizeof(ngl::Vec3)*treeType.m_heroThicknessValues.size(), + &treeType.m_heroThicknessValues[0]); + vao->setVertexAttributePointer(6,1,GL_FLOAT,4,0); + m_forestVAOs[_treeNum][_id][_age][_index]->unbind(); +} + +//------------------------------------------------------------------------------------------------------------------------ + +void NGLScene::buildForestLeafVAO(size_t _treeNum, size_t _id, size_t _age, size_t _index) +{ + LSystem &treeType = m_forest.m_treeTypes[_treeNum]; + CACHE_STRUCTURE(Instance) &instanceCache = treeType.m_instanceCache; + std::unique_ptr &vao = m_forestVAOs[_treeNum][_id][_age][_index]; + + buildInstanceCacheVAO(vao, + treeType.m_heroLeafVertices, + treeType.m_heroLeafIndices, + m_forest.m_transformCache[_treeNum][_id][_age][_index], + instanceCache[_id][_age][_index], + GL_POINTS); + + m_forestVAOs[_treeNum][_id][_age][_index]->bind(); + addBufferToBoundVAO(sizeof(ngl::Vec3)*treeType.m_heroLeafDirections.size(), + &treeType.m_heroLeafRightVectors[0].m_x); + vao->setVertexAttributePointer(5,3,GL_FLOAT,12,0); + addBufferToBoundVAO(sizeof(ngl::Vec3)*treeType.m_heroLeafRightVectors.size(), + &treeType.m_heroLeafRightVectors[0]); + vao->setVertexAttributePointer(6,3,GL_FLOAT,12,0); + m_forestVAOs[_treeNum][_id][_age][_index]->unbind(); +} + +//------------------------------------------------------------------------------------------------------------------------ + +void NGLScene::buildForestPolygonVAO(size_t _treeNum, size_t _id, size_t _age, size_t _index) +{ + LSystem &treeType = m_forest.m_treeTypes[_treeNum]; + CACHE_STRUCTURE(Instance) &instanceCache = treeType.m_instanceCache; + + buildInstanceCacheVAO(m_forestVAOs[_treeNum][_id][_age][_index], + treeType.m_heroPolygonVertices, + treeType.m_heroPolygonIndices, + m_forest.m_transformCache[_treeNum][_id][_age][_index], + instanceCache[_id][_age][_index], + GL_TRIANGLES); +} + +//------------------------------------------------------------------------------------------------------------------------ + void NGLScene::buildForestVAOs() { for(size_t t=0; t