Try to solve task 2.2
This commit is contained in:
parent
f86fc26703
commit
9a0df4e4ab
3 changed files with 125 additions and 61 deletions
|
@ -1,8 +1,10 @@
|
|||
#version 330
|
||||
// This source code is property of the Computer Graphics and Visualization
|
||||
// chair of the TU Dresden. Do not distribute!
|
||||
// This source code is property of the Computer Graphics and Visualization
|
||||
// chair of the TU Dresden. Do not distribute!
|
||||
// Copyright (C) CGV TU Dresden - All Rights Reserved
|
||||
|
||||
in vec3 n;
|
||||
|
||||
out vec4 color;
|
||||
|
||||
uniform vec3 cameraPos;
|
||||
|
@ -11,7 +13,7 @@ uniform vec3 cameraPos;
|
|||
uniform sampler2D background;
|
||||
uniform vec2 screenSize;
|
||||
|
||||
const vec3 dirToLight = normalize(vec3(1, 3, 1));
|
||||
const vec3 dirToLight = normalize(vec3(1, 3, 1));
|
||||
|
||||
//Calculates the visible surface color based on the Blinn-Phong illumination model
|
||||
vec4 calculateLighting(vec4 materialColor, float specularIntensity, vec3 normalizedNormal, vec3 directionToViewer)
|
||||
|
@ -31,17 +33,17 @@ vec4 getBackgroundColor()
|
|||
void main()
|
||||
{
|
||||
//surface geometry
|
||||
vec3 n = vec3(0, 1, 0);
|
||||
//vec3 n = vec3(0, 1, 0);
|
||||
vec3 dirToViewer = vec3(0, 1, 0);
|
||||
|
||||
//material properties
|
||||
//material properties
|
||||
color = vec4(0.6, 0.6, 0.6, 1);
|
||||
float specular = 0;
|
||||
|
||||
|
||||
|
||||
|
||||
//Calculate light
|
||||
color = calculateLighting(color, specular, n, dirToViewer);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -5,18 +5,31 @@
|
|||
|
||||
in vec4 position;
|
||||
|
||||
|
||||
out vec3 n;
|
||||
|
||||
uniform mat4 mvp;
|
||||
|
||||
//Returns the height of the procedural terrain at a given xz position
|
||||
float getTerrainHeight(vec2 p);
|
||||
|
||||
vec3 calculate_normal(vec4 terrain_position);
|
||||
vec4 offset_point(vec4 base, vec2 offset);
|
||||
|
||||
const vec2 offsets[6] = vec2[6](
|
||||
vec2(0.0, 0.0),
|
||||
vec2(0.0, 1.0),
|
||||
vec2(1.0, 0.0),
|
||||
vec2(0.0, 1.0),
|
||||
vec2(1.0, 0.0),
|
||||
vec2(1.0, 1.0)
|
||||
);
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = mvp * position;
|
||||
vec4 terrain_position = vec4(position.x, getTerrainHeight(vec2(position.x, position.z)), position.z, position.w);
|
||||
n = calculate_normal(position);
|
||||
|
||||
gl_Position = mvp * terrain_position;
|
||||
}
|
||||
|
||||
//source: https://gist.github.com/patriciogonzalezvivo/670c22f3966e662d2f83
|
||||
|
@ -47,7 +60,7 @@ float getTerrainHeight(vec2 p)
|
|||
float maxAmplitude = 0.0;
|
||||
float amplitude = 1.0;
|
||||
float frequency = 0.02;
|
||||
for (int i = 0; i < 11; i++)
|
||||
for (int i = 0; i < 11; i++)
|
||||
{
|
||||
total += ((1.0 - abs(perlinNoise(p * frequency))) * 2.0 - 1.0) * amplitude;
|
||||
frequency *= 2.0;
|
||||
|
@ -56,3 +69,49 @@ float getTerrainHeight(vec2 p)
|
|||
}
|
||||
return 15 * total / maxAmplitude;
|
||||
}
|
||||
|
||||
vec4 offset_point(vec4 base, vec2 offset) {
|
||||
float y = getTerrainHeight(vec2(base.x, base.z) + offset);
|
||||
return vec4(base.x + offset.x, y, base.z + offset.y, base.w);
|
||||
}
|
||||
|
||||
// calculate the position of the first vertex in this square
|
||||
vec4 pos_to_base(vec4 pos, int v_id) {
|
||||
return vec4(pos.x - offsets[v_id].x, pos.y, pos.z - offsets[v_id].y, pos.w);
|
||||
}
|
||||
|
||||
// calculates the normal of terrain_position
|
||||
// it generates the complete triangle based on the gl_VertexID and then normal math
|
||||
vec3 calculate_normal(vec4 terrain_position) {
|
||||
int offset_index = gl_VertexID % 6;
|
||||
|
||||
vec4 base_vertex = pos_to_base(terrain_position, offset_index);
|
||||
|
||||
// the other 2 points from the triangle
|
||||
int points_index = 0;
|
||||
vec4 points[2];
|
||||
|
||||
int iterator_offset = 0;
|
||||
|
||||
// second triangle offset
|
||||
if (offset_index > 2) {
|
||||
iterator_offset = 3;
|
||||
}
|
||||
|
||||
for (int i = iterator_offset; i < (3 + iterator_offset); i++) {
|
||||
// skip for current vertex
|
||||
if (i == offset_index) {
|
||||
continue;
|
||||
}
|
||||
|
||||
points[points_index] = offset_point(base_vertex, offsets[i]);
|
||||
points_index++;
|
||||
}
|
||||
|
||||
// create connection vectors
|
||||
vec3 p1 = (points[0] - terrain_position).xyz;
|
||||
vec3 p2 = (points[1] - terrain_position).xyz;
|
||||
|
||||
// calculate normal
|
||||
return normalize(cross(p1, p2));
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
// This source code is property of the Computer Graphics and Visualization
|
||||
// chair of the TU Dresden. Do not distribute!
|
||||
// This source code is property of the Computer Graphics and Visualization
|
||||
// chair of the TU Dresden. Do not distribute!
|
||||
// Copyright (C) CGV TU Dresden - All Rights Reserved
|
||||
|
||||
#include "Viewer.h"
|
||||
|
@ -14,7 +14,7 @@
|
|||
|
||||
#include <stb_image.h>
|
||||
|
||||
#include "glsl.h"
|
||||
#include "glsl.h"
|
||||
#include "textures.h"
|
||||
|
||||
#include <fstream>
|
||||
|
@ -23,25 +23,25 @@ const uint32_t PATCH_SIZE = 256; //number of vertices along one side of the terr
|
|||
|
||||
Viewer::Viewer()
|
||||
: AbstractViewer("CG1 Exercise 2"),
|
||||
terrainPositions(nse::gui::VertexBuffer), terrainIndices(nse::gui::IndexBuffer),
|
||||
offsetBuffer(nse::gui::VertexBuffer)
|
||||
{
|
||||
terrainPositions(nse::gui::VertexBuffer), terrainIndices(nse::gui::IndexBuffer),
|
||||
offsetBuffer(nse::gui::VertexBuffer)
|
||||
{
|
||||
LoadShaders();
|
||||
CreateGeometry();
|
||||
|
||||
|
||||
//Create a texture and framebuffer for the background
|
||||
glGenFramebuffers(1, &backgroundFBO);
|
||||
glGenTextures(1, &backgroundTexture);
|
||||
glGenFramebuffers(1, &backgroundFBO);
|
||||
glGenTextures(1, &backgroundTexture);
|
||||
|
||||
//Align camera to view a reasonable part of the terrain
|
||||
camera().SetSceneExtent(nse::math::BoundingBox<float, 3>(Eigen::Vector3f(0, 0, 0), Eigen::Vector3f(PATCH_SIZE - 1, 0, PATCH_SIZE - 1)));
|
||||
camera().FocusOnPoint(0.5f * Eigen::Vector3f(PATCH_SIZE - 1, 15, PATCH_SIZE - 1));
|
||||
camera().FocusOnPoint(0.5f * Eigen::Vector3f(PATCH_SIZE - 1, 15, PATCH_SIZE - 1));
|
||||
camera().Zoom(-30);
|
||||
camera().RotateAroundFocusPointLocal(Eigen::AngleAxisf(-0.5f, Eigen::Vector3f::UnitY()) * Eigen::AngleAxisf(-0.05f, Eigen::Vector3f::UnitX()));
|
||||
camera().FixClippingPlanes(0.1, 1000);
|
||||
}
|
||||
|
||||
bool Viewer::resizeEvent(const Eigen::Vector2i&)
|
||||
bool Viewer::resizeEvent(const Eigen::Vector2i &)
|
||||
{
|
||||
//Re-generate the texture and FBO for the background
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, backgroundFBO);
|
||||
|
@ -87,7 +87,7 @@ void Viewer::LoadShaders()
|
|||
terrainShader.init("Terrain Shader", terrain_vs, terrain_fs);
|
||||
}
|
||||
|
||||
GLuint CreateTexture(const unsigned char* fileData, size_t fileLength, bool repeat = true)
|
||||
GLuint CreateTexture(const unsigned char *fileData, size_t fileLength, bool repeat = true)
|
||||
{
|
||||
GLuint textureName;
|
||||
int textureWidth, textureHeight, textureChannels;
|
||||
|
@ -102,32 +102,36 @@ void Viewer::CreateGeometry()
|
|||
//empty VAO for sky
|
||||
emptyVAO.generate();
|
||||
|
||||
//terrain VAO
|
||||
//terrain VAO
|
||||
terrainVAO.generate();
|
||||
terrainVAO.bind();
|
||||
|
||||
|
||||
std::vector<Eigen::Vector4f> positions;
|
||||
std::vector<uint32_t> indices;
|
||||
|
||||
|
||||
/*Generate positions and indices for a terrain patch with a
|
||||
single triangle strip */
|
||||
|
||||
for (int i = 0; i < PATCH_SIZE; i++) {
|
||||
for (int j = 0; j < PATCH_SIZE; j++) {
|
||||
for (int i = 0; i < PATCH_SIZE; i++)
|
||||
{
|
||||
for (int j = 0; j < PATCH_SIZE; j++)
|
||||
{
|
||||
positions.emplace_back((float)i, 0.0f, (float)j, 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
// full x direction, we skip x = 255 inside the loop
|
||||
// decrease y direction by 1
|
||||
int count = (PATCH_SIZE) * (PATCH_SIZE-1);
|
||||
int count = (PATCH_SIZE) * (PATCH_SIZE - 1);
|
||||
|
||||
for (int k = 0; k < count; k++) {
|
||||
for (int k = 0; k < count; k++)
|
||||
{
|
||||
|
||||
// skip creating triangles on last x in row
|
||||
int end_of_x = k % (PATCH_SIZE-1);
|
||||
int end_of_x = k % (PATCH_SIZE - 1);
|
||||
|
||||
if (end_of_x == 0) {
|
||||
if (end_of_x == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -142,12 +146,12 @@ void Viewer::CreateGeometry()
|
|||
terrainIndices.uploadData(indices.size() * sizeof(uint32_t), indices.data());
|
||||
|
||||
//textures
|
||||
grassTexture = CreateTexture((unsigned char*)grass_jpg, grass_jpg_size);
|
||||
rockTexture = CreateTexture((unsigned char*)rock_jpg, rock_jpg_size);
|
||||
roadColorTexture = CreateTexture((unsigned char*)roadcolor_jpg, roadcolor_jpg_size);
|
||||
roadNormalMap = CreateTexture((unsigned char*)roadnormals_jpg, roadnormals_jpg_size);
|
||||
roadSpecularMap = CreateTexture((unsigned char*)roadspecular_jpg, roadspecular_jpg_size);
|
||||
alphaMap = CreateTexture((unsigned char*)alpha_jpg, alpha_jpg_size, false);
|
||||
grassTexture = CreateTexture((unsigned char *)grass_jpg, grass_jpg_size);
|
||||
rockTexture = CreateTexture((unsigned char *)rock_jpg, rock_jpg_size);
|
||||
roadColorTexture = CreateTexture((unsigned char *)roadcolor_jpg, roadcolor_jpg_size);
|
||||
roadNormalMap = CreateTexture((unsigned char *)roadnormals_jpg, roadnormals_jpg_size);
|
||||
roadSpecularMap = CreateTexture((unsigned char *)roadspecular_jpg, roadspecular_jpg_size);
|
||||
alphaMap = CreateTexture((unsigned char *)alpha_jpg, alpha_jpg_size, false);
|
||||
}
|
||||
|
||||
void Viewer::RenderSky()
|
||||
|
@ -171,7 +175,7 @@ void Viewer::RenderSky()
|
|||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
void CalculateViewFrustum(const Eigen::Matrix4f& mvp, Eigen::Vector4f* frustumPlanes, nse::math::BoundingBox<float, 3>& bbox)
|
||||
void CalculateViewFrustum(const Eigen::Matrix4f &mvp, Eigen::Vector4f *frustumPlanes, nse::math::BoundingBox<float, 3> &bbox)
|
||||
{
|
||||
frustumPlanes[0] = (mvp.row(3) + mvp.row(0)).transpose();
|
||||
frustumPlanes[1] = (mvp.row(3) - mvp.row(0)).transpose();
|
||||
|
@ -182,27 +186,26 @@ void CalculateViewFrustum(const Eigen::Matrix4f& mvp, Eigen::Vector4f* frustumPl
|
|||
|
||||
Eigen::Matrix4f invMvp = mvp.inverse();
|
||||
bbox.reset();
|
||||
for(int x = -1; x <= 1; x += 2)
|
||||
for(int y = -1; y <= 1; y += 2)
|
||||
for (int x = -1; x <= 1; x += 2)
|
||||
for (int y = -1; y <= 1; y += 2)
|
||||
for (int z = -1; z <= 1; z += 2)
|
||||
{
|
||||
Eigen::Vector4f corner = invMvp * Eigen::Vector4f(x, y, z, 1);
|
||||
corner /= corner.w();
|
||||
bbox.expand(corner.head<3>());
|
||||
}
|
||||
{
|
||||
Eigen::Vector4f corner = invMvp * Eigen::Vector4f(x, y, z, 1);
|
||||
corner /= corner.w();
|
||||
bbox.expand(corner.head<3>());
|
||||
}
|
||||
}
|
||||
|
||||
bool IsBoxCompletelyBehindPlane(const Eigen::Vector3f& boxMin, const Eigen::Vector3f& boxMax, const Eigen::Vector4f& plane)
|
||||
bool IsBoxCompletelyBehindPlane(const Eigen::Vector3f &boxMin, const Eigen::Vector3f &boxMax, const Eigen::Vector4f &plane)
|
||||
{
|
||||
return
|
||||
plane.dot(Eigen::Vector4f(boxMin.x(), boxMin.y(), boxMin.z(), 1)) < 0 &&
|
||||
plane.dot(Eigen::Vector4f(boxMin.x(), boxMin.y(), boxMax.z(), 1)) < 0 &&
|
||||
plane.dot(Eigen::Vector4f(boxMin.x(), boxMax.y(), boxMin.z(), 1)) < 0 &&
|
||||
plane.dot(Eigen::Vector4f(boxMin.x(), boxMax.y(), boxMin.z(), 1)) < 0 &&
|
||||
plane.dot(Eigen::Vector4f(boxMax.x(), boxMin.y(), boxMin.z(), 1)) < 0 &&
|
||||
plane.dot(Eigen::Vector4f(boxMax.x(), boxMin.y(), boxMax.z(), 1)) < 0 &&
|
||||
plane.dot(Eigen::Vector4f(boxMax.x(), boxMax.y(), boxMin.z(), 1)) < 0 &&
|
||||
plane.dot(Eigen::Vector4f(boxMax.x(), boxMax.y(), boxMin.z(), 1)) < 0;
|
||||
return plane.dot(Eigen::Vector4f(boxMin.x(), boxMin.y(), boxMin.z(), 1)) < 0 &&
|
||||
plane.dot(Eigen::Vector4f(boxMin.x(), boxMin.y(), boxMax.z(), 1)) < 0 &&
|
||||
plane.dot(Eigen::Vector4f(boxMin.x(), boxMax.y(), boxMin.z(), 1)) < 0 &&
|
||||
plane.dot(Eigen::Vector4f(boxMin.x(), boxMax.y(), boxMin.z(), 1)) < 0 &&
|
||||
plane.dot(Eigen::Vector4f(boxMax.x(), boxMin.y(), boxMin.z(), 1)) < 0 &&
|
||||
plane.dot(Eigen::Vector4f(boxMax.x(), boxMin.y(), boxMax.z(), 1)) < 0 &&
|
||||
plane.dot(Eigen::Vector4f(boxMax.x(), boxMax.y(), boxMin.z(), 1)) < 0 &&
|
||||
plane.dot(Eigen::Vector4f(boxMax.x(), boxMax.y(), boxMin.z(), 1)) < 0;
|
||||
}
|
||||
|
||||
void Viewer::drawContents()
|
||||
|
@ -214,20 +217,20 @@ void Viewer::drawContents()
|
|||
int visiblePatches = 0;
|
||||
|
||||
RenderSky();
|
||||
|
||||
|
||||
//render terrain
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
terrainVAO.bind();
|
||||
terrainShader.bind();
|
||||
|
||||
terrainShader.bind();
|
||||
|
||||
terrainShader.setUniform("screenSize", Eigen::Vector2f(width(), height()), false);
|
||||
terrainShader.setUniform("mvp", mvp);
|
||||
terrainShader.setUniform("cameraPos", cameraPosition, false);
|
||||
|
||||
/* Task: Render the terrain */
|
||||
//glPrimitiveRestartIndex(255);
|
||||
glDrawElements(GL_TRIANGLE_STRIP, (PATCH_SIZE-1) * (PATCH_SIZE-1) * 4, GL_UNSIGNED_INT, 0);
|
||||
|
||||
glPrimitiveRestartIndex(512);
|
||||
glDrawElements(GL_TRIANGLE_STRIP, (PATCH_SIZE - 1) * (PATCH_SIZE - 1) * 4, GL_UNSIGNED_INT, 0);
|
||||
|
||||
//Render text
|
||||
nvgBeginFrame(mNVGContext, width(), height(), mPixelRatio);
|
||||
std::string text = "Patches visible: " + std::to_string(visiblePatches);
|
||||
|
|
Loading…
Reference in a new issue