Degenerated triangle strip and instancing

This commit is contained in:
hodasemi 2018-11-29 12:16:21 +01:00
parent a6705f6e6e
commit bd0175fcda
4 changed files with 100 additions and 100 deletions

View file

@ -16,6 +16,7 @@ uniform sampler2D rock;
uniform sampler2D alpha; uniform sampler2D alpha;
uniform sampler2D road; uniform sampler2D road;
uniform sampler2D specular_road; uniform sampler2D specular_road;
uniform sampler2D normal_road;
uniform sampler2D background; uniform sampler2D background;
uniform vec2 screenSize; uniform vec2 screenSize;
@ -40,12 +41,11 @@ vec4 getBackgroundColor()
void main() void main()
{ {
//surface geometry //surface geometry
//vec3 n = vec3(0, 1, 0);
vec3 dirToViewer = vec3(0, 1, 0); vec3 dirToViewer = vec3(0, 1, 0);
//material properties //material properties
//color = vec4(0.6, 0.6, 0.6, 1); float angle = acos(dot(n, dirToViewer));
color = mix(texture(grass, uv), texture(rock, uv), dot(n, dirToViewer)); color = mix(texture(grass, uv), texture(rock, uv), angle * angle);
color = mix(color, texture(road, road_uv), texture(alpha, uv).x); color = mix(color, texture(road, road_uv), texture(alpha, uv).x);
float specular = texture(specular_road, road_uv).x; float specular = texture(specular_road, road_uv).x;

View file

@ -4,6 +4,7 @@
// Copyright (C) CGV TU Dresden - All Rights Reserved // Copyright (C) CGV TU Dresden - All Rights Reserved
in vec4 position; in vec4 position;
in vec2 offset;
out vec3 n; out vec3 n;
out vec2 uv; out vec2 uv;
@ -28,11 +29,12 @@ const vec2 offsets[6] = vec2[6](
void main() void main()
{ {
vec4 terrain_position = vec4(position.x, getTerrainHeight(vec2(position.x, position.z)), position.z, position.w); vec2 instanced_pos = vec2(position.x + offset.x, position.z + offset.y);
vec4 terrain_position = vec4(instanced_pos.x, getTerrainHeight(instanced_pos), instanced_pos.y, position.w);
n = calculate_normal(terrain_position); n = calculate_normal(terrain_position);
//n = vec3(0.0, 1.0, 0.0); //n = vec3(0.0, 1.0, 0.0);
uv = vec2(terrain_position.x / 255.0, terrain_position.z / 255.0); uv = vec2(terrain_position.x / 25.5, terrain_position.z / 25.5);
road_uv = offsets[gl_VertexID % 6]; road_uv = offsets[gl_VertexID % 6];
gl_Position = mvp * terrain_position; gl_Position = mvp * terrain_position;

View file

@ -23,8 +23,6 @@ class Viewer : public nse::gui::AbstractViewer
private: private:
void RenderSky(); void RenderSky();
Counter counter;
Eigen::Matrix4f view, proj; Eigen::Matrix4f view, proj;
nse::gui::GLShader skyShader; nse::gui::GLShader skyShader;
@ -35,9 +33,6 @@ class Viewer : public nse::gui::AbstractViewer
nse::gui::GLBuffer terrainPositions; nse::gui::GLBuffer terrainPositions;
nse::gui::GLBuffer terrainIndices; nse::gui::GLBuffer terrainIndices;
nse::gui::GLVertexArray referenceVAO;
nse::gui::GLBuffer referenceVB, referenceIB;
GLuint grassTexture, rockTexture, roadColorTexture, roadNormalMap, roadSpecularMap, alphaMap; GLuint grassTexture, rockTexture, roadColorTexture, roadNormalMap, roadSpecularMap, alphaMap;
GLint grass_texture_location; GLint grass_texture_location;
@ -45,8 +40,12 @@ class Viewer : public nse::gui::AbstractViewer
GLint alpha_texture_location; GLint alpha_texture_location;
GLint road_texture_location; GLint road_texture_location;
GLint road_specular_location; GLint road_specular_location;
GLint road_normal_location;
GLint offset_buffer_location;
nse::gui::GLBuffer offsetBuffer; nse::gui::GLBuffer offsetBuffer;
GLuint backgroundFBO, backgroundTexture; GLuint backgroundFBO, backgroundTexture;
std::vector<Eigen::Vector2f> offsets;
}; };

View file

@ -20,23 +20,13 @@
#include <sstream> #include <sstream>
#include <cmath> #include <cmath>
//using vec4 = Eigen::Vector4f; constexpr uint32_t PATCH_SIZE = 256; //number of vertices along one side of the terrain patch
/* constexpr int max_offset = 5;
#define Eigen::Vector4f vec4
#define Eigen::Vector3f vec3
#define Eigen::Vector2f vec2
*/
constexpr bool REFERENCE = false;
constexpr uint32_t PATCH_SIZE = 32; //number of vertices along one side of the terrain patch
constexpr int elements = PATCH_SIZE * 12;
Viewer::Viewer() Viewer::Viewer()
: AbstractViewer("CG1 Exercise 2"), : AbstractViewer("CG1 Exercise 2"),
terrainPositions(nse::gui::VertexBuffer), terrainIndices(nse::gui::IndexBuffer), terrainPositions(nse::gui::VertexBuffer), terrainIndices(nse::gui::IndexBuffer),
offsetBuffer(nse::gui::VertexBuffer), offsetBuffer(nse::gui::VertexBuffer)
referenceVB(nse::gui::VertexBuffer), referenceIB(nse::gui::IndexBuffer),
counter(elements, 0.5)
{ {
LoadShaders(); LoadShaders();
CreateGeometry(); CreateGeometry();
@ -46,6 +36,8 @@ Viewer::Viewer()
alpha_texture_location = terrainShader.uniform("alpha"); alpha_texture_location = terrainShader.uniform("alpha");
road_texture_location = terrainShader.uniform("road"); road_texture_location = terrainShader.uniform("road");
road_specular_location = terrainShader.uniform("specular_road"); road_specular_location = terrainShader.uniform("specular_road");
offset_buffer_location = terrainShader.attrib("offset");
road_normal_location = terrainShader.attrib("normal_road");
//Create a texture and framebuffer for the background //Create a texture and framebuffer for the background
glGenFramebuffers(1, &backgroundFBO); glGenFramebuffers(1, &backgroundFBO);
@ -57,6 +49,12 @@ Viewer::Viewer()
camera().Zoom(-30); camera().Zoom(-30);
camera().RotateAroundFocusPointLocal(Eigen::AngleAxisf(-0.5f, Eigen::Vector3f::UnitY()) * Eigen::AngleAxisf(-0.05f, Eigen::Vector3f::UnitX())); camera().RotateAroundFocusPointLocal(Eigen::AngleAxisf(-0.5f, Eigen::Vector3f::UnitY()) * Eigen::AngleAxisf(-0.05f, Eigen::Vector3f::UnitX()));
camera().FixClippingPlanes(0.1, 1000); camera().FixClippingPlanes(0.1, 1000);
for (int j = -max_offset; j < max_offset; j++)
for (int i = -max_offset; i < max_offset; i++)
{
offsets.emplace_back((float)(i * PATCH_SIZE), (float)(j * PATCH_SIZE));
}
} }
bool Viewer::resizeEvent(const Eigen::Vector2i &) bool Viewer::resizeEvent(const Eigen::Vector2i &)
@ -119,6 +117,7 @@ GLuint CreateTexture(const unsigned char *fileData, size_t fileLength, bool repe
} }
else if (textureChannels == 2) else if (textureChannels == 2)
{ {
// wild assumption
provided_format = GL_RG; provided_format = GL_RG;
} }
else if (textureChannels == 3) else if (textureChannels == 3)
@ -129,6 +128,11 @@ GLuint CreateTexture(const unsigned char *fileData, size_t fileLength, bool repe
{ {
provided_format = GL_RGBA; provided_format = GL_RGBA;
} }
else
{
// not handled format
abort();
}
glGenTextures(1, &textureName); glGenTextures(1, &textureName);
glBindTexture(GL_TEXTURE_2D, textureName); glBindTexture(GL_TEXTURE_2D, textureName);
@ -141,8 +145,8 @@ GLuint CreateTexture(const unsigned char *fileData, size_t fileLength, bool repe
if (repeat) if (repeat)
{ {
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
} }
else else
{ {
@ -200,72 +204,51 @@ void Viewer::CreateGeometry()
} }
} }
// full x direction, we skip x = 255 inside the loop // full x direction, decreased y direction by 1
// decrease y direction by 1
int count = (PATCH_SIZE) * (PATCH_SIZE - 1); int count = (PATCH_SIZE) * (PATCH_SIZE - 1);
int current_target = PATCH_SIZE - 1;
// our increment value
int current_direction = 1;
int current_index = 0;
int current_column = 0;
for (int k = 0; k < count; k++) for (int k = 0; k < count; k++)
{ {
indices.emplace_back(current_index);
indices.emplace_back(current_index + PATCH_SIZE);
// skip creating triangles on last x in row if (current_index == current_target)
/*
int end_of_x = k % (PATCH_SIZE);
if (end_of_x == 0)
{ {
continue; current_index += PATCH_SIZE;
} current_column++;
*/
indices.emplace_back(k); if (current_direction == -1)
indices.emplace_back(k + PATCH_SIZE); {
//indices.emplace_back(k + 1); current_target = (PATCH_SIZE - 1) + current_column * PATCH_SIZE;
//indices.emplace_back(k + 1 + PATCH_SIZE); }
else if (current_direction == 1)
{
current_target += 1;
}
else
{
// we've done something wrong
abort();
}
current_direction = -current_direction;
}
else
{
current_index += current_direction;
}
} }
terrainShader.bind(); terrainShader.bind();
terrainPositions.uploadData(positions).bindToAttribute("position"); terrainPositions.uploadData(positions).bindToAttribute("position");
terrainIndices.uploadData(indices.size() * sizeof(uint32_t), indices.data()); terrainIndices.uploadData(indices.size() * sizeof(uint32_t), indices.data());
referenceVAO.generate();
referenceVAO.bind();
std::vector<Eigen::Vector4f> ref_pos;
std::vector<uint32_t> ref_ind;
for (int i = 0; i < PATCH_SIZE; i++)
{
for (int j = 0; j < PATCH_SIZE; j++)
{
ref_pos.emplace_back((float)j, 0.0f, (float)i, 1.0f);
}
}
int index_width = PATCH_SIZE - 1;
for (int i = 0; i < index_width; i++)
{
for (int j = 0; j < index_width; j++)
{
int p1 = i + (PATCH_SIZE * j);
int p2 = i + (PATCH_SIZE * j) + 1;
int p3 = i + (PATCH_SIZE * (j + 1));
int p4 = i + (PATCH_SIZE * (j + 1)) + 1;
ref_ind.emplace_back(p1);
ref_ind.emplace_back(p3);
ref_ind.emplace_back(p2);
ref_ind.emplace_back(p3);
ref_ind.emplace_back(p2);
ref_ind.emplace_back(p4);
}
}
referenceVB.uploadData(ref_pos)
.bindToAttribute("position");
referenceIB.uploadData(ref_ind.size() * sizeof(uint32_t), ref_ind.data());
//textures //textures
grassTexture = CreateTexture((unsigned char *)grass_jpg, grass_jpg_size); grassTexture = CreateTexture((unsigned char *)grass_jpg, grass_jpg_size);
rockTexture = CreateTexture((unsigned char *)rock_jpg, rock_jpg_size); rockTexture = CreateTexture((unsigned char *)rock_jpg, rock_jpg_size);
@ -335,21 +318,43 @@ void Viewer::drawContents()
Eigen::Matrix4f mvp = proj * view; Eigen::Matrix4f mvp = proj * view;
Eigen::Vector3f cameraPosition = view.inverse().col(3).head<3>(); Eigen::Vector3f cameraPosition = view.inverse().col(3).head<3>();
int visiblePatches = 0;
Eigen::Vector4f frustum_planes[6];
nse::math::BoundingBox<float, 3> bbox;
CalculateViewFrustum(mvp, frustum_planes, bbox);
std::vector<Eigen::Vector2f> instances;
for (Eigen::Vector2f v : offsets)
{
Eigen::Vector3f min(v.x(), v.y(), 0.0f);
Eigen::Vector3f max(v.x() + (float)PATCH_SIZE, v.y() + (float)PATCH_SIZE, 15.0f);
bool is_inside = false;
for (int i = 0; i < 6; i++)
{
if (IsBoxCompletelyBehindPlane(min, max, frustum_planes[i]))
{
is_inside = true;
break;
}
}
if (is_inside)
instances.emplace_back(v);
}
RenderSky(); RenderSky();
//render terrain //render terrain
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
if (REFERENCE)
{
referenceVAO.bind();
}
else
{
terrainVAO.bind(); terrainVAO.bind();
}
offsetBuffer.bind();
offsetBuffer.uploadData(instances);
glVertexAttribDivisor(offset_buffer_location, instances.size());
terrainShader.bind(); terrainShader.bind();
@ -373,27 +378,21 @@ void Viewer::drawContents()
glBindTexture(GL_TEXTURE_2D, roadColorTexture); glBindTexture(GL_TEXTURE_2D, roadColorTexture);
glUniform1i(road_texture_location, 3); glUniform1i(road_texture_location, 3);
/*
glActiveTexture(GL_TEXTURE4); glActiveTexture(GL_TEXTURE4);
glBindTexture(GL_TEXTURE_2D, roadSpecularMap); glBindTexture(GL_TEXTURE_2D, roadSpecularMap);
glUniform1i(road_specular_location, 4); glUniform1i(road_specular_location, 4);
if (REFERENCE) glActiveTexture(GL_TEXTURE5);
{ glBindTexture(GL_TEXTURE_2D, roadNormalMap);
glDrawElements(GL_TRIANGLES, (PATCH_SIZE - 1) * (PATCH_SIZE - 1) * 6, GL_UNSIGNED_INT, 0); glUniform1i(road_specular_location, 5);
} */
else
{
int n = counter.get_counter();
std::cout << "current n: " << n << std::endl; glDrawElementsInstanced(GL_TRIANGLE_STRIP, (PATCH_SIZE - 1) * PATCH_SIZE * 2, GL_UNSIGNED_INT, 0, instances.size());
glPrimitiveRestartIndex(n);
glDrawElements(GL_TRIANGLE_STRIP, (PATCH_SIZE - 1) * PATCH_SIZE * 2, GL_UNSIGNED_INT, 0);
}
//Render text //Render text
nvgBeginFrame(mNVGContext, width(), height(), mPixelRatio); nvgBeginFrame(mNVGContext, width(), height(), mPixelRatio);
std::string text = "Patches visible: " + std::to_string(visiblePatches); std::string text = "Patches visible: " + std::to_string(instances.size());
nvgText(mNVGContext, 10, 20, text.c_str(), nullptr); nvgText(mNVGContext, 10, 20, text.c_str(), nullptr);
nvgEndFrame(mNVGContext); nvgEndFrame(mNVGContext);
} }