Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,8 @@
*.exe
*.out
*.app

# Custom
.idea/*
build/*
bindings/*
66 changes: 66 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
cmake_minimum_required(VERSION 3.0)
set(PROJECT_NAME "Task-4-metaballs")
set(CMAKE_PREFIX_PATH ${CMAKE_BINARY_DIR})
set(CMAKE_MODULE_PATH ${CMAKE_BINARY_DIR})
set(CMAKE_CXX_STANDARD 17)

project(${PROJECT_NAME} CXX)

# CONFIG option is important so that CMake doesnt search for modules into the default modules directory
find_package(imgui CONFIG)
find_package(glfw CONFIG)
find_package(glew CONFIG)
find_package(fmt CONFIG)
find_package(glm CONFIG)
find_package(stb CONFIG)

add_executable(
${PROJECT_NAME}

src/main.cpp
src/utils/settings.h
src/utils/buffers.h

src/utils/shader.cpp
src/elements/camera.h

src/elements/opengl.h
src/elements/window.h
src/elements/cubemap.h
src/elements/metaballs.h

bindings/imgui_impl_glfw.cpp
bindings/imgui_impl_opengl3.cpp

# Shaders
assets/cubemap/shaders/vertex.glsl
assets/cubemap/shaders/fragment.glsl

assets/metaballs/shaders/fragment.glsl
assets/metaballs/shaders/geometry.glsl
assets/metaballs/shaders/vertex.glsl
)

add_custom_command(
TARGET ${PROJECT_NAME}

POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory ${PROJECT_SOURCE_DIR}/assets ${PROJECT_BINARY_DIR}/assets
)

target_compile_definitions(
${PROJECT_NAME}
PUBLIC
IMGUI_IMPL_OPENGL_LOADER_GLEW
)

target_link_libraries(
${PROJECT_NAME}

imgui::imgui
GLEW::glew_s
glfw::glfw
fmt::fmt
glm::glm
stb::stb
)
15 changes: 14 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,14 @@
# ComputerGraphics-OpenGL
# GPU metaballs marching cubes

### Условие
Динамические metaball'ы c отражением и преломлением

## Запуск
Собираем проект:
1) Windows `build.bat`
2) Linux `build.sh`

Далее запускаем `build/Task-4-metaballs`

## Примеры
![](screenshots/metaballs.png)
11 changes: 11 additions & 0 deletions assets/cubemap/shaders/fragment.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#version 430 core

out vec4 gl_FragColor;

in vec3 shader_texture_position;

uniform samplerCube u_skybox;

void main() {
gl_FragColor = texture(u_skybox, shader_texture_position);
}
15 changes: 15 additions & 0 deletions assets/cubemap/shaders/vertex.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#version 430 core

layout (location = 0) in vec3 in_position;

out vec3 shader_texture_position;

uniform mat4 u_view;
uniform mat4 u_projection;

void main() {
shader_texture_position = in_position;
vec4 pos = u_projection * u_view * vec4(in_position, 1.0);

gl_Position = pos.xyww;
}
Binary file added assets/cubemap/textures/simple/back.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/cubemap/textures/simple/bottom.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/cubemap/textures/simple/front.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/cubemap/textures/simple/left.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/cubemap/textures/simple/right.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/cubemap/textures/simple/top.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
26 changes: 26 additions & 0 deletions assets/metaballs/shaders/fragment.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#version 430 core

uniform vec3 u_camera_pos;
uniform samplerCube u_skybox;

float u_refraction_value = 1000;

in vec3 shader_position;
in vec3 shader_normal;

out vec4 gl_FragColor;

float coefficient_refraction = 0.25f;
float coefficient_reflection = 0.75f;
float fresnel_alpha = 0.5f;

void main() {
vec3 reflection = reflect(u_camera_pos, shader_normal);
vec3 refraction = refract(u_camera_pos, shader_normal, 1 / coefficient_refraction);

gl_FragColor = mix(
vec4(texture(u_skybox, refraction).rgb, 1.0),
vec4(texture(u_skybox, reflection).rgb, 1.0),
0.2f
);
}
98 changes: 98 additions & 0 deletions assets/metaballs/shaders/geometry.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
#version 430 core
layout (points) in;
layout (triangle_strip, max_vertices = 24) out;

layout(std430, binding = 1) buffer edge_table_buffer { int edge_table[]; };
layout(std430, binding = 2) buffer triangle_table_buffer { int triangle_table[256][16]; };

uniform mat4 u_model;
uniform mat4 u_view;
uniform mat4 u_projection;

const float CUBE_SIZE = 0.05f;

out vec3 shader_normal;

float vertex_function(vec3 point) {
vec3 metaball_center1 = vec3(0.0f, 0.0f, 0.0f);
vec3 metaball_center2 = vec3(0.1f, -0.2f, 0.5f);
vec3 metaball_center3 = vec3(-0.5f, 0.5f, -0.5f);

vec3 delta1 = point - metaball_center1;
vec3 delta2 = point - metaball_center2;
vec3 delta3 = point - metaball_center3;

float radius = 0.25f;
float sum = (1 / dot(delta1, delta1)) + (1 / dot(delta2, delta2)) + (1 / dot(delta3, delta3));

return radius * radius * sum - 1;
}

vec3 evaluate_normal(vec3 point) {
return normalize(vec3(
vertex_function(point + vec3(CUBE_SIZE / 8, 0, 0)) - vertex_function(point - vec3(CUBE_SIZE / 8, 0, 0)),
vertex_function(point + vec3(0, CUBE_SIZE / 8, 0)) - vertex_function(point - vec3(0, CUBE_SIZE / 8, 0)),
vertex_function(point + vec3(0, 0, CUBE_SIZE / 8)) - vertex_function(point - vec3(0, 0, CUBE_SIZE / 8))
));
}

vec3 lerp(vec3 point1, vec3 point2) {
float coefficient = abs(vertex_function(point1)) / (abs(vertex_function(point1)) + abs(vertex_function(point2)));
return point1 + (point2 - point1) * coefficient;
}

void main() {
vec3 cube[8] = {
gl_in[0].gl_Position.xyz + vec3(-CUBE_SIZE / 2, -CUBE_SIZE/ 2, -CUBE_SIZE/ 2),
gl_in[0].gl_Position.xyz + vec3(CUBE_SIZE/ 2, -CUBE_SIZE/ 2, -CUBE_SIZE/ 2),
gl_in[0].gl_Position.xyz + vec3(CUBE_SIZE/ 2, -CUBE_SIZE/ 2, CUBE_SIZE/ 2),
gl_in[0].gl_Position.xyz + vec3(-CUBE_SIZE/ 2, -CUBE_SIZE/ 2, CUBE_SIZE/ 2),
gl_in[0].gl_Position.xyz + vec3(-CUBE_SIZE/ 2, CUBE_SIZE/ 2, -CUBE_SIZE/ 2),
gl_in[0].gl_Position.xyz + vec3(CUBE_SIZE/ 2, CUBE_SIZE/ 2, -CUBE_SIZE/ 2),
gl_in[0].gl_Position.xyz + vec3(CUBE_SIZE/ 2, CUBE_SIZE/ 2, CUBE_SIZE/ 2),
gl_in[0].gl_Position.xyz + vec3(-CUBE_SIZE/ 2, CUBE_SIZE/ 2, CUBE_SIZE/ 2)
};

int cubeBitMaskIndex = 0;
if (vertex_function(cube[0]) < 0) cubeBitMaskIndex |= 1;
if (vertex_function(cube[1]) < 0) cubeBitMaskIndex |= 2;
if (vertex_function(cube[2]) < 0) cubeBitMaskIndex |= 4;
if (vertex_function(cube[3]) < 0) cubeBitMaskIndex |= 8;
if (vertex_function(cube[4]) < 0) cubeBitMaskIndex |= 16;
if (vertex_function(cube[5]) < 0) cubeBitMaskIndex |= 32;
if (vertex_function(cube[6]) < 0) cubeBitMaskIndex |= 64;
if (vertex_function(cube[7]) < 0) cubeBitMaskIndex |= 128;

vec3 vertexOnEdge[12];
int edges = edge_table[cubeBitMaskIndex];
if (edges == 0) return;
if ((edges & 1) != 0) vertexOnEdge[0] = lerp(cube[0], cube[1]);
if ((edges & 2) != 0) vertexOnEdge[1] = lerp(cube[1], cube[2]);
if ((edges & 4) != 0) vertexOnEdge[2] = lerp(cube[2], cube[3]);
if ((edges & 8) != 0) vertexOnEdge[3] = lerp(cube[3], cube[0]);
if ((edges & 16) != 0) vertexOnEdge[4] = lerp(cube[4], cube[5]);
if ((edges & 32) != 0) vertexOnEdge[5] = lerp(cube[5], cube[6]);
if ((edges & 64) != 0) vertexOnEdge[6] = lerp(cube[6], cube[7]);
if ((edges & 128) != 0) vertexOnEdge[7] = lerp(cube[7], cube[4]);
if ((edges & 256) != 0) vertexOnEdge[8] = lerp(cube[0], cube[4]);
if ((edges & 512) != 0) vertexOnEdge[9] = lerp(cube[1], cube[5]);
if ((edges & 1024) != 0) vertexOnEdge[10] = lerp(cube[2], cube[6]);
if ((edges & 2048) != 0) vertexOnEdge[11] = lerp(cube[3], cube[7]);

mat4 mvp = u_projection * u_view * u_model;
for (int i = 0; triangle_table[cubeBitMaskIndex][i] != -1; i += 3) {
gl_Position = mvp * vec4(vertexOnEdge[triangle_table[cubeBitMaskIndex][i]], 1);
shader_normal = evaluate_normal(vertexOnEdge[triangle_table[cubeBitMaskIndex][i]]);
EmitVertex();

gl_Position = mvp * vec4(vertexOnEdge[triangle_table[cubeBitMaskIndex][i + 1]], 1);
shader_normal = evaluate_normal(vertexOnEdge[triangle_table[cubeBitMaskIndex][i + 1]]);
EmitVertex();

gl_Position = mvp * vec4(vertexOnEdge[triangle_table[cubeBitMaskIndex][i + 2]], 1);
shader_normal = evaluate_normal(vertexOnEdge[triangle_table[cubeBitMaskIndex][i + 2]]);
EmitVertex();

EndPrimitive();
}
}
7 changes: 7 additions & 0 deletions assets/metaballs/shaders/vertex.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#version 430 core

layout (location = 0) in vec3 in_position;

void main() {
gl_Position = vec4(in_position, 1.0);
}
9 changes: 9 additions & 0 deletions build.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
@ECHO ON

RMDIR /Q /S build
MKDIR build
PUSHD build

conan install ..
cmake .. -G "Visual Studio 15 2017 Win64"
cmake --build . --config Release
13 changes: 13 additions & 0 deletions build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/bin/bash

set -e
set -x

rm -rf build
mkdir build
pushd build

export CONAN_SYSREQUIRES_MODE=enabled
conan install ..
cmake .. -DCMAKE_BUILD_TYPE=Release
cmake --build .
21 changes: 21 additions & 0 deletions conanfile.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
[requires]
imgui/1.74
glfw/3.3.2
glew/2.1.0
fmt/7.0.3
glm/0.9.9.8
stb/20200203
assimp/5.0.1

[generators]
cmake_find_package_multi

[options]
glew:shared=False
fmt:header_only=True

[imports]
./res/bindings, imgui_impl_glfw.cpp -> ../bindings
./res/bindings, imgui_impl_opengl3.cpp -> ../bindings
./res/bindings, imgui_impl_glfw.h -> ../bindings
./res/bindings, imgui_impl_opengl3.h -> ../bindings
Binary file added screenshots/metaballs.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
66 changes: 66 additions & 0 deletions src/elements/camera.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#pragma once

#include <vector>

#include <GL/glew.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>

class Camera {
const GLfloat MOUSE_SENSITIVITY = 45.0f;

glm::vec3 position_{};

GLfloat pitch_ = 0.0f;
GLfloat yaw_ = 0.0f;

GLfloat zoom_ = 45.0f;

public:
explicit Camera(glm::vec3 position) {
position_ = position;
}

[[nodiscard]]
glm::mat4 view() const {
return glm::lookAt(
position(),
glm::vec3(0.0f, 0.0f, 0.0f),
glm::vec3(0.0f, 1.0f, 0.0f)
);
}

void process_mouse_movement(GLfloat offset_x, GLfloat offset_y) {
yaw_ += offset_x * MOUSE_SENSITIVITY;
pitch_ += offset_y * MOUSE_SENSITIVITY;

if (pitch_ > 89.0f) pitch_ = 89.0f;
if (pitch_ < -89.0f) pitch_ = -89.0f;
}

void process_mouse_scroll(GLfloat offset_y) {
if (offset_y < 0) zoom_ *= 1.2;
else zoom_ /= 1.2;
}

[[nodiscard]]
glm::vec3 position() const {
glm::vec3 pos = position_ * zoom_;

auto rotate = glm::rotate(
glm::identity<glm::mat4>(),
glm::radians(yaw_),
glm::vec3(0.0f, 1.0f, 0.0f)
);
pos = glm::vec3(rotate * glm::vec4(pos, 1.0f));

auto inverse = glm::vec3(rotate * glm::vec4(1.0f, 0.0f, 0.0f, 1.0f));
rotate = glm::rotate(
glm::identity<glm::mat4>(),
glm::radians(pitch_),
inverse
);

return pos = glm::vec3(rotate * glm::vec4(pos, 1.0f));
}
};
Loading