Fixed heissenbug caused by quat initialization and added sound server.

This commit is contained in:
2023-04-24 11:24:26 +03:00
parent 9de9f2a9e7
commit fc3095a1a5
44 changed files with 1132 additions and 409 deletions
+3 -1
View File
@@ -6,6 +6,8 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
include(FindPkgConfig)
find_package(glfw3 3.3 REQUIRED)
find_package(OpenGL REQUIRED)
find_package(SDL2 REQUIRED)
include_directories(${SDL2_INCLUDE_DIRS})
include_directories("src/")
include_directories("gl/include")
@@ -30,4 +32,4 @@ set(SOURCE
)
add_executable(demo main.cpp gl/src/glad.c ${SOURCE} lib/easyloggingpp/src/easylogging++.cc)
target_link_libraries(demo glfw OpenGL::GL)
target_link_libraries(demo glfw OpenGL::GL ${SDL2_LIBRARIES})
+80 -75
View File
@@ -1,4 +1,5 @@
#include <memory>
#include <iterator>
#include "imgui.h"
#include "imgui_impl_glfw.h"
@@ -7,6 +8,8 @@
#include "peripherals_glfw.h"
#include "demo/demo_engine.h"
#include "timer.h"
#include "audio/sound_server.h"
#include <bitset>
using namespace acidrain;
using namespace std;
@@ -15,30 +18,30 @@ INITIALIZE_EASYLOGGINGPP
int main() {
acidrain::peripherals_glfw peripherals;
peripherals.init();
peripherals.init(demo_data::screen_width, demo_data::screen_height, "acidrain", false);
LOG(INFO) << "peripherals initialized";
glDisable(GL_DEPTH_TEST);
const float DEMO_LENGTH_IN_SECONDS = 100;
const float DEMO_LENGTH_IN_SECONDS = 1000;
// --------------------------------------------------------------------------------------
// Load resources
// --------------------------------------------------------------------------------------
acidrain::texture_generator tg(256, 256);
tg.brick(0, 50, 20, 4, glm::vec4(1), glm::vec4(0));
// tg.checker_board(0, 50, glm::vec4(1), glm::vec4(0));
// tg.brick(0, 50, 20, 4, glm::vec4(1), glm::vec4(0));
tg.checker_board(0, 50, glm::vec4(1), glm::vec4(0));
shared_ptr<mesh> affectedSphere = mesh_generator::sphere(50, 50);
map_transform(affectedSphere, tg, 0, 0, 0.2f);
calculate_normals(*affectedSphere.get());
shared_ptr<mesh> affected_sphere = mesh_generator::sphere(50, 50);
map_transform(affected_sphere, tg, 0, 0, 0.2f);
calculate_normals(*affected_sphere);
// affectedSphere = mesh_generator::cog(0.2, 0.5, 50, 4, 0.1, 0.2, 0.2, 0.1);
demo_data::meshes.push_back(affectedSphere);
demo_data::meshes.push_back(affected_sphere);
demo_data::meshes.push_back(mesh_generator::sphere(3, 3));
demo_data::meshes.push_back(mesh_generator::grid(30, 30));
demo_data::meshes.push_back(mesh_generator::grid(1, 1));
demo_data::meshes.push_back(mesh_generator::cube());
auto mat = std::make_shared<material>();
@@ -49,21 +52,21 @@ int main() {
mat->shininess = 200;
mat->cast_shadows = true;
auto *textureGenerator1 = new texture_generator(256, 256);
// mat->textures[texture_role::diffuse] = textureGenerator1->checker_board(0, 20,
// colour(1, 1, 1, 1),
// colour(0, 0.5, 0.2, 1)).get_texture(0);
mat->textures[texture_role::diffuse] = textureGenerator1->brick(0,
50, 20,
4,
colour(0.3, 0.1, 0, 1),
colour(1, 0.3, 0, 1)).get_texture(0);
auto *texgen = new texture_generator(256, 256);
mat->textures[texture_role::diffuse] = texgen->checker_board(0, 20,
colour(1, 1, 1, 1),
colour(0, 0.5, 0.2, 1)).get_texture(0);
// mat->textures[texture_role::diffuse] = textureGenerator1->brick(0,
// 50, 20,
// 4,
// colour(0.3, 0.1, 0, 1),
// colour(1, 0.3, 0, 1)).get_texture(0);
demo_data::materials.push_back(mat);
auto material2 = make_shared<material>();
material2->ambient = glm::vec4(0, 0, 0.15, 1);
material2->textures[texture_role::diffuse] = textureGenerator1->get_texture(0);
material2->textures[texture_role::diffuse] = texgen->get_texture(0);
// material2->diffuse = glm::vec4(0.2, 1.0, 0.7, 1);
material2->diffuse = glm::vec4(1, 1, 1, 1);
material2->specular = glm::vec4(0.3, 0.3, 0.3, 1);
@@ -102,14 +105,14 @@ int main() {
// Set up demo parts
// --------------------------------------------------------------------------------------
DemoPartClear demoPartClear;
demoPartClear.startTime = 0;
demoPartClear.endTime = DEMO_LENGTH_IN_SECONDS;
demo_part_clear demoPartClear;
demoPartClear.start_time = 0;
demoPartClear.end_time = DEMO_LENGTH_IN_SECONDS;
demoPartClear.color = glm::vec4(0.1f, 0.1f, 0.3f, 1.0f);
DemoPartScene demoPartScene;
demoPartScene.startTime = 0;
demoPartScene.endTime = DEMO_LENGTH_IN_SECONDS;
demo_part_scene demoPartScene;
demoPartScene.start_time = 0;
demoPartScene.end_time = DEMO_LENGTH_IN_SECONDS;
demoPartScene.cameraName = "cam1";
demoPartScene.lightName = "light1";
@@ -135,21 +138,21 @@ int main() {
back_plane->material_ = demo_data::materials[1];
back_plane->position = glm::vec3(0, 5, -5);
back_plane->scale = glm::vec3(10);
back_plane->rotation = angleAxis(3.141529f, glm::vec3(1.0f, 0.0f, 0.0f));
back_plane->rotation = glm::angleAxis(3.141529f, glm::vec3(1.0f, 0.0f, 0.0f));
auto left_plane = std::make_shared<mesh_node>("left plane");
left_plane->mesh_ = demo_data::meshes[2];
left_plane->material_ = demo_data::materials[1];
left_plane->position = glm::vec3(-5, 5, 0);
left_plane->scale = glm::vec3(10);
left_plane->rotation = angleAxis(-3.141529f / 2.0f, glm::vec3(0.0f, 1.0f, 0.0f));
left_plane->rotation = glm::angleAxis(-3.141529f / 2.0f, glm::vec3(0.0f, 1.0f, 0.0f));
auto right_plane = std::make_shared<mesh_node>("right plane");
right_plane->mesh_ = demo_data::meshes[2];
right_plane->material_ = demo_data::materials[1];
right_plane->position = glm::vec3(5, 5, 0);
right_plane->scale = glm::vec3(10);
right_plane->rotation = angleAxis(3.141529f / 2.0f, glm::vec3(0.0f, 1.0f, 0.0f));
right_plane->rotation = glm::angleAxis(3.141529f / 2.0f, glm::vec3(0.0f, 1.0f, 0.0f));
auto bigSphere = make_shared<mesh_node>("big sphere");
bigSphere->mesh_ = demo_data::meshes[0];
@@ -178,7 +181,7 @@ int main() {
lightNode->spot_cutoff = 50.0f;
lightNode->spot_exponent = 16.0f;
lightNode->ambient = glm::vec4(0.1, 0.1, 0.1, 1.0);
lightNode->diffuse = glm::vec4(0.5, 1.0, 1.0, 1.0);
lightNode->diffuse = glm::vec4(0.1, 0.3, 1.0, 1.0);
lightNode->specular = glm::vec4(0.0, 0.8, 0.1, 1.0);
auto lightNode2 = make_shared<light_node>(light_type::spot);
@@ -188,8 +191,8 @@ int main() {
lightNode2->spot_cutoff = 50.0f;
lightNode2->spot_exponent = 16.0f;
lightNode2->ambient = glm::vec4(0.1, 0.1, 0.1, 1.0);
lightNode2->diffuse = glm::vec4(1.0, 0.5, 1.0, 1.0);
lightNode2->specular = glm::vec4(0.0, 0.8, 0.1, 1.0);
lightNode2->diffuse = glm::vec4(1.0, 0.5, 0.3, 1.0);
lightNode2->specular = glm::vec4(1.0, 0.8, 0.1, 1.0);
scene1->tree->add(ground_plane);
scene1->tree->add(back_plane);
@@ -213,14 +216,15 @@ int main() {
glBindFramebuffer(GL_FRAMEBUFFER, 0);
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
ImGui::StyleColorsDark();
// Setup Platform/Renderer backends
ImGui_ImplGlfw_InitForOpenGL(((peripherals_glfw*)&peripherals)->get_window(), true);
ImGui_ImplOpenGL3_Init("#version 150");
// IMGUI_CHECKVERSION();
// ImGui::CreateContext();
// ImGuiIO& io = ImGui::GetIO();
// (void) io;
// ImGui::StyleColorsDark();
//
// // Setup Platform/Renderer backends
// ImGui_ImplGlfw_InitForOpenGL(((peripherals_glfw *) &peripherals)->get_window(), true);
// ImGui_ImplOpenGL3_Init("#version 150");
timer timer1;
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
@@ -228,56 +232,57 @@ int main() {
bool show_another_window = false;
while (!peripherals.should_close() && timer1.seconds_since_start() < DEMO_LENGTH_IN_SECONDS) {
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
{
static float f = 0.0f;
static int counter = 0;
ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
ImGui::Checkbox("Another Window", &show_another_window);
ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
counter++;
ImGui::SameLine();
ImGui::Text("counter = %d", counter);
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
ImGui::End();
}
// ImGui_ImplOpenGL3_NewFrame();
// ImGui_ImplGlfw_NewFrame();
// ImGui::NewFrame();
//
// {
// static float f = 0.0f;
// static int counter = 0;
//
// ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
//
// ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
// ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
// ImGui::Checkbox("Another Window", &show_another_window);
//
// ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
// ImGui::ColorEdit3("clear color", (float *) &clear_color); // Edit 3 floats representing a color
//
// if (ImGui::Button(
// "Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
// counter++;
// ImGui::SameLine();
// ImGui::Text("counter = %d", counter);
//
// ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
// ImGui::End();
// }
double elapsedSeconds = timer1.seconds_since_start();
auto elapsed_seconds = timer1.seconds_since_start();
bigSphere->mesh_ = mesh_generator::extrude(mesh_generator::sphere(50, 50), {200, 201, 100, 101, 400, 401}, 0.05,
(int) ((sin(elapsedSeconds) + 0.5) * 40));
(int) ((sinf(elapsed_seconds) + 0.5f) * 40));
smallSphere->position = glm::vec3(0, sin(2 * M_PI * 0.13 * elapsedSeconds) * 2.0 + 0.5, 0);
smallSphere->position = glm::vec3(0, sin(2 * M_PI * 0.13 * elapsed_seconds) * 2.0 + 0.5, 0);
// meshNode->position = glm::vec3(0, 0.001, 0);
// camNode->target = glm::vec3(0, 0.0001, 0);
// camNode->position = glm::vec3(0, 5, -10);
lightNode2->position = glm::vec3(5 * sin(2 * M_PI * 0.05 * elapsedSeconds), 2,
5 * cos(2 * M_PI * 0.05 * elapsedSeconds));
lightNode->position = glm::vec3(5 * cos(2 * M_PI * 0.75 * elapsedSeconds), 2,
5 * sin(2 * M_PI * 0.75 * elapsedSeconds));
lightNode2->position = glm::vec3(5 * sin(2 * M_PI * 0.05 * elapsed_seconds), 2,
5 * cos(2 * M_PI * 0.05 * elapsed_seconds));
lightNode->position = glm::vec3(5 * cos(2 * M_PI * 0.75 * elapsed_seconds), 2,
5 * sin(2 * M_PI * 0.75 * elapsed_seconds));
lightMeshNode->position = lightNode2->position;
bigSphere->rotation *= angleAxis((float) (M_PI / 4.0 * timer1.lap()), normalize(glm::vec3(0.2, 0.5, 0.3)));
demoPartClear.process(demoPartClear.normalizeTime(elapsedSeconds));
demoPartScene.process(demoPartScene.normalizeTime(elapsedSeconds));
demoPartClear.process(demoPartClear.normalize_time(elapsed_seconds));
demoPartScene.process(demoPartScene.normalize_time(elapsed_seconds));
ImGui::Render();
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
// ImGui::Render();
// ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
peripherals.swap_buffers();
peripherals.poll_events();
+39
View File
@@ -0,0 +1,39 @@
Midi events delta time
https://sites.uci.edu/camp2014/2014/05/19/timing-in-midi-files/
http://www.music.mcgill.ca/~ich/classes/mumt306/StandardMIDIfileformat.html#BM2_3
- Delta-time is in some fraction of a beat (or a second, for recording a track with SMPTE times), as specified in the header chunk.
- nardis header track:
Format: 1
tracks: 10
division : 480
The third word, <division>, specifies the meaning of the delta-times.
It has two formats, one for metrical time, and one for time-code-based time:
bit 15 bits 14 thru 8 bits 7 thru 0
======|===============================|==============
0 | ticks per quarter-note
1 | negative SMPTE format | ticks per frame
If bit 15 of <division> is zero, the bits 14 thru 0 represent the number of delta time "ticks" which make up a quarter-note.
For instance, if division is 96, then a time interval of an eighth-note between two events in the file would be 48.
nardis division == 480 => bit 15 is zero, so we have 480 ticks per quarter note.
default tempo is 120, if not specified by a meta event
default time signature is 4/4 if not specified by a meta event
nardis has 4/4 time signature and tempo of 300000 microseconds per quarter note
MIDI header track gives division, which is PPQ (parts per quarter or ticks per quarter note). Nardis = 480 => delta time of 480 means a quarter note.
But how long is a quarter note? that is given by the tempo.
PITCH bending
https://sites.uci.edu/camp2014/2014/04/30/managing-midi-pitchbend-messages/
- we get a 14bit value, [0..16383]
- map this to [-1..1], meaning that 16383/2 means no bend
- the float is the relative amount of bending, we should multiply it by a synth setting which says what is the bending range (+/- 2 semitones for example)
+7 -1
View File
@@ -1,5 +1,6 @@
set(HEADERS
${HEADERS}
${CMAKE_CURRENT_SOURCE_DIR}/audio/sound_server.h
${CMAKE_CURRENT_SOURCE_DIR}/animation_track.h
${CMAKE_CURRENT_SOURCE_DIR}/camera_node.h
${CMAKE_CURRENT_SOURCE_DIR}/colour.h
@@ -10,13 +11,15 @@ set(HEADERS
${CMAKE_CURRENT_SOURCE_DIR}/mesh.h
${CMAKE_CURRENT_SOURCE_DIR}/mesh_generator.h
${CMAKE_CURRENT_SOURCE_DIR}/mesh_node.h
${CMAKE_CURRENT_SOURCE_DIR}/particles.h
${CMAKE_CURRENT_SOURCE_DIR}/peripherals.h
${CMAKE_CURRENT_SOURCE_DIR}/peripherals_glfw.h
${CMAKE_CURRENT_SOURCE_DIR}/perlin.h
${CMAKE_CURRENT_SOURCE_DIR}/scene.h
${CMAKE_CURRENT_SOURCE_DIR}/scene_node.h
${CMAKE_CURRENT_SOURCE_DIR}/scene_renderer.h
${CMAKE_CURRENT_SOURCE_DIR}/scene_tree.h
${CMAKE_CURRENT_SOURCE_DIR}/shader.h
${CMAKE_CURRENT_SOURCE_DIR}/shader_program.h
${CMAKE_CURRENT_SOURCE_DIR}/shader_constants.h
${CMAKE_CURRENT_SOURCE_DIR}/texture.h
${CMAKE_CURRENT_SOURCE_DIR}/texture_generator.h
@@ -27,6 +30,7 @@ set(HEADERS
set(SOURCE
${SOURCE}
${CMAKE_CURRENT_SOURCE_DIR}/audio/sound_server.cpp
${CMAKE_CURRENT_SOURCE_DIR}/animation_track.cpp
${CMAKE_CURRENT_SOURCE_DIR}/camera_node.cpp
${CMAKE_CURRENT_SOURCE_DIR}/demo_data.cpp
@@ -36,7 +40,9 @@ set(SOURCE
${CMAKE_CURRENT_SOURCE_DIR}/mesh.cpp
${CMAKE_CURRENT_SOURCE_DIR}/mesh_generator.cpp
${CMAKE_CURRENT_SOURCE_DIR}/mesh_node.cpp
${CMAKE_CURRENT_SOURCE_DIR}/particles.cpp
${CMAKE_CURRENT_SOURCE_DIR}/peripherals_glfw.cpp
${CMAKE_CURRENT_SOURCE_DIR}/perlin.cpp
${CMAKE_CURRENT_SOURCE_DIR}/scene.cpp
${CMAKE_CURRENT_SOURCE_DIR}/scene_node.cpp
${CMAKE_CURRENT_SOURCE_DIR}/scene_renderer.cpp
+36
View File
@@ -0,0 +1,36 @@
#include "sound_server.h"
#include <iostream>
#include <SDL.h>
void audio_callback(void *param, uint8_t *stream, int len) {
auto producer = reinterpret_cast<sound_producer *>(param);
uint16_t samples = len >> 2; // 4 bytes per F32
uint16_t frames = samples >> 1; // 2 channels, left and right
producer->render(reinterpret_cast<float *>(stream), frames);
}
sound_server::sound_server(uint16_t samplerate, sound_producer& producer) {
if (SDL_Init(SDL_INIT_AUDIO) < 0) {
std::cerr << "Init failed" << std::endl;
exit(1);
}
SDL_AudioSpec spec;
spec.freq = samplerate;
spec.format = AUDIO_F32;
spec.samples = 256;
spec.callback = audio_callback;
spec.userdata = reinterpret_cast<void *>(&producer);
spec.channels = 2;
if (SDL_OpenAudio(&spec, nullptr) < 0) {
std::cerr << "Unable to open audio" << std::endl;
exit(1);
}
SDL_PauseAudio(0);
}
sound_server::~sound_server() {
SDL_Quit();
}
+13
View File
@@ -0,0 +1,13 @@
#pragma once
#include <cstdint>
struct sound_producer {
// interleaved samples, LR
virtual void render(float *buffer, uint16_t frames) = 0;
};
struct sound_server {
sound_server(uint16_t samplerate, sound_producer& producer);
~sound_server();
};
+9
View File
@@ -1,9 +1,18 @@
#pragma once
#include <glad/glad.h>
#include <easylogging++.h>
#define BEGIN_NAMESPACE namespace acidrain {
#define END_NAMESPACE };
inline int rand_int(int x, int y) { return rand() % (y - x + 1) + x; }
inline double rand_float() { return ((rand()) / (RAND_MAX + 1.0)); }
inline double rand_in_range(double x, double y) {
return x + rand_float() * (y - x);
}
//static int SCREEN_WIDTH = 800;
//static int SCREEN_HEIGHT = 600;
+5 -5
View File
@@ -4,12 +4,12 @@
BEGIN_NAMESPACE
struct DemoPart {
float startTime; // absolute time, since demo starts
float endTime; // absolute time, since demo starts
struct demo_part {
float start_time; // absolute time, since demo starts
float end_time; // absolute time, since demo starts
float normalizeTime(float absoluteTimeInSeconds) {
return (absoluteTimeInSeconds - startTime) / static_cast<float>(endTime - startTime);
float normalize_time(float absolute_time_in_seconds) {
return (absolute_time_in_seconds - start_time) / static_cast<float>(end_time - start_time);
}
virtual void process(float normalizedTime) = 0;
+4 -4
View File
@@ -2,18 +2,18 @@
BEGIN_NAMESPACE
void DemoPartClear::process(float normalizedTime) {
void demo_part_clear::process(float normalized_time) {
glClearColor(color.r, color.g, color.b, color.a);
GLbitfield mask = 0;
if (clearDepth)
if (do_clear_depth)
mask |= GL_DEPTH_BUFFER_BIT;
if (clearColor)
if (do_clear_color)
mask |= GL_COLOR_BUFFER_BIT;
if (clearStencil)
if (do_clear_stencil)
mask |= GL_STENCIL_BUFFER_BIT;
glClear(mask);
+5 -5
View File
@@ -5,15 +5,15 @@
BEGIN_NAMESPACE
struct DemoPartClear : DemoPart {
struct demo_part_clear : demo_part {
glm::vec4 color = glm::vec4(0, 0, 0, 0);
bool clearDepth = true;
bool clearColor = true;
bool clearStencil = true;
bool do_clear_depth = true;
bool do_clear_color = true;
bool do_clear_stencil = true;
void process(float normalizedTime) override;
void process(float normalized_time) override;
};
END_NAMESPACE
+52 -52
View File
@@ -6,7 +6,7 @@
BEGIN_NAMESPACE
DemoPartMarchingCubes::DemoPartMarchingCubes(std::shared_ptr<mesh> affectedMesh) {
demo_part_marching_cubes::demo_part_marching_cubes(std::shared_ptr<mesh> affectedMesh) {
mesh_ = affectedMesh;
field.emitters.push_back(glm::vec4(0, 0.7, 0, 1));
@@ -15,36 +15,36 @@ DemoPartMarchingCubes::DemoPartMarchingCubes(std::shared_ptr<mesh> affectedMesh)
// field.emitters.push_back(glm::vec4(-0.5, 0.7, -0.3, 1));
}
void DemoPartMarchingCubes::process(float normalizedTime) {
void demo_part_marching_cubes::process(float normalized_time) {
field.emitters[0].x = sin(normalizedTime * 2 * M_PI * 4);
field.emitters[0].z = cos(normalizedTime * 2 * M_PI * 4);
field.emitters[0].y = 0.7 * cos(normalizedTime * 2 * M_PI * 2);
field.emitters[0].x = sin(normalized_time * 2 * M_PI * 4);
field.emitters[0].z = cos(normalized_time * 2 * M_PI * 4);
field.emitters[0].y = 0.7 * cos(normalized_time * 2 * M_PI * 2);
field.emitters[1].x = sin(normalizedTime * 2 * M_PI * 7);
field.emitters[1].z = cos(normalizedTime * 2 * M_PI * 3.5);
field.emitters[1].x = sin(normalized_time * 2 * M_PI * 7);
field.emitters[1].z = cos(normalized_time * 2 * M_PI * 3.5);
field.emitters[2].y = 0.5 * sin(normalizedTime * 2 * M_PI * 4);
field.emitters[2].z = 0.8 * cos(normalizedTime * 2 * M_PI * 2);
field.emitters[2].y = 0.5 * sin(normalized_time * 2 * M_PI * 4);
field.emitters[2].z = 0.8 * cos(normalized_time * 2 * M_PI * 2);
// field.emitters[3].y = 0.8 * cos(normalizedTime * 2 * M_PI * 3);
// field.emitters[3].z = 0.2 * sin(normalizedTime * 2 * M_PI * 8);
grid.evaluateForces(field);
grid.triangulate(*mesh_.get(), minFieldValue);
grid.evaluate_forces(field);
grid.triangulate(*mesh_.get(), min_field_value);
for (auto &v: mesh_->vertices)
v.normal = field.getFieldNormalAt(v.position);
v.normal = field.get_field_normal_at(v.position);
// calculateNormals(*mesh.get());
}
void MarchingCubesGrid::evaluateForces(ForceField &field) {
void marching_cubes_grid::evaluate_forces(force_field &field) {
// Make sure we have enough space preallocated.
// We use resize because we want it also logically allocated with defaults
// so we can simply access an item at certain index with no issues
gridVertices.resize((xCells + 1) * (yCells + 1) * (zCells + 1));
grid_vertices.resize((xCells + 1) * (yCells + 1) * (zCells + 1));
glm::vec3 stepSize(
(xMax - xMin) / static_cast<float>(xCells),
@@ -64,11 +64,11 @@ void MarchingCubesGrid::evaluateForces(ForceField &field) {
for (int x = 0; x <= xCells; x++) {
gridVertex.x = xMin + x * stepSize.x;
gridVertex.w = field.getFieldValueAt(glm::vec3(gridVertex));
gridVertex.w = field.get_field_value_at(glm::vec3(gridVertex));
// std::cout << std::setprecision(5) << std::fixed << "(x: " << gridVertex.x << ", y: " << gridVertex.y << ", z: " << gridVertex.z << ", val: " << gridVertex.w << ")" << std::endl;
gridVertices[cellIndex] = gridVertex;
grid_vertices[cellIndex] = gridVertex;
cellIndex++;
}
@@ -77,7 +77,7 @@ void MarchingCubesGrid::evaluateForces(ForceField &field) {
}
void MarchingCubesGrid::triangulate(mesh &m, float minFieldValue) {
void marching_cubes_grid::triangulate(mesh &m, float minFieldValue) {
m.vertices.clear();
m.facets.clear();
@@ -87,20 +87,20 @@ void MarchingCubesGrid::triangulate(mesh &m, float minFieldValue) {
for (int y = 0; y < yCells; y++) {
for (int x = 0; x < xCells; x++) {
calculateCellVertices(x, y, z);
calculate_cell_vertices(x, y, z);
int cellType = classifyCell(minFieldValue);
int cellType = classify_cell(minFieldValue);
if (!edgeTable[cellType]) continue;
calculateIntersectionVertices(cellType, minFieldValue);
addResultingFacets(m, cellType);
calculate_intersection_vertices(cellType, minFieldValue);
add_resulting_facets(m, cellType);
}
}
}
}
void MarchingCubesGrid::calculateCellVertices(int x, int y, int z) {
void marching_cubes_grid::calculate_cell_vertices(int x, int y, int z) {
// TODO: optimize these out. they are constant for a given grid size.
int xVerts = xCells + 1;
int yVerts = yCells + 1;
@@ -109,61 +109,61 @@ void MarchingCubesGrid::calculateCellVertices(int x, int y, int z) {
int leftTopFarthestIndex = z * vertsInXYPlane + x + y * xCells;
// see http://paulbourke.net/geometry/polygonise/polygonise1.gif
cubeVertexIndices[0] = leftTopFarthestIndex + xVerts;
cubeVertexIndices[1] = leftTopFarthestIndex + xVerts + 1;
cubeVertexIndices[2] = leftTopFarthestIndex + xVerts + 1 + vertsInXYPlane;
cubeVertexIndices[3] = leftTopFarthestIndex + xVerts + vertsInXYPlane;
cube_vertex_indices[0] = leftTopFarthestIndex + xVerts;
cube_vertex_indices[1] = leftTopFarthestIndex + xVerts + 1;
cube_vertex_indices[2] = leftTopFarthestIndex + xVerts + 1 + vertsInXYPlane;
cube_vertex_indices[3] = leftTopFarthestIndex + xVerts + vertsInXYPlane;
cubeVertexIndices[4] = leftTopFarthestIndex;
cubeVertexIndices[5] = leftTopFarthestIndex + 1;
cubeVertexIndices[6] = leftTopFarthestIndex + 1 + vertsInXYPlane;
cubeVertexIndices[7] = leftTopFarthestIndex + vertsInXYPlane;
cube_vertex_indices[4] = leftTopFarthestIndex;
cube_vertex_indices[5] = leftTopFarthestIndex + 1;
cube_vertex_indices[6] = leftTopFarthestIndex + 1 + vertsInXYPlane;
cube_vertex_indices[7] = leftTopFarthestIndex + vertsInXYPlane;
}
int MarchingCubesGrid::classifyCell(float minFieldValue) {
int marching_cubes_grid::classify_cell(float minFieldValue) {
int result = 0;
for (int i = 0; i < 8; i++)
if (gridVertices[cubeVertexIndices[i]].w <= minFieldValue)
if (grid_vertices[cube_vertex_indices[i]].w <= minFieldValue)
result |= 1 << i;
return result;
}
void MarchingCubesGrid::calculateIntersectionVertices(int cellType, float minFieldValue) {
void marching_cubes_grid::calculate_intersection_vertices(int cellType, float minFieldValue) {
if (edgeTable[cellType] & 1)
intersectionVertices[0] = intersection(cubeVertexIndices[0], cubeVertexIndices[1], minFieldValue);
intersection_vertices[0] = intersection(cube_vertex_indices[0], cube_vertex_indices[1], minFieldValue);
if (edgeTable[cellType] & 2)
intersectionVertices[1] = intersection(cubeVertexIndices[1], cubeVertexIndices[2], minFieldValue);
intersection_vertices[1] = intersection(cube_vertex_indices[1], cube_vertex_indices[2], minFieldValue);
if (edgeTable[cellType] & 4)
intersectionVertices[2] = intersection(cubeVertexIndices[2], cubeVertexIndices[3], minFieldValue);
intersection_vertices[2] = intersection(cube_vertex_indices[2], cube_vertex_indices[3], minFieldValue);
if (edgeTable[cellType] & 8)
intersectionVertices[3] = intersection(cubeVertexIndices[3], cubeVertexIndices[0], minFieldValue);
intersection_vertices[3] = intersection(cube_vertex_indices[3], cube_vertex_indices[0], minFieldValue);
if (edgeTable[cellType] & 16)
intersectionVertices[4] = intersection(cubeVertexIndices[4], cubeVertexIndices[5], minFieldValue);
intersection_vertices[4] = intersection(cube_vertex_indices[4], cube_vertex_indices[5], minFieldValue);
if (edgeTable[cellType] & 32)
intersectionVertices[5] = intersection(cubeVertexIndices[5], cubeVertexIndices[6], minFieldValue);
intersection_vertices[5] = intersection(cube_vertex_indices[5], cube_vertex_indices[6], minFieldValue);
if (edgeTable[cellType] & 64)
intersectionVertices[6] = intersection(cubeVertexIndices[6], cubeVertexIndices[7], minFieldValue);
intersection_vertices[6] = intersection(cube_vertex_indices[6], cube_vertex_indices[7], minFieldValue);
if (edgeTable[cellType] & 128)
intersectionVertices[7] = intersection(cubeVertexIndices[7], cubeVertexIndices[4], minFieldValue);
intersection_vertices[7] = intersection(cube_vertex_indices[7], cube_vertex_indices[4], minFieldValue);
if (edgeTable[cellType] & 256)
intersectionVertices[8] = intersection(cubeVertexIndices[0], cubeVertexIndices[4], minFieldValue);
intersection_vertices[8] = intersection(cube_vertex_indices[0], cube_vertex_indices[4], minFieldValue);
if (edgeTable[cellType] & 512)
intersectionVertices[9] = intersection(cubeVertexIndices[1], cubeVertexIndices[5], minFieldValue);
intersection_vertices[9] = intersection(cube_vertex_indices[1], cube_vertex_indices[5], minFieldValue);
if (edgeTable[cellType] & 1024)
intersectionVertices[10] = intersection(cubeVertexIndices[2], cubeVertexIndices[6], minFieldValue);
intersection_vertices[10] = intersection(cube_vertex_indices[2], cube_vertex_indices[6], minFieldValue);
if (edgeTable[cellType] & 2048)
intersectionVertices[11] = intersection(cubeVertexIndices[3], cubeVertexIndices[7], minFieldValue);
intersection_vertices[11] = intersection(cube_vertex_indices[3], cube_vertex_indices[7], minFieldValue);
}
glm::vec3 MarchingCubesGrid::intersection(int v1Index, int v2Index, float minFieldValue) {
glm::vec4 &a = gridVertices[v1Index];
glm::vec4 &b = gridVertices[v2Index];
glm::vec3 marching_cubes_grid::intersection(int v1Index, int v2Index, float minFieldValue) {
glm::vec4 &a = grid_vertices[v1Index];
glm::vec4 &b = grid_vertices[v2Index];
if (a.w != b.w) {
float alpha = (minFieldValue - a.w) / (b.w - a.w);
@@ -174,7 +174,7 @@ glm::vec3 MarchingCubesGrid::intersection(int v1Index, int v2Index, float minFie
}
void MarchingCubesGrid::addResultingFacets(mesh &m, int cellType) {
void marching_cubes_grid::add_resulting_facets(mesh &m, int cellType) {
facet f{};
vertex v{};
int vertexOffset = m.vertices.size();
@@ -182,7 +182,7 @@ void MarchingCubesGrid::addResultingFacets(mesh &m, int cellType) {
for (int n = 0; triTable[cellType][n] != -1; n += 3) {
for (int i = 0; i < 3; i++) {
v.position = intersectionVertices[triTable[cellType][n + 2 - i]];
v.position = intersection_vertices[triTable[cellType][n + 2 - i]];
m.vertices.push_back(v);
}
@@ -194,7 +194,7 @@ void MarchingCubesGrid::addResultingFacets(mesh &m, int cellType) {
}
float ForceField::getFieldValueAt(const glm::vec3 &position) const {
float force_field::get_field_value_at(const glm::vec3 &position) const {
float result = 0;
for (auto &e: emitters) {
@@ -206,7 +206,7 @@ float ForceField::getFieldValueAt(const glm::vec3 &position) const {
}
glm::vec3 ForceField::getFieldNormalAt(const glm::vec3 &position) const {
glm::vec3 force_field::get_field_normal_at(const glm::vec3 &position) const {
// Hello blackpawn! http://www.blackpawn.com/texts/metanormals/default.html
glm::vec3 normal = glm::vec3(0);
+19 -19
View File
@@ -6,14 +6,14 @@
BEGIN_NAMESPACE
struct ForceField {
float getFieldValueAt(const glm::vec3 &position) const;
glm::vec3 getFieldNormalAt(const glm::vec3 &position) const;
struct force_field {
float get_field_value_at(const glm::vec3& position) const;
glm::vec3 get_field_normal_at(const glm::vec3& position) const;
std::vector<glm::vec4> emitters; // vec4 = position + strength
};
struct MarchingCubesGrid {
struct marching_cubes_grid {
int xCells = 60;
int yCells = 60;
int zCells = 60;
@@ -28,31 +28,31 @@ struct MarchingCubesGrid {
float zMax = 2;
// .w will hold field value for code size optimisation purposes
std::vector<glm::vec4> gridVertices;
std::vector<glm::vec4> grid_vertices;
void evaluateForces(ForceField &field);
void triangulate(mesh &m, float minFieldValue);
void evaluate_forces(force_field& field);
void triangulate(mesh& m, float minFieldValue);
private:
void calculateCellVertices(int x, int y, int z);
int classifyCell(float minFieldValue);
void calculateIntersectionVertices(int cellType, float minFieldValue);
void addResultingFacets(mesh &m, int cellType);
void calculate_cell_vertices(int x, int y, int z);
int classify_cell(float minFieldValue);
void calculate_intersection_vertices(int cellType, float minFieldValue);
void add_resulting_facets(mesh& m, int cellType);
glm::vec3 intersection(int v1Index, int v2Index, float minFieldValue);
int cubeVertexIndices[8];
glm::vec3 intersectionVertices[12];
int cube_vertex_indices[8];
glm::vec3 intersection_vertices[12];
};
struct DemoPartMarchingCubes : DemoPart {
DemoPartMarchingCubes(std::shared_ptr<mesh> affectedMesh);
struct demo_part_marching_cubes : demo_part {
explicit demo_part_marching_cubes(std::shared_ptr<mesh> affected_mesh);
void process(float normalizedTime) override;
void process(float normalized_time) override;
MarchingCubesGrid grid;
ForceField field;
float minFieldValue = 2.6;
marching_cubes_grid grid;
force_field field;
float min_field_value = 2.6;
std::shared_ptr<mesh> mesh_;
};
+3 -3
View File
@@ -3,12 +3,12 @@
BEGIN_NAMESPACE
DemoPartRenderToTexture::DemoPartRenderToTexture(int s, RenderToTextureAction a)
demo_part_render_to_texture::demo_part_render_to_texture(int s, render_to_texture_action a)
: slot(s), action(a) {
}
void DemoPartRenderToTexture::process(float normalizedTime) {
if (action == RenderToTextureAction::Start)
void demo_part_render_to_texture::process(float normalizedTime) {
if (action == render_to_texture_action::start)
demo_data::fbos[slot]->use();
else
demo_data::fbos[slot]->unuse();
+7 -8
View File
@@ -4,19 +4,18 @@
BEGIN_NAMESPACE
enum class RenderToTextureAction {
Start,
Stop
enum class render_to_texture_action {
start,
stop
};
struct DemoPartRenderToTexture : DemoPart {
struct demo_part_render_to_texture : demo_part {
demo_part_render_to_texture(int slot, render_to_texture_action action);
DemoPartRenderToTexture(int slot, RenderToTextureAction action);
void process(float normalizedTime) override;
void process(float normalized_time) override;
int slot;
RenderToTextureAction action;
render_to_texture_action action;
};
END_NAMESPACE
+3 -6
View File
@@ -7,16 +7,13 @@
BEGIN_NAMESPACE
DemoPartScene::DemoPartScene() {
demo_part_scene::demo_part_scene() {
renderer = std::make_shared<scene_renderer>();
}
DemoPartScene::~DemoPartScene() {
}
void DemoPartScene::process(float normalizedTime) {
void demo_part_scene::process(float normalized_time) {
if (scene_->animation)
scene_->animation->set_at_time(normalizedTime);
scene_->animation->set_at_time(normalized_time);
if (scene_->tree) {
scene_->tree->transform();
+12 -11
View File
@@ -9,27 +9,28 @@
BEGIN_NAMESPACE
struct DemoPartScene : DemoPart {
struct demo_part_scene : demo_part {
DemoPartScene();
virtual ~DemoPartScene();
demo_part_scene();
~demo_part_scene() = default;
void process(float normalized_time) override;
std::shared_ptr<scene_renderer> renderer;
std::shared_ptr<scene> scene_;
std::string cameraName;
std::string lightName;
float animationStartTime; // normalized time, [0-1]
float animationEndTime; // normalized time, [0-1]
float animationStartTime = 0; // normalized time, [0-1]
float animationEndTime = 1.0; // normalized time, [0-1]
GLuint fboID = 0;
GLuint shadowMapTexID = 0;
std::shared_ptr<shader_program> firstPassShadowShader;
GLuint fboID;
GLuint shadowMapTexID;
std::shared_ptr<shader> firstPassShadowShader;
std::shared_ptr<material> firstPassShadowMaterial;
std::shared_ptr<shader_program> secondPassShadowShader;
std::shared_ptr<shader> secondPassShadowShader;
std::shared_ptr<material> secondPassShadowMaterial;
void process(float normalizedTime) override;
};
END_NAMESPACE
+1 -1
View File
@@ -14,7 +14,7 @@
#include "glm/gtx/transform.hpp"
#include "glm/gtc/matrix_transform.hpp"
#include "shader.h"
#include "shader_program.h"
#include "texture.h"
+3 -3
View File
@@ -3,12 +3,12 @@
BEGIN_NAMESPACE
std::vector<std::shared_ptr<texture>> demo_data::textures;
std::vector<std::shared_ptr<shader>> demo_data::shaders;
std::vector<std::shared_ptr<shader_program>> demo_data::shaders;
std::vector<std::shared_ptr<material>> demo_data::materials;
std::vector<std::shared_ptr<mesh>> demo_data::meshes;
std::vector<std::shared_ptr<fbo>> demo_data::fbos;
int demo_data::screen_width = 1024;
int demo_data::screen_height = 768;
int demo_data::screen_width = 1024 * 2;
int demo_data::screen_height = 768 * 2;
END_NAMESPACE
+1 -1
View File
@@ -10,7 +10,7 @@ BEGIN_NAMESPACE
struct demo_data {
static std::vector<std::shared_ptr<texture>> textures;
static std::vector<std::shared_ptr<shader>> shaders;
static std::vector<std::shared_ptr<shader_program>> shaders;
static std::vector<std::shared_ptr<material>> materials;
static std::vector<std::shared_ptr<mesh>> meshes;
static std::vector<std::shared_ptr<fbo>> fbos;
+2 -3
View File
@@ -24,8 +24,7 @@ fbo::fbo(int w, int h)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, color_buffer_id,
0);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, color_buffer_id, 0);
glBindRenderbuffer(GL_RENDERBUFFER, depth_buffer_id);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height);
@@ -52,7 +51,7 @@ void fbo::use() {
old_width = demo_data::screen_width;
old_height = demo_data::screen_height;
demo_data::screen_height = width;
demo_data::screen_width = width;
demo_data::screen_height = height;
glBindFramebuffer(GL_FRAMEBUFFER, frame_buffer_id);
+1 -1
View File
@@ -13,7 +13,7 @@ enum class light_type {
};
struct light_node : scene_node {
light_node(light_type type);
explicit light_node(light_type type);
void calculate_local_transform() override;
+2 -2
View File
@@ -29,7 +29,7 @@ GLenum to_gl(const blending_constant &c) {
void set_material(std::shared_ptr<material> &mat) {
// glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
mat->shader_->use();
mat->shader->bind();
// if (material->textures[TextureRole::Diffuse]) {
// std::cout << "CAN has diffuse texture!!!!!!!!!11" << std::endl;
@@ -86,7 +86,7 @@ void unset_material(std::shared_ptr<material> &mat) {
// textureUnit++;
// }
mat->shader_->unuse();
mat->shader->unbind();
if (mat->transparent)
glDisable(GL_BLEND);
+4 -4
View File
@@ -3,7 +3,7 @@
#include <memory>
#include <map>
#include "texture.h"
#include "shader.h"
#include "shader_program.h"
#include "glm/glm.hpp"
BEGIN_NAMESPACE
@@ -52,11 +52,11 @@ struct material {
blending_constant blend_dst_fact = blending_constant::one_minus_src_alpha;
fill_mode_type fill_mode = fill_mode_type::solid;
std::shared_ptr<shader> shader_;
std::shared_ptr<shader_program> shader;
texture_map textures;
};
void set_material(std::shared_ptr<material> &material);
void unset_material(std::shared_ptr<material> &material);
void set_material(std::shared_ptr<material>& material);
void unset_material(std::shared_ptr<material>& material);
END_NAMESPACE
+1 -1
View File
@@ -8,7 +8,7 @@ BEGIN_NAMESPACE
struct mesh_node : scene_node {
mesh_node();
mesh_node(std::string name);
explicit mesh_node(std::string name);
std::shared_ptr<mesh> mesh_;
std::shared_ptr<material> material_;
+225
View File
@@ -0,0 +1,225 @@
#include "particles.h"
BEGIN_NAMESPACE
particle_emitter::particle_emitter() {
to_spawn = 0;
start_size = 1.0f;
end_size = 1.0f;
}
particle *particle_emitter::new_particle() {
particle *p;
if (dead_particles.empty()) {
p = new particle{};
} else {
p = dead_particles.back();
dead_particles.pop_back();
}
particles.push_back(p);
return p;
}
void particle_emitter::update(float elapsed_ms) {
float factor = elapsed_ms / 1000.0f;
for (auto p : particles) {
p->old_pos = p->position;
p->position += p->velocity * factor;
p->life -= life_decay * factor;
p->color = glm::mix(start_colour, end_colour, p->life);
p->size = glm::mix(start_size, end_size, p->life);
}
// move dead particles to the dead list
auto pit = particles.begin();
while (pit != particles.end()) {
if ((*pit)->life <= 0.0) {
dead_particles.push_back(*pit);
pit = particles.erase(pit);
} else {
++pit;
}
}
// spawn if needed
to_spawn += factor * emission_rate;
auto new_particles = static_cast<int>(to_spawn);
for (auto i = 0; i < new_particles; i++) {
particle *p = new_particle();
spawn(p);
}
to_spawn -= static_cast<float>(new_particles);
}
void particle_system::update(float elapsed_ms) {
particles.clear();
for (auto& emitter: emitters) {
emitter->update(elapsed_ms);
std::copy(emitter->particles.begin(), emitter->particles.end(), std::back_inserter(particles));
}
for (auto& modifier: modifiers) {
for (auto& particle: particles) {
modifier->affect_particle(particle, elapsed_ms);
}
}
}
void particle_system::render() {
// draw trail
// draw head
// Matrix mat;
// mat.fromGL(GL_MODELVIEW_MATRIX);
//
// Vector3D a(mat._mat[0], mat._mat[4], mat._mat[8]);
// Vector3D b(mat._mat[1], mat._mat[5], mat._mat[9]);
//
// Vector3D pos[4];
// pos[0] = (-a - b);
// pos[1] = (a - b);
// pos[2] = (a + b);
// pos[3] = (-a + b);
//
//
// glEnable(GL_COLOR_MATERIAL);
// glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
//
// glBegin(GL_QUADS);
//
// for (ParticleList::iterator it = particles.begin(); it != particles.end(); it++) {
// Particle *p = (*it);
//
// glColor4d(p->color.r, p->color.g, p->color.b, p->color.a);
//
// glTexCoord2f(1.0f, 1.0f);
// glVertex3d(pos[0].x * p->size + p->position.x, pos[0].y * p->size + p->position.y, pos[0].z * p->size + p->position.z);
//
// glTexCoord2f(0.0f, 1.0f);
// glVertex3d(pos[1].x * p->size + p->position.x, pos[1].y * p->size + p->position.y, pos[1].z * p->size + p->position.z);
//
// glTexCoord2f(0.0f, 0.0f);
// glVertex3d(pos[2].x * p->size + p->position.x, pos[2].y * p->size + p->position.y, pos[2].z * p->size + p->position.z);
//
// glTexCoord2f(1.0f, 0.0f);
// glVertex3d(pos[3].x * p->size + p->position.x, pos[3].y * p->size + p->position.y, pos[3].z * p->size + p->position.z);
// }
//
// glEnd();
//
// //
//
// glDisable(GL_TEXTURE_2D);
// glBegin(GL_LINES);
//
// for (ParticleList::iterator it = particles.begin(); it != particles.end(); it++) {
// Particle *p = (*it);
//
// glColor4d(p->color.r, p->color.g, p->color.b, p->color.a);
//
// glVertex3d(p->previousPosition.x, p->previousPosition.y, p->previousPosition.z);
// glVertex3d(p->position.x, p->position.y, p->position.z);
// }
//
// glEnd();
//
//
// glDisable(GL_COLOR_MATERIAL);
/*
glEnable( GL_COLOR_MATERIAL );
glColorMaterial( GL_FRONT, GL_AMBIENT_AND_DIFFUSE );
glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE );
// This is how will our point sprite's size will be modified by
// distance from the viewer
float quadratic[] = { 1.0f, 0.0f, 0.01f };
glPointParameterfvARB( GL_POINT_DISTANCE_ATTENUATION_ARB, quadratic );
// Query for the max point size supported by the hardware
float maxSize = 0.0f;
glGetFloatv( GL_POINT_SIZE_MAX_ARB, &maxSize );
// Clamp size to 100.0f or the sprites could get a little too big on some
// of the newer graphic cards. My ATI card at home supports a max point
// size of 1024.0f!
maxSize = min( maxSize, 100.0f );
glPointSize( maxSize );
// The alpha of a point is calculated to allow the fading of points
// instead of shrinking them past a defined threshold size. The threshold
// is defined by GL_POINT_FADE_THRESHOLD_SIZE_ARB and is not clamped to
// the minimum and maximum point sizes.
glPointParameterfARB( GL_POINT_FADE_THRESHOLD_SIZE_ARB, 60.0f );
glPointParameterfARB( GL_POINT_SIZE_MIN_ARB, 1.0f );
glPointParameterfARB( GL_POINT_SIZE_MAX_ARB, maxSize );
// Specify point sprite texture coordinate replacement mode for each
// texture unit
glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE );
glEnable( GL_POINT_SPRITE_ARB );
glBegin( GL_POINTS );
for ( ParticleList::iterator it = particles.begin(); it != particles.end(); it++ ) {
Particle *p = (*it);
glColor4d( p->color.r, p->color.g, p->color.b, p->color.a );
glVertex3d( p->position.x, p->position.y, p->position.z );
}
glEnd();
glDisable( GL_POINT_SPRITE_ARB );
glDisable( GL_BLEND );
glDisable( GL_COLOR_MATERIAL );
*/
}
dot_particle_emitter::dot_particle_emitter() {
emission_rate = 30.0f;
life_decay = 0.1;
}
void dot_particle_emitter::spawn(acidrain::particle *p) {
if (nullptr == p) {
return;
}
p->position = {0, 0, 0};
p->color = {rand_in_range(0, 1), rand_in_range(0, 1), rand_in_range(0, 1), 1.0};
p->velocity = glm::normalize(glm::vec3(rand_in_range(-1, 1), rand_in_range(-1, 1), rand_in_range(-1, 1)));
// p->velocity *= 10;
p->life = 1.0;
}
END_NAMESPACE
void acidrain::particle_attractor::init(glm::vec3& center, float s) {
attractor_center = center;
strength = s;
}
void acidrain::particle_attractor::affect_particle(acidrain::particle *p, float elapsed_ms) {
float factor = elapsed_ms / 1000.0f;
glm::vec3 attract_direction = attractor_center - p->position;
float distance_to_center = glm::length(attract_direction);
float amount = 1.0f / (distance_to_center * distance_to_center) * strength;
p->velocity += attract_direction * amount * factor;
}
+76
View File
@@ -0,0 +1,76 @@
#pragma once
#include "defines.h"
#include "colour.h"
#include <glm/glm.hpp>
#include <vector>
BEGIN_NAMESPACE
struct particle;
struct particle_emitter;
struct particle_modifier;
using particle_list = std::vector<particle *>;
using particle_emitter_list = std::vector<particle_emitter *>;
using particle_modifier_list = std::vector<particle_modifier *>;
struct particle {
glm::vec3 position;
glm::vec3 old_pos;
glm::vec3 velocity;
colour color;
float life;
float size;
};
struct particle_emitter {
particle_emitter();
virtual ~particle_emitter() = default;
particle *new_particle();
void update(float elapsed_ms);
virtual void spawn(particle *p) = 0;
particle_list particles;
particle_list dead_particles;
glm::vec3 position{};
float emission_rate{}; // particles per second
float to_spawn;
float life_decay{};
colour start_colour{};
colour end_colour{};
float start_size;
float end_size;
};
struct particle_modifier {
virtual void affect_particle(particle *p, float elapsed_ms) = 0;
};
struct particle_system {
void update(float elapsed_ms);
void render();
particle_list particles;
particle_emitter_list emitters;
particle_modifier_list modifiers;
};
struct dot_particle_emitter : particle_emitter {
dot_particle_emitter();
void spawn(particle *p) override;
};
struct particle_attractor : particle_modifier {
void init(glm::vec3& center, float strength_);
void affect_particle(particle *p, float elapsed_ms) override;
glm::vec3 attractor_center;
float strength;
};
END_NAMESPACE
+1 -1
View File
@@ -5,7 +5,7 @@ BEGIN_NAMESPACE
class peripherals {
public:
virtual bool init() = 0;
virtual bool init(uint16_t width, uint16_t height, const char* title, bool fullscreen = false) = 0;
virtual void swap_buffers() = 0;
virtual void poll_events() = 0;
virtual bool should_close() = 0;
+4 -6
View File
@@ -1,7 +1,6 @@
#include "peripherals_glfw.h"
#include <GLFW/glfw3.h>
#include <iostream>
#include "demo_data.h"
#include "defines.h"
BEGIN_NAMESPACE
@@ -20,7 +19,7 @@ static void key_callback(GLFWwindow *window, int key, int scancode, int action,
}
}
bool peripherals_glfw::init() {
bool peripherals_glfw::init(uint16_t width, uint16_t height, const char *title, bool fullscreen) {
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
@@ -31,10 +30,9 @@ bool peripherals_glfw::init() {
glfwSetErrorCallback(error_callback);
bool fullscreen = false;
window = glfwCreateWindow(demo_data::screen_width,
demo_data::screen_height,
"Demo",
window = glfwCreateWindow(width,
height,
title,
fullscreen ? glfwGetPrimaryMonitor() : nullptr,
nullptr);
if (window == nullptr) {
+1 -1
View File
@@ -9,7 +9,7 @@ BEGIN_NAMESPACE
class peripherals_glfw : public peripherals {
public:
bool init() override;
bool init(uint16_t width, uint16_t height, const char* title, bool fullscreen = false) override;
void swap_buffers() override;
void poll_events() override;
bool should_close() override;
+263
View File
@@ -0,0 +1,263 @@
#include "perlin.h"
#include <cmath>
// Thank you, Ken Perlin
BEGIN_NAMESPACE
namespace perlin {
#define B 0x100
#define BM 0xff
#define N 0x1000
#define NP 12 /* 2^N */
#define NM 0xfff
#define s_curve(t) ( t * t * (3. - 2. * t) )
#define lerp(t, a, b) ( a + t * (b - a) )
#define setup(i, b0, b1, r0, r1)\
t = vec[i] + N;\
b0 = ((int)t) & BM;\
b1 = (b0+1) & BM;\
r0 = t - (int)t;\
r1 = r0 - 1.;
#define at2(rx, ry) ( rx * q[0] + ry * q[1] )
#define at3(rx, ry, rz) ( rx * q[0] + ry * q[1] + rz * q[2] )
/* Coherent noise function over 1, 2 or 3 dimensions */
/* (copyright Ken Perlin) */
static int p[B + B + 2];
static double g3[B + B + 2][3];
static double g2[B + B + 2][2];
static double g1[B + B + 2];
static int start = 1;
double noise1(double arg) {
int bx0, bx1;
double rx0, rx1, sx, t, u, v, vec[1];
vec[0] = arg;
if (start) {
start = 0;
init();
}
setup(0, bx0, bx1, rx0, rx1);
sx = s_curve(rx0);
u = rx0 * g1[p[bx0]];
v = rx1 * g1[p[bx1]];
return (lerp(sx, u, v));
}
double noise2(double vec[2]) {
int bx0, bx1, by0, by1, b00, b10, b01, b11;
double rx0, rx1, ry0, ry1, *q, sx, sy, a, b, t, u, v;
int i, j;
if (start) {
start = 0;
init();
}
setup(0, bx0, bx1, rx0, rx1);
setup(1, by0, by1, ry0, ry1);
i = p[bx0];
j = p[bx1];
b00 = p[i + by0];
b10 = p[j + by0];
b01 = p[i + by1];
b11 = p[j + by1];
sx = s_curve(rx0);
sy = s_curve(ry0);
q = g2[b00];
u = at2(rx0, ry0);
q = g2[b10];
v = at2(rx1, ry0);
a = lerp(sx, u, v);
q = g2[b01];
u = at2(rx0, ry1);
q = g2[b11];
v = at2(rx1, ry1);
b = lerp(sx, u, v);
return lerp(sy, a, b);
}
double noise3(double vec[3]) {
int bx0, bx1, by0, by1, bz0, bz1, b00, b10, b01, b11;
double rx0, rx1, ry0, ry1, rz0, rz1, *q, sy, sz, a, b, c, d, t, u, v;
int i, j;
if (start) {
start = 0;
init();
}
setup(0, bx0, bx1, rx0, rx1);
setup(1, by0, by1, ry0, ry1);
setup(2, bz0, bz1, rz0, rz1);
i = p[bx0];
j = p[bx1];
b00 = p[i + by0];
b10 = p[j + by0];
b01 = p[i + by1];
b11 = p[j + by1];
t = s_curve(rx0);
sy = s_curve(ry0);
sz = s_curve(rz0);
q = g3[b00 + bz0];
u = at3(rx0, ry0, rz0);
q = g3[b10 + bz0];
v = at3(rx1, ry0, rz0);
a = lerp(t, u, v);
q = g3[b01 + bz0];
u = at3(rx0, ry1, rz0);
q = g3[b11 + bz0];
v = at3(rx1, ry1, rz0);
b = lerp(t, u, v);
c = lerp(sy, a, b);
q = g3[b00 + bz1];
u = at3(rx0, ry0, rz1);
q = g3[b10 + bz1];
v = at3(rx1, ry0, rz1);
a = lerp(t, u, v);
q = g3[b01 + bz1];
u = at3(rx0, ry1, rz1);
q = g3[b11 + bz1];
v = at3(rx1, ry1, rz1);
b = lerp(t, u, v);
d = lerp(sy, a, b);
return lerp(sz, c, d);
}
void normalize2(double v[2]) {
double s;
s = sqrt(v[0] * v[0] + v[1] * v[1]);
v[0] = v[0] / s;
v[1] = v[1] / s;
}
void normalize3(double v[3]) {
double s;
s = sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
v[0] = v[0] / s;
v[1] = v[1] / s;
v[2] = v[2] / s;
}
/* --- My harmonic summing functions - PDB --------------------------*/
/*
In what follows "alpha" is the weight when the sum is formed.
Typically it is 2, As this approaches 1 the function is noisier.
"beta" is the harmonic scaling/spacing, typically 2.
*/
double noise1D(double x, double alpha, double beta, int n) {
int i;
double val, sum = 0;
double p, scale = 1;
p = x;
for (i = 0; i < n; i++) {
val = noise1(p);
sum += val / scale;
scale *= alpha;
p *= beta;
}
return (sum);
}
double noise2D(double x, double y, double alpha, double beta, int n) {
int i;
double val, sum = 0;
double p[2], scale = 1;
p[0] = x;
p[1] = y;
for (i = 0; i < n; i++) {
val = noise2(p);
sum += val / scale;
scale *= alpha;
p[0] *= beta;
p[1] *= beta;
}
return (sum);
}
double noise3D(double x, double y, double z, double alpha, double beta, int n) {
int i;
double val, sum = 0;
double p[3], scale = 1;
p[0] = x;
p[1] = y;
p[2] = z;
for (i = 0; i < n; i++) {
val = noise3(p);
sum += val / scale;
scale *= alpha;
p[0] *= beta;
p[1] *= beta;
p[2] *= beta;
}
return (sum);
}
void init() {
int i, j, k;
for (i = 0; i < B; i++) {
p[i] = i;
g1[i] = (double) ((rand() % (B + B)) - B) / B;
for (j = 0; j < 2; j++)
g2[i][j] = (double) ((rand() % (B + B)) - B) / B;
normalize2(g2[i]);
for (j = 0; j < 3; j++)
g3[i][j] = (double) ((rand() % (B + B)) - B) / B;
normalize3(g3[i]);
}
while (--i) {
k = p[i];
p[i] = p[j = rand() % B];
p[j] = k;
}
for (i = 0; i < B + 2; i++) {
p[B + i] = p[i];
g1[B + i] = g1[i];
for (j = 0; j < 2; j++)
g2[B + i][j] = g2[i][j];
for (j = 0; j < 3; j++)
g3[B + i][j] = g3[i][j];
}
}
}
END_NAMESPACE
+14
View File
@@ -0,0 +1,14 @@
#pragma once
#include "defines.h"
BEGIN_NAMESPACE
namespace perlin {
void init();
double noise1D(double x, double alpha, double beta, int n);
double noise2D(double x, double y, double alpha, double beta, int n);
double noise3D(double x, double y, double z, double alpha, double beta, int n);
}
END_NAMESPACE
+12 -5
View File
@@ -15,24 +15,31 @@ void scene_node::calculate_local_transform() {
* glm::scale(glm::mat4(1.0f), scale);
}
void scene_node::apply_parent_transform(const glm::mat4 &parent_transform) {
void scene_node::apply_parent_transform(const glm::mat4& parent_transform) {
model_to_world_space_matrix = parent_transform * local_to_parent_space_matrix;
for (auto &child: children)
for (auto& child: children)
child->apply_parent_transform(model_to_world_space_matrix);
}
mesh_node &scene_node::as_mesh_node() {
mesh_node& scene_node::as_mesh_node() {
return *static_cast<mesh_node *>(this);
}
light_node &scene_node::as_light_node() {
light_node& scene_node::as_light_node() {
return *static_cast<light_node *>(this);
}
camera_node &scene_node::as_camera_node() {
camera_node& scene_node::as_camera_node() {
return *static_cast<camera_node *>(this);
}
static size_t current_id = 0;
scene_node::scene_node() {
id = current_id++;
rotation = glm::angleAxis(0.0f, glm::vec3(1, 0, 0));
}
END_NAMESPACE
+7 -5
View File
@@ -21,14 +21,16 @@ struct light_node;
struct camera_node;
struct scene_node {
scene_node();
virtual void calculate_local_transform();
void apply_parent_transform(const glm::mat4 &parent_transform);
void apply_parent_transform(const glm::mat4& parent_transform);
mesh_node &as_mesh_node();
light_node &as_light_node();
camera_node &as_camera_node();
mesh_node& as_mesh_node();
light_node& as_light_node();
camera_node& as_camera_node();
int id;
size_t id;
std::string name;
scene_node_type type; // We rely on type comparison instead of dynamic casting because comparing types is much faster
+80 -61
View File
@@ -1,6 +1,6 @@
#include "scene_renderer.h"
#include "light_node.h"
#include "shader.h"
#include "shader_program.h"
#include "material.h"
#include "mesh_node.h"
#include "demo_data.h"
@@ -277,20 +277,20 @@ scene_renderer::scene_renderer()
glGenFramebuffers(1, &fbo_id);
first_pass_shadow_shader = std::make_shared<shader>(vs, ps);
first_pass_shadow_shader = std::make_shared<shader_program>(vs, ps);
first_pass_shadow_material = std::make_shared<material>();
first_pass_shadow_material->shader_ = first_pass_shadow_shader;
first_pass_shadow_material->shader = first_pass_shadow_shader;
first_pass_shadow_material->zbuffer_write = true;
first_pass_shadow_material->zbuffer_test = true;
first_pass_shadow_material->transparent = false;
first_pass_shadow_material->cull_faces = true;
first_pass_shadow_material->cull_front_faces = false;
second_pass_shadow_shader = std::make_shared<shader>(vs3, ps3);
second_pass_shadow_shader = std::make_shared<shader_program>(vs3, ps3);
second_pass_shadow_material = std::make_shared<material>();
second_pass_shadow_material->shader_ = second_pass_shadow_shader;
second_pass_shadow_material->shader = second_pass_shadow_shader;
second_pass_shadow_material->diffuse = glm::vec4(1, 0, 0, 1);
second_pass_shadow_material->zbuffer_write = true;
second_pass_shadow_material->zbuffer_test = true;
@@ -299,21 +299,34 @@ scene_renderer::scene_renderer()
second_pass_shadow_material->flat_shaded = false;
}
void scene_renderer::attach_depth_texture(texture &text) const {
void scene_renderer::attach_depth_texture(texture& text) const {
glBindFramebuffer(GL_FRAMEBUFFER, fbo_id);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, text.get_id(), 0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
void scene_renderer::render(const scene_tree &tree, const std::string &cameraName) {
// for (auto &node: scene.lights) {
// light_node &light = node->as_light_node();
// glActiveTexture(GL_TEXTURE0);
// render_shadow_map(scene, light);
// }
std::shared_ptr<scene_node> camNode = tree.node_by_name_and_type(cameraName, scene_node_type::camera);
camera_node &camera = camNode->as_camera_node();
std::string to_string(const glm::vec3& v) {
std::stringstream ss;
ss << "{x:" << v.x << ", y:" << v.y << ", z:" << v.z << "}";
return ss.str();
}
std::string to_string(const glm::quat& v) {
std::stringstream ss;
ss << "{x:" << v.x << ", y:" << v.y << ", z:" << v.z << ", w:" << v.w << "}";
return ss.str();
}
void scene_renderer::render(const scene_tree& tree, const std::string& cam_name) {
for (auto& node: tree.lights) {
light_node& light = node->as_light_node();
glActiveTexture(GL_TEXTURE0);
render_shadow_map(tree, light);
}
std::shared_ptr<scene_node> cam_node = tree.node_by_name_and_type(cam_name, scene_node_type::camera);
camera_node& camera = cam_node->as_camera_node();
shader_consts.set(uniforms::ViewMatrix, camera.view_matrix);
shader_consts.set(uniforms::ProjectionMatrix, camera.projection_matrix);
@@ -323,81 +336,87 @@ std::shared_ptr<scene_node> camNode = tree.node_by_name_and_type(cameraName, sce
set_material(second_pass_shadow_material);
int lightIndex = 0;
for (auto &node: tree.lights) {
light_node &light = node->as_light_node();
int light_index = 0;
for (auto& node: tree.lights) {
light_node& light = node->as_light_node();
shader_consts.set(uniforms::WorldToLightMatrix, light.world_to_light_matrix[0], lightIndex);
shader_consts.set(uniforms::LightProjectionMatrix, light.light_projection_matrix[0], lightIndex);
shader_consts.set(uniforms::ShadowMatrix, light.final_shadow_map_matrix[0], lightIndex);
shader_consts.set(uniforms::WorldToLightMatrix, light.world_to_light_matrix[0], light_index);
shader_consts.set(uniforms::LightProjectionMatrix, light.light_projection_matrix[0], light_index);
shader_consts.set(uniforms::ShadowMatrix, light.final_shadow_map_matrix[0], light_index);
shader_consts.set(uniforms::ShadowBiasMatrix, light.shadow_map_bias_matrix);
glm::vec3 lightPositionInEyeSpace = light.position - camera.position;
shader_consts.set(uniforms::LightPosition, lightPositionInEyeSpace, lightIndex);
glm::vec3 light_pos_in_eye_space = light.position - camera.position;
shader_consts.set(uniforms::LightPosition, light_pos_in_eye_space, light_index);
glm::vec3 lightTargetInEyeSpace = light.spot_target - camera.position;
shader_consts.set(uniforms::LightTarget, lightTargetInEyeSpace, lightIndex);
glm::vec3 light_target_in_eye_space = light.spot_target - camera.position;
shader_consts.set(uniforms::LightTarget, light_target_in_eye_space, light_index);
shader_consts.set(uniforms::LightAmbient, light.ambient, lightIndex);
shader_consts.set(uniforms::LightDiffuse, light.diffuse, lightIndex);
shader_consts.set(uniforms::LightSpecular, light.specular, lightIndex);
shader_consts.set(uniforms::LightAmbient, light.ambient, light_index);
shader_consts.set(uniforms::LightDiffuse, light.diffuse, light_index);
shader_consts.set(uniforms::LightSpecular, light.specular, light_index);
shader_consts.set(uniforms::LightSpotCutoff, light.spot_cutoff, lightIndex);
shader_consts.set(uniforms::LightSpotExponent, light.spot_exponent, lightIndex);
shader_consts.set(uniforms::LightAttenuation, light.attenuation, lightIndex);
shader_consts.set(uniforms::LightSpotCutoff, light.spot_cutoff, light_index);
shader_consts.set(uniforms::LightSpotExponent, light.spot_exponent, light_index);
shader_consts.set(uniforms::LightAttenuation, light.attenuation, light_index);
glActiveTexture(GL_TEXTURE0 + 4 + lightIndex);
glActiveTexture(GL_TEXTURE0 + 4 + light_index);
glBindTexture(GL_TEXTURE_2D, light.shadow_map[0]->get_id());
if (lightIndex == 0) {
shader_consts.set(uniforms::ShadowMap1, lightIndex + 4);
} else if (lightIndex == 1) {
shader_consts.set(uniforms::ShadowMap2, lightIndex + 4);
} else if (lightIndex == 2) {
shader_consts.set(uniforms::ShadowMap3, lightIndex + 4);
} else if (lightIndex == 3) {
shader_consts.set(uniforms::ShadowMap4, lightIndex + 4);
if (light_index == 0) {
shader_consts.set(uniforms::ShadowMap1, light_index + 4);
} else if (light_index == 1) {
shader_consts.set(uniforms::ShadowMap2, light_index + 4);
} else if (light_index == 2) {
shader_consts.set(uniforms::ShadowMap3, light_index + 4);
} else if (light_index == 3) {
shader_consts.set(uniforms::ShadowMap4, light_index + 4);
}
lightIndex++;
light_index++;
}
// draw opaque nodes
for (auto &node: tree.nodes) {
for (auto& node: tree.nodes) {
if (node->type == scene_node_type::mesh) {
mesh_node &meshNode = node->as_mesh_node();
mesh_node& mesh_node = node->as_mesh_node();
glm::mat3 normalMatrix = glm::inverseTranspose(
glm::mat3(camera.view_matrix * meshNode.model_to_world_space_matrix));
// if (node->name == "light mesh") {
// LOG(INFO) << "rendering light mesh. position: " << to_string(mesh_node.position)
// << ", scale: " << to_string(mesh_node.scale)
// << ", rotation: " << to_string(mesh_node.rotation);
// }
shader_consts.set(uniforms::ModelToWorldMatrix, meshNode.model_to_world_space_matrix);
shader_consts.set(uniforms::NormalMatrix, normalMatrix);
shader_consts.set(uniforms::MaterialAmbientColor, meshNode.material_->ambient);
shader_consts.set(uniforms::MaterialDiffuseColor, meshNode.material_->diffuse);
shader_consts.set(uniforms::MaterialSpecularColor, meshNode.material_->specular);
shader_consts.set(uniforms::MaterialShininess, meshNode.material_->shininess);
glm::mat3 normal_mat = glm::inverseTranspose(
glm::mat3(camera.view_matrix * mesh_node.model_to_world_space_matrix));
shader_consts.apply_to(*second_pass_shadow_material->shader_);
shader_consts.set(uniforms::ModelToWorldMatrix, mesh_node.model_to_world_space_matrix);
shader_consts.set(uniforms::NormalMatrix, normal_mat);
shader_consts.set(uniforms::MaterialAmbientColor, mesh_node.material_->ambient);
shader_consts.set(uniforms::MaterialDiffuseColor, mesh_node.material_->diffuse);
shader_consts.set(uniforms::MaterialSpecularColor, mesh_node.material_->specular);
shader_consts.set(uniforms::MaterialShininess, mesh_node.material_->shininess);
if (meshNode.material_->textures[texture_role::diffuse]) {
int textureUnit = 0;
glActiveTexture(GL_TEXTURE0 + textureUnit);
meshNode.material_->textures[texture_role::diffuse]->use();
shader_consts.apply_to(*second_pass_shadow_material->shader);
second_pass_shadow_material->shader_->setIntUniform(textureUnit, "diffuseMap");
if (mesh_node.material_->textures[texture_role::diffuse]) {
int texture_unit = 0;
glActiveTexture(GL_TEXTURE0 + texture_unit);
mesh_node.material_->textures[texture_role::diffuse]->use();
second_pass_shadow_material->shader->set_int(texture_unit, "diffuseMap");
} else {
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, 0);
}
meshNode.mesh_->render(second_pass_shadow_material->flat_shaded);
mesh_node.mesh_->render(second_pass_shadow_material->flat_shaded);
}
}
unset_material(second_pass_shadow_material);
}
void scene_renderer::render_shadow_map(const scene_tree &scene, light_node &light) {
void scene_renderer::render_shadow_map(const scene_tree& scene, light_node& light) {
light.calculate_local_transform();
attach_depth_texture(*light.shadow_map[0]);
@@ -416,13 +435,13 @@ void scene_renderer::render_shadow_map(const scene_tree &scene, light_node &ligh
set_material(first_pass_shadow_material);
// first pass - draw all objects that may cast shadows as seen from light
for (auto &node: scene.nodes) {
for (auto& node: scene.nodes) {
if (node->type == scene_node_type::mesh) {
mesh_node &meshNode = node->as_mesh_node();
mesh_node& meshNode = node->as_mesh_node();
if (!meshNode.material_->transparent && meshNode.material_->cast_shadows) {
shader_consts.set(uniforms::ModelToWorldMatrix, meshNode.model_to_world_space_matrix);
shader_consts.apply_to(*first_pass_shadow_material->shader_);
shader_consts.apply_to(*first_pass_shadow_material->shader);
meshNode.mesh_->render(first_pass_shadow_material->flat_shaded);
}
+4 -4
View File
@@ -6,7 +6,7 @@
BEGIN_NAMESPACE
class shader;
class shader_program;
class material;
@@ -17,16 +17,16 @@ public:
scene_renderer();
void render(const scene_tree &tree, const std::string &cameraName);
void render(const scene_tree &tree, const std::string &cam_name);
private:
void attach_depth_texture(texture &text) const;
void render_shadow_map(const scene_tree &scene, light_node &light);
std::shared_ptr<shader> first_pass_shadow_shader;
std::shared_ptr<shader_program> first_pass_shadow_shader;
std::shared_ptr<material> first_pass_shadow_material;
std::shared_ptr<shader> second_pass_shadow_shader;
std::shared_ptr<shader_program> second_pass_shadow_shader;
std::shared_ptr<material> second_pass_shadow_material;
shader_constants shader_consts;
+8 -6
View File
@@ -1,29 +1,31 @@
#include "scene_tree.h"
#include <utility>
BEGIN_NAMESPACE
std::shared_ptr<scene_node> scene_tree::nodeById(int id) const {
std::shared_ptr<scene_node> scene_tree::node_by_id(size_t id) const {
for (auto& node : nodes)
if (node->id == id)
return node;
return std::shared_ptr<scene_node>(nullptr);
return {nullptr};
}
std::shared_ptr<scene_node> scene_tree::node_by_name_and_type(std::string name, scene_node_type type) const {
std::shared_ptr<scene_node> scene_tree::node_by_name_and_type(const std::string& name, scene_node_type type) const {
for (auto& node : nodes)
if (node->name == name && node->type == type)
return node;
return std::shared_ptr<scene_node>(nullptr);
return {nullptr};
}
void scene_tree::add(std::shared_ptr<scene_node> node) {
add(node, std::shared_ptr<scene_node>(nullptr));
add(std::move(node), std::shared_ptr<scene_node>(nullptr));
}
void scene_tree::add(std::shared_ptr<scene_node> node, std::shared_ptr<scene_node> parent) {
void scene_tree::add(const std::shared_ptr<scene_node>& node, std::shared_ptr<scene_node> parent) {
nodes.push_back(node);
node->parent = parent;
+3 -3
View File
@@ -8,11 +8,11 @@ BEGIN_NAMESPACE
class scene_tree {
public:
std::shared_ptr<scene_node> nodeById(int id) const;
std::shared_ptr<scene_node> node_by_name_and_type(std::string name, scene_node_type type) const;
std::shared_ptr<scene_node> node_by_id(size_t id) const;
std::shared_ptr<scene_node> node_by_name_and_type(const std::string& name, scene_node_type type) const;
void add(std::shared_ptr<scene_node> node);
void add(std::shared_ptr<scene_node> node, std::shared_ptr<scene_node> parent);
void add(const std::shared_ptr<scene_node>& node, std::shared_ptr<scene_node> parent);
void transform();
+21 -21
View File
@@ -1,4 +1,4 @@
#include "shader.h"
#include "shader_program.h"
#include <iostream>
BEGIN_NAMESPACE
@@ -47,7 +47,7 @@ void check_link_error(GLuint program_id) {
}
}
shader::shader(const char *vs_content, const char *ps_content)
shader_program::shader_program(const char *vs_content, const char *ps_content)
: shader_ids{0, 0},
program_id{0} {
@@ -117,7 +117,7 @@ shader::shader(const char *vs_content, const char *ps_content)
// glUseProgram(program_id);
}
shader::~shader() {
shader_program::~shader_program() {
glDetachShader(program_id, shader_ids[0]);
glDetachShader(program_id, shader_ids[1]);
@@ -127,53 +127,53 @@ shader::~shader() {
glDeleteProgram(program_id);
}
void shader::use() const {
void shader_program::bind() const {
glUseProgram(program_id);
}
void shader::unuse() const {
void shader_program::unbind() {
glUseProgram(0);
}
int shader::getUniform(const char *uniformName) {
if (uniform_cache.count(uniformName) == 0) {
uniform_cache[uniformName] = glGetUniformLocation(program_id, uniformName);
int shader_program::get_uniform(const char *name) {
if (uniform_cache.count(name) == 0) {
uniform_cache[name] = glGetUniformLocation(program_id, name);
}
return uniform_cache[uniformName];
return uniform_cache[name];
}
void shader::setMatrix3Uniform(float *matrix, const char *uniformName) {
GLint location = getUniform(uniformName);
void shader_program::set_mat3(float *matrix, const char *uniform_name) {
GLint location = get_uniform(uniform_name);
if (location != -1)
glUniformMatrix3fv(location, 1, false, matrix);
}
void shader::setMatrix4Uniform(float *matrix, const char *uniformName) {
GLint location = getUniform(uniformName);
void shader_program::set_mat4(float *matrix, const char *uniform_name) {
GLint location = get_uniform(uniform_name);
if (location != -1)
glUniformMatrix4fv(location, 1, false, matrix);
}
void shader::setVec3Uniform(float *value, const char *uniformName) {
GLint location = getUniform(uniformName);
void shader_program::set_vec3(float *value, const char *uniform_name) {
GLint location = get_uniform(uniform_name);
if (location != -1)
glUniform3fv(location, 1, value);
}
void shader::setVec4Uniform(float *value, const char *uniformName) {
GLint location = getUniform(uniformName);
void shader_program::set_vec4(float *value, const char *uniform_name) {
GLint location = get_uniform(uniform_name);
if (location != -1)
glUniform4fv(location, 1, value);
}
void shader::setIntUniform(int value, const char *uniformName) {
GLint location = getUniform(uniformName);
void shader_program::set_int(int value, const char *uniform_name) {
GLint location = get_uniform(uniform_name);
if (location != -1)
glUniform1i(location, value);
}
void shader::setFloatUniform(float value, const char *uniformName) {
GLint location = getUniform(uniformName);
void shader_program::set_float(float value, const char *uniform_name) {
GLint location = get_uniform(uniform_name);
if (location != -1)
glUniform1f(location, value);
}
-33
View File
@@ -1,33 +0,0 @@
#pragma once
#include "defines.h"
#include <map>
BEGIN_NAMESPACE
class shader {
public:
shader(const char *vs_content, const char *ps_content);
virtual ~shader();
void use() const;
void unuse() const;
GLuint getId() const { return program_id; }
int getUniform(const char *uniformName);
void setMatrix3Uniform(float *value, const char *uniformName);
void setMatrix4Uniform(float *value, const char *uniformName);
void setVec3Uniform(float *value, const char *uniformName);
void setVec4Uniform(float *value, const char *uniformName);
void setFloatUniform(float value, const char *uniformName);
void setIntUniform(int value, const char *uniformName);
private:
GLuint program_id;
GLuint shader_ids[2];
std::map<const char *, int> uniform_cache;
};
END_NAMESPACE
+50 -51
View File
@@ -1,7 +1,7 @@
#pragma once
#include "defines.h"
#include "shader.h"
#include "shader_program.h"
#include "texture.h"
#include <map>
#include "material.h"
@@ -16,8 +16,7 @@ struct uniform_descriptor {
std::string member_name;
// TODO: implement memoization of uniform name calculation
uniform_descriptor(const char *member) {
explicit uniform_descriptor(const char *member) {
structure_name = "";
member_name = member;
}
@@ -27,7 +26,7 @@ struct uniform_descriptor {
member_name = member;
}
std::string get_name() {
std::string get_name() const {
if (structure_name.empty())
return member_name;
@@ -36,7 +35,7 @@ struct uniform_descriptor {
return ss.str();
}
std::string get_name(int index) {
std::string get_name(int index) const {
std::stringstream ss;
if (structure_name.empty()) {
ss << member_name << "[" << index << "]";
@@ -93,72 +92,72 @@ public:
shader_constant_type type;
glm::vec3 vec3Val{};
glm::vec4 vec4Val{};
glm::mat3 mat3Val{};
glm::mat4 mat4Val{};
int intVal{};
float floatVal{};
glm::vec3 vec3_val{};
glm::vec4 vec4_val{};
glm::mat3 mat3_val{};
glm::mat4 mat4_val{};
int int_val{};
float float_val{};
shader_constant_value(const shader_constant_value &rhs) {
shader_constant_value(const shader_constant_value& rhs) {
type = rhs.type;
vec3Val = rhs.vec3Val;
vec4Val = rhs.vec4Val;
mat3Val = rhs.mat3Val;
mat4Val = rhs.mat4Val;
intVal = rhs.intVal;
floatVal = rhs.floatVal;
vec3_val = rhs.vec3_val;
vec4_val = rhs.vec4_val;
mat3_val = rhs.mat3_val;
mat4_val = rhs.mat4_val;
int_val = rhs.int_val;
float_val = rhs.float_val;
}
shader_constant_value(glm::vec3 &value) {
vec3Val = value;
explicit shader_constant_value(glm::vec3& value) {
vec3_val = value;
type = shader_constant_type::vec3;
}
shader_constant_value(glm::vec4 &value) {
vec4Val = value;
explicit shader_constant_value(glm::vec4& value) {
vec4_val = value;
type = shader_constant_type::vec4;
}
shader_constant_value(glm::mat3 &value) {
mat3Val = value;
explicit shader_constant_value(glm::mat3& value) {
mat3_val = value;
type = shader_constant_type::mat3;
}
shader_constant_value(glm::mat4 &value) {
mat4Val = value;
explicit shader_constant_value(glm::mat4& value) {
mat4_val = value;
type = shader_constant_type::mat4;
}
shader_constant_value(int value) {
intVal = value;
explicit shader_constant_value(int value) {
int_val = value;
type = shader_constant_type::integer;
}
shader_constant_value(float value) {
floatVal = value;
explicit shader_constant_value(float value) {
float_val = value;
type = shader_constant_type::decimal;
}
void apply_to(shader &sh, const char *uniform_name) {
void apply_to(shader_program& sh, const char *uniform_name) {
switch (type) {
case shader_constant_type::vec3:
sh.setVec3Uniform(glm::value_ptr(vec3Val), uniform_name);
sh.set_vec3(glm::value_ptr(vec3_val), uniform_name);
break;
case shader_constant_type::vec4:
sh.setVec4Uniform(glm::value_ptr(vec4Val), uniform_name);
sh.set_vec4(glm::value_ptr(vec4_val), uniform_name);
break;
case shader_constant_type::mat3:
sh.setMatrix3Uniform(glm::value_ptr(mat3Val), uniform_name);
sh.set_mat3(glm::value_ptr(mat3_val), uniform_name);
break;
case shader_constant_type::mat4:
sh.setMatrix4Uniform(glm::value_ptr(mat4Val), uniform_name);
sh.set_mat4(glm::value_ptr(mat4_val), uniform_name);
break;
case shader_constant_type::integer:
sh.setIntUniform(intVal, uniform_name);
sh.set_int(int_val, uniform_name);
break;
case shader_constant_type::decimal:
sh.setFloatUniform(floatVal, uniform_name);
sh.set_float(float_val, uniform_name);
break;
}
}
@@ -168,56 +167,56 @@ public:
class shader_constants {
public:
void set(uniform_descriptor descriptor, glm::mat3 value) {
void set(const uniform_descriptor& descriptor, glm::mat3 value) {
constants[descriptor.get_name()] = std::make_shared<shader_constant_value>(value);
}
void set(uniform_descriptor descriptor, glm::mat3 value, int index) {
void set(const uniform_descriptor& descriptor, glm::mat3 value, int index) {
constants[descriptor.get_name(index)] = std::make_shared<shader_constant_value>(value);
}
void set(uniform_descriptor descriptor, glm::mat4 value) {
void set(const uniform_descriptor& descriptor, glm::mat4 value) {
constants[descriptor.get_name()] = std::make_shared<shader_constant_value>(value);
}
void set(uniform_descriptor descriptor, glm::mat4 value, int index) {
void set(const uniform_descriptor& descriptor, glm::mat4 value, int index) {
constants[descriptor.get_name(index)] = std::make_shared<shader_constant_value>(value);
}
void set(uniform_descriptor descriptor, glm::vec3 value) {
void set(const uniform_descriptor& descriptor, glm::vec3 value) {
constants[descriptor.get_name()] = std::make_shared<shader_constant_value>(value);
}
void set(uniform_descriptor descriptor, glm::vec3 value, int index) {
void set(const uniform_descriptor& descriptor, glm::vec3 value, int index) {
constants[descriptor.get_name(index)] = std::make_shared<shader_constant_value>(value);
}
void set(uniform_descriptor descriptor, glm::vec4 value) {
void set(const uniform_descriptor& descriptor, glm::vec4 value) {
constants[descriptor.get_name()] = std::make_shared<shader_constant_value>(value);
}
void set(uniform_descriptor descriptor, glm::vec4 value, int index) {
void set(const uniform_descriptor& descriptor, glm::vec4 value, int index) {
constants[descriptor.get_name(index)] = std::make_shared<shader_constant_value>(value);
}
void set(uniform_descriptor descriptor, int value) {
void set(const uniform_descriptor& descriptor, int value) {
constants[descriptor.get_name()] = std::make_shared<shader_constant_value>(value);
}
void set(uniform_descriptor descriptor, int value, int index) {
void set(const uniform_descriptor& descriptor, int value, int index) {
constants[descriptor.get_name(index)] = std::make_shared<shader_constant_value>(value);
}
void set(uniform_descriptor descriptor, float value) {
void set(const uniform_descriptor& descriptor, float value) {
constants[descriptor.get_name()] = std::make_shared<shader_constant_value>(value);
}
void set(uniform_descriptor descriptor, float value, int index) {
void set(const uniform_descriptor& descriptor, float value, int index) {
constants[descriptor.get_name(index)] = std::make_shared<shader_constant_value>(value);
}
void apply_to(shader &shd) {
for (auto &kv: constants)
void apply_to(shader_program& shd) {
for (auto& kv: constants)
kv.second->apply_to(shd, kv.first.c_str());
}
+33
View File
@@ -0,0 +1,33 @@
#pragma once
#include "defines.h"
#include <map>
BEGIN_NAMESPACE
class shader_program {
public:
shader_program(const char *vs_content, const char *ps_content);
virtual ~shader_program();
void bind() const;
static void unbind() ;
GLuint get_id() const { return program_id; }
int get_uniform(const char *name);
void set_mat3(float *value, const char *uniform_name);
void set_mat4(float *value, const char *uniform_name);
void set_vec3(float *value, const char *uniform_name);
void set_vec4(float *value, const char *uniform_name);
void set_float(float value, const char *uniform_name);
void set_int(int value, const char *uniform_name);
private:
GLuint program_id;
GLuint shader_ids[2];
std::map<const char *, int> uniform_cache;
};
END_NAMESPACE
+4 -4
View File
@@ -7,15 +7,15 @@ timer::timer() {
last_lap_time = start_time;
}
double timer::seconds_since_start() {
float timer::seconds_since_start() {
std::chrono::time_point<std::chrono::system_clock> now = std::chrono::system_clock::now();
std::chrono::duration<double> elapsed_seconds = now - start_time;
std::chrono::duration<float> elapsed_seconds = now - start_time;
return elapsed_seconds.count();
}
double timer::lap() {
float timer::lap() {
std::chrono::time_point<std::chrono::system_clock> now = std::chrono::system_clock::now();
std::chrono::duration<double> elapsed_seconds = now - last_lap_time;
std::chrono::duration<float> elapsed_seconds = now - last_lap_time;
last_lap_time = now;
return elapsed_seconds.count();
}
+2 -2
View File
@@ -9,8 +9,8 @@ class timer {
public:
timer();
double seconds_since_start();
double lap();
float seconds_since_start();
float lap();
private:
std::chrono::time_point<std::chrono::system_clock> start_time;
+12
View File
@@ -0,0 +1,12 @@
intro:
- benzene elements come together and form the symbol
- they slowly come into place and rotate
- either explode into particles or fade away
scenes:
- camera flyby trhough a sci-fi tunnel composed of metalic pipe systems and awkward light
- walk through a forest made with L-systems
- heightmap