diff --git a/Renderer/Renderer.cpp b/Renderer/Renderer.cpp index 924129f..d1790e9 100644 --- a/Renderer/Renderer.cpp +++ b/Renderer/Renderer.cpp @@ -8,6 +8,7 @@ #include #include +#include #include #include @@ -18,6 +19,8 @@ #include + + using namespace std::string_literals; Renderer::Renderer(Window& win) : win(win) { @@ -338,7 +341,7 @@ void Renderer::draw() { const auto p = glm::perspective(glm::radians(90.0f), static_cast(sz.width) / static_cast(sz.height), 0.01f, 2000.0f); - uniform_buffer->upload(UniformData { + auto uni = UniformData{ .view = cam.view(), .proj = p, .time = time, @@ -346,7 +349,11 @@ void Renderer::draw() { .viewport = glm::vec2(viewport.width, viewport.y), .tess_factor = tess_factor, .tess_edge_size = tess_edge_size, - }); + }; + + std::memcpy(uni.frustum, frustum(p * uni.view).data(), sizeof(uni.frustum)); + + uniform_buffer->upload(uni); command_buffer->bind(*terrain_pipeline); command_buffer->command_buffer.setViewport(0, viewport); diff --git a/Renderer/UniformBuffer.hpp b/Renderer/UniformBuffer.hpp index 9b41513..851df66 100644 --- a/Renderer/UniformBuffer.hpp +++ b/Renderer/UniformBuffer.hpp @@ -18,6 +18,7 @@ struct UniformData { float pad2; glm::vec3 cam_pos; float pad3; + glm::vec4 frustum[6]; glm::vec2 viewport; float tess_factor; float tess_edge_size; diff --git a/Resources/Texture.hpp b/Resources/Texture.hpp index 8215f92..08b8058 100644 --- a/Resources/Texture.hpp +++ b/Resources/Texture.hpp @@ -27,7 +27,7 @@ struct Texture { .binding = binding, .descriptorType = vk::DescriptorType::eCombinedImageSampler, .descriptorCount = 1, - .stageFlags = vk::ShaderStageFlagBits::eFragment | vk::ShaderStageFlagBits::eTessellationEvaluation, + .stageFlags = vk::ShaderStageFlagBits::eFragment | vk::ShaderStageFlagBits::eTessellationControl | vk::ShaderStageFlagBits::eTessellationEvaluation, .pImmutableSamplers = nullptr, }; } diff --git a/assets/shaders/terrain.frag b/assets/shaders/terrain.frag index 0c72e5c..f312305 100644 --- a/assets/shaders/terrain.frag +++ b/assets/shaders/terrain.frag @@ -10,6 +10,7 @@ layout (set = 0, binding = 0) uniform Matrices { mat4 proj; float time; vec3 cam_pos; + vec4 frustum[6]; vec2 viewport; float tess_factor; float tess_edge_size; @@ -23,5 +24,5 @@ void main() { float r = length(light_pos-pos); float t = clamp(dot(L, norm), 0.0, 1.0) * 20.0/(r*r); - FragColor = vec4(norm * texture(tex, texCoord).xyz + t, 1.0); + FragColor = vec4(1.0); } \ No newline at end of file diff --git a/assets/shaders/terrain.frag.spv b/assets/shaders/terrain.frag.spv index 4ed3f7c..f41ddc0 100644 Binary files a/assets/shaders/terrain.frag.spv and b/assets/shaders/terrain.frag.spv differ diff --git a/assets/shaders/terrain.tesc b/assets/shaders/terrain.tesc index 660ff06..fc7a229 100644 --- a/assets/shaders/terrain.tesc +++ b/assets/shaders/terrain.tesc @@ -6,6 +6,7 @@ layout (set = 0, binding = 0) uniform Matrices { mat4 proj; float time; vec3 cam_pos; + vec4 frustum[6]; vec2 viewport; float tess_factor; float tess_edge_size; @@ -45,22 +46,39 @@ float screen_space_tess(vec4 p0, vec4 p1) { return clamp(distance(clip0, clip1) / tess_edge_size * tess_factor, 1.0, 64.0); } +bool frustum_culling() { + /* square root of patch size */ + const float r = 8.0f; + /* ensure this is consistent with tese shader */ + vec4 fpos = gl_in[gl_InvocationID].gl_Position; + fpos.y += 15.0 * textureLod(heightmap, texCoord[0], 0.0).r; + + for(int i = 0; i < 6; i++) { + if(dot(fpos, frustum[i]) + r < 0.0) + return false; + } + return true; +} + void main() { if(gl_InvocationID == 0) { - gl_TessLevelOuter[0] = screen_space_tess(gl_in[3].gl_Position, gl_in[0].gl_Position); - gl_TessLevelOuter[1] = screen_space_tess(gl_in[0].gl_Position, gl_in[1].gl_Position); - gl_TessLevelOuter[2] = screen_space_tess(gl_in[1].gl_Position, gl_in[2].gl_Position); - gl_TessLevelOuter[3] = screen_space_tess(gl_in[2].gl_Position, gl_in[3].gl_Position); - gl_TessLevelInner[0] = mix(gl_TessLevelOuter[0], gl_TessLevelOuter[3], 0.5); - gl_TessLevelInner[1] = mix(gl_TessLevelOuter[2], gl_TessLevelOuter[1], 0.5); - - /*gl_TessLevelOuter[0] = tess_factor; - gl_TessLevelOuter[1] = tess_factor; - gl_TessLevelOuter[2] = tess_factor; - gl_TessLevelOuter[3] = tess_factor; - gl_TessLevelInner[0] = mix(gl_TessLevelOuter[0], gl_TessLevelOuter[3], 0.5); - gl_TessLevelInner[1] = mix(gl_TessLevelOuter[2], gl_TessLevelOuter[1], 0.5);*/ + /* perform frustum culling */ + if(frustum_culling()) { + gl_TessLevelOuter[0] = screen_space_tess(gl_in[3].gl_Position, gl_in[0].gl_Position); + gl_TessLevelOuter[1] = screen_space_tess(gl_in[0].gl_Position, gl_in[1].gl_Position); + gl_TessLevelOuter[2] = screen_space_tess(gl_in[1].gl_Position, gl_in[2].gl_Position); + gl_TessLevelOuter[3] = screen_space_tess(gl_in[2].gl_Position, gl_in[3].gl_Position); + gl_TessLevelInner[0] = mix(gl_TessLevelOuter[0], gl_TessLevelOuter[3], 0.5); + gl_TessLevelInner[1] = mix(gl_TessLevelOuter[2], gl_TessLevelOuter[1], 0.5); + } else { + gl_TessLevelOuter[0] = 0.0; + gl_TessLevelOuter[1] = 0.0; + gl_TessLevelOuter[2] = 0.0; + gl_TessLevelOuter[3] = 0.0; + gl_TessLevelInner[0] = 0.0; + gl_TessLevelInner[1] = 0.0; + } } gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position; diff --git a/assets/shaders/terrain.tesc.spv b/assets/shaders/terrain.tesc.spv index 1c57fa2..720e58b 100644 Binary files a/assets/shaders/terrain.tesc.spv and b/assets/shaders/terrain.tesc.spv differ diff --git a/assets/shaders/terrain.tese b/assets/shaders/terrain.tese index 0648f04..dc0f379 100644 --- a/assets/shaders/terrain.tese +++ b/assets/shaders/terrain.tese @@ -5,6 +5,7 @@ layout (set = 0, binding = 0) uniform Matrices { mat4 proj; float time; vec3 cam_pos; + vec4 frustum[6]; vec2 viewport; float tess_factor; float tess_edge_size; @@ -40,7 +41,7 @@ void main() { vec4 pos2 = mix(gl_in[3].gl_Position, gl_in[2].gl_Position, gl_TessCoord.x); vec4 fpos = mix(pos1, pos2, gl_TessCoord.y); - fpos.y += 15.0 * texture(heightmap, _texCoord).r; //+ cos(fpos.x*fpos.y); + fpos.y += 15.0 * texture(heightmap, _texCoord).r; _pos = fpos.xyz; gl_Position = proj * view * fpos; diff --git a/assets/shaders/terrain.tese.spv b/assets/shaders/terrain.tese.spv index a83223e..c92bf8b 100644 Binary files a/assets/shaders/terrain.tese.spv and b/assets/shaders/terrain.tese.spv differ diff --git a/assets/shaders/terrain.vert b/assets/shaders/terrain.vert index eaf4d57..5910cdf 100644 --- a/assets/shaders/terrain.vert +++ b/assets/shaders/terrain.vert @@ -12,6 +12,7 @@ layout (set = 0, binding = 0) uniform Matrices { mat4 proj; float time; vec3 cam_pos; + vec4 frustum[6]; vec2 viewport; float tess_factor; float tess_edge_size; diff --git a/assets/shaders/terrain.vert.spv b/assets/shaders/terrain.vert.spv index e232378..68eecdb 100644 Binary files a/assets/shaders/terrain.vert.spv and b/assets/shaders/terrain.vert.spv differ diff --git a/util/geo.hpp b/util/geo.hpp new file mode 100644 index 0000000..6e35f07 --- /dev/null +++ b/util/geo.hpp @@ -0,0 +1,17 @@ +#pragma once + +#include +#include + +/* extracts frustum from projection matrix */ +static std::array frustum(const glm::mat4& mat) { + /* Left, Right, Top, Bottom, Back, Front */ + std::array ret; + + for (size_t i = 0; i < 3; i++) + for (size_t j = 0; j < 4; j++) + ret[i * 2][j] = mat[j].w + mat[j][i], + ret[i * 2 + 1][j] = mat[j].w - mat[j][i]; + + return ret; +} \ No newline at end of file